Added SILC Thread Queue API
[runtime.git] / apps / irssi / src / fe-common / core / fe-ignore.c
1 /*
2  fe-ignore.c : irssi
3
4     Copyright (C) 1999-2000 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "module.h"
22 #include "module-formats.h"
23 #include "signals.h"
24 #include "commands.h"
25 #include "levels.h"
26 #include "misc.h"
27
28 #include "servers.h"
29 #include "ignore.h"
30 #include "printtext.h"
31
32 static char *ignore_get_key(IGNORE_REC *rec)
33 {
34         char *chans, *ret;
35
36         if (rec->channels == NULL)
37                 return g_strdup(rec->mask != NULL ? rec->mask : "*" );
38
39         chans = g_strjoinv(",", rec->channels);
40         if (rec->mask == NULL) return chans;
41
42         ret = g_strdup_printf("%s %s", rec->mask, chans);
43         g_free(chans);
44         return ret;
45 }
46
47 static void ignore_print(int index, IGNORE_REC *rec)
48 {
49         GString *options;
50         char *key, *levels;
51
52         key = ignore_get_key(rec);
53         levels = bits2level(rec->level);
54
55         options = g_string_new(NULL);
56         if (rec->exception) g_string_append(options, "-except ");
57         if (rec->regexp) {
58                 g_string_append(options, "-regexp ");
59 #ifdef HAVE_REGEX_H
60                 if (!rec->regexp_compiled)
61                         g_string_append(options, "[INVALID!] ");
62 #endif
63         }
64         if (rec->fullword) g_string_append(options, "-full ");
65         if (rec->replies) g_string_append(options, "-replies ");
66         if (rec->servertag != NULL) 
67                 g_string_sprintfa(options, "-network %s ", rec->servertag);
68         if (rec->pattern != NULL)
69                 g_string_sprintfa(options, "-pattern %s ", rec->pattern);
70
71         if (options->len > 1) g_string_truncate(options, options->len-1);
72
73         if (index >= 0) {
74                 printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
75                             TXT_IGNORE_LINE, index, key != NULL ? key : "",
76                             levels != NULL ? levels : "", options->str);
77         } else {
78                 printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
79                             options->len > 0 ? TXT_IGNORED_OPTIONS : TXT_IGNORED,
80                             key != NULL ? key : "",
81                             levels != NULL ? levels : "", options->str);
82         }
83         g_string_free(options, TRUE);
84         g_free(key);
85         g_free(levels);
86 }
87
88 static void cmd_ignore_show(void)
89 {
90         GSList *tmp;
91         int index;
92
93         if (ignores == NULL) {
94                 printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
95                             TXT_IGNORE_NO_IGNORES);
96                 return;
97         }
98
99         printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_IGNORE_HEADER);
100         index = 1;
101         for (tmp = ignores; tmp != NULL; tmp = tmp->next, index++) {
102                 IGNORE_REC *rec = tmp->data;
103
104                 ignore_print(index, rec);
105         }
106         printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_IGNORE_FOOTER);
107 }
108
109 /* SYNTAX: IGNORE [-regexp | -full] [-pattern <pattern>] [-except] [-replies]
110                   [-network <network>] [-channels <channel>] [-time <secs>] <mask> [<levels>]
111            IGNORE [-regexp | -full] [-pattern <pattern>] [-except] [-replies]
112                   [-network <network>] [-time <secs>] <channels> [<levels>] */
113 /* NOTE: -network replaces the old -ircnet flag. */
114 static void cmd_ignore(const char *data)
115 {
116         GHashTable *optlist;
117         IGNORE_REC *rec;
118         char *patternarg, *chanarg, *mask, *levels, *timestr, *servertag;
119         char **channels;
120         void *free_arg;
121         int new_ignore, msecs;
122
123         if (*data == '\0') {
124                 cmd_ignore_show();
125                 return;
126         }
127
128         if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
129                             "ignore", &optlist, &mask, &levels))
130                 return;
131
132         patternarg = g_hash_table_lookup(optlist, "pattern");
133         chanarg = g_hash_table_lookup(optlist, "channels");
134         servertag = g_hash_table_lookup(optlist, "network");
135         /* Allow -ircnet for backwards compatibility */
136         if (!servertag)
137                 servertag = g_hash_table_lookup(optlist, "ircnet");
138         
139         if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
140         if (*levels == '\0') levels = "ALL";
141
142         msecs = 0;
143         timestr = g_hash_table_lookup(optlist, "time");
144         if (timestr != NULL) {
145                 if (!parse_time_interval(timestr, &msecs))
146                         cmd_param_error(CMDERR_INVALID_TIME);
147         }
148
149         if (active_win->active_server != NULL &&
150             server_ischannel(active_win->active_server, mask)) {
151                 chanarg = mask;
152                 mask = NULL;
153         }
154         channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
155                 g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1);
156
157         rec = patternarg != NULL ? NULL: ignore_find(NULL, mask, channels);
158         new_ignore = rec == NULL;
159
160         if (rec == NULL) {
161                 rec = g_new0(IGNORE_REC, 1);
162
163                 rec->mask = mask == NULL || *mask == '\0' ||
164                         strcmp(mask, "*") == 0 ? NULL : g_strdup(mask);
165                 rec->channels = channels;
166         } else {
167                 g_free_and_null(rec->pattern);
168                 g_strfreev(channels);
169         }
170
171         rec->level = combine_level(rec->level, levels);
172
173         if (new_ignore && rec->level == 0) {
174                 /* tried to unignore levels from nonexisting ignore */
175                 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
176                             TXT_IGNORE_NOT_FOUND, rec->mask);
177                 g_free(rec->mask);
178                 g_strfreev(rec->channels);
179                 g_free(rec);
180                 cmd_params_free(free_arg);
181                 return;
182         }
183         rec->servertag = (servertag == NULL || *servertag == '\0') ?
184                 NULL : g_strdup(servertag);
185         rec->pattern = (patternarg == NULL || *patternarg == '\0') ?
186                 NULL : g_strdup(patternarg);
187         rec->exception = g_hash_table_lookup(optlist, "except") != NULL;
188         rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL;
189         rec->fullword = g_hash_table_lookup(optlist, "full") != NULL;
190         rec->replies = g_hash_table_lookup(optlist, "replies") != NULL;
191         if (msecs != 0)
192                 rec->unignore_time = time(NULL)+msecs/1000;
193
194         if (new_ignore)
195                 ignore_add_rec(rec);
196         else
197                 ignore_update_rec(rec);
198
199         cmd_params_free(free_arg);
200 }
201
202 /* SYNTAX: UNIGNORE <id>|<mask> */
203 static void cmd_unignore(const char *data)
204 {
205         IGNORE_REC *rec;
206         GSList *tmp;
207         char *mask;
208         void *free_arg;
209
210         if (!cmd_get_params(data, &free_arg, 1, &mask))
211                 return;
212
213         if (*mask == '\0')
214                 cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
215
216         if (is_numeric(mask, ' ')) {
217                 /* with index number */
218                 tmp = g_slist_nth(ignores, atoi(mask)-1);
219                 rec = tmp == NULL ? NULL : tmp->data;
220         } else {
221                 /* with mask */
222                 const char *chans[2] = { "*", NULL };
223
224                 if (active_win->active_server != NULL &&
225                     server_ischannel(active_win->active_server, mask)) {
226                         chans[0] = mask;
227                         mask = NULL;
228                 }
229                 rec = ignore_find("*", mask, (char **) chans);
230         }
231
232         if (rec != NULL) {
233                 rec->level = 0;
234                 ignore_update_rec(rec);
235         } else {
236                 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
237                             TXT_IGNORE_NOT_FOUND, mask);
238         }
239         cmd_params_free(free_arg);
240 }
241
242 static void sig_ignore_created(IGNORE_REC *rec)
243 {
244         ignore_print(-1, rec);
245 }
246
247 static void sig_ignore_destroyed(IGNORE_REC *rec)
248 {
249         char *key;
250
251         key = ignore_get_key(rec);
252         printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_UNIGNORED, key);
253         g_free(key);
254 }
255
256 void fe_ignore_init(void)
257 {
258         command_bind("ignore", NULL, (SIGNAL_FUNC) cmd_ignore);
259         command_bind("unignore", NULL, (SIGNAL_FUNC) cmd_unignore);
260
261         signal_add("ignore destroyed", (SIGNAL_FUNC) sig_ignore_destroyed);
262         signal_add("ignore created", (SIGNAL_FUNC) sig_ignore_created);
263         signal_add("ignore changed", (SIGNAL_FUNC) sig_ignore_created);
264
265         command_set_options("ignore", "regexp full except replies -network -ircnet -time -pattern -channels");
266 }
267
268 void fe_ignore_deinit(void)
269 {
270         command_unbind("ignore", (SIGNAL_FUNC) cmd_ignore);
271         command_unbind("unignore", (SIGNAL_FUNC) cmd_unignore);
272
273         signal_remove("ignore destroyed", (SIGNAL_FUNC) sig_ignore_destroyed);
274         signal_remove("ignore created", (SIGNAL_FUNC) sig_ignore_created);
275         signal_remove("ignore changed", (SIGNAL_FUNC) sig_ignore_created);
276 }