updates.
[silc.git] / apps / silc / client_ops.c
index 0dd9d1ef7859ea6cada76443e7f107418ca28f59..acf3186a237fbc8fdda1d116d03c22a61777b4da 100644 (file)
@@ -46,32 +46,215 @@ void silc_say(SilcClient client, SilcClientConnection conn,
    received in the packet. The `channel_name' is the name of the channel. */
 
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
-                         char *sender, char *channel_name, char *msg)
+                         SilcClientEntry sender, SilcChannelEntry channel
+                         , char *msg)
 {
   /* Message from client */
-  if (!strcmp(conn->current_channel->channel_name, channel_name))
-    silc_print(client, "<%s> %s", sender, msg);
+  if (conn && !strcmp(conn->current_channel->channel_name, 
+                     channel->channel_name))
+    silc_print(client, "<%s> %s", sender ? sender->nickname : "[<unknown>]", 
+              msg);
   else
-    silc_print(client, "<%s:%s> %s", sender, channel_name, msg);
+    silc_print(client, "<%s:%s> %s", sender ? sender->nickname : "[<unknown>]",
+              channel->channel_name, msg);
 }
 
 /* Private message to the client. The `sender' is the nickname of the
    sender received in the packet. */
 
 void silc_private_message(SilcClient client, SilcClientConnection conn,
-                         char *sender, char *msg)
+                         SilcClientEntry sender, char *msg)
 {
-  silc_print(client, "*%s* %s", sender, msg);
+  silc_print(client, "*%s* %s", sender->nickname, msg);
 }
 
 
-/* Notify message to the client.  The `type' is the notify type received
-   from server.  The `msg' is a human readable message sent by the server. */
+/* Notify message to the client. The notify arguments are sent in the
+   same order as servers sends them. The arguments are same as received
+   from the server except for ID's.  If ID is received application receives
+   the corresponding entry to the ID. For example, if Client ID is received
+   application receives SilcClientEntry.  Also, if the notify type is
+   for channel the channel entry is sent to application (even if server
+   does not send it). */
 
 void silc_notify(SilcClient client, SilcClientConnection conn, 
-                SilcNotifyType type, char *msg)
+                SilcNotifyType type, ...)
 {
-  silc_print(client, "*** %s", msg);
+  SilcClientInternal app = (SilcClientInternal)client->application;
+  va_list vp;
+  char message[4096];
+  SilcClientEntry client_entry, client_entry2;
+  SilcChannelEntry channel_entry;
+  char *tmp = NULL;
+  unsigned int tmp_int;
+
+  va_start(vp, type);
+
+  memset(message, 0, sizeof(message));
+
+  /* Get arguments (defined by protocol in silc-pp-01 -draft) */
+  switch(type) {
+  case SILC_NOTIFY_TYPE_NONE:
+    tmp = va_arg(vp, char *);
+    if (!tmp)
+      return;
+    strcpy(message, tmp);
+    break;
+
+  case SILC_NOTIFY_TYPE_INVITE:
+    client_entry = va_arg(vp, SilcClientEntry);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+    snprintf(message, sizeof(message), "%s invites you to channel %s", 
+            client_entry->nickname, channel_entry->channel_name);
+    break;
+
+  case SILC_NOTIFY_TYPE_JOIN:
+    client_entry = va_arg(vp, SilcClientEntry);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+    snprintf(message, sizeof(message), "%s (%s) has joined channel %s", 
+            client_entry->nickname, client_entry->username, 
+            channel_entry->channel_name);
+    break;
+
+  case SILC_NOTIFY_TYPE_LEAVE:
+    client_entry = va_arg(vp, SilcClientEntry);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+    if (client_entry->server)
+      snprintf(message, sizeof(message), "%s@%s has left channel %s", 
+              client_entry->nickname, client_entry->server, 
+              channel_entry->channel_name);
+    else
+      snprintf(message, sizeof(message), "%s has left channel %s", 
+              client_entry->nickname, channel_entry->channel_name);
+    break;
+
+  case SILC_NOTIFY_TYPE_SIGNOFF:
+    client_entry = va_arg(vp, SilcClientEntry);
+    tmp = va_arg(vp, char *);
+    if (client_entry->server)
+      snprintf(message, sizeof(message), "Signoff: %s@%s %s%s%s", 
+              client_entry->nickname, client_entry->server,
+              tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+    else
+      snprintf(message, sizeof(message), "Signoff: %s %s%s%s", 
+              client_entry->nickname,
+              tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+    break;
+
+  case SILC_NOTIFY_TYPE_TOPIC_SET:
+    client_entry = va_arg(vp, SilcClientEntry);
+    tmp = va_arg(vp, char *);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+    if (client_entry->server)
+      snprintf(message, sizeof(message), "%s@%s set topic on %s: %s", 
+              client_entry->nickname, client_entry->server,
+              channel_entry->channel_name, tmp);
+    else
+      snprintf(message, sizeof(message), "%s set topic on %s: %s", 
+              client_entry->nickname, channel_entry->channel_name, tmp);
+    break;
+
+  case SILC_NOTIFY_TYPE_NICK_CHANGE:
+    client_entry = va_arg(vp, SilcClientEntry);
+    client_entry2 = va_arg(vp, SilcClientEntry);
+    if (client_entry->server && client_entry2->server)
+      snprintf(message, sizeof(message), "%s@%s is known as %s@%s", 
+              client_entry->nickname, client_entry->server,
+              client_entry2->nickname, client_entry2->server);
+    else
+      snprintf(message, sizeof(message), "%s is known as %s", 
+              client_entry->nickname, client_entry2->nickname);
+    break;
+
+  case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+    client_entry = va_arg(vp, SilcClientEntry);
+    tmp = silc_client_chmode(va_arg(vp, unsigned int));
+    channel_entry = va_arg(vp, SilcChannelEntry);
+    if (tmp)
+      snprintf(message, sizeof(message), "%s changed channel mode to +%s", 
+              client_entry->nickname, tmp);
+    else
+      snprintf(message, sizeof(message), "%s removed all channel modes", 
+              client_entry->nickname);
+    if (app->screen->bottom_line->channel_mode)
+      silc_free(app->screen->bottom_line->channel_mode);
+    app->screen->bottom_line->channel_mode = tmp;
+    silc_screen_print_bottom_line(app->screen, 0);
+    break;
+
+  case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+    client_entry = va_arg(vp, SilcClientEntry);
+    tmp_int = va_arg(vp, unsigned int);
+    tmp = silc_client_chumode(tmp_int);
+    client_entry2 = va_arg(vp, SilcClientEntry);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+    if (tmp)
+      snprintf(message, sizeof(message), "%s changed %s's mode to +%s", 
+              client_entry->nickname, client_entry2->nickname, tmp);
+    else
+      snprintf(message, sizeof(message), "%s removed %s's modes", 
+              client_entry->nickname, client_entry2->nickname);
+    if (client_entry2 == conn->local_entry) {
+      if (app->screen->bottom_line->mode)
+       silc_free(app->screen->bottom_line->mode);
+      app->screen->bottom_line->mode = silc_client_chumode_char(tmp_int);
+      silc_screen_print_bottom_line(app->screen, 0);
+    }
+    silc_free(tmp);
+    break;
+
+  case SILC_NOTIFY_TYPE_MOTD:
+    {
+      char line[256];
+      int i;
+      tmp = va_arg(vp, unsigned char *);
+
+      i = 0;
+      while(tmp[i] != 0) {
+       if (tmp[i++] == '\n') {
+         memset(line, 0, sizeof(line));
+         strncat(line, tmp, i - 1);
+         tmp += i;
+         
+         silc_say(client, conn, "%s", line);
+         
+         if (!strlen(tmp))
+           break;
+         i = 0;
+       }
+      }
+    }
+    return;
+
+  case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
+    break;
+
+  case SILC_NOTIFY_TYPE_KICKED:
+    client_entry = va_arg(vp, SilcClientEntry);
+    tmp = va_arg(vp, char *);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+
+    if (client_entry == conn->local_entry) {
+      snprintf(message, sizeof(message), 
+              "You have been kicked off channel %s %s%s%s", 
+              conn->current_channel->channel_name,
+              tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+    } else {
+      snprintf(message, sizeof(message), 
+              "%s%s%s has been kicked off channel %s %s%s%s", 
+              client_entry->nickname, 
+              client_entry->server ? "@" : "",
+              client_entry->server ? client_entry->server : "",
+              conn->current_channel->channel_name,
+              tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  silc_print(client, "*** %s", message);
 }
 
 /* Command handler. This function is called always in the command function.
@@ -129,29 +312,57 @@ void silc_command(SilcClient client, SilcClientConnection conn,
 
 void silc_command_reply(SilcClient client, SilcClientConnection conn,
                        SilcCommandPayload cmd_payload, int success,
-                       SilcCommand command, ...)
+                       SilcCommand command, SilcCommandStatus status, ...)
 {
   SilcClientInternal app = (SilcClientInternal)client->application;
+  SilcChannelUser chu;
   va_list vp;
 
   if (!success)
     return;
 
-  va_start(vp, command);
+  va_start(vp, status);
 
   switch(command)
     {
 
     case SILC_COMMAND_JOIN:
-      app->screen->bottom_line->channel = va_arg(vp, char *);
-      silc_screen_print_bottom_line(app->screen, 0);
+      {
+       unsigned int mode;
+
+       app->screen->bottom_line->channel = va_arg(vp, char *);
+       (void)va_arg(vp, void *);
+       mode = va_arg(vp, unsigned int);
+       app->screen->bottom_line->channel_mode = silc_client_chmode(mode);
+       silc_screen_print_bottom_line(app->screen, 0);
+      }
       break;
 
     case SILC_COMMAND_NICK:
-      app->screen->bottom_line->nickname = va_arg(vp, char *);
-      silc_screen_print_bottom_line(app->screen, 0);
+      {
+       SilcClientEntry entry;
+
+       entry = va_arg(vp, SilcClientEntry);
+       silc_say(client, conn, "Your current nickname is %s", entry->nickname);
+       app->screen->bottom_line->nickname = entry->nickname;
+       silc_screen_print_bottom_line(app->screen, 0);
+      }
       break;
 
+    case SILC_COMMAND_USERS:
+      silc_list_start(conn->current_channel->clients);
+      while ((chu = silc_list_get(conn->current_channel->clients)) 
+            != SILC_LIST_END) {
+       if (chu->client == conn->local_entry) {
+         if (app->screen->bottom_line->mode)
+           silc_free(app->screen->bottom_line->mode);
+         app->screen->bottom_line->mode = 
+           silc_client_chumode_char(chu->mode);
+         silc_screen_print_bottom_line(app->screen, 0);
+         break;
+       }
+      break;
+      }
     }
 }
 
@@ -178,6 +389,7 @@ void silc_disconnect(SilcClient client, SilcClientConnection conn)
 
   app->screen->bottom_line->connection = NULL;
   silc_screen_print_bottom_line(app->screen, 0);
+  app->conn = NULL;
 }
 
 /* Asks passphrase from user on the input line. */
@@ -406,6 +618,37 @@ int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
   return FALSE;
 }
 
+/* Notifies application that failure packet was received.  This is called
+   if there is some protocol active in the client.  The `protocol' is the
+   protocol context.  The `failure' is opaque pointer to the failure
+   indication.  Note, that the `failure' is protocol dependant and application
+   must explicitly cast it to correct type.  Usually `failure' is 32 bit
+   failure type (see protocol specs for all protocol failure types). */
+
+void silc_failure(SilcClient client, SilcClientConnection conn, 
+                 SilcProtocol protocol, void *failure)
+{
+  SilcClientInternal app = (SilcClientInternal)client->application;
+
+}
+
+/* Asks whether the user would like to perform the key agreement protocol.
+   This is called after we have received an key agreement packet or an
+   reply to our key agreement packet. This returns TRUE if the user wants
+   the library to perform the key agreement protocol and FALSE if it is not
+   desired (application may start it later by calling the function
+   silc_client_perform_key_agreement). */
+
+int silc_key_agreement(SilcClient client, SilcClientConnection conn,
+                      SilcClientEntry client_entry, char *hostname,
+                      int port,
+                      SilcKeyAgreementCallback *completion,
+                      void **context)
+{
+
+  return FALSE;
+}
+
 /* SILC client operations */
 SilcClientOperations ops = {
   say:                  silc_say,
@@ -419,4 +662,6 @@ SilcClientOperations ops = {
   get_auth_method:      silc_get_auth_method,
   verify_server_key:    silc_verify_server_key,
   ask_passphrase:       silc_ask_passphrase,
+  failure:              silc_failure,
+  key_agreement:        silc_key_agreement,
 };