Implement WHO for the admin network.
[jelmer/ctrlproxy.git] / src / admin.c
index c58487745a6e4b63a9aa6e07df64b54b252e0e85..29831cc74c9b77d79ca9919d305eaf407c95ea01 100644 (file)
@@ -38,7 +38,7 @@ static void privmsg_admin_out(admin_handle h, const char *data)
        char *nick = c->nick;
        char *hostmask;
 
-       hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", c->network->name);
+       hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", c->network->info.name);
        if (c->network->state) nick = c->network->state->me.nick;
        client_send_args_ex(c, hostmask, "NOTICE", nick, data, NULL);
 
@@ -50,7 +50,7 @@ static void network_admin_out(admin_handle h, const char *data)
        struct client *c = h->client;
        char *hostmask;
 
-       hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", c->network->name);
+       hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", c->network->info.name);
        virtual_network_recv_args(c->network, hostmask, "PRIVMSG", ADMIN_CHANNEL, 
                                                          data, NULL);
 
@@ -60,8 +60,6 @@ static void network_admin_out(admin_handle h, const char *data)
 static void cmd_help(admin_handle h, char **args, void *userdata)
 {
        const char *s;
-       char **lines;
-       int i;
 
        s = help_get(help, args[1] != NULL?args[1]:"index");
 
@@ -73,13 +71,13 @@ static void cmd_help(admin_handle h, char **args, void *userdata)
                return;
        }
 
-       lines = g_strsplit(s, "\n", 0);
-
-       for (i = 0; lines[i]; i++) {
-               admin_out(h, "%s", lines[i]);
+       while (strncmp(s, "%\n", 2) != 0) {
+               char *tmp;
+               admin_out(h, "%s", tmp = g_strndup(s, strchr(s, '\n')-s));
+               g_free(tmp);
+                       
+               s = strchr(s, '\n')+1;
        }
-
-       g_strfreev(lines);
 }
 
 struct client *admin_get_client(admin_handle h)
@@ -119,6 +117,11 @@ static void add_network (admin_handle h, char **args, void *userdata)
                return;
        }
 
+       if (find_network(admin_get_global(h), args[1]) != NULL) {
+               admin_out(h, "Network with name `%s' already exists", args[1]);
+               return;
+       }
+
        nc = network_config_init(admin_get_global(h)->config);
        g_free(nc->name); nc->name = g_strdup(args[1]);
        load_network(admin_get_global(h), nc);
@@ -254,7 +257,7 @@ static void com_next_server (admin_handle h, char **args, void *userdata)
                n = find_network(admin_get_global(h), args[1]);
        } else {
                n = admin_get_network(h);
-               name = n->name;
+               name = n->info.name;
        }
        if(!n) {
                admin_out(h, "%s: Not connected", name);
@@ -286,17 +289,17 @@ static void list_networks(admin_handle h, char **args, void *userdata)
                switch (n->connection.state) {
                case NETWORK_CONNECTION_STATE_NOT_CONNECTED:
                        if (n->connection.data.tcp.last_disconnect_reason)
-                               admin_out(h, "%s: Not connected: %s", n->name, 
+                               admin_out(h, "%s: Not connected: %s", n->info.name, 
                                                  n->connection.data.tcp.last_disconnect_reason);
                        else
-                               admin_out(h, "%s: Not connected", n->name);
+                               admin_out(h, "%s: Not connected", n->info.name);
                        break;
                case NETWORK_CONNECTION_STATE_RECONNECT_PENDING:
-                       admin_out(h, "%s: Reconnecting", n->name);
+                       admin_out(h, "%s: Reconnecting", n->info.name);
                        break;
                case NETWORK_CONNECTION_STATE_LOGIN_SENT:
                case NETWORK_CONNECTION_STATE_MOTD_RECVD:
-                       admin_out(h, "%s: connected", n->name);
+                       admin_out(h, "%s: connected", n->info.name);
                        break;
                }
        }
@@ -325,7 +328,7 @@ static void dump_joined_channels(admin_handle h, char **args, void *userdata)
        }
 
        if (!n->state) {
-               admin_out(h, "Network '%s' not connected", n->name);
+               admin_out(h, "Network '%s' not connected", n->info.name);
                return;
        }
 
@@ -364,9 +367,12 @@ static void repl_command(admin_handle h, char **args, void *userdata)
        }
 
        if(!args[1]) {
-               admin_out(h, "Sending backlog for network '%s'", n->name);
+               admin_out(h, "Sending backlog for network '%s'", n->info.name);
 
-               linestack_send(n->linestack, lm, NULL, admin_get_client(h));
+               if (n->global->config->report_time)
+                       linestack_send_timed(n->linestack, lm, NULL, admin_get_client(h));
+               else
+                       linestack_send(n->linestack, lm, NULL, admin_get_client(h));
 
                g_hash_table_replace(markers, n, linestack_get_marker(n->linestack));
 
@@ -506,7 +512,7 @@ static gboolean admin_net_init(struct network *n)
        char *hostmask;
        char *nicks;
 
-       hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", n->name);
+       hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", n->info.name);
        
        virtual_network_recv_args(n, n->state->me.hostmask, "JOIN", ADMIN_CHANNEL, NULL);
        virtual_network_recv_response(n, RPL_TOPIC, ADMIN_CHANNEL, 
@@ -525,7 +531,7 @@ static gboolean admin_net_init(struct network *n)
 
 static gboolean admin_to_server (struct network *n, struct client *c, const struct line *l)
 {
-       if (!g_strcasecmp(l->args[0], "PRIVMSG") && 
+       if (!g_strcasecmp(l->args[0], "PRIVMSG") ||
                !g_strcasecmp(l->args[0], "NOTICE")) {
                struct admin_handle ah;
 
@@ -592,6 +598,40 @@ static gboolean admin_to_server (struct network *n, struct client *c, const stru
                        g_free(gl->data);
                        gl = g_list_remove(gl, gl->data);
                }
+               return TRUE;
+       } else if (!g_strcasecmp(l->args[0], "QUIT")) {
+               return TRUE;
+       } else if (!g_strcasecmp(l->args[0], "MODE")) {
+               /* FIXME: Do something here ? */
+               return TRUE;
+       } else if (!g_strcasecmp(l->args[0], "WHO")) {
+               if (!strcmp(l->args[1], ADMIN_CHANNEL) || 
+                       !strcmp(l->args[1], "ctrlproxy")) {
+                       virtual_network_recv_response(n, RPL_WHOREPLY, ADMIN_CHANNEL, 
+                                                                         "ctrlproxy",
+                                                                         get_my_hostname(),
+                                                                         get_my_hostname(),
+                                                                         "ctrlproxy",
+                                                                         "H",
+                                                                         "0 CtrlProxy user",
+                                                                         NULL);
+               }
+               if (!strcmp(l->args[1], ADMIN_CHANNEL) ||
+                       !strcmp(l->args[1], n->state->me.nick)) {
+                       char *fullname = g_strdup_printf("0 %s", n->state->me.fullname);
+                       virtual_network_recv_response(n, RPL_WHOREPLY, ADMIN_CHANNEL, 
+                                                                         n->state->me.username,
+                                                                         n->state->me.hostname,
+                                                                         get_my_hostname(),
+                                                                         n->state->me.nick,
+                                                                         "H",
+                                                                         fullname,
+                                                                         NULL);
+                       g_free(fullname);
+               }
+
+               virtual_network_recv_response(n, RPL_ENDOFWHO, l->args[1], "End of /WHO list.", NULL);
+
                return TRUE;
        } else {
                virtual_network_recv_response(n, ERR_UNKNOWNCOMMAND, l->args[0], "Unknown command", NULL);
@@ -629,7 +669,7 @@ void admin_log(enum log_level level, const struct network *n, const struct clien
        tmp = g_strdup_printf("%s%s%s%s%s%s", 
                                                  data, 
                                                  n?" (":"",
-                                                 n?n->name:"", 
+                                                 n?n->info.name:"", 
                                                  c?"/":"",
                                                  c?c->description:"",
                                                  n?")":"");
@@ -640,7 +680,7 @@ void admin_log(enum log_level level, const struct network *n, const struct clien
                if (network->connection.data.virtual.ops != &admin_network)
                        continue;
 
-               hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", network->name);
+               hostmask = g_strdup_printf("ctrlproxy!ctrlproxy@%s", network->info.name);
                l = irc_parse_line_args(hostmask, "PRIVMSG", ADMIN_CHANNEL, tmp, NULL); 
                g_free(hostmask);
                
@@ -655,24 +695,24 @@ void admin_log(enum log_level level, const struct network *n, const struct clien
 }
 
 const static struct admin_command builtin_commands[] = {
-       { "ADDNETWORK", add_network, "<name>", "Add new network with specified name" },
-       { "ADDSERVER", add_server, "<network> <host>[:<port>] [<password>]", "Add server to network" },
-       { "BACKLOG", repl_command, "[channel]", "Send backlogs for this network or a channel, if specified" },
-       { "CONNECT", com_connect_network, "<network>", "Connect to specified network. Forces reconnect when waiting." },
-       { "DELNETWORK", del_network, "<network>", "Remove specified network" },
-       { "ECHO", cmd_echo, "<DATA>", "Simple echo command" },
-       { "LOG_LEVEL", cmd_log_level, "[level]", "Change/Show log level" },
-       { "NEXTSERVER", com_next_server, "[network]", "Disconnect and use to the next server in the list" },
-       { "CHARSET", handle_charset, "<charset>", "Change client charset" },
-       { "DIE", handle_die, "", "Exit ctrlproxy" },
-       { "DISCONNECT", com_disconnect_network, "<network>", "Disconnect specified network" },
-       { "LISTNETWORKS", list_networks, "", "List current networks and their status" },
-       { "SAVECONFIG", com_save_config, "<name>", "Save current XML configuration to specified file" },
-       { "DETACH", detach_client, "", "Detach current client" },
-       { "HELP", cmd_help, "[command]", "This help command" },
-       { "DUMPJOINEDCHANNELS", dump_joined_channels, "[network]", NULL, NULL },
+       { "ADDNETWORK", add_network },
+       { "ADDSERVER", add_server },
+       { "BACKLOG", repl_command },
+       { "CONNECT", com_connect_network },
+       { "DELNETWORK", del_network },
+       { "ECHO", cmd_echo },
+       { "LOG_LEVEL", cmd_log_level },
+       { "NEXTSERVER", com_next_server },
+       { "CHARSET", handle_charset },
+       { "DIE", handle_die },
+       { "DISCONNECT", com_disconnect_network },
+       { "LISTNETWORKS", list_networks },
+       { "SAVECONFIG", com_save_config },
+       { "DETACH", detach_client },
+       { "HELP", cmd_help },
+       { "DUMPJOINEDCHANNELS", dump_joined_channels },
 #ifdef DEBUG
-       { "ABORT", do_abort, "", NULL, NULL },
+       { "ABORT", do_abort },
 #endif
        { NULL }
 };