annotate src/gt_urn.c @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
rev   line source
paulo@0 1 /*
paulo@0 2 * $Id: gt_urn.c,v 1.4 2004/03/05 17:47:29 hipnod Exp $
paulo@0 3 *
paulo@0 4 * Copyright (C) 2003 giFT project (gift.sourceforge.net)
paulo@0 5 *
paulo@0 6 * This program is free software; you can redistribute it and/or modify it
paulo@0 7 * under the terms of the GNU General Public License as published by the
paulo@0 8 * Free Software Foundation; either version 2, or (at your option) any
paulo@0 9 * later version.
paulo@0 10 *
paulo@0 11 * This program is distributed in the hope that it will be useful, but
paulo@0 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
paulo@0 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
paulo@0 14 * General Public License for more details.
paulo@0 15 */
paulo@0 16
paulo@0 17 #include "gt_gnutella.h"
paulo@0 18 #include "gt_urn.h"
paulo@0 19 #include "encoding/base32.h"
paulo@0 20 #include "sha1.h"
paulo@0 21
paulo@0 22 /*****************************************************************************/
paulo@0 23
paulo@0 24 #define URN_PREFIX_LEN (sizeof("urn:")-1)
paulo@0 25 #define SHA1_PREFIX_LEN (sizeof("sha1:")-1)
paulo@0 26 #define BITPRINT_PREFIX_LEN (sizeof("bitprint:")-1)
paulo@0 27
paulo@0 28 /*****************************************************************************/
paulo@0 29
paulo@0 30 enum urn_types
paulo@0 31 {
paulo@0 32 GT_URN_SHA1 = 0,
paulo@0 33 GT_URN_BITPRINT = 1, /* for now, collapse bitprint to sha1 */
paulo@0 34 };
paulo@0 35
paulo@0 36 /*****************************************************************************/
paulo@0 37
paulo@0 38 static long get_urn_type (gt_urn_t *urn)
paulo@0 39 {
paulo@0 40 long tmp;
paulo@0 41
paulo@0 42 memcpy (&tmp, urn, sizeof(tmp));
paulo@0 43 return tmp;
paulo@0 44 }
paulo@0 45
paulo@0 46 static void set_urn_type (gt_urn_t *urn, enum urn_types t)
paulo@0 47 {
paulo@0 48 long tmp = t;
paulo@0 49
paulo@0 50 memcpy (urn, &tmp, sizeof(tmp));
paulo@0 51 }
paulo@0 52
paulo@0 53 static unsigned char *get_urn_data (const gt_urn_t *urn)
paulo@0 54 {
paulo@0 55 return (unsigned char *)urn + sizeof(long);
paulo@0 56 }
paulo@0 57
paulo@0 58 static void set_urn_data (gt_urn_t *urn, const unsigned char *data, size_t len)
paulo@0 59 {
paulo@0 60 memcpy (get_urn_data (urn), data, len);
paulo@0 61 }
paulo@0 62
paulo@0 63 /*****************************************************************************/
paulo@0 64
paulo@0 65 static size_t bin_length (enum urn_types t)
paulo@0 66 {
paulo@0 67 switch (t)
paulo@0 68 {
paulo@0 69 case GT_URN_BITPRINT:
paulo@0 70 case GT_URN_SHA1: return SHA1_BINSIZE;
paulo@0 71 default: return 0;
paulo@0 72 }
paulo@0 73 }
paulo@0 74
paulo@0 75 static gt_urn_t *sha1_urn_new (const unsigned char *data)
paulo@0 76 {
paulo@0 77 gt_urn_t *new_urn;
paulo@0 78
paulo@0 79 if (!(new_urn = malloc (SHA1_BINSIZE + sizeof(long))))
paulo@0 80 return NULL;
paulo@0 81
paulo@0 82 /* put the identifier at the beginning */
paulo@0 83 set_urn_type (new_urn, GT_URN_SHA1);
paulo@0 84
paulo@0 85 /* copy the data */
paulo@0 86 set_urn_data (new_urn, data, SHA1_BINSIZE);
paulo@0 87
paulo@0 88 return new_urn;
paulo@0 89 }
paulo@0 90
paulo@0 91 gt_urn_t *gt_urn_new (const char *urn_type, const unsigned char *data)
paulo@0 92 {
paulo@0 93 if (!strcasecmp (urn_type, "urn:sha1"))
paulo@0 94 return sha1_urn_new (data);
paulo@0 95
paulo@0 96 return NULL;
paulo@0 97 }
paulo@0 98
paulo@0 99 unsigned char *gt_urn_data (const gt_urn_t *urn)
paulo@0 100 {
paulo@0 101 if (!urn)
paulo@0 102 return NULL;
paulo@0 103
paulo@0 104 return get_urn_data (urn);
paulo@0 105 }
paulo@0 106
paulo@0 107 char *gt_urn_string (const gt_urn_t *urn)
paulo@0 108 {
paulo@0 109 unsigned char *data;
paulo@0 110 char *urn_str;
paulo@0 111 const size_t prefix_len = URN_PREFIX_LEN + SHA1_PREFIX_LEN;
paulo@0 112
paulo@0 113 /*
paulo@0 114 * This is the same for bitprint and sha1 urns, because we convert
paulo@0 115 * to sha1 anyway.
paulo@0 116 */
paulo@0 117
paulo@0 118 if (!(data = gt_urn_data (urn)))
paulo@0 119 return NULL;
paulo@0 120
paulo@0 121 if (!(urn_str = malloc (prefix_len + SHA1_STRLEN + 1)))
paulo@0 122 return NULL;
paulo@0 123
paulo@0 124 memcpy (urn_str, "urn:sha1:", prefix_len);
paulo@0 125 gt_base32_encode (data, SHA1_BINSIZE, urn_str + prefix_len, SHA1_STRLEN);
paulo@0 126
paulo@0 127 urn_str[prefix_len + SHA1_STRLEN] = 0;
paulo@0 128
paulo@0 129 return urn_str;
paulo@0 130 }
paulo@0 131
paulo@0 132 /*****************************************************************************/
paulo@0 133
paulo@0 134 static gt_urn_t *sha1_urn_parse (const char *base32)
paulo@0 135 {
paulo@0 136 gt_urn_t *bin;
paulo@0 137
paulo@0 138 /* make sure the hash is the right length */
paulo@0 139 if (!gt_base32_valid (base32, SHA1_STRLEN))
paulo@0 140 return NULL;
paulo@0 141
paulo@0 142 if (!(bin = malloc (SHA1_BINSIZE + sizeof(long))))
paulo@0 143 return NULL;
paulo@0 144
paulo@0 145 gt_base32_decode (base32, SHA1_STRLEN, bin + sizeof(long), SHA1_BINSIZE);
paulo@0 146 set_urn_type (bin, GT_URN_SHA1);
paulo@0 147
paulo@0 148 return bin;
paulo@0 149 }
paulo@0 150
paulo@0 151 /*
paulo@0 152 * Bitprint urns are the format:
paulo@0 153 *
paulo@0 154 * urn:bitprint:[32-character SHA1].[39-character TigerTree]
paulo@0 155 *
paulo@0 156 * We use the sha1 parsing and truncate the tigertree for now.
paulo@0 157 */
paulo@0 158 static gt_urn_t *bitprint_urn_parse (const char *base32)
paulo@0 159 {
paulo@0 160 return sha1_urn_parse (base32);
paulo@0 161 }
paulo@0 162
paulo@0 163 gt_urn_t *gt_urn_parse (const char *str)
paulo@0 164 {
paulo@0 165 if (strncasecmp ("urn:", str, URN_PREFIX_LEN) != 0)
paulo@0 166 return NULL;
paulo@0 167
paulo@0 168 str += URN_PREFIX_LEN;
paulo@0 169
paulo@0 170 if (!strncasecmp (str, "sha1:", SHA1_PREFIX_LEN))
paulo@0 171 return sha1_urn_parse (str + SHA1_PREFIX_LEN);
paulo@0 172
paulo@0 173 if (!strncasecmp (str, "bitprint:", BITPRINT_PREFIX_LEN))
paulo@0 174 return bitprint_urn_parse (str + BITPRINT_PREFIX_LEN);
paulo@0 175
paulo@0 176 return NULL;
paulo@0 177 }
paulo@0 178
paulo@0 179 /*****************************************************************************/
paulo@0 180
paulo@0 181 int gt_urn_cmp (gt_urn_t *a, gt_urn_t *b)
paulo@0 182 {
paulo@0 183 int ret;
paulo@0 184
paulo@0 185 if (!a || !b)
paulo@0 186 return -1;
paulo@0 187
paulo@0 188 if ((ret = memcmp (a, b, 4)))
paulo@0 189 return ret;
paulo@0 190
paulo@0 191 return memcmp (a + sizeof(long), b + sizeof(long),
paulo@0 192 bin_length (get_urn_type (a)));
paulo@0 193 }