updates.
[silc.git] / lib / silcutil / silcutil.c
index 9da9aea45de65065768afe63f0dff48b303eac79..2cf26fe92df9f0011cd3b36b95e07e4f7a246391 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcutil.c
+  silcutil.c 
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2002 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
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 #include "silcincludes.h"
 
-/* Reads a file to a buffer. The allocated buffer is returned. Length of
-   the file read is returned to the return_len argument. */
-
-char *silc_file_read(const char *filename, uint32 *return_len)
-{
-  int fd;
-  char *buffer;
-  int filelen;
-
-  fd = open(filename, O_RDONLY);
-  if (fd < 0) {
-    SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
-    return NULL;
-  }
-
-  filelen = lseek(fd, (off_t)0L, SEEK_END);
-  if (filelen < 0) {
-    close(fd);
-    return NULL;
-  }
-  if (lseek(fd, (off_t)0L, SEEK_SET) < 0) {
-    close(fd);
-    return NULL;
-  }
-
-  if (filelen < 0) {
-    SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
-    close(fd);
-    return NULL;
-  }
-  
-  buffer = silc_calloc(filelen + 1, sizeof(char));
-  
-  if ((read(fd, buffer, filelen)) == -1) {
-    memset(buffer, 0, sizeof(buffer));
-    close(fd);
-    SILC_LOG_ERROR(("Cannot read from file %s: %s", filename,
-                    strerror(errno)));
-    return NULL;
-  }
-
-  close(fd);
-  buffer[filelen] = EOF;
-
-  if (return_len)
-    *return_len = filelen;
-
-  return buffer;
-}
-
-/* Writes a buffer to the file. */
-
-int silc_file_write(const char *filename, const char *buffer, uint32 len)
-{
-  int fd;
-        
-  if ((fd = creat(filename, 0644)) == -1) {
-    SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
-                   strerror(errno)));
-    return -1;
-  }
-  
-  if ((write(fd, buffer, len)) == -1) {
-    SILC_LOG_ERROR(("Cannot write to file %s: %s", filename, strerror(errno)));
-    close(fd);
-    return -1;
-  }
-
-  close(fd);
-  
-  return 0;
-}
-
-/* Writes a buffer to the file.  If the file is created specific mode is
-   set to the file. */
-
-int silc_file_write_mode(const char *filename, const char *buffer, 
-                        uint32 len, int mode)
-{
-  int fd;
-        
-  if ((fd = creat(filename, mode)) == -1) {
-    SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
-                   strerror(errno)));
-    return -1;
-  }
-  
-  if ((write(fd, buffer, len)) == -1) {
-    SILC_LOG_ERROR(("Cannot write to file %s: %s", filename, strerror(errno)));
-    close(fd);
-    return -1;
-  }
-
-  close(fd);
-  
-  return 0;
-}
-
 /* Gets line from a buffer. Stops reading when a newline or EOF occurs.
    This doesn't remove the newline sign from the destination buffer. The
    argument begin is returned and should be passed again for the function. */
@@ -355,49 +256,36 @@ unsigned char *silc_decode_pem(unsigned char *pem, uint32 pem_len,
   return data;
 }
 
-/* Parse nickname string. The format may be <num>!<nickname>@<server> to
-   support multiple same nicknames. The <num> is the final unifier if same
-   nickname is on same server. Note, this is only local format and server
-   does not know anything about these. */
+/* Parse userfqdn string which is in user@fqdn format */
 
-int silc_parse_nickname(char *string, char **nickname, char **server,
-                       uint32 *num)
+bool silc_parse_userfqdn(const char *string, char **left, char **right)
 {
   uint32 tlen;
-  char tmp[256];
 
   if (!string)
     return FALSE;
 
-  if (strchr(string, '!')) {
-    tlen = strcspn(string, "!");
-    memset(tmp, 0, sizeof(tmp));
-    memcpy(tmp, string, tlen);
-
-    if (num)
-      *num = atoi(tmp);
-
-    if (tlen >= strlen(string))
-      return FALSE;
-
-    string += tlen + 1;
+  if (string[0] == '@') {
+    if (left)
+      *left = strdup(string);
+    return TRUE;
   }
 
   if (strchr(string, '@')) {
     tlen = strcspn(string, "@");
     
-    if (nickname) {
-      *nickname = silc_calloc(tlen + 1, sizeof(char));
-      memcpy(*nickname, string, tlen);
+    if (left) {
+      *left = silc_calloc(tlen + 1, sizeof(char));
+      memcpy(*left, string, tlen);
     }
     
-    if (server) {
-      *server = silc_calloc((strlen(string) - tlen) + 1, sizeof(char));
-      memcpy(*server, string + tlen + 1, strlen(string) - tlen - 1);
+    if (right) {
+      *right = silc_calloc((strlen(string) - tlen) + 1, sizeof(char));
+      memcpy(*right, string + tlen + 1, strlen(string) - tlen - 1);
     }
   } else {
-    if (nickname)
-      *nickname = strdup(string);
+    if (left)
+      *left = strdup(string);
   }
 
   return TRUE;
@@ -418,15 +306,21 @@ void silc_parse_command_line(unsigned char *buffer,
   int i, len = 0;
   int argc = 0;
   const char *cp = buffer;
+  char *tmp;
 
   *parsed = silc_calloc(1, sizeof(**parsed));
   *parsed_lens = silc_calloc(1, sizeof(**parsed_lens));
 
   /* Get the command first */
   len = strcspn(cp, " ");
-  (*parsed)[0] = silc_to_upper((char *)cp);
+  tmp = silc_to_upper((char *)cp);
+  (*parsed)[0] = silc_calloc(len + 1, sizeof(char));
+  memcpy((*parsed)[0], tmp, len);
+  silc_free(tmp);
   (*parsed_lens)[0] = len;
-  cp += len + 1;
+  cp += len;
+  while (*cp == ' ')
+    cp++;
   argc++;
 
   /* Parse arguments */
@@ -437,6 +331,10 @@ void silc_parse_command_line(unsigned char *buffer,
        len = strcspn(cp, " ");
       else
        len = strlen(cp);
+      while (len && cp[len - 1] == ' ')
+       len--;
+      if (!len)
+       break;
       
       *parsed = silc_realloc(*parsed, sizeof(**parsed) * (argc + 1));
       *parsed_lens = silc_realloc(*parsed_lens, 
@@ -450,7 +348,8 @@ void silc_parse_command_line(unsigned char *buffer,
       if (strlen(cp) == 0)
        break;
       else
-       cp++;
+       while (*cp == ' ')
+         cp++;
     }
   }
 
@@ -494,12 +393,16 @@ char *silc_id_render(void *id, uint16 type)
   case SILC_ID_SERVER:
     {
       SilcServerID *server_id = (SilcServerID *)id;
-      struct in_addr ipv4;
-
       if (server_id->ip.data_len > 4) {
-
+#ifdef HAVE_IPV6
+       struct in6_addr ipv6;
+       memmove(&ipv6, server_id->ip.data, sizeof(ipv6));
+       if (!inet_ntop(AF_INET6, &ipv6, tmp, sizeof(tmp)))
+         strcat(rid, tmp);
+#endif
       } else {
-       SILC_GET32_MSB(ipv4.s_addr, server_id->ip.data);
+       struct in_addr ipv4;
+       memmove(&ipv4.s_addr, server_id->ip.data, 4);
        strcat(rid, inet_ntoa(ipv4));
       }
 
@@ -515,12 +418,16 @@ char *silc_id_render(void *id, uint16 type)
   case SILC_ID_CLIENT:
     {
       SilcClientID *client_id = (SilcClientID *)id;
-      struct in_addr ipv4;
-
       if (client_id->ip.data_len > 4) {
-
+#ifdef HAVE_IPV6
+       struct in6_addr ipv6;
+       memmove(&ipv6, client_id->ip.data, sizeof(ipv6));
+       if (!inet_ntop(AF_INET6, &ipv6, tmp, sizeof(tmp)))
+         strcat(rid, tmp);
+#endif
       } else {
-       SILC_GET32_MSB(ipv4.s_addr, client_id->ip.data);
+       struct in_addr ipv4;
+       memmove(&ipv4.s_addr, client_id->ip.data, 4);
        strcat(rid, inet_ntoa(ipv4));
       }
 
@@ -537,12 +444,16 @@ char *silc_id_render(void *id, uint16 type)
   case SILC_ID_CHANNEL:
     {
       SilcChannelID *channel_id = (SilcChannelID *)id;
-      struct in_addr ipv4;
-
       if (channel_id->ip.data_len > 4) {
-
+#ifdef HAVE_IPV6
+       struct in6_addr ipv6;
+       memmove(&ipv6, channel_id->ip.data, sizeof(ipv6));
+       if (!inet_ntop(AF_INET6, &ipv6, tmp, sizeof(tmp)))
+         strcat(rid, tmp);
+#endif
       } else {
-       SILC_GET32_MSB(ipv4.s_addr, channel_id->ip.data);
+       struct in_addr ipv4;
+       memmove(&ipv4.s_addr, channel_id->ip.data, 4);
        strcat(rid, inet_ntoa(ipv4));
       }
 
@@ -566,13 +477,16 @@ char *silc_id_render(void *id, uint16 type)
 int silc_string_compare(char *string1, char *string2)
 {
   int i;
-  int slen1 = strlen(string1);
-  int slen2 = strlen(string2);
+  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, strlen(string2)))
     return TRUE;
@@ -630,147 +544,6 @@ int silc_string_compare(char *string1, char *string2)
   return FALSE;
 }
 
-/* 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)
-{
-  int i, len, count;
-  char *regex;
-
-  len = strlen(string);
-  count = 4;
-  for (i = 0; i < len; i++)
-    if (string[i] == '*' || string[i] == '?')
-      count++;
-
-  regex = silc_calloc(len + count, sizeof(*regex));
-
-  count = 0;
-  regex[count] = '(';
-  count++;
-
-  for (i = 0; i < len; i++) {
-    if (string[i] == '*' || string[i] == '?') {
-      regex[count] = '.';
-      count++;
-    } else if (string[i] == ',') {
-      regex[count] = '|';
-      count++;
-      continue;
-    }
-
-    regex[count] = string[i];
-    count++;
-  }
-
-  regex[count - 1] = ')';
-  regex[count] = '$';
-
-  return regex;
-}
-
-/* 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'. */
-
-char *silc_string_regex_combine(const char *string1, const char *string2)
-{
-  char *tmp;
-  int len1, len2;
-
-  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);
-
-  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;
-
-  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;
-
-  s1 = silc_string_regexify(string1);
-  ret = silc_string_regex_match(s1, string2);
-  silc_free(s1);
-
-  return ret;
-}
-
-/* Returns the username of the user. If the global variable LOGNAME
-   does not exists we will get the name from the password file. */
-
-char *silc_get_username()
-{
-  char *logname = NULL;
-  
-  logname = getenv("LOGNAME");
-  if (!logname) {
-    logname = getlogin();
-    if (!logname) {
-      struct passwd *pw;
-
-      pw = getpwuid(getuid());
-      if (!pw) {
-       fprintf(stderr, "silc_get_username: %s\n", strerror(errno));
-       return NULL;
-      }
-      
-      logname = pw->pw_name;
-    }
-  }
-  
-  return strdup(logname);
-}                          
-
-/* Returns the real name of ther user. */
-
-char *silc_get_real_name()
-{
-  char *realname = NULL;
-  struct passwd *pw;
-    
-  pw = getpwuid(getuid());
-  if (!pw) {
-    fprintf(stderr, "silc_get_username: %s\n", strerror(errno));
-    return NULL;
-  }
-
-  if (strchr(pw->pw_gecos, ','))
-    *strchr(pw->pw_gecos, ',') = 0;
-
-  realname = strdup(pw->pw_gecos);
-
-  return realname;
-}
-
 /* Basic has function to hash strings. May be used with the SilcHashTable. 
    Note that this lowers the characters of the string (with tolower()) so
    this is used usually with nicknames, channel and server names to provide
@@ -1000,3 +773,31 @@ char *silc_client_chumode_char(uint32 mode)
 
   return strdup(string);
 }
+
+/* Creates fingerprint from data, usually used with SHA1 digests */
+
+char *silc_fingerprint(const unsigned char *data, uint32 data_len)
+{
+  char fingerprint[64], *cp;
+  int i;
+
+  memset(fingerprint, 0, sizeof(fingerprint));
+  cp = fingerprint;
+  for (i = 0; i < data_len; i++) {
+    snprintf(cp, sizeof(fingerprint), "%02X", data[i]);
+    cp += 2;
+    
+    if ((i + 1) % 2 == 0)
+      snprintf(cp++, sizeof(fingerprint), " ");
+
+    if ((i + 1) % 10 == 0)
+      snprintf(cp++, sizeof(fingerprint), " ");
+  }
+  i--;
+  if ((i + 1) % 2 == 0)
+    cp[-2] = 0;
+  if ((i + 1) % 10 == 0)
+    cp[-1] = 0;
+  
+  return strdup(fingerprint);
+}