X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcstrutil.c;h=3251c2b0a4d47c43255ca71746e17cf899ffedb4;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=d1f04883d69d99818031a839b35feda68cc30f8c;hpb=b3e67d3dfa6409755be33f352b5a86fbb094a570;p=silc.git diff --git a/lib/silcutil/silcstrutil.c b/lib/silcutil/silcstrutil.c index d1f04883..3251c2b0 100644 --- a/lib/silcutil/silcstrutil.c +++ b/lib/silcutil/silcstrutil.c @@ -1,10 +1,10 @@ /* - silcstrutil.c + silcstrutil.c Author: Pekka Riikonen - Copyright (C) 2002 Pekka Riikonen + Copyright (C) 2002 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,393 +18,253 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcstrutil.h" -static unsigned char pem_enc[64] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +/* Concatenates the `src' into `dest'. If `src_len' is more than the + size of the `dest' (minus NULL at the end) the `src' will be + truncated to fit. */ -/* Encodes data into PEM encoding. Returns NULL terminated PEM encoded - data string. Note: This is originally public domain code and is - still PD. */ - -char *silc_pem_encode(unsigned char *data, SilcUInt32 len) +char *silc_strncat(char *dest, SilcUInt32 dest_size, + const char *src, SilcUInt32 src_len) { - int i, j; - SilcUInt32 bits, c, char_count; - char *pem; - - char_count = 0; - bits = 0; - j = 0; + int len; - pem = silc_calloc(((len * 8 + 5) / 6) + 5, sizeof(*pem)); - - for (i = 0; i < len; i++) { - c = data[i]; - bits += c; - char_count++; - - if (char_count == 3) { - pem[j++] = pem_enc[bits >> 18]; - pem[j++] = pem_enc[(bits >> 12) & 0x3f]; - pem[j++] = pem_enc[(bits >> 6) & 0x3f]; - pem[j++] = pem_enc[bits & 0x3f]; - bits = 0; - char_count = 0; - } else { - bits <<= 8; - } - } + dest[dest_size - 1] = '\0'; - if (char_count != 0) { - bits <<= 16 - (8 * char_count); - pem[j++] = pem_enc[bits >> 18]; - pem[j++] = pem_enc[(bits >> 12) & 0x3f]; - - if (char_count == 1) { - pem[j++] = '='; - pem[j] = '='; - } else { - pem[j++] = pem_enc[(bits >> 6) & 0x3f]; - pem[j] = '='; - } + len = dest_size - 1 - strlen(dest); + if (len < src_len) { + if (len > 0) + strncat(dest, src, len); + } else { + strncat(dest, src, src_len); } - return pem; + return dest; } -/* Same as above but puts newline ('\n') every 72 characters. */ +/* Compares two strings. Strings may include wildcards '*' and '?'. + Returns TRUE if strings match. */ -char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len) +int silc_string_compare(char *string1, char *string2) { - int i, j; - SilcUInt32 len, cols; - char *pem, *pem2; - - pem = silc_pem_encode(data, data_len); - len = strlen(pem); + int i; + int slen1; + int slen2; + char *tmpstr1, *tmpstr2; + + if (!string1 || !string2) + return FALSE; + + slen1 = strlen(string1); + slen2 = strlen(string2); + + /* See if they are same already */ + if (!strncmp(string1, string2, slen2) && slen2 == slen1) + return TRUE; + + if (slen2 < slen1) + if (!strchr(string1, '*')) + return FALSE; + + /* Take copies of the original strings as we will change them */ + tmpstr1 = silc_calloc(slen1 + 1, sizeof(char)); + memcpy(tmpstr1, string1, slen1); + tmpstr2 = silc_calloc(slen2 + 1, sizeof(char)); + memcpy(tmpstr2, string2, slen2); + + for (i = 0; i < slen1; i++) { + + /* * wildcard. Only one * wildcard is possible. */ + if (tmpstr1[i] == '*') + if (!strncmp(tmpstr1, tmpstr2, i)) { + memset(tmpstr2, 0, slen2); + strncpy(tmpstr2, tmpstr1, i); + break; + } - pem2 = silc_calloc(len + (len / 72) + 1, sizeof(*pem2)); + /* ? wildcard */ + if (tmpstr1[i] == '?') { + if (!strncmp(tmpstr1, tmpstr2, i)) { + if (!(slen1 < i + 1)) + if (tmpstr1[i + 1] != '?' && + tmpstr1[i + 1] != tmpstr2[i + 1]) + continue; - for (i = 0, j = 0, cols = 1; i < len; i++, cols++) { - if (cols == 72) { - pem2[i] = '\n'; - cols = 0; - len++; - continue; + if (!(slen1 < slen2)) + tmpstr2[i] = '?'; + } } + } - pem2[i] = pem[j++]; + /* if using *, remove it */ + if (strchr(tmpstr1, '*')) + *strchr(tmpstr1, '*') = 0; + + if (!strcmp(tmpstr1, tmpstr2)) { + memset(tmpstr1, 0, slen1); + memset(tmpstr2, 0, slen2); + silc_free(tmpstr1); + silc_free(tmpstr2); + return TRUE; } - silc_free(pem); - return pem2; + memset(tmpstr1, 0, slen1); + memset(tmpstr2, 0, slen2); + silc_free(tmpstr1); + silc_free(tmpstr2); + return FALSE; } -/* Decodes PEM into data. Returns the decoded data. Note: This is - originally public domain code and is still PD. */ +/* Splits a string containing separator `ch' and returns an array of the + splitted strings. */ -unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len, - SilcUInt32 *ret_len) +char **silc_string_split(const char *string, char ch, int *ret_count) { - int i, j; - SilcUInt32 len, c, char_count, bits; - unsigned char *data; - static char ialpha[256], decoder[256]; - - for (i = 64 - 1; i >= 0; i--) { - ialpha[pem_enc[i]] = 1; - decoder[pem_enc[i]] = i; + char **splitted = NULL, sep[2], *item, *cp; + int i = 0, len; + + if (!string || !ret_count) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; } - char_count = 0; - bits = 0; - j = 0; + splitted = silc_calloc(1, sizeof(*splitted)); + if (!splitted) + return NULL; - if (!pem_len) - len = strlen(pem); - else - len = pem_len; + if (!strchr(string, ch)) { + splitted[0] = silc_memdup(string, strlen(string)); + *ret_count = 1; + return splitted; + } - data = silc_calloc(((len * 6) / 8), sizeof(*data)); + sep[0] = ch; + sep[1] = '\0'; + cp = (char *)string; + while (cp) { + len = strcspn(cp, sep); + if (!len) + break; - for (i = 0; i < len; i++) { - c = pem[i]; + item = silc_memdup(cp, len); + if (!item) { + silc_free(splitted); + return NULL; + } - if (c == '=') - break; + cp += len; + if (strlen(cp) == 0) + cp = NULL; + else + cp++; - if (c > 127 || !ialpha[c]) - continue; + splitted[i++] = item; - bits += decoder[c]; - char_count++; - - if (char_count == 4) { - data[j++] = bits >> 16; - data[j++] = (bits >> 8) & 0xff; - data[j++] = bits & 0xff; - bits = 0; - char_count = 0; - } else { - bits <<= 6; + if (cp) { + splitted = silc_realloc(splitted, (i + 1) * sizeof(*splitted)); + if (!splitted) + return NULL; } } + *ret_count = i; - switch(char_count) { - case 1: - silc_free(data); - return NULL; - break; - case 2: - data[j++] = bits >> 10; - break; - case 3: - data[j++] = bits >> 16; - data[j++] = (bits >> 8) & 0xff; - break; - } - - if (ret_len) - *ret_len = j; - - return data; + return splitted; } -/* Encodes the string `bin' of which encoding is `bin_encoding' to the - UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'. - Returns the length of the UTF-8 encoded string, or zero (0) on error. - By default `bin_encoding' is ASCII, and the caller needs to know the - encoding of the input string if it is anything else. */ +/* Inspects the `string' for wildcards and returns regex string that can + be used by the GNU regex library. A comma (`,') in the `string' means + that the string is list. */ -SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len, - SilcStringEncoding bin_encoding, - unsigned char *utf8, SilcUInt32 utf8_size) +char *silc_string_regexify(const char *string) { - SilcUInt32 enclen = 0, i, charval = 0; + int i, len, count; + char *regex; - if (!bin || !bin_len) - return 0; + if (!string) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } - for (i = 0; i < bin_len; i++) { - switch (bin_encoding) { - case SILC_STRING_ASCII: - charval = bin[i]; - break; - case SILC_STRING_ASCII_ESC: - break; - case SILC_STRING_BMP: - break; - case SILC_STRING_UNIVERSAL: - break; - } + len = strlen(string); + count = 4; + for (i = 0; i < len; i++) { + if (string[i] == '*' || string[i] == '?') + count++; /* Will add '.' */ + if (string[i] == ',') + count += 2; /* Will add '|' and '^' */ + } - if (charval < 0x80) { - if (utf8) { - if (enclen > utf8_size) - return 0; + regex = silc_calloc(len + count + 1, sizeof(*regex)); + if (!regex) + return NULL; - utf8[enclen] = (unsigned char)charval; - } - enclen++; - } else if (charval < 0x800) { - if (utf8) { - if (enclen + 2 > utf8_size) - return 0; - - utf8[enclen ] = (unsigned char )(((charval >> 6) & 0x1f) | 0xc0); - utf8[enclen + 1] = (unsigned char )((charval & 0x3f) | 0x80); - } - enclen += 2; - } else if (charval < 0x10000) { - if (utf8) { - if (enclen + 3 > utf8_size) - return 0; - - utf8[enclen ] = (unsigned char )(((charval >> 12) & 0xf) | 0xe0); - utf8[enclen + 1] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80); - utf8[enclen + 2] = (unsigned char )((charval & 0x3f) | 0x80); - } - enclen += 3; - } else if (charval < 0x200000) { - if (utf8) { - if (enclen + 4 > utf8_size) - return 0; - - utf8[enclen ] = (unsigned char )(((charval >> 18) & 0x7) | 0xf0); - utf8[enclen + 1] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80); - utf8[enclen + 2] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80); - utf8[enclen + 3] = (unsigned char )((charval & 0x3f) | 0x80); - } - enclen += 4; - } else if (charval < 0x4000000) { - if (utf8) { - if (enclen + 5 > utf8_size) - return 0; - - utf8[enclen ] = (unsigned char )(((charval >> 24) & 0x3) | 0xf8); - utf8[enclen + 1] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80); - utf8[enclen + 2] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80); - utf8[enclen + 3] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80); - utf8[enclen + 4] = (unsigned char )((charval & 0x3f) | 0x80); - } - enclen += 5; - } else { - if (utf8) { - if (enclen + 6 > utf8_size) - return 0; - - utf8[enclen ] = (unsigned char )(((charval >> 30) & 0x1) | 0xfc); - utf8[enclen + 1] = (unsigned char )(((charval >> 24) & 0x3f) | 0x80); - utf8[enclen + 2] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80); - utf8[enclen + 3] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80); - utf8[enclen + 4] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80); - utf8[enclen + 5] = (unsigned char )((charval & 0x3f) | 0x80); - } - enclen += 6; + count = 0; + regex[count++] = '('; + regex[count++] = '^'; + + for (i = 0; i < len; i++) { + if (string[i] == '*' || string[i] == '?') { + regex[count] = '.'; + count++; + } else if (string[i] == ',') { + if (i + 2 == len) + continue; + regex[count++] = '|'; + regex[count++] = '^'; + continue; } + + regex[count++] = string[i]; } - return enclen; + regex[count++] = ')'; + regex[count] = '$'; + + return regex; } -/* Decodes UTF-8 encoded string `utf8' to string of which encoding is - to be `bin_encoding', into the `bin' buffer of size of `bin_size'. - Returns the length of the decoded buffer, or zero (0) on error. - By default `bin_encoding' is ASCII, and the caller needs to know to - which encoding the output string is to be encoded if ASCII is not - desired. */ +/* Combines two regex strings into one regex string so that they can be + used as one by the GNU regex library. The `string2' is combine into + the `string1'. */ -SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len, - SilcStringEncoding bin_encoding, - unsigned char *bin, SilcUInt32 bin_size) +char *silc_string_regex_combine(const char *string1, const char *string2) { - SilcUInt32 enclen = 0, i, charval; - - if (!utf8 || !utf8_len) - return 0; - - for (i = 0; i < utf8_len; i++) { - if ((utf8[i] & 0x80) == 0x00) { - charval = utf8[i] & 0x7f; - } else if ((utf8[i] & 0xe0) == 0xc0) { - if (utf8_len < 2) - return 0; - - if ((utf8[i + 1] & 0xc0) != 0x80) - return 0; - - charval = (utf8[i++] & 0x1f) << 6; - charval |= utf8[i] & 0x3f; - if (charval < 0x80) - return 0; - } else if ((utf8[i] & 0xf0) == 0xe0) { - if (utf8_len < 3) - return 0; - - if (((utf8[i + 1] & 0xc0) != 0x80) || - ((utf8[i + 2] & 0xc0) != 0x80)) - return 0; - - charval = (utf8[i++] & 0xf) << 12; - charval |= (utf8[i++] & 0x3f) << 6; - charval |= utf8[i] & 0x3f; - if (charval < 0x800) - return 0; - } else if ((utf8[i] & 0xf8) == 0xf0) { - if (utf8_len < 4) - return 0; - - if (((utf8[i + 1] & 0xc0) != 0x80) || - ((utf8[i + 2] & 0xc0) != 0x80) || - ((utf8[i + 3] & 0xc0) != 0x80)) - return 0; - - charval = ((SilcUInt32)(utf8[i++] & 0x7)) << 18; - charval |= (utf8[i++] & 0x3f) << 12; - charval |= (utf8[i++] & 0x3f) << 6; - charval |= utf8[i] & 0x3f; - if (charval < 0x10000) - return 0; - } else if ((utf8[i] & 0xfc) == 0xf8) { - if (utf8_len < 5) - return 0; - - if (((utf8[i + 1] & 0xc0) != 0x80) || - ((utf8[i + 2] & 0xc0) != 0x80) || - ((utf8[i + 3] & 0xc0) != 0x80) || - ((utf8[i + 4] & 0xc0) != 0x80)) - return 0; - - charval = ((SilcUInt32)(utf8[i++] & 0x3)) << 24; - charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18; - charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12; - charval |= (utf8[i++] & 0x3f) << 6; - charval |= utf8[i] & 0x3f; - if (charval < 0x200000) - return 0; - } else if ((utf8[i] & 0xfe) == 0xfc) { - if (utf8_len < 6) - return 0; - - if (((utf8[i + 1] & 0xc0) != 0x80) || - ((utf8[i + 2] & 0xc0) != 0x80) || - ((utf8[i + 3] & 0xc0) != 0x80) || - ((utf8[i + 4] & 0xc0) != 0x80) || - ((utf8[i + 5] & 0xc0) != 0x80)) - return 0; - - charval = ((SilcUInt32)(utf8[i++] & 0x1)) << 30; - charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 24; - charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18; - charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12; - charval |= (utf8[i++] & 0x3f) << 6; - charval |= utf8[i] & 0x3f; - if (charval < 0x4000000) - return 0; - } else { - return 0; - } - - switch (bin_encoding) { - case SILC_STRING_ASCII: - if (bin) { - if (enclen + 1 > bin_size) - return 0; + char *tmp; + int len1, len2; - bin[enclen] = (unsigned char)charval; - } - enclen++; - break; - case SILC_STRING_ASCII_ESC: - return 0; - break; - case SILC_STRING_BMP: - return 0; - break; - case SILC_STRING_UNIVERSAL: - return 0; - break; - } + if (!string1 || !string2) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; } - return enclen; -} + len1 = strlen(string1); + len2 = strlen(string2); -/* Returns the length of UTF-8 encoded string if the `bin' of - encoding of `bin_encoding' is encoded with silc_utf8_encode. */ + tmp = silc_calloc(2 + len1 + len2, sizeof(*tmp)); + strncat(tmp, string1, len1 - 2); + strncat(tmp, "|", 1); + strncat(tmp, string2 + 1, len2 - 1); -SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len, - SilcStringEncoding bin_encoding) -{ - return silc_utf8_encode(bin, bin_len, bin_encoding, NULL, 0); + return tmp; } -/* Returns TRUE if the `utf8' string of length of `utf8_len' is valid - UTF-8 encoded string, FALSE if it is not UTF-8 encoded string. */ +/* Do regex match to the two strings `string1' and `string2'. If the + `string2' matches the `string1' this returns TRUE. */ -bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len) +int silc_string_match(const char *string1, const char *string2) { - return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0; + char *s1; + int ret = FALSE; + + if (!string1 || !string2) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return ret; + } + + s1 = silc_string_regexify(string1); + ret = silc_string_regex_match(s1, string2); + silc_free(s1); + + return ret; }