]>
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 | ||
f7f3304a | 35 | #include "squid.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; | |
bd76637b AJ |
89 | const char *src; |
90 | char *dst; | |
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 | } |
bd76637b | 98 | for (src = url, dst = buf; *src != '\0' && dst < (buf + bufsize - 1); src++, dst++) { |
afbdbe91 AJ |
99 | |
100 | /* a-z, A-Z and 0-9 are SAFE. */ | |
bd76637b AJ |
101 | if ((*src >= 'a' && *src <= 'z') || (*src >= 'A' && *src <= 'Z') || (*src >= '0' && *src <= '9')) { |
102 | *dst = *src; | |
afbdbe91 AJ |
103 | continue; |
104 | } | |
105 | ||
26ac0430 | 106 | do_escape = 0; |
090089c4 | 107 | |
26ac0430 | 108 | /* RFC 1738 defines these chars as unsafe */ |
afbdbe91 | 109 | if ((flags & RFC1738_ESCAPE_UNSAFE)) { |
42ff91f9 | 110 | for (i = 0; i < sizeof(rfc1738_unsafe_chars); i++) { |
bd76637b | 111 | if (*src == rfc1738_unsafe_chars[i]) { |
afbdbe91 AJ |
112 | do_escape = 1; |
113 | break; | |
114 | } | |
26ac0430 | 115 | } |
afbdbe91 | 116 | /* Handle % separately */ |
bd76637b | 117 | if (!(flags & RFC1738_ESCAPE_NOPERCENT) && *src == '%') |
afbdbe91 AJ |
118 | do_escape = 1; |
119 | /* Handle space separately */ | |
bd76637b | 120 | else if (!(flags & RFC1738_ESCAPE_NOSPACE) && *src <= ' ') |
afbdbe91 | 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++) { | |
bd76637b | 126 | if (*src == rfc1738_reserved_chars[i]) { |
afbdbe91 AJ |
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 */ | |
bd76637b | 134 | if ((unsigned char) *src <= (unsigned char) 0x1F) |
afbdbe91 AJ |
135 | do_escape = 1; |
136 | /* RFC 1738 says 0x7f is encoded */ | |
bd76637b | 137 | else if (*src == (char) 0x7F) |
afbdbe91 AJ |
138 | do_escape = 1; |
139 | /* RFC 1738 says any non-US-ASCII are encoded */ | |
bd76637b | 140 | else if (((unsigned char) *src >= (unsigned char) 0x80)) |
afbdbe91 | 141 | do_escape = 1; |
26ac0430 AJ |
142 | } |
143 | /* Do the triplet encoding, or just copy the char */ | |
26ac0430 | 144 | if (do_escape == 1) { |
bd76637b AJ |
145 | (void) snprintf(dst, (bufsize-(dst-buf)), "%%%02X", (unsigned char) *src); |
146 | dst += sizeof(char) * 2; | |
26ac0430 | 147 | } else { |
bd76637b | 148 | *dst = *src; |
26ac0430 | 149 | } |
090089c4 | 150 | } |
bd76637b | 151 | *dst = '\0'; |
090089c4 | 152 | return (buf); |
153 | } | |
154 | ||
155 | /* | |
e4d5e365 | 156 | * Converts a ascii hex code into a binary character. |
090089c4 | 157 | */ |
c6f72b94 | 158 | static int |
e0d6837c HN |
159 | fromhex(char ch) |
160 | { | |
161 | if (ch >= '0' && ch <= '9') | |
162 | return ch - '0'; | |
163 | if (ch >= 'a' && ch <= 'f') | |
164 | return ch - 'a' + 10; | |
165 | if (ch >= 'A' && ch <= 'F') | |
166 | return ch - 'A' + 10; | |
167 | return -1; | |
168 | } | |
169 | ||
e4d5e365 AJ |
170 | /* |
171 | * rfc1738_unescape() - Converts escaped characters (%xy numbers) in | |
172 | * given the string. %% is a %. %ab is the 8-bit hexadecimal number "ab" | |
173 | */ | |
b8d8561b | 174 | void |
8d917594 | 175 | rfc1738_unescape(char *s) |
090089c4 | 176 | { |
090089c4 | 177 | int i, j; /* i is write, j is read */ |
090089c4 | 178 | for (i = j = 0; s[j]; i++, j++) { |
26ac0430 | 179 | s[i] = s[j]; |
e0d6837c HN |
180 | if (s[j] != '%') { |
181 | /* normal case, nothing more to do */ | |
182 | } else if (s[j + 1] == '%') { /* %% case */ | |
183 | j++; /* Skip % */ | |
184 | } else { | |
185 | /* decode */ | |
0a9e98f6 | 186 | int v1, v2, x; |
e0d6837c | 187 | v1 = fromhex(s[j + 1]); |
79c8a298 A |
188 | if (v1 < 0) |
189 | continue; /* non-hex or \0 */ | |
e0d6837c | 190 | v2 = fromhex(s[j + 2]); |
79c8a298 A |
191 | if (v2 < 0) |
192 | continue; /* non-hex or \0 */ | |
55b5914b HN |
193 | x = v1 << 4 | v2; |
194 | if (x > 0 && x <= 255) { | |
195 | s[i] = x; | |
196 | j += 2; | |
197 | } | |
26ac0430 | 198 | } |
090089c4 | 199 | } |
200 | s[i] = '\0'; | |
201 | } |