SilcClientEntry silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, char *userinfo, SilcClientID *id, SilcServerEntry router, void *connection) { SilcClientEntry client; char *nicknamec = NULL; SILC_LOG_DEBUG(("Adding new client entry")); /* Normalize name. This is cached, original is in client context. */ if (nickname) { nicknamec = silc_identifier_check(nickname, strlen(nickname), SILC_STRING_UTF8, 128, NULL); if (!nicknamec) return NULL; } /* Check username. */ if (username) { char u[128 + 1], h[256 + 1]; int ret; ret = silc_parse_userfqdn(username, u, sizeof(u), h, sizeof(h)); if (!ret) return NULL; if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) return NULL; if (ret > 1 && !silc_identifier_verify(h, strlen(h), SILC_STRING_UTF8, 256)) return NULL; } client = silc_calloc(1, sizeof(*client)); if (!client) return NULL; client->nickname = nickname; client->username = username ? strdup(username) : NULL; client->userinfo = userinfo; client->id = id; client->router = router; client->connection = connection; client->channels = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); if (!silc_idcache_add(id_list->clients, nicknamec, (void *)client->id, (void *)client)) { silc_hash_table_free(client->channels); silc_free(client); silc_free(nicknamec); return NULL; } return client; }
SilcChannelEntry silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, SilcChannelID *id, SilcServerEntry router, SilcCipher send_key, SilcCipher receive_key, SilcHmac hmac) { SilcChannelEntry channel; char *channel_namec = NULL; SILC_LOG_DEBUG(("Adding new channel %s", channel_name)); /* Normalize name. This is cached, original is in client context. */ if (channel_name) { channel_namec = silc_channel_name_check(channel_name, strlen(channel_name), SILC_STRING_UTF8, 256, NULL); if (!channel_namec) return NULL; } channel = silc_calloc(1, sizeof(*channel)); channel->channel_name = channel_name; channel->mode = mode; channel->id = id; channel->router = router; channel->send_key = send_key; channel->receive_key = receive_key; channel->hmac = hmac; channel->created = channel->updated = time(0); if (!channel->hmac) if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) { silc_free(channel); return NULL; } channel->user_list = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); if (!silc_idcache_add(id_list->channels, channel_namec, (void *)channel->id, (void *)channel)) { silc_hmac_free(channel->hmac); silc_hash_table_free(channel->user_list); silc_free(channel); silc_free(channel_namec); return NULL; } return channel; }
SilcMime silc_mime_alloc(void) { SilcMime mime; mime = silc_calloc(1, sizeof(*mime)); if (!mime) return NULL; mime->fields = silc_hash_table_alloc(0, silc_hash_string, mime, silc_hash_string_compare, mime, silc_mime_field_dest, mime, TRUE); if (!mime->fields) { silc_mime_free(mime); return NULL; } return mime; }
SilcMimeAssembler silc_mime_assembler_alloc(void) { SilcMimeAssembler assembler; assembler = silc_calloc(1, sizeof(*assembler)); if (!assembler) return NULL; assembler->fragments = silc_hash_table_alloc(0, silc_hash_string, NULL, silc_hash_string_compare, NULL, silc_mime_assembler_dest, assembler, TRUE); if (!assembler->fragments) { silc_mime_assembler_free(assembler); return NULL; } return assembler; }
SilcAttributePayload silc_client_attribute_add(SilcClient client, SilcClientConnection conn, SilcAttribute attribute, void *object, SilcUInt32 object_size) { SilcAttributePayload attr; attr = silc_attribute_payload_alloc(attribute, SILC_ATTRIBUTE_FLAG_VALID, object, object_size); if (!attr) return NULL; if (!conn->internal->attrs) conn->internal->attrs = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL, silc_client_attribute_destruct, NULL, TRUE); silc_hash_table_add(conn->internal->attrs, SILC_32_TO_PTR(attribute), attr); return attr; }
SilcMime silc_mime_assemble(SilcMimeAssembler assembler, SilcMime partial) { char *type, *id = NULL, *tmp; SilcHashTable f; SilcMime p, complete; int i, number, total = -1; const unsigned char *data; SilcUInt32 data_len; SilcBuffer compbuf = NULL; SILC_LOG_DEBUG(("Assembling MIME fragments")); if (!assembler || !partial) goto err; type = (char *)silc_mime_get_field(partial, "Content-Type"); if (!type) goto err; /* Get ID */ tmp = strstr(type, "id="); if (!tmp) goto err; if (strlen(tmp) <= 4) goto err; tmp += 3; if (*tmp == '"') tmp++; id = strdup(tmp); if (strchr(id, ';')) *strchr(id, ';') = '\0'; if (strrchr(id, '"')) *strrchr(id, '"') = '\0'; SILC_LOG_DEBUG(("Fragment ID %s", id)); /* Get fragment number */ tmp = strstr(type, "number="); if (!tmp) goto err; tmp = strchr(tmp, '='); if (strlen(tmp) < 2) goto err; tmp++; if (strchr(tmp, ';')) { tmp = strdup(tmp); *strchr(tmp, ';') = '\0'; number = atoi(tmp); silc_free(tmp); } else { number = atoi(tmp); } SILC_LOG_DEBUG(("Fragment number %d", number)); /* Find fragments with this ID. */ if (!silc_hash_table_find(assembler->fragments, (void *)id, NULL, (void *)&f)) { /* This is new fragment to new message. Add to hash table and return. */ f = silc_hash_table_alloc(0, silc_hash_uint, NULL, NULL, NULL, silc_mime_assemble_dest, NULL, TRUE); if (!f) goto err; silc_hash_table_add(f, SILC_32_TO_PTR(number), partial); silc_hash_table_add(assembler->fragments, id, f); return NULL; } /* Try to get total number */ tmp = strstr(type, "total="); if (tmp) { tmp = strchr(tmp, '='); if (strlen(tmp) < 2) goto err; tmp++; if (strchr(tmp, ';')) { tmp = strdup(tmp); *strchr(tmp, ';') = '\0'; total = atoi(tmp); silc_free(tmp); } else { total = atoi(tmp); } SILC_LOG_DEBUG(("Fragment total %d", total)); } /* If more fragments to come, add to hash table */ if (number != total) { silc_hash_table_add(f, SILC_32_TO_PTR(number), partial); return NULL; } silc_hash_table_add(f, SILC_32_TO_PTR(number), partial); /* Verify that we really have all the fragments */ if (silc_hash_table_count(f) < total) return NULL; /* Assemble the complete MIME message now. We get them in order from the hash table. */ for (i = 1; i <= total; i++) { if (!silc_hash_table_find(f, SILC_32_TO_PTR(i), NULL, (void *)&p)) goto err; /* The fragment is in the data portion of the partial message */ data = silc_mime_get_data(p, &data_len); if (!data) goto err; /* Assemble */ if (!compbuf) { compbuf = silc_buffer_alloc_size(data_len); if (!compbuf) goto err; silc_buffer_put(compbuf, data, data_len); } else { compbuf = silc_buffer_realloc(compbuf, silc_buffer_truelen(compbuf) + data_len); if (!compbuf) goto err; silc_buffer_put_tail(compbuf, data, data_len); silc_buffer_pull_tail(compbuf, data_len); } } /* Now parse the complete MIME message and deliver it */ complete = silc_mime_decode(NULL, (const unsigned char *)compbuf->head, silc_buffer_truelen(compbuf)); if (!complete) goto err; /* Delete the hash table entry. Destructors will free memory */ silc_hash_table_del(assembler->fragments, (void *)id); silc_free(id); silc_buffer_free(compbuf); return complete; err: silc_free(id); if (compbuf) silc_buffer_free(compbuf); silc_mime_free(partial); return NULL; }