diff options
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 1169 |
1 files changed, 0 insertions, 1169 deletions
diff --git a/src/buffer.c b/src/buffer.c deleted file mode 100644 index 7354bda5..00000000 --- a/src/buffer.c +++ /dev/null @@ -1,1169 +0,0 @@ -#include <stdlib.h> -#include <string.h> - -#include <stdio.h> -#include <assert.h> -#include <ctype.h> - -#include "buffer.h" - - -static const char hex_chars[] = "0123456789abcdef"; - - -/** - * init the buffer - * - */ - -buffer* buffer_init(void) { - buffer *b; - - b = malloc(sizeof(*b)); - assert(b); - - b->ptr = NULL; - b->size = 0; - b->used = 0; - - return b; -} - -buffer *buffer_init_buffer(buffer *src) { - buffer *b = buffer_init(); - buffer_copy_string_buffer(b, src); - return b; -} - -/** - * free the buffer - * - */ - -void buffer_free(buffer *b) { - if (!b) return; - - free(b->ptr); - free(b); -} - -void buffer_reset(buffer *b) { - if (!b) return; - - /* limit don't reuse buffer larger than ... bytes */ - if (b->size > BUFFER_MAX_REUSE_SIZE) { - free(b->ptr); - b->ptr = NULL; - b->size = 0; - } else if (b->size) { - b->ptr[0] = '\0'; - } - - b->used = 0; -} - - -/** - * - * allocate (if necessary) enough space for 'size' (+1, if 'size' > 0) bytes and - * set the 'used' counter to 0 - * - */ - -#define BUFFER_PIECE_SIZE 64 - -int buffer_prepare_copy(buffer *b, size_t size) { - if (!b) return -1; - - if ((0 == b->size) || - (size >= b->size)) { - if (b->size) free(b->ptr); - - b->size = size; - - /* always allocate a multiple of BUFFER_PIECE_SIZE */ - /* adds a least 1 byte */ - b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE); - - b->ptr = malloc(b->size); - assert(b->ptr); - } - b->used = 0; - return 0; -} - -/** - * - * increase the internal buffer (if necessary) to append another 'size' byte - * ->used isn't changed - * - */ - -int buffer_prepare_append(buffer *b, size_t size) { - if (!b) return -1; - - if (0 == b->size) { - b->size = size; - - /* always allocate a multiple of BUFFER_PIECE_SIZE */ - b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE); - - b->ptr = malloc(b->size); - b->used = 0; - assert(b->ptr); - } else if (b->used + size >= b->size) { - b->size += size; - - /* always allocate a multiple of BUFFER_PIECE_SIZE */ - b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE); - - b->ptr = realloc(b->ptr, b->size); - assert(b->ptr); - } - return 0; -} - -int buffer_copy_string(buffer *b, const char *s) { - size_t s_len; - - if (!s || !b) return -1; - - s_len = strlen(s) + 1; - buffer_prepare_copy(b, s_len); - - memcpy(b->ptr, s, s_len); - b->used = s_len; - - return 0; -} - -int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) { - if (!s || !b) return -1; -#if 0 - /* removed optimization as we have to keep the empty string - * in some cases for the config handling - * - * url.access-deny = ( "" ) - */ - if (s_len == 0) return 0; -#endif - buffer_prepare_copy(b, s_len + 1); - - memcpy(b->ptr, s, s_len); - b->ptr[s_len] = '\0'; - b->used = s_len + 1; - - return 0; -} - -int buffer_copy_string_buffer(buffer *b, const buffer *src) { - if (!src) return -1; - - if (src->used == 0) { - buffer_reset(b); - return 0; - } - return buffer_copy_string_len(b, src->ptr, src->used - 1); -} - -int buffer_append_string(buffer *b, const char *s) { - size_t s_len; - - if (!s || !b) return -1; - - s_len = strlen(s); - buffer_prepare_append(b, s_len + 1); - if (b->used == 0) - b->used++; - - memcpy(b->ptr + b->used - 1, s, s_len + 1); - b->used += s_len; - - return 0; -} - -int buffer_append_string_rfill(buffer *b, const char *s, size_t maxlen) { - size_t s_len; - - if (!s || !b) return -1; - - s_len = strlen(s); - if (s_len > maxlen) s_len = maxlen; - buffer_prepare_append(b, maxlen + 1); - if (b->used == 0) - b->used++; - - memcpy(b->ptr + b->used - 1, s, s_len); - if (maxlen > s_len) { - memset(b->ptr + b->used - 1 + s_len, ' ', maxlen - s_len); - } - - b->used += maxlen; - b->ptr[b->used - 1] = '\0'; - return 0; -} - -/** - * append a string to the end of the buffer - * - * the resulting buffer is terminated with a '\0' - * s is treated as an un-terminated string (a \0 is handled as a normal character) - * - * @param b a buffer - * @param s the string - * @param s_len size of the string (without the terminating \0) - */ - -int buffer_append_string_len(buffer *b, const char *s, size_t s_len) { - if (!s || !b) return -1; - if (s_len == 0) return 0; - - buffer_prepare_append(b, s_len + 1); - if (b->used == 0) - b->used++; - - memcpy(b->ptr + b->used - 1, s, s_len); - b->used += s_len; - b->ptr[b->used - 1] = '\0'; - - return 0; -} - -int buffer_append_string_buffer(buffer *b, const buffer *src) { - if (!src) return -1; - if (src->used == 0) return 0; - - return buffer_append_string_len(b, src->ptr, src->used - 1); -} - -int buffer_append_memory(buffer *b, const char *s, size_t s_len) { - if (!s || !b) return -1; - if (s_len == 0) return 0; - - buffer_prepare_append(b, s_len); - memcpy(b->ptr + b->used, s, s_len); - b->used += s_len; - - return 0; -} - -int buffer_copy_memory(buffer *b, const char *s, size_t s_len) { - if (!s || !b) return -1; - - b->used = 0; - - return buffer_append_memory(b, s, s_len); -} - -int buffer_append_long_hex(buffer *b, unsigned long value) { - char *buf; - int shift = 0; - unsigned long copy = value; - - while (copy) { - copy >>= 4; - shift++; - } - if (shift == 0) - shift++; - if (shift & 0x01) - shift++; - - buffer_prepare_append(b, shift + 1); - if (b->used == 0) - b->used++; - buf = b->ptr + (b->used - 1); - b->used += shift; - - shift <<= 2; - while (shift > 0) { - shift -= 4; - *(buf++) = hex_chars[(value >> shift) & 0x0F]; - } - *buf = '\0'; - - return 0; -} - -int LI_ltostr(char *buf, long val) { - char swap; - char *end; - int len = 1; - - if (val < 0) { - len++; - *(buf++) = '-'; - val = -val; - } - - end = buf; - while (val > 9) { - *(end++) = '0' + (val % 10); - val = val / 10; - } - *(end) = '0' + val; - *(end + 1) = '\0'; - len += end - buf; - - while (buf < end) { - swap = *end; - *end = *buf; - *buf = swap; - - buf++; - end--; - } - - return len; -} - -int buffer_append_long(buffer *b, long val) { - if (!b) return -1; - - buffer_prepare_append(b, 32); - if (b->used == 0) - b->used++; - - b->used += LI_ltostr(b->ptr + (b->used - 1), val); - return 0; -} - -int buffer_copy_long(buffer *b, long val) { - if (!b) return -1; - - b->used = 0; - return buffer_append_long(b, val); -} - -#if !defined(SIZEOF_LONG) || (SIZEOF_LONG != SIZEOF_OFF_T) -int buffer_append_off_t(buffer *b, off_t val) { - char swap; - char *end; - char *start; - int len = 1; - - if (!b) return -1; - - buffer_prepare_append(b, 32); - if (b->used == 0) - b->used++; - - start = b->ptr + (b->used - 1); - if (val < 0) { - len++; - *(start++) = '-'; - val = -val; - } - - end = start; - while (val > 9) { - *(end++) = '0' + (val % 10); - val = val / 10; - } - *(end) = '0' + val; - *(end + 1) = '\0'; - len += end - start; - - while (start < end) { - swap = *end; - *end = *start; - *start = swap; - - start++; - end--; - } - - b->used += len; - return 0; -} - -int buffer_copy_off_t(buffer *b, off_t val) { - if (!b) return -1; - - b->used = 0; - return buffer_append_off_t(b, val); -} -#endif /* !defined(SIZEOF_LONG) || (SIZEOF_LONG != SIZEOF_OFF_T) */ - -char int2hex(char c) { - return hex_chars[(c & 0x0F)]; -} - -/* converts hex char (0-9, A-Z, a-z) to decimal. - * returns 0xFF on invalid input. - */ -char hex2int(unsigned char hex) { - hex = hex - '0'; - if (hex > 9) { - hex = (hex + '0' - 1) | 0x20; - hex = hex - 'a' + 11; - } - if (hex > 15) - hex = 0xFF; - - return hex; -} - - -/** - * init the ptr buffer - * - */ -buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer) -{ - buffer_ptr *l = calloc(1, sizeof(buffer_ptr)); - l->free = freer; - - return l; -} - -/** - * free the buffer_array - * - */ -void buffer_ptr_free(buffer_ptr *l) -{ - if (NULL != l) { - buffer_ptr_clear(l); - free(l); - } -} - -void buffer_ptr_clear(buffer_ptr *l) -{ - assert(NULL != l); - - if (l->free && l->used) { - size_t i; - for (i = 0; i < l->used; i ++) { - l->free(l->ptr[i]); - } - } - - if (l->ptr) { - free(l->ptr); - l->ptr = NULL; - } - l->used = 0; - l->size = 0; -} - -void buffer_ptr_append(buffer_ptr* l, void *item) -{ - assert(NULL != l); - if (l->ptr == NULL) { - l->size = 16; - l->ptr = (void **)malloc(sizeof(void *) * l->size); - } - else if (l->used == l->size) { - l->size += 16; - l->ptr = realloc(l->ptr, sizeof(void *) * l->size); - } - l->ptr[l->used++] = item; -} - -void *buffer_ptr_pop(buffer_ptr* l) -{ - assert(NULL != l && l->used > 0); - return l->ptr[--l->used]; -} - -void *buffer_ptr_top(buffer_ptr* l) -{ - assert(NULL != l && l->used > 0); - return l->ptr[l->used-1]; -} - -/** - * init the buffer - * - */ - -buffer_array* buffer_array_init(void) { - buffer_array *b; - - b = malloc(sizeof(*b)); - - assert(b); - b->ptr = NULL; - b->size = 0; - b->used = 0; - - return b; -} - -void buffer_array_reset(buffer_array *b) { - size_t i; - - if (!b) return; - - /* if they are too large, reduce them */ - for (i = 0; i < b->used; i++) { - buffer_reset(b->ptr[i]); - } - - b->used = 0; -} - - -/** - * free the buffer_array - * - */ - -void buffer_array_free(buffer_array *b) { - size_t i; - if (!b) return; - - for (i = 0; i < b->size; i++) { - if (b->ptr[i]) buffer_free(b->ptr[i]); - } - free(b->ptr); - free(b); -} - -buffer *buffer_array_append_get_buffer(buffer_array *b) { - size_t i; - - if (b->size == 0) { - b->size = 16; - b->ptr = malloc(sizeof(*b->ptr) * b->size); - assert(b->ptr); - for (i = 0; i < b->size; i++) { - b->ptr[i] = NULL; - } - } else if (b->size == b->used) { - b->size += 16; - b->ptr = realloc(b->ptr, sizeof(*b->ptr) * b->size); - assert(b->ptr); - for (i = b->used; i < b->size; i++) { - b->ptr[i] = NULL; - } - } - - if (b->ptr[b->used] == NULL) { - b->ptr[b->used] = buffer_init(); - } - - b->ptr[b->used]->used = 0; - - return b->ptr[b->used++]; -} - - -char * buffer_search_string_len(buffer *b, const char *needle, size_t len) { - size_t i; - if (len == 0) return NULL; - if (needle == NULL) return NULL; - - if (b->used < len) return NULL; - - for(i = 0; i < b->used - len; i++) { - if (0 == memcmp(b->ptr + i, needle, len)) { - return b->ptr + i; - } - } - - return NULL; -} - -buffer *buffer_init_string(const char *str) { - buffer *b = buffer_init(); - - buffer_copy_string(b, str); - - return b; -} - -int buffer_is_empty(buffer *b) { - if (!b) return 1; - - return (b->used == 0); -} - -/** - * check if two buffers contain the same data - * - * HISTORY: this function was pretty much optimized, but didn't handled - * alignment properly. - */ - -int buffer_is_equal(buffer *a, buffer *b) { - if (a->used != b->used) return 0; - if (a->used == 0) return 1; - - return (0 == strncmp(a->ptr, b->ptr, a->used - 1)); -} - -int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) { - buffer b; - - b.ptr = (char *)s; - b.used = b_len + 1; - - return buffer_is_equal(a, &b); -} - -/* simple-assumption: - * - * most parts are equal and doing a case conversion takes time - * - */ -int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) { - size_t ndx = 0, max_ndx; - size_t *al, *bl; - size_t mask = sizeof(*al) - 1; - - al = (size_t *)a; - bl = (size_t *)b; - - /* is the alignment correct? */ - if ( ((size_t)al & mask) == 0 && - ((size_t)bl & mask) == 0 ) { - - max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask; - - for (; ndx < max_ndx; ndx += sizeof(*al)) { - if (*al != *bl) break; - al++; bl++; - - } - - } - - a = (char *)al; - b = (char *)bl; - - max_ndx = ((a_len < b_len) ? a_len : b_len); - - for (; ndx < max_ndx; ndx++) { - int a1 = *a++, b1 = *b++; - - if (a1 != b1) { - /* always lowercase for transitive results */ - if (a1 >= 'A' && a1 <= 'Z') a1 |= 32; - if (b1 >= 'A' && b1 <= 'Z') b1 |= 32; - - if ((a1 - b1) != 0) return (a1 - b1); - } - } - - /* all chars are the same, and the length match too - * - * they are the same */ - if (a_len == b_len) return 0; - - /* if a is shorter then b, then b is larger */ - return (a_len - b_len); -} - - -/** - * check if the rightmost bytes of the string are equal. - * - * - */ - -int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) { - /* no, len -> equal */ - if (len == 0) return 1; - - /* len > 0, but empty buffers -> not equal */ - if (b1->used == 0 || b2->used == 0) return 0; - - /* buffers too small -> not equal */ - if (b1->used - 1 < len || b2->used - 1 < len) return 0; - - if (0 == strncmp(b1->ptr + b1->used - 1 - len, - b2->ptr + b2->used - 1 - len, len)) { - return 1; - } - - return 0; -} - -int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) { - size_t i; - - /* BO protection */ - if (in_len * 2 < in_len) return -1; - - buffer_prepare_copy(b, in_len * 2 + 1); - - for (i = 0; i < in_len; i++) { - b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F]; - b->ptr[b->used++] = hex_chars[in[i] & 0x0F]; - } - b->ptr[b->used++] = '\0'; - - return 0; -} - -/* everything except: ! ( ) * - . 0-9 A-Z _ a-z */ -const char encoded_chars_rel_uri_part[] = { - /* - 0 1 2 3 4 5 6 7 8 9 A B C D E F - */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ - 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F @ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 5F [ \ ] ^ */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F ` */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 7F { | } ~ DEL */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ -}; - -/* everything except: ! ( ) * - . / 0-9 A-Z _ a-z */ -const char encoded_chars_rel_uri[] = { - /* - 0 1 2 3 4 5 6 7 8 9 A B C D E F - */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ - 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F @ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 5F [ \ ] ^ */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F ` */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 7F { | } ~ DEL */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ -}; - -const char encoded_chars_html[] = { - /* - 0 1 2 3 4 5 6 7 8 9 A B C D E F - */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 70 - 7F DEL */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ -}; - -const char encoded_chars_minimal_xml[] = { - /* - 0 1 2 3 4 5 6 7 8 9 A B C D E F - */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 70 - 7F DEL */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ -}; - -const char encoded_chars_hex[] = { - /* - 0 1 2 3 4 5 6 7 8 9 A B C D E F - */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ -}; - - -int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_encoding_t encoding) { - unsigned char *ds, *d; - size_t d_len, ndx; - const char *map = NULL; - - if (!s || !b) return -1; - if (b->used == 0) return -1; - - if (b->ptr[b->used - 1] != '\0') return -1; - - if (s_len == 0) return 0; - - switch(encoding) { - case ENCODING_REL_URI: - map = encoded_chars_rel_uri; - break; - case ENCODING_REL_URI_PART: - map = encoded_chars_rel_uri_part; - break; - case ENCODING_HTML: - map = encoded_chars_html; - break; - case ENCODING_MINIMAL_XML: - map = encoded_chars_minimal_xml; - break; - case ENCODING_HEX: - map = encoded_chars_hex; - break; - case ENCODING_UNSET: - return buffer_append_string_len(b, s, s_len); - } - - assert(map != NULL); - - /* count to-be-encoded characters */ - for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { - if (map[*ds]) { - switch(encoding) { - case ENCODING_REL_URI: - case ENCODING_REL_URI_PART: - d_len += 3; - break; - case ENCODING_HTML: - case ENCODING_MINIMAL_XML: - d_len += 6; - break; - case ENCODING_HEX: - d_len += 2; - break; - case ENCODING_UNSET: - break; - } - } else { - d_len ++; - } - } - - buffer_prepare_append(b, d_len); - - for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { - if (map[*ds]) { - switch(encoding) { - case ENCODING_REL_URI: - case ENCODING_REL_URI_PART: - d[d_len++] = '%'; - d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F]; - d[d_len++] = hex_chars[(*ds) & 0x0F]; - break; - case ENCODING_HTML: - case ENCODING_MINIMAL_XML: - d[d_len++] = '&'; - d[d_len++] = '#'; - d[d_len++] = 'x'; - d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F]; - d[d_len++] = hex_chars[(*ds) & 0x0F]; - d[d_len++] = ';'; - break; - case ENCODING_HEX: - d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F]; - d[d_len++] = hex_chars[(*ds) & 0x0F]; - break; - case ENCODING_UNSET: - break; - } - } else { - d[d_len++] = *ds; - } - } - - /* terminate buffer and calculate new length */ - b->ptr[b->used + d_len - 1] = '\0'; - - b->used += d_len; - - return 0; -} - - -/* decodes url-special chars in-place. - * replaces non-printable characters with '_' - */ - -static int buffer_urldecode_internal(buffer *url, int is_query) { - unsigned char high, low; - const char *src; - char *dst; - - if (!url || !url->ptr) return -1; - - src = (const char*) url->ptr; - dst = (char*) url->ptr; - - while ((*src) != '\0') { - if (is_query && *src == '+') { - *dst = ' '; - } else if (*src == '%') { - *dst = '%'; - - high = hex2int(*(src + 1)); - if (high != 0xFF) { - low = hex2int(*(src + 2)); - if (low != 0xFF) { - high = (high << 4) | low; - - /* map out control characters */ - if (high < 32 || high == 127) high = '_'; - - *dst = high; - src += 2; - } - } - } else { - *dst = *src; - } - - dst++; - src++; - } - - *dst = '\0'; - url->used = (dst - url->ptr) + 1; - - return 0; -} - -int buffer_urldecode_path(buffer *url) { - return buffer_urldecode_internal(url, 0); -} - -int buffer_urldecode_query(buffer *url) { - return buffer_urldecode_internal(url, 1); -} - -/* Remove "/../", "//", "/./" parts from path. - * - * /blah/.. gets / - * /blah/../foo gets /foo - * /abc/./xyz gets /abc/xyz - * /abc//xyz gets /abc/xyz - * - * NOTE: src and dest can point to the same buffer, in which case - * the operation is performed in-place. - */ - -int buffer_path_simplify(buffer *dest, buffer *src) -{ - int toklen; - char c, pre1; - char *start, *slash, *walk, *out; - unsigned short pre; - - if (src == NULL || src->ptr == NULL || dest == NULL) - return -1; - - if (src == dest) - buffer_prepare_append(dest, 1); - else - buffer_prepare_copy(dest, src->used + 1); - - walk = src->ptr; - start = dest->ptr; - out = dest->ptr; - slash = dest->ptr; - while (*walk == ' ') { - walk++; - } - - pre1 = *(walk++); - c = *(walk++); - pre = pre1; - if (pre1 != '/') { - pre = ('/' << 8) | pre1; - *(out++) = '/'; - } - *(out++) = pre1; - - if (pre1 == '\0') { - dest->used = (out - start) + 1; - return 0; - } - - while (1) { - if (c == '/' || c == '\0') { - toklen = out - slash; - if (toklen == 3 && pre == (('.' << 8) | '.')) { - out = slash; - if (out > start) { - out--; - while (out > start && *out != '/') { - out--; - } - } - - if (c == '\0') - out++; - } else if (toklen == 1 || pre == (('/' << 8) | '.')) { - out = slash; - if (c == '\0') - out++; - } - - slash = out; - } - - if (c == '\0') - break; - - pre1 = c; - pre = (pre << 8) | pre1; - c = *walk; - *out = pre1; - - out++; - walk++; - } - - *out = '\0'; - dest->used = (out - start) + 1; - - return 0; -} - -int light_isdigit(int c) { - return (c >= '0' && c <= '9'); -} - -int light_isxdigit(int c) { - if (light_isdigit(c)) return 1; - - c |= 32; - return (c >= 'a' && c <= 'f'); -} - -int light_isalpha(int c) { - c |= 32; - return (c >= 'a' && c <= 'z'); -} - -int light_isalnum(int c) { - return light_isdigit(c) || light_isalpha(c); -} - -#undef BUFFER_CTYPE_FUNC -#define BUFFER_CTYPE_FUNC(type) \ - int buffer_is##type(buffer *b) { \ - size_t i, len; \ - if (b->used < 2) return 0; \ - /* strlen */ \ - len = b->used - 1; \ - /* c-string only */ \ - if (b->ptr[len] != '\0') { \ - return 0; \ - } \ - /* check on the whole string */ \ - for (i = 0; i < len; i ++) { \ - if (!light_is##type(b->ptr[i])) { \ - return 0; \ - } \ - } \ - return 1; \ - } - -BUFFER_CTYPE_FUNC(digit) -BUFFER_CTYPE_FUNC(xdigit) -BUFFER_CTYPE_FUNC(alpha) -BUFFER_CTYPE_FUNC(alnum) - -int buffer_to_lower(buffer *b) { - char *c; - - if (b->used == 0) return 0; - - for (c = b->ptr; *c; c++) { - if (*c >= 'A' && *c <= 'Z') { - *c |= 32; - } - } - - return 0; -} - - -int buffer_to_upper(buffer *b) { - char *c; - - if (b->used == 0) return 0; - - for (c = b->ptr; *c; c++) { - if (*c >= 'a' && *c <= 'z') { - *c &= ~32; - } - } - - return 0; -} - -buffer_pool *buffer_pool_init() { - buffer_pool *bp; - - bp = calloc(1, sizeof(*bp)); - - return bp; -} - -void buffer_pool_free(buffer_pool *bp) { - if (!bp) return; - - ARRAY_STATIC_FREE(bp, buffer, b, buffer_free(b)); - - free(bp); - - return; -} - -buffer *buffer_pool_get(buffer_pool *bp) { - buffer *b; - - if (bp->used == 0) { - return buffer_init(); - } - - b = bp->ptr[--bp->used]; - - buffer_reset(b); - - return b; -} - -void buffer_pool_append(buffer_pool *bp, buffer *b) { - ARRAY_STATIC_PREPARE_APPEND(bp); - - bp->ptr[bp->used++] = b; -} - - |