X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_entry.c;h=a58298fc05f81ebf0610ce48f9455910eb0d097f;hb=9905799a86c606304fd7df2cd401de1740a272a1;hp=1d3189ba04f89791e06dfef82c9aeba0ed6f02f6;hpb=77336860c5d419c9d25a6366de0269c0edb38889;p=silc.git diff --git a/lib/silcclient/client_entry.c b/lib/silcclient/client_entry.c index 1d3189ba..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); @@ -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, @@ -905,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]; @@ -918,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; @@ -943,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)); @@ -1027,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; @@ -1046,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 *************************/ @@ -1280,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; @@ -1341,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)); @@ -1376,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); @@ -1416,10 +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_int8(&channel_entry->internal.refcnt) - 1, - silc_atomic_get_int8(&channel_entry->internal.refcnt))); + silc_atomic_get_int16(&channel_entry->internal.refcnt) - 1, + silc_atomic_get_int16(&channel_entry->internal.refcnt))); } /* Release reference of channel entry */ @@ -1429,8 +1565,8 @@ void silc_client_unref_channel(SilcClient client, SilcClientConnection conn, { if (channel_entry) { SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry, - silc_atomic_get_int8(&channel_entry->internal.refcnt), - silc_atomic_get_int8(&channel_entry->internal.refcnt) + 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); }