+
+ silc_rwlock_unlock(client_entry->internal.lock);
+}
+
+/* Change a client's nickname. Must be called with `client_entry' locked. */
+
+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);
+ }
+
+ client_entry->internal.valid = TRUE;
+ return TRUE;