octstr.c.debug
资源名称:gateway-1.2.1 [点击查看]
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:47k
源码类别:
手机WAP编程
开发平台:
WINDOWS
- /*
- * octstr.c - implementation of Octet strings
- *
- * See octstr.h for explanations of what public functions should do.
- *
- * Lars Wirzenius
- */
- #include <ctype.h>
- #include <limits.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include "gwlib.h"
- /***********************************************************************
- * Definitions of data structures. These are not visible to the external
- * world -- they may be accessed only via the functions declared in
- * octstr.h. This ensures they really are abstract.
- */
- /*
- * The octet string.
- *
- * `data' is a pointer to dynamically allocated memory are where the
- * octets in the string. It may be bigger than the actual length of the
- * string.
- *
- * `len' is the length of the string.
- *
- * `size' is the size of the memory area `data' points at.
- *
- * When `size' is greater than zero, it is at least `len+1', and the
- * character at `len' is ' '. This is so that octstr_get_cstr will
- * always work.
- *
- * `immutable' defines whether the octet string is immutable or not.
- */
- struct Octstr
- {
- unsigned char *data;
- long len;
- long size;
- int immutable;
- };
- /**********************************************************************
- * Hash table of immutable octet strings.
- */
- #define MAX_IMMUTABLES 1024
- static Octstr *immutables[MAX_IMMUTABLES];
- static Mutex immutables_mutex;
- static int immutables_init = 0;
- static char is_safe[UCHAR_MAX + 1];
- /*
- * Convert a pointer to a C string literal to a long that can be used
- * for hashing. This is done by converting the pointer into an integer
- * and discarding the lowest to bits to get rid of typical alignment
- * bits.
- */
- #define CSTR_TO_LONG(ptr) (((long) ptr) >> 2)
- /***********************************************************************
- * Declarations of internal functions. These are defined at the end of
- * the file.
- */
- static void seems_valid_real(Octstr *ostr, const char *filename, long lineno,
- const char *function);
- #ifdef NO_GWASSERT
- #define seems_valid(ostr)
- #else
- #define seems_valid(ostr)
- (seems_valid_real(ostr, __FILE__, __LINE__, __func__))
- #endif
- /***********************************************************************
- * Implementations of the functions declared in octstr.h. See the
- * header for explanations of what they should do.
- */
- /* Reserve space for at least 'size' octets */
- static void octstr_grow(Octstr *ostr, long size)
- {
- gw_assert(!ostr->immutable);
- seems_valid(ostr);
- gw_assert(size >= 0);
- size++; /* make room for the invisible terminating NUL */
- if (size > ostr->size) {
- ostr->data = gw_realloc(ostr->data, size);
- ostr->size = size;
- }
- }
- /*
- * Fill is_safe table. is_safe[c] means that c can be left as such when
- * url-encoded.
- * RFC 2396 defines the list of characters that need to be encoded.
- * Space is treated as an exception by the encoding routine;
- * it's listed as safe here, but is actually changed to '+'.
- */
- static void urlcode_init(void)
- {
- int i;
- unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz-_.!~*'()";
- for (i = 0; safe[i] != ' '; ++i)
- is_safe[safe[i]] = 1;
- }
- void octstr_init(void)
- {
- urlcode_init();
- mutex_init_static(&immutables_mutex);
- immutables_init = 1;
- }
- void octstr_shutdown(void)
- {
- long i, n;
- n = 0;
- for (i = 0; i < MAX_IMMUTABLES; ++i) {
- if (immutables[i] != NULL) {
- gw_free(immutables[i]);
- ++n;
- }
- }
- debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n);
- mutex_destroy(&immutables_mutex);
- }
- Octstr *octstr_create_real(const char *cstr)
- {
- gw_assert(cstr != NULL);
- return octstr_create_from_data(cstr, strlen(cstr));
- }
- Octstr *octstr_create_from_data_real(const char *data, long len)
- {
- Octstr *ostr;
- gw_assert(len >= 0);
- if (data == NULL)
- gw_assert(len == 0);
- ostr = gw_malloc(sizeof(*ostr));
- if (len == 0) {
- ostr->len = 0;
- ostr->size = 0;
- ostr->data = NULL;
- } else {
- ostr->len = len;
- ostr->size = len + 1;
- ostr->data = gw_malloc(ostr->size);
- memcpy(ostr->data, data, len);
- ostr->data[len] = ' ';
- }
- ostr->immutable = 0;
- seems_valid(ostr);
- return ostr;
- }
- Octstr *octstr_imm(const char *cstr)
- {
- Octstr *os;
- long i, index;
- unsigned char *data;
- gw_assert(immutables_init);
- gw_assert(cstr != NULL);
- index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES;
- data = (unsigned char *) cstr;
- mutex_lock(&immutables_mutex);
- i = index;
- for (; ; ) {
- if (immutables[i] == NULL || immutables[i]->data == data)
- break;
- i = (i + 1) % MAX_IMMUTABLES;
- if (i == index)
- panic(0, "Too many immutable strings.");
- }
- os = immutables[i];
- if (os == NULL) {
- /*
- * Can't use octstr_create() because it copies the string,
- * which would break our hashing.
- */
- os = gw_malloc(sizeof(*os));
- os->data = data;
- os->len = strlen(data);
- os->size = os->len + 1;
- os->immutable = 1;
- immutables[i] = os;
- seems_valid(os);
- }
- mutex_unlock(&immutables_mutex);
- return os;
- }
- void octstr_destroy_impl(Octstr *ostr, const char *file,
- long line, const char *func)
- {
- if (ostr != NULL) {
- seems_valid_real(ostr, file, line, func);
- if (!ostr->immutable) {
- gw_free(ostr->data);
- gw_free(ostr);
- }
- }
- }
- void octstr_destroy_item(void *os)
- {
- octstr_destroy(os);
- }
- long octstr_len(Octstr *ostr)
- {
- if (ostr == NULL)
- return 0;
- seems_valid(ostr);
- return ostr->len;
- }
- Octstr *octstr_copy_real(Octstr *ostr, long from, long len)
- {
- seems_valid(ostr);
- gw_assert(from >= 0);
- gw_assert(len >= 0);
- if (from >= ostr->len)
- return octstr_create("");
- if (len > ostr->len - from)
- len = ostr->len - from;
- return octstr_create_from_data(ostr->data + from, len);
- }
- Octstr *octstr_duplicate_real(Octstr *ostr)
- {
- if (ostr == NULL)
- return NULL;
- seems_valid(ostr);
- return octstr_create_from_data(ostr->data, ostr->len);
- }
- Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2)
- {
- Octstr *ostr;
- seems_valid(ostr1);
- seems_valid(ostr2);
- gw_assert(!ostr1->immutable);
- ostr = octstr_create("");
- ostr->len = ostr1->len + ostr2->len;
- ostr->size = ostr->len + 1;
- ostr->data = gw_malloc(ostr->size);
- if (ostr1->len > 0)
- memcpy(ostr->data, ostr1->data, ostr1->len);
- if (ostr2->len > 0)
- memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len);
- ostr->data[ostr->len] = ' ';
- seems_valid(ostr);
- return ostr;
- }
- int octstr_get_char(Octstr *ostr, long pos)
- {
- seems_valid(ostr);
- if (pos >= ostr->len || pos < 0)
- return -1;
- return ostr->data[pos];
- }
- void octstr_set_char(Octstr *ostr, long pos, int ch)
- {
- seems_valid(ostr);
- gw_assert(!ostr->immutable);
- if (pos < ostr->len)
- ostr->data[pos] = ch;
- seems_valid(ostr);
- }
- void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
- {
- gw_assert(buf != NULL);
- seems_valid(ostr);
- if (pos >= ostr->len)
- return;
- if (pos + len > ostr->len)
- len = ostr->len - pos;
- if (len > 0)
- memcpy(buf, ostr->data + pos, len);
- }
- char *octstr_get_cstr_real(Octstr *ostr, const char *file, long line,
- const char *func)
- {
- seems_valid_real(ostr, file, line, func);
- if (ostr->len == 0)
- return "";
- return ostr->data;
- }
- void octstr_append_from_hex(Octstr *ostr, char *hex)
- {
- Octstr *output;
- seems_valid(ostr);
- gw_assert(!ostr->immutable);
- output = octstr_create(hex);
- octstr_hex_to_binary(output);
- octstr_append(ostr, output);
- octstr_destroy(output);
- }
- void octstr_binary_to_hex(Octstr *ostr, int uppercase)
- {
- unsigned char *hexits;
- long i;
- seems_valid(ostr);
- gw_assert(!ostr->immutable);
- if (ostr->len == 0)
- return;
- hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
- octstr_grow(ostr, ostr->len * 2);
- /* In-place modification must be done back-to-front to avoid
- * overwriting the data while we read it. Even the order of
- * the two assignments is important, to get i == 0 right. */
- for (i = ostr->len - 1; i >= 0; i--) {
- ostr->data[i * 2 + 1] = hexits[ostr->data[i] % 16];
- ostr->data[i * 2] = hexits[(ostr->data[i] / 16) & 0xf];
- }
- ostr->len = ostr->len * 2;
- ostr->data[ostr->len] = ' ';
- seems_valid(ostr);
- }
- int octstr_hex_to_binary(Octstr *ostr)
- {
- long len, i;
- unsigned char *p;
- seems_valid(ostr);
- gw_assert(!ostr->immutable);
- if (ostr->len == 0)
- return 0;
- /* Check if it's in the right format */
- if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit))
- return -1;
- len = ostr->len;
- /* Convert ascii data to binary values */
- for (i = 0, p = ostr->data; i < len; i++, p++) {
- if (*p >= '0' && *p <= '9')
- *p -= '0';
- else if (*p >= 'a' && *p <= 'f')
- *p = *p - 'a' + 10;
- else if (*p >= 'A' && *p <= 'F')
- *p = *p - 'A' + 10;
- else {
- /* isxdigit checked the whole string, so we should
- * not be able to get here. */
- gw_assert(0);
- *p = 0;
- }
- }
- /* De-hexing will compress data by factor of 2 */
- len = ostr->len / 2;
- for (i = 0; i < len; i++) {
- ostr->data[i] = ostr->data[i * 2] * 16 | ostr->data[i * 2 + 1];
- }
- ostr->len = len;
- ostr->data[len] = ' ';
- seems_valid(ostr);
- return 0;
- }
- void octstr_binary_to_base64(Octstr *ostr)
- {
- static const unsigned char base64[64] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- long triplets;
- long lines;
- long orig_len;
- unsigned char *data;
- long from, to;
- int left_on_line;
- seems_valid(ostr);
- gw_assert(!ostr->immutable);
- if (ostr->len == 0) {
- /* Always terminate with CR LF */
- octstr_insert(ostr, octstr_imm("