2 ctrlproxy: A modular IRC proxy
3 (c) 2002-2007 Jelmer Vernooij <jelmer@nl.linux.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "ctrlproxy.h"
23 static char **matches = NULL;
24 static GHashTable *markers = NULL;
25 static GHashTable *lastdisconnect_backlog = NULL;
26 static GHashTable *simple_backlog = NULL;
28 static gboolean check_highlight(struct line *l, time_t t, void *userdata)
30 struct client *c = userdata;
33 if (g_strcasecmp(l->args[0], "PRIVMSG") != 0 &&
34 g_strcasecmp(l->args[0], "NOTICE") != 0)
37 for (i = 0; matches && matches[i]; i++) {
38 if (strstr(l->args[2], matches[i]) != NULL) {
39 return client_send_line(c, l);
46 static void highlight_replicate(struct client *c)
48 struct linestack_marker *lm = g_hash_table_lookup(markers, c->network);
50 if (c->network->state) {
51 client_send_state(c, c->network->state);
54 if (c->network->linestack == NULL)
57 linestack_traverse(c->network->linestack, lm, NULL, check_highlight, c);
58 g_hash_table_replace(markers, c->network, linestack_get_marker(c->network->linestack));
61 static void none_replicate(struct client *c)
63 if (c->network->state)
64 client_send_state(c, c->network->state);
67 static void lastdisconnect_mark(struct client *c, void *userdata)
72 if (c->network->linestack != NULL)
73 g_hash_table_replace(lastdisconnect_backlog, c->network,
74 linestack_get_marker(c->network->linestack));
77 static void lastdisconnect_replicate(struct client *c)
79 struct linestack_marker *lm = g_hash_table_lookup(lastdisconnect_backlog, c->network);
80 struct network_state *ns;
82 if (c->network->linestack == NULL)
85 ns = linestack_get_state(c->network->linestack, lm);
87 client_send_state(c, ns);
89 free_network_state(ns);
91 linestack_send(c->network->linestack, lm, NULL, c, FALSE,
92 c->network->global->config->report_time);
95 static gboolean log_data(struct network *n, const struct line *l, enum data_direction dir, void *userdata)
97 if(dir != TO_SERVER) return TRUE;
99 if (g_strcasecmp(l->args[0], "PRIVMSG") &&
100 g_strcasecmp(l->args[0], "NOTICE")) return TRUE;
102 if (n->linestack != NULL)
103 g_hash_table_replace(simple_backlog, n, linestack_get_marker(n->linestack));
108 static void simple_replicate(struct client *c)
110 struct linestack_marker *m;
111 struct network_state *ns;
113 if (c->network->linestack == NULL)
116 m = g_hash_table_lookup(simple_backlog, c->network);
117 ns = linestack_get_state(c->network->linestack, m);
119 client_send_state(c, ns);
121 free_network_state(ns);
123 linestack_send(c->network->linestack, m, NULL, c, FALSE,
124 c->network->global->config->report_time);
127 static const struct replication_backend backends[] = {
128 { "none", none_replicate },
129 { "highlight", highlight_replicate },
130 { "lastdisconnect", lastdisconnect_replicate },
131 { "simple", simple_replicate },
135 static void load_config(struct global *global)
137 matches = g_key_file_get_string_list(global->config->keyfile,
138 "global", "match", NULL, NULL);
139 markers = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)linestack_free_marker);
142 gboolean init_replication(void)
145 for (i = 0; backends[i].name; i++)
146 register_replication_backend(&backends[i]);
148 register_load_config_notify(load_config);
149 add_lose_client_hook("repl_lastdisconnect", lastdisconnect_mark, NULL);
150 lastdisconnect_backlog = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)linestack_free_marker);
151 simple_backlog = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)linestack_free_marker);
152 add_server_filter("repl_simple", log_data, NULL, 200);