Added SILC Server library.
[silc.git] / lib / silccore / silcargument.c
index dd470a37dbc4ef704a7d6f55e9cc5a2d17250799..a57370495565523b7b787728f8a365b0c59b4f0a 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcargument.c 
+  silcargument.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 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
   GNU General Public License for more details.
 
 */
-/* Implementation of Argument Payload routines */ 
+/* Implementation of Argument Payload routines */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcargument.h"
 
 /******************************************************************************
@@ -50,8 +50,6 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
   SilcUInt32 pull_len = 0;
   int i = 0, ret;
 
-  SILC_LOG_DEBUG(("Parsing argument payload"));
-
   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
   newp = silc_calloc(1, sizeof(*newp));
   if (!newp)
@@ -65,7 +63,7 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
   newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
   if (!newp->argv_types)
     goto err;
-    
+
   /* Get arguments */
   arg_num = 1;
   for (i = 0; i < argc; i++) {
@@ -73,19 +71,16 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
                               SILC_STR_UI_SHORT(&p_len),
                               SILC_STR_UI_CHAR(&arg_type),
                               SILC_STR_END);
-    if (ret == -1)
+    if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3)
       goto err;
-    
+
     newp->argv_lens[i] = p_len;
     newp->argv_types[i] = arg_type;
 
-    if (p_len > buffer.len - 3)
-      break;
-    
     /* Get argument data */
     silc_buffer_pull(&buffer, 3);
     ret = silc_buffer_unformat(&buffer,
-                              SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i], 
+                              SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i],
                                                          p_len),
                               SILC_STR_END);
     if (ret == -1)
@@ -95,8 +90,10 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
     pull_len += 3 + p_len;
   }
 
-  if (buffer.len != 0)
+  if (silc_buffer_len(&buffer) != 0) {
+    SILC_LOG_DEBUG(("Malformed argument payload"));
     goto err;
+  }
 
   newp->argc = argc;
   newp->pos = 0;
@@ -106,6 +103,7 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
   return newp;
 
  err:
+  SILC_LOG_DEBUG(("Error parsing argument payload"));
   if (i)
     for (ret = 0; ret < i; ret++)
       silc_free(newp->argv[ret]);
@@ -129,11 +127,9 @@ SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
   SilcUInt32 len;
   int i;
 
-  SILC_LOG_DEBUG(("Encoding Argument payload"));
-
   len = 0;
   for (i = 0; i < argc; i++)
-    len += 3 + argv_lens[i];
+    len += 3 + (SilcUInt16)argv_lens[i];
 
   buffer = silc_buffer_alloc_size(len);
   if (!buffer)
@@ -144,9 +140,9 @@ SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
     silc_buffer_format(buffer,
                       SILC_STR_UI_SHORT(argv_lens[i]),
                       SILC_STR_UI_CHAR(argv_types[i]),
-                      SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
+                      SILC_STR_UI_XNSTRING(argv[i], (SilcUInt16)argv_lens[i]),
                       SILC_STR_END);
-    silc_buffer_pull(buffer, 3 + argv_lens[i]);
+    silc_buffer_pull(buffer, 3 + (SilcUInt16)argv_lens[i]);
   }
 
   silc_buffer_push(buffer, len);
@@ -154,6 +150,33 @@ SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
   return buffer;
 }
 
+/* Encode one argument to buffer */
+
+SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
+                                           unsigned char *arg,
+                                           SilcUInt32 arg_len,
+                                           SilcUInt32 arg_type)
+{
+  SilcBuffer buffer = args;
+  SilcUInt32 len;
+
+  len = 3 + (SilcUInt16)arg_len;
+  buffer = silc_buffer_realloc(buffer,
+                              (buffer ? silc_buffer_truelen(buffer) + len : len));
+  if (!buffer)
+    return NULL;
+  silc_buffer_pull(buffer, silc_buffer_len(buffer));
+  silc_buffer_pull_tail(buffer, len);
+  silc_buffer_format(buffer,
+                    SILC_STR_UI_SHORT(arg_len),
+                    SILC_STR_UI_CHAR(arg_type),
+                    SILC_STR_UI_XNSTRING(arg, (SilcUInt16)arg_len),
+                    SILC_STR_END);
+  silc_buffer_push(buffer, buffer->data - buffer->head);
+
+  return buffer;
+}
+
 /* Same as above but encode the buffer from SilcArgumentPayload structure
    instead of raw data. */
 
@@ -163,8 +186,6 @@ SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
   SilcUInt32 len;
   int i;
 
-  SILC_LOG_DEBUG(("Encoding Argument payload"));
-
   len = 0;
   for (i = 0; i < payload->argc; i++)
     len += 3 + payload->argv_lens[i];
@@ -178,7 +199,7 @@ SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
     silc_buffer_format(buffer,
                       SILC_STR_UI_SHORT(payload->argv_lens[i]),
                       SILC_STR_UI_CHAR(payload->argv_types[i]),
-                      SILC_STR_UI_XNSTRING(payload->argv[i], 
+                      SILC_STR_UI_XNSTRING(payload->argv[i],
                                            payload->argv_lens[i]),
                       SILC_STR_END);
     silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
@@ -216,6 +237,7 @@ SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
 /* Returns first argument from payload. */
 
 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
+                                          SilcUInt32 *type,
                                           SilcUInt32 *ret_len)
 {
   if (!payload)
@@ -223,6 +245,8 @@ unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
 
   payload->pos = 0;
 
+  if (type)
+    *type = payload->argv_types[payload->pos];
   if (ret_len)
     *ret_len = payload->argv_lens[payload->pos];
 
@@ -232,6 +256,7 @@ unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
 /* Returns next argument from payload or NULL if no more arguments. */
 
 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
+                                         SilcUInt32 *type,
                                          SilcUInt32 *ret_len)
 {
   if (!payload)
@@ -240,6 +265,8 @@ unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
   if (payload->pos >= payload->argc)
     return NULL;
 
+  if (type)
+    *type = payload->argv_types[payload->pos];
   if (ret_len)
     *ret_len = payload->argv_lens[payload->pos];