Merged from silc_1_0_branch.
[silc.git] / lib / silccore / silcargument.c
index 471e92c78fe18130da9bbbd89caac6ad4d7e8394..d492ed742576b6e4442812568c86d0634581f679 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 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
 ******************************************************************************/
 
 struct SilcArgumentPayloadStruct {
-  uint32 argc;
+  SilcUInt32 argc;
   unsigned char **argv;
-  uint32 *argv_lens;
-  uint32 *argv_types;
-  uint32 pos;
+  SilcUInt32 *argv_lens;
+  SilcUInt32 *argv_types;
+  SilcUInt32 pos;
 };
 
 /* Parses arguments and returns them into Argument Payload structure. */
 
 SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
-                                               uint32 payload_len,
-                                               uint32 argc)
+                                               SilcUInt32 payload_len,
+                                               SilcUInt32 argc)
 {
   SilcBufferStruct buffer;
-  SilcArgumentPayload new;
-  uint16 p_len = 0;
+  SilcArgumentPayload newp;
+  SilcUInt16 p_len = 0;
   unsigned char arg_num = 0;
   unsigned char arg_type = 0;
-  uint32 pull_len = 0;
+  SilcUInt32 pull_len = 0;
   int i = 0, ret;
 
-  SILC_LOG_DEBUG(("Parsing argument payload"));
-
   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
-  new = silc_calloc(1, sizeof(*new));
-  new->argv = silc_calloc(argc, sizeof(unsigned char *));
-  new->argv_lens = silc_calloc(argc, sizeof(uint32));
-  new->argv_types = silc_calloc(argc, sizeof(uint32));
+  newp = silc_calloc(1, sizeof(*newp));
+  if (!newp)
+    return NULL;
+  newp->argv = silc_calloc(argc, sizeof(unsigned char *));
+  if (!newp->argv)
+    goto err;
+  newp->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
+  if (!newp->argv_lens)
+    goto err;
+  newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
+  if (!newp->argv_types)
+    goto err;
     
   /* Get arguments */
   arg_num = 1;
@@ -68,8 +74,8 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
     if (ret == -1)
       goto err;
     
-    new->argv_lens[i] = p_len;
-    new->argv_types[i] = arg_type;
+    newp->argv_lens[i] = p_len;
+    newp->argv_types[i] = arg_type;
 
     if (p_len > buffer.len - 3)
       break;
@@ -77,7 +83,7 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
     /* Get argument data */
     silc_buffer_pull(&buffer, 3);
     ret = silc_buffer_unformat(&buffer,
-                              SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i], 
+                              SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i], 
                                                          p_len),
                               SILC_STR_END);
     if (ret == -1)
@@ -87,62 +93,59 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
     pull_len += 3 + p_len;
   }
 
-  if (buffer.len != 0)
+  if (buffer.len != 0) {
+    SILC_LOG_DEBUG(("Malformed argument payload"));
     goto err;
+  }
 
-  new->argc = argc;
-  new->pos = 0;
+  newp->argc = argc;
+  newp->pos = 0;
 
   silc_buffer_push(&buffer, pull_len);
 
-  return new;
+  return newp;
 
  err:
-  if (i) {
-    int k;
+  SILC_LOG_DEBUG(("Error parsing argument payload"));
+  if (i)
+    for (ret = 0; ret < i; ret++)
+      silc_free(newp->argv[ret]);
 
-    for (k = 0; k < i; k++)
-      silc_free(new->argv[k]);
-  }
-
-  silc_free(new->argv);
-  silc_free(new->argv_lens);
-  silc_free(new->argv_types);
-
-  if (new)
-    silc_free(new);
+  silc_free(newp->argv);
+  silc_free(newp->argv_lens);
+  silc_free(newp->argv_types);
+  silc_free(newp);
 
   return NULL;
 }
 
 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
 
-SilcBuffer silc_argument_payload_encode(uint32 argc,
+SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
                                        unsigned char **argv,
-                                       uint32 *argv_lens,
-                                       uint32 *argv_types)
+                                       SilcUInt32 *argv_lens,
+                                       SilcUInt32 *argv_types)
 {
   SilcBuffer buffer;
-  uint32 len;
+  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(len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  buffer = silc_buffer_alloc_size(len);
+  if (!buffer)
+    return NULL;
 
   /* Put arguments */
   for (i = 0; i < argc; i++) {
     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);
@@ -150,23 +153,49 @@ SilcBuffer silc_argument_payload_encode(uint32 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 ? buffer->truelen + len : len));
+  if (!buffer)
+    return NULL;
+  silc_buffer_pull(buffer, buffer->len);
+  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. */
 
 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
 {
   SilcBuffer buffer;
-  uint32 len;
+  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];
 
-  buffer = silc_buffer_alloc(len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  buffer = silc_buffer_alloc_size(len);
+  if (!buffer)
+    return NULL;
 
   /* Put arguments */
   for (i = 0; i < payload->argc; i++) {
@@ -203,7 +232,7 @@ void silc_argument_payload_free(SilcArgumentPayload payload)
 
 /* Returns number of arguments in payload */
 
-uint32 silc_argument_get_arg_num(SilcArgumentPayload payload)
+SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
 {
   return payload ? payload->argc : 0;
 }
@@ -211,13 +240,16 @@ uint32 silc_argument_get_arg_num(SilcArgumentPayload payload)
 /* Returns first argument from payload. */
 
 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
-                                          uint32 *ret_len)
+                                          SilcUInt32 *type,
+                                          SilcUInt32 *ret_len)
 {
   if (!payload)
     return NULL;
 
   payload->pos = 0;
 
+  if (type)
+    *type = payload->argv_types[payload->pos];
   if (ret_len)
     *ret_len = payload->argv_lens[payload->pos];
 
@@ -227,7 +259,8 @@ 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,
-                                         uint32 *ret_len)
+                                         SilcUInt32 *type,
+                                         SilcUInt32 *ret_len)
 {
   if (!payload)
     return NULL;
@@ -235,6 +268,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];
 
@@ -244,8 +279,8 @@ unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
 /* Returns argument which type is `type'. */
 
 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
-                                         uint32 type,
-                                         uint32 *ret_len)
+                                         SilcUInt32 type,
+                                         SilcUInt32 *ret_len)
 {
   int i;