⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 octstr.c.debug

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 DEBUG
📖 第 1 页 / 共 4 页
字号:
/* * 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 '\0'. 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 1024static 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] != '\0'; ++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] = '\0';    }    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] = '\0';    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] = '\0';    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] = '\0';    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("\015\012"), 0);        return;    }    /* The lines must be 76 characters each (or less), and each     * triplet will expand to 4 characters, so we can fit 19     * triplets on one line.  We need a CR LF after each line,     * which will add 2 octets per 19 triplets (rounded up). */    triplets = (ostr->len + 2) / 3;   /* round up */    lines = (triplets + 18) / 19;    octstr_grow(ostr, triplets * 4 + lines * 2);    orig_len = ostr->len;    data = ostr->data;    ostr->len = triplets * 4 + lines * 2;    data[ostr->len] = '\0';    /* This function works back-to-front, so that encoded data will     * not overwrite source data.     * from points to the start of the last triplet (which may be     * an odd-sized one), and to points to the start of where the     * last quad should go.  */    from = (triplets - 1) * 3;    to = (triplets - 1) * 4 + (lines - 1) * 2;    /* First write the CR LF after the last quad */    data[to + 5] = 10;   /* LF */    data[to + 4] = 13;   /* CR */    left_on_line = triplets - ((lines - 1) * 19);    /* base64 encoding is in 3-octet units.  To handle leftover     * octets, conceptually we have to zero-pad up to the next     * 6-bit unit, and pad with '=' characters for missing 6-bit     * units.     * We do it by first completing the first triplet with      * zero-octets, and after the loop replacing some of the     * result characters with '=' characters.     * There is enough room for this, because even with a 1 or 2     * octet source string, space for four octets of output     * will be reserved.     */    switch (orig_len % 3) {    case 0:        break;    case 1:        data[orig_len] = 0;        data[orig_len + 1] = 0;        break;    case 2:        data[orig_len + 1] = 0;        break;    }    /* Now we only have perfect triplets. */    while (from >= 0) {        long whole_triplet;        /* Add a newline, if necessary */        if (left_on_line == 0) {            to -= 2;            data[to + 5] = 10;  /* LF */            data[to + 4] = 13;  /* CR */            left_on_line = 19;        }        whole_triplet = (data[from] << 16) |                        (data[from + 1] << 8) |                        data[from + 2];        data[to + 3] = base64[whole_triplet % 64];        data[to + 2] = base64[(whole_triplet >> 6) % 64];        data[to + 1] = base64[(whole_triplet >> 12) % 64];        data[to] = base64[(whole_triplet >> 18) % 64];        to -= 4;        from -= 3;        left_on_line--;    }    gw_assert(left_on_line == 0);    gw_assert(from == -3);    gw_assert(to == -4);    /* Insert padding characters in the last quad.  Remember that     * there is a CR LF between the last quad and the end of the     * string. */    switch (orig_len % 3) {    case 0:        break;    case 1:        gw_assert(data[ostr->len - 3] == 'A');        gw_assert(data[ostr->len - 4] == 'A');        data[ostr->len - 3] = '=';        data[ostr->len - 4] = '=';        break;    case 2:        gw_assert(data[ostr->len - 3] == 'A');        data[ostr->len - 3] = '=';        break;    }    seems_valid(ostr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -