annotate src/xspf/urlencode.c @ 95:b5a1b762f586 trunk

[svn] - xspf now uses url encoding for location entry.
author yaz
date Fri, 20 Oct 2006 00:59:45 -0700
parents
children 1983383db0f5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
95
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
1 /* the original code was taken from wget-1.10.2 */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
2
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
3 #include <stdio.h>
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
4 #include <string.h>
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
5 #include <glib.h>
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
6 #include <ctype.h>
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
7 #include "urlencode.h"
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
8
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
9 enum {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
10 /* rfc1738 reserved chars + "$" and ",". */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
11 urlchr_reserved = 1,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
12
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
13 /* rfc1738 unsafe chars, plus non-printables. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
14 urlchr_unsafe = 2
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
15 };
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
16
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
17 #define urlchr_test(c, mask) (urlchr_table[(unsigned char)(c)] & (mask))
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
18 #define URL_RESERVED_CHAR(c) urlchr_test(c, urlchr_reserved)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
19 #define URL_UNSAFE_CHAR(c) urlchr_test(c, urlchr_unsafe)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
20 #define XNUM_TO_DIGIT(x) ("0123456789ABCDEF"[x] + 0)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
21 #define ISXDIGIT(x) (isxdigit((unsigned char)(x)))
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
22 #define X2DIGITS_TO_NUM(h1, h2) ((XDIGIT_TO_NUM (h1) << 4) + XDIGIT_TO_NUM (h2))
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
23 #define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : toupper (h) - 'A' + 10)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
24
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
25 /* Shorthands for the table: */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
26 #define R urlchr_reserved
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
27 #define U urlchr_unsafe
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
28 #define RU R|U
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
29
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
30 static const unsigned char urlchr_table[256] =
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
31 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
32 U, U, U, U, U, U, U, U, /* NUL SOH STX ETX EOT ENQ ACK BEL */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
33 U, U, U, U, U, U, U, U, /* BS HT LF VT FF CR SO SI */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
34 U, U, U, U, U, U, U, U, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
35 U, U, U, U, U, U, U, U, /* CAN EM SUB ESC FS GS RS US */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
36 U, 0, U, RU, R, U, R, 0, /* SP ! " # $ % & ' */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
37 0, 0, 0, R, R, 0, 0, R, /* ( ) * + , - . / */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
38 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
39 0, 0, RU, R, U, R, U, R, /* 8 9 : ; < = > ? */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
40 RU, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
41 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
42 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
43 0, 0, 0, RU, U, RU, U, 0, /* X Y Z [ \ ] ^ _ */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
44 U, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
45 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
46 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
47 0, 0, 0, U, U, U, 0, U, /* x y z { | } ~ DEL */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
48
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
49 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
50 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
51 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
52 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
53
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
54 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
55 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
56 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
57 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
58 };
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
59 #undef R
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
60 #undef U
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
61 #undef RU
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
62
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
63 /* URL-unescape the string S.
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
64
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
65 This is done by transforming the sequences "%HH" to the character
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
66 represented by the hexadecimal digits HH. If % is not followed by
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
67 two hexadecimal digits, it is inserted literally.
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
68
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
69 The transformation is done in place. If you need the original
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
70 string intact, make a copy before calling this function. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
71
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
72 char *
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
73 xspf_url_decode (const char *s)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
74 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
75 char *copy = strdup(s);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
76 char *t = copy; /* t - tortoise */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
77 char *h = copy; /* h - hare */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
78
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
79 for (; *h; h++, t++)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
80 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
81 if (*h != '%')
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
82 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
83 copychar:
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
84 *t = *h;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
85 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
86 else
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
87 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
88 char c;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
89 /* Do nothing if '%' is not followed by two hex digits. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
90 if (!h[1] || !h[2] || !(ISXDIGIT (h[1]) && ISXDIGIT (h[2])))
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
91 goto copychar;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
92 c = X2DIGITS_TO_NUM (h[1], h[2]);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
93 /* Don't unescape %00 because there is no way to insert it
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
94 into a C string without effectively truncating it. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
95 if (c == '\0')
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
96 goto copychar;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
97 *t = c;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
98 h += 2;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
99 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
100 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
101 *t = '\0';
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
102 return copy;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
103 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
104
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
105 /* The core of url_escape_* functions. Escapes the characters that
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
106 match the provided mask in urlchr_table.
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
107
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
108 If ALLOW_PASSTHROUGH is non-zero, a string with no unsafe chars
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
109 will be returned unchanged. If ALLOW_PASSTHROUGH is zero, a
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
110 freshly allocated string will be returned in all cases. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
111
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
112 static char *
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
113 url_escape_1 (const char *s, unsigned char mask, int allow_passthrough)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
114 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
115 const char *p1;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
116 char *p2, *newstr;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
117 int newlen;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
118 int addition = 0;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
119
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
120 for (p1 = s; *p1; p1++)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
121 if (urlchr_test (*p1, mask))
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
122 addition += 2; /* Two more characters (hex digits) */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
123
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
124 if (!addition)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
125 return allow_passthrough ? (char *)s : strdup (s);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
126
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
127 newlen = (p1 - s) + addition;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
128 newstr = (char *)malloc (newlen + 1);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
129
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
130 p1 = s;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
131 p2 = newstr;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
132 while (*p1)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
133 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
134 /* Quote the characters that match the test mask. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
135 if (urlchr_test (*p1, mask))
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
136 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
137 unsigned char c = *p1++;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
138 *p2++ = '%';
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
139 *p2++ = XNUM_TO_DIGIT (c >> 4);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
140 *p2++ = XNUM_TO_DIGIT (c & 0xf);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
141 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
142 else
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
143 *p2++ = *p1++;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
144 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
145 g_return_if_fail (p2 - newstr == newlen);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
146 *p2 = '\0';
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
147
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
148 return newstr;
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
149 }
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
150
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
151 /* URL-escape the unsafe characters (see urlchr_table) in a given
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
152 string, returning a freshly allocated string. */
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
153
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
154 char *
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
155 xspf_url_encode (const char *s)
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
156 {
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
157 return url_escape_1 (s, urlchr_unsafe, 0);
b5a1b762f586 [svn] - xspf now uses url encoding for location entry.
yaz
parents:
diff changeset
158 }