diff options
Diffstat (limited to 'htp/bstr.c')
-rw-r--r-- | htp/bstr.c | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/htp/bstr.c b/htp/bstr.c new file mode 100644 index 0000000..7673c68 --- /dev/null +++ b/htp/bstr.c @@ -0,0 +1,638 @@ +/*************************************************************************** + * Copyright (c) 2009-2010 Open Information Security Foundation + * Copyright (c) 2010-2013 Qualys, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + + * - Neither the name of the Qualys, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ***************************************************************************/ + +/** + * @file + * @author Ivan Ristic <ivanr@webkreator.com> + */ + +#include <ctype.h> + +#include "bstr.h" + +bstr *bstr_alloc(size_t len) { + bstr *b = malloc(sizeof (bstr) + len); + if (b == NULL) return NULL; + + b->len = 0; + b->size = len; + b->realptr = NULL; + + return b; +} + +bstr *bstr_add(bstr *destination, const bstr *source) { + return bstr_add_mem(destination, bstr_ptr(source), bstr_len(source)); +} + +bstr *bstr_add_c(bstr *bdestination, const char *csource) { + return bstr_add_mem(bdestination, csource, strlen(csource)); +} + +bstr *bstr_add_c_noex(bstr *destination, const char *source) { + return bstr_add_mem_noex(destination, source, strlen(source)); +} + +bstr *bstr_add_mem(bstr *destination, const void *data, size_t len) { + // Expand the destination if necessary + if (bstr_size(destination) < bstr_len(destination) + len) { + destination = bstr_expand(destination, bstr_len(destination) + len); + if (destination == NULL) return NULL; + } + + // Add source to destination + bstr *b = (bstr *) destination; + memcpy(bstr_ptr(destination) + bstr_len(b), data, len); + bstr_adjust_len(b, bstr_len(b) + len); + + return destination; +} + +bstr *bstr_add_mem_noex(bstr *destination, const void *data, size_t len) { + size_t copylen = len; + + // Is there enough room in the destination? + if (bstr_size(destination) < bstr_len(destination) + copylen) { + copylen = bstr_size(destination) - bstr_len(destination); + if (copylen <= 0) return destination; + } + + // Copy over the bytes + bstr *b = (bstr *) destination; + memcpy(bstr_ptr(destination) + bstr_len(b), data, copylen); + bstr_adjust_len(b, bstr_len(b) + copylen); + + return destination; +} + +bstr *bstr_add_noex(bstr *destination, const bstr *source) { + return bstr_add_mem_noex(destination, bstr_ptr(source), bstr_len(source)); +} + +void bstr_adjust_len(bstr *b, size_t newlen) { + b->len = newlen; +} + +void bstr_adjust_realptr(bstr *b, void *newrealptr) { + b->realptr = newrealptr; +} + +void bstr_adjust_size(bstr *b, size_t newsize) { + b->size = newsize; +} + +int bstr_begins_with(const bstr *haystack, const bstr *needle) { + return bstr_begins_with_mem(haystack, bstr_ptr(needle), bstr_len(needle)); +} + +int bstr_begins_with_c(const bstr *haystack, const char *needle) { + return bstr_begins_with_mem(haystack, needle, strlen(needle)); +} + +int bstr_begins_with_c_nocase(const bstr *haystack, const char *needle) { + return bstr_begins_with_mem_nocase(haystack, needle, strlen(needle)); +} + +int bstr_begins_with_nocase(const bstr *haystack, const bstr *needle) { + return bstr_begins_with_mem_nocase(haystack, bstr_ptr(needle), bstr_len(needle)); +} + +int bstr_begins_with_mem(const bstr *haystack, const void *_data, size_t len) { + const unsigned char *data = (unsigned char *) _data; + const unsigned char *hdata = bstr_ptr(haystack); + size_t hlen = bstr_len(haystack); + size_t pos = 0; + + while ((pos < len) && (pos < hlen)) { + if (hdata[pos] != data[pos]) { + return 0; + } + + pos++; + } + + if (pos == len) { + return 1; + } else { + return 0; + } +} + +int bstr_begins_with_mem_nocase(const bstr *haystack, const void *_data, size_t len) { + const unsigned char *data = (const unsigned char *) _data; + const unsigned char *hdata = bstr_ptr(haystack); + size_t hlen = bstr_len(haystack); + size_t pos = 0; + + while ((pos < len) && (pos < hlen)) { + if (tolower((int) hdata[pos]) != tolower((int) data[pos])) { + return 0; + } + + pos++; + } + + if (pos == len) { + return 1; + } else { + return 0; + } +} + +int bstr_char_at(const bstr *b, size_t pos) { + unsigned char *data = bstr_ptr(b); + size_t len = bstr_len(b); + + if (pos >= len) return -1; + return data[pos]; +} + +int bstr_char_at_end(const bstr *b, size_t pos) { + unsigned char *data = bstr_ptr(b); + size_t len = bstr_len(b); + + if (pos >= len) return -1; + return data[len - 1 - pos]; +} + +void bstr_chop(bstr *b) { + if (bstr_len(b) > 0) { + bstr_adjust_len(b, bstr_len(b) - 1); + } +} + +int bstr_chr(const bstr *b, int c) { + unsigned char *data = bstr_ptr(b); + size_t len = bstr_len(b); + + size_t i = 0; + while (i < len) { + if (data[i] == c) { + return (int) i; + } + + i++; + } + + return -1; +} + +int bstr_cmp(const bstr *b1, const bstr *b2) { + return bstr_util_cmp_mem(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2)); +} + +int bstr_cmp_c(const bstr *b, const char *c) { + return bstr_util_cmp_mem(bstr_ptr(b), bstr_len(b), c, strlen(c)); +} + +int bstr_cmp_c_nocase(const bstr *b, const char *c) { + return bstr_util_cmp_mem_nocase(bstr_ptr(b), bstr_len(b), c, strlen(c)); +} + +int bstr_cmp_c_nocasenorzero(const bstr *b, const char *c) { + return bstr_util_cmp_mem_nocasenorzero(bstr_ptr(b), bstr_len(b), c, strlen(c)); +} + +int bstr_cmp_mem(const bstr *b, const void *data, size_t len) { + return bstr_util_cmp_mem(bstr_ptr(b), bstr_len(b), data, len); +} + +int bstr_cmp_mem_nocase(const bstr *b, const void *data, size_t len) { + return bstr_util_cmp_mem_nocase(bstr_ptr(b), bstr_len(b), data, len); +} + +int bstr_cmp_nocase(const bstr *b1, const bstr *b2) { + return bstr_util_cmp_mem_nocase(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2)); +} + +bstr *bstr_dup(const bstr *b) { + return bstr_dup_ex(b, 0, bstr_len(b)); +} + +bstr *bstr_dup_c(const char *cstr) { + return bstr_dup_mem(cstr, strlen(cstr)); +} + +bstr *bstr_dup_ex(const bstr *b, size_t offset, size_t len) { + bstr *bnew = bstr_alloc(len); + if (bnew == NULL) return NULL; + memcpy(bstr_ptr(bnew), bstr_ptr(b) + offset, len); + bstr_adjust_len(bnew, len); + return bnew; +} + +bstr *bstr_dup_lower(const bstr *b) { + return bstr_to_lowercase(bstr_dup(b)); +} + +bstr *bstr_dup_mem(const void *data, size_t len) { + bstr *bnew = bstr_alloc(len); + if (bnew == NULL) return NULL; + memcpy(bstr_ptr(bnew), data, len); + bstr_adjust_len(bnew, len); + return bnew; +} + +bstr *bstr_expand(bstr *b, size_t newsize) { + if (bstr_realptr(b) != NULL) { + // Refuse to expand a wrapped bstring. In the future, + // we can change this to make a copy of the data, thus + // leaving the original memory area intact. + return NULL; + } + + // Catch attempts to "expand" to a smaller size + if (bstr_size(b) > newsize) return NULL; + + bstr *bnew = realloc(b, sizeof (bstr) + newsize); + if (bnew == NULL) return NULL; + + bstr_adjust_size(bnew, newsize); + + return bnew; +} + +void bstr_free(bstr *b) { + if (b == NULL) return; + free(b); +} + +int bstr_index_of(const bstr *haystack, const bstr *needle) { + return bstr_index_of_mem(haystack, bstr_ptr(needle), bstr_len(needle)); +} + +int bstr_index_of_c(const bstr *haystack, const char *needle) { + return bstr_index_of_mem(haystack, needle, strlen(needle)); +} + +int bstr_index_of_c_nocase(const bstr *haystack, const char *needle) { + return bstr_index_of_mem_nocase(haystack, needle, strlen(needle)); +} + +int bstr_index_of_c_nocasenorzero(const bstr *haystack, const char *needle) { + return bstr_util_mem_index_of_mem_nocasenorzero(bstr_ptr(haystack), bstr_len(haystack), needle, strlen(needle)); +} + +int bstr_index_of_mem(const bstr *haystack, const void *_data2, size_t len2) { + return bstr_util_mem_index_of_mem(bstr_ptr(haystack), bstr_len(haystack), _data2, len2); +} + +int bstr_index_of_mem_nocase(const bstr *haystack, const void *_data2, size_t len2) { + return bstr_util_mem_index_of_mem_nocase(bstr_ptr(haystack), bstr_len(haystack), _data2, len2); +} + +int bstr_index_of_nocase(const bstr *haystack, const bstr *needle) { + return bstr_index_of_mem_nocase(haystack, bstr_ptr(needle), bstr_len(needle)); +} + +int bstr_rchr(const bstr *b, int c) { + const unsigned char *data = bstr_ptr(b); + size_t len = bstr_len(b); + + size_t i = len; + while (i > 0) { + if (data[i - 1] == c) { + return (int) (i - 1); + } + + i--; + } + + return -1; +} + +bstr *bstr_to_lowercase(bstr *b) { + if (b == NULL) return NULL; + + unsigned char *data = bstr_ptr(b); + size_t len = bstr_len(b); + + size_t i = 0; + while (i < len) { + data[i] = (uint8_t)tolower(data[i]); + i++; + } + + return b; +} + +int bstr_util_cmp_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) { + const unsigned char *data1 = (const unsigned char *) _data1; + const unsigned char *data2 = (const unsigned char *) _data2; + size_t p1 = 0, p2 = 0; + + while ((p1 < len1) && (p2 < len2)) { + if (data1[p1] != data2[p2]) { + // Difference. + return (data1[p1] < data2[p2]) ? -1 : 1; + } + + p1++; + p2++; + } + + if ((p1 == len2) && (p2 == len1)) { + // They're identical. + return 0; + } else { + // One string is shorter. + if (p1 == len1) return -1; + else return 1; + } +} + +int bstr_util_cmp_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) { + const unsigned char *data1 = (const unsigned char *) _data1; + const unsigned char *data2 = (const unsigned char *) _data2; + size_t p1 = 0, p2 = 0; + + while ((p1 < len1) && (p2 < len2)) { + if (tolower(data1[p1]) != tolower(data2[p2])) { + // Difference. + return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1; + } + + p1++; + p2++; + } + + if ((p1 == len2) && (p2 == len1)) { + // They're identical. + return 0; + } else { + // One string is shorter. + if (p1 == len1) return -1; + else return 1; + } +} + +int bstr_util_cmp_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) { + const unsigned char *data1 = (const unsigned char *) _data1; + const unsigned char *data2 = (const unsigned char *) _data2; + size_t p1 = 0, p2 = 0; + + while ((p1 < len1) && (p2 < len2)) { + if (data1[p1] == 0) { + p1++; + continue; + } + if (tolower(data1[p1]) != tolower(data2[p2])) { + // Difference. + return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1; + } + + p1++; + p2++; + } + + while((p1 < len1) && (data1[p1] == 0)) { + p1++; + } + if ((p1 == len1) && (p2 == len2)) { + // They're identical. + return 0; + } else { + // One string is shorter. + if (p1 == len1) return -1; + else return 1; + } +} + +int64_t bstr_util_mem_to_pint(const void *_data, size_t len, int base, size_t *lastlen) { + const unsigned char *data = (unsigned char *) _data; + int64_t rval = 0, tflag = 0; + size_t i = 0; + + *lastlen = i; + + for (i = 0; i < len; i++) { + int d = data[i]; + + *lastlen = i; + + // Convert character to digit. + if ((d >= '0') && (d <= '9')) { + d -= '0'; + } else if ((d >= 'a') && (d <= 'z')) { + d -= 'a' - 10; + } else if ((d >= 'A') && (d <= 'Z')) { + d -= 'A' - 10; + } else { + d = -1; + } + + // Check that the digit makes sense with the base we are using. + if ((d == -1) || (d >= base)) { + if (tflag) { + // Return what we have so far; lastlen points + // to the first non-digit position. + return rval; + } else { + // We didn't see a single digit. + return -1; + } + } + + if (tflag) { + if (((INT64_MAX - d) / base) < rval) { + // Overflow + return -2; + } + + rval *= base; + rval += d; + } else { + rval = d; + tflag = 1; + } + } + + *lastlen = i + 1; + + return rval; +} + +int bstr_util_mem_index_of_c(const void *_data1, size_t len1, const char *cstr) { + return bstr_util_mem_index_of_mem(_data1, len1, cstr, strlen(cstr)); +} + +int bstr_util_mem_index_of_c_nocase(const void *_data1, size_t len1, const char *cstr) { + return bstr_util_mem_index_of_mem_nocase(_data1, len1, cstr, strlen(cstr)); +} + +int bstr_util_mem_index_of_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) { + const unsigned char *data1 = (unsigned char *) _data1; + const unsigned char *data2 = (unsigned char *) _data2; + size_t i, j; + + // If we ever want to optimize this function, the following link + // might be useful: http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm + + for (i = 0; i < len1; i++) { + size_t k = i; + + for (j = 0; ((j < len2) && (k < len1)); j++, k++) { + if (data1[k] != data2[j]) break; + } + + if (j == len2) { + return (int) i; + } + } + + return -1; +} + +int bstr_util_mem_index_of_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) { + const unsigned char *data1 = (unsigned char *) _data1; + const unsigned char *data2 = (unsigned char *) _data2; + size_t i, j; + + // If we ever want to optimize this function, the following link + // might be useful: http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm + + for (i = 0; i < len1; i++) { + size_t k = i; + + for (j = 0; ((j < len2) && (k < len1)); j++, k++) { + if (toupper(data1[k]) != toupper(data2[j])) break; + } + + if (j == len2) { + return (int) i; + } + } + + return -1; +} + +int bstr_util_mem_index_of_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) { + const unsigned char *data1 = (unsigned char *) _data1; + const unsigned char *data2 = (unsigned char *) _data2; + size_t i, j; + + // If we ever want to optimize this function, the following link + // might be useful: http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm + + for (i = 0; i < len1; i++) { + size_t k = i; + if (data1[i] == 0) { + // skip leading zeroes to avoid quadratic complexity + continue; + } + + for (j = 0; ((j < len2) && (k < len1)); j++, k++) { + if (data1[k] == 0) { + j--; + continue; + } + if (toupper(data1[k]) != toupper(data2[j])) break; + } + + if (j == len2) { + return (int) i; + } + } + + return -1; +} + +void bstr_util_mem_trim(unsigned char **data, size_t *len) { + if ((data == NULL)||(len == NULL)) return; + + unsigned char *d = *data; + size_t l = *len; + + // Ignore whitespace at the beginning. + size_t pos = 0; + while ((pos < l) && isspace(d[pos])) pos++; + d += pos; + l -= pos; + + // Ignore whitespace at the end. + while ((l > 0)&&(isspace(d[l - 1]))) l--; + + *data = d; + *len = l; +} + +char *bstr_util_memdup_to_c(const void *_data, size_t len) { + const unsigned char *data = (unsigned char *) _data; + + // Count how many NUL bytes we have in the string. + size_t i, nulls = 0; + for (i = 0; i < len; i++) { + if (data[i] == '\0') { + nulls++; + } + } + + // Now copy the string into a NUL-terminated buffer. + + char *r, *d; + r = d = malloc(len + nulls + 1); + if (d == NULL) return NULL; + + while (len--) { + if (*data == '\0') { + data++; + *d++ = '\\'; + *d++ = '0'; + } else { + *d++ = *data++; + } + } + + *d = '\0'; + + return r; +} + +char *bstr_util_strdup_to_c(const bstr *b) { + if (b == NULL) return NULL; + return bstr_util_memdup_to_c(bstr_ptr(b), bstr_len(b)); +} + +bstr *bstr_wrap_c(const char *cstr) { + return bstr_wrap_mem((unsigned char *) cstr, strlen(cstr)); +} + +bstr *bstr_wrap_mem(const void *data, size_t len) { + bstr *b = (bstr *) malloc(sizeof (bstr)); + if (b == NULL) return NULL; + + b->size = b->len = len; + b->realptr = (unsigned char *) data; + + return b; +} |