5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
19 /* Implementation of Argument Payload routines */
22 #include "silcincludes.h"
23 #include "silcargument.h"
25 /******************************************************************************
29 ******************************************************************************/
31 struct SilcArgumentPayloadStruct {
34 SilcUInt32 *argv_lens;
35 SilcUInt32 *argv_types;
39 /* Parses arguments and returns them into Argument Payload structure. */
41 SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
42 SilcUInt32 payload_len,
45 SilcBufferStruct buffer;
46 SilcArgumentPayload newp;
48 unsigned char arg_num = 0;
49 unsigned char arg_type = 0;
50 SilcUInt32 pull_len = 0;
53 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
54 newp = silc_calloc(1, sizeof(*newp));
57 newp->argv = silc_calloc(argc, sizeof(unsigned char *));
60 newp->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
63 newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
64 if (!newp->argv_types)
69 for (i = 0; i < argc; i++) {
70 ret = silc_buffer_unformat(&buffer,
71 SILC_STR_UI_SHORT(&p_len),
72 SILC_STR_UI_CHAR(&arg_type),
77 newp->argv_lens[i] = p_len;
78 newp->argv_types[i] = arg_type;
80 if (p_len > buffer.len - 3)
83 /* Get argument data */
84 silc_buffer_pull(&buffer, 3);
85 ret = silc_buffer_unformat(&buffer,
86 SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i],
92 silc_buffer_pull(&buffer, p_len);
93 pull_len += 3 + p_len;
96 if (buffer.len != 0) {
97 SILC_LOG_DEBUG(("Malformed argument payload"));
104 silc_buffer_push(&buffer, pull_len);
109 SILC_LOG_DEBUG(("Error parsing argument payload"));
111 for (ret = 0; ret < i; ret++)
112 silc_free(newp->argv[ret]);
114 silc_free(newp->argv);
115 silc_free(newp->argv_lens);
116 silc_free(newp->argv_types);
122 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
124 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
125 unsigned char **argv,
126 SilcUInt32 *argv_lens,
127 SilcUInt32 *argv_types)
134 for (i = 0; i < argc; i++)
135 len += 3 + argv_lens[i];
137 buffer = silc_buffer_alloc_size(len);
142 for (i = 0; i < argc; i++) {
143 silc_buffer_format(buffer,
144 SILC_STR_UI_SHORT(argv_lens[i]),
145 SILC_STR_UI_CHAR(argv_types[i]),
146 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
148 silc_buffer_pull(buffer, 3 + argv_lens[i]);
151 silc_buffer_push(buffer, len);
156 /* Encode one argument to buffer */
158 SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
163 SilcBuffer buffer = args;
167 buffer = silc_buffer_realloc(buffer,
168 (buffer ? buffer->truelen + len : len));
171 silc_buffer_pull(buffer, buffer->len);
172 silc_buffer_pull_tail(buffer, len);
173 silc_buffer_format(buffer,
174 SILC_STR_UI_SHORT(arg_len),
175 SILC_STR_UI_CHAR(arg_type),
176 SILC_STR_UI_XNSTRING(arg, arg_len),
178 silc_buffer_push(buffer, buffer->data - buffer->head);
183 /* Same as above but encode the buffer from SilcArgumentPayload structure
184 instead of raw data. */
186 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
193 for (i = 0; i < payload->argc; i++)
194 len += 3 + payload->argv_lens[i];
196 buffer = silc_buffer_alloc_size(len);
201 for (i = 0; i < payload->argc; i++) {
202 silc_buffer_format(buffer,
203 SILC_STR_UI_SHORT(payload->argv_lens[i]),
204 SILC_STR_UI_CHAR(payload->argv_types[i]),
205 SILC_STR_UI_XNSTRING(payload->argv[i],
206 payload->argv_lens[i]),
208 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
211 silc_buffer_push(buffer, len);
216 /* Frees Argument Payload */
218 void silc_argument_payload_free(SilcArgumentPayload payload)
223 for (i = 0; i < payload->argc; i++)
224 silc_free(payload->argv[i]);
226 silc_free(payload->argv);
227 silc_free(payload->argv_lens);
228 silc_free(payload->argv_types);
233 /* Returns number of arguments in payload */
235 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
237 return payload ? payload->argc : 0;
240 /* Returns first argument from payload. */
242 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
252 *type = payload->argv_types[payload->pos];
254 *ret_len = payload->argv_lens[payload->pos];
256 return payload->argv[payload->pos++];
259 /* Returns next argument from payload or NULL if no more arguments. */
261 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
268 if (payload->pos >= payload->argc)
272 *type = payload->argv_types[payload->pos];
274 *ret_len = payload->argv_lens[payload->pos];
276 return payload->argv[payload->pos++];
279 /* Returns argument which type is `type'. */
281 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
290 for (i = 0; i < payload->argc; i++)
291 if (payload->argv_types[i] == type)
294 if (i >= payload->argc)
298 *ret_len = payload->argv_lens[i];
300 return payload->argv[i];