Merged silc_1_1_branch to trunk.
[silc.git] / apps / irssi / src / silc / core / silc-servers.c
index 38ea4f487addd8d4aa504621f8ab37caf35cbe1c..e16fb02cdc056fef1116a982f49259c3bf0d7483 100644 (file)
@@ -33,6 +33,7 @@
 #include "settings.h"
 
 #include "servers-setup.h"
+#include "channels-setup.h"
 
 #include "client_ops.h"
 #include "silc-servers.h"
@@ -88,48 +89,38 @@ static void silc_send_msg_clients(SilcClient client,
   PRIVMSG_REC *rec = context;
   SILC_SERVER_REC *server = rec->server;
   SilcClientEntry target;
-  char nickname[128 + 1];
-  SilcDList lclients = NULL;
 
   if (!clients) {
     printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
              "%s: There is no such client", rec->nick);
-  } else {
-    if (silc_dlist_count(clients) > 1) {
-      silc_parse_userfqdn(rec->nick, nickname, sizeof(nickname), NULL, 0);
-
-      /* Find the correct one. The rec->nick might be a formatted nick
-        so this will find the correct one. */
-      clients = lclients =
-       silc_client_get_clients_local(silc_client, server->conn,
-                                     nickname, rec->nick);
-      if (!clients) {
-       printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
-                 "%s: There is no such client", rec->nick);
-       goto out;
-      }
-    }
-
-    target = silc_dlist_get(clients);
+    goto out;
+  }
 
-    /* Still check for exact math for nickname, this compares the
-       real (formatted) nickname and the nick (maybe formatted) that
-       user gave. This is to assure that `nick' does not match
-       `nick@host'. */
-    if (!silc_utf8_strcasecmp(rec->nick, target->nickname)) {
+  /* Find the correct one. The rec->nick might be a formatted nick
+     so this will find the correct one. */
+  target = silc_dlist_get(clients);
+  clients = silc_client_get_clients_local(silc_client, server->conn,
+                                         rec->nick, FALSE);
+  if (!clients) {
+    if (strchr(rec->nick, '@') && target->server)
       printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
-               "%s: There is no such client", rec->nick);
-      goto out;
-    }
-
-    /* Send the private message */
-    silc_client_send_private_message(client, conn, target,
-                                    rec->flags, sha1hash,
-                                    rec->msg, rec->len);
+               "%s: There is no such client (did you mean %s@%s?)", rec->nick,
+               target->nickname, target->server);
+    else
+      printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+               "%s: There is no such client (did you mean %s?)", rec->nick,
+               target->nickname);
+    goto out;
   }
 
+  /* Send the private message */
+  silc_dlist_start(clients);
+  target = silc_dlist_get(clients);
+  silc_client_send_private_message(client, conn, target, rec->flags, sha1hash,
+                                  rec->msg, rec->len);
+
  out:
-  silc_client_list_free(silc_client, server->conn, lclients);
+  silc_client_list_free(silc_client, server->conn, clients);
   g_free(rec->nick);
   g_free(rec->msg);
   g_free(rec);
@@ -139,21 +130,16 @@ int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
                  int msg_len, SilcMessageFlags flags)
 {
   PRIVMSG_REC *rec;
-  char nickname[128 + 1];
   SilcDList clients;
   SilcClientEntry target;
   int ret;
 
-  if (!silc_parse_userfqdn(nick, nickname, sizeof(nickname), NULL, 0)) {
-    printformat_module("fe-common/silc", server, NULL,
-                      MSGLEVEL_CRAP, SILCTXT_BAD_NICK, nick);
-    return FALSE;
-  }
-
   /* Find client entry */
-  clients = silc_client_get_clients_local(silc_client, server->conn,
-                                         nickname, nick);
+  clients = silc_client_get_clients_local(silc_client, server->conn, nick,
+                                         FALSE);
   if (!clients) {
+    char *nickname = NULL;
+
     rec = g_new0(PRIVMSG_REC, 1);
     rec->nick = g_strdup(nick);
     rec->msg = g_strdup(msg);
@@ -161,10 +147,14 @@ int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
     rec->flags = flags;
     rec->len = msg_len;
 
+    silc_client_nickname_parse(silc_client, server->conn, nick, &nickname);
+    if (!nickname)
+      nickname = strdup(nick);
+
     /* Could not find client with that nick, resolve it from server. */
-    silc_client_get_clients_whois(silc_client, server->conn,
-                                 nickname, NULL, NULL,
-                                 silc_send_msg_clients, rec);
+    silc_client_get_clients_whois(silc_client, server->conn, nickname,
+                                 NULL, NULL, silc_send_msg_clients, rec);
+    silc_free(nickname);
     return TRUE;
   }
 
@@ -290,6 +280,7 @@ static void silc_connect_cb(SilcClient client,
                            void *context)
 {
   SILC_SERVER_REC *server = context;
+  FtpSession ftp;
   char *file;
 
   SILC_LOG_DEBUG(("Connection callback %p, status %d, error %d, message %s",
@@ -308,10 +299,13 @@ static void silc_connect_cb(SilcClient client,
 
     /* Enable queueing until we have our requested nick */
     if (((opt_nickname &&
-         strcmp(opt_nickname, conn->local_entry->nickname)) ||
+         !silc_utf8_strcasecmp(opt_nickname,
+                               conn->local_entry->nickname)) ||
         (settings_get_str("nick") &&
-         strcmp(settings_get_str("nick"), conn->local_entry->nickname))) &&
-       !strcmp(conn->local_entry->nickname, conn->local_entry->username))
+         !silc_utf8_strcasecmp(settings_get_str("nick"),
+                               conn->local_entry->nickname))) &&
+       silc_utf8_strcasecmp(conn->local_entry->nickname,
+                            conn->local_entry->username))
       silc_queue_enable(conn);
 
     /* Put default attributes */
@@ -360,6 +354,12 @@ static void silc_connect_cb(SilcClient client,
               silc_get_status_message(error), error,
               message ? message : "");
 
+    /* Close FTP sessions */
+    silc_dlist_start(server->ftp_sessions);
+    while ((ftp = silc_dlist_get(server->ftp_sessions)))
+      silc_client_file_close(client, conn, ftp->session_id);
+    silc_dlist_uninit(server->ftp_sessions);
+
     if (server->conn)
       server->conn->context = NULL;
     server->conn = NULL;
@@ -396,6 +396,7 @@ static void sig_connected_stream_created(SilcSocketStreamStatus status,
   SilcClientConnectionParams params;
   char *file;
 
+  server->tcp_op = NULL;
   if (!stream) {
     server->connection_lost = TRUE;
     server_disconnect(SERVER(server));
@@ -423,6 +424,7 @@ static void sig_connected_stream_created(SilcSocketStreamStatus status,
   if (params.detach_data)
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                        SILCTXT_REATTACH, server->tag);
+  silc_free(file);
 
   /* Start key exchange */
   server->op = silc_client_key_exchange(silc_client, &params,
@@ -453,8 +455,10 @@ static void sig_connected(SILC_SERVER_REC *server)
 
   /* Wrap the socket to TCP stream */
   fd = g_io_channel_unix_get_fd(net_sendbuffer_handle(server->handle));
-  silc_socket_tcp_stream_create(fd, TRUE, FALSE, silc_client->schedule,
-                               sig_connected_stream_created, server);
+  server->tcp_op =
+    silc_socket_tcp_stream_create(fd, TRUE, FALSE,
+                                 silc_client->schedule,
+                                 sig_connected_stream_created, server);
 }
 
 static void sig_disconnected(SILC_SERVER_REC *server)
@@ -462,8 +466,6 @@ static void sig_disconnected(SILC_SERVER_REC *server)
   if (!IS_SILC_SERVER(server))
     return;
 
-  silc_dlist_uninit(server->ftp_sessions);
-
   if (server->conn) {
     /* Close connection */
     silc_client_close_connection(silc_client, server->conn);
@@ -471,12 +473,18 @@ static void sig_disconnected(SILC_SERVER_REC *server)
     /* Abort on going connecting (key exchange) */
     silc_async_abort(server->op, NULL, NULL);
     server->op = NULL;
+  } else if (server->tcp_op) {
+    /* Abort on going TCP stream creation */
+    silc_async_abort(server->tcp_op, NULL, NULL);
+    server->tcp_op = NULL;
   }
 
   /* SILC closes the handle */
-  g_io_channel_unref(net_sendbuffer_handle(server->handle));
-  net_sendbuffer_destroy(server->handle, FALSE);
-  server->handle = NULL;
+  if (server->handle) {
+    g_io_channel_unref(net_sendbuffer_handle(server->handle));
+    net_sendbuffer_destroy(server->handle, FALSE);
+    server->handle = NULL;
+  }
 }
 
 SERVER_REC *silc_server_init_connect(SERVER_CONNECT_REC *conn)
@@ -526,8 +534,14 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
   chans = g_string_new(NULL);
   for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
     CHANNEL_REC *channel = tmp->data;
+    CHANNEL_SETUP_REC *schannel;
 
-    g_string_sprintfa(chans, "%s,", channel->name);
+    if ((schannel = channel_setup_find(channel->name, server->connrec->chatnet)) &&
+        schannel->password)
+      g_string_sprintfa(chans, "%s %s,", channel->name,
+                       schannel->password);
+    else
+      g_string_sprintfa(chans, "%s,", channel->name);
   }
 
   if (chans->len > 0)
@@ -851,8 +865,8 @@ static void silc_client_command_file_get_clients(SilcClient client,
   FileGetClients internal = (FileGetClients)context;
 
   if (!clients) {
-    printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
-             internal->nick);
+    printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+             "There was no such nickname: %s", internal->nick);
     silc_free(internal->data);
     silc_free(internal->nick);
     silc_free(internal);
@@ -874,7 +888,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
   SilcClientEntry client_entry;
   SilcDList entries;
   SilcClientFileError ret;
-  char nickname[128 + 1], *tmp;
+  char *nickname = NULL, *tmp;
   unsigned char **argv;
   SilcUInt32 argc;
   SilcUInt32 *argv_lens, *argv_types;
@@ -918,22 +932,19 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
       cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
 
     /* Parse the typed nickname. */
-    if (!silc_parse_userfqdn(argv[3], nickname, sizeof(nickname), NULL, 0)) {
-      printformat_module("fe-common/silc", server, NULL,
-                        MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[3]);
-      goto out;
-    }
+    silc_client_nickname_parse(silc_client, conn, argv[3], &nickname);
+    if (!nickname)
+      nickname = strdup(argv[3]);
 
     /* Find client entry */
-    entries = silc_client_get_clients_local(silc_client, conn, nickname,
-                                           argv[3]);
+    entries = silc_client_get_clients_local(silc_client, conn, argv[3], FALSE);
     if (!entries) {
       FileGetClients inter = silc_calloc(1, sizeof(*inter));
       inter->server = server;
       inter->data = strdup(data);
       inter->nick = strdup(nickname);
       inter->item = item;
-      silc_client_get_clients(silc_client, conn, nickname, argv[3],
+      silc_client_get_clients(silc_client, conn, nickname, NULL,
                              silc_client_command_file_get_clients, inter);
       goto out;
     }
@@ -1013,22 +1024,21 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
   case 2:
     /* Parse the typed nickname. */
     if (argc >= 3) {
-      if (!silc_parse_userfqdn(argv[2], nickname, sizeof(nickname), NULL, 0)) {
-       printformat_module("fe-common/silc", server, NULL,
-                          MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
-       goto out;
-      }
+      /* Parse the typed nickname. */
+      silc_client_nickname_parse(silc_client, conn, argv[2], &nickname);
+      if (!nickname)
+       nickname = strdup(argv[2]);
 
       /* Find client entry */
-      entries = silc_client_get_clients_local(silc_client, conn, nickname,
-                                             argv[2]);
+      entries = silc_client_get_clients_local(silc_client, conn, argv[2],
+                                             FALSE);
       if (!entries) {
        FileGetClients inter = silc_calloc(1, sizeof(*inter));
        inter->server = server;
        inter->data = strdup(data);
        inter->nick = strdup(nickname);
        inter->item = item;
-       silc_client_get_clients(silc_client, conn, nickname, argv[2],
+       silc_client_get_clients(silc_client, conn, nickname, NULL,
                                silc_client_command_file_get_clients, inter);
        goto out;
       }
@@ -1146,22 +1156,21 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
   case 3:
     /* Parse the typed nickname. */
     if (argc >= 3) {
-      if (!silc_parse_userfqdn(argv[2], nickname, sizeof(nickname), NULL, 0)) {
-       printformat_module("fe-common/silc", server, NULL,
-                          MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
-       goto out;
-      }
+      /* Parse the typed nickname. */
+      silc_client_nickname_parse(silc_client, conn, argv[2], &nickname);
+      if (!nickname)
+       nickname = strdup(argv[2]);
 
       /* Find client entry */
-      entries = silc_client_get_clients_local(silc_client, conn, nickname,
-                                             argv[2]);
+      entries = silc_client_get_clients_local(silc_client, conn, argv[2],
+                                             FALSE);
       if (!entries) {
        FileGetClients inter = silc_calloc(1, sizeof(*inter));
        inter->server = server;
        inter->data = strdup(data);
        inter->nick = strdup(nickname);
        inter->item = item;
-       silc_client_get_clients(silc_client, conn, nickname, argv[2],
+       silc_client_get_clients(silc_client, conn, nickname, NULL,
                                silc_client_command_file_get_clients, inter);
        goto out;
       }
@@ -1251,6 +1260,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
   }
 
  out:
+  silc_free(nickname);
   return;
 }