X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_entry.c;h=a58298fc05f81ebf0610ce48f9455910eb0d097f;hb=9905799a86c606304fd7df2cd401de1740a272a1;hp=c68dc4754508a7301bc6d200d90bd7ff28bbf175;hpb=81f0294584576e6cff50ebcfd7160017dbf7ba97;p=silc.git diff --git a/lib/silcclient/client_entry.c b/lib/silcclient/client_entry.c index c68dc475..a58298fc 100644 --- a/lib/silcclient/client_entry.c +++ b/lib/silcclient/client_entry.c @@ -423,6 +423,7 @@ SilcUInt16 silc_client_get_clients_by_list(SilcClient client, SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; SilcUInt16 idp_len, cmd_ident; SilcID id; + va_list tmp; int i; SILC_LOG_DEBUG(("Resolve clients from Client ID list")); @@ -490,7 +491,7 @@ SilcUInt16 silc_client_get_clients_by_list(SilcClient client, /* We have the clients in cache, get them and call the completion */ silc_client_get_clients_list_cb(client, conn, SILC_COMMAND_WHOIS, - SILC_STATUS_OK, SILC_STATUS_OK, in, NULL); + SILC_STATUS_OK, SILC_STATUS_OK, in, tmp); return 0; err: @@ -730,7 +731,7 @@ SilcClientEntry silc_client_add_client(SilcClient client, } /* Format the nickname */ - silc_client_nickname_format(client, conn, client_entry); + silc_client_nickname_format(client, conn, client_entry, FALSE); silc_mutex_lock(conn->internal->lock); @@ -750,7 +751,7 @@ SilcClientEntry silc_client_add_client(SilcClient client, silc_mutex_unlock(conn->internal->lock); silc_client_ref_client(client, conn, client_entry); - SILC_LOG_DEBUG(("Added")); + SILC_LOG_DEBUG(("Added %p", client_entry)); return client_entry; } @@ -790,7 +791,8 @@ void silc_client_update_client(SilcClient client, return; /* Format nickname */ - silc_client_nickname_format(client, conn, client_entry); + silc_client_nickname_format(client, conn, client_entry, + client_entry == conn->local_entry); /* Update cache entry */ silc_mutex_lock(conn->internal->lock); @@ -802,6 +804,57 @@ void silc_client_update_client(SilcClient client, client_entry->mode = mode; } +/* Change a client's nickname */ + +SilcBool silc_client_change_nickname(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry, + const char *new_nick, + SilcClientID *new_id, + const unsigned char *idp, + SilcUInt32 idp_len) +{ + char *tmp; + + SILC_LOG_DEBUG(("Change nickname %s to %s", client_entry->nickname, + new_nick)); + + /* Normalize nickname */ + tmp = silc_identifier_check(new_nick, strlen(new_nick), + SILC_STRING_UTF8, 128, NULL); + if (!tmp) + return FALSE; + + /* Update the client entry */ + silc_mutex_lock(conn->internal->lock); + if (!silc_idcache_update_by_context(conn->internal->client_cache, + client_entry, new_id, tmp, TRUE)) { + silc_free(tmp); + silc_mutex_unlock(conn->internal->lock); + return FALSE; + } + silc_mutex_unlock(conn->internal->lock); + + memset(client_entry->nickname, 0, sizeof(client_entry->nickname)); + memcpy(client_entry->nickname, new_nick, strlen(new_nick)); + client_entry->nickname_normalized = tmp; + silc_client_nickname_format(client, conn, client_entry, + client_entry == conn->local_entry); + + /* For my client entry, update ID and set new ID to packet stream */ + if (client_entry == conn->local_entry) { + if (idp && idp_len) { + silc_buffer_enlarge(conn->internal->local_idp, idp_len); + silc_buffer_put(conn->internal->local_idp, idp, idp_len); + } + if (new_id) + silc_packet_set_ids(conn->stream, SILC_ID_CLIENT, conn->local_id, + 0, NULL); + } + + return TRUE; +} + /* Deletes the client entry and frees all memory. */ void silc_client_del_client_entry(SilcClient client, @@ -841,13 +894,10 @@ SilcBool silc_client_del_client(SilcClient client, SilcClientConnection conn, if (!client_entry) return FALSE; - SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry, - silc_atomic_get_int8(&client_entry->internal.refcnt), - silc_atomic_get_int8(&client_entry->internal.refcnt) - 1)); if (silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) > 0) return FALSE; - SILC_LOG_DEBUG(("Deleting client %p")); + SILC_LOG_DEBUG(("Deleting client %p", client_entry)); silc_mutex_lock(conn->internal->lock); ret = silc_idcache_del_by_context(conn->internal->client_cache, @@ -881,13 +931,12 @@ void silc_client_ref_client(SilcClient client, SilcClientConnection conn, void silc_client_unref_client(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { - if (client_entry) + if (client_entry) { SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry, silc_atomic_get_int8(&client_entry->internal.refcnt), silc_atomic_get_int8(&client_entry->internal.refcnt) - 1)); - if (client_entry && - silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) == 0) silc_client_del_client(client, conn, client_entry); + } } /* Free client entry list */ @@ -909,11 +958,13 @@ void silc_client_list_free(SilcClient client, SilcClientConnection conn, /* Formats the nickname of the client specified by the `client_entry'. If the format is specified by the application this will format the nickname and replace the old nickname in the client entry. If the - format string is not specified then this function has no effect. */ + format string is not specified then this function has no effect. + Returns the client entry that was formatted. */ -void silc_client_nickname_format(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry) +SilcClientEntry silc_client_nickname_format(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry, + SilcBool priority) { char *cp; char newnick[128 + 1]; @@ -922,21 +973,25 @@ void silc_client_nickname_format(SilcClient client, SilcDList clients; SilcClientEntry entry, unformatted = NULL; - SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("Format nickname")); if (!client->internal->params->nickname_format[0]) - return; - + return client_entry; if (!client_entry->nickname[0]) - return; + return NULL; /* Get all clients with same nickname. Do not perform the formatting if there aren't any clients with same nickname unless the application is forcing us to do so. */ clients = silc_client_get_clients_local(client, conn, client_entry->nickname, NULL); - if (!clients && !client->internal->params->nickname_force_format) - return; + if (!clients) + return NULL; + if (silc_dlist_count(clients) == 1 && + !client->internal->params->nickname_force_format) { + silc_client_list_free(client, conn, clients); + return client_entry; + } len = 0; freebase = TRUE; @@ -947,15 +1002,16 @@ void silc_client_nickname_format(SilcClient client, silc_utf8_strcasecmp(entry->nickname, client_entry->nickname)) { freebase = FALSE; unformatted = entry; + break; } } - if (!len || freebase) - return; + if (!len || freebase) { + silc_client_list_free(client, conn, clients); + return client_entry; + } - /* If we are changing nickname of our local entry we'll enforce - that we will always get the unformatted nickname. Give our - format number to the one that is not formatted now. */ - if (unformatted && client_entry == conn->local_entry) + /* If priority formatting, this client always gets unformatted nickname. */ + if (unformatted && priority) client_entry = unformatted; memset(newnick, 0, sizeof(newnick)); @@ -1031,7 +1087,7 @@ void silc_client_nickname_format(SilcClient client, } memset(tmp, 0, sizeof(tmp)); - snprintf(tmp, sizeof(tmp) - 1, "%d", ++max); + silc_snprintf(tmp, sizeof(tmp) - 1, "%d", ++max); len = strlen(tmp); memcpy(&newnick[off], tmp, len); off += len; @@ -1050,6 +1106,79 @@ void silc_client_nickname_format(SilcClient client, newnick[off] = 0; memcpy(client_entry->nickname, newnick, strlen(newnick)); silc_client_list_free(client, conn, clients); + + return client_entry; +} + +/* Parses nickname according to nickname format string */ + +SilcBool silc_client_nickname_parse(SilcClient client, + SilcClientConnection conn, + char *nickname, + char **ret_nick) +{ + char *cp, s = 0, e = 0, *nick; + SilcBool n = FALSE; + int len; + + if (!client->internal->params->nickname_format[0]) + return TRUE; + + if (!nickname || !nickname[0]) + return FALSE; + + cp = client->internal->params->nickname_format; + while (cp && *cp) { + if (*cp == '%') { + cp++; + continue; + } + + switch(*cp) { + case 'n': + n = TRUE; + break; + + case 'h': + case 'H': + case 's': + case 'S': + case 'a': + break; + + default: + /* Get separator character */ + if (n) + e = *cp; + else + s = *cp; + break; + } + + cp++; + } + if (!n) + return FALSE; + + /* Parse the nickname */ + nick = nickname; + len = strlen(nick); + if (s) + if (strchr(nickname, s)) + nick = strchr(nickname, s) + 1; + if (e) + if (strchr(nick, e)) + len = strchr(nick, e) - nick; + if (!len) + return FALSE; + + *ret_nick = silc_memdup(nick, len); + if (!(*ret_nick)) + return FALSE; + + SILC_LOG_DEBUG(("Parsed nickname: %s", *ret_nick)); + + return TRUE; } /************************ Channel Searching Locally *************************/ @@ -1284,7 +1413,7 @@ SilcChannelEntry silc_client_add_channel(SilcClient client, if (!channel) return NULL; - silc_atomic_init8(&channel->internal.refcnt, 0); + silc_atomic_init16(&channel->internal.refcnt, 0); channel->id = *channel_id; channel->mode = mode; @@ -1328,7 +1457,7 @@ SilcChannelEntry silc_client_add_channel(SilcClient client, silc_mutex_unlock(conn->internal->lock); silc_client_ref_channel(client, conn, channel); - SILC_LOG_DEBUG(("Added")); + SILC_LOG_DEBUG(("Added %p", channel)); return channel; } @@ -1345,7 +1474,7 @@ SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn, if (!channel) return FALSE; - if (silc_atomic_sub_int8(&channel->internal.refcnt, 1) > 0) + if (silc_atomic_sub_int16(&channel->internal.refcnt, 1) > 0) return FALSE; SILC_LOG_DEBUG(("Deleting channel %p", channel)); @@ -1359,6 +1488,7 @@ SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn, return FALSE; silc_client_empty_channel(client, conn, channel); + silc_hash_table_free(channel->user_list); silc_free(channel->channel_name); silc_free(channel->topic); if (channel->founder_key) @@ -1379,8 +1509,11 @@ SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn, silc_hmac_free(hmac); silc_dlist_uninit(channel->internal.old_hmacs); } + if (channel->channel_pubkeys) + silc_argument_list_free(channel->channel_pubkeys, + SILC_ARGUMENT_PUBLIC_KEY); silc_client_del_channel_private_keys(client, conn, channel); - silc_atomic_uninit8(&channel->internal.refcnt); + silc_atomic_uninit16(&channel->internal.refcnt); silc_schedule_task_del_by_context(conn->client->schedule, channel); silc_free(channel); @@ -1419,7 +1552,10 @@ SilcBool silc_client_replace_channel_id(SilcClient client, void silc_client_ref_channel(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel_entry) { - silc_atomic_add_int8(&channel_entry->internal.refcnt, 1); + silc_atomic_add_int16(&channel_entry->internal.refcnt, 1); + SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry, + silc_atomic_get_int16(&channel_entry->internal.refcnt) - 1, + silc_atomic_get_int16(&channel_entry->internal.refcnt))); } /* Release reference of channel entry */ @@ -1427,9 +1563,13 @@ void silc_client_ref_channel(SilcClient client, SilcClientConnection conn, void silc_client_unref_channel(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel_entry) { - if (channel_entry && - silc_atomic_sub_int8(&channel_entry->internal.refcnt, 1) == 0) + if (channel_entry) { + SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry, + silc_atomic_get_int16(&channel_entry->internal.refcnt), + silc_atomic_get_int16(&channel_entry->internal.refcnt) + - 1)); silc_client_del_channel(client, conn, channel_entry); + } } /* Free channel entry list */ @@ -1698,7 +1838,7 @@ SilcServerEntry silc_client_add_server(SilcClient client, silc_mutex_unlock(conn->internal->lock); silc_client_ref_server(client, conn, server_entry); - SILC_LOG_DEBUG(("Added")); + SILC_LOG_DEBUG(("Added %p", server_entry)); return server_entry; } @@ -1780,6 +1920,9 @@ void silc_client_ref_server(SilcClient client, SilcClientConnection conn, SilcServerEntry server_entry) { silc_atomic_add_int8(&server_entry->internal.refcnt, 1); + SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry, + silc_atomic_get_int8(&server_entry->internal.refcnt) - 1, + silc_atomic_get_int8(&server_entry->internal.refcnt))); } /* Release reference of server entry */ @@ -1787,9 +1930,13 @@ void silc_client_ref_server(SilcClient client, SilcClientConnection conn, void silc_client_unref_server(SilcClient client, SilcClientConnection conn, SilcServerEntry server_entry) { - if (server_entry && - silc_atomic_sub_int8(&server_entry->internal.refcnt, 1) == 0) + if (server_entry) { + SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry, + silc_atomic_get_int8(&server_entry->internal.refcnt), + silc_atomic_get_int8(&server_entry->internal.refcnt) + - 1)); silc_client_del_server(client, conn, server_entry); + } } /* Free server entry list */