Watcher list support added.
[silc.git] / lib / silcutil / silcutil.c
index 1473fc80d1619f8dfb748d59f294da60f5e9f018..f622bed5eb341807ead387dc4463b032edefb2b7 100644 (file)
@@ -94,166 +94,32 @@ char *silc_get_time()
 
 /* Converts string to capital characters. */
 
-char *silc_to_upper(char *string)
+bool silc_to_upper(const char *string, char *dest, SilcUInt32 dest_size)
 {
   int i;
-  char *ret = silc_calloc(strlen(string) + 1, sizeof(char));
 
-  for (i = 0; i < strlen(string); i++)
-    ret[i] = toupper(string[i]);
-
-  return ret;
-}
-
-static unsigned char pem_enc[64] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/* 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_encode_pem(unsigned char *data, SilcUInt32 len)
-{
-  int i, j;
-  SilcUInt32 bits, c, char_count;
-  char *pem;
-
-  char_count = 0;
-  bits = 0;
-  j = 0;
-
-  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;
-    }
-  }
-
-  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] = '=';
-    }
-  }
-
-  return pem;
-}
-
-/* Same as above but puts newline ('\n') every 72 characters. */
-
-char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len)
-{
-  int i, j;
-  SilcUInt32 len, cols;
-  char *pem, *pem2;
-
-  pem = silc_encode_pem(data, data_len);
-  len = strlen(pem);
-
-  pem2 = silc_calloc(len + (len / 72) + 1, sizeof(*pem2));
-
-  for (i = 0, j = 0, cols = 1; i < len; i++, cols++) {
-    if (cols == 72) {
-      pem2[i] = '\n';
-      cols = 0;
-      len++;
-      continue;
-    }
+  if (strlen(string) > dest_size)
+    return FALSE;
 
-    pem2[i] = pem[j++];
-  }
+  for (i = 0; i < strlen(string); i++)
+    dest[i] = toupper(string[i]);
 
-  silc_free(pem);
-  return pem2;
+  return TRUE;
 }
 
-/* Decodes PEM into data. Returns the decoded data. Note: This is
-   originally public domain code and is still PD. */
+/* Converts string to lower letter characters. */
 
-unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len,
-                              SilcUInt32 *ret_len)
+bool silc_to_lower(const char *string, char *dest, SilcUInt32 dest_size)
 {
-  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_count = 0;
-  bits = 0;
-  j = 0;
-
-  if (!pem_len)
-    len = strlen(pem);
-  else
-    len = pem_len;
-
-  data = silc_calloc(((len * 6) / 8), sizeof(*data));
-
-  for (i = 0; i < len; i++) {
-    c = pem[i];
-
-    if (c == '=')
-      break;
-
-    if (c > 127 || !ialpha[c])
-      continue;
-
-    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;
-    }
-  }
+  int 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 (strlen(string) > dest_size)
+    return FALSE;
 
-  if (ret_len)
-    *ret_len = j;
+  for (i = 0; i < strlen(string); i++)
+    dest[i] = tolower(string[i]);
 
-  return data;
+  return TRUE;
 }
 
 /* Parse userfqdn string which is in user@fqdn format. */
@@ -313,7 +179,10 @@ void silc_parse_command_line(unsigned char *buffer,
 
   /* Get the command first */
   len = strcspn(cp, " ");
-  tmp = silc_to_upper((char *)cp);
+  tmp = silc_calloc(strlen(cp) + 1, sizeof(*tmp));
+  if (!tmp)
+    return;
+  silc_to_upper(cp, tmp, strlen(cp));
   (*parsed)[0] = silc_calloc(len + 1, sizeof(char));
   memcpy((*parsed)[0], tmp, len);
   silc_free(tmp);
@@ -619,22 +488,12 @@ SilcUInt32 silc_hash_id(void *key, void *user_context)
   case SILC_ID_CLIENT:
     {
       SilcClientID *id = (SilcClientID *)key;
-      SilcUInt32 g;
 
       /* The client ID is hashed by hashing the hash of the ID
         (which is a truncated MD5 hash of the nickname) so that we
         can access the entry from the cache with both Client ID but
         with just a hash from the ID as well. */
-
-      for (i = 0; i < sizeof(id->hash); i++) {
-       h = (h << 4) + id->hash[i];
-       if ((g = h & 0xf0000000)) {
-         h = h ^ (g >> 24);
-         h = h ^ g;
-       }
-      }
-
-      return h;
+      return silc_hash_client_id_hash(id->hash, NULL);
     }
     break;
   case SILC_ID_SERVER:
@@ -666,6 +525,25 @@ SilcUInt32 silc_hash_id(void *key, void *user_context)
   return h;
 }
 
+/* Hash Client ID's hash. */
+
+SilcUInt32 silc_hash_client_id_hash(void *key, void *user_context)
+{
+  int i;
+  unsigned char *hash = key;
+  SilcUInt32 h = 0, g;
+
+  for (i = 0; i < CLIENTID_HASH_LEN; i++) {
+    h = (h << 4) + hash[i];
+    if ((g = h & 0xf0000000)) {
+      h = h ^ (g >> 24);
+      h = h ^ g;
+    }
+  }
+
+  return h;
+}
+
 /* Hash binary data. The `user_context' is the data length. */
 
 SilcUInt32 silc_hash_data(void *key, void *user_context)
@@ -769,6 +647,12 @@ char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
     strncat(string, "f", 1);
 
+  if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
+    strncat(string, "m", 1);
+
+  if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
+    strncat(string, "M", 1);
+
   if (mode & SILC_CHANNEL_MODE_CIPHER)
     strncat(string, cipher, strlen(cipher));
 
@@ -797,6 +681,15 @@ char *silc_client_chumode(SilcUInt32 mode)
   if (mode & SILC_CHANNEL_UMODE_CHANOP)
     strncat(string, "o", 1);
 
+  if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
+    strncat(string, "b", 1);
+
+  if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
+    strncat(string, "u", 1);
+
+  if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
+    strncat(string, "r", 1);
+
   return strdup(string);
 }
 
@@ -1042,3 +935,25 @@ char *silc_get_input(const char *prompt, bool echo_off)
   return NULL;
 #endif /* SILC_UNIX */
 }
+
+/* Return mode list */
+
+bool silc_get_mode_list(SilcBuffer mode_list, SilcUInt32 mode_list_count,
+                       SilcUInt32 **list)
+{
+  int i;
+
+  if (mode_list->len / 4 != mode_list_count)
+    return FALSE;
+
+  *list = silc_calloc(mode_list_count, sizeof(**list));
+
+  for (i = 0; i < mode_list_count; i++) {
+    SILC_GET32_MSB((*list)[i], mode_list->data);
+    silc_buffer_pull(mode_list, 4);
+  }
+
+  silc_buffer_push(mode_list, mode_list->data - mode_list->head);
+
+  return TRUE;
+}