ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/contrib/ircd_alis.C
Revision: 1.4
Committed: Thu Aug 30 06:57:25 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.3: +19 -16 lines
Log Message:
- chanlist to std::map

File Contents

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