1*76404edcSAsim Jamshed #include "buffer.h"
2*76404edcSAsim Jamshed 
3*76404edcSAsim Jamshed #include <stdlib.h>
4*76404edcSAsim Jamshed #include <string.h>
5*76404edcSAsim Jamshed 
6*76404edcSAsim Jamshed #include <stdio.h>
7*76404edcSAsim Jamshed #include <assert.h>
8*76404edcSAsim Jamshed #include <ctype.h>
9*76404edcSAsim Jamshed 
10*76404edcSAsim Jamshed 
11*76404edcSAsim Jamshed static const char hex_chars[] = "0123456789abcdef";
12*76404edcSAsim Jamshed 
13*76404edcSAsim Jamshed 
14*76404edcSAsim Jamshed /**
15*76404edcSAsim Jamshed  * init the buffer
16*76404edcSAsim Jamshed  *
17*76404edcSAsim Jamshed  */
18*76404edcSAsim Jamshed 
buffer_init(void)19*76404edcSAsim Jamshed buffer* buffer_init(void) {
20*76404edcSAsim Jamshed 	buffer *b;
21*76404edcSAsim Jamshed 
22*76404edcSAsim Jamshed 	b = malloc(sizeof(*b));
23*76404edcSAsim Jamshed 	assert(b);
24*76404edcSAsim Jamshed 
25*76404edcSAsim Jamshed 	b->ptr = NULL;
26*76404edcSAsim Jamshed 	b->size = 0;
27*76404edcSAsim Jamshed 	b->used = 0;
28*76404edcSAsim Jamshed 
29*76404edcSAsim Jamshed 	return b;
30*76404edcSAsim Jamshed }
31*76404edcSAsim Jamshed 
buffer_init_buffer(buffer * src)32*76404edcSAsim Jamshed buffer *buffer_init_buffer(buffer *src) {
33*76404edcSAsim Jamshed 	buffer *b = buffer_init();
34*76404edcSAsim Jamshed 	buffer_copy_string_buffer(b, src);
35*76404edcSAsim Jamshed 	return b;
36*76404edcSAsim Jamshed }
37*76404edcSAsim Jamshed 
38*76404edcSAsim Jamshed /**
39*76404edcSAsim Jamshed  * free the buffer
40*76404edcSAsim Jamshed  *
41*76404edcSAsim Jamshed  */
42*76404edcSAsim Jamshed 
buffer_free(buffer * b)43*76404edcSAsim Jamshed void buffer_free(buffer *b) {
44*76404edcSAsim Jamshed 	if (!b) return;
45*76404edcSAsim Jamshed 
46*76404edcSAsim Jamshed 	free(b->ptr);
47*76404edcSAsim Jamshed 	free(b);
48*76404edcSAsim Jamshed }
49*76404edcSAsim Jamshed 
buffer_reset(buffer * b)50*76404edcSAsim Jamshed void buffer_reset(buffer *b) {
51*76404edcSAsim Jamshed 	if (!b) return;
52*76404edcSAsim Jamshed 
53*76404edcSAsim Jamshed 	/* limit don't reuse buffer larger than ... bytes */
54*76404edcSAsim Jamshed 	if (b->size > BUFFER_MAX_REUSE_SIZE) {
55*76404edcSAsim Jamshed 		free(b->ptr);
56*76404edcSAsim Jamshed 		b->ptr = NULL;
57*76404edcSAsim Jamshed 		b->size = 0;
58*76404edcSAsim Jamshed 	} else if (b->size) {
59*76404edcSAsim Jamshed 		b->ptr[0] = '\0';
60*76404edcSAsim Jamshed 	}
61*76404edcSAsim Jamshed 
62*76404edcSAsim Jamshed 	b->used = 0;
63*76404edcSAsim Jamshed }
64*76404edcSAsim Jamshed 
65*76404edcSAsim Jamshed 
66*76404edcSAsim Jamshed /**
67*76404edcSAsim Jamshed  *
68*76404edcSAsim Jamshed  * allocate (if neccessary) enough space for 'size' bytes and
69*76404edcSAsim Jamshed  * set the 'used' counter to 0
70*76404edcSAsim Jamshed  *
71*76404edcSAsim Jamshed  */
72*76404edcSAsim Jamshed 
73*76404edcSAsim Jamshed #define BUFFER_PIECE_SIZE 64
74*76404edcSAsim Jamshed 
buffer_prepare_copy(buffer * b,size_t size)75*76404edcSAsim Jamshed int buffer_prepare_copy(buffer *b, size_t size) {
76*76404edcSAsim Jamshed 	if (!b) return -1;
77*76404edcSAsim Jamshed 
78*76404edcSAsim Jamshed 	if ((0 == b->size) ||
79*76404edcSAsim Jamshed 	    (size > b->size)) {
80*76404edcSAsim Jamshed 		if (b->size) free(b->ptr);
81*76404edcSAsim Jamshed 
82*76404edcSAsim Jamshed 		b->size = size;
83*76404edcSAsim Jamshed 
84*76404edcSAsim Jamshed 		/* always allocate a multiply of BUFFER_PIECE_SIZE */
85*76404edcSAsim Jamshed 		b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
86*76404edcSAsim Jamshed 
87*76404edcSAsim Jamshed 		b->ptr = malloc(b->size);
88*76404edcSAsim Jamshed 		assert(b->ptr);
89*76404edcSAsim Jamshed 	}
90*76404edcSAsim Jamshed 	b->used = 0;
91*76404edcSAsim Jamshed 	return 0;
92*76404edcSAsim Jamshed }
93*76404edcSAsim Jamshed 
94*76404edcSAsim Jamshed /**
95*76404edcSAsim Jamshed  *
96*76404edcSAsim Jamshed  * increase the internal buffer (if neccessary) to append another 'size' byte
97*76404edcSAsim Jamshed  * ->used isn't changed
98*76404edcSAsim Jamshed  *
99*76404edcSAsim Jamshed  */
100*76404edcSAsim Jamshed 
buffer_prepare_append(buffer * b,size_t size)101*76404edcSAsim Jamshed int buffer_prepare_append(buffer *b, size_t size) {
102*76404edcSAsim Jamshed 	if (!b) return -1;
103*76404edcSAsim Jamshed 
104*76404edcSAsim Jamshed 	if (0 == b->size) {
105*76404edcSAsim Jamshed 		b->size = size;
106*76404edcSAsim Jamshed 
107*76404edcSAsim Jamshed 		/* always allocate a multiply of BUFFER_PIECE_SIZE */
108*76404edcSAsim Jamshed 		b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
109*76404edcSAsim Jamshed 
110*76404edcSAsim Jamshed 		b->ptr = malloc(b->size);
111*76404edcSAsim Jamshed 		b->used = 0;
112*76404edcSAsim Jamshed 		assert(b->ptr);
113*76404edcSAsim Jamshed 	} else if (b->used + size > b->size) {
114*76404edcSAsim Jamshed 		b->size += size;
115*76404edcSAsim Jamshed 
116*76404edcSAsim Jamshed 		/* always allocate a multiply of BUFFER_PIECE_SIZE */
117*76404edcSAsim Jamshed 		b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
118*76404edcSAsim Jamshed 
119*76404edcSAsim Jamshed 		b->ptr = realloc(b->ptr, b->size);
120*76404edcSAsim Jamshed 		assert(b->ptr);
121*76404edcSAsim Jamshed 	}
122*76404edcSAsim Jamshed 	return 0;
123*76404edcSAsim Jamshed }
124*76404edcSAsim Jamshed 
buffer_copy_string(buffer * b,const char * s)125*76404edcSAsim Jamshed int buffer_copy_string(buffer *b, const char *s) {
126*76404edcSAsim Jamshed 	size_t s_len;
127*76404edcSAsim Jamshed 
128*76404edcSAsim Jamshed 	if (!s || !b) return -1;
129*76404edcSAsim Jamshed 
130*76404edcSAsim Jamshed 	s_len = strlen(s) + 1;
131*76404edcSAsim Jamshed 	buffer_prepare_copy(b, s_len);
132*76404edcSAsim Jamshed 
133*76404edcSAsim Jamshed 	memcpy(b->ptr, s, s_len);
134*76404edcSAsim Jamshed 	b->used = s_len;
135*76404edcSAsim Jamshed 
136*76404edcSAsim Jamshed 	return 0;
137*76404edcSAsim Jamshed }
138*76404edcSAsim Jamshed 
buffer_copy_string_len(buffer * b,const char * s,size_t s_len)139*76404edcSAsim Jamshed int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
140*76404edcSAsim Jamshed 	if (!s || !b) return -1;
141*76404edcSAsim Jamshed #if 0
142*76404edcSAsim Jamshed 	/* removed optimization as we have to keep the empty string
143*76404edcSAsim Jamshed 	 * in some cases for the config handling
144*76404edcSAsim Jamshed 	 *
145*76404edcSAsim Jamshed 	 * url.access-deny = ( "" )
146*76404edcSAsim Jamshed 	 */
147*76404edcSAsim Jamshed 	if (s_len == 0) return 0;
148*76404edcSAsim Jamshed #endif
149*76404edcSAsim Jamshed 	buffer_prepare_copy(b, s_len + 1);
150*76404edcSAsim Jamshed 
151*76404edcSAsim Jamshed 	memcpy(b->ptr, s, s_len);
152*76404edcSAsim Jamshed 	b->ptr[s_len] = '\0';
153*76404edcSAsim Jamshed 	b->used = s_len + 1;
154*76404edcSAsim Jamshed 
155*76404edcSAsim Jamshed 	return 0;
156*76404edcSAsim Jamshed }
157*76404edcSAsim Jamshed 
buffer_copy_string_buffer(buffer * b,const buffer * src)158*76404edcSAsim Jamshed int buffer_copy_string_buffer(buffer *b, const buffer *src) {
159*76404edcSAsim Jamshed 	if (!src) return -1;
160*76404edcSAsim Jamshed 
161*76404edcSAsim Jamshed 	if (src->used == 0) {
162*76404edcSAsim Jamshed 		buffer_reset(b);
163*76404edcSAsim Jamshed 		return 0;
164*76404edcSAsim Jamshed 	}
165*76404edcSAsim Jamshed 	return buffer_copy_string_len(b, src->ptr, src->used - 1);
166*76404edcSAsim Jamshed }
167*76404edcSAsim Jamshed 
buffer_append_string(buffer * b,const char * s)168*76404edcSAsim Jamshed int buffer_append_string(buffer *b, const char *s) {
169*76404edcSAsim Jamshed 	size_t s_len;
170*76404edcSAsim Jamshed 
171*76404edcSAsim Jamshed 	if (!s || !b) return -1;
172*76404edcSAsim Jamshed 
173*76404edcSAsim Jamshed 	s_len = strlen(s);
174*76404edcSAsim Jamshed 	buffer_prepare_append(b, s_len + 1);
175*76404edcSAsim Jamshed 	if (b->used == 0)
176*76404edcSAsim Jamshed 		b->used++;
177*76404edcSAsim Jamshed 
178*76404edcSAsim Jamshed 	memcpy(b->ptr + b->used - 1, s, s_len + 1);
179*76404edcSAsim Jamshed 	b->used += s_len;
180*76404edcSAsim Jamshed 
181*76404edcSAsim Jamshed 	return 0;
182*76404edcSAsim Jamshed }
183*76404edcSAsim Jamshed 
buffer_append_string_rfill(buffer * b,const char * s,size_t maxlen)184*76404edcSAsim Jamshed int buffer_append_string_rfill(buffer *b, const char *s, size_t maxlen) {
185*76404edcSAsim Jamshed 	size_t s_len;
186*76404edcSAsim Jamshed 
187*76404edcSAsim Jamshed 	if (!s || !b) return -1;
188*76404edcSAsim Jamshed 
189*76404edcSAsim Jamshed 	s_len = strlen(s);
190*76404edcSAsim Jamshed 	if (s_len > maxlen)  s_len = maxlen;
191*76404edcSAsim Jamshed 	buffer_prepare_append(b, maxlen + 1);
192*76404edcSAsim Jamshed 	if (b->used == 0)
193*76404edcSAsim Jamshed 		b->used++;
194*76404edcSAsim Jamshed 
195*76404edcSAsim Jamshed 	memcpy(b->ptr + b->used - 1, s, s_len);
196*76404edcSAsim Jamshed 	if (maxlen > s_len) {
197*76404edcSAsim Jamshed 		memset(b->ptr + b->used - 1 + s_len, ' ', maxlen - s_len);
198*76404edcSAsim Jamshed 	}
199*76404edcSAsim Jamshed 
200*76404edcSAsim Jamshed 	b->used += maxlen;
201*76404edcSAsim Jamshed 	b->ptr[b->used - 1] = '\0';
202*76404edcSAsim Jamshed 	return 0;
203*76404edcSAsim Jamshed }
204*76404edcSAsim Jamshed 
205*76404edcSAsim Jamshed /**
206*76404edcSAsim Jamshed  * append a string to the end of the buffer
207*76404edcSAsim Jamshed  *
208*76404edcSAsim Jamshed  * the resulting buffer is terminated with a '\0'
209*76404edcSAsim Jamshed  * s is treated as a un-terminated string (a \0 is handled a normal character)
210*76404edcSAsim Jamshed  *
211*76404edcSAsim Jamshed  * @param b a buffer
212*76404edcSAsim Jamshed  * @param s the string
213*76404edcSAsim Jamshed  * @param s_len size of the string (without the terminating \0)
214*76404edcSAsim Jamshed  */
215*76404edcSAsim Jamshed 
buffer_append_string_len(buffer * b,const char * s,size_t s_len)216*76404edcSAsim Jamshed int buffer_append_string_len(buffer *b, const char *s, size_t s_len) {
217*76404edcSAsim Jamshed 	if (!s || !b) return -1;
218*76404edcSAsim Jamshed 	if (s_len == 0) return 0;
219*76404edcSAsim Jamshed 
220*76404edcSAsim Jamshed 	buffer_prepare_append(b, s_len + 1);
221*76404edcSAsim Jamshed 	if (b->used == 0)
222*76404edcSAsim Jamshed 		b->used++;
223*76404edcSAsim Jamshed 
224*76404edcSAsim Jamshed 	memcpy(b->ptr + b->used - 1, s, s_len);
225*76404edcSAsim Jamshed 	b->used += s_len;
226*76404edcSAsim Jamshed 	b->ptr[b->used - 1] = '\0';
227*76404edcSAsim Jamshed 
228*76404edcSAsim Jamshed 	return 0;
229*76404edcSAsim Jamshed }
230*76404edcSAsim Jamshed 
buffer_append_string_buffer(buffer * b,const buffer * src)231*76404edcSAsim Jamshed int buffer_append_string_buffer(buffer *b, const buffer *src) {
232*76404edcSAsim Jamshed 	if (!src) return -1;
233*76404edcSAsim Jamshed 	if (src->used == 0) return 0;
234*76404edcSAsim Jamshed 
235*76404edcSAsim Jamshed 	return buffer_append_string_len(b, src->ptr, src->used - 1);
236*76404edcSAsim Jamshed }
237*76404edcSAsim Jamshed 
buffer_append_memory(buffer * b,const char * s,size_t s_len)238*76404edcSAsim Jamshed int buffer_append_memory(buffer *b, const char *s, size_t s_len) {
239*76404edcSAsim Jamshed 	if (!s || !b) return -1;
240*76404edcSAsim Jamshed 	if (s_len == 0) return 0;
241*76404edcSAsim Jamshed 
242*76404edcSAsim Jamshed 	buffer_prepare_append(b, s_len);
243*76404edcSAsim Jamshed 	memcpy(b->ptr + b->used, s, s_len);
244*76404edcSAsim Jamshed 	b->used += s_len;
245*76404edcSAsim Jamshed 
246*76404edcSAsim Jamshed 	return 0;
247*76404edcSAsim Jamshed }
248*76404edcSAsim Jamshed 
buffer_copy_memory(buffer * b,const char * s,size_t s_len)249*76404edcSAsim Jamshed int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
250*76404edcSAsim Jamshed 	if (!s || !b) return -1;
251*76404edcSAsim Jamshed 
252*76404edcSAsim Jamshed 	b->used = 0;
253*76404edcSAsim Jamshed 
254*76404edcSAsim Jamshed 	return buffer_append_memory(b, s, s_len);
255*76404edcSAsim Jamshed }
256*76404edcSAsim Jamshed 
buffer_append_long_hex(buffer * b,unsigned long value)257*76404edcSAsim Jamshed int buffer_append_long_hex(buffer *b, unsigned long value) {
258*76404edcSAsim Jamshed 	char *buf;
259*76404edcSAsim Jamshed 	int shift = 0;
260*76404edcSAsim Jamshed 	unsigned long copy = value;
261*76404edcSAsim Jamshed 
262*76404edcSAsim Jamshed 	while (copy) {
263*76404edcSAsim Jamshed 		copy >>= 4;
264*76404edcSAsim Jamshed 		shift++;
265*76404edcSAsim Jamshed 	}
266*76404edcSAsim Jamshed 	if (shift == 0)
267*76404edcSAsim Jamshed 		shift++;
268*76404edcSAsim Jamshed 	if (shift & 0x01)
269*76404edcSAsim Jamshed 		shift++;
270*76404edcSAsim Jamshed 
271*76404edcSAsim Jamshed 	buffer_prepare_append(b, shift + 1);
272*76404edcSAsim Jamshed 	if (b->used == 0)
273*76404edcSAsim Jamshed 		b->used++;
274*76404edcSAsim Jamshed 	buf = b->ptr + (b->used - 1);
275*76404edcSAsim Jamshed 	b->used += shift;
276*76404edcSAsim Jamshed 
277*76404edcSAsim Jamshed 	shift <<= 2;
278*76404edcSAsim Jamshed 	while (shift > 0) {
279*76404edcSAsim Jamshed 		shift -= 4;
280*76404edcSAsim Jamshed 		*(buf++) = hex_chars[(value >> shift) & 0x0F];
281*76404edcSAsim Jamshed 	}
282*76404edcSAsim Jamshed 	*buf = '\0';
283*76404edcSAsim Jamshed 
284*76404edcSAsim Jamshed 	return 0;
285*76404edcSAsim Jamshed }
286*76404edcSAsim Jamshed 
LI_ltostr(char * buf,long val)287*76404edcSAsim Jamshed int LI_ltostr(char *buf, long val) {
288*76404edcSAsim Jamshed 	char swap;
289*76404edcSAsim Jamshed 	char *end;
290*76404edcSAsim Jamshed 	int len = 1;
291*76404edcSAsim Jamshed 
292*76404edcSAsim Jamshed 	if (val < 0) {
293*76404edcSAsim Jamshed 		len++;
294*76404edcSAsim Jamshed 		*(buf++) = '-';
295*76404edcSAsim Jamshed 		val = -val;
296*76404edcSAsim Jamshed 	}
297*76404edcSAsim Jamshed 
298*76404edcSAsim Jamshed 	end = buf;
299*76404edcSAsim Jamshed 	while (val > 9) {
300*76404edcSAsim Jamshed 		*(end++) = '0' + (val % 10);
301*76404edcSAsim Jamshed 		val = val / 10;
302*76404edcSAsim Jamshed 	}
303*76404edcSAsim Jamshed 	*(end) = '0' + val;
304*76404edcSAsim Jamshed 	*(end + 1) = '\0';
305*76404edcSAsim Jamshed 	len += end - buf;
306*76404edcSAsim Jamshed 
307*76404edcSAsim Jamshed 	while (buf < end) {
308*76404edcSAsim Jamshed 		swap = *end;
309*76404edcSAsim Jamshed 		*end = *buf;
310*76404edcSAsim Jamshed 		*buf = swap;
311*76404edcSAsim Jamshed 
312*76404edcSAsim Jamshed 		buf++;
313*76404edcSAsim Jamshed 		end--;
314*76404edcSAsim Jamshed 	}
315*76404edcSAsim Jamshed 
316*76404edcSAsim Jamshed 	return len;
317*76404edcSAsim Jamshed }
318*76404edcSAsim Jamshed 
buffer_append_long(buffer * b,long val)319*76404edcSAsim Jamshed int buffer_append_long(buffer *b, long val) {
320*76404edcSAsim Jamshed 	if (!b) return -1;
321*76404edcSAsim Jamshed 
322*76404edcSAsim Jamshed 	buffer_prepare_append(b, 32);
323*76404edcSAsim Jamshed 	if (b->used == 0)
324*76404edcSAsim Jamshed 		b->used++;
325*76404edcSAsim Jamshed 
326*76404edcSAsim Jamshed 	b->used += LI_ltostr(b->ptr + (b->used - 1), val);
327*76404edcSAsim Jamshed 	return 0;
328*76404edcSAsim Jamshed }
329*76404edcSAsim Jamshed 
buffer_copy_long(buffer * b,long val)330*76404edcSAsim Jamshed int buffer_copy_long(buffer *b, long val) {
331*76404edcSAsim Jamshed 	if (!b) return -1;
332*76404edcSAsim Jamshed 
333*76404edcSAsim Jamshed 	b->used = 0;
334*76404edcSAsim Jamshed 	return buffer_append_long(b, val);
335*76404edcSAsim Jamshed }
336*76404edcSAsim Jamshed 
337*76404edcSAsim Jamshed #if !defined(SIZEOF_LONG) || (SIZEOF_LONG != SIZEOF_OFF_T)
buffer_append_off_t(buffer * b,off_t val)338*76404edcSAsim Jamshed int buffer_append_off_t(buffer *b, off_t val) {
339*76404edcSAsim Jamshed 	char swap;
340*76404edcSAsim Jamshed 	char *end;
341*76404edcSAsim Jamshed 	char *start;
342*76404edcSAsim Jamshed 	int len = 1;
343*76404edcSAsim Jamshed 
344*76404edcSAsim Jamshed 	if (!b) return -1;
345*76404edcSAsim Jamshed 
346*76404edcSAsim Jamshed 	buffer_prepare_append(b, 32);
347*76404edcSAsim Jamshed 	if (b->used == 0)
348*76404edcSAsim Jamshed 		b->used++;
349*76404edcSAsim Jamshed 
350*76404edcSAsim Jamshed 	start = b->ptr + (b->used - 1);
351*76404edcSAsim Jamshed 	if (val < 0) {
352*76404edcSAsim Jamshed 		len++;
353*76404edcSAsim Jamshed 		*(start++) = '-';
354*76404edcSAsim Jamshed 		val = -val;
355*76404edcSAsim Jamshed 	}
356*76404edcSAsim Jamshed 
357*76404edcSAsim Jamshed 	end = start;
358*76404edcSAsim Jamshed 	while (val > 9) {
359*76404edcSAsim Jamshed 		*(end++) = '0' + (val % 10);
360*76404edcSAsim Jamshed 		val = val / 10;
361*76404edcSAsim Jamshed 	}
362*76404edcSAsim Jamshed 	*(end) = '0' + val;
363*76404edcSAsim Jamshed 	*(end + 1) = '\0';
364*76404edcSAsim Jamshed 	len += end - start;
365*76404edcSAsim Jamshed 
366*76404edcSAsim Jamshed 	while (start < end) {
367*76404edcSAsim Jamshed 		swap   = *end;
368*76404edcSAsim Jamshed 		*end   = *start;
369*76404edcSAsim Jamshed 		*start = swap;
370*76404edcSAsim Jamshed 
371*76404edcSAsim Jamshed 		start++;
372*76404edcSAsim Jamshed 		end--;
373*76404edcSAsim Jamshed 	}
374*76404edcSAsim Jamshed 
375*76404edcSAsim Jamshed 	b->used += len;
376*76404edcSAsim Jamshed 	return 0;
377*76404edcSAsim Jamshed }
378*76404edcSAsim Jamshed 
buffer_copy_off_t(buffer * b,off_t val)379*76404edcSAsim Jamshed int buffer_copy_off_t(buffer *b, off_t val) {
380*76404edcSAsim Jamshed 	if (!b) return -1;
381*76404edcSAsim Jamshed 
382*76404edcSAsim Jamshed 	b->used = 0;
383*76404edcSAsim Jamshed 	return buffer_append_off_t(b, val);
384*76404edcSAsim Jamshed }
385*76404edcSAsim Jamshed #endif /* !defined(SIZEOF_LONG) || (SIZEOF_LONG != SIZEOF_OFF_T) */
386*76404edcSAsim Jamshed 
int2hex(char c)387*76404edcSAsim Jamshed char int2hex(char c) {
388*76404edcSAsim Jamshed 	return hex_chars[(c & 0x0F)];
389*76404edcSAsim Jamshed }
390*76404edcSAsim Jamshed 
391*76404edcSAsim Jamshed /* converts hex char (0-9, A-Z, a-z) to decimal.
392*76404edcSAsim Jamshed  * returns 0xFF on invalid input.
393*76404edcSAsim Jamshed  */
hex2int(unsigned char hex)394*76404edcSAsim Jamshed char hex2int(unsigned char hex) {
395*76404edcSAsim Jamshed 	hex = hex - '0';
396*76404edcSAsim Jamshed 	if (hex > 9) {
397*76404edcSAsim Jamshed 		hex = (hex + '0' - 1) | 0x20;
398*76404edcSAsim Jamshed 		hex = hex - 'a' + 11;
399*76404edcSAsim Jamshed 	}
400*76404edcSAsim Jamshed 	if (hex > 15)
401*76404edcSAsim Jamshed 		hex = 0xFF;
402*76404edcSAsim Jamshed 
403*76404edcSAsim Jamshed 	return hex;
404*76404edcSAsim Jamshed }
405*76404edcSAsim Jamshed 
406*76404edcSAsim Jamshed 
407*76404edcSAsim Jamshed /**
408*76404edcSAsim Jamshed  * init the buffer
409*76404edcSAsim Jamshed  *
410*76404edcSAsim Jamshed  */
411*76404edcSAsim Jamshed 
buffer_array_init(void)412*76404edcSAsim Jamshed buffer_array* buffer_array_init(void) {
413*76404edcSAsim Jamshed 	buffer_array *b;
414*76404edcSAsim Jamshed 
415*76404edcSAsim Jamshed 	b = malloc(sizeof(*b));
416*76404edcSAsim Jamshed 
417*76404edcSAsim Jamshed 	assert(b);
418*76404edcSAsim Jamshed 	b->ptr = NULL;
419*76404edcSAsim Jamshed 	b->size = 0;
420*76404edcSAsim Jamshed 	b->used = 0;
421*76404edcSAsim Jamshed 
422*76404edcSAsim Jamshed 	return b;
423*76404edcSAsim Jamshed }
424*76404edcSAsim Jamshed 
buffer_array_reset(buffer_array * b)425*76404edcSAsim Jamshed void buffer_array_reset(buffer_array *b) {
426*76404edcSAsim Jamshed 	size_t i;
427*76404edcSAsim Jamshed 
428*76404edcSAsim Jamshed 	if (!b) return;
429*76404edcSAsim Jamshed 
430*76404edcSAsim Jamshed 	/* if they are too large, reduce them */
431*76404edcSAsim Jamshed 	for (i = 0; i < b->used; i++) {
432*76404edcSAsim Jamshed 		buffer_reset(b->ptr[i]);
433*76404edcSAsim Jamshed 	}
434*76404edcSAsim Jamshed 
435*76404edcSAsim Jamshed 	b->used = 0;
436*76404edcSAsim Jamshed }
437*76404edcSAsim Jamshed 
438*76404edcSAsim Jamshed 
439*76404edcSAsim Jamshed /**
440*76404edcSAsim Jamshed  * free the buffer_array
441*76404edcSAsim Jamshed  *
442*76404edcSAsim Jamshed  */
443*76404edcSAsim Jamshed 
buffer_array_free(buffer_array * b)444*76404edcSAsim Jamshed void buffer_array_free(buffer_array *b) {
445*76404edcSAsim Jamshed 	size_t i;
446*76404edcSAsim Jamshed 	if (!b) return;
447*76404edcSAsim Jamshed 
448*76404edcSAsim Jamshed 	for (i = 0; i < b->size; i++) {
449*76404edcSAsim Jamshed 		if (b->ptr[i]) buffer_free(b->ptr[i]);
450*76404edcSAsim Jamshed 	}
451*76404edcSAsim Jamshed 	free(b->ptr);
452*76404edcSAsim Jamshed 	free(b);
453*76404edcSAsim Jamshed }
454*76404edcSAsim Jamshed 
buffer_array_append_get_buffer(buffer_array * b)455*76404edcSAsim Jamshed buffer *buffer_array_append_get_buffer(buffer_array *b) {
456*76404edcSAsim Jamshed 	size_t i;
457*76404edcSAsim Jamshed 
458*76404edcSAsim Jamshed 	if (b->size == 0) {
459*76404edcSAsim Jamshed 		b->size = 16;
460*76404edcSAsim Jamshed 		b->ptr = malloc(sizeof(*b->ptr) * b->size);
461*76404edcSAsim Jamshed 		assert(b->ptr);
462*76404edcSAsim Jamshed 		for (i = 0; i < b->size; i++) {
463*76404edcSAsim Jamshed 			b->ptr[i] = NULL;
464*76404edcSAsim Jamshed 		}
465*76404edcSAsim Jamshed 	} else if (b->size == b->used) {
466*76404edcSAsim Jamshed 		b->size += 16;
467*76404edcSAsim Jamshed 		b->ptr = realloc(b->ptr, sizeof(*b->ptr) * b->size);
468*76404edcSAsim Jamshed 		assert(b->ptr);
469*76404edcSAsim Jamshed 		for (i = b->used; i < b->size; i++) {
470*76404edcSAsim Jamshed 			b->ptr[i] = NULL;
471*76404edcSAsim Jamshed 		}
472*76404edcSAsim Jamshed 	}
473*76404edcSAsim Jamshed 
474*76404edcSAsim Jamshed 	if (b->ptr[b->used] == NULL) {
475*76404edcSAsim Jamshed 		b->ptr[b->used] = buffer_init();
476*76404edcSAsim Jamshed 	}
477*76404edcSAsim Jamshed 
478*76404edcSAsim Jamshed 	b->ptr[b->used]->used = 0;
479*76404edcSAsim Jamshed 
480*76404edcSAsim Jamshed 	return b->ptr[b->used++];
481*76404edcSAsim Jamshed }
482*76404edcSAsim Jamshed 
483*76404edcSAsim Jamshed 
buffer_search_string_len(buffer * b,const char * needle,size_t len)484*76404edcSAsim Jamshed char * buffer_search_string_len(buffer *b, const char *needle, size_t len) {
485*76404edcSAsim Jamshed 	size_t i;
486*76404edcSAsim Jamshed 	if (len == 0) return NULL;
487*76404edcSAsim Jamshed 	if (needle == NULL) return NULL;
488*76404edcSAsim Jamshed 
489*76404edcSAsim Jamshed 	if (b->used < len) return NULL;
490*76404edcSAsim Jamshed 
491*76404edcSAsim Jamshed 	for(i = 0; i < b->used - len; i++) {
492*76404edcSAsim Jamshed 		if (0 == memcmp(b->ptr + i, needle, len)) {
493*76404edcSAsim Jamshed 			return b->ptr + i;
494*76404edcSAsim Jamshed 		}
495*76404edcSAsim Jamshed 	}
496*76404edcSAsim Jamshed 
497*76404edcSAsim Jamshed 	return NULL;
498*76404edcSAsim Jamshed }
499*76404edcSAsim Jamshed 
buffer_init_string(const char * str)500*76404edcSAsim Jamshed buffer *buffer_init_string(const char *str) {
501*76404edcSAsim Jamshed 	buffer *b = buffer_init();
502*76404edcSAsim Jamshed 
503*76404edcSAsim Jamshed 	buffer_copy_string(b, str);
504*76404edcSAsim Jamshed 
505*76404edcSAsim Jamshed 	return b;
506*76404edcSAsim Jamshed }
507*76404edcSAsim Jamshed 
buffer_is_empty(buffer * b)508*76404edcSAsim Jamshed int buffer_is_empty(buffer *b) {
509*76404edcSAsim Jamshed 	if (!b) return 1;
510*76404edcSAsim Jamshed 	return (b->used == 0);
511*76404edcSAsim Jamshed }
512*76404edcSAsim Jamshed 
513*76404edcSAsim Jamshed /**
514*76404edcSAsim Jamshed  * check if two buffer contain the same data
515*76404edcSAsim Jamshed  *
516*76404edcSAsim Jamshed  * HISTORY: this function was pretty much optimized, but didn't handled
517*76404edcSAsim Jamshed  * alignment properly.
518*76404edcSAsim Jamshed  */
519*76404edcSAsim Jamshed 
buffer_is_equal(buffer * a,buffer * b)520*76404edcSAsim Jamshed int buffer_is_equal(buffer *a, buffer *b) {
521*76404edcSAsim Jamshed 	if (a->used != b->used) return 0;
522*76404edcSAsim Jamshed 	if (a->used == 0) return 1;
523*76404edcSAsim Jamshed 
524*76404edcSAsim Jamshed 	return (0 == strcmp(a->ptr, b->ptr));
525*76404edcSAsim Jamshed }
526*76404edcSAsim Jamshed 
buffer_is_equal_string(buffer * a,const char * s,size_t b_len)527*76404edcSAsim Jamshed int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
528*76404edcSAsim Jamshed 	buffer b;
529*76404edcSAsim Jamshed 
530*76404edcSAsim Jamshed 	b.ptr = (char *)s;
531*76404edcSAsim Jamshed 	b.used = b_len + 1;
532*76404edcSAsim Jamshed 
533*76404edcSAsim Jamshed 	return buffer_is_equal(a, &b);
534*76404edcSAsim Jamshed }
535*76404edcSAsim Jamshed 
536*76404edcSAsim Jamshed /* simple-assumption:
537*76404edcSAsim Jamshed  *
538*76404edcSAsim Jamshed  * most parts are equal and doing a case conversion needs time
539*76404edcSAsim Jamshed  *
540*76404edcSAsim Jamshed  */
buffer_caseless_compare(const char * a,size_t a_len,const char * b,size_t b_len)541*76404edcSAsim Jamshed int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
542*76404edcSAsim Jamshed 	size_t ndx = 0, max_ndx;
543*76404edcSAsim Jamshed 	size_t *al, *bl;
544*76404edcSAsim Jamshed 	size_t mask = sizeof(*al) - 1;
545*76404edcSAsim Jamshed 
546*76404edcSAsim Jamshed 	al = (size_t *)a;
547*76404edcSAsim Jamshed 	bl = (size_t *)b;
548*76404edcSAsim Jamshed 
549*76404edcSAsim Jamshed 	/* is the alignment correct ? */
550*76404edcSAsim Jamshed 	if ( ((size_t)al & mask) == 0 &&
551*76404edcSAsim Jamshed 	     ((size_t)bl & mask) == 0 ) {
552*76404edcSAsim Jamshed 
553*76404edcSAsim Jamshed 		max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
554*76404edcSAsim Jamshed 
555*76404edcSAsim Jamshed 		for (; ndx < max_ndx; ndx += sizeof(*al)) {
556*76404edcSAsim Jamshed 			if (*al != *bl) break;
557*76404edcSAsim Jamshed 			al++; bl++;
558*76404edcSAsim Jamshed 
559*76404edcSAsim Jamshed 		}
560*76404edcSAsim Jamshed 
561*76404edcSAsim Jamshed 	}
562*76404edcSAsim Jamshed 
563*76404edcSAsim Jamshed 	a = (char *)al;
564*76404edcSAsim Jamshed 	b = (char *)bl;
565*76404edcSAsim Jamshed 
566*76404edcSAsim Jamshed 	max_ndx = ((a_len < b_len) ? a_len : b_len);
567*76404edcSAsim Jamshed 
568*76404edcSAsim Jamshed 	for (; ndx < max_ndx; ndx++) {
569*76404edcSAsim Jamshed 		int a1 = *a++, b1 = *b++;
570*76404edcSAsim Jamshed 
571*76404edcSAsim Jamshed 		if (a1 != b1) {
572*76404edcSAsim Jamshed 			/* always lowercase for transitive results */
573*76404edcSAsim Jamshed 			if (a1 >= 'A' && a1 <= 'Z') a1 |= 32;
574*76404edcSAsim Jamshed 			if (b1 >= 'A' && b1 <= 'Z') b1 |= 32;
575*76404edcSAsim Jamshed 
576*76404edcSAsim Jamshed 			if ((a1 - b1) != 0) return (a1 - b1);
577*76404edcSAsim Jamshed 		}
578*76404edcSAsim Jamshed 	}
579*76404edcSAsim Jamshed 
580*76404edcSAsim Jamshed 	/* all chars are the same, and the length match too
581*76404edcSAsim Jamshed 	 *
582*76404edcSAsim Jamshed 	 * they are the same */
583*76404edcSAsim Jamshed 	if (a_len == b_len) return 0;
584*76404edcSAsim Jamshed 
585*76404edcSAsim Jamshed 	/* if a is shorter then b, then b is larger */
586*76404edcSAsim Jamshed 	return (a_len - b_len);
587*76404edcSAsim Jamshed }
588*76404edcSAsim Jamshed 
589*76404edcSAsim Jamshed 
590*76404edcSAsim Jamshed /**
591*76404edcSAsim Jamshed  * check if the rightmost bytes of the string are equal.
592*76404edcSAsim Jamshed  *
593*76404edcSAsim Jamshed  *
594*76404edcSAsim Jamshed  */
595*76404edcSAsim Jamshed 
buffer_is_equal_right_len(buffer * b1,buffer * b2,size_t len)596*76404edcSAsim Jamshed int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
597*76404edcSAsim Jamshed 	/* no, len -> equal */
598*76404edcSAsim Jamshed 	if (len == 0) return 1;
599*76404edcSAsim Jamshed 
600*76404edcSAsim Jamshed 	/* len > 0, but empty buffers -> not equal */
601*76404edcSAsim Jamshed 	if (b1->used == 0 || b2->used == 0) return 0;
602*76404edcSAsim Jamshed 
603*76404edcSAsim Jamshed 	/* buffers too small -> not equal */
604*76404edcSAsim Jamshed 	if (b1->used - 1 < len || b1->used - 1 < len) return 0;
605*76404edcSAsim Jamshed 
606*76404edcSAsim Jamshed 	if (0 == strncmp(b1->ptr + b1->used - 1 - len,
607*76404edcSAsim Jamshed 			 b2->ptr + b2->used - 1 - len, len)) {
608*76404edcSAsim Jamshed 		return 1;
609*76404edcSAsim Jamshed 	}
610*76404edcSAsim Jamshed 
611*76404edcSAsim Jamshed 	return 0;
612*76404edcSAsim Jamshed }
613*76404edcSAsim Jamshed 
buffer_copy_string_hex(buffer * b,const char * in,size_t in_len)614*76404edcSAsim Jamshed int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
615*76404edcSAsim Jamshed 	size_t i;
616*76404edcSAsim Jamshed 
617*76404edcSAsim Jamshed 	/* BO protection */
618*76404edcSAsim Jamshed 	if (in_len * 2 < in_len) return -1;
619*76404edcSAsim Jamshed 
620*76404edcSAsim Jamshed 	buffer_prepare_copy(b, in_len * 2 + 1);
621*76404edcSAsim Jamshed 
622*76404edcSAsim Jamshed 	for (i = 0; i < in_len; i++) {
623*76404edcSAsim Jamshed 		b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
624*76404edcSAsim Jamshed 		b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
625*76404edcSAsim Jamshed 	}
626*76404edcSAsim Jamshed 	b->ptr[b->used++] = '\0';
627*76404edcSAsim Jamshed 
628*76404edcSAsim Jamshed 	return 0;
629*76404edcSAsim Jamshed }
630*76404edcSAsim Jamshed 
631*76404edcSAsim Jamshed /* everything except: ! ( ) * - . 0-9 A-Z _ a-z */
632*76404edcSAsim Jamshed static const char encoded_chars_rel_uri_part[] = {
633*76404edcSAsim Jamshed 	/*
634*76404edcSAsim Jamshed 	0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
635*76404edcSAsim Jamshed 	*/
636*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
637*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
638*76404edcSAsim Jamshed 	1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,  /*  20 -  2F space " # $ % & ' + , / */
639*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; < = > ? */
640*76404edcSAsim Jamshed 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F @ */
641*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,  /*  50 -  5F [ \ ] ^ */
642*76404edcSAsim Jamshed 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  60 -  6F ` */
643*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,  /*  70 -  7F { | } ~ DEL */
644*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
645*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
646*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  A0 -  AF */
647*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  B0 -  BF */
648*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  C0 -  CF */
649*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  D0 -  DF */
650*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  E0 -  EF */
651*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  F0 -  FF */
652*76404edcSAsim Jamshed };
653*76404edcSAsim Jamshed 
654*76404edcSAsim Jamshed /* everything except: ! ( ) * - . / 0-9 A-Z _ a-z */
655*76404edcSAsim Jamshed static const char encoded_chars_rel_uri[] = {
656*76404edcSAsim Jamshed 	/*
657*76404edcSAsim Jamshed 	0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
658*76404edcSAsim Jamshed 	*/
659*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
660*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
661*76404edcSAsim Jamshed 	1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,  /*  20 -  2F space " # $ % & ' + , */
662*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; < = > ? */
663*76404edcSAsim Jamshed 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F @ */
664*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,  /*  50 -  5F [ \ ] ^ */
665*76404edcSAsim Jamshed 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  60 -  6F ` */
666*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,  /*  70 -  7F { | } ~ DEL */
667*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
668*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
669*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  A0 -  AF */
670*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  B0 -  BF */
671*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  C0 -  CF */
672*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  D0 -  DF */
673*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  E0 -  EF */
674*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  F0 -  FF */
675*76404edcSAsim Jamshed };
676*76404edcSAsim Jamshed 
677*76404edcSAsim Jamshed static const char encoded_chars_html[] = {
678*76404edcSAsim Jamshed 	/*
679*76404edcSAsim Jamshed 	0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
680*76404edcSAsim Jamshed 	*/
681*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
682*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
683*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
684*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
685*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
686*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  50 -  5F */
687*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  60 -  6F */
688*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,  /*  70 -  7F DEL */
689*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
690*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
691*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  A0 -  AF */
692*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  B0 -  BF */
693*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  C0 -  CF */
694*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  D0 -  DF */
695*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  E0 -  EF */
696*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  F0 -  FF */
697*76404edcSAsim Jamshed };
698*76404edcSAsim Jamshed 
699*76404edcSAsim Jamshed static const char encoded_chars_minimal_xml[] = {
700*76404edcSAsim Jamshed 	/*
701*76404edcSAsim Jamshed 	0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
702*76404edcSAsim Jamshed 	*/
703*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
704*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
705*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
706*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
707*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
708*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  50 -  5F */
709*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  60 -  6F */
710*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,  /*  70 -  7F DEL */
711*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  80 -  8F */
712*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  90 -  9F */
713*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  A0 -  AF */
714*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  B0 -  BF */
715*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  C0 -  CF */
716*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  D0 -  DF */
717*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  E0 -  EF */
718*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  F0 -  FF */
719*76404edcSAsim Jamshed };
720*76404edcSAsim Jamshed 
721*76404edcSAsim Jamshed static const char encoded_chars_hex[] = {
722*76404edcSAsim Jamshed 	/*
723*76404edcSAsim Jamshed 	0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
724*76404edcSAsim Jamshed 	*/
725*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
726*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
727*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */
728*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */
729*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */
730*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */
731*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */
732*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  70 -  7F */
733*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
734*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
735*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  A0 -  AF */
736*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  B0 -  BF */
737*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  C0 -  CF */
738*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  D0 -  DF */
739*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  E0 -  EF */
740*76404edcSAsim Jamshed 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  F0 -  FF */
741*76404edcSAsim Jamshed };
742*76404edcSAsim Jamshed 
743*76404edcSAsim Jamshed static const char encoded_chars_http_header[] = {
744*76404edcSAsim Jamshed 	/*
745*76404edcSAsim Jamshed 	0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
746*76404edcSAsim Jamshed 	*/
747*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,  /*  00 -  0F */
748*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  10 -  1F */
749*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F */
750*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  30 -  3F */
751*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
752*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  50 -  5F */
753*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  60 -  6F */
754*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  70 -  7F */
755*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  80 -  8F */
756*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  90 -  9F */
757*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  A0 -  AF */
758*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  B0 -  BF */
759*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  C0 -  CF */
760*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  D0 -  DF */
761*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  E0 -  EF */
762*76404edcSAsim Jamshed 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  F0 -  FF */
763*76404edcSAsim Jamshed };
764*76404edcSAsim Jamshed 
765*76404edcSAsim Jamshed 
766*76404edcSAsim Jamshed 
buffer_append_string_encoded(buffer * b,const char * s,size_t s_len,buffer_encoding_t encoding)767*76404edcSAsim Jamshed int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_encoding_t encoding) {
768*76404edcSAsim Jamshed 	unsigned char *ds, *d;
769*76404edcSAsim Jamshed 	size_t d_len, ndx;
770*76404edcSAsim Jamshed 	const char *map = NULL;
771*76404edcSAsim Jamshed 
772*76404edcSAsim Jamshed 	if (!s || !b) return -1;
773*76404edcSAsim Jamshed 
774*76404edcSAsim Jamshed 	if (b->ptr[b->used - 1] != '\0') {
775*76404edcSAsim Jamshed 		SEGFAULT();
776*76404edcSAsim Jamshed 	}
777*76404edcSAsim Jamshed 
778*76404edcSAsim Jamshed 	if (s_len == 0) return 0;
779*76404edcSAsim Jamshed 
780*76404edcSAsim Jamshed 	switch(encoding) {
781*76404edcSAsim Jamshed 	case ENCODING_REL_URI:
782*76404edcSAsim Jamshed 		map = encoded_chars_rel_uri;
783*76404edcSAsim Jamshed 		break;
784*76404edcSAsim Jamshed 	case ENCODING_REL_URI_PART:
785*76404edcSAsim Jamshed 		map = encoded_chars_rel_uri_part;
786*76404edcSAsim Jamshed 		break;
787*76404edcSAsim Jamshed 	case ENCODING_HTML:
788*76404edcSAsim Jamshed 		map = encoded_chars_html;
789*76404edcSAsim Jamshed 		break;
790*76404edcSAsim Jamshed 	case ENCODING_MINIMAL_XML:
791*76404edcSAsim Jamshed 		map = encoded_chars_minimal_xml;
792*76404edcSAsim Jamshed 		break;
793*76404edcSAsim Jamshed 	case ENCODING_HEX:
794*76404edcSAsim Jamshed 		map = encoded_chars_hex;
795*76404edcSAsim Jamshed 		break;
796*76404edcSAsim Jamshed 	case ENCODING_HTTP_HEADER:
797*76404edcSAsim Jamshed 		map = encoded_chars_http_header;
798*76404edcSAsim Jamshed 		break;
799*76404edcSAsim Jamshed 	case ENCODING_UNSET:
800*76404edcSAsim Jamshed 		break;
801*76404edcSAsim Jamshed 	}
802*76404edcSAsim Jamshed 
803*76404edcSAsim Jamshed 	assert(map != NULL);
804*76404edcSAsim Jamshed 
805*76404edcSAsim Jamshed 	/* count to-be-encoded-characters */
806*76404edcSAsim Jamshed 	for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
807*76404edcSAsim Jamshed 		if (map[*ds]) {
808*76404edcSAsim Jamshed 			switch(encoding) {
809*76404edcSAsim Jamshed 			case ENCODING_REL_URI:
810*76404edcSAsim Jamshed 			case ENCODING_REL_URI_PART:
811*76404edcSAsim Jamshed 				d_len += 3;
812*76404edcSAsim Jamshed 				break;
813*76404edcSAsim Jamshed 			case ENCODING_HTML:
814*76404edcSAsim Jamshed 			case ENCODING_MINIMAL_XML:
815*76404edcSAsim Jamshed 				d_len += 6;
816*76404edcSAsim Jamshed 				break;
817*76404edcSAsim Jamshed 			case ENCODING_HTTP_HEADER:
818*76404edcSAsim Jamshed 			case ENCODING_HEX:
819*76404edcSAsim Jamshed 				d_len += 2;
820*76404edcSAsim Jamshed 				break;
821*76404edcSAsim Jamshed 			case ENCODING_UNSET:
822*76404edcSAsim Jamshed 				break;
823*76404edcSAsim Jamshed 			}
824*76404edcSAsim Jamshed 		} else {
825*76404edcSAsim Jamshed 			d_len ++;
826*76404edcSAsim Jamshed 		}
827*76404edcSAsim Jamshed 	}
828*76404edcSAsim Jamshed 
829*76404edcSAsim Jamshed 	buffer_prepare_append(b, d_len);
830*76404edcSAsim Jamshed 
831*76404edcSAsim Jamshed 	for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
832*76404edcSAsim Jamshed 		if (map[*ds]) {
833*76404edcSAsim Jamshed 			switch(encoding) {
834*76404edcSAsim Jamshed 			case ENCODING_REL_URI:
835*76404edcSAsim Jamshed 			case ENCODING_REL_URI_PART:
836*76404edcSAsim Jamshed 				d[d_len++] = '%';
837*76404edcSAsim Jamshed 				d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
838*76404edcSAsim Jamshed 				d[d_len++] = hex_chars[(*ds) & 0x0F];
839*76404edcSAsim Jamshed 				break;
840*76404edcSAsim Jamshed 			case ENCODING_HTML:
841*76404edcSAsim Jamshed 			case ENCODING_MINIMAL_XML:
842*76404edcSAsim Jamshed 				d[d_len++] = '&';
843*76404edcSAsim Jamshed 				d[d_len++] = '#';
844*76404edcSAsim Jamshed 				d[d_len++] = 'x';
845*76404edcSAsim Jamshed 				d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
846*76404edcSAsim Jamshed 				d[d_len++] = hex_chars[(*ds) & 0x0F];
847*76404edcSAsim Jamshed 				d[d_len++] = ';';
848*76404edcSAsim Jamshed 				break;
849*76404edcSAsim Jamshed 			case ENCODING_HEX:
850*76404edcSAsim Jamshed 				d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
851*76404edcSAsim Jamshed 				d[d_len++] = hex_chars[(*ds) & 0x0F];
852*76404edcSAsim Jamshed 				break;
853*76404edcSAsim Jamshed 			case ENCODING_HTTP_HEADER:
854*76404edcSAsim Jamshed 				d[d_len++] = *ds;
855*76404edcSAsim Jamshed 				d[d_len++] = '\t';
856*76404edcSAsim Jamshed 				break;
857*76404edcSAsim Jamshed 			case ENCODING_UNSET:
858*76404edcSAsim Jamshed 				break;
859*76404edcSAsim Jamshed 			}
860*76404edcSAsim Jamshed 		} else {
861*76404edcSAsim Jamshed 			d[d_len++] = *ds;
862*76404edcSAsim Jamshed 		}
863*76404edcSAsim Jamshed 	}
864*76404edcSAsim Jamshed 
865*76404edcSAsim Jamshed 	/* terminate buffer and calculate new length */
866*76404edcSAsim Jamshed 	b->ptr[b->used + d_len - 1] = '\0';
867*76404edcSAsim Jamshed 
868*76404edcSAsim Jamshed 	b->used += d_len;
869*76404edcSAsim Jamshed 
870*76404edcSAsim Jamshed 	return 0;
871*76404edcSAsim Jamshed }
872*76404edcSAsim Jamshed 
873*76404edcSAsim Jamshed 
874*76404edcSAsim Jamshed /* decodes url-special-chars inplace.
875*76404edcSAsim Jamshed  * replaces non-printable characters with '_'
876*76404edcSAsim Jamshed  */
877*76404edcSAsim Jamshed 
buffer_urldecode_internal(buffer * url,int is_query)878*76404edcSAsim Jamshed static int buffer_urldecode_internal(buffer *url, int is_query) {
879*76404edcSAsim Jamshed 	unsigned char high, low;
880*76404edcSAsim Jamshed 	const char *src;
881*76404edcSAsim Jamshed 	char *dst;
882*76404edcSAsim Jamshed 
883*76404edcSAsim Jamshed 	if (!url || !url->ptr) return -1;
884*76404edcSAsim Jamshed 
885*76404edcSAsim Jamshed 	src = (const char*) url->ptr;
886*76404edcSAsim Jamshed 	dst = (char*) url->ptr;
887*76404edcSAsim Jamshed 
888*76404edcSAsim Jamshed 	while ((*src) != '\0') {
889*76404edcSAsim Jamshed 		if (is_query && *src == '+') {
890*76404edcSAsim Jamshed 			*dst = ' ';
891*76404edcSAsim Jamshed 		} else if (*src == '%') {
892*76404edcSAsim Jamshed 			*dst = '%';
893*76404edcSAsim Jamshed 
894*76404edcSAsim Jamshed 			high = hex2int(*(src + 1));
895*76404edcSAsim Jamshed 			if (high != 0xFF) {
896*76404edcSAsim Jamshed 				low = hex2int(*(src + 2));
897*76404edcSAsim Jamshed 				if (low != 0xFF) {
898*76404edcSAsim Jamshed 					high = (high << 4) | low;
899*76404edcSAsim Jamshed 
900*76404edcSAsim Jamshed 					/* map control-characters out */
901*76404edcSAsim Jamshed 					if (high < 32 || high == 127) high = '_';
902*76404edcSAsim Jamshed 
903*76404edcSAsim Jamshed 					*dst = high;
904*76404edcSAsim Jamshed 					src += 2;
905*76404edcSAsim Jamshed 				}
906*76404edcSAsim Jamshed 			}
907*76404edcSAsim Jamshed 		} else {
908*76404edcSAsim Jamshed 			*dst = *src;
909*76404edcSAsim Jamshed 		}
910*76404edcSAsim Jamshed 
911*76404edcSAsim Jamshed 		dst++;
912*76404edcSAsim Jamshed 		src++;
913*76404edcSAsim Jamshed 	}
914*76404edcSAsim Jamshed 
915*76404edcSAsim Jamshed 	*dst = '\0';
916*76404edcSAsim Jamshed 	url->used = (dst - url->ptr) + 1;
917*76404edcSAsim Jamshed 
918*76404edcSAsim Jamshed 	return 0;
919*76404edcSAsim Jamshed }
920*76404edcSAsim Jamshed 
buffer_urldecode_path(buffer * url)921*76404edcSAsim Jamshed int buffer_urldecode_path(buffer *url) {
922*76404edcSAsim Jamshed 	return buffer_urldecode_internal(url, 0);
923*76404edcSAsim Jamshed }
924*76404edcSAsim Jamshed 
buffer_urldecode_query(buffer * url)925*76404edcSAsim Jamshed int buffer_urldecode_query(buffer *url) {
926*76404edcSAsim Jamshed 	return buffer_urldecode_internal(url, 1);
927*76404edcSAsim Jamshed }
928*76404edcSAsim Jamshed 
929*76404edcSAsim Jamshed /* Remove "/../", "//", "/./" parts from path.
930*76404edcSAsim Jamshed  *
931*76404edcSAsim Jamshed  * /blah/..         gets  /
932*76404edcSAsim Jamshed  * /blah/../foo     gets  /foo
933*76404edcSAsim Jamshed  * /abc/./xyz       gets  /abc/xyz
934*76404edcSAsim Jamshed  * /abc//xyz        gets  /abc/xyz
935*76404edcSAsim Jamshed  *
936*76404edcSAsim Jamshed  * NOTE: src and dest can point to the same buffer, in which case,
937*76404edcSAsim Jamshed  *       the operation is performed in-place.
938*76404edcSAsim Jamshed  */
939*76404edcSAsim Jamshed 
buffer_path_simplify(buffer * dest,buffer * src)940*76404edcSAsim Jamshed int buffer_path_simplify(buffer *dest, buffer *src)
941*76404edcSAsim Jamshed {
942*76404edcSAsim Jamshed 	int toklen;
943*76404edcSAsim Jamshed 	char c, pre1;
944*76404edcSAsim Jamshed 	char *start, *slash, *walk, *out;
945*76404edcSAsim Jamshed 	unsigned short pre;
946*76404edcSAsim Jamshed 
947*76404edcSAsim Jamshed 	if (src == NULL || src->ptr == NULL || dest == NULL)
948*76404edcSAsim Jamshed 		return -1;
949*76404edcSAsim Jamshed 
950*76404edcSAsim Jamshed 	if (src == dest)
951*76404edcSAsim Jamshed 		buffer_prepare_append(dest, 1);
952*76404edcSAsim Jamshed 	else
953*76404edcSAsim Jamshed 		buffer_prepare_copy(dest, src->used + 1);
954*76404edcSAsim Jamshed 
955*76404edcSAsim Jamshed 	walk  = src->ptr;
956*76404edcSAsim Jamshed 	start = dest->ptr;
957*76404edcSAsim Jamshed 	out   = dest->ptr;
958*76404edcSAsim Jamshed 	slash = dest->ptr;
959*76404edcSAsim Jamshed 
960*76404edcSAsim Jamshed 
961*76404edcSAsim Jamshed #if defined(__WIN32) || defined(__CYGWIN__)
962*76404edcSAsim Jamshed 	/* cygwin is treating \ and / the same, so we have to that too
963*76404edcSAsim Jamshed 	 */
964*76404edcSAsim Jamshed 
965*76404edcSAsim Jamshed 	for (walk = src->ptr; *walk; walk++) {
966*76404edcSAsim Jamshed 		if (*walk == '\\') *walk = '/';
967*76404edcSAsim Jamshed 	}
968*76404edcSAsim Jamshed 	walk = src->ptr;
969*76404edcSAsim Jamshed #endif
970*76404edcSAsim Jamshed 
971*76404edcSAsim Jamshed 	while (*walk == ' ') {
972*76404edcSAsim Jamshed 		walk++;
973*76404edcSAsim Jamshed 	}
974*76404edcSAsim Jamshed 
975*76404edcSAsim Jamshed 	pre1 = *(walk++);
976*76404edcSAsim Jamshed 	c    = *(walk++);
977*76404edcSAsim Jamshed 	pre  = pre1;
978*76404edcSAsim Jamshed 	if (pre1 != '/') {
979*76404edcSAsim Jamshed 		pre = ('/' << 8) | pre1;
980*76404edcSAsim Jamshed 		*(out++) = '/';
981*76404edcSAsim Jamshed 	}
982*76404edcSAsim Jamshed 	*(out++) = pre1;
983*76404edcSAsim Jamshed 
984*76404edcSAsim Jamshed 	if (pre1 == '\0') {
985*76404edcSAsim Jamshed 		dest->used = (out - start) + 1;
986*76404edcSAsim Jamshed 		return 0;
987*76404edcSAsim Jamshed 	}
988*76404edcSAsim Jamshed 
989*76404edcSAsim Jamshed 	while (1) {
990*76404edcSAsim Jamshed 		if (c == '/' || c == '\0') {
991*76404edcSAsim Jamshed 			toklen = out - slash;
992*76404edcSAsim Jamshed 			if (toklen == 3 && pre == (('.' << 8) | '.')) {
993*76404edcSAsim Jamshed 				out = slash;
994*76404edcSAsim Jamshed 				if (out > start) {
995*76404edcSAsim Jamshed 					out--;
996*76404edcSAsim Jamshed 					while (out > start && *out != '/') {
997*76404edcSAsim Jamshed 						out--;
998*76404edcSAsim Jamshed 					}
999*76404edcSAsim Jamshed 				}
1000*76404edcSAsim Jamshed 
1001*76404edcSAsim Jamshed 				if (c == '\0')
1002*76404edcSAsim Jamshed 					out++;
1003*76404edcSAsim Jamshed 			} else if (toklen == 1 || pre == (('/' << 8) | '.')) {
1004*76404edcSAsim Jamshed 				out = slash;
1005*76404edcSAsim Jamshed 				if (c == '\0')
1006*76404edcSAsim Jamshed 					out++;
1007*76404edcSAsim Jamshed 			}
1008*76404edcSAsim Jamshed 
1009*76404edcSAsim Jamshed 			slash = out;
1010*76404edcSAsim Jamshed 		}
1011*76404edcSAsim Jamshed 
1012*76404edcSAsim Jamshed 		if (c == '\0')
1013*76404edcSAsim Jamshed 			break;
1014*76404edcSAsim Jamshed 
1015*76404edcSAsim Jamshed 		pre1 = c;
1016*76404edcSAsim Jamshed 		pre  = (pre << 8) | pre1;
1017*76404edcSAsim Jamshed 		c    = *walk;
1018*76404edcSAsim Jamshed 		*out = pre1;
1019*76404edcSAsim Jamshed 
1020*76404edcSAsim Jamshed 		out++;
1021*76404edcSAsim Jamshed 		walk++;
1022*76404edcSAsim Jamshed 	}
1023*76404edcSAsim Jamshed 
1024*76404edcSAsim Jamshed 	*out = '\0';
1025*76404edcSAsim Jamshed 	dest->used = (out - start) + 1;
1026*76404edcSAsim Jamshed 
1027*76404edcSAsim Jamshed 	return 0;
1028*76404edcSAsim Jamshed }
1029*76404edcSAsim Jamshed 
light_isdigit(int c)1030*76404edcSAsim Jamshed int light_isdigit(int c) {
1031*76404edcSAsim Jamshed 	return (c >= '0' && c <= '9');
1032*76404edcSAsim Jamshed }
1033*76404edcSAsim Jamshed 
light_isxdigit(int c)1034*76404edcSAsim Jamshed int light_isxdigit(int c) {
1035*76404edcSAsim Jamshed 	if (light_isdigit(c)) return 1;
1036*76404edcSAsim Jamshed 
1037*76404edcSAsim Jamshed 	c |= 32;
1038*76404edcSAsim Jamshed 	return (c >= 'a' && c <= 'f');
1039*76404edcSAsim Jamshed }
1040*76404edcSAsim Jamshed 
light_isalpha(int c)1041*76404edcSAsim Jamshed int light_isalpha(int c) {
1042*76404edcSAsim Jamshed 	c |= 32;
1043*76404edcSAsim Jamshed 	return (c >= 'a' && c <= 'z');
1044*76404edcSAsim Jamshed }
1045*76404edcSAsim Jamshed 
light_isalnum(int c)1046*76404edcSAsim Jamshed int light_isalnum(int c) {
1047*76404edcSAsim Jamshed 	return light_isdigit(c) || light_isalpha(c);
1048*76404edcSAsim Jamshed }
1049*76404edcSAsim Jamshed 
buffer_to_lower(buffer * b)1050*76404edcSAsim Jamshed int buffer_to_lower(buffer *b) {
1051*76404edcSAsim Jamshed 	char *c;
1052*76404edcSAsim Jamshed 
1053*76404edcSAsim Jamshed 	if (b->used == 0) return 0;
1054*76404edcSAsim Jamshed 
1055*76404edcSAsim Jamshed 	for (c = b->ptr; *c; c++) {
1056*76404edcSAsim Jamshed 		if (*c >= 'A' && *c <= 'Z') {
1057*76404edcSAsim Jamshed 			*c |= 32;
1058*76404edcSAsim Jamshed 		}
1059*76404edcSAsim Jamshed 	}
1060*76404edcSAsim Jamshed 
1061*76404edcSAsim Jamshed 	return 0;
1062*76404edcSAsim Jamshed }
1063*76404edcSAsim Jamshed 
1064*76404edcSAsim Jamshed 
buffer_to_upper(buffer * b)1065*76404edcSAsim Jamshed int buffer_to_upper(buffer *b) {
1066*76404edcSAsim Jamshed 	char *c;
1067*76404edcSAsim Jamshed 
1068*76404edcSAsim Jamshed 	if (b->used == 0) return 0;
1069*76404edcSAsim Jamshed 
1070*76404edcSAsim Jamshed 	for (c = b->ptr; *c; c++) {
1071*76404edcSAsim Jamshed 		if (*c >= 'a' && *c <= 'z') {
1072*76404edcSAsim Jamshed 			*c &= ~32;
1073*76404edcSAsim Jamshed 		}
1074*76404edcSAsim Jamshed 	}
1075*76404edcSAsim Jamshed 
1076*76404edcSAsim Jamshed 	return 0;
1077*76404edcSAsim Jamshed }
1078