]>
Commit | Line | Data |
---|---|---|
30a4f2a8 | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 The Squid Software Foundation and contributors |
e25c139f | 3 | * |
0545caaa AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
30a4f2a8 | 7 | */ |
8 | ||
f7f3304a | 9 | #include "squid.h" |
1fa9b1a7 | 10 | #include "rfc1738.h" |
0d94e9fe | 11 | |
30a4f2a8 | 12 | #if HAVE_STRING_H |
090089c4 | 13 | #include <string.h> |
30a4f2a8 | 14 | #endif |
15 | ||
26ac0430 | 16 | /* |
090089c4 | 17 | * RFC 1738 defines that these characters should be escaped, as well |
18 | * any non-US-ASCII character or anything between 0x00 - 0x1F. | |
19 | */ | |
26ac0430 | 20 | static char rfc1738_unsafe_chars[] = { |
f53969cc SM |
21 | (char) 0x3C, /* < */ |
22 | (char) 0x3E, /* > */ | |
23 | (char) 0x22, /* " */ | |
24 | (char) 0x23, /* # */ | |
25 | #if 0 /* done in code */ | |
26 | (char) 0x20, /* space */ | |
27 | (char) 0x25, /* % */ | |
9bc73deb | 28 | #endif |
f53969cc SM |
29 | (char) 0x7B, /* { */ |
30 | (char) 0x7D, /* } */ | |
31 | (char) 0x7C, /* | */ | |
32 | (char) 0x5C, /* \ */ | |
33 | (char) 0x5E, /* ^ */ | |
34 | (char) 0x7E, /* ~ */ | |
35 | (char) 0x5B, /* [ */ | |
36 | (char) 0x5D, /* ] */ | |
37 | (char) 0x60, /* ` */ | |
38 | (char) 0x27 /* ' */ | |
090089c4 | 39 | }; |
40 | ||
26ac0430 | 41 | static char rfc1738_reserved_chars[] = { |
f53969cc SM |
42 | (char) 0x3b, /* ; */ |
43 | (char) 0x2f, /* / */ | |
44 | (char) 0x3f, /* ? */ | |
45 | (char) 0x3a, /* : */ | |
46 | (char) 0x40, /* @ */ | |
47 | (char) 0x3d, /* = */ | |
48 | (char) 0x26 /* & */ | |
9bc73deb | 49 | }; |
50 | ||
090089c4 | 51 | /* |
26ac0430 | 52 | * rfc1738_escape - Returns a static buffer contains the RFC 1738 |
090089c4 | 53 | * compliant, escaped version of the given url. |
54 | */ | |
1fa9b1a7 AJ |
55 | char * |
56 | rfc1738_do_escape(const char *url, int flags) | |
090089c4 | 57 | { |
3fdadc70 | 58 | static char *buf; |
59 | static size_t bufsize = 0; | |
bd76637b AJ |
60 | const char *src; |
61 | char *dst; | |
2d72d4fd | 62 | unsigned int i, do_escape; |
090089c4 | 63 | |
3fdadc70 | 64 | if (buf == NULL || strlen(url) * 3 > bufsize) { |
26ac0430 AJ |
65 | xfree(buf); |
66 | bufsize = strlen(url) * 3 + 1; | |
1fa9b1a7 | 67 | buf = (char*)xcalloc(bufsize, 1); |
3fdadc70 | 68 | } |
bd76637b | 69 | for (src = url, dst = buf; *src != '\0' && dst < (buf + bufsize - 1); src++, dst++) { |
afbdbe91 AJ |
70 | |
71 | /* a-z, A-Z and 0-9 are SAFE. */ | |
bd76637b AJ |
72 | if ((*src >= 'a' && *src <= 'z') || (*src >= 'A' && *src <= 'Z') || (*src >= '0' && *src <= '9')) { |
73 | *dst = *src; | |
afbdbe91 AJ |
74 | continue; |
75 | } | |
76 | ||
26ac0430 | 77 | do_escape = 0; |
090089c4 | 78 | |
26ac0430 | 79 | /* RFC 1738 defines these chars as unsafe */ |
afbdbe91 | 80 | if ((flags & RFC1738_ESCAPE_UNSAFE)) { |
42ff91f9 | 81 | for (i = 0; i < sizeof(rfc1738_unsafe_chars); i++) { |
bd76637b | 82 | if (*src == rfc1738_unsafe_chars[i]) { |
afbdbe91 AJ |
83 | do_escape = 1; |
84 | break; | |
85 | } | |
26ac0430 | 86 | } |
afbdbe91 | 87 | /* Handle % separately */ |
bd76637b | 88 | if (!(flags & RFC1738_ESCAPE_NOPERCENT) && *src == '%') |
afbdbe91 AJ |
89 | do_escape = 1; |
90 | /* Handle space separately */ | |
bd76637b | 91 | else if (!(flags & RFC1738_ESCAPE_NOSPACE) && *src <= ' ') |
afbdbe91 | 92 | do_escape = 1; |
26ac0430 | 93 | } |
26ac0430 | 94 | /* RFC 1738 defines these chars as reserved */ |
afbdbe91 AJ |
95 | if ((flags & RFC1738_ESCAPE_RESERVED) && do_escape == 0) { |
96 | for (i = 0; i < sizeof(rfc1738_reserved_chars); i++) { | |
bd76637b | 97 | if (*src == rfc1738_reserved_chars[i]) { |
afbdbe91 AJ |
98 | do_escape = 1; |
99 | break; | |
100 | } | |
26ac0430 AJ |
101 | } |
102 | } | |
afbdbe91 AJ |
103 | if ((flags & RFC1738_ESCAPE_CTRLS) && do_escape == 0) { |
104 | /* RFC 1738 says any control chars (0x00-0x1F) are encoded */ | |
bd76637b | 105 | if ((unsigned char) *src <= (unsigned char) 0x1F) |
afbdbe91 AJ |
106 | do_escape = 1; |
107 | /* RFC 1738 says 0x7f is encoded */ | |
bd76637b | 108 | else if (*src == (char) 0x7F) |
afbdbe91 AJ |
109 | do_escape = 1; |
110 | /* RFC 1738 says any non-US-ASCII are encoded */ | |
bd76637b | 111 | else if (((unsigned char) *src >= (unsigned char) 0x80)) |
afbdbe91 | 112 | do_escape = 1; |
26ac0430 AJ |
113 | } |
114 | /* Do the triplet encoding, or just copy the char */ | |
26ac0430 | 115 | if (do_escape == 1) { |
bd76637b AJ |
116 | (void) snprintf(dst, (bufsize-(dst-buf)), "%%%02X", (unsigned char) *src); |
117 | dst += sizeof(char) * 2; | |
26ac0430 | 118 | } else { |
bd76637b | 119 | *dst = *src; |
26ac0430 | 120 | } |
090089c4 | 121 | } |
bd76637b | 122 | *dst = '\0'; |
090089c4 | 123 | return (buf); |
124 | } | |
125 | ||
126 | /* | |
e4d5e365 | 127 | * Converts a ascii hex code into a binary character. |
090089c4 | 128 | */ |
c6f72b94 | 129 | static int |
e0d6837c HN |
130 | fromhex(char ch) |
131 | { | |
132 | if (ch >= '0' && ch <= '9') | |
133 | return ch - '0'; | |
134 | if (ch >= 'a' && ch <= 'f') | |
135 | return ch - 'a' + 10; | |
136 | if (ch >= 'A' && ch <= 'F') | |
137 | return ch - 'A' + 10; | |
138 | return -1; | |
139 | } | |
140 | ||
e4d5e365 AJ |
141 | /* |
142 | * rfc1738_unescape() - Converts escaped characters (%xy numbers) in | |
143 | * given the string. %% is a %. %ab is the 8-bit hexadecimal number "ab" | |
144 | */ | |
b8d8561b | 145 | void |
8d917594 | 146 | rfc1738_unescape(char *s) |
090089c4 | 147 | { |
f53969cc | 148 | int i, j; /* i is write, j is read */ |
090089c4 | 149 | for (i = j = 0; s[j]; i++, j++) { |
26ac0430 | 150 | s[i] = s[j]; |
e0d6837c HN |
151 | if (s[j] != '%') { |
152 | /* normal case, nothing more to do */ | |
f53969cc SM |
153 | } else if (s[j + 1] == '%') { /* %% case */ |
154 | j++; /* Skip % */ | |
e0d6837c HN |
155 | } else { |
156 | /* decode */ | |
0a9e98f6 | 157 | int v1, v2, x; |
e0d6837c | 158 | v1 = fromhex(s[j + 1]); |
79c8a298 A |
159 | if (v1 < 0) |
160 | continue; /* non-hex or \0 */ | |
e0d6837c | 161 | v2 = fromhex(s[j + 2]); |
79c8a298 A |
162 | if (v2 < 0) |
163 | continue; /* non-hex or \0 */ | |
55b5914b HN |
164 | x = v1 << 4 | v2; |
165 | if (x > 0 && x <= 255) { | |
166 | s[i] = x; | |
167 | j += 2; | |
168 | } | |
26ac0430 | 169 | } |
090089c4 | 170 | } |
171 | s[i] = '\0'; | |
172 | } | |
f53969cc | 173 |