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 }
|