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 /* Same as above but encode the buffer from SilcArgumentPayload structure
157 instead of raw data. */
159 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
166 for (i = 0; i < payload->argc; i++)
167 len += 3 + payload->argv_lens[i];
169 buffer = silc_buffer_alloc_size(len);
174 for (i = 0; i < payload->argc; i++) {
175 silc_buffer_format(buffer,
176 SILC_STR_UI_SHORT(payload->argv_lens[i]),
177 SILC_STR_UI_CHAR(payload->argv_types[i]),
178 SILC_STR_UI_XNSTRING(payload->argv[i],
179 payload->argv_lens[i]),
181 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
184 silc_buffer_push(buffer, len);
189 /* Frees Argument Payload */
191 void silc_argument_payload_free(SilcArgumentPayload payload)
196 for (i = 0; i < payload->argc; i++)
197 silc_free(payload->argv[i]);
199 silc_free(payload->argv);
200 silc_free(payload->argv_lens);
201 silc_free(payload->argv_types);
206 /* Returns number of arguments in payload */
208 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
210 return payload ? payload->argc : 0;
213 /* Returns first argument from payload. */
215 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
224 *ret_len = payload->argv_lens[payload->pos];
226 return payload->argv[payload->pos++];
229 /* Returns next argument from payload or NULL if no more arguments. */
231 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
237 if (payload->pos >= payload->argc)
241 *ret_len = payload->argv_lens[payload->pos];
243 return payload->argv[payload->pos++];
246 /* Returns argument which type is `type'. */
248 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
257 for (i = 0; i < payload->argc; i++)
258 if (payload->argv_types[i] == type)
261 if (i >= payload->argc)
265 *ret_len = payload->argv_lens[i];
267 return payload->argv[i];