ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/contrib/ircd_alis.C
Revision: 1.6
Committed: Sun Sep 16 18:54:43 2007 UTC (19 years ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +10 -5 lines
Log Message:
#defines to enum

File Contents

# User Rev Content
1 pippijn 1.6 /**
2     * ircd_alis.C: ALIS, based on the ratbox-services implementation.
3     *
4     * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5     * Rights to this code are as documented in COPYING.
6     *
7     *
8     * Portions of this file were derived from sources bearing the following license:
9 pippijn 1.3 * Copyright © 2005-2007 William Pitcock, et al.
10 pippijn 1.2 * The rights to this code are as documented under doc/pod/license.pod.
11 pippijn 1.1 *
12 pippijn 1.3 * Copyright © 2003-2007 Lee Hardy <leeh@leeh.co.uk>
13     * Copyright © 2003-2007 ircd-ratbox development team
14 pippijn 1.1 *
15 pippijn 1.6 * $Id: ircd_alis.C,v 1.5 2007-08-30 19:56:22 pippijn Exp $
16 pippijn 1.1 */
17    
18 pippijn 1.4 #include <boost/foreach.hpp>
19    
20 pippijn 1.1 #include "atheme.h"
21 pippijn 1.3 #include <ermyth/module.h>
22    
23 pippijn 1.6 static char const rcsid[] = "$Id: ircd_alis.C,v 1.5 2007-08-30 19:56:22 pippijn Exp $";
24 pippijn 1.1
25 pippijn 1.3 REGISTER_MODULE ("alis", false, "William Pitcock <nenolod -at- nenolod.net>");
26 pippijn 1.1
27     #define ALIS_MAX_PARC 10
28     #define ALIS_MAX_MATCH 60
29    
30     #define DIR_UNSET 0
31     #define DIR_SET 1
32     #define DIR_EQUAL 2
33    
34     service_t *alis;
35     cmdvec alis_cmdtree;
36    
37     static void alis_cmd_list (sourceinfo_t *si, int parc, char *parv[]);
38     static void alis_cmd_help (sourceinfo_t *si, int parc, char *parv[]);
39     static void alis_handler (sourceinfo_t *si, int parc, char *parv[]);
40    
41 pippijn 1.3 command_t const alis_list = { "LIST", "Lists channels matching given parameters.", AC_NONE, ALIS_MAX_PARC, alis_cmd_list };
42     command_t const alis_help = { "HELP", "Displays contextual help information.", AC_NONE, 1, alis_cmd_help };
43 pippijn 1.1
44     struct alis_query
45     {
46     char const *mask;
47     char *topic;
48     int min;
49     int max;
50     int show_mode;
51     int show_topicwho;
52     unsigned int mode;
53     int mode_dir;
54     int mode_key;
55     int mode_limit;
56     int skip;
57     };
58    
59 pippijn 1.3 bool
60     _modinit (module *m)
61 pippijn 1.1 {
62     alis = add_service ("ALIS", "alis", me.name, "Channel Directory", alis_handler, alis_cmdtree);
63    
64 pippijn 1.3 alis_cmdtree << alis_list;
65     alis_cmdtree << alis_help;
66    
67     return true;
68 pippijn 1.1 }
69    
70     void
71     _moddeinit ()
72     {
73 pippijn 1.3 alis_cmdtree >> alis_list;
74     alis_cmdtree >> alis_help;
75 pippijn 1.1
76     del_service (alis);
77     }
78    
79     static int
80 pippijn 1.3 alis_parse_mode (char const * const txt, int *key, int *limit)
81 pippijn 1.1 {
82     int mode = 0;
83 pippijn 1.3 char const *text = txt;
84 pippijn 1.1
85     if (!text)
86     return 0;
87    
88     while (*text)
89     {
90     switch (*text)
91     {
92     case 'l':
93     *limit = 1;
94     break;
95     case 'k':
96     *key = 1;
97     break;
98     default:
99     mode |= mode_to_flag (*text);
100     break;
101     }
102    
103     text++;
104     }
105    
106     return mode;
107     }
108    
109     static int
110     parse_alis (sourceinfo_t *si, int parc, char *parv[], struct alis_query *query)
111     {
112     int i = 0;
113     char *opt = NULL, *arg = NULL;
114    
115     while ((opt = parv[i++]))
116     {
117     if (!strcasecmp (opt, "-min"))
118     {
119     if ((arg = parv[i++]) == NULL || (query->min = atoi (arg)) < 1)
120     {
121 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -min option");
122 pippijn 1.1 return 0;
123     }
124     }
125     else if (!strcasecmp (opt, "-max"))
126     {
127     if ((arg = parv[i++]) == NULL || (query->max = atoi (arg)) < 1)
128     {
129 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -max option");
130 pippijn 1.1 return 0;
131     }
132     }
133     else if (!strcasecmp (opt, "-skip"))
134     {
135     if ((arg = parv[i++]) == NULL || (query->skip = atoi (arg)) < 1)
136     {
137 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -skip option");
138 pippijn 1.1 return 0;
139     }
140     }
141     else if (!strcasecmp (opt, "-topic"))
142     {
143     query->topic = strtok (NULL, " ");
144     }
145     else if (!strcasecmp (opt, "-show"))
146     {
147     arg = parv[i++];
148    
149     if (arg == NULL)
150     {
151 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -show option");
152 pippijn 1.1 return 0;
153     }
154    
155     if (arg[0] == 'm')
156     {
157     query->show_mode = 1;
158    
159     if (arg[1] == 't')
160     query->show_topicwho = 1;
161     }
162     else if (arg[0] == 't')
163     {
164     query->show_topicwho = 1;
165    
166     if (arg[1] == 'm')
167     query->show_mode = 1;
168     }
169     }
170     else if (!strcasecmp (opt, "-mode"))
171     {
172     arg = parv[i++];
173    
174     if (arg == NULL)
175     {
176 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -mode option");
177 pippijn 1.1 return 0;
178     }
179    
180     switch (*arg)
181     {
182     case '+':
183     query->mode_dir = DIR_SET;
184     break;
185     case '-':
186     query->mode_dir = DIR_UNSET;
187     break;
188     case '=':
189     query->mode_dir = DIR_EQUAL;
190     break;
191     default:
192 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -mode option");
193 pippijn 1.1 return 0;
194     }
195    
196     query->mode = alis_parse_mode (arg + 1, &query->mode_key, &query->mode_limit);
197    
198     if (query->mode == 0)
199     {
200 pippijn 1.5 command_fail (si, fault::badparams, "Invalid -mode option");
201 pippijn 1.1 return 0;
202     }
203     }
204     else
205     {
206 pippijn 1.5 command_fail (si, fault::badparams, "Invalid option %s", opt);
207 pippijn 1.1 return 0;
208     }
209     }
210    
211     return 1;
212     }
213    
214     static void
215     print_channel (sourceinfo_t *si, channel_t *c, struct alis_query *query)
216     {
217     int show_topicwho = query->show_topicwho;
218     int show_topic = 1;
219     char modestr[MAXEXTMODES + 60];
220     int i, j;
221    
222     /* cant show a topicwho, when a channel has no topic. */
223     if (!c->topic)
224     {
225     show_topicwho = 0;
226     show_topic = 0;
227     }
228     if (query->show_mode)
229     {
230     j = 0;
231     modestr[j++] = '+';
232     for (i = 0; i < MAXEXTMODES; i++)
233     if (c->extmodes[i] != NULL)
234     modestr[j++] = ignore_mode_list[i].mode;
235     if (c->limit != 0)
236     modestr[j++] = 'l';
237     if (c->key != NULL)
238     modestr[j++] = 'k';
239     modestr[j] = '\0';
240     strlcat (modestr, flags_to_string (c->modes), sizeof modestr);
241     }
242    
243     if (query->show_mode && show_topicwho && show_topic)
244     command_success_nodata (si, "%-50s %-8s %3ld :%s (%s)", c->name, modestr, LIST_LENGTH (&c->members), c->topic, c->topic_setter);
245     else if (query->show_mode)
246     command_success_nodata (si, "%-50s %-8s %3ld :%s", c->name, modestr, LIST_LENGTH (&c->members), c->topic);
247     else if (show_topicwho && show_topic)
248     command_success_nodata (si, "%-50s %3ld :%s (%s)", c->name, LIST_LENGTH (&c->members), c->topic, c->topic_setter);
249     else if (show_topic)
250     command_success_nodata (si, "%-50s %3ld :%s", c->name, LIST_LENGTH (&c->members), c->topic);
251     else
252     command_success_nodata (si, "%-50s %3ld", c->name, LIST_LENGTH (&c->members));
253     }
254    
255     static int
256     show_channel (channel_t *c, struct alis_query *query)
257     {
258     /* skip +s channels */
259     if (c->modes & CMODE_SEC)
260     return 0;
261    
262     if ((int) LIST_LENGTH (&c->members) < query->min || (query->max && (int) LIST_LENGTH (&c->members) > query->max))
263     return 0;
264    
265     if (query->mode)
266     {
267     if (query->mode_dir == DIR_SET)
268     {
269     if (((c->modes & query->mode) == 0) || (query->mode_key && c->key[0] == '\0') || (query->mode_limit && !c->limit))
270     return 0;
271     }
272     else if (query->mode_dir == DIR_UNSET)
273     {
274     if ((c->modes & query->mode) || (query->mode_key && c->key[0] != '\0') || (query->mode_limit && c->limit))
275     return 0;
276     }
277     else if (query->mode_dir == DIR_EQUAL)
278     {
279     if ((c->modes != query->mode) || (query->mode_key && c->key[0] == '\0') || (query->mode_limit && !c->limit))
280     return 0;
281     }
282     }
283    
284     if (match (query->mask, c->name))
285     return 0;
286    
287     if (query->topic != NULL && match (query->topic, c->topic))
288     return 0;
289    
290     if (query->skip)
291     {
292     query->skip--;
293     return 0;
294     }
295    
296     return 1;
297     }
298    
299     static void
300     alis_cmd_list (sourceinfo_t *si, int parc, char *parv[])
301     {
302     channel_t *c;
303     struct alis_query query;
304     int maxmatch = ALIS_MAX_MATCH;
305    
306     memset (&query, 0, sizeof (struct alis_query));
307    
308     query.mask = parc >= 1 ? parv[0] : "*";
309     if (!parse_alis (si, parc - 1, parv + 1, &query))
310     return;
311    
312     logcommand (si, CMDLOG_GET, "LIST %s", query.mask);
313    
314     command_success_nodata (si, "Returning maximum of %d channel names matching '\2%s\2'", ALIS_MAX_MATCH, query.mask);
315    
316     /* hunting for one channel.. */
317     if (strchr (query.mask, '*') == NULL && strchr (query.mask, '?') == NULL)
318     {
319     if ((c = channel_find (query.mask)) != NULL)
320     {
321     if (!(c->modes & CMODE_SEC))
322     print_channel (si, c, &query);
323     }
324    
325     command_success_nodata (si, "End of output");
326     return;
327     }
328    
329 pippijn 1.4 foreach (channel_pair &cp, chanlist)
330     {
331     c = cp.second;
332     /* matches, so show it */
333     if (show_channel (c, &query))
334     {
335     print_channel (si, c, &query);
336    
337     if (--maxmatch == 0)
338     {
339     command_success_nodata (si, "Maximum channel output reached");
340     break;
341     }
342     }
343     }
344 pippijn 1.1
345     command_success_nodata (si, "End of output");
346     return;
347     }
348    
349     static void
350     alis_cmd_help (sourceinfo_t *si, int parc, char *parv[])
351     {
352 pippijn 1.3 command_help (si, alis_cmdtree);
353 pippijn 1.1 }
354    
355     static void
356     alis_handler (sourceinfo_t *si, int parc, char *parv[])
357     {
358     char orig[BUFSIZE];
359     char *cmd;
360     char *text;
361    
362     /* this should never happen */
363     if (parv[0][0] == '&')
364     {
365     slog (LG_ERROR, "services(): got parv with local channel: %s", parv[0]);
366     return;
367     }
368    
369     /* make a copy of the original for debugging */
370     strlcpy (orig, parv[parc - 1], BUFSIZE);
371    
372     /* lets go through this to get the command */
373     cmd = strtok (parv[parc - 1], " ");
374     text = strtok (NULL, "");
375    
376     if (!cmd)
377     return;
378     if (*cmd == '\001')
379     {
380     handle_ctcp_common (si, cmd, text);
381     return;
382     }
383    
384     /* take the command through the hash table */
385 pippijn 1.3 command_exec_split (alis, si, cmd, text, alis_cmdtree);
386 pippijn 1.1 }