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