Allow clients to handle CTCP requests.
authorJelmer Vernooij <jelmer@samba.org>
Sun, 6 Apr 2008 04:07:55 +0000 (06:07 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 6 Apr 2008 04:07:55 +0000 (06:07 +0200)
Makefile
src/client.c
src/ctcp.c
src/ctcp.h
src/ctcp_redirect.c [new file with mode: 0644]
src/network.c

index 4ea78c305990ffb4c851af6ac938fd39e5e6df5f..8812d226bacdb0abd2ce4e5d0d966f36f76b7c19 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,7 @@ objs = src/posix.o \
           src/gen_config.o \
           src/repl.o \
           src/linestack_file.o \
+          src/ctcp_redirect.o \
           src/ctcp.o \
           src/motd.o \
           src/nickserv.o \
index 95c3c38ad9ec2db11b855cba0670f501b4b3d47e..1b68f5de668f55c749f606200b2bb05b345b9214 100644 (file)
@@ -94,10 +94,13 @@ static gboolean process_from_client(struct irc_client *c, const struct irc_line
        } else if (!g_strcasecmp(l->args[0], "PRIVMSG") && l->argc > 2 && 
                        l->args[2][0] == '\001' && 
                        g_strncasecmp(l->args[2], "\001ACTION", 7) != 0) {
-               ctcp_process_client_request(c, l);
+               ctcp_client_request_record(c, l);
+
+               /* send off to server */
+               network_send_line(c->network, c, l, TRUE);
        } else if (!g_strcasecmp(l->args[0], "NOTICE") && l->argc > 2 && 
                        l->args[2][0] == '\001') {
-               ctcp_process_client_reply(c, l);
+               network_send_line(c->network, c, l, TRUE);
        } else if (!g_strcasecmp(l->args[0], "")) {
        } else if (c->network->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
                if (c->network->config->disable_cache || !client_try_cache(c, c->network->state, l)) {
index c47412a6f738b230b1329a9461d3407d865b7149..c7992b735540d32beef3b017e331d27204c7ca3c 100644 (file)
@@ -84,30 +84,6 @@ void ctcp_send(struct irc_network *n, const char *nick, ...)
        g_free(msg);
 }
 
-static char *get_ctcp_command(const char *data)
-{
-       char *tmp;
-       char *p;
-       g_assert(data[0] == '\001');
-
-       tmp = g_strdup(data+1);
-
-       p = strchr(tmp, ' ');
-       if (p) {
-               *p = '\0';
-               return tmp;
-       }
-
-       p = strrchr(tmp, '\001');
-       if (p) {
-               *p = '\0';
-               return tmp;
-       }
-
-       g_free(tmp);
-       return NULL;
-}
-
 static void handle_time(struct ctcp_handle *h, char **args)
 {
        time_t ti = time(NULL);
@@ -190,111 +166,7 @@ void ctcp_register_handler(const struct ctcp_handler *h)
        cmds = g_list_append(cmds, g_memdup(h, sizeof(*h)));
 }
 
-/**
- * A CTCP request.
- */
-struct ctcp_request {
-       struct irc_client *client;
-       char *destination;
-       char *command;
-};
-
-static GList *ctcp_request_queue = NULL;
-
-gboolean ctcp_process_client_request (struct irc_client *c, struct irc_line *l)
-{
-       struct ctcp_request *req;
-       char *command = get_ctcp_command(l->args[2]);
-
-       if (command == NULL) {
-               client_log(LOG_WARNING, c, "Received mailformed CTCP request");
-               return FALSE;
-       }
-
-       req = g_new0(struct ctcp_request, 1);
-
-       /* store client and command in table */
-       req->client = c;
-       if (!is_channelname(l->args[1], c->network->info))
-               req->destination = g_strdup(l->args[1]);
-       req->command = command;
-
-       client_log(LOG_TRACE, c, "Tracking CTCP request '%s' to %s", req->command, req->destination);
-
-       ctcp_request_queue = g_list_append(ctcp_request_queue, req);
-
-       /* send off to server */
-       network_send_line(c->network, c, l, TRUE);
-
-       return TRUE;
-}
-
-gboolean ctcp_process_client_reply (struct irc_client *c, struct irc_line *l)
-{
-       char *command = get_ctcp_command(l->args[2]);
-
-       if (command == NULL) {
-               client_log(LOG_WARNING, c, "Received mailformed CTCP reply");
-               return FALSE;
-       }
-
-       client_log(LOG_WARNING, c, "Received CTCP client reply '%s' from client", command);
-       g_free(command);
-
-       return TRUE;
-}
-
-gboolean ctcp_process_network_reply (struct irc_network *n, const struct irc_line *l) 
-{
-       GList *gl;
-       char *nick;
-
-       char *command = get_ctcp_command(l->args[2]);
-
-       nick = line_get_nick(l);
-
-       if (command == NULL) {
-               network_log(LOG_WARNING, n, "Received mailformed CTCP request from `%s'", nick);
-               g_free(nick);
-               return FALSE;
-       }
-
-
-       /* look in table */
-       /* if found send to specified client, remove entry from table */
-       for (gl = ctcp_request_queue; gl; gl = gl->next) {
-               struct ctcp_request *req = gl->data;
-
-               if (req->client->network != n)
-                       continue;
-
-               if (req->destination && strcmp(req->destination, nick) != 0)
-                       continue;
-
-               if (strcmp(req->command, command) != 0)
-                       continue;
-
-               client_send_line(req->client, l);
-
-               g_free(req->command);
-               g_free(req->destination);
-               ctcp_request_queue = g_list_remove(ctcp_request_queue, req);
-               g_free(req);
-               g_free(nick);
-               g_free(command);
-
-               return TRUE;
-       }
-
-       /* otherwise, inform user */
-       network_log(LOG_WARNING, n, "Don't know where to send unknown CTCP reply '%s'", command);
-
-       g_free(command);
-
-       return TRUE;
-}
-
-gboolean ctcp_process_network_request (struct irc_network *n, const struct irc_line *l) 
+gboolean ctcp_process_request (struct irc_network *n, const struct irc_line *l) 
 {
        GList *gl;
        int i;
@@ -318,7 +190,6 @@ gboolean ctcp_process_network_request (struct irc_network *n, const struct irc_l
        *t = '\0';
 
        args = g_strsplit(data, " ", 0);
-
        for (gl = cmds; gl; gl = gl->next) {
                struct ctcp_handler *hl = gl->data;
 
@@ -345,6 +216,7 @@ gboolean ctcp_process_network_request (struct irc_network *n, const struct irc_l
                ret = FALSE;
        }
 
+
        g_strfreev(args);
        g_free(data);
        g_free(h.nick);
index 0835424c023800463d002fb9d07eebc7d94cdd6e..efa0b495f1cfdb18b663201123e53cd59bf7ac6f 100644 (file)
@@ -34,10 +34,9 @@ struct ctcp_handler {
        void (*fn) (struct ctcp_handle *, char **args);
 };
 
-gboolean ctcp_process_network_request(struct irc_network *, const struct irc_line *);
-gboolean ctcp_process_network_reply(struct irc_network *, const struct irc_line *);
-gboolean ctcp_process_client_request(struct irc_client *, struct irc_line *);
-gboolean ctcp_process_client_reply(struct irc_client *, struct irc_line *);
+gboolean ctcp_network_redirect_response(struct irc_network *, const struct irc_line *);
+gboolean ctcp_client_request_record(struct irc_client *, struct irc_line *);
+gboolean ctcp_process_request(struct irc_network *, const struct irc_line *);
 G_MODULE_EXPORT void ctcp_register_handler(const struct ctcp_handler *);
 G_MODULE_EXPORT G_GNUC_NULL_TERMINATED void ctcp_send(struct irc_network *, const char *, ...);
 G_MODULE_EXPORT G_GNUC_NULL_TERMINATED void ctcp_reply(struct ctcp_handle *, ...);
diff --git a/src/ctcp_redirect.c b/src/ctcp_redirect.c
new file mode 100644 (file)
index 0000000..28d21bc
--- /dev/null
@@ -0,0 +1,130 @@
+/* 
+       ctrlproxy: A modular IRC proxy
+       (c) 2002-2003 Jelmer Vernooij <jelmer@nl.linux.org>
+
+       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
+       the Free Software Foundation; either version 3 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "internals.h"
+
+char *get_ctcp_command(const char *data)
+{
+       char *tmp;
+       char *p;
+       g_assert(data[0] == '\001');
+
+       tmp = g_strdup(data+1);
+
+       p = strchr(tmp, ' ');
+       if (p) {
+               *p = '\0';
+               return tmp;
+       }
+
+       p = strrchr(tmp, '\001');
+       if (p) {
+               *p = '\0';
+               return tmp;
+       }
+
+       g_free(tmp);
+       return NULL;
+}
+
+/**
+ * A CTCP request.
+ */
+struct ctcp_request {
+       struct irc_client *client;
+       char *destination;
+       char *command;
+};
+
+static GList *ctcp_request_queue = NULL;
+
+gboolean ctcp_client_request_record (struct irc_client *c, struct irc_line *l)
+{
+       struct ctcp_request *req;
+       char *command = get_ctcp_command(l->args[2]);
+
+       if (command == NULL) {
+               client_log(LOG_WARNING, c, "Received mailformed CTCP request");
+               return FALSE;
+       }
+
+       req = g_new0(struct ctcp_request, 1);
+
+       /* store client and command in table */
+       req->client = c;
+       if (!is_channelname(l->args[1], c->network->info))
+               req->destination = g_strdup(l->args[1]);
+       req->command = command;
+
+       client_log(LOG_TRACE, c, "Tracking CTCP request '%s' to %s", req->command, req->destination);
+
+       ctcp_request_queue = g_list_append(ctcp_request_queue, req);
+
+       return TRUE;
+}
+
+gboolean ctcp_network_redirect_response(struct irc_network *n, const struct irc_line *l) 
+{
+       GList *gl;
+       char *nick;
+
+       char *command = get_ctcp_command(l->args[2]);
+
+       nick = line_get_nick(l);
+
+       if (command == NULL) {
+               network_log(LOG_WARNING, n, "Received mailformed CTCP request from `%s'", nick);
+               g_free(nick);
+               return FALSE;
+       }
+
+
+       /* look in table */
+       /* if found send to specified client, remove entry from table */
+       for (gl = ctcp_request_queue; gl; gl = gl->next) {
+               struct ctcp_request *req = gl->data;
+
+               if (req->client->network != n)
+                       continue;
+
+               if (req->destination && strcmp(req->destination, nick) != 0)
+                       continue;
+
+               if (strcmp(req->command, command) != 0)
+                       continue;
+
+               client_send_line(req->client, l);
+
+               g_free(req->command);
+               g_free(req->destination);
+               ctcp_request_queue = g_list_remove(ctcp_request_queue, req);
+               g_free(req);
+               g_free(nick);
+               g_free(command);
+
+               return TRUE;
+       }
+
+       /* otherwise, inform user */
+       network_log(LOG_WARNING, n, "Don't know where to send unknown CTCP reply '%s'", command);
+
+       g_free(command);
+
+       return TRUE;
+}
index 2faa8921fdac165d656205292f8566f02004977d..2bbcade4fcecbffacd170db37b9906926e0dc349 100644 (file)
@@ -64,6 +64,18 @@ static gboolean network_update_isupport(struct irc_network_info *net_info,
        return TRUE;
 }
 
+static gboolean network_process_ctcp_request(struct irc_network *n, const struct irc_line *l)
+{
+       /* If there are no clients connected, answer by ourselve */
+       if (g_list_length(n->clients) == 0) {
+               return ctcp_process_request(n, l);
+       } else {
+               /* otherwise, just send to all clients and hope one answers */
+               clients_send(n->clients, l, NULL);
+               return TRUE;
+       }
+}
+
 
 /**
  * Process a line received from the server
@@ -164,10 +176,10 @@ static gboolean process_from_server(struct irc_network *n, const struct irc_line
                                if (!g_strcasecmp(l->args[0], "PRIVMSG") && l->argc > 2 && 
                                        l->args[2][0] == '\001' && 
                                        g_strncasecmp(l->args[2], "\001ACTION", 7) != 0) {
-                                       ctcp_process_network_request(n, l);
+                                       network_process_ctcp_request(n, l);
                                } else if (!g_strcasecmp(l->args[0], "NOTICE") && l->argc > 2 && 
                                        l->args[2][0] == '\001') {
-                                       ctcp_process_network_reply(n, l);
+                                       ctcp_network_redirect_response(n, l);
                                }
                        } else if (run_server_filter(n, l, FROM_SERVER)) {
                                if (!strcmp(l->args[0], "PRIVMSG") &&