1 : #define VSTR_CONV_C
2 : /*
3 : * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 James Antill
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 : *
19 : * email: james@and.org
20 : */
21 : /* functions for converting data in vstrs */
22 : #include "main.h"
23 :
24 : /* Can overestimate number of nodes needed, as you get a new one
25 : * everytime you get a new node but it's not a big problem.
26 : * Also note that if you just have _NON nodes and _BUF nodes ot doesn't do
27 : * anything */
28 : #define VSTR__BUF_NEEDED(test, sub) do { \
29 : Vstr_iter iter[1]; \
30 : unsigned int extra_nodes[4] = {0}; \
31 : \
32 : if (!vstr_iter_fwd_beg(base, pos, len, iter)) \
33 : return (FALSE); \
34 : \
35 : if (base->node_ptr_used || base->node_ref_used || \
36 : ( (sub) && base->node_non_used) || \
37 : (!(sub) && !base->conf->split_buf_del)) \
38 : do \
39 : { \
40 : int done = FALSE; \
41 : int first_pass = TRUE; \
42 : \
43 : if ((iter->node->type == VSTR_TYPE_NODE_BUF) && \
44 : ((sub) || !base->conf->split_buf_del)) \
45 : continue; \
46 : if (iter->node->type == VSTR_TYPE_NODE_NON) \
47 : continue; \
48 : \
49 : while (iter->len > 0) \
50 : { \
51 : if (test) \
52 : { \
53 : done = TRUE; \
54 : first_pass = TRUE; \
55 : } \
56 : else if ((sub) || done) \
57 : /* deleteing from the begining of a node is always ok */ \
58 : { \
59 : size_t start_scan_len = iter->len; \
60 : \
61 : if (done && first_pass) \
62 : ++ extra_nodes[iter->node->type - 1]; \
63 : if (sub) \
64 : ++ extra_nodes[VSTR_TYPE_NODE_BUF - 1]; \
65 : \
66 : first_pass = FALSE; \
67 : \
68 : do \
69 : { \
70 : --iter->len; \
71 : ++iter->ptr; \
72 : } while ((iter->len > 0) && \
73 : (!(sub) || \
74 : ((start_scan_len - iter->len) <= base->conf->buf_sz)) && \
75 : !(test)); \
76 : \
77 : continue; \
78 : } \
79 : \
80 : --iter->len; \
81 : ++iter->ptr; \
82 : } \
83 : } while (vstr_iter_fwd_nxt(iter)); \
84 : \
85 : assert(!extra_nodes[VSTR_TYPE_NODE_NON - 1]); \
86 : assert(!extra_nodes[VSTR_TYPE_NODE_BUF - 1] || (sub) || \
87 : base->conf->split_buf_del); \
88 : \
89 : if ((base->node_ptr_used || base->node_ref_used) && \
90 : ((sub) || base->conf->split_buf_del) && \
91 : !extra_nodes[0] && !extra_nodes[1] && \
92 : !extra_nodes[2] && !extra_nodes[3]) \
93 : { } \
94 : else \
95 : { \
96 : ++extra_nodes[VSTR_TYPE_NODE_BUF - 1]; \
97 : \
98 : if (FALSE || \
99 : !vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF, \
100 : extra_nodes[VSTR_TYPE_NODE_BUF - 1], UINT_MAX) || \
101 : !vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_PTR, \
102 : extra_nodes[VSTR_TYPE_NODE_PTR - 1], UINT_MAX) || \
103 : !vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF, \
104 : extra_nodes[VSTR_TYPE_NODE_REF - 1], UINT_MAX) || \
105 : FALSE) \
106 : return (FALSE); \
107 : } \
108 : } while (FALSE)
109 :
110 : int vstr_conv_lowercase(Vstr_base *base, size_t pos, size_t len)
111 11445 : {
112 11445 : Vstr_iter miter[1];
113 11445 : int ret = FALSE;
114 :
115 11445 : VSTR__BUF_NEEDED(!VSTR__IS_ASCII_UPPER(*iter->ptr), TRUE);
116 :
117 11441 : ret = vstr_iter_fwd_beg(base, pos, len, miter);
118 106547 : ASSERT(ret);
119 :
120 131567 : while (len)
121 : {
122 120126 : char tmp = vstr_iter_fwd_chr(miter, NULL);
123 :
124 120126 : if (VSTR__IS_ASCII_UPPER(tmp))
125 : {
126 7919 : tmp = VSTR__TO_ASCII_LOWER(tmp);
127 :
128 7919 : ret = vstr_sub_buf(base, pos, 1, &tmp, 1);
129 7919 : ASSERT(ret);
130 7919 : ret = vstr_iter_fwd_beg(base, pos + 1, len - 1, miter);
131 96740 : ASSERT(ret || (len == 1));
132 : }
133 :
134 120126 : ++pos;
135 120126 : --len;
136 : }
137 :
138 11441 : return (TRUE);
139 : }
140 :
141 : int vstr_conv_uppercase(Vstr_base *base, size_t pos, size_t len)
142 10 : {
143 10 : VSTR__BUF_NEEDED(!VSTR__IS_ASCII_LOWER(*iter->ptr), TRUE);
144 :
145 175 : while (len)
146 : {
147 170 : char tmp = vstr_export_chr(base, pos);
148 170 : int ret = FALSE;
149 :
150 170 : if (VSTR__IS_ASCII_LOWER(tmp))
151 : {
152 65 : tmp = VSTR__TO_ASCII_UPPER(tmp);
153 :
154 65 : ret = vstr_sub_buf(base, pos, 1, &tmp, 1);
155 149 : ASSERT(ret);
156 : }
157 :
158 170 : ++pos;
159 170 : --len;
160 : }
161 :
162 5 : return (TRUE);
163 : }
164 :
165 : /* is it a printable ASCII character */
166 : #define VSTR__IS_ASCII_PRINTABLE(x, flags) ( \
167 : (VSTR__UC(x) == 0x00) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_NUL) : \
168 : (VSTR__UC(x) == 0x07) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_BEL) : \
169 : (VSTR__UC(x) == 0x08) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_BS) : \
170 : (VSTR__UC(x) == 0x09) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_HT) : \
171 : (VSTR__UC(x) == 0x0A) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_LF) : \
172 : (VSTR__UC(x) == 0x0B) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_VT) : \
173 : (VSTR__UC(x) == 0x0C) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_FF) : \
174 : (VSTR__UC(x) == 0x0D) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_CR) : \
175 : (VSTR__UC(x) == 0x1B) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_ESC) : \
176 : (VSTR__UC(x) == 0x20) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_SP) : \
177 : (VSTR__UC(x) == 0x2C) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_COMMA): \
178 : (VSTR__UC(x) == 0x2E) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_DOT) : \
179 : (VSTR__UC(x) == 0x5F) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW__) : \
180 : (VSTR__UC(x) == 0x7F) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_DEL) : \
181 : (VSTR__UC(x) == 0xA0) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_HSP) : \
182 : (VSTR__UC(x) >= 0xA1) ? (flags & VSTR_FLAG_CONV_UNPRINTABLE_ALLOW_HIGH) : \
183 : (unsigned int)((VSTR__UC(x) >= 0x21) && (VSTR__UC(x) <= 0x7E)))
184 :
185 : int vstr_conv_unprintable_chr(Vstr_base *base, size_t pos, size_t len,
186 : unsigned int flags, char swp)
187 1373 : {
188 1373 : VSTR__BUF_NEEDED(VSTR__IS_ASCII_PRINTABLE(*iter->ptr, flags), TRUE);
189 :
190 64836 : while (len)
191 : {
192 63628 : size_t skip_non = vstr_spn_chrs_fwd(base, pos, len, NULL, 1);
193 :
194 63628 : if (skip_non)
195 : {
196 20 : pos += skip_non;
197 20 : len -= skip_non;
198 : }
199 : else
200 : {
201 63608 : char tmp = vstr_export_chr(base, pos);
202 :
203 63608 : if (!VSTR__IS_ASCII_PRINTABLE(tmp, flags))
204 : {
205 32772 : int ret = vstr_sub_buf(base, pos, 1, &swp, 1);
206 57096 : ASSERT(ret);
207 : }
208 :
209 63608 : ++pos;
210 63608 : --len;
211 : }
212 : }
213 :
214 1208 : return (TRUE);
215 : }
216 :
217 : int vstr_conv_unprintable_del(Vstr_base *base, size_t pos, size_t passed_len,
218 : unsigned int flags)
219 266 : {
220 266 : size_t len = passed_len;
221 266 : size_t del_pos = 0;
222 :
223 266 : VSTR__BUF_NEEDED(VSTR__IS_ASCII_PRINTABLE(*iter->ptr, flags), FALSE);
224 :
225 48900 : while (len)
226 : {
227 48700 : size_t skip_non = vstr_spn_chrs_fwd(base, pos, len, NULL, 1);
228 :
229 48700 : if (skip_non)
230 : {
231 20 : pos += skip_non;
232 20 : len -= skip_non;
233 : }
234 : else
235 : {
236 48680 : char tmp = vstr_export_chr(base, pos);
237 :
238 48680 : if (!VSTR__IS_ASCII_PRINTABLE(tmp, flags))
239 : {
240 24740 : if (!del_pos)
241 710 : del_pos = pos;
242 :
243 5516 : assert(pos >= del_pos);
244 : }
245 23940 : else if (del_pos)
246 : {
247 570 : vstr_del(base, del_pos, pos - del_pos);
248 570 : pos = del_pos;
249 570 : del_pos = 0;
250 : }
251 :
252 48680 : ++pos;
253 48680 : --len;
254 : }
255 : }
256 :
257 200 : if (del_pos)
258 140 : vstr_del(base, del_pos, pos - del_pos);
259 :
260 200 : return (TRUE);
261 : }
262 :
263 : #if 0
264 : /* from section 6.7. of rfc2045 */
265 : int vstr_conv_encode_qp(Vstr_base *base, size_t pos, size_t passed_len)
266 : {
267 :
268 : }
269 :
270 : int vstr_conv_decode_qp(Vstr_base *base, size_t pos, size_t passed_len)
271 : {
272 : }
273 : #endif
274 :
275 : int vstr_conv_encode_uri(Vstr_base *base, size_t pos, size_t len)
276 513 : {
277 513 : Vstr_sects *sects = vstr_sects_make(VSTR__SECTS_SZ);
278 513 : size_t count = 0;
279 : /* from rfc2396 Excluded + Reserved + 0x27 (') */
280 : static const unsigned char chrs_disallowed[] = {
281 : 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
282 : 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
283 : 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
284 : 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* control */
285 : 0x20, /* space */
286 : 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2B, 0x2C, 0x2F, 0x3A, 0x3B,
287 : 0x3C, 0x3D, 0x3E, 0x3F, 0x40, /* delims + reserved */
288 : 0x5B, 0x5C, 0x5D, 0x5E, 0x60, 0x7B, 0x7C, 0x7D, /* unwise */
289 : 0x7F, /* control */
290 : 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
291 : 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
292 : 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
293 : 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
294 : 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
295 : 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
296 : 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
297 : 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
298 : 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
299 : 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
300 : 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
301 : 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
302 : 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
303 : 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
304 : 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
305 : 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF /* high ascii */
306 513 : };
307 513 : unsigned int scan = 0;
308 513 : unsigned int multi = 3;
309 :
310 513 : if (!sects)
311 2 : goto malloc_bad;
312 :
313 957 : while (len)
314 : {
315 957 : count = vstr_cspn_chrs_fwd(base, pos, len,
316 : (char *)chrs_disallowed,sizeof(chrs_disallowed));
317 957 : pos += count;
318 957 : len -= count;
319 :
320 957 : if (!len)
321 508 : break;
322 :
323 449 : if (!vstr_sects_add(sects, pos, 1))
324 3 : goto sects_malloc_bad;
325 :
326 446 : ++pos;
327 446 : --len;
328 : }
329 :
330 508 : if (base->conf->buf_sz >= 3)
331 508 : multi = 1;
332 :
333 : /* overestimates */
334 508 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF,
335 : (sects->num * multi) + 2, UINT_MAX))
336 14 : goto nodes_malloc_bad;
337 494 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_NON,
338 : sects->num, UINT_MAX))
339 5 : goto nodes_malloc_bad;
340 489 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_PTR,
341 : sects->num, UINT_MAX))
342 7 : goto nodes_malloc_bad;
343 482 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF,
344 : sects->num, UINT_MAX))
345 5 : goto nodes_malloc_bad;
346 :
347 537 : while (scan < sects->num)
348 : {
349 60 : unsigned int bad = 0;
350 60 : char sub[3];
351 60 : static const char digits[] = "0123456789abcdef";
352 60 : size_t tpos = sects->ptr[scan].pos + (scan * 2);
353 :
354 60 : assert(sects->ptr[scan].len == 1);
355 :
356 60 : bad = vstr_export_chr(base, tpos);
357 60 : sub[0] = '%';
358 60 : sub[1] = digits[((bad >> 4) & 0x0F)];
359 60 : sub[2] = digits[(bad & 0x0F)];
360 :
361 60 : len = base->len;
362 60 : vstr_sub_buf(base, tpos, 1, sub, 3);
363 60 : assert(len == (base->len - 2));
364 :
365 60 : ++scan;
366 : }
367 :
368 477 : vstr_sects_free(sects);
369 :
370 477 : return (TRUE);
371 :
372 : nodes_malloc_bad:
373 : sects_malloc_bad:
374 34 : vstr_sects_free(sects);
375 : malloc_bad:
376 36 : base->conf->malloc_bad = TRUE;
377 36 : return (FALSE);
378 : }
379 :
380 : int vstr_conv_decode_uri(Vstr_base *base, size_t pos, size_t len)
381 13112 : {
382 13112 : Vstr_sects *sects = vstr_sects_make(VSTR__SECTS_SZ);
383 13112 : size_t srch_pos = 0;
384 13112 : unsigned int err = 0;
385 13112 : size_t hex_len = 0;
386 13112 : unsigned int scan = 0;
387 13112 : int percent = 0x25;
388 :
389 13112 : if (!sects)
390 2 : goto malloc_bad;
391 :
392 13498 : while ((srch_pos = vstr_srch_chr_fwd(base, pos, len, percent)))
393 : {
394 422 : size_t left = len - (srch_pos - pos);
395 422 : unsigned char sub = 0;
396 :
397 422 : if (left < 3)
398 31 : break;
399 391 : pos = srch_pos + 1;
400 391 : len = left - 1;
401 :
402 391 : sub = vstr_parse_ushort(base, srch_pos + 1, 2, 16 |
403 : VSTR_FLAG_PARSE_NUM_NO_BEG_PM,
404 : &hex_len, &err);
405 391 : if (err)
406 64 : continue;
407 327 : assert(hex_len == 2);
408 327 : if (!vstr_sects_add(sects, srch_pos, 3))
409 3 : goto sects_malloc_bad;
410 :
411 324 : pos += 2;
412 324 : len -= 2;
413 : }
414 :
415 : /* overestimates */
416 13107 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF,
417 : sects->num + 2, UINT_MAX))
418 12 : goto sects_malloc_bad;
419 13095 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_NON,
420 : sects->num, UINT_MAX))
421 4 : goto sects_malloc_bad;
422 13091 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_PTR,
423 : sects->num, UINT_MAX))
424 6 : goto sects_malloc_bad;
425 13085 : if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF,
426 : sects->num, UINT_MAX))
427 4 : goto sects_malloc_bad;
428 :
429 13131 : while (scan < sects->num)
430 : {
431 50 : unsigned char sub = 0;
432 : /* TODO: tpos is instead of vstr_sub_alter_sects_buf */
433 50 : size_t tpos = sects->ptr[scan].pos - (scan * 2);
434 :
435 50 : assert(sects->ptr[scan].len == 3);
436 50 : sub = vstr_parse_ushort(base, tpos + 1, 2,
437 : 16 | VSTR_FLAG_PARSE_NUM_NO_BEG_PM,
438 : &hex_len, &err);
439 50 : assert(!err);
440 50 : assert(hex_len == 2);
441 :
442 50 : len = base->len;
443 50 : vstr_sub_buf(base, tpos, 3, &sub, 1);
444 50 : assert(len == (base->len + 2));
445 :
446 50 : ++scan;
447 : }
448 :
449 13081 : vstr_sects_free(sects);
450 :
451 13081 : return (TRUE);
452 :
453 : sects_malloc_bad:
454 29 : vstr_sects_free(sects);
455 : malloc_bad:
456 31 : base->conf->malloc_bad = TRUE;
457 31 : return (FALSE);
458 : }
|