diff options
Diffstat (limited to '')
-rw-r--r-- | htp/bstr.h | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/htp/bstr.h b/htp/bstr.h new file mode 100644 index 0000000..eb6497b --- /dev/null +++ b/htp/bstr.h @@ -0,0 +1,678 @@ +/*************************************************************************** + * 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> + */ + +#ifndef _BSTR_H +#define _BSTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct bstr_t bstr; + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "bstr_builder.h" + +// Data structures + +struct bstr_t { + /** The length of the string stored in the buffer. */ + size_t len; + + /** The current size of the buffer. If there is extra room in the + * buffer the string will be able to expand without reallocation. + */ + size_t size; + + /** Optional buffer pointer. If this pointer is NULL the string buffer + * will immediately follow this structure. If the pointer is not NUL, + * it points to the actual buffer used, and there's no data following + * this structure. + */ + unsigned char *realptr; +}; + + +// Defines + +#define bstr_len(X) ((*(X)).len) +#define bstr_size(X) ((*(X)).size) +#define bstr_ptr(X) ( ((*(X)).realptr == NULL) ? ((unsigned char *)(X) + sizeof(bstr)) : (unsigned char *)(*(X)).realptr ) +#define bstr_realptr(X) ((*(X)).realptr) + + +// Functions + +/** + * Append source bstring to destination bstring, growing destination if + * necessary. If the destination bstring is expanded, the pointer will change. + * You must replace the original destination pointer with the returned one. + * Destination is not changed on memory allocation failure. + * + * @param[in] bdestination + * @param[in] bsource + * @return Updated bstring, or NULL on memory allocation failure. + */ +bstr *bstr_add(bstr *bdestination, const bstr *bsource); + +/** + * Append a NUL-terminated source to destination, growing destination if + * necessary. If the string is expanded, the pointer will change. You must + * replace the original destination pointer with the returned one. Destination + * is not changed on memory allocation failure. + * + * @param[in] b + * @param[in] cstr + * @return Updated bstring, or NULL on memory allocation failure. + */ +bstr *bstr_add_c(bstr *b, const char *cstr); + +/** + * Append as many bytes from the source to destination bstring. The + * destination storage will not be expanded if there is not enough space in it + * already to accommodate all of the data. + * + * @param[in] b + * @param[in] cstr + * @return The destination bstring. + */ +bstr *bstr_add_c_noex(bstr *b, const char *cstr); + +/** + * Append a memory region to destination, growing destination if necessary. If + * the string is expanded, the pointer will change. You must replace the + * original destination pointer with the returned one. Destination is not + * changed on memory allocation failure. + * + * @param[in] b + * @param[in] data + * @param[in] len + * @return Updated bstring, or NULL on memory allocation failure. + */ +bstr *bstr_add_mem(bstr *b, const void *data, size_t len); + +/** + * Append as many bytes from the source to destination bstring. The + * destination storage will not be expanded if there is not enough space in it + * already to accommodate all of the data. + * + * @param[in] b + * @param[in] data + * @param[in] len + * @return The destination bstring. + */ +bstr *bstr_add_mem_noex(bstr *b, const void *data, size_t len); + +/** + * Append as many bytes from the source bstring to destination bstring. The + * destination storage will not be expanded if there is not enough space in it + * already to accommodate all of the data. + * + * @param[in] bdestination + * @param[in] bsource + * @return The destination bstring. + */ +bstr *bstr_add_noex(bstr *bdestination, const bstr *bsource); + +/** + * Adjust bstring length. You will need to use this method whenever + * you work directly with the string contents, and end up changing + * its length by direct structure manipulation. + * + * @param[in] b + * @param[in] newlen + */ +void bstr_adjust_len(bstr *b, size_t newlen); + +/** + * Change the external pointer used by bstring. You will need to use this + * function only if you're messing with bstr internals. Use with caution. + * + * @param[in] b + * @param[in] newrealptr + */ +void bstr_adjust_realptr(bstr *b, void *newrealptr); + +/** + * Adjust bstring size. This does not change the size of the storage behind + * the bstring, just changes the field that keeps track of how many bytes + * there are in the storage. You will need to use this function only if + * you're messing with bstr internals. Use with caution. + * + * @param[in] b + * @param[in] newsize + */ +void bstr_adjust_size(bstr *b, size_t newsize); + +/** + * Allocate a zero-length bstring, reserving space for at least size bytes. + * + * @param[in] size + * @return New string instance + */ +bstr *bstr_alloc(size_t size); + +/** + * Checks whether bstring begins with another bstring. Case sensitive. + * + * @param[in] bhaystack + * @param[in] bneedle + * @return 1 if true, otherwise 0. + */ +int bstr_begins_with(const bstr *bhaystack, const bstr *bneedle); + +/** + * Checks whether bstring begins with NUL-terminated string. Case sensitive. + * + * @param[in] bhaystack + * @param[in] cneedle + * @return 1 if true, otherwise 0. + */ +int bstr_begins_with_c(const bstr *bhaystack, const char *cneedle); + +/** + * Checks whether bstring begins with NUL-terminated string. Case insensitive. + * + * @param[in] bhaystack + * @param[in] cneedle + * @return 1 if true, otherwise 0. + */ +int bstr_begins_with_c_nocase(const bstr *bhaystack, const char *cneedle); + +/** + * Checks whether the bstring begins with the given memory block. Case sensitive. + * + * @param[in] bhaystack + * @param[in] data + * @param[in] len + * @return 1 if true, otherwise 0. + */ +int bstr_begins_with_mem(const bstr *bhaystack, const void *data, size_t len); + +/** + * Checks whether bstring begins with memory block. Case insensitive. + * + * @param[in] bhaystack + * @param[in] data + * @param[in] len + * @return 1 if true, otherwise 0. + */ +int bstr_begins_with_mem_nocase(const bstr *bhaystack, const void *data, size_t len); + +/** + * Checks whether bstring begins with another bstring. Case insensitive. + * + * @param[in] bhaystack + * @param[in] cneedle + * @return 1 if true, otherwise 0. + */ +int bstr_begins_with_nocase(const bstr *bhaystack, const bstr *cneedle); + +/** + * Return the byte at the given position. + * + * @param[in] b + * @param[in] pos + * @return The byte at the given location, or -1 if the position is out of range. + */ +int bstr_char_at(const bstr *b, size_t pos); + +/** + * Return the byte at the given position, counting from the end of the string (e.g., + * byte at position 0 is the last byte in the string.) + * + * @param[in] b + * @param[in] pos + * @return The byte at the given location, or -1 if the position is out of range. + */ +int bstr_char_at_end(const bstr *b, size_t pos); + +/** + * Remove the last byte from bstring, assuming it contains at least one byte. This + * function will not reduce the storage that backs the string, only the amount + * of data used. + * + * @param[in] b + */ +void bstr_chop(bstr *b); + +/** + * Return the first position of the provided byte. + * + * @param[in] b + * @param[in] c + * @return The first position of the byte, or -1 if it could not be found + */ +int bstr_chr(const bstr *b, int c); + +/** + * Case-sensitive comparison of two bstrings. + * + * @param[in] b1 + * @param[in] b2 + * @return Zero on string match, 1 if b1 is greater than b2, and -1 if b2 is + * greater than b1. + */ +int bstr_cmp(const bstr *b1, const bstr *b2); + +/** + * Case-sensitive comparison of a bstring and a NUL-terminated string. + * + * @param[in] b + * @param[in] cstr + * @return Zero on string match, 1 if b is greater than cstr, and -1 if cstr is + * greater than b. + */ +int bstr_cmp_c(const bstr *b, const char *cstr); + +/** + * Case-insensitive comparison of a bstring with a NUL-terminated string. + * + * @param[in] b + * @param[in] cstr + * @return Zero on string match, 1 if b is greater than cstr, and -1 if cstr is greater than b. + */ +int bstr_cmp_c_nocase(const bstr *b, const char *cstr); + +/** + * Case-insensitive zero-skipping comparison of a bstring with a NUL-terminated string. + * + * @param[in] b + * @param[in] cstr + * @return Zero on string match, 1 if b is greater than cstr, and -1 if cstr is greater than b. + */ +int bstr_cmp_c_nocasenorzero(const bstr *b, const char *cstr); + +/** + * Performs a case-sensitive comparison of a bstring with a memory region. + * + * @param[in] b + * @param[in] data + * @param[in] len + * @return Zero ona match, 1 if b is greater than data, and -1 if data is greater than b. + */ +int bstr_cmp_mem(const bstr *b, const void *data, size_t len); + +/** + * Performs a case-insensitive comparison of a bstring with a memory region. + * + * @param[in] b + * @param[in] data + * @param[in] len + * @return Zero ona match, 1 if b is greater than data, and -1 if data is greater than b. + */ +int bstr_cmp_mem_nocase(const bstr *b, const void *data, size_t len); + +/** + * Case-insensitive comparison two bstrings. + * + * @param[in] b1 + * @param[in] b2 + * @return Zero on string match, 1 if b1 is greater than b2, and -1 if b2 is + * greater than b1. + */ +int bstr_cmp_nocase(const bstr *b1, const bstr *b2); + +/** + * Case-insensitive and zero skipping comparison two bstrings. + * + * @param[in] b1 + * @param[in] b2 + * @return Zero on string match, 1 if b1 is greater than b2, and -1 if b2 is + * greater than b1. + */ +int bstr_cmp_nocasenorzero(const bstr *b1, const bstr *b2); + +/** + * Create a new bstring by copying the provided bstring. + * + * @param[in] b + * @return New bstring, or NULL if memory allocation failed. + */ +bstr *bstr_dup(const bstr *b); + +/** + * Create a new bstring by copying the provided NUL-terminated string. + * + * @param[in] cstr + * @return New bstring, or NULL if memory allocation failed. + */ +bstr *bstr_dup_c(const char *cstr); + +/** + * Create a new bstring by copying a part of the provided bstring. + * + * @param[in] b + * @param[in] offset + * @param[in] len + * @return New bstring, or NULL if memory allocation failed. + */ +bstr *bstr_dup_ex(const bstr *b, size_t offset, size_t len); + +/** + * Create a copy of the provided bstring, then convert it to lowercase. + * + * @param[in] b + * @return New bstring, or NULL if memory allocation failed + */ +bstr *bstr_dup_lower(const bstr *b); + +/** + * Create a new bstring by copying the provided memory region. + * + * @param[in] data + * @param[in] len + * @return New bstring, or NULL if memory allocation failed + */ +bstr *bstr_dup_mem(const void *data, size_t len); + +/** + * Expand internal bstring storage to support at least newsize bytes. The storage + * is not expanded if the current size is equal or greater to newsize. Because + * realloc is used underneath, the old pointer to bstring may no longer be valid + * after this function completes successfully. + * + * @param[in] b + * @param[in] newsize + * @return Updated string instance, or NULL if memory allocation failed or if + * attempt was made to "expand" the bstring to a smaller size. + */ +bstr *bstr_expand(bstr *b, size_t newsize); + +/** + * Deallocate the supplied bstring instance and set it to NULL. Allows NULL on + * input. + * + * @param[in] b + */ +void bstr_free(bstr *b); + +/** + * Find the needle in the haystack. + * + * @param[in] bhaystack + * @param[in] bneedle + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of(const bstr *bhaystack, const bstr *bneedle); + +/** + * Find the needle in the haystack, ignoring case differences. + * + * @param[in] bhaystack + * @param[in] bneedle + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of_nocase(const bstr *bhaystack, const bstr *bneedle); + +/** + * Find the needle in the haystack, with the needle being a NUL-terminated + * string. + * + * @param[in] bhaystack + * @param[in] cneedle + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of_c(const bstr *bhaystack, const char *cneedle); + +/** + * Find the needle in the haystack, with the needle being a NUL-terminated + * string. Ignore case differences. + * + * @param[in] bhaystack + * @param[in] cneedle + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of_c_nocase(const bstr *bhaystack, const char *cneedle); + +/** + * Find the needle in the haystack, with the needle being a NUL-terminated + * string. Ignore case differences. Skip zeroes in haystack + * + * @param[in] bhaystack + * @param[in] cneedle + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of_c_nocasenorzero(const bstr *bhaystack, const char *cneedle); + +/** + * Find the needle in the haystack, with the needle being a memory region. + * + * @param[in] bhaystack + * @param[in] data + * @param[in] len + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of_mem(const bstr *bhaystack, const void *data, size_t len); + +/** + * Find the needle in the haystack, with the needle being a memory region. + * Ignore case differences. + * + * @param[in] bhaystack + * @param[in] data + * @param[in] len + * @return Position of the match, or -1 if the needle could not be found. + */ +int bstr_index_of_mem_nocase(const bstr *bhaystack, const void *data, size_t len); + +/** + * Return the last position of a character (byte). + * + * @param[in] b + * @param[in] c + * @return The last position of the character, or -1 if it could not be found. + */ +int bstr_rchr(const bstr *b, int c); + +/** + * Convert bstring to lowercase. This function converts the supplied string, + * it does not create a new string. + * + * @param[in] b + * @return The same bstring received on input + */ +bstr *bstr_to_lowercase(bstr *b); + +/** + * Case-sensitive comparison of two memory regions. + * + * @param[in] data1 + * @param[in] len1 + * @param[in] data2 + * @param[in] len2 + * @return Zero if the memory regions are identical, 1 if data1 is greater than + * data2, and -1 if data2 is greater than data1. + */ +int bstr_util_cmp_mem(const void *data1, size_t len1, const void *data2, size_t len2); + +/** + * Case-insensitive comparison of two memory regions. + * + * @param[in] data1 + * @param[in] len1 + * @param[in] data2 + * @param[in] len2 + * @return Zero if the memory regions are identical, 1 if data1 is greater than + * data2, and -1 if data2 is greater than data1. + */ + int bstr_util_cmp_mem_nocase(const void *data1, size_t len1, const void *data2, size_t len2); + +/** + * Case-insensitive zero-skipping comparison of two memory regions. + * + * @param[in] data1 + * @param[in] len1 + * @param[in] data2 + * @param[in] len2 + * @return Zero if the memory regions are identical, 1 if data1 is greater than + * data2, and -1 if data2 is greater than data1. + */ + int bstr_util_cmp_mem_nocasenorzero(const void *data1, size_t len1, const void *data2, size_t len2); + +/** + * Convert contents of a memory region to a positive integer. + * + * @param[in] data + * @param[in] len + * @param[in] base The desired number base. + * @param[in] lastlen Points to the first unused byte in the region + * @return If the conversion was successful, this function returns the + * number. When the conversion fails, -1 will be returned when not + * one valid digit was found, and -2 will be returned if an overflow + * occurred. + */ +int64_t bstr_util_mem_to_pint(const void *data, size_t len, int base, size_t *lastlen); + +/** + * Searches a memory block for the given NUL-terminated string. Case sensitive. + * + * @param[in] data + * @param[in] len + * @param[in] cstr + * @return Index of the first location of the needle on success, or -1 if the needle was not found. + */ +int bstr_util_mem_index_of_c(const void *data, size_t len, const char *cstr); + +/** + * Searches a memory block for the given NUL-terminated string. Case insensitive. + * + * @param[in] data + * @param[in] len + * @param[in] cstr + * @return Index of the first location of the needle on success, or -1 if the needle was not found. + */ +int bstr_util_mem_index_of_c_nocase(const void *data, size_t len, const char *cstr); + +/** + * Searches the haystack memory block for the needle memory block. Case sensitive. + * + * @param data1 + * @param len1 + * @param data2 + * @param len2 + * @return Index of the first location of the needle on success, or -1 if the needle was not found. + */ +int bstr_util_mem_index_of_mem(const void *data1, size_t len1, const void *data2, size_t len2); + +/** + * Searches the haystack memory block for the needle memory block. Case sensitive. + * + * @param data1 + * @param len1 + * @param data2 + * @param len2 + * @return Index of the first location of the needle on success, or -1 if the needle was not found. + */ +int bstr_util_mem_index_of_mem_nocase(const void *data1, size_t len1, const void *data2, size_t len2); + +/** + * Searches the haystack memory block for the needle memory block. Case sensitive. Skips zeroes in data1 + * + * @param data1 + * @param len1 + * @param data2 + * @param len2 + * @return Index of the first location of the needle on success, or -1 if the needle was not found. + */ +int bstr_util_mem_index_of_mem_nocasenorzero(const void *data1, size_t len1, const void *data2, size_t len2); + +/** + * Removes whitespace from the beginning and the end of a memory region. The data + * itself is not modified; this function only adjusts the provided pointers. + * + * @param[in,out] data + * @param[in,out] len + */ +void bstr_util_mem_trim(unsigned char **data, size_t *len); + +/** + * Take the provided memory region, allocate a new memory buffer, and construct + * a NUL-terminated string, replacing each NUL byte with "\0" (two bytes). The + * caller is responsible to keep track of the allocated memory area and free + * it once it is no longer needed. + * + * @param[in] data + * @param[in] len + * @return The newly created NUL-terminated string, or NULL in case of memory + * allocation failure. + */ +char *bstr_util_memdup_to_c(const void *data, size_t len); + +/** + * Create a new NUL-terminated string out of the provided bstring. If NUL bytes + * are contained in the bstring, each will be replaced with "\0" (two characters). + * The caller is responsible to keep track of the allocated memory area and free + * it once it is no longer needed. + * + * @param[in] b + * @return The newly created NUL-terminated string, or NULL in case of memory + * allocation failure. + */ +char *bstr_util_strdup_to_c(const bstr *b); + +/** + * Create a new bstring from the provided NUL-terminated string and without + * copying the data. The caller must ensure that the input string continues + * to point to a valid memory location for as long as the bstring is used. + * + * @param[in] cstr + * @return New bstring, or NULL on memory allocation failure. + */ +bstr *bstr_wrap_c(const char *cstr); + +/** + * Create a new bstring from the provided memory buffer without + * copying the data. The caller must ensure that the buffer remains + * valid for as long as the bstring is used. + * + * @param[in] data + * @param[in] len + * @return New bstring, or NULL on memory allocation failure. + */ +bstr *bstr_wrap_mem(const void *data, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* _BSTR_H */ |