Added preliminary Symbian support.
[silc.git] / lib / silcutil / silcstrutil.c
index 8fddd0b22a7ebdebdeabbfbcd54cebce110eb3fb..5ba4c02e271d22d1a8d4731e8d67a475d22fc69a 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -18,7 +18,7 @@
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcstrutil.h"
 
 static unsigned char pem_enc[64] =
@@ -170,87 +170,14 @@ unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
   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. */
-
-SilcBool
-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;
+#ifndef HAVE_SNPRINTF
+/* Outputs string according to the `format'. */
 
-  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;
+int silc_snprintf(char *str, SilcUInt32 size, const char *format, ...)
+{
 
-  /* 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;
 }
+#endif /* HAVE_SNPRINTF */
 
 /* 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
@@ -274,122 +201,124 @@ char *silc_strncat(char *dest, SilcUInt32 dest_size,
   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;
-
-  if (!identifier || !identifier_len)
-    return NULL;
-
-  if (max_allowed_length && identifier_len > max_allowed_length)
-    return NULL;
-
-  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;
-  }
-
-  if (out_len)
-    *out_len = utf8s_len;
-
-  return utf8s;
-}
-
-/* Same as above but does not allocate memory, just checks the
-   validity of the string. */
+/* Compares two strings. Strings may include wildcards '*' and '?'.
+   Returns TRUE if strings match. */
 
-SilcBool silc_identifier_verify(const unsigned char *identifier,
-                           SilcUInt32 identifier_len,
-                           SilcStringEncoding identifier_encoding,
-                           SilcUInt32 max_allowed_length)
+int silc_string_compare(char *string1, char *string2)
 {
-  SilcStringprepStatus status;
+  int i;
+  int slen1;
+  int slen2;
+  char *tmpstr1, *tmpstr2;
 
-  if (!identifier || !identifier_len)
+  if (!string1 || !string2)
     return FALSE;
 
-  if (max_allowed_length && identifier_len > max_allowed_length)
-    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;
+      }
+
+    /* ? 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] = '?';
+      }
+    }
+  }
 
-  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 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 TRUE;
+  memset(tmpstr1, 0, slen1);
+  memset(tmpstr2, 0, slen2);
+  silc_free(tmpstr1);
+  silc_free(tmpstr2);
+  return FALSE;
 }
 
-unsigned char *silc_channel_name_check(const unsigned char *identifier,
-                                      SilcUInt32 identifier_len,
-                                      SilcStringEncoding identifier_encoding,
-                                      SilcUInt32 max_allowed_length,
-                                      SilcUInt32 *out_len)
+/* Splits a string containing separator `ch' and returns an array of the
+   splitted strings. */
+
+char **silc_string_split(const char *string, char ch, int *ret_count)
 {
-  unsigned char *utf8s;
-  SilcUInt32 utf8s_len;
-  SilcStringprepStatus status;
+  char **splitted = NULL, sep[1], *item, *cp;
+  int i = 0, len;
 
-  if (!identifier || !identifier_len)
+  if (!string)
     return NULL;
-
-  if (max_allowed_length && identifier_len > max_allowed_length)
+  if (!ret_count)
     return NULL;
 
-  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));
+  splitted = silc_calloc(1, sizeof(*splitted));
+  if (!splitted)
     return NULL;
-  }
-
-  if (out_len)
-    *out_len = utf8s_len;
 
-  return utf8s;
-}
-
-/* Same as above but does not allocate memory, just checks the
-   validity of the string. */
-
-SilcBool silc_channel_name_verify(const unsigned char *identifier,
-                             SilcUInt32 identifier_len,
-                             SilcStringEncoding identifier_encoding,
-                             SilcUInt32 max_allowed_length)
-{
-  SilcStringprepStatus status;
+  if (!strchr(string, ch)) {
+    splitted[0] = silc_memdup(string, strlen(string));
+    *ret_count = 1;
+    return splitted;
+  }
 
-  if (!identifier || !identifier_len)
-    return FALSE;
+  sep[0] = ch;
+  cp = (char *)string;
+  while(cp) {
+    len = strcspn(cp, sep);
+    item = silc_memdup(cp, len);
+    if (!item) {
+      silc_free(splitted);
+      return NULL;
+    }
 
-  if (max_allowed_length && identifier_len > max_allowed_length)
-    return FALSE;
+    cp += len;
+    if (strlen(cp) == 0)
+      cp = NULL;
+    else
+      cp++;
 
-  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 FALSE;
+    splitted = silc_realloc(splitted, (i + 1) * sizeof(*splitted));
+    if (!splitted)
+      return NULL;
+    splitted[i++] = item;
   }
+  *ret_count = i;
 
-  return TRUE;
+  return splitted;
 }