]>
Commit | Line | Data |
---|---|---|
30a4f2a8 | 1 | /* |
262a0e14 | 2 | * $Id$ |
30a4f2a8 | 3 | * |
26ac0430 | 4 | * DEBUG: |
30a4f2a8 | 5 | * AUTHOR: Harvest Derived |
6 | * | |
2b6662ba | 7 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 8 | * ---------------------------------------------------------- |
30a4f2a8 | 9 | * |
2b6662ba | 10 | * Squid is the result of efforts by numerous individuals from |
11 | * the Internet community; see the CONTRIBUTORS file for full | |
12 | * details. Many organizations have provided support for Squid's | |
13 | * development; see the SPONSORS file for full details. Squid is | |
14 | * Copyrighted (C) 2001 by the Regents of the University of | |
15 | * California; see the COPYRIGHT file for full details. Squid | |
16 | * incorporates software developed and/or copyrighted by other | |
17 | * sources; see the CREDITS file for full details. | |
30a4f2a8 | 18 | * |
19 | * This program is free software; you can redistribute it and/or modify | |
20 | * it under the terms of the GNU General Public License as published by | |
21 | * the Free Software Foundation; either version 2 of the License, or | |
22 | * (at your option) any later version. | |
26ac0430 | 23 | * |
30a4f2a8 | 24 | * This program is distributed in the hope that it will be useful, |
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
27 | * GNU General Public License for more details. | |
26ac0430 | 28 | * |
30a4f2a8 | 29 | * You should have received a copy of the GNU General Public License |
30 | * along with this program; if not, write to the Free Software | |
cbdec147 | 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 32 | * |
30a4f2a8 | 33 | */ |
34 | ||
35 | #include "config.h" | |
1fa9b1a7 | 36 | #include "rfc1738.h" |
0d94e9fe | 37 | |
30a4f2a8 | 38 | #if HAVE_STDIO_H |
090089c4 | 39 | #include <stdio.h> |
30a4f2a8 | 40 | #endif |
41 | #if HAVE_STRING_H | |
090089c4 | 42 | #include <string.h> |
30a4f2a8 | 43 | #endif |
44 | ||
26ac0430 | 45 | /* |
090089c4 | 46 | * RFC 1738 defines that these characters should be escaped, as well |
47 | * any non-US-ASCII character or anything between 0x00 - 0x1F. | |
48 | */ | |
26ac0430 | 49 | static char rfc1738_unsafe_chars[] = { |
090089c4 | 50 | (char) 0x3C, /* < */ |
51 | (char) 0x3E, /* > */ | |
52 | (char) 0x22, /* " */ | |
53 | (char) 0x23, /* # */ | |
9bc73deb | 54 | #if 0 /* done in code */ |
afbdbe91 | 55 | (char) 0x20, /* space */ |
090089c4 | 56 | (char) 0x25, /* % */ |
9bc73deb | 57 | #endif |
090089c4 | 58 | (char) 0x7B, /* { */ |
59 | (char) 0x7D, /* } */ | |
60 | (char) 0x7C, /* | */ | |
61 | (char) 0x5C, /* \ */ | |
62 | (char) 0x5E, /* ^ */ | |
63 | (char) 0x7E, /* ~ */ | |
64 | (char) 0x5B, /* [ */ | |
65 | (char) 0x5D, /* ] */ | |
66 | (char) 0x60, /* ` */ | |
afbdbe91 | 67 | (char) 0x27 /* ' */ |
090089c4 | 68 | }; |
69 | ||
26ac0430 | 70 | static char rfc1738_reserved_chars[] = { |
9bc73deb | 71 | (char) 0x3b, /* ; */ |
72 | (char) 0x2f, /* / */ | |
73 | (char) 0x3f, /* ? */ | |
74 | (char) 0x3a, /* : */ | |
75 | (char) 0x40, /* @ */ | |
76 | (char) 0x3d, /* = */ | |
77 | (char) 0x26 /* & */ | |
78 | }; | |
79 | ||
090089c4 | 80 | /* |
26ac0430 | 81 | * rfc1738_escape - Returns a static buffer contains the RFC 1738 |
090089c4 | 82 | * compliant, escaped version of the given url. |
83 | */ | |
1fa9b1a7 AJ |
84 | char * |
85 | rfc1738_do_escape(const char *url, int flags) | |
090089c4 | 86 | { |
3fdadc70 | 87 | static char *buf; |
88 | static size_t bufsize = 0; | |
0ee4272b | 89 | const char *p; |
90 | char *q; | |
2d72d4fd | 91 | unsigned int i, do_escape; |
090089c4 | 92 | |
3fdadc70 | 93 | if (buf == NULL || strlen(url) * 3 > bufsize) { |
26ac0430 AJ |
94 | xfree(buf); |
95 | bufsize = strlen(url) * 3 + 1; | |
1fa9b1a7 | 96 | buf = (char*)xcalloc(bufsize, 1); |
3fdadc70 | 97 | } |
6512a760 | 98 | for (p = url, q = buf; *p != '\0' && q < (buf + bufsize - 1); p++, q++) { |
afbdbe91 AJ |
99 | |
100 | /* a-z, A-Z and 0-9 are SAFE. */ | |
101 | if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9')) { | |
102 | *q = *p; | |
103 | continue; | |
104 | } | |
105 | ||
26ac0430 | 106 | do_escape = 0; |
090089c4 | 107 | |
26ac0430 | 108 | /* RFC 1738 defines these chars as unsafe */ |
afbdbe91 AJ |
109 | if ((flags & RFC1738_ESCAPE_UNSAFE)) { |
110 | for (i = 0;i < sizeof(rfc1738_unsafe_chars); i++) { | |
111 | if (*p == rfc1738_unsafe_chars[i]) { | |
112 | do_escape = 1; | |
113 | break; | |
114 | } | |
26ac0430 | 115 | } |
afbdbe91 AJ |
116 | /* Handle % separately */ |
117 | if (!(flags & RFC1738_ESCAPE_NOPERCENT) && *p == '%') | |
118 | do_escape = 1; | |
119 | /* Handle space separately */ | |
120 | else if (!(flags & RFC1738_ESCAPE_NOSPACE) && *p <= ' ') | |
121 | do_escape = 1; | |
26ac0430 | 122 | } |
26ac0430 | 123 | /* RFC 1738 defines these chars as reserved */ |
afbdbe91 AJ |
124 | if ((flags & RFC1738_ESCAPE_RESERVED) && do_escape == 0) { |
125 | for (i = 0; i < sizeof(rfc1738_reserved_chars); i++) { | |
126 | if (*p == rfc1738_reserved_chars[i]) { | |
127 | do_escape = 1; | |
128 | break; | |
129 | } | |
26ac0430 AJ |
130 | } |
131 | } | |
afbdbe91 AJ |
132 | if ((flags & RFC1738_ESCAPE_CTRLS) && do_escape == 0) { |
133 | /* RFC 1738 says any control chars (0x00-0x1F) are encoded */ | |
134 | if ((unsigned char) *p <= (unsigned char) 0x1F) | |
135 | do_escape = 1; | |
136 | /* RFC 1738 says 0x7f is encoded */ | |
137 | else if (*p == (char) 0x7F) | |
138 | do_escape = 1; | |
139 | /* RFC 1738 says any non-US-ASCII are encoded */ | |
140 | else if (((unsigned char) *p >= (unsigned char) 0x80)) | |
141 | do_escape = 1; | |
26ac0430 AJ |
142 | } |
143 | /* Do the triplet encoding, or just copy the char */ | |
144 | /* note: we do not need snprintf here as q is appropriately | |
145 | * allocated - KA */ | |
93fc29fe | 146 | |
26ac0430 | 147 | if (do_escape == 1) { |
cc630482 | 148 | (void) snprintf(q, (bufsize-(p-buf)), "%%%02X", (unsigned char) *p); |
26ac0430 AJ |
149 | q += sizeof(char) * 2; |
150 | } else { | |
151 | *q = *p; | |
152 | } | |
090089c4 | 153 | } |
154 | *q = '\0'; | |
155 | return (buf); | |
156 | } | |
157 | ||
158 | /* | |
e4d5e365 | 159 | * Converts a ascii hex code into a binary character. |
090089c4 | 160 | */ |
c6f72b94 | 161 | static int |
e0d6837c HN |
162 | fromhex(char ch) |
163 | { | |
164 | if (ch >= '0' && ch <= '9') | |
165 | return ch - '0'; | |
166 | if (ch >= 'a' && ch <= 'f') | |
167 | return ch - 'a' + 10; | |
168 | if (ch >= 'A' && ch <= 'F') | |
169 | return ch - 'A' + 10; | |
170 | return -1; | |
171 | } | |
172 | ||
e4d5e365 AJ |
173 | /* |
174 | * rfc1738_unescape() - Converts escaped characters (%xy numbers) in | |
175 | * given the string. %% is a %. %ab is the 8-bit hexadecimal number "ab" | |
176 | */ | |
b8d8561b | 177 | void |
8d917594 | 178 | rfc1738_unescape(char *s) |
090089c4 | 179 | { |
090089c4 | 180 | int i, j; /* i is write, j is read */ |
090089c4 | 181 | for (i = j = 0; s[j]; i++, j++) { |
26ac0430 | 182 | s[i] = s[j]; |
e0d6837c HN |
183 | if (s[j] != '%') { |
184 | /* normal case, nothing more to do */ | |
185 | } else if (s[j + 1] == '%') { /* %% case */ | |
186 | j++; /* Skip % */ | |
187 | } else { | |
188 | /* decode */ | |
0a9e98f6 | 189 | int v1, v2, x; |
e0d6837c | 190 | v1 = fromhex(s[j + 1]); |
79c8a298 A |
191 | if (v1 < 0) |
192 | continue; /* non-hex or \0 */ | |
e0d6837c | 193 | v2 = fromhex(s[j + 2]); |
79c8a298 A |
194 | if (v2 < 0) |
195 | continue; /* non-hex or \0 */ | |
55b5914b HN |
196 | x = v1 << 4 | v2; |
197 | if (x > 0 && x <= 255) { | |
198 | s[i] = x; | |
199 | j += 2; | |
200 | } | |
26ac0430 | 201 | } |
090089c4 | 202 | } |
203 | s[i] = '\0'; | |
204 | } |