Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 - 2005 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
*/
/* $Id$ */
-#include "silcincludes.h"
+#include "silc.h"
#include "silcstrutil.h"
static unsigned char pem_enc[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-/* Encodes data into PEM encoding. Returns NULL terminated PEM encoded
+/* Encodes data into Base 64 encoding. Returns NULL terminated base 64 encoded
data string. */
-char *silc_pem_encode(unsigned char *data, SilcUInt32 len)
+char *silc_base64_encode(unsigned char *data, SilcUInt32 len)
{
int i, j;
SilcUInt32 bits, c, char_count;
/* Same as above but puts newline ('\n') every 72 characters. */
-char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len)
+char *silc_base64_encode_file(unsigned char *data, SilcUInt32 data_len)
{
int i, j;
SilcUInt32 len, cols;
char *pem, *pem2;
- pem = silc_pem_encode(data, data_len);
+ pem = silc_base64_encode(data, data_len);
len = strlen(pem);
pem2 = silc_calloc(len + (len / 72) + 1, sizeof(*pem2));
return pem2;
}
-/* Decodes PEM into data. Returns the decoded data. */
+/* Decodes Base 64 into data. Returns the decoded data. */
-unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
- SilcUInt32 *ret_len)
+unsigned char *silc_base64_decode(unsigned char *base64,
+ SilcUInt32 base64_len,
+ SilcUInt32 *ret_len)
{
int i, j;
SilcUInt32 len, c, char_count, bits;
bits = 0;
j = 0;
- if (!pem_len)
- len = strlen(pem);
+ if (!base64_len)
+ len = strlen(base64);
else
- len = pem_len;
+ len = base64_len;
data = silc_calloc(((len * 6) / 8), sizeof(*data));
for (i = 0; i < len; i++) {
- c = pem[i];
+ c = base64[i];
if (c == '=')
break;
return data;
}
-/* Mime constants and macros */
-#define MIME_VERSION "MIME-Version: "
-#define MIME_VERSION_LEN 14
-#define MIME_CONTENT_TYPE "Content-Type: "
-#define MIME_CONTENT_TYPE_LEN 14
-#define MIME_TRANSFER_ENCODING "Content-Transfer-Encoding: "
-#define MIME_TRANSFER_ENCODING_LEN 27
-
-#define MIME_GET_FIELD(mime, mime_len, field, field_len, \
- dest, dest_size) \
-do { \
- if (dest) { \
- char *f = strstr(mime, field); \
- if (f) { \
- int parse_len; \
- f += field_len; \
- parse_len = (mime_len - (f - (char *)mime)); \
- for (i = 0; i < parse_len; i++) { \
- if ((i == dest_size) || \
- ((f[i] == '\n') && \
- ((i == parse_len - 1) || \
- ((f[i+1] != ' ') && (f[i+1] != '\t')))) || \
- ((f[i] == '\r') && \
- ((i == parse_len - 1) || (f[i+1] == '\n')) && \
- ((i >= parse_len - 2) || \
- ((f[i+2] != ' ') && (f[i+2] != '\t'))))) \
- break; \
- dest[i] = f[i]; \
- } \
- } \
- } \
-} while(0)
-
-/* Parses MIME object and MIME header in it. */
-
-bool
-silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
- char *version, SilcUInt32 version_size,
- char *content_type, SilcUInt32 content_type_size,
- char *transfer_encoding, SilcUInt32 transfer_encoding_size,
- unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len)
-{
- int i;
- unsigned char *tmp;
-
- /* Get the pointer to the data area in the object */
- for (i = 0; i < mime_len; i++) {
- if ((mime_len >= i + 4 &&
- mime[i ] == '\r' && mime[i + 1] == '\n' &&
- mime[i + 2] == '\r' && mime[i + 3] == '\n') ||
- (mime_len >= i + 2 &&
- mime[i ] == '\n' && mime[i + 1] == '\n'))
- break;
- }
- if (i >= mime_len)
- return FALSE;
-
- if (mime_data_ptr)
- *mime_data_ptr = (unsigned char *)mime + i +
- (mime[i] == '\n' ? 2 : 4);
- if (mime_data_len)
- *mime_data_len = mime_len - (i + (mime[i] == '\n' ? 2 : 4));
-
- /* Check for mandatory Content-Type field */
- tmp = strstr(mime, MIME_CONTENT_TYPE);
- if (!tmp || (tmp - mime) >= i)
- return FALSE;
-
- /* Get MIME version, Content-Type and Transfer Encoding fields */
- MIME_GET_FIELD(mime, mime_len,
- MIME_VERSION, MIME_VERSION_LEN,
- version, version_size);
- MIME_GET_FIELD(mime, mime_len,
- MIME_CONTENT_TYPE, MIME_CONTENT_TYPE_LEN,
- content_type, content_type_size);
- MIME_GET_FIELD(mime, mime_len,
- MIME_TRANSFER_ENCODING, MIME_TRANSFER_ENCODING_LEN,
- transfer_encoding, transfer_encoding_size);
-
- return TRUE;
-}
-
/* 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. */
return dest;
}
-/* Checks that the 'identifier' string is valid identifier string
- and does not contain any unassigned or prohibited character. This
- function is used to check for valid nicknames, channel names,
- server names, usernames, hostnames, service names, algorithm names,
- other security property names, and SILC Public Key name. */
-
-unsigned char *silc_identifier_check(const unsigned char *identifier,
- SilcUInt32 identifier_len,
- SilcStringEncoding identifier_encoding,
- SilcUInt32 max_allowed_length,
- SilcUInt32 *out_len)
-{
- unsigned char *utf8s;
- SilcUInt32 utf8s_len;
- SilcStringprepStatus status;
+/* Compares two strings. Strings may include wildcards '*' and '?'.
+ Returns TRUE if strings match. */
- if (!identifier || !identifier_len)
- return NULL;
+int silc_string_compare(char *string1, char *string2)
+{
+ int i;
+ int slen1;
+ int slen2;
+ char *tmpstr1, *tmpstr2;
- if (max_allowed_length && identifier_len > max_allowed_length)
- return NULL;
+ if (!string1 || !string2)
+ return FALSE;
- status = silc_stringprep(identifier, identifier_len,
- identifier_encoding, SILC_IDENTIFIER_PREP, 0,
- &utf8s, &utf8s_len, SILC_STRING_UTF8);
- if (status != SILC_STRINGPREP_OK) {
- SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
- return NULL;
+ 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;
+ }
+
+ /* ? wildcard */
+ if (tmpstr1[i] == '?') {
+ if (!strncmp(tmpstr1, tmpstr2, i)) {
+ if (!(slen1 < i + 1))
+ if (tmpstr1[i + 1] != '?' &&
+ tmpstr1[i + 1] != tmpstr2[i + 1])
+ continue;
+
+ if (!(slen1 < slen2))
+ tmpstr2[i] = '?';
+ }
+ }
}
- if (out_len)
- *out_len = utf8s_len;
+ /* 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;
+ }
- return utf8s;
+ memset(tmpstr1, 0, slen1);
+ memset(tmpstr2, 0, slen2);
+ silc_free(tmpstr1);
+ silc_free(tmpstr2);
+ return FALSE;
}
-/* Same as above but does not allocate memory, just checks the
- validity of the string. */
+/* Splits a string containing separator `ch' and returns an array of the
+ splitted strings. */
-bool silc_identifier_verify(const unsigned char *identifier,
- SilcUInt32 identifier_len,
- SilcStringEncoding identifier_encoding,
- SilcUInt32 max_allowed_length)
+char **silc_string_split(const char *string, char ch, int *ret_count)
{
- SilcStringprepStatus status;
+ char **splitted = NULL, sep[1], *item, *cp;
+ int i = 0, len;
- if (!identifier || !identifier_len)
- return FALSE;
+ if (!string)
+ return NULL;
+ if (!ret_count)
+ return NULL;
- if (max_allowed_length && identifier_len > max_allowed_length)
- return FALSE;
+ splitted = silc_calloc(1, sizeof(*splitted));
+ if (!splitted)
+ return NULL;
- status = silc_stringprep(identifier, identifier_len,
- identifier_encoding, SILC_IDENTIFIER_PREP, 0,
- NULL, NULL, SILC_STRING_UTF8);
- if (status != SILC_STRINGPREP_OK) {
- SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
- return FALSE;
+ if (!strchr(string, ch)) {
+ splitted[0] = silc_memdup(string, strlen(string));
+ *ret_count = 1;
+ return splitted;
}
- return TRUE;
+ sep[0] = ch;
+ cp = (char *)string;
+ while(cp) {
+ len = strcspn(cp, sep);
+ item = silc_memdup(cp, len);
+ if (!item) {
+ silc_free(splitted);
+ return NULL;
+ }
+
+ cp += len;
+ if (strlen(cp) == 0)
+ cp = NULL;
+ else
+ cp++;
+
+ splitted = silc_realloc(splitted, (i + 1) * sizeof(*splitted));
+ if (!splitted)
+ return NULL;
+ splitted[i++] = item;
+ }
+ *ret_count = i;
+
+ return splitted;
}
-unsigned char *silc_channel_name_check(const unsigned char *identifier,
- SilcUInt32 identifier_len,
- SilcStringEncoding identifier_encoding,
- SilcUInt32 max_allowed_length,
- SilcUInt32 *out_len)
+/* 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. */
+
+char *silc_string_regexify(const char *string)
{
- unsigned char *utf8s;
- SilcUInt32 utf8s_len;
- SilcStringprepStatus status;
+ int i, len, count;
+ char *regex;
- if (!identifier || !identifier_len)
+ if (!string)
return NULL;
- if (max_allowed_length && identifier_len > max_allowed_length)
- return NULL;
+ 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 '^' */
+ }
- status = silc_stringprep(identifier, identifier_len,
- identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
- &utf8s, &utf8s_len, SILC_STRING_UTF8);
- if (status != SILC_STRINGPREP_OK) {
- SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+ regex = silc_calloc(len + count + 1, sizeof(*regex));
+ if (!regex)
return NULL;
+
+ 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];
}
- if (out_len)
- *out_len = utf8s_len;
+ regex[count++] = ')';
+ regex[count] = '$';
- return utf8s;
+ return regex;
}
-/* Same as above but does not allocate memory, just checks the
- validity of the string. */
+/* 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'. */
-bool silc_channel_name_verify(const unsigned char *identifier,
- SilcUInt32 identifier_len,
- SilcStringEncoding identifier_encoding,
- SilcUInt32 max_allowed_length)
+char *silc_string_regex_combine(const char *string1, const char *string2)
{
- SilcStringprepStatus status;
+ char *tmp;
+ int len1, len2;
- if (!identifier || !identifier_len)
- return FALSE;
+ if (!string1 || !string2)
+ return NULL;
- if (max_allowed_length && identifier_len > max_allowed_length)
- return FALSE;
+ len1 = strlen(string1);
+ len2 = strlen(string2);
+
+ tmp = silc_calloc(2 + len1 + len2, sizeof(*tmp));
+ strncat(tmp, string1, len1 - 2);
+ strncat(tmp, "|", 1);
+ strncat(tmp, string2 + 1, len2 - 1);
- status = silc_stringprep(identifier, identifier_len,
- identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
- NULL, NULL, SILC_STRING_UTF8);
- if (status != SILC_STRINGPREP_OK) {
- SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+ return tmp;
+}
+
+/* Matches the two strings and returns TRUE if the strings match. */
+
+int silc_string_regex_match(const char *regex, const char *string)
+{
+ regex_t preg;
+ int ret = FALSE;
+
+ if (regcomp(&preg, regex, REG_NOSUB | REG_EXTENDED) != 0)
return FALSE;
- }
- return TRUE;
+ if (regexec(&preg, string, 0, NULL, 0) == 0)
+ ret = TRUE;
+
+ regfree(&preg);
+
+ return ret;
+}
+
+/* Do regex match to the two strings `string1' and `string2'. If the
+ `string2' matches the `string1' this returns TRUE. */
+
+int silc_string_match(const char *string1, const char *string2)
+{
+ char *s1;
+ int ret = FALSE;
+
+ if (!string1 || !string2)
+ return ret;
+
+ s1 = silc_string_regexify(string1);
+ ret = silc_string_regex_match(s1, string2);
+ silc_free(s1);
+
+ return ret;
}