Merged silc_1_1_branch to trunk.
[silc.git] / lib / silccore / silcattrs.c
index 7af8f6a052ed5068ee121ee5c3577e6d34b1edd5..796f6255d3318732c0ffbe7ba47191c8d8c165ed 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcattrs.c 
+  silcattrs.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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
@@ -19,7 +19,7 @@
 /* Implementation of Attribute Payload routines */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcattrs.h"
 
 /******************************************************************************
@@ -76,6 +76,8 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
        len = strlen(service->address);
        len2 = strlen(service->signon);
        tmpbuf = silc_buffer_alloc_size(13 + len + len2);
+       if (!tmpbuf)
+         return NULL;
        silc_buffer_format(tmpbuf,
                           SILC_STR_UI_INT(service->port),
                           SILC_STR_UI_SHORT(len),
@@ -86,14 +88,14 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
                           SILC_STR_UI_INT(service->idle),
                           SILC_STR_END);
        object = tmpbuf->data;
-       object_size = tmpbuf->len;
+       object_size = silc_buffer_len(tmpbuf);
       }
       break;
 
     case SILC_ATTRIBUTE_STATUS_MOOD:
     case SILC_ATTRIBUTE_PREFERRED_CONTACT:
       {
-       SilcUInt32 mask = (SilcUInt32)object;
+       SilcUInt32 mask = SILC_PTR_TO_32(object);
        if (object_size != sizeof(SilcUInt32))
          return NULL;
        SILC_PUT32_MSB(mask, tmp);
@@ -119,12 +121,15 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
 
     case SILC_ATTRIBUTE_STATUS_MESSAGE:
     case SILC_ATTRIBUTE_EXTENSION:
+    case SILC_ATTRIBUTE_USER_ICON:
       {
-       SilcAttributeObjMime *mime = object;
+       SilcMime mime = object;
        if (object_size != sizeof(*mime))
          return NULL;
-       object = (void *)mime->mime;
-       object_size = mime->mime_len;
+       str = silc_mime_encode(mime, &object_size);
+       if (!str)
+         return NULL;
+       object = str;
       }
       break;
 
@@ -155,7 +160,7 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
                           SILC_STR_UI16_STRING(len4 ? geo->accuracy : ""),
                           SILC_STR_END);
        object = tmpbuf->data;
-       object_size = tmpbuf->len;
+       object_size = silc_buffer_len(tmpbuf);
       }
       break;
 
@@ -187,7 +192,28 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
                           SILC_STR_UI16_STRING(len4 ? dev->language : ""),
                           SILC_STR_END);
        object = tmpbuf->data;
-       object_size = tmpbuf->len;
+       object_size = silc_buffer_len(tmpbuf);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_PHONE_NUMBER:
+      {
+       SilcAttributeObjPN *pn = object;
+       if (object_size != sizeof(*pn))
+         return NULL;
+       if (!pn->number || strlen(pn->number) < 5)
+         return NULL;
+       tmpbuf = silc_buffer_alloc(0);
+       if (!tmpbuf)
+         return NULL;
+       if (silc_buffer_format(tmpbuf,
+                              SILC_STR_UI_INT(pn->format),
+                              SILC_STR_UI_SHORT(strlen(pn->number)),
+                              SILC_STR_UI16_STRING(pn->number),
+                              SILC_STR_END) < 0)
+         return NULL;
+       object = tmpbuf->data;
+       object_size = silc_buffer_len(tmpbuf);
       }
       break;
 
@@ -207,7 +233,7 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
                           SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
                           SILC_STR_END);
        object = tmpbuf->data;
-       object_size = tmpbuf->len;
+       object_size = silc_buffer_len(tmpbuf);
       }
       break;
 
@@ -286,32 +312,32 @@ SilcDList silc_attribute_payload_parse(const unsigned char *payload,
   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
   list = silc_dlist_init();
 
-  while (buffer.len) {
+  while (silc_buffer_len(&buffer)) {
     newp = silc_calloc(1, sizeof(*newp));
     if (!newp)
       goto err;
     ret = silc_buffer_unformat(&buffer,
                               SILC_STR_UI_CHAR(&newp->attribute),
                               SILC_STR_UI_CHAR(&newp->flags),
-                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
+                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
                                                           &newp->data_len),
                               SILC_STR_END);
     if (ret == -1)
       goto err;
 
-    if (newp->data_len > buffer.len - 4) {
+    if (newp->data_len > silc_buffer_len(&buffer) - 4) {
       SILC_LOG_ERROR(("Incorrect attribute payload in list"));
       goto err;
     }
 
     len = 4 + newp->data_len;
-    if (buffer.len < len)
+    if (silc_buffer_len(&buffer) < len)
       break;
     silc_buffer_pull(&buffer, len);
 
     silc_dlist_add(list, newp);
   }
-  
+
   return list;
 
  err:
@@ -349,12 +375,13 @@ SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
 
   len = 4 + (SilcUInt16)data_len;
   buffer = silc_buffer_realloc(buffer,
-                              (buffer ? buffer->truelen + len : len));
+                              (buffer ? silc_buffer_truelen(buffer) +
+                               len : len));
   if (!buffer)
     return NULL;
-  silc_buffer_pull(buffer, buffer->len);
+  silc_buffer_pull(buffer, silc_buffer_len(buffer));
   silc_buffer_pull_tail(buffer, len);
-  silc_buffer_format(buffer, 
+  silc_buffer_format(buffer,
                     SILC_STR_UI_CHAR(attribute),
                     SILC_STR_UI_CHAR(flags),
                     SILC_STR_UI_SHORT((SilcUInt16)data_len),
@@ -415,7 +442,7 @@ const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
 /* Construct digital signature verification data */
 
 unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
-                                             bool server_verification,
+                                             SilcBool server_verification,
                                              SilcUInt32 *data_len)
 {
   SilcAttributePayload attr;
@@ -444,7 +471,7 @@ unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
       if (!data)
        return NULL;
       silc_buffer_set(&buffer, data + len, 4 + attr->data_len);
-      silc_buffer_format(&buffer, 
+      silc_buffer_format(&buffer,
                         SILC_STR_UI_CHAR(attr->attribute),
                         SILC_STR_UI_CHAR(attr->flags),
                         SILC_STR_UI_SHORT(attr->data_len),
@@ -463,11 +490,11 @@ unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
 
 /* Return parsed attribute object */
 
-bool silc_attribute_get_object(SilcAttributePayload payload,
-                              void *object, SilcUInt32 object_size)
+SilcBool silc_attribute_get_object(SilcAttributePayload payload,
+                                  void *object, SilcUInt32 object_size)
 {
   SilcUInt16 len;
-  bool ret = FALSE;
+  SilcBool ret = FALSE;
 
   if (!object || payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
     return FALSE;
@@ -549,12 +576,13 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
 
   case SILC_ATTRIBUTE_STATUS_MESSAGE:
   case SILC_ATTRIBUTE_EXTENSION:
+  case SILC_ATTRIBUTE_USER_ICON:
     {
-      SilcAttributeObjMime *mime = object;
+      SilcMime mime = object;
       if (object_size != sizeof(*mime))
        break;
-      mime->mime = (const unsigned char *)payload->data;
-      mime->mime_len = payload->data_len;
+      if (!silc_mime_decode(mime, payload->data, payload->data_len))
+       break;
       ret = TRUE;
     }
     break;
@@ -605,6 +633,28 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
     }
     break;
 
+  case SILC_ATTRIBUTE_PHONE_NUMBER:
+    {
+      SilcAttributeObjPN *pn = object;
+      SilcBufferStruct buffer;
+      SilcUInt32 pn_format;
+      int res;
+      if (object_size != sizeof(*pn))
+       break;
+      silc_buffer_set(&buffer, (unsigned char *)payload->data,
+                     payload->data_len);
+      res =
+       silc_buffer_unformat(&buffer,
+                            SILC_STR_UI_INT(&pn_format),
+                            SILC_STR_UI16_STRING_ALLOC(&pn->number),
+                            SILC_STR_END);
+      if (res == -1)
+       break;
+      pn->format = pn_format;
+      ret = TRUE;
+    }
+    break;
+
   case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
   case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
     {
@@ -619,7 +669,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
        silc_buffer_unformat(&buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
                             SILC_STR_END);
-      if (res == -1 || len > buffer.len - 2)
+      if (res == -1 || len > silc_buffer_len(&buffer) - 2)
        break;
       pk->data = silc_memdup(payload->data + 2 + len,
                             payload->data_len - 2 - len);