rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * $Id: url.c,v 1.1 2004/03/24 06:34:36 hipnod Exp $
|
paulo@0
|
3 *
|
paulo@0
|
4 * Copyright (C) 2001-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 "encoding/url.h"
|
paulo@0
|
19
|
paulo@0
|
20 #include <ctype.h>
|
paulo@0
|
21
|
paulo@0
|
22 /*****************************************************************************/
|
paulo@0
|
23 /* url decode/encode helpers */
|
paulo@0
|
24
|
paulo@0
|
25 static int oct_value_from_hex (char hex_char)
|
paulo@0
|
26 {
|
paulo@0
|
27 if (!isxdigit (hex_char))
|
paulo@0
|
28 return 0;
|
paulo@0
|
29
|
paulo@0
|
30 if (hex_char >= '0' && hex_char <= '9')
|
paulo@0
|
31 return (hex_char - '0');
|
paulo@0
|
32
|
paulo@0
|
33 hex_char = toupper (hex_char);
|
paulo@0
|
34
|
paulo@0
|
35 return ((hex_char - 'A') + 10);
|
paulo@0
|
36 }
|
paulo@0
|
37
|
paulo@0
|
38 char *gt_url_decode (const char *encoded)
|
paulo@0
|
39 {
|
paulo@0
|
40 char *decoded, *ptr;
|
paulo@0
|
41
|
paulo@0
|
42 if (!encoded)
|
paulo@0
|
43 return NULL;
|
paulo@0
|
44
|
paulo@0
|
45 /* make sure we are using our own memory here ... */
|
paulo@0
|
46 ptr = strdup (encoded);
|
paulo@0
|
47
|
paulo@0
|
48 /* save the head */
|
paulo@0
|
49 decoded = ptr;
|
paulo@0
|
50
|
paulo@0
|
51 /* convert '+' -> ' ' and %2x -> char value */
|
paulo@0
|
52 while (*ptr)
|
paulo@0
|
53 {
|
paulo@0
|
54 switch (*ptr)
|
paulo@0
|
55 {
|
paulo@0
|
56 case '+':
|
paulo@0
|
57 *ptr = ' ';
|
paulo@0
|
58 break;
|
paulo@0
|
59 case '%':
|
paulo@0
|
60 if (isxdigit (ptr[1]) && isxdigit (ptr[2]))
|
paulo@0
|
61 {
|
paulo@0
|
62 int oct_val;
|
paulo@0
|
63
|
paulo@0
|
64 oct_val = oct_value_from_hex (ptr[1]) * 16;
|
paulo@0
|
65 oct_val += oct_value_from_hex (ptr[2]);
|
paulo@0
|
66
|
paulo@0
|
67 *ptr = (char) oct_val;
|
paulo@0
|
68
|
paulo@0
|
69 string_move (ptr + 1, ptr + 3);
|
paulo@0
|
70 }
|
paulo@0
|
71 break;
|
paulo@0
|
72 default:
|
paulo@0
|
73 break;
|
paulo@0
|
74 }
|
paulo@0
|
75
|
paulo@0
|
76 ptr++;
|
paulo@0
|
77 }
|
paulo@0
|
78
|
paulo@0
|
79 return decoded;
|
paulo@0
|
80 }
|
paulo@0
|
81
|
paulo@0
|
82 static char *gt_url_encode_char (char *stream, unsigned char c)
|
paulo@0
|
83 {
|
paulo@0
|
84 const char hex_alpha[] = "0123456789abcdef";
|
paulo@0
|
85
|
paulo@0
|
86 *stream++ = '%';
|
paulo@0
|
87
|
paulo@0
|
88 *stream++ = hex_alpha[(c & 0xf0) >> 4];
|
paulo@0
|
89 *stream++ = hex_alpha[(c & 0x0f)];
|
paulo@0
|
90
|
paulo@0
|
91 return stream;
|
paulo@0
|
92 }
|
paulo@0
|
93
|
paulo@0
|
94 /*
|
paulo@0
|
95 * This is a bit overzealous about what to encode..hopefully that's ok. This
|
paulo@0
|
96 * escapes path components ('/').
|
paulo@0
|
97 */
|
paulo@0
|
98 static BOOL is_safe_char (unsigned char c)
|
paulo@0
|
99 {
|
paulo@0
|
100 if (c >= 'A' && c <= 'Z')
|
paulo@0
|
101 return TRUE;
|
paulo@0
|
102
|
paulo@0
|
103 if (c >= 'a' && c <= 'z')
|
paulo@0
|
104 return TRUE;
|
paulo@0
|
105
|
paulo@0
|
106 if (c >= '0' && c <= '9')
|
paulo@0
|
107 return TRUE;
|
paulo@0
|
108
|
paulo@0
|
109 switch (c)
|
paulo@0
|
110 {
|
paulo@0
|
111 case '-':
|
paulo@0
|
112 case '.':
|
paulo@0
|
113 case '_':
|
paulo@0
|
114 return TRUE;
|
paulo@0
|
115 default:
|
paulo@0
|
116 return FALSE;
|
paulo@0
|
117 }
|
paulo@0
|
118
|
paulo@0
|
119 return FALSE;
|
paulo@0
|
120 }
|
paulo@0
|
121
|
paulo@0
|
122 char *gt_url_encode (const char *decoded)
|
paulo@0
|
123 {
|
paulo@0
|
124 char *encoded, *ptr;
|
paulo@0
|
125 unsigned char chr;
|
paulo@0
|
126
|
paulo@0
|
127 if (!decoded)
|
paulo@0
|
128 return NULL;
|
paulo@0
|
129
|
paulo@0
|
130 /* allocate a large enough buffer for all cases */
|
paulo@0
|
131 encoded = ptr = malloc ((strlen (decoded) * 3) + 1);
|
paulo@0
|
132
|
paulo@0
|
133 while ((chr = *decoded) != 0)
|
paulo@0
|
134 {
|
paulo@0
|
135 if (is_safe_char (chr))
|
paulo@0
|
136 *ptr++ = chr;
|
paulo@0
|
137 else
|
paulo@0
|
138 ptr = gt_url_encode_char (ptr, chr);
|
paulo@0
|
139
|
paulo@0
|
140 decoded++;
|
paulo@0
|
141 }
|
paulo@0
|
142
|
paulo@0
|
143 *ptr = 0;
|
paulo@0
|
144
|
paulo@0
|
145 return encoded;
|
paulo@0
|
146 }
|
paulo@0
|
147
|
paulo@0
|
148 /*****************************************************************************/
|
paulo@0
|
149
|
paulo@0
|
150 #if 0
|
paulo@0
|
151 int main (int argc, char **argv)
|
paulo@0
|
152 {
|
paulo@0
|
153 int i;
|
paulo@0
|
154
|
paulo@0
|
155 for (i = 1; i < argc; i++)
|
paulo@0
|
156 {
|
paulo@0
|
157 char *enc, *dec;
|
paulo@0
|
158
|
paulo@0
|
159 enc = gt_url_encode (argv[i]);
|
paulo@0
|
160 dec = gt_url_decode (enc);
|
paulo@0
|
161
|
paulo@0
|
162 printf ("%s\n%s\n%s\n", argv[i], enc, dec);
|
paulo@0
|
163
|
paulo@0
|
164 assert (strcmp (argv[i], dec) == 0);
|
paulo@0
|
165 }
|
paulo@0
|
166
|
paulo@0
|
167 return 0;
|
paulo@0
|
168 }
|
paulo@0
|
169 #endif
|