+
+/* Return argument already decoded */
+
+SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
+ SilcUInt32 type,
+ SilcArgumentDecodeType dec_type,
+ void *ret_arg,
+ void **ret_arg_alloc)
+{
+ unsigned char *tmp;
+ SilcUInt32 tmp_len;
+
+ tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
+ if (!tmp)
+ return FALSE;
+
+ return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
+}
+
+/************************* Argument List Payload ****************************/
+
+/* Parses argument payload list */
+
+SilcArgumentPayload
+silc_argument_list_parse(const unsigned char *payload,
+ SilcUInt32 payload_len)
+{
+ SilcArgumentPayload arg;
+ SilcUInt16 argc;
+
+ if (payload_len < 5)
+ return NULL;
+
+ SILC_GET16_MSB(argc, payload);
+
+ arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
+
+ return arg;
+}
+
+/* Parses argument payload list of specific argument types */
+
+SilcDList
+silc_argument_list_parse_decoded(const unsigned char *payload,
+ SilcUInt32 payload_len,
+ SilcArgumentDecodeType dec_type)
+{
+ SilcArgumentPayload arg;
+ SilcArgumentDecodedList dec;
+ unsigned char *data;
+ SilcUInt32 data_len, type;
+ SilcDList list;
+
+ arg = silc_argument_list_parse(payload, payload_len);
+ if (!arg)
+ return NULL;
+
+ list = silc_dlist_init();
+ if (!list) {
+ silc_argument_payload_free(arg);
+ return NULL;
+ }
+
+ data = silc_argument_get_first_arg(arg, &type, &data_len);
+ while (data) {
+ dec = silc_calloc(1, sizeof(*dec));
+ if (!dec)
+ continue;
+ dec->arg_type = type;
+ if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
+ silc_dlist_add(list, dec);
+ else
+ silc_free(dec);
+ data = silc_argument_get_next_arg(arg, &type, &data_len);
+ }
+
+ silc_argument_payload_free(arg);
+
+ silc_dlist_start(list);
+
+ return list;
+}
+
+/* Free decoded argument payload list */
+
+void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
+{
+ SilcArgumentDecodedList dec;
+
+ if (!list)
+ return;
+
+ silc_dlist_start(list);
+ while ((dec = silc_dlist_get(list))) {
+ switch (dec_type) {
+
+ case SILC_ARGUMENT_ID:
+ case SILC_ARGUMENT_UINT32:
+ case SILC_ARGUMENT_BOOL:
+ silc_free(dec->argument);
+ break;
+
+ case SILC_ARGUMENT_PUBLIC_KEY:
+ silc_pkcs_public_key_free(dec->argument);
+ break;
+
+ case SILC_ARGUMENT_ATTRIBUTES:
+ silc_attribute_payload_free(dec->argument);
+ break;
+
+ default:
+ break;
+ }
+
+ silc_free(dec);
+ }
+
+ silc_dlist_uninit(list);
+}