Added connection authentication request support.
[silc.git] / lib / silcclient / client_notify.c
index 068b22d5926560c9dc9c9389a27f3e85eb96c8d1..7cdb688c5e0cbcadc544290eeb805be007569e8f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -75,7 +75,7 @@ static SilcBool silc_client_notify_wait_continue(SilcClient client,
   /* Continue after last command reply received */
   if (SILC_STATUS_IS_ERROR(status) || status == SILC_STATUS_OK ||
       status == SILC_STATUS_LIST_END)
-    SILC_FSM_CALL_CONTINUE(notify->fsm);
+    SILC_FSM_CALL_CONTINUE_SYNC(notify->fsm);
 
   return TRUE;
 }
@@ -95,21 +95,21 @@ SILC_FSM_STATE(silc_client_notify)
   if (!payload) {
     SILC_LOG_DEBUG(("Malformed notify payload"));
     silc_packet_free(packet);
-    return SILC_FSM_FINISH;
+    SILC_FSM_FINISH;
   }
 
   if (!silc_notify_get_args(payload)) {
-    SILC_LOG_DEBUG(("Malformed notify"));
+    SILC_LOG_DEBUG(("Malformed notify %d", silc_notify_get_type(payload)));
     silc_notify_payload_free(payload);
     silc_packet_free(packet);
-    return SILC_FSM_FINISH;
+    SILC_FSM_FINISH;
   }
 
   notify = silc_calloc(1, sizeof(*notify));
   if (!notify) {
     silc_notify_payload_free(payload);
     silc_packet_free(packet);
-    return SILC_FSM_FINISH;
+    SILC_FSM_FINISH;
   }
 
   /* Save notify payload to packet context during processing */
@@ -206,11 +206,11 @@ SILC_FSM_STATE(silc_client_notify)
     silc_notify_payload_free(payload);
     silc_packet_free(packet);
     silc_free(notify);
-    return SILC_FSM_FINISH;
+    SILC_FSM_FINISH;
     break;
   }
 
-  return SILC_FSM_YIELD;
+  SILC_FSM_YIELD;
 }
 
 /* Notify processed, finish the packet processing thread */
@@ -224,7 +224,7 @@ SILC_FSM_STATE(silc_client_notify_processed)
   silc_notify_payload_free(payload);
   silc_packet_free(packet);
   silc_free(notify);
-  return SILC_FSM_FINISH;
+  SILC_FSM_FINISH;
 }
 
 /********************************** NONE ************************************/
@@ -245,7 +245,7 @@ SILC_FSM_STATE(silc_client_notify_none)
 
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /********************************* INVITE ***********************************/
@@ -279,6 +279,8 @@ SILC_FSM_STATE(silc_client_notify_invite)
 
   /* Get the channel entry */
   channel = silc_client_get_channel_by_id(client, conn, &id.u.channel_id);
+  if (!channel)
+    goto out;
 
   /* If channel is being resolved handle notify after resolving */
   if (channel->internal.resolve_cmd_ident) {
@@ -318,7 +320,7 @@ SILC_FSM_STATE(silc_client_notify_invite)
   /** Notify processed */
   silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /********************************** JOIN ************************************/
@@ -379,7 +381,7 @@ SILC_FSM_STATE(silc_client_notify_join)
   }
 
   if (client_entry != conn->local_entry)
-    silc_client_nickname_format(client, conn, client_entry);
+    silc_client_nickname_format(client, conn, client_entry, FALSE);
 
   /* Join the client to channel */
   if (!silc_client_add_to_channel(client, conn, channel, client_entry, 0))
@@ -394,7 +396,7 @@ SILC_FSM_STATE(silc_client_notify_join)
   /** Notify processed */
   silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /********************************** LEAVE ***********************************/
@@ -456,7 +458,7 @@ SILC_FSM_STATE(silc_client_notify_leave)
   /** Notify processed */
   silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /********************************* SIGNOFF **********************************/
@@ -469,10 +471,12 @@ SILC_FSM_STATE(silc_client_notify_signoff)
   SilcClient client = conn->client;
   SilcClientNotify notify = state_context;
   SilcNotifyPayload payload = notify->payload;
+  SilcPacket packet = notify->packet;
   SilcNotifyType type = silc_notify_get_type(payload);
   SilcArgumentPayload args = silc_notify_get_args(payload);
   SilcClientEntry client_entry;
-   unsigned char *tmp;
+  SilcChannelEntry channel;
+  unsigned char *tmp;
   SilcUInt32 tmp_len;
   SilcID id;
 
@@ -489,21 +493,32 @@ SILC_FSM_STATE(silc_client_notify_signoff)
 
   /* Get signoff message */
   tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-  if (tmp_len > 128)
+  if (tmp && tmp_len > 128)
     tmp[128] = '\0';
 
   /* Notify application */
   NOTIFY(client, conn, type, client_entry, tmp);
 
+  /* Remove from channel */
+  if (packet->dst_id_type == SILC_ID_CHANNEL) {
+    if (silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
+                      &id.u.channel_id, sizeof(id.u.channel_id))) {
+      channel = silc_client_get_channel_by_id(client, conn, &id.u.channel_id);
+      if (channel) {
+       silc_client_remove_from_channel(client, conn, channel, client_entry);
+       silc_client_unref_channel(client, conn, channel);
+      }
+    }
+  }
+
   /* Delete client */
-  silc_client_remove_from_channels(client, conn, client_entry);
   silc_client_del_client(client, conn, client_entry);
   silc_client_unref_client(client, conn, client_entry);
 
  out:
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /******************************** TOPIC_SET *********************************/
@@ -620,7 +635,7 @@ SILC_FSM_STATE(silc_client_notify_topic_set)
   /** Notify processed */
   silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /****************************** NICK_CHANGE *********************************/
@@ -636,7 +651,7 @@ SILC_FSM_STATE(silc_client_notify_nick_change)
   SilcNotifyType type = silc_notify_get_type(payload);
   SilcArgumentPayload args = silc_notify_get_args(payload);
   SilcClientEntry client_entry = NULL;
-  unsigned char *tmp, *nick, oldnick[128 + 1];
+  unsigned char *tmp, oldnick[128 + 1];
   SilcUInt32 tmp_len;
   SilcID id, id2;
 
@@ -691,24 +706,11 @@ SILC_FSM_STATE(silc_client_notify_nick_change)
     goto out;
   }
 
-  /* Normalize nickname */
-  nick = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, 128, NULL);
-  if (!nick)
-    goto out;
-
-  /* Update nickname */
-  silc_mutex_lock(conn->internal->lock);
-  if (!silc_idcache_update_by_context(conn->internal->client_cache,
-                                     client_entry, NULL, nick, TRUE)) {
-    silc_free(nick);
-    silc_mutex_unlock(conn->internal->lock);
-    goto out;
-  }
-  silc_mutex_unlock(conn->internal->lock);
+  /* Change the nickname */
   memcpy(oldnick, client_entry->nickname, sizeof(client_entry->nickname));
-  memcpy(client_entry->nickname, tmp, tmp_len);
-  client_entry->nickname_normalized = nick;
-  silc_client_nickname_format(client, conn, client_entry);
+  if (!silc_client_change_nickname(client, conn, client_entry, tmp,
+                                  &id2.u.client_id, NULL, 0))
+    goto out;
 
   /* Notify application */
   NOTIFY(client, conn, type, client_entry, client_entry->nickname, oldnick);
@@ -717,7 +719,7 @@ SILC_FSM_STATE(silc_client_notify_nick_change)
   /** Notify processed */
   silc_client_unref_client(client, conn, client_entry);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /****************************** CMODE_CHANGE ********************************/
@@ -876,6 +878,8 @@ SILC_FSM_STATE(silc_client_notify_cmode_change)
     chpks = silc_argument_list_parse_decoded(tmp, tmp_len,
                                             SILC_ARGUMENT_PUBLIC_KEY);
 
+  /* XXX add to/remove from channel pubkeys channel->channel_pubkeys */
+
   /* Notify application. */
   NOTIFY(client, conn, type, id.type, entry, mode, cipher, hmac,
         passphrase, channel->founder_key, chpks, channel);
@@ -895,7 +899,7 @@ SILC_FSM_STATE(silc_client_notify_cmode_change)
 
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /***************************** CUMODE_CHANGE ********************************/
@@ -1033,7 +1037,7 @@ SILC_FSM_STATE(silc_client_notify_cumode_change)
 
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /********************************* MOTD *************************************/
@@ -1064,7 +1068,7 @@ SILC_FSM_STATE(silc_client_notify_motd)
  out:
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /**************************** CHANNEL CHANGE ********************************/
@@ -1119,7 +1123,7 @@ SILC_FSM_STATE(silc_client_notify_channel_change)
   /** Notify processed */
   silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /******************************** KICKED ************************************/
@@ -1215,7 +1219,7 @@ SILC_FSM_STATE(silc_client_notify_kicked)
   /** Notify processed */
   silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /******************************** KILLED ************************************/
@@ -1318,7 +1322,7 @@ SILC_FSM_STATE(silc_client_notify_killed)
 
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /**************************** SERVER SIGNOFF ********************************/
@@ -1370,7 +1374,7 @@ SILC_FSM_STATE(silc_client_notify_server_signoff)
   /** Notify processed */
   silc_client_list_free(client, conn, clients);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /******************************** ERROR *************************************/
@@ -1417,7 +1421,7 @@ SILC_FSM_STATE(silc_client_notify_error)
  out:
   /** Notify processed */
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }
 
 /******************************** WATCH *************************************/
@@ -1476,11 +1480,8 @@ SILC_FSM_STATE(silc_client_notify_watch)
   if (tmp) {
     char *tmp_nick = NULL;
 
-    if (client->internal->params->nickname_parse)
-      client->internal->params->nickname_parse(client_entry->nickname,
-                                              &tmp_nick);
-    else
-      tmp_nick = strdup(tmp);
+    silc_client_nickname_parse(client, conn, client_entry->nickname,
+                              &tmp_nick);
 
     /* If same nick, the client was new to us and has become "present"
        to network.  Send NULL as nick to application. */
@@ -1528,5 +1529,5 @@ SILC_FSM_STATE(silc_client_notify_watch)
   /** Notify processed */
   silc_client_unref_client(client, conn, client_entry);
   silc_fsm_next(fsm, silc_client_notify_processed);
-  return SILC_FSM_CONTINUE;
+  SILC_FSM_CONTINUE;
 }