]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hcommands.c
Critical bug fix
[irc/quakenet/newserv.git] / helpmod2 / hcommands.c
1 #include <string.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <assert.h>
5 #include <sys/types.h>
6 #include <dirent.h>
7
8 #include "../nick/nick.h"
9 #include "../channel/channel.h"
10 #include "../lib/irc_string.h"
11
12 #include "hcommands.h"
13 #include "hcommand.h"
14
15 #include "helpmod.h"
16 #include "klingon.h"
17 #include "helpmod_alias.h"
18
19 #include "haccount.h"
20 #include "hqueue.h"
21 #include "hterm.h"
22
23 #include "hgen.h"
24 #include "hban.h"
25 #include "hchanban.h"
26
27 #include "hticket.h"
28
29 /* following are macros for use ONLY IN HERE
30 they may not look pretty, but work surprisingly well */
31
32 #define SKIP_WORD \
33 {\
34 if (*ostr == '"' && strchr(ostr+1, '"'))\
35 ostr = strchr(ostr+1, '"');\
36 while (!isspace(*ostr) && *ostr)\
37 ostr++;\
38 while (isspace(*ostr) && *ostr)\
39 ostr++;\
40 argc--;\
41 argv++;\
42 }
43
44 #define DEFINE_HCHANNEL \
45 {\
46 if (argc == 0)\
47 hchan = hchannel_get_by_channel(returntype);\
48 else if (*argv[0] == '#')\
49 {\
50 hchan = hchannel_get_by_name(argv[0]);\
51 SKIP_WORD;\
52 }\
53 else\
54 hchan = hchannel_get_by_channel(returntype);\
55 }
56
57 #define HCHANNEL_VERIFY_AUTHORITY(c, u)\
58 {\
59 if ((c) != NULL && !hchannel_authority((c), (u)))\
60 {\
61 helpmod_reply(u, returntype, "Sorry, channel %s is oper only", hchannel_get_name((c)));\
62 return;\
63 }\
64 }
65
66 enum
67 {
68 H_CMD_OP,
69 H_CMD_DEOP,
70 H_CMD_VOICE,
71 H_CMD_DEVOICE
72 };
73
74 enum
75 {
76 H_TERM_FIND,
77 H_TERM_MINUS,
78 H_TERM_PLUS
79 };
80
81 static void helpmod_cmd_addchan (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
82 {
83 if (argc == 0)
84 {
85 helpmod_reply(sender, returntype, "Cannot add channel: Channel not defined");
86 return;
87 }
88
89 if (*argv[0] != '#')
90 {
91 helpmod_reply(sender, returntype, "Can not add channel: Channel name must start with '#'");
92 return;
93 }
94
95 if (hchannel_get_by_name(argv[0]) != NULL)
96 {
97 helpmod_reply(sender, returntype, "Can not add channel: Channel %s already active", argv[0]);
98 return;
99 }
100
101 if (hchannel_add(argv[0]) != NULL)
102 {
103 helpmod_reply(sender, returntype, "Channel %s added succesfully", argv[0]);
104 return;
105 }
106 }
107
108 static void helpmod_cmd_delchan (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
109 {
110 hchannel *hchan;
111 char buffer[256];
112 DEFINE_HCHANNEL;
113
114 if (hchan == NULL)
115 {
116 helpmod_reply(sender, returntype, "Can not delete channel: Channel not defined or not found");
117 return;
118 }
119 strcpy(buffer, hchan->real_channel->index->name->content);
120 if (argc == 0 || strcmp(argv[0], "YesImSure"))
121 {
122 helpmod_reply(sender, returntype, "Can not delete channel: Sanity check. Please add a parameter \"YesImSure\" to confirm channel deletion");
123 return;
124 }
125 hchannel_del(hchan);
126
127 helpmod_reply(sender, returntype, "Channel %s deleted succesfully", buffer);
128 }
129
130 static void helpmod_cmd_whoami (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
131 {
132 helpmod_reply(sender, returntype, "You are %s", huser_get_nick(sender));
133 helpmod_reply(sender, returntype, "Your userlevel is %s", hlevel_name(huser_get_level(sender)));
134 if (sender->account == NULL)
135 helpmod_reply(sender, returntype, "You do not have an account with me");
136 else
137 helpmod_reply(sender, returntype, "Your accounts name is %s", sender->account->name->content);
138 if (huser_get_level(sender) < H_TRIAL)
139 {
140 if (sender->lc[0] || sender->lc[1] || sender->lc[2] || sender->lc[3] || sender->lc[4])
141 helpmod_reply(sender, returntype, "You violated the following rules: Excessive use of capital letters: %d, repeating: %d, improper use of language: %d, flooding: %d and spamming: %d", sender->lc[0], sender->lc[1], sender->lc[2], sender->lc[3], sender->lc[4]);
142 else
143 helpmod_reply(sender, returntype, "You have not violated any rules");
144 }
145
146 {
147 int pos;
148 huser_channel *huserchan = sender->hchannels;
149 for (;huserchan;huserchan = huserchan->next)
150 if ((pos = hqueue_get_position(huserchan->hchan, sender)) > -1)
151 helpmod_reply(sender, returntype, "You have queue position #%d on channel %s", pos, hchannel_get_name(huserchan->hchan));
152 }
153
154 if (IsAccount(sender->real_user))
155 {
156 hchannel *hchan;
157 hticket *htick;
158 for (hchan = hchannels;hchan;hchan = hchan->next)
159 if (hchan->flags & H_REQUIRE_TICKET)
160 {
161 htick = hticket_get(huser_get_auth(sender), hchan);
162 if (htick != NULL)
163 helpmod_reply(sender, returntype, "You have an invite ticket for channel %s that expires in %s", hchannel_get_name(hchan), helpmod_strtime(time(NULL) - htick->time_expiration));
164 }
165 }
166 }
167
168 static void helpmod_cmd_whois (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
169 {
170 huser *husr;
171 int i;
172
173 if (argc == 0)
174 {
175 helpmod_reply(sender, returntype, "Cannot get user information: User not specified");
176 return;
177 }
178 if (argc > H_CMD_MAX_ARGS)
179 argc = H_CMD_MAX_ARGS;
180
181 for (i=0;i<argc;i++)
182 {
183 husr = huser_get(getnickbynick(argv[i]));
184 if (husr == NULL)
185 {
186 helpmod_reply(sender, returntype, "Cannot get user information: User %s not found", argv[i]);
187 continue;
188 }
189 helpmod_reply(sender, returntype, "User %s has userlevel %s", huser_get_nick(husr), hlevel_name(huser_get_level(husr)));
190 if (husr->account == NULL)
191 helpmod_reply(sender, returntype, "User %s does not have an account with me", huser_get_nick(husr));
192 else
193 helpmod_reply(sender, returntype, "User %s has account named %s", huser_get_nick(husr),husr->account->name->content);
194 if (huser_get_level(husr) < H_TRIAL)
195 {
196 if (husr->lc[0] || husr->lc[1] || husr->lc[2] || husr->lc[3] || husr->lc[4])
197 helpmod_reply(sender, returntype, "User %s has lamercontrol entries: Excessive use of capital letters: %d, repeating: %d, improper use of language: %d, flooding: %d and spamming: %d", huser_get_nick(husr), husr->lc[0], husr->lc[1], husr->lc[2], husr->lc[3], husr->lc[4]);
198 else
199 helpmod_reply(sender, returntype, "User %s has no lamercontrol entries", huser_get_nick(husr));
200 }
201 {
202 int pos;
203 huser_channel *huserchan = husr->hchannels;
204 for (;huserchan;huserchan = huserchan->next)
205 {
206 if ((pos = hqueue_get_position(huserchan->hchan, husr)) > -1)
207 helpmod_reply(sender, returntype, "User %s has queue queue position #%d on channel %s", huser_get_nick(husr), pos, hchannel_get_name(huserchan->hchan));
208 if (on_desk(husr, huserchan))
209 helpmod_reply(sender, returntype, "User %s is receiving support on channel %s", huser_get_nick(husr), hchannel_get_name(huserchan->hchan));
210 }
211 }
212 if (IsAccount(husr->real_user))
213 {
214 hchannel *hchan;
215 hticket *htick;
216 for (hchan = hchannels;hchan;hchan = hchan->next)
217 if (hchan->flags & H_REQUIRE_TICKET)
218 {
219 htick = hticket_get(huser_get_auth(husr), hchan);
220 if (htick != NULL)
221 helpmod_reply(sender, returntype, "User %s has an invite ticket for channel %s that expires in %s", huser_get_nick(husr), hchannel_get_name(hchan), helpmod_strtime(time(NULL) - htick->time_expiration));
222 }
223 }
224 }
225 }
226 /*
227 void helpmod_cmd_megod (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
228 {
229 if (sender->account == NULL)
230 sender->account = haccount_add(huser_get_nick(sender), H_ADMIN);
231
232 sender->account->level = H_ADMIN;
233 }
234 */
235
236 static void helpmod_cmd_seen (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
237 {
238 huser *target_huser;
239 haccount *target_haccount;
240 int i;
241
242 if (argc == 0)
243 {
244 helpmod_reply(sender, returntype, "No targets specified for seen");
245 return;
246 }
247 for (i=0;i < argc;i++)
248 {
249 if (*argv[i] == '#')
250 { /* account */
251 if (!ci_strcmp(argv[i] + 1, HELPMOD_AUTH))
252 { /* A nice special case */
253 helpmod_reply(sender, returntype, "I'm right here");
254 continue;
255 }
256 target_haccount = haccount_get_by_name(argv[i]);
257 if (target_haccount == NULL)
258 {
259 helpmod_reply(sender, returntype, "Account %s not found", argv[i] + 1);
260 continue;
261 }
262
263 helpmod_reply(sender, returntype, "Account %s's last recorded activity was %s ago", target_haccount->name->content, helpmod_strtime(time(NULL) - target_haccount->last_activity));
264 }
265 else
266 {
267 if (getnickbynick(argv[i]) == helpmodnick)
268 { /* A nice special case */
269 helpmod_reply(sender, returntype, "I'm right here");
270 continue;
271 }
272 target_huser = huser_get(getnickbynick(argv[i]));
273 if (target_huser == NULL)
274 {
275 helpmod_reply(sender, returntype, "User %s not found", argv[i]);
276 continue;
277 }
278 helpmod_reply(sender, returntype, "User %s's last recorded activity was %s ago", huser_get_nick(target_huser), helpmod_strtime(time(NULL) - target_huser->last_activity));
279 }
280 }
281 }
282
283 static void helpmod_cmd_change_userlevel(huser *sender, hlevel target_level, channel* returntype, char* ostr, int argc, char *argv[])
284 {
285 huser *target_huser;
286 haccount *target_haccount;
287 int i;
288
289 if (argc == 0)
290 {
291 helpmod_reply(sender, returntype, "Incorrect syntax: Nick or account required");
292 return ;
293 }
294
295 if (argc > H_CMD_MAX_ARGS)
296 argc = H_CMD_MAX_ARGS;
297
298 for (i = 0;i < argc;i++)
299 {
300 if (*argv[i] == '#') /* account */
301 {
302 target_haccount = haccount_get_by_name(argv[i]);
303 if (target_haccount == NULL)
304 {
305 helpmod_reply(sender, returntype, "Cannot change userlevel: Account '%s' not found", argv[i]);
306 continue;
307 }
308 if (target_haccount->level > huser_get_level(sender))
309 {
310 helpmod_reply(sender, returntype, "Cannot change userlevel: Account '%s' has a userlevel higher than yours", argv[i]);
311 continue;
312 }
313
314 if (target_haccount->level == target_level)
315 {
316 helpmod_reply(sender, returntype, "Cannot change userlevel: Account '%s' already has userlevel %s", argv[i], hlevel_name(target_level));
317 continue;
318 }
319
320 target_haccount->level = target_level;
321
322 helpmod_reply(sender, returntype, "Userlevel changed: Account '%s' now has userlevel %s", argv[i], hlevel_name(target_level));
323
324 }
325 else
326 {
327 target_huser = huser_get(getnickbynick(argv[i]));
328 if (target_huser == NULL)
329 {
330 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' not found", argv[i]);
331 continue;
332 }
333 if (huser_get_level(target_huser) > huser_get_level(sender))
334 {
335 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' has a userlevel higher than yours", argv[i]);
336 continue;
337 }
338 if (huser_get_level(target_huser) == H_STAFF && huser_get_level(sender) == H_STAFF)
339 {
340 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' has the same userlevel as you have", argv[i]);
341 continue;
342 }
343
344 if (huser_get_level(target_huser) == target_level)
345 {
346 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' already has userlevel %s", argv[i], hlevel_name(target_level));
347 continue;
348 }
349 if (target_huser == sender)
350 {
351 helpmod_reply(sender, returntype, "Cannot change userlevel: Sanity check, you're changing your own userlevel, use #account instead of nick if you really wish to do this");
352 continue;
353 }
354 if (!IsAccount(target_huser->real_user))
355 {
356 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' is not authed", argv[i]);
357 continue;
358 }
359
360 if (target_huser->account == NULL)
361 {
362 if (haccount_get_by_name(huser_get_auth(target_huser)) != NULL)
363 {
364 helpmod_reply(sender, returntype, "Cannot change userlevel: Unable to create an account. Account %s already exists", huser_get_auth(target_huser));
365 continue;
366 }
367 else
368 target_huser->account = haccount_add(huser_get_auth(target_huser), target_level);
369 }
370
371 target_huser->account->level = target_level;
372
373 helpmod_reply(sender, returntype, "Userlevel changed: User '%s' now has userlevel %s", argv[i], hlevel_name(target_level));
374
375 if (huser_get_level(target_huser) == H_LAMER)
376 {
377 const char *banmask = hban_ban_string(target_huser->real_user, HBAN_HOST);
378 hban_add(banmask, "Improper user", time(NULL) + HCMD_OUT_DEFAULT, 1);
379 }
380 else
381 helpmod_reply(target_huser, NULL, "Your userlevel has been changed, your current userlevel is %s", hlevel_name(target_level));
382 }
383 }
384 }
385
386 /* pseudo commands for the above */
387 static void helpmod_cmd_improper (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_LAMER, returntype, ostr, argc, argv); }
388 static void helpmod_cmd_peon (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_PEON, returntype, ostr, argc, argv); }
389 static void helpmod_cmd_trial (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_TRIAL, returntype, ostr, argc, argv); }
390 static void helpmod_cmd_staff (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_STAFF, returntype, ostr, argc, argv); }
391 static void helpmod_cmd_oper (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_OPER, returntype, ostr, argc, argv); }
392 static void helpmod_cmd_admin (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_ADMIN, returntype, ostr, argc, argv); }
393
394 static void helpmod_cmd_deluser (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
395 {
396 int i;
397 huser *target_huser;
398 haccount *target_haccount;
399
400 if (argc == 0)
401 {
402 helpmod_reply(sender, returntype, "Usage: deluser [nick|#account]");
403 return;
404 }
405
406 if (argc > H_CMD_MAX_ARGS)
407 argc = H_CMD_MAX_ARGS;
408
409 for (i = 0;i < argc;i++)
410 {
411 if (*argv[i] != '#')
412 {
413 target_huser = huser_get(getnickbynick(argv[i]));
414 if (target_huser == NULL)
415 {
416 helpmod_reply(sender, returntype, "Cannot delete the account: User %s does not exist", argv[i]);
417 continue;
418 }
419 if (target_huser->account == NULL)
420 {
421 helpmod_reply(sender, returntype, "Cannot delete the account: User %s does not have an account", argv[i]);
422 continue;
423 }
424 target_haccount = target_huser->account;
425 }
426 else
427 target_haccount = haccount_get_by_name(argv[i]);
428
429 if (target_haccount == NULL)
430 {
431 helpmod_reply(sender, returntype, "Cannot delete the account: Account %s does not exist", argv[i]);
432 continue;
433 }
434 if (target_haccount->level > huser_get_level(sender))
435 {
436 helpmod_reply(sender, returntype, "Cannot delete the account: Account %s has higher userlevel than you", target_haccount->name->content);
437 continue;
438 }
439 helpmod_reply(sender, returntype, "Account %s deleted", target_haccount->name->content);
440 haccount_del(target_haccount);
441 }
442 }
443
444 static void helpmod_cmd_listuser (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
445 {
446 char *pattern;
447 haccount *hack = haccounts;
448 int count = 0, lvl = -1;
449 time_t timer;
450
451 if (argc > 0 && sscanf(argv[0], "%d", &lvl) && lvl >= H_LAMER && lvl <= H_ADMIN)
452 {
453 SKIP_WORD;
454 }
455 else
456 lvl = -1;
457
458 if (argc == 0)
459 pattern = "*";
460 else
461 pattern = argv[0];
462
463 if (lvl >= 0)
464 helpmod_reply(sender, returntype, "%s accounts matching pattern %s: (account name, userlevel, expires in)", hlevel_name(lvl), pattern);
465 else
466 helpmod_reply(sender, returntype, "Accounts matching pattern %s: (account name, userlevel, expires in)", pattern);
467 for (;hack;hack = hack->next)
468 {
469 if (strregexp(hack->name->content, pattern))
470 {
471 if (lvl >= 0 && hack->level != lvl)
472 continue;
473 timer = hack->last_activity + HELPMOD_ACCOUNT_EXPIRATION[hack->level];
474 helpmod_reply(sender, returntype, "%-16s %-32s %s", hack->name->content, hlevel_name(hack->level), asctime(localtime(&timer)));
475 count++;
476 }
477 }
478 if (lvl >= 0)
479 helpmod_reply(sender, returntype, "%s accounts matching pattern %d", hlevel_name(lvl), count);
480 else
481 helpmod_reply(sender, returntype, "Accounts matching pattern %d", count);
482 }
483
484 static void helpmod_cmd_censor (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
485 {
486 hchannel *hchan;
487 hcensor *hcens;
488 int i = 0;
489
490 DEFINE_HCHANNEL;
491
492 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
493
494 if (hchan == NULL)
495 {
496 helpmod_reply(sender, returntype, "Cannot handle the censor: Channel not specified or found");
497 return;
498 }
499
500 if (argc < 2 || !ci_strcmp(argv[0], "list")) /* view */
501 {
502 if (hchan->censor == NULL)
503 helpmod_reply(sender, returntype, "Nothing is censored on channel %s", hchan->real_channel->index->name->content);
504 else
505 {
506 helpmod_reply(sender, returntype, "Censored patterns for channel %s (%s):", hchan->real_channel->index->name->content, (hchan->flags & H_CENSOR)?"active":"inactive");
507 for (hcens = hchan->censor;hcens;hcens = hcens->next)
508 helpmod_reply(sender, returntype, "#%-4d %-8s %s%s%s", i++, hcensor_get_typename(hcens->type), hcens->pattern->content, hcens->reason?" :: ":"", hcens->reason?hcens->reason->content:"");
509 }
510 }
511 else
512 {
513 if (!ci_strcmp(argv[0], "add"))
514 {
515 char *pattern;
516 char *reason;
517 int type = HCENSOR_KICK;
518
519 SKIP_WORD;
520
521 /* not very elegant but will have to do */
522 if (argc > 1)
523 {
524 if (!ci_strcmp(argv[0], "warn"))
525 {
526 type = HCENSOR_WARN;
527 if (argc <= 2)
528 {
529 helpmod_reply(sender, returntype, "Cannot add censor entry: Entries of type warn require a reason");
530 return;
531 }
532 SKIP_WORD;
533 }
534 else if (!ci_strcmp(argv[0], "kick"))
535 {
536 type = HCENSOR_KICK;
537 SKIP_WORD;
538 }
539 else if (!ci_strcmp(argv[0], "chanban"))
540 {
541 type = HCENSOR_CHANBAN;
542 SKIP_WORD;
543 }
544 else if (!ci_strcmp(argv[0], "ban"))
545 {
546 type = HCENSOR_BAN;
547 SKIP_WORD;
548 }
549 }
550
551 pattern = argv[0];
552 SKIP_WORD;
553 if (argc)
554 reason = ostr;
555 else
556 reason = NULL;
557
558 if (hcensor_get_by_pattern(hchan->censor, pattern))
559 {
560 helpmod_reply(sender, returntype, "Cannot add censor entry: Pattern '%s' is already censored", pattern);
561 return;
562 }
563
564 if (hcensor_add(&hchan->censor, pattern, reason, type))
565 helpmod_reply(sender, returntype, "Pattern '%s' (%s) with type %s, censored succesfully", pattern, reason?reason:"no reason specified", hcensor_get_typename(type));
566 else
567 helpmod_reply(sender, returntype, "Cannot add censor entry: Pattern '%s' is already censored", pattern);
568
569 }
570 else if (!ci_strcmp(argv[0], "del"))
571 {
572 SKIP_WORD;
573 if (*argv[0] == '#')
574 {
575 int tmp;
576 if (!sscanf(argv[0], "#%d", &tmp))
577 {
578 helpmod_reply(sender, returntype, "Cannot delete censor entry: Bad index, integer expected");
579 return;
580 }
581 hcens = hcensor_get_by_index(hchan->censor, tmp);
582 }
583 else
584 hcens = hcensor_get_by_pattern(hchan->censor, argv[0]);
585
586 if (hcens == NULL)
587 helpmod_reply(sender, returntype, "Cannot delete censor entry: Entry not found");
588 else
589 {
590 hcensor_del(&hchan->censor, hcens);
591 helpmod_reply(sender, returntype, "Censor entry deleted succesfully");
592 }
593 }
594 else
595 helpmod_reply(sender, returntype, "Unknown censor command %s", argv[0]);
596 }
597 }
598
599 static void helpmod_cmd_chanconf (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
600 {
601 hchannel *hchan;
602 int old_flags=0;
603
604 DEFINE_HCHANNEL;
605
606 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
607
608 if (hchan == NULL)
609 {
610 helpmod_reply(sender, returntype, "Cannot change or view channel configuration: Channel not specified or found");
611 return;
612 }
613
614 if (argc == 0) /* view, spammy but with pretty formatting */
615 {
616 int i;
617 helpmod_reply(sender, returntype, "Channel configuration for %s:", hchan->real_channel->index->name->content);
618
619 for (i=0;i<=HCHANNEL_CONF_COUNT;i++)
620 helpmod_reply(sender, returntype, "(%02d) %-32s : %s", i, hchannel_get_sname(i), hchannel_get_state(hchan, 1 << i));
621 }
622 else /* change */
623 {
624 int i, tmp, type;
625 old_flags = hchan->flags;
626
627 if (argc > H_CMD_MAX_ARGS)
628 argc = H_CMD_MAX_ARGS;
629
630 for (i=0;i<argc;i++)
631 {
632 if (*argv[i] == '+')
633 {
634 type = 1;
635 argv[i]++;
636 }
637 else if (*argv[i] == '-')
638 {
639 type = -1;
640 argv[i]++;
641 }
642 else
643 type = 0;
644
645 if (!sscanf(argv[i], "%d", &tmp) || (tmp < 0) || (tmp > HCHANNEL_CONF_COUNT))
646 {
647 helpmod_reply(sender, returntype, "Cannot change channel configuration: Expected integer between [0, %d]", HCHANNEL_CONF_COUNT);
648 continue;
649 }
650
651 switch (type)
652 {
653 case -1: /* unset */
654 hchan->flags &= ~(1 << tmp);
655 helpmod_reply(sender, returntype, "Channel configuration for %s changed: %s set to %s",hchannel_get_name(hchan), hchannel_get_sname(tmp), hchannel_get_state(hchan, 1 << tmp));
656 break;
657 case 0: /* view */
658 helpmod_reply(sender, returntype, "(%02d) %-32s : %s", tmp, hchannel_get_sname(tmp), hchannel_get_state(hchan, 1 << tmp));
659 break;
660 case 1: /* set */
661 hchan->flags |= (1 << tmp);
662 helpmod_reply(sender, returntype, "Channel configuration for %s changed: %s set to %s", hchannel_get_name(hchan), hchannel_get_sname(tmp), hchannel_get_state(hchan, 1 << tmp));
663 break;
664 }
665 }
666 hchannel_conf_change(hchan, old_flags);
667 }
668 }
669
670 static void helpmod_cmd_acconf (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
671 {
672 haccount *hacc = sender->account;
673
674 if (hacc == NULL)
675 {
676 helpmod_reply(sender, returntype, "Account configuration impossible: You do not have an account");
677 return;
678 }
679
680 if (argc == 0) /* view, spammy but with pretty formatting */
681 {
682 int i;
683 helpmod_reply(sender, returntype, "Account configuration for %s:", hacc->name->content);
684
685 for (i=0;i<=HACCOUNT_CONF_COUNT;i++)
686 helpmod_reply(sender, returntype, "(%02d) %-35s : %s", i, haccount_get_sname(i), haccount_get_state(hacc, 1 << i));
687 }
688 else /* change */
689 {
690 int i, tmp, type;
691
692 if (argc > H_CMD_MAX_ARGS)
693 argc = H_CMD_MAX_ARGS;
694
695 for (i=0;i<argc;i++)
696 {
697 if (*argv[i] == '+')
698 {
699 type = 1;
700 argv[i]++;
701 }
702 else if (*argv[i] == '-')
703 {
704 type = -1;
705 argv[i]++;
706 }
707 else
708 type = 0;
709
710 if (!sscanf(argv[i], "%d", &tmp) || (tmp < 0) || (tmp > HACCOUNT_CONF_COUNT))
711 {
712 helpmod_reply(sender, returntype, "Cannot change account configuration: Expected integer between [0, %d]", HACCOUNT_CONF_COUNT);
713 continue;
714 }
715
716 switch (type)
717 {
718 case -1: /* unset */
719 hacc->flags &= ~(1 << tmp);
720 helpmod_reply(sender, returntype, "Account configuration for %s changed: %s set to %s",hacc->name->content, haccount_get_sname(tmp), haccount_get_state(hacc, 1 << tmp));
721 break;
722 case 0: /* view */
723 helpmod_reply(sender, returntype, "(%02d) %-35s : %s", tmp, haccount_get_sname(tmp), haccount_get_state(hacc, 1 << tmp));
724 break;
725 case 1: /* set */
726 hacc->flags |= (1 << tmp);
727 helpmod_reply(sender, returntype, "Account configuration for %s changed: %s set to %s", hacc->name->content, haccount_get_sname(tmp), haccount_get_state(hacc, 1 << tmp));
728 break;
729 }
730 }
731 }
732 }
733
734 static void helpmod_cmd_welcome (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
735 {
736 hchannel *hchan;
737
738 DEFINE_HCHANNEL;
739
740 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
741
742 if (hchan == NULL)
743 {
744 helpmod_reply(sender, returntype, "Cannot change or view the welcome message: Channel not specified or found");
745 return;
746 }
747
748 if (argc == 0) /* view */
749 {
750 helpmod_reply(sender, returntype, "Welcome message for channel %s (%s): %s", hchan->real_channel->index->name->content, hchannel_get_state(hchan, H_WELCOME), hchan->welcome);
751 }
752 else
753 {
754 strcpy(hchan->welcome, ostr);
755 helpmod_reply(sender, returntype, "Welcome message for channel %s (%s) is now: %s", hchan->real_channel->index->name->content, hchannel_get_state(hchan, H_WELCOME), hchan->welcome);
756 }
757 }
758
759 static void helpmod_cmd_aliases (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
760 {
761 char buf[512];
762 int i = 0;
763 void helpmod_list_aliases(alias_tree node)
764 {
765 if (i > 256)
766 {
767 helpmod_reply(sender, returntype, "%s", buf);
768 i = 0;
769 }
770 if (!node)
771 return;
772 sprintf(buf+i,"%.200s ",node->name->content);
773 i+=(1+strlen(node->name->content));
774 helpmod_list_aliases(node->left);
775 helpmod_list_aliases(node->right);
776 }
777 helpmod_list_aliases(aliases);
778 if (i)
779 helpmod_reply(sender, returntype, "%s", buf);
780 }
781
782 static void helpmod_cmd_showcommands (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
783 {
784 int level = H_PEON, previous_level = H_PEON;
785 hcommand *tmp;
786
787 if (!(argc && (sscanf(argv[0], "%d", &level)) && (level >= 0) && (level <= huser_get_level(sender))))
788 level = huser_get_level(sender);
789
790 helpmod_reply(sender, returntype, "HelpMod %s commands for userlevel %s:", HELPMOD_VERSION, hlevel_name(level));
791
792 hcommand_list(H_NONE);
793
794 while ((tmp = hcommand_list(level)) != NULL)
795 {
796 if (tmp->level > previous_level)
797 {
798 helpmod_reply(sender, returntype, "--- Additional commands for userlevel %s ---", hlevel_name(tmp->level));
799 previous_level = tmp->level;
800 }
801 helpmod_reply(sender, returntype, "%-16s %s", tmp->name->content, tmp->help->content);
802 }
803
804 return;
805 }
806
807 static void helpmod_cmd_lamercontrol (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
808 {
809 hchannel *hchan;
810 hlc_profile *ptr;
811
812 DEFINE_HCHANNEL;
813
814 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
815
816 if (hchan == NULL) /* list profiles */
817 {
818 helpmod_reply(sender, returntype, "Following lamercontrol profiles are available:");
819 for (ptr = hlc_profiles;ptr;ptr = ptr->next)
820 helpmod_reply(sender, returntype, "%s", ptr->name->content);
821 return;
822 }
823 if (argc == 0)
824 {
825 if (hchan->lc_profile == NULL)
826 helpmod_reply(sender, returntype, "Channel %s has no lamercontrol profile set", hchannel_get_name(hchan));
827 else
828 helpmod_reply(sender, returntype, "Channel %s is using lamercontrol profile %s (%s)", hchannel_get_name(hchan), hchan->lc_profile->name->content, hchannel_get_state(hchan, H_LAMER_CONTROL));
829 return;
830 }
831 if (!ci_strcmp(argv[0], "list"))
832 {
833 helpmod_reply(sender, returntype, "Following lamercontrol profiles are available:");
834 for (ptr = hlc_profiles;ptr;ptr = ptr->next)
835 helpmod_reply(sender, returntype, "%s", ptr->name->content);
836 return;
837 }
838 ptr = hlc_get(argv[0]);
839 if (ptr == NULL)
840 {
841 helpmod_reply(sender, returntype, "Cannot set the lamercontrol profile: Profile %s does not exist:", argv[0]);
842 return;
843 }
844 else
845 {
846 hchan->lc_profile = ptr;
847 helpmod_reply(sender, returntype, "Lamercontrol profile %s set to channel %s succesfully",ptr->name->content,hchannel_get_name(hchan));
848 }
849
850 }
851
852 static void helpmod_cmd_term_find_general (huser *sender, channel* returntype, int type, char* ostr, int argc, char *argv[])
853 {
854 hterm *htrm;
855 hterm *source;
856 hchannel *hchan;
857 huser *targets[6];
858 int i,ntargets = 0;
859
860 DEFINE_HCHANNEL;
861
862 if (hchan == NULL)
863 source = hterms;
864 else
865 source = hchan->channel_hterms;
866
867 if (argc == 0)
868 {
869 if (type == H_TERM_PLUS)
870 hqueue_advance(hchan, sender, 1);
871 else
872 helpmod_reply(sender, returntype, "Cannot find term: Term not specified");
873 return;
874 }
875 htrm = hterm_get_and_find(source, argv[0]);
876 if (htrm == NULL)
877 {
878 helpmod_reply(sender, returntype, "No term found matching '%s'", argv[0]);
879 return;
880 }
881 if (returntype != NULL && huser_get_level(sender) > H_PEON)
882 {
883 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
884
885 if (argc > 1)
886 {
887 SKIP_WORD;
888 if (argc > H_CMD_MAX_ARGS)
889 argc = H_CMD_MAX_ARGS;
890 for (i=0;i<argc;i++)
891 {
892 targets[ntargets] = huser_get(getnickbynick(argv[i]));
893 if (targets[ntargets] == NULL)
894 {
895 helpmod_reply(sender, returntype, "Error using ?: User %s not found", argv[i]);
896 continue;
897 }
898 else
899 ntargets++;
900 }
901 }
902
903 if (ntargets == 0)
904 helpmod_message_channel_long(hchannel_get_by_channel(returntype), "(%s): %s", htrm->name->content, htrm->description->content);
905 else
906 {
907 char buffer[256] = "";
908 for (i=0;i<ntargets;i++)
909 {
910 if (i != 0)
911 strcat(buffer, " ");
912 strcat(buffer, huser_get_nick(targets[i]));
913 }
914
915 helpmod_message_channel_long(hchannel_get_by_channel(returntype), "%s: (%s) %s", buffer, htrm->name->content, htrm->description->content);
916 if (type != H_TERM_FIND)
917 {
918 if (hchan->flags & H_QUEUE)
919 {
920 for (i=0;i<ntargets;i++)
921 {
922 huser_channel *huserchan = huser_on_channel(targets[i], hchan);
923 huserchan->flags |= HQUEUE_DONE;
924 if (huserchan->flags & HCUMODE_VOICE)
925 helpmod_channick_modes(targets[i], hchan, MC_DEVOICE, HLAZY);
926 }
927 if (type == H_TERM_PLUS)
928 hqueue_advance(hchan, sender, ntargets);
929 }
930 }
931 }
932 }
933 else
934 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
935 }
936
937 static void helpmod_cmd_term_find (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
938 {
939 helpmod_cmd_term_find_general(sender, returntype, H_TERM_FIND, ostr, argc, argv);
940 }
941
942 static void helpmod_cmd_term_find_minus (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
943 {
944 helpmod_cmd_term_find_general(sender, returntype, H_TERM_MINUS, ostr, argc, argv);
945 }
946
947 static void helpmod_cmd_term_find_plus (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
948 {
949 helpmod_cmd_term_find_general(sender, returntype, H_TERM_PLUS, ostr, argc, argv);
950 }
951
952 static void helpmod_cmd_klingon (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
953 {
954 hchannel *hchan;
955 huser *target = NULL;
956 int rand_val;
957
958 DEFINE_HCHANNEL;
959
960 if (hchan == NULL)
961 {
962 rand_val = rand() % KLINGON_NTARGETED;
963 helpmod_reply(sender, NULL, "%s: %s", huser_get_nick(sender), klingon_targeted[rand_val]);
964 return;
965 }
966
967 if (argc)
968 target = huser_get(getnickbynick(argv[0]));
969
970 if (target)
971 {
972 rand_val = rand() % KLINGON_NTARGETED;
973 helpmod_message_channel(hchan, "%s: %s", huser_get_nick(target), klingon_targeted[rand_val]);
974 }
975 else
976 {
977 rand_val = rand() % KLINGON_NGENERAL;
978 helpmod_message_channel(hchan, "%s", klingon_general[rand_val]);
979 }
980 }
981
982 void helpmod_cmd_term (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
983 {
984 hterm *htrm;
985 hterm **source;
986 hchannel *hchan;
987
988 DEFINE_HCHANNEL;
989
990 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
991
992 if (hchan == NULL)
993 source = &hterms;
994 else
995 source = &hchan->channel_hterms;
996
997 if (argc == 0)
998 {
999 helpmod_reply(sender, returntype, "Cannot handle terms: Operation not specified");
1000 return;
1001 }
1002 if (!ci_strcmp(argv[0], "list"))
1003 {
1004 char buffer[512];
1005 int count = 0;
1006 char *pattern = "*";
1007
1008 buffer[0] = '\0';
1009 htrm = *source;
1010
1011 if (argc >= 2)
1012 pattern = argv[1];
1013 else
1014 pattern = "*";
1015
1016 helpmod_reply(sender, returntype, "Terms matching pattern '%s'", pattern);
1017 for (;htrm;htrm = htrm->next)
1018 {
1019 if (strlen(buffer) >= 250)
1020 {
1021 helpmod_reply(sender, returntype, "%s", buffer);
1022 buffer[0] = '\0';
1023 }
1024 if (strregexp(htrm->description->content, pattern) || strregexp(htrm->name->content, pattern))
1025 {
1026 sprintf(buffer+strlen(buffer) /* :) */, "%s(%d) ", htrm->name->content, strlen(htrm->description->content));
1027 count++;
1028 }
1029 }
1030 if (buffer[0])
1031 helpmod_reply(sender, returntype, "%s", buffer);
1032 helpmod_reply(sender, returntype, "%d term%s match%s pattern '%s'", count, (count == 1)?"":"s", (count == 1)?"es":"", pattern);
1033 }
1034 else if (!ci_strcmp(argv[0], "listfull"))
1035 {
1036 htrm = *source;
1037 helpmod_reply(sender, returntype, "Following terms have been entered:");
1038 for (;htrm;htrm = htrm->next)
1039 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
1040 }
1041 else if (!ci_strcmp(argv[0], "get"))
1042 {
1043 if (argc < 2)
1044 {
1045 helpmod_reply(sender, returntype, "Cannot get term: Term not specified");
1046 return;
1047 }
1048 htrm = hterm_get(*source, argv[1]);
1049 if (htrm == NULL)
1050 helpmod_reply(sender, returntype, "Cannot get term: Term %s not found", argv[1]);
1051 else
1052 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
1053 }
1054 else if (!ci_strcmp(argv[0], "add"))
1055 {
1056 if (argc < 2)
1057 helpmod_reply(sender, returntype, "Cannot add term: Term name not specified");
1058 else if (argc < 3)
1059 helpmod_reply(sender, returntype, "Cannot add term: Term description not specified");
1060 else if ((htrm = hterm_get(*source, argv[1])) != NULL)
1061 helpmod_reply(sender, returntype, "Cannot add term: Term %s is already added", argv[1]);
1062 else
1063 {
1064 char *name = argv[1], *description;
1065 SKIP_WORD; SKIP_WORD;
1066 description = ostr;
1067 htrm = hterm_add(source, name, description);
1068 helpmod_reply(sender, returntype, "Term %s added succesfully", name);
1069 }
1070 }
1071 else if (!ci_strcmp(argv[0], "del"))
1072 {
1073 int i;
1074 if (argc < 2)
1075 {
1076 helpmod_reply(sender, returntype, "Cannot delete term: Term name not specified");
1077 return;
1078 }
1079 if (argc > H_CMD_MAX_ARGS)
1080 argc = H_CMD_MAX_ARGS;
1081 for (i=1;i<argc;i++)
1082 {
1083 htrm = hterm_get(*source, argv[i]);
1084 if (htrm == NULL)
1085 {
1086 helpmod_reply(sender, returntype, "Cannot delete term: Term %s not found", argv[i]);
1087 continue;
1088 }
1089 hterm_del(source != NULL?source:&hterms, htrm);
1090 helpmod_reply(sender, returntype, "Term %s deleted succesfully", argv[i]);
1091 }
1092 }
1093 else if (!ci_strcmp(argv[0], "find"))
1094 {
1095 if (argc < 2)
1096 {
1097 helpmod_reply(sender, returntype, "Cannot find term: Term name not specified");
1098 return;
1099 }
1100 htrm = hterm_get_and_find(*source, argv[1]);
1101
1102 if (htrm == NULL)
1103 {
1104 helpmod_reply(sender, returntype, "No term found matching '%s'", argv[1]);
1105 return;
1106 }
1107 if (returntype != NULL && huser_get_level(sender) > H_PEON)
1108 helpmod_message_channel(hchannel_get_by_channel(returntype), "(%s): %s", htrm->name->content, htrm->description->content);
1109 else
1110 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
1111 }
1112 else
1113 {
1114 helpmod_reply(sender, returntype, "Cannot handle terms: Operation not specified");
1115 }
1116 }
1117
1118 static void helpmod_cmd_queue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1119 {
1120 hchannel *hchan;
1121 int operation;
1122
1123 DEFINE_HCHANNEL;
1124
1125 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1126
1127 if (argc == 0)
1128 {
1129 helpmod_reply(sender, returntype, "Cannot handle queue: Operation not specified");
1130 return;
1131 }
1132
1133 if (!ci_strcmp(argv[0], "done"))
1134 operation = HQ_DONE;
1135 else if (!ci_strcmp(argv[0], "next"))
1136 operation = HQ_NEXT;
1137 else if (!ci_strcmp(argv[0], "on"))
1138 operation = HQ_ON;
1139 else if (!ci_strcmp(argv[0], "off"))
1140 operation = HQ_OFF;
1141 else if (!ci_strcmp(argv[0], "maintain"))
1142 operation = HQ_MAINTAIN;
1143 else if (!ci_strcmp(argv[0], "list"))
1144 operation = HQ_LIST;
1145 else if (!ci_strcmp(argv[0], "summary"))
1146 operation = HQ_SUMMARY;
1147 else if (!ci_strcmp(argv[0], "reset"))
1148 operation = HQ_RESET;
1149 else
1150 operation = HQ_NONE;
1151
1152 SKIP_WORD;
1153
1154 helpmod_queue_handler(sender, returntype, hchan, operation, ostr, argc, argv);
1155 }
1156
1157 static void helpmod_cmd_done (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1158 {
1159 hchannel *hchan;
1160 DEFINE_HCHANNEL;
1161 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1162 helpmod_queue_handler(sender, returntype, hchan, HQ_DONE, ostr, argc, argv);
1163 }
1164
1165 static void helpmod_cmd_next (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1166 {
1167 hchannel *hchan;
1168 DEFINE_HCHANNEL;
1169 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1170 helpmod_queue_handler(sender, returntype, hchan, HQ_NEXT, ostr, argc, argv);
1171 }
1172
1173 static void helpmod_cmd_enqueue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1174 {
1175 hchannel *hchan;
1176 DEFINE_HCHANNEL;
1177 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1178 helpmod_queue_handler(sender, returntype, hchan, HQ_ON, ostr, argc, argv);
1179 }
1180
1181 static void helpmod_cmd_dequeue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1182 {
1183 hchannel *hchan;
1184 DEFINE_HCHANNEL;
1185 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1186 helpmod_queue_handler(sender, returntype, hchan, HQ_OFF, ostr, argc, argv);
1187 }
1188
1189 static void helpmod_cmd_autoqueue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1190 {
1191 hchannel *hchan;
1192 DEFINE_HCHANNEL;
1193 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1194 helpmod_queue_handler(sender, returntype, hchan, HQ_MAINTAIN, ostr, argc, argv);
1195 }
1196
1197 static void helpmod_cmd_dnmo (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1198 {
1199 int i;
1200 if (argc == 0)
1201 {
1202 helpmod_reply(sender, returntype, "Cannot correct the luser: User not defined");
1203 return;
1204 }
1205 if (argc > H_CMD_MAX_ARGS)
1206 argc = H_CMD_MAX_ARGS;
1207 for (i=0;i<argc;i++)
1208 {
1209 huser *husr = huser_get(getnickbynick(argv[i]));
1210 if (husr == NULL)
1211 {
1212 helpmod_reply(sender, returntype, "Cannot correct the luser: User %s not found", argv[i]);
1213 continue;
1214 }
1215 if (huser_get_level(husr) > H_PEON)
1216 {
1217 helpmod_reply(sender, returntype, "Cannot correct the luser: User %s is not a peon", argv[i]);
1218 continue;
1219 }
1220 /*
1221 if (!hchannels_on_queue(husr) && !hchannels_on_desk(husr))
1222 {
1223 helpmod_reply(sender, returntype, "Cannot correct the luser: User %s is not in any queue", argv[i]);
1224 continue;
1225 }
1226 */
1227 hchannels_dnmo(husr);
1228
1229 helpmod_reply(husr, NULL, "You contacted a channel operator without permission. This is a violation of the channel rules. As a result you have been set to the last queue position");
1230 helpmod_reply(sender, returntype, "User %s has been informed of his mistake", argv[i]);
1231 }
1232 { /* fix the autoqueue for the channel(s) */
1233 hchannel *hchan;
1234 for (hchan = hchannels;hchan;hchan = hchan->next)
1235 hqueue_handle_queue(hchan, sender);
1236 }
1237 }
1238
1239 static void helpmod_cmd_ban (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1240 {
1241 if (argc == 0)
1242 {
1243 helpmod_reply(sender, returntype, "Cannot global handle bans: Operation not defined");
1244 return;
1245 }
1246
1247 else if (!ci_strcmp(argv[0], "list"))
1248 {
1249 hban *ptr = hbans;
1250 char *pattern;
1251 int count = 0;
1252
1253 if (argc == 1)
1254 pattern = "*";
1255 else
1256 pattern = argv[1];
1257
1258 helpmod_reply(sender, returntype, "Global bans matching pattern %s", pattern);
1259
1260 for (;ptr;ptr = ptr->next)
1261 if (strregexp(bantostring(ptr->real_ban), pattern))
1262 {
1263 helpmod_reply(sender, returntype, "%-64s %-15s %s", bantostring(ptr->real_ban), helpmod_strtime(ptr->expiration - time(NULL)), ptr->reason?ptr->reason->content:"");
1264 count++;
1265 }
1266
1267 helpmod_reply(sender, returntype, "%d Global bans match pattern %s", count, pattern);
1268 }
1269
1270 else if (!ci_strcmp(argv[0], "add"))
1271 {
1272 int duration = 4 * HDEF_h;
1273 char *reason = "Banned";
1274 char *target = argv[1];
1275
1276 if (argc == 1)
1277 {
1278 helpmod_reply(sender, returntype, "Cannot add global ban: Target hostmask not defined");
1279 return;
1280 }
1281 if (argc >= 3)
1282 {
1283 if ((duration = helpmod_read_strtime(argv[2])) < 0)
1284 {
1285 helpmod_reply(sender, returntype, "Cannot add global ban: Invalid time %s", argv[2]);
1286 return;
1287 }
1288 }
1289 if (argc >= 4)
1290 {
1291 SKIP_WORD;
1292 SKIP_WORD;
1293 SKIP_WORD;
1294
1295 reason = ostr;
1296 }
1297 hban_add(target, reason, time(NULL) + duration, 0);
1298 helpmod_reply(sender, returntype, "Added ban for %s (%s), expires in %s", target, reason, helpmod_strtime(duration));
1299 }
1300 else if (!ci_strcmp(argv[0], "del"))
1301 {
1302 int i;
1303 if (argc == 1)
1304 {
1305 helpmod_reply(sender, returntype, "Cannot remove global ban: Target hostmask not defined");
1306 return;
1307 }
1308 if (argc > H_CMD_MAX_ARGS)
1309 argc = H_CMD_MAX_ARGS;
1310 for (i=1;i<argc;i++)
1311 {
1312 hban *ptr = hban_get(argv[i]);
1313 if (ptr == NULL)
1314 {
1315 helpmod_reply(sender, returntype, "Cannot remove global ban: Hostmask %s is not banned", argv[i]);
1316 continue;
1317 }
1318 helpmod_reply(sender, returntype, "Global ban for hostmask %s removed", argv[i]);
1319 hban_del(ptr,0);
1320 }
1321 }
1322 else
1323 {
1324 helpmod_reply(sender, returntype, "Cannot handle global bans: Unknown operation %s", argv[0]);
1325 return;
1326 }
1327 }
1328
1329 static void helpmod_cmd_chanban (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1330 {
1331 hchannel *hchan;
1332 int i;
1333
1334 DEFINE_HCHANNEL;
1335
1336 if (hchan == NULL)
1337 {
1338 helpmod_reply(sender, returntype, "Cannot handle channel bans: Channel not defined or not found");
1339 return;
1340 }
1341
1342 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1343 /*
1344 if (argc == 0)
1345 {
1346 helpmod_reply(sender, returntype, "Cannot handle channel bans: Operation not defined");
1347 return;
1348 }
1349 */
1350 if (argc == 0 || !ci_strcmp(argv[0], "list"))
1351 {
1352 char *pattern, *cban;
1353 chanban *ptr = hchan->real_channel->bans;
1354 int count = 0;
1355
1356 if (argc <= 1)
1357 pattern = "*";
1358 else
1359 pattern = argv[1];
1360
1361 helpmod_reply(sender, returntype, "Bans matching pattern %s for channel %s", pattern, hchannel_get_name(hchan));
1362 for (;ptr;ptr = ptr->next)
1363 if (strregexp((cban = bantostring(ptr)), pattern))
1364 {
1365 count++;
1366 if (hchanban_get(hchan,cban))
1367 helpmod_reply(sender, returntype, "%s Expires in %s", bantostring(ptr), helpmod_strtime(hchanban_get(hchan, cban)->expiration - time(NULL)));
1368 else
1369 helpmod_reply(sender, returntype, "%s", bantostring(ptr));
1370 }
1371 helpmod_reply(sender, returntype, "%d bans match pattern %s on channel %s", count, pattern, hchannel_get_name(hchan));
1372 }
1373 else if (!ci_strcmp(argv[0], "add"))
1374 {
1375 if (argc == 1)
1376 {
1377 helpmod_reply(sender, returntype, "Cannot add channel bans: Pattern not defined");
1378 return;
1379 }
1380 if (argc > H_CMD_MAX_ARGS)
1381 argc = H_CMD_MAX_ARGS;
1382 for (i=1;i<argc;i++)
1383 {
1384 /* POSSIBLE BUG ? */
1385 helpmod_setban(hchan, argv[i], H_ETERNITY, MCB_ADD, HLAZY);
1386 helpmod_reply(sender, returntype, "Added ban %s to channel %s", argv[i], hchannel_get_name(hchan));
1387 }
1388 }
1389 else if (!ci_strcmp(argv[0], "del"))
1390 {
1391 if (argc == 1)
1392 {
1393 helpmod_reply(sender, returntype, "Cannot remove channel bans: Pattern not defined");
1394 return;
1395 }
1396 if (argc > H_CMD_MAX_ARGS)
1397 argc = H_CMD_MAX_ARGS;
1398 for (i=1;i<argc;i++)
1399 {
1400 chanban *ptr = hchan->real_channel->bans;
1401 for (;ptr;ptr = ptr->next)
1402 if (strregexp(bantostring(ptr), argv[i]))
1403 {
1404 helpmod_setban(hchan, argv[i], 0, MCB_DEL, HLAZY);
1405 helpmod_reply(sender, returntype, "Channel ban %s removed from channel %s", argv[i], hchannel_get_name(hchan));
1406 break;
1407 }
1408 if (ptr == NULL)
1409 helpmod_reply(sender, returntype, "Cannot remove channel ban: Pattern %s not banned on channel %s", argv[i], hchannel_get_name(hchan));
1410 }
1411 }
1412 else
1413 {
1414 helpmod_reply(sender, returntype, "Cannot handle channel bans: Unknown operation %s", argv[0]);
1415 return;
1416 }
1417 }
1418
1419 static void helpmod_cmd_idlekick (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1420 {
1421 hchannel *hchan;
1422 int tmp;
1423
1424 DEFINE_HCHANNEL;
1425
1426 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1427
1428 if (hchan == NULL)
1429 {
1430 helpmod_reply(sender, returntype, "Cannot handle the idlekick: Channel not defined or not found");
1431 return;
1432 }
1433 if (argc == 0) /* view */
1434 {
1435 helpmod_reply(sender, returntype, "Idlekick for channel %s is set to %s", hchannel_get_name(hchan), helpmod_strtime(hchan->max_idle));
1436 return;
1437 }
1438 else if ((tmp = helpmod_read_strtime(argv[0])) < 0 || tmp < HDEF_m || tmp > HDEF_w)
1439 {
1440 helpmod_reply(sender, returntype, "Cannot set the idlekick: Invalid time given '%s'", argv[0]);
1441 return;
1442 }
1443 else /* set it ! */
1444 {
1445 hchan->max_idle = tmp;
1446 helpmod_reply(sender, returntype, "Idlekick for channel %s set to %s succesfully", hchannel_get_name(hchan), helpmod_strtime(hchan->max_idle));
1447 }
1448 }
1449
1450 static void helpmod_cmd_topic (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1451 {
1452 hchannel *hchan;
1453 DEFINE_HCHANNEL;
1454
1455 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1456
1457 if (hchan == NULL)
1458 {
1459 helpmod_reply(sender, returntype, "Cannot handle the topic: Channel not defined or not found");
1460 return;
1461 }
1462 if (!(hchan -> flags & H_HANDLE_TOPIC))
1463 helpmod_reply(sender, returntype, "Note: I'm not set to handle the topic on channel %s", hchannel_get_name(hchan));
1464
1465 if (argc == 0) /* check the topic */
1466 {
1467 helpmod_reply(sender, returntype, "Topic of channel %s is currently: %s", hchannel_get_name(hchan), htopic_construct(hchan->topic));
1468 return;
1469 }
1470 if (!ci_strcmp(argv[0], "erase"))
1471 {
1472 htopic_del_all(&hchan->topic);
1473 hchannel_set_topic(hchan);
1474 helpmod_reply(sender, returntype, "Topic of channel %s erased", hchannel_get_name(hchan));
1475 }
1476 else if (!ci_strcmp(argv[0], "refresh"))
1477 {
1478 hchannel_set_topic(hchan);
1479 helpmod_reply(sender, returntype, "Topic of channel %s refreshed", hchannel_get_name(hchan));
1480 }
1481 else if (!ci_strcmp(argv[0], "add"))
1482 {
1483 int pos;
1484 SKIP_WORD;
1485 if (argc == 0)
1486 {
1487 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1488 return;
1489 }
1490 if (sscanf(argv[0], "%d", &pos) && pos >= 0)
1491 {
1492 SKIP_WORD;
1493 }
1494 else
1495 pos = 0;
1496 if (argc == 0) /* lame repeat :( */
1497 {
1498 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1499 return;
1500 }
1501 if (htopic_len(hchan->topic) + strlen(ostr) + 3 > TOPICLEN)
1502 {
1503 helpmod_reply(sender, returntype, "Cannot add to the topic of channel %s: Maximum topic length exceeded", hchannel_get_name(hchan));
1504 return;
1505 }
1506
1507 htopic_add(&hchan->topic, ostr, pos);
1508 hchannel_set_topic(hchan);
1509 helpmod_reply(sender, returntype, "Added '%s' to the topic of channel %s", ostr, hchannel_get_name(hchan));
1510 }
1511 else if (!ci_strcmp(argv[0], "del"))
1512 {
1513 int pos;
1514 if (argc == 1)
1515 {
1516 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1517 return;
1518 }
1519 SKIP_WORD;
1520 if (!sscanf(argv[0], "%d", &pos) || pos < 0)
1521 {
1522 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Expected positive integer", hchannel_get_name(hchan));
1523 return;
1524 }
1525 if (htopic_count(hchan->topic) < pos)
1526 {
1527 helpmod_reply(sender, returntype, "Cannot delete from the topic of channel %s: No such topic element %d", hchannel_get_name(hchan), pos);
1528 return;
1529 }
1530 htopic_del(&hchan->topic, htopic_get(hchan->topic, pos));
1531 hchannel_set_topic(hchan);
1532 }
1533 else if (!ci_strcmp(argv[0], "set"))
1534 {
1535 if (argc == 1)
1536 {
1537 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1538 return;
1539 }
1540 SKIP_WORD;
1541 htopic_del_all(&hchan->topic);
1542 htopic_add(&hchan->topic, ostr, 0);
1543 hchannel_set_topic(hchan);
1544 }
1545 else
1546 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Unknown operation %s", hchannel_get_name(hchan), argv[0]);
1547 }
1548
1549 static void helpmod_cmd_out (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1550 {
1551 huser *husr;
1552 int i;
1553 char *reason = "Banned";
1554 huser *targets[H_CMD_MAX_ARGS];
1555 int ntargets = 0;
1556
1557 if (argc == 0)
1558 {
1559 helpmod_reply(sender, returntype, "Cannot get rid of the user: User not specified");
1560 return;
1561 }
1562
1563 if (argc > H_CMD_MAX_ARGS)
1564 argc = H_CMD_MAX_ARGS;
1565 for (i=0;i<argc;i++)
1566 {
1567 if (argv[i][0] == ':')
1568 {
1569 if (i == 0)
1570 {
1571 helpmod_reply(sender, returntype, "Cannot get rid of users: No users specified");
1572 return;
1573 }
1574 while (i--)
1575 {
1576 SKIP_WORD;
1577 }
1578 reason = ostr + 1;
1579 break;
1580 }
1581
1582 husr = huser_get(getnickbynick(argv[i]));
1583 if (husr == NULL)
1584 {
1585 helpmod_reply(sender, returntype, "Cannot get rid of the user: User %s not found", argv[i]);
1586 continue;
1587 }
1588 if (huser_get_level(husr) > H_PEON)
1589 {
1590 helpmod_reply(sender, returntype, "Cannot get rid of the user: User %s is not a peon", huser_get_nick(husr));
1591 continue;
1592 }
1593 targets[ntargets++] = husr;
1594 }
1595
1596 for (i=0;i<ntargets;i++)
1597 {
1598 const char *banmask = hban_ban_string(targets[i]->real_user, HBAN_HOST);
1599
1600 hban_add(banmask, reason, time(NULL) + HCMD_OUT_DEFAULT, HLAZY);
1601
1602 helpmod_reply(sender, returntype, "User %s is now gone", huser_get_nick(targets[i]));
1603 }
1604 hcommit_modes();
1605 }
1606
1607 static void helpmod_cmd_everyoneout (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1608 {
1609 hchannel *hchan;
1610 hchannel_user **hchanuser;
1611 char *reason = "clearing channel";
1612 int autoqueue_tmp = -1;
1613
1614 DEFINE_HCHANNEL;
1615
1616 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1617
1618 if (hchan == NULL)
1619 {
1620 helpmod_reply(sender, returntype, "Cannot clear channel: Channel not defined or not found");
1621 return;
1622 }
1623
1624 if (argc)
1625 reason = ostr;
1626
1627 hchan->flags |= H_MAINTAIN_I;
1628 hchannel_mode_check(hchan);
1629
1630 hchanuser = &hchan->channel_users;
1631
1632 if ((hchan->flags & H_QUEUE) && (hchan->flags & H_QUEUE_MAINTAIN))
1633 {
1634 autoqueue_tmp = hchan->autoqueue;
1635 hchan->autoqueue = 0;
1636 }
1637
1638 while (*hchanuser)
1639 {
1640 if (huser_get_level((*hchanuser)->husr) < H_TRIAL)
1641 helpmod_kick(hchan, (*hchanuser)->husr, reason);
1642 else
1643 hchanuser = &(*hchanuser)->next;
1644 }
1645
1646 if (autoqueue_tmp > 0)
1647 hchan->autoqueue = autoqueue_tmp;
1648
1649 helpmod_reply(sender, returntype, "Channel %s has been cleared of normal users", hchannel_get_name(hchan));
1650 }
1651
1652 static void helpmod_cmd_kick (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1653 {
1654 hchannel *hchan;
1655 int i;
1656 huser *husr, *targets[H_CMD_MAX_ARGS];
1657 int ntargets = 0;
1658 char *reason = "out";
1659 DEFINE_HCHANNEL;
1660
1661 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1662
1663 if (hchan == NULL)
1664 {
1665 helpmod_reply(sender, returntype, "Cannot kick the user: Channel not defined or not found");
1666 return;
1667 }
1668
1669 if (argc == 0)
1670 {
1671 helpmod_reply(sender, returntype, "Cannot kick users: No users specified");
1672 return;
1673 }
1674
1675 if (argc > H_CMD_MAX_ARGS)
1676 argc = H_CMD_MAX_ARGS;
1677 for (i=0;i<argc;i++)
1678 {
1679 if (*argv[i] == ':')
1680 {
1681 if (i == 0)
1682 {
1683 helpmod_reply(sender, returntype, "Cannot kick the user: No users defined");
1684 return;
1685 }
1686 while (i--)
1687 {
1688 SKIP_WORD;
1689 }
1690 reason = ostr+1;
1691 break;
1692 }
1693 husr = huser_get(getnickbynick(argv[i]));
1694 if (husr == NULL)
1695 {
1696 helpmod_reply(sender, returntype, "Cannot kick the user: User %s not found", argv[i]);
1697 continue;
1698 }
1699 if (huser_on_channel(husr, hchan) == NULL)
1700 {
1701 helpmod_reply(sender, returntype, "Cannot kick the user: User %s is not on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
1702 continue;
1703 }
1704 if (huser_get_level(husr) > H_PEON)
1705 {
1706 helpmod_reply(sender, returntype, "Cannot kick the user: User %s is not a peon", huser_get_nick(husr));
1707 continue;
1708 }
1709 targets[ntargets++] = husr;
1710 }
1711
1712 for (i=0;i<ntargets;i++)
1713 helpmod_kick(hchan, targets[i], reason);
1714 }
1715
1716 static void helpmod_cmd_stats (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1717 {
1718 hchannel *hchan;
1719 haccount *target = sender->account;
1720 hstat_account *ptr;
1721 hstat_account_entry *stat_entry;
1722 int days = 1, weeks = 0;
1723 int type = HSTAT_ACCOUNT_SHORT;
1724
1725 time_t timer = time(NULL);
1726 struct tm *tstruct = localtime(&timer);
1727
1728 int i = 0;
1729
1730 DEFINE_HCHANNEL;
1731
1732 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1733
1734 if (hchan == NULL)
1735 {
1736 helpmod_reply(sender, returntype, "Cannot show user statistics: Channel not defined or not found");
1737 return;
1738 }
1739
1740 if (argc > 0 && huser_get_level(sender) == H_ADMIN)
1741 { /* not very elegant */
1742 if (argv[0][0] == '#') /* account */
1743 {
1744 target = haccount_get_by_name(argv[0]+1);
1745 if (target == NULL)
1746 {
1747 helpmod_reply(sender, returntype, "Cannot show user statistics: Account %s not found", argv[0]);
1748 return;
1749 }
1750 SKIP_WORD;
1751 }
1752 }
1753
1754 if (target == NULL)
1755 {
1756 helpmod_reply(sender, returntype, "Cannot show user statistics: You do not have an account");
1757 return;
1758 }
1759
1760 if (argc > 0)
1761 {
1762 if (!ci_strcmp(argv[0], "short") || !ci_strcmp(argv[0], "s"))
1763 {
1764 type = HSTAT_ACCOUNT_SHORT;
1765 SKIP_WORD;
1766 }
1767 else if (!ci_strcmp(argv[0], "long") || !ci_strcmp(argv[0], "l"))
1768 {
1769 type = HSTAT_ACCOUNT_LONG;
1770 SKIP_WORD;
1771 }
1772 }
1773
1774 if (argc > 0)
1775 if (sscanf(argv[0], "%d", &days))
1776 {
1777 if (days < 0 || days > 7)
1778 {
1779 helpmod_reply(sender, returntype, "Cannot show user statistics: Expected integer between [0, 7]");
1780 return;
1781 }
1782 else
1783 {
1784 SKIP_WORD;
1785 }
1786 }
1787
1788 if (argc > 0)
1789 if (sscanf(argv[0], "%d", &weeks))
1790 {
1791 if (weeks < 0 || weeks > 10)
1792 {
1793 helpmod_reply(sender, returntype, "Cannot show user statistics: Expected integer between [0, 10]");
1794 return;
1795 }
1796 else
1797 {
1798 SKIP_WORD;
1799 }
1800 }
1801
1802 for (ptr = target->stats;ptr;ptr = ptr->next)
1803 if (ptr->hchan == hchan)
1804 break;
1805
1806 if (ptr == NULL)
1807 {
1808 helpmod_reply(sender, returntype, "Cannot show user statistics: User %s has no statistics for channel %s", target->name->content, hchannel_get_name(hchan));
1809 return;
1810 }
1811
1812 if (!days && !weeks)
1813 return;
1814
1815 helpmod_reply(sender, returntype, "Statistics for user %s on channel %s", target->name->content, hchannel_get_name(hchan));
1816
1817 if (days)
1818 {
1819 helpmod_reply(sender, returntype, "Last %d day%s", days, (days==1)?"":"s");
1820 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1821 for (i=0;i<days;i++)
1822 {
1823 stat_entry = &ptr->week[(tstruct->tm_wday - i + 7) % 7];
1824 helpmod_reply(sender, returntype, "%s", hstat_account_print(stat_entry, type));
1825 }
1826 }
1827
1828 if (weeks)
1829 {
1830 helpmod_reply(sender, returntype, "Last %d week%s", weeks, (weeks==1)?"":"s");
1831 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1832 for (i=0;i<weeks;i++)
1833 {
1834 stat_entry = &ptr->longterm[(hstat_week() - i + 10) % 10];
1835 helpmod_reply(sender, returntype, "%s", hstat_account_print(stat_entry, type));
1836 }
1837 }
1838 }
1839
1840 static void helpmod_cmd_chanstats (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1841 {
1842 hchannel *hchan;
1843 hstat_channel *channel_stats;
1844 hstat_channel_entry *stat_entry;
1845
1846 time_t timer = time(NULL);
1847 struct tm *tstruct = localtime(&timer);
1848
1849 int days=1;
1850 int type = HSTAT_CHANNEL_SHORT;
1851 int weeks=0;
1852
1853 int i = 7;
1854
1855 DEFINE_HCHANNEL;
1856
1857 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1858
1859 if (hchan == NULL)
1860 {
1861 helpmod_reply(sender, returntype, "Cannot show channel statistics: Channel not defined or not found");
1862 return;
1863 }
1864
1865 if (argc > 0)
1866 {
1867 if (!ci_strcmp(argv[0], "short") || !ci_strcmp(argv[0], "s"))
1868 {
1869 type = HSTAT_CHANNEL_SHORT;
1870 SKIP_WORD;
1871 }
1872 else if (!ci_strcmp(argv[0], "long") || !ci_strcmp(argv[0], "l"))
1873 {
1874 type = HSTAT_CHANNEL_LONG;
1875 SKIP_WORD;
1876 }
1877 }
1878
1879 if (argc > 0)
1880 if (sscanf(argv[0], "%d", &days))
1881 {
1882 if (days < 0 || days > 7)
1883 {
1884 helpmod_reply(sender, returntype, "Cannot show channel statistics: Expected integer between [0, 7]");
1885 return;
1886 }
1887 else
1888 {
1889 SKIP_WORD;
1890 }
1891 }
1892
1893 if (argc > 0)
1894 if (sscanf(argv[0], "%d", &weeks))
1895 {
1896 if (weeks < 0 || weeks > 10)
1897 {
1898 helpmod_reply(sender, returntype, "Cannot show channel statistics: Expected integer between [0, 10]");
1899 return;
1900 }
1901 else
1902 {
1903 SKIP_WORD;
1904 }
1905 }
1906
1907 channel_stats = hchan->stats;
1908
1909 if (!days && !weeks)
1910 return;
1911
1912 helpmod_reply(sender, returntype, "Statistics for channel %s", hchannel_get_name(hchan));
1913
1914 if (days)
1915 {
1916 helpmod_reply(sender, returntype, "Last %d day%s", days, (days==1)?"":"s");
1917 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1918 for (i=0;i<days;i++) /* latest week */
1919 {
1920 stat_entry = &hchan->stats->week[(tstruct->tm_wday - i + 7) % 7];
1921 helpmod_reply(sender, returntype, "%s", hstat_channel_print(stat_entry, type));
1922 }
1923 }
1924
1925 if (weeks)
1926 {
1927 helpmod_reply(sender, returntype, "Last %d week%s", weeks, (weeks==1)?"":"s");
1928 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1929 for (i=0;i<weeks;i++) /* latest weeks */
1930 {
1931 stat_entry = &hchan->stats->longterm[(hstat_week() - i + 10) % 10];
1932 helpmod_reply(sender, returntype, "%s", hstat_channel_print(stat_entry, type));
1933 }
1934 }
1935 }
1936
1937 static void helpmod_cmd_activestaff (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1938 {
1939 hchannel *hchan;
1940 hstat_accounts_array arr;
1941 hlevel lvl = H_OPER;
1942 int listtype = 0;
1943 int i;
1944
1945 DEFINE_HCHANNEL;
1946
1947 if (hchan == NULL)
1948 {
1949 helpmod_reply(sender, returntype, "Cannot list active staff: Channel not specified or not found");
1950 return;
1951 }
1952
1953 if (argc == 1)
1954 {
1955 if (!ci_strcmp(argv[0], "opers") || !ci_strcmp(argv[0], "o"))
1956 {
1957 lvl = H_OPER;
1958 SKIP_WORD;
1959 }
1960 else if (!ci_strcmp(argv[0], "staff") || !ci_strcmp(argv[0], "s"))
1961 {
1962 lvl = H_STAFF;
1963 SKIP_WORD;
1964 }
1965 else if (!ci_strcmp(argv[0], "staff") || !ci_strcmp(argv[0], "s"))
1966 {
1967 lvl = H_ANY;
1968 SKIP_WORD;
1969 }
1970 }
1971
1972 if (argc == 1)
1973 {
1974 if (!ci_strcmp(argv[0], "active") || !ci_strcmp(argv[0], "a"))
1975 {
1976 listtype = 0;
1977 SKIP_WORD;
1978 }
1979 else if (!ci_strcmp(argv[0], "inactive") || !ci_strcmp(argv[0], "i"))
1980 {
1981 listtype = 1;
1982 SKIP_WORD;
1983 }
1984 }
1985
1986 arr = create_hstat_account_array(hchan, lvl);
1987
1988 helpmod_reply(sender, returntype, "%s %ss for channel %s", listtype?"Inactive":"Active", hlevel_name(lvl), hchannel_get_name(hchan));
1989 switch (listtype)
1990 {
1991 case 0:
1992 for (i=0;i < arr.arrlen && arr.array[i].prime_time_spent > H_ACTIVE_LIMIT;i++)
1993 helpmod_reply(sender, returntype, "#%-2d %-20s %-20s %-20s", i+1,((haccount*)(arr.array[i].owner))->name->content, helpmod_strtime(arr.array[i].prime_time_spent), helpmod_strtime(arr.array[i].time_spent));
1994 break;
1995 case 1:
1996 for (i=arr.arrlen-1;i >= 0 && arr.array[i].prime_time_spent < H_ACTIVE_LIMIT;i--)
1997 helpmod_reply(sender, returntype, "#%-2d %-20s %-20s %-20s", (arr.arrlen - i),((haccount*)(arr.array[i].owner))->name->content, helpmod_strtime(arr.array[i].prime_time_spent), helpmod_strtime(arr.array[i].time_spent));
1998 break;
1999 }
2000
2001 free(arr.array);
2002 }
2003
2004 static void helpmod_cmd_top10 (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2005 {
2006 hchannel *hchan;
2007 hstat_accounts_array arr;
2008 hlevel lvl = H_OPER;
2009 int i, top_n = 10;
2010
2011 DEFINE_HCHANNEL;
2012
2013 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2014
2015 if (hchan == NULL)
2016 {
2017 helpmod_reply(sender, returntype, "Cannot list channel Top10: Channel not specified or not found");
2018 return;
2019 }
2020
2021 if (argc >= 1)
2022 {
2023 if (!ci_strcmp(argv[0], "opers") || !ci_strcmp(argv[0], "o"))
2024 lvl = H_OPER;
2025 else if (!ci_strcmp(argv[0], "staff") || !ci_strcmp(argv[0], "s"))
2026 lvl = H_STAFF;
2027 else if (!ci_strcmp(argv[0], "all") || !ci_strcmp(argv[0], "a"))
2028 lvl = H_ANY;
2029 }
2030 if (argc == 3)
2031 {
2032 int tmp;
2033 if (sscanf(argv[1], "%d", &tmp) && (tmp >= 10) && (tmp <= 50))
2034 top_n = tmp;
2035 }
2036
2037 arr = create_hstat_account_array(hchan, lvl);
2038
2039 helpmod_reply(sender, returntype, "Top%d most active %ss of channel %s", top_n, hlevel_name(lvl), hchannel_get_name(hchan));
2040 for (i=0;i < arr.arrlen && i < top_n;i++)
2041 helpmod_reply(sender, returntype, "#%-2d %-20s %-20s %-20s",i+1,((haccount*)(arr.array[i].owner))->name->content, helpmod_strtime(arr.array[i].prime_time_spent), helpmod_strtime(arr.array[i].time_spent));
2042
2043 free(arr.array);
2044 }
2045
2046 static void helpmod_cmd_report (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2047 {
2048 hchannel *hchan, *target;
2049 DEFINE_HCHANNEL;
2050
2051 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2052
2053 if (hchan != NULL && (argc == 2))
2054 {
2055 hchan = hchannel_get_by_name(argv[0]);
2056 SKIP_WORD;
2057 }
2058
2059 if (hchan == NULL)
2060 {
2061 helpmod_reply(sender, returntype, "Cannot view or set channel reporting: Channel not defined or not found");
2062 return;
2063 }
2064 if (argc != 1)
2065 {
2066 if (hchan->report_to == NULL || !hchannel_is_valid(hchan->report_to))
2067 helpmod_reply(sender, returntype, "Channel %s is not reported anywhere (%s)", hchannel_get_name(hchan), hchannel_get_state(hchan, H_REPORT));
2068 else
2069 helpmod_reply(sender, returntype, "Channel %s is reported to channel %s (%s)", hchannel_get_name(hchan), hchannel_get_name(hchan->report_to), hchannel_get_state(hchan, H_REPORT));
2070 return;
2071 }
2072 if ((target = hchannel_get_by_name(argv[0])) == NULL)
2073 {
2074 helpmod_reply(sender, returntype, "Cannot set channel reporting: Channel %s not found", argv[0]);
2075 return;
2076 }
2077 hchan->report_to = target;
2078 helpmod_reply(sender, returntype, "Channel %s is now reported to channel %s (%s)", hchannel_get_name(hchan), hchannel_get_name(hchan->report_to), hchannel_get_state(hchan, H_REPORT));
2079 }
2080
2081 static void helpmod_cmd_mode(huser *sender, channel* returntype, int change, char* ostr, int argc, char *argv[])
2082 {
2083 hchannel *hchan;
2084 huser_channel *huserchan;
2085 huser *husr;
2086 int i;
2087
2088 DEFINE_HCHANNEL;
2089
2090 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2091
2092 if (hchan == NULL)
2093 {
2094 helpmod_reply(sender, returntype, "Cannot change mode: Channel not specified or not found");
2095 return;
2096 }
2097
2098 if (argc==0) /* for a simple opme */
2099 {
2100 argc = 1;
2101 argv[0] = (char*)huser_get_nick(sender);
2102 }
2103
2104 if (argc > H_CMD_MAX_ARGS)
2105 argc = H_CMD_MAX_ARGS;
2106
2107 for (i=0;i<argc;i++)
2108 {
2109 husr = huser_get(getnickbynick(argv[i]));
2110 if (husr == NULL)
2111 {
2112 helpmod_reply(sender, returntype, "Cannot change mode: User %s not found", argv[i], hchannel_get_name(hchan));
2113 continue;
2114 }
2115 huserchan = huser_on_channel(husr, hchan);
2116 if (huserchan == NULL)
2117 {
2118 helpmod_reply(sender, returntype, "Cannot change mode: User %s it not on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2119 continue;
2120 }
2121
2122 switch (change)
2123 {
2124 case H_CMD_OP:
2125 {
2126 int j;
2127 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2128 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2129 break;
2130 if ((huserchan->flags & HCUMODE_OP) && !(hchan->real_channel->users->content[j] & CUMODE_OP))
2131 {
2132 huserchan->flags &= ~HCUMODE_OP;
2133 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (+o when should be -o)");
2134 }
2135 if (huserchan->flags & HCUMODE_OP)
2136 {
2137 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already +o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2138 continue;
2139 }
2140 if (huser_get_level(husr) < H_STAFF)
2141 {
2142 helpmod_reply(sender, returntype, "Cannot change mode: User %s is not allowed to have +o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2143 continue;
2144 }
2145 helpmod_channick_modes(husr, hchan, MC_OP, HLAZY);
2146 }
2147 break;
2148 case H_CMD_DEOP:
2149 {
2150 int j;
2151 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2152 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2153 break;
2154 if (!(huserchan->flags & HCUMODE_OP) && (hchan->real_channel->users->content[j] & CUMODE_OP))
2155 {
2156 huserchan->flags |= HCUMODE_OP;
2157 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (-o when should be +o)");
2158 }
2159 if (!(huserchan->flags & HCUMODE_OP))
2160 {
2161 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already -o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2162 continue;
2163 }
2164 if (huser_get_level(husr) > huser_get_level(sender))
2165 {
2166 helpmod_reply(sender, returntype, "Cannot change mode: User %s is meant to have +o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2167 continue;
2168 }
2169 helpmod_channick_modes(husr, hchan, MC_DEOP, HLAZY);
2170 }
2171 break;
2172 case H_CMD_VOICE:
2173 {
2174 int j;
2175 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2176 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2177 break;
2178 if ((huserchan->flags & HCUMODE_VOICE) && !(hchan->real_channel->users->content[j] & CUMODE_VOICE))
2179 {
2180 huserchan->flags &= ~HCUMODE_VOICE;
2181 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (+v when should be -v)");
2182 }
2183 if (huserchan->flags & HCUMODE_VOICE)
2184 {
2185 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already +v on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2186 continue;
2187 }
2188 helpmod_channick_modes(husr, hchan, MC_VOICE, HLAZY);
2189 }
2190 break;
2191 case H_CMD_DEVOICE:
2192 {
2193 int j;
2194 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2195 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2196 break;
2197 if (!(huserchan->flags & HCUMODE_VOICE) && (hchan->real_channel->users->content[j] & CUMODE_VOICE))
2198 {
2199 huserchan->flags |= HCUMODE_VOICE;
2200 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (-v when should be +v)");
2201 }
2202 if (!(huserchan->flags & HCUMODE_VOICE))
2203 {
2204 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already -v on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2205 continue;
2206 }
2207 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
2208 }
2209 break;
2210 }
2211 }
2212 }
2213
2214 static void helpmod_cmd_op (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_OP, ostr, argc, argv); }
2215 static void helpmod_cmd_deop (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_DEOP, ostr, argc, argv); }
2216 static void helpmod_cmd_voice (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_VOICE, ostr, argc, argv); }
2217 static void helpmod_cmd_devoice (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_DEVOICE, ostr, argc, argv); }
2218
2219 static void helpmod_cmd_invite (huser *sender, channel *returntype, char* arg, int argc, char *argv[])
2220 {
2221 hchannel *hchan;
2222 int i;
2223
2224 if (argc == 0)
2225 {
2226 helpmod_reply(sender, returntype, "Cannot invite: Channel not defined or not found");
2227 return;
2228 }
2229
2230 if (huser_get_level(sender) == H_PEON)
2231 {
2232 hticket *htick;
2233 hchan = hchannel_get_by_name(argv[0]);
2234 if (hchan == NULL)
2235 {
2236 helpmod_reply(sender, returntype, "Cannot invite: Unknown channel %s", argv[0]);
2237 return;
2238 }
2239 /* if tickets don't work, it's better that the user doesn't know that the channel really exists */
2240 if (!(hchan->flags & H_REQUIRE_TICKET))
2241 {
2242 helpmod_reply(sender, returntype, "Cannot invite: Unknown channel %s", argv[0]);
2243 return;
2244 }
2245 htick = hticket_get(huser_get_auth(sender), hchan);
2246
2247 if (htick == NULL)
2248 {
2249 helpmod_reply(sender, returntype, "Cannot invite: You do not have an invite ticket for channel %s", argv[0]);
2250 return;
2251 }
2252
2253 if (nickbanned(sender->real_user, hchan->real_channel))
2254 {
2255 helpmod_reply(sender, returntype, "Cannot invite: You are banned from channel %s", argv[0]);
2256 return;
2257 }
2258
2259 helpmod_invite(hchan, sender);
2260 helpmod_reply(sender, returntype, "Invited you to channel %s", hchannel_get_name(hchan));
2261 return;
2262 }
2263
2264 if (argc > H_CMD_MAX_ARGS)
2265 argc = H_CMD_MAX_ARGS;
2266
2267 for (i = 0;i < argc; i++)
2268 {
2269 hchan = hchannel_get_by_name(argv[i]);
2270 if (hchan == NULL)
2271 {
2272 helpmod_reply(sender, returntype, "Cannot invite: Unknown channel %s", argv[i]);
2273 continue;
2274 }
2275 if (!(hchannel_authority(hchan, sender) || hticket_get(huser_get_auth(sender), hchan)))
2276 {
2277 helpmod_reply(sender, returntype, "Sorry, channel %s is oper only", hchannel_get_name(hchan));
2278 continue;
2279 }
2280 if (huser_on_channel(sender, hchan) != NULL)
2281 {
2282 helpmod_reply(sender, returntype, "Cannot invite: You are already on channel %s", hchannel_get_name(hchan));
2283 continue;
2284 }
2285 helpmod_invite(hchan, sender);
2286 helpmod_reply(sender, returntype, "Invited you to channel %s", hchannel_get_name(hchan));
2287 }
2288 }
2289
2290 static void helpmod_cmd_ticket (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2291 {
2292 int expiration = HTICKET_EXPIRATION_TIME;
2293 hchannel *hchan;
2294 huser *husr;
2295 hticket *htick;
2296
2297 if (argc < 1)
2298 {
2299 helpmod_reply(sender, returntype, "Cannot issue a ticket: Channel not specified");
2300 return;
2301 }
2302
2303 hchan = hchannel_get_by_name(argv[0]);
2304 if (hchan == NULL)
2305 {
2306 helpmod_reply(sender, returntype, "Cannot issue a ticket: Unknown channel %s", argv[0]);
2307 return;
2308 }
2309 if (!(hchan->flags & H_REQUIRE_TICKET))
2310 {
2311 helpmod_reply(sender, returntype, "Cannot issue a ticket: Tickets are not enabled for channel %s", argv[0]);
2312 return;
2313 }
2314 if (argc < 2)
2315 {
2316 helpmod_reply(sender, returntype, "Cannot issue a ticket: Target user not specified");
2317 return;
2318 }
2319
2320 husr = huser_get(getnickbynick(argv[1]));
2321 if (husr == NULL)
2322 {
2323 helpmod_reply(sender, returntype, "Cannot issue a ticket: Unknown user %s", argv[1]);
2324 return;
2325 }
2326 if (!IsAccount(husr->real_user))
2327 {
2328 helpmod_reply(sender, returntype, "Cannot issue a ticket: User %s is not authed", argv[1]);
2329 return;
2330 }
2331 if (huser_get_level(husr) < H_PEON)
2332 {
2333 helpmod_reply(sender, returntype, "Cannot issue a ticket: User %s is considered improper and not worthy of a ticket", argv[1]);
2334 return;
2335 }
2336 if (huser_get_level(husr) > H_PEON)
2337 {
2338 helpmod_reply(sender, returntype, "Cannot issue a ticket: User %s does not require a ticket", argv[1]);
2339 return;
2340 }
2341 if (argc >= 3)
2342 {
2343 int tmp;
2344 tmp = helpmod_read_strtime(argv[2]);
2345 if (tmp > HDEF_m && tmp < 2 * HDEF_M)
2346 expiration = tmp;
2347 }
2348
2349 htick = hticket_get(huser_get_auth(husr), hchan);
2350
2351 if (htick != NULL)
2352 htick->time_expiration = time(NULL) + expiration;
2353 else
2354 hticket_add(huser_get_auth(husr), time(NULL) + expiration, hchan);
2355
2356 helpmod_reply(sender, returntype, "Issued an invite ticket to user %s for channel %s expiring in %s", huser_get_nick(husr), hchannel_get_name(hchan), helpmod_strtime(expiration));
2357 helpmod_reply(husr, NULL, "You have been issued an invite ticket for channel %s. This ticket is valid for a period of %s. You can use my invite command to get to the channel now. Type /msg %s invite %s",hchannel_get_name(hchan), helpmod_strtime(HTICKET_EXPIRATION_TIME), helpmodnick->nick, hchannel_get_name(hchan));
2358 if (hchan->flags & H_TICKET_MESSAGE && hchan->ticket_message != NULL)
2359 helpmod_reply(husr, NULL, "Ticket information for %s: %s", hchannel_get_name(hchan), hchan->ticket_message->content);
2360
2361 }
2362 static void helpmod_cmd_resolve (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2363 {
2364 int i;
2365 hchannel *hchan;
2366 hticket *htick;
2367 huser *husr;
2368
2369 DEFINE_HCHANNEL;
2370
2371 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2372
2373 if (argc > H_CMD_MAX_ARGS)
2374 argc = H_CMD_MAX_ARGS;
2375
2376 if (hchan == NULL)
2377 {
2378 helpmod_reply(sender, returntype, "Cannot resolve a ticket: The channel is not specified");
2379 return;
2380 }
2381
2382 for (i = 0;i< argc;i++)
2383 {
2384 if (argv[i][0] == '#')
2385 {
2386 htick = hticket_get(&argv[i][1], hchan);
2387 if (htick == NULL)
2388 {
2389 helpmod_reply(sender, returntype, "Cannot resolve a ticket: Authname %s does not have a ticket for channel %s", &argv[i][1], hchannel_get_name(hchan));
2390 continue;
2391 }
2392 hticket_del(htick, hchan);
2393 helpmod_reply(sender, returntype, "Resolved authname %s's ticket for channel %s", &argv[i][1], hchannel_get_name(hchan));
2394 }
2395 else
2396 {
2397 husr = huser_get(getnickbynick(argv[i]));
2398 if (husr == NULL)
2399 {
2400 helpmod_reply(sender, returntype, "Cannot resolve a ticket: User %s not found", argv[i]);
2401 continue;
2402 }
2403 if (!IsAccount(husr->real_user))
2404 {
2405 helpmod_reply(sender, returntype, "Cannot resolve a ticket: User %s is not authed", argv[i]);
2406 continue;
2407 }
2408 htick = hticket_get(huser_get_auth(husr),hchan);
2409 if (htick == NULL)
2410 {
2411 helpmod_reply(sender, returntype, "Cannot resolve a ticket: User %s does not have a ticket for channel %s", argv[i], hchannel_get_name(hchan));
2412 continue;
2413 }
2414 hticket_del(htick, hchan);
2415 helpmod_reply(sender, returntype, "Resolved user %s's ticket for channel %s", argv[i], hchannel_get_name(hchan));
2416 }
2417 }
2418 }
2419
2420 static void helpmod_cmd_tickets (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2421 {
2422 hchannel *hchan;
2423 hticket *htick;
2424 int i;
2425
2426 DEFINE_HCHANNEL;
2427
2428 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2429
2430 if (hchan == NULL)
2431 {
2432 helpmod_reply(sender, returntype, "Cannot list tickets: Channel not defined or not found");
2433 return;
2434 }
2435
2436 if (!(hchan->flags & H_REQUIRE_TICKET))
2437 {
2438 helpmod_reply(sender, returntype, "Cannot list tickets: Channel %s does not use the ticket system", hchannel_get_name(hchan));
2439 return;
2440 }
2441
2442 htick = hchan->htickets;
2443
2444 if (htick == NULL)
2445 {
2446 helpmod_reply(sender, returntype, "Channel %s has no valid tickets", hchannel_get_name(hchan));
2447 return;
2448 }
2449
2450 helpmod_reply(sender, returntype, "Valid tickets for channel %s", hchannel_get_name(hchan));
2451
2452 for (i = 0;htick;htick = htick->next, i++)
2453 helpmod_reply(sender, returntype, "%4d %16s %48s", i, htick->authname, helpmod_strtime(time(NULL) - htick->time_expiration));
2454
2455 helpmod_reply(sender, returntype, "Done listing tickets. Channel %s had %d valid ticket%s", hchannel_get_name(hchan), i, (i==1)?"":"s");
2456 }
2457
2458 static void helpmod_cmd_showticket (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2459 {
2460 hchannel *hchan;
2461 huser *husr;
2462 hticket *htick;
2463 int i;
2464
2465 DEFINE_HCHANNEL;
2466
2467 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2468
2469 if (argc > H_CMD_MAX_ARGS)
2470 argc = H_CMD_MAX_ARGS;
2471
2472 if (hchan == NULL)
2473 {
2474 helpmod_reply(sender, returntype, "Cannot show the ticket: Channel not defined or not found");
2475 return;
2476 }
2477 for (i = 0;i < argc;i++)
2478 {
2479 husr = huser_get(getnickbynick(argv[i]));
2480 if (husr == NULL)
2481 {
2482 helpmod_reply(sender, returntype, "Cannot show the ticket: User %s not found", argv[i]);
2483 continue;
2484 }
2485 if (!IsAccount(husr->real_user))
2486 {
2487 helpmod_reply(sender, returntype, "Cannot show the ticket: User %s is not authed", argv[i]);
2488 continue;
2489 }
2490 htick = hticket_get(huser_get_auth(husr), hchan);
2491 if (htick == NULL)
2492 {
2493 helpmod_reply(sender, returntype, "Cannot show the ticket: User %s does not have a valid ticket for channel %s", argv[i], hchannel_get_name(hchan));
2494 continue;
2495 }
2496 helpmod_reply(sender, returntype, "User %s has a ticket for channel %s expiring in %s", argv[i], hchannel_get_name(hchan), helpmod_strtime(htick->time_expiration - time(NULL)));
2497 }
2498 }
2499
2500 static int helpmod_cmd_termstats_sort(const void *left, const void *right)
2501 {
2502 return (*((hterm**)right))->usage - (*((hterm**)left))->usage;
2503 }
2504
2505 static void helpmod_cmd_termstats(huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2506 {
2507 hterm **arr, *origin;
2508 hchannel *hchan;
2509 int i, count;
2510
2511 DEFINE_HCHANNEL;
2512
2513 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2514
2515 if (hchan == NULL)
2516 origin = hterms;
2517 else
2518 origin = hchan->channel_hterms;
2519
2520 count = hterm_count(origin);
2521
2522 if (count == 0)
2523 {
2524 helpmod_reply(sender, returntype, "Cannot list term usage statistics: No terms available");
2525 return;
2526 }
2527
2528 arr = malloc(sizeof(hterm*) * count);
2529 assert(arr != NULL);
2530
2531 for (i=0;i < count;i++,origin = origin->next)
2532 arr[i] = origin;
2533
2534 qsort(arr, count, sizeof(hterm*), helpmod_cmd_termstats_sort);
2535
2536 if (hchan == NULL)
2537 helpmod_reply(sender, returntype, "10 Most used global terms");
2538 else
2539 helpmod_reply(sender, returntype, "10 Most used terms for channel %s", hchannel_get_name(hchan));
2540
2541 for (i=0;i < 10 && i < count;i++)
2542 helpmod_reply(sender, returntype, "#%02d %32s :%d",i+1, arr[i]->name->content,arr[i]->usage);
2543
2544 free(arr);
2545 }
2546
2547 static int helpmod_cmd_checkchannel_nicksort(const void *left, const void *right)
2548 {
2549 return ci_strcmp(getnickbynumeric(*((unsigned long*)left))->nick, getnickbynumeric(*((unsigned long*)right))->nick);
2550 }
2551
2552 static int helpmod_cmd_checkchannel_statussort(const void *left, const void *right)
2553 {
2554 int level1 = 0, level2 = 0;
2555
2556 if (*((unsigned long*)left) & CUMODE_VOICE)
2557 level1 = 1;
2558 if (*((unsigned long*)left) & CUMODE_OP)
2559 level1 = 2;
2560
2561 if (*((unsigned long*)right) & CUMODE_VOICE)
2562 level2 = 1;
2563 if (*((unsigned long*)right) & CUMODE_OP)
2564 level2 = 2;
2565
2566 return level2 - level1;
2567 }
2568
2569 static void helpmod_cmd_checkchannel(huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2570 {
2571 channel *chan;
2572 nick *nck;
2573 int i, j, nick_count = 0, authed_count = 0, o_limit = 0, v_limit = 0, summary_only = 0;
2574 unsigned long *numeric_array;
2575
2576 if (argc == 0)
2577 {
2578 helpmod_reply(sender, returntype, "Cannot check channel: Channel not defined");
2579 return;
2580 }
2581
2582 chan = findchannel(argv[0]);
2583 if (chan == NULL)
2584 {
2585 helpmod_reply(sender, returntype, "Cannot check channel: Channel %s not found", argv[0]);
2586 return;
2587 }
2588 if (argc > 1 && !ci_strcmp(argv[1], "summary"))
2589 summary_only = 1;
2590
2591 /* first pass - verify validity and count nicks */
2592 for (i=0;i < chan->users->hashsize;i++)
2593 {
2594 nck = getnickbynumeric(chan->users->content[i]);
2595 if (!nck) /* it's a hash, not an array */
2596 continue;
2597
2598 nick_count++;
2599
2600 if (IsAccount(nck))
2601 authed_count++;
2602
2603 if (IsOper(nck) && strlen(nck->nick) > 1)
2604 {
2605 helpmod_reply(sender, returntype, "Cannot check channel: Permission denied. Channel %s has an oper on it", argv[0]);
2606 return;
2607 }
2608 }
2609
2610 numeric_array = (unsigned long*)malloc(nick_count * sizeof(unsigned long));
2611
2612 /* second pass - construct array */
2613 for (i=0,j=0;i < chan->users->hashsize;i++)
2614 {
2615 if (getnickbynumeric(chan->users->content[i]) == NULL) /* it's a hash, not an array */
2616 continue;
2617
2618 numeric_array[j++] = chan->users->content[i];
2619 }
2620
2621 qsort(numeric_array, nick_count, sizeof(unsigned long), helpmod_cmd_checkchannel_statussort);
2622
2623 /* third pass - find status boundaries */
2624 {
2625 for (;o_limit < nick_count && numeric_array[o_limit] & CUMODE_OP; o_limit++);
2626 v_limit = o_limit;
2627 for(v_limit = o_limit; (v_limit < nick_count) && numeric_array[v_limit] & CUMODE_VOICE; v_limit++);
2628 }
2629
2630 helpmod_reply(sender, returntype, "Information on channel %s", argv[0]);
2631 helpmod_reply(sender, returntype, "Channel created %s ago", helpmod_strtime(time(NULL) - chan->timestamp));
2632 if (!IsKey(chan) && !IsInviteOnly(chan))
2633 helpmod_reply(sender, returntype, "Channel topic: %s", chan->topic?chan->topic->content:"Not set");
2634 helpmod_reply(sender, returntype, "Channel modes: %s", printflags(chan->flags, cmodeflags));
2635
2636
2637 /* sort the sub arrays */
2638
2639 if (o_limit > 0)
2640 qsort(numeric_array, o_limit, sizeof(unsigned long), helpmod_cmd_checkchannel_nicksort);
2641 if (v_limit - o_limit > 0)
2642 qsort(numeric_array + o_limit, v_limit - o_limit, sizeof(unsigned long), helpmod_cmd_checkchannel_nicksort);
2643 if (nick_count - v_limit > 0)
2644 qsort(numeric_array + v_limit, nick_count - v_limit, sizeof(unsigned long), helpmod_cmd_checkchannel_nicksort);
2645
2646 /* fourth pass - print results */
2647 if (!summary_only)
2648 for (i=0;i < nick_count;i++)
2649 {
2650 char buf[256], status;
2651
2652 if (numeric_array[i] & CUMODE_OP)
2653 status = '@';
2654 else if (numeric_array[i] & CUMODE_VOICE)
2655 status = '+';
2656 else
2657 status = ' ';
2658
2659 visiblehostmask(getnickbynumeric(numeric_array[i]), buf);
2660 if (IsAccount(getnickbynumeric(numeric_array[i])))
2661 helpmod_reply(sender, returntype, "%c%s (%s)", status, buf, getnickbynumeric(numeric_array[i])->authname);
2662 else
2663 helpmod_reply(sender, returntype, "%c%s", status, buf);
2664 }
2665
2666 helpmod_reply(sender, returntype, "Users: %d Clones: %d Opped: %d Voiced: %d Authed: %3.0f%%", nick_count, nick_count - countuniquehosts(chan), o_limit, v_limit - o_limit, ((float)authed_count / (float)nick_count) * 100.0);
2667
2668 free(numeric_array);
2669 }
2670
2671 static void helpmod_cmd_statsdump (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2672 {
2673 haccount *hacc = haccounts;
2674 hstat_account *ptr;
2675 int i;
2676
2677 helpmod_reply(sender, returntype, "Account statistics");
2678 for (;hacc;hacc = hacc->next)
2679 for (ptr = hacc->stats;ptr;ptr = ptr->next)
2680 {
2681 helpmod_reply(sender, returntype, "Account %s channel %s short-term", hacc->name->content, hchannel_get_name(ptr->hchan));
2682 for (i = 0;i < 7;i++)
2683 helpmod_reply(sender, returntype, "%d %d %d %d", ptr->week[i].time_spent, ptr->week[i].prime_time_spent, ptr->week[i].lines, ptr->week[i].words);
2684 helpmod_reply(sender, returntype, "Account %s channel %s long-term", hacc->name->content, hchannel_get_name(ptr->hchan));
2685 for (i = 0;i < 10;i++)
2686 helpmod_reply(sender, returntype, "%d %d %d %d", ptr->longterm[i].time_spent, ptr->longterm[i].prime_time_spent, ptr->longterm[i].lines, ptr->longterm[i].words);
2687 }
2688 }
2689
2690 static void helpmod_cmd_statsrepair (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2691 {
2692 haccount *hacc = haccounts;
2693 hstat_account *ptr;
2694 int i;
2695
2696 helpmod_reply(sender, returntype, "Repairing account statistics");
2697 for (;hacc;hacc = hacc->next)
2698 for (ptr = hacc->stats;ptr;ptr = ptr->next)
2699 {
2700 for (i = 0;i < 7;i++)
2701 {
2702 if (ptr->week[i].time_spent > HDEF_d)
2703 {
2704 ptr->week[i].time_spent = 0;
2705 helpmod_reply(sender, returntype, "repaired short term TimeSpent %s @ %s : Greater than one day",hacc->name->content, hchannel_get_name(ptr->hchan));
2706 }
2707 if (ptr->week[i].time_spent < 0)
2708 {
2709 ptr->week[i].time_spent = 0;
2710 helpmod_reply(sender, returntype, "repaired short term TimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2711 }
2712
2713 if (ptr->week[i].prime_time_spent > HDEF_d)
2714 {
2715 ptr->week[i].prime_time_spent = 0;
2716 helpmod_reply(sender, returntype, "repaired short term PrimeTimeSpent %s @ %s : Greater than one day",hacc->name->content, hchannel_get_name(ptr->hchan));
2717 }
2718 if (ptr->week[i].prime_time_spent < 0)
2719 {
2720 ptr->week[i].prime_time_spent = 0;
2721 helpmod_reply(sender, returntype, "repaired short term PrimeTimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2722 }
2723
2724 if (ptr->week[i].lines > 10000)
2725 {
2726 ptr->week[i].lines = 0;
2727 helpmod_reply(sender, returntype, "repaired short term Lines %s @ %s : Greater than 10000",hacc->name->content, hchannel_get_name(ptr->hchan));
2728 }
2729 if (ptr->week[i].lines < 0)
2730 {
2731 ptr->week[i].lines = 0;
2732 helpmod_reply(sender, returntype, "repaired short term Lines %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2733 }
2734
2735 if (ptr->week[i].words > 50000)
2736 {
2737 ptr->week[i].words = 0;
2738 helpmod_reply(sender, returntype, "repaired short term Words %s @ %s : Greater than 50000",hacc->name->content, hchannel_get_name(ptr->hchan));
2739 }
2740 if (ptr->week[i].words < 0)
2741 {
2742 ptr->week[i].words = 0;
2743 helpmod_reply(sender, returntype, "repaired short term Words %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2744 }
2745 }
2746 for (i = 0;i < 10;i++)
2747 {
2748 if (ptr->longterm[i].time_spent > HDEF_w)
2749 {
2750 ptr->longterm[i].time_spent = 0;
2751 helpmod_reply(sender, returntype, "repaired long term TimeSpent %s @ %s : Greater than one week",hacc->name->content, hchannel_get_name(ptr->hchan));
2752 }
2753 if (ptr->longterm[i].time_spent < 0)
2754 {
2755 ptr->longterm[i].time_spent = 0;
2756 helpmod_reply(sender, returntype, "repaired long term TimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2757 }
2758
2759 if (ptr->longterm[i].prime_time_spent > HDEF_w)
2760 {
2761 ptr->longterm[i].prime_time_spent = 0;
2762 helpmod_reply(sender, returntype, "repaired long term PrimeTimeSpent %s @ %s : Greater than one week",hacc->name->content, hchannel_get_name(ptr->hchan));
2763 }
2764 if (ptr->longterm[i].prime_time_spent < 0)
2765 {
2766 ptr->longterm[i].prime_time_spent = 0;
2767 helpmod_reply(sender, returntype, "repaired long term PrimeTimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2768 }
2769
2770 if (ptr->longterm[i].lines > 50000)
2771 {
2772 ptr->longterm[i].lines = 0;
2773 helpmod_reply(sender, returntype, "repaired long term Lines %s @ %s : Greater than 50000",hacc->name->content, hchannel_get_name(ptr->hchan));
2774 }
2775 if (ptr->longterm[i].lines < 0)
2776 {
2777 ptr->longterm[i].lines = 0;
2778 helpmod_reply(sender, returntype, "repaired long term Lines %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2779 }
2780
2781 if (ptr->longterm[i].words > 50000)
2782 {
2783 ptr->longterm[i].words = 0;
2784 helpmod_reply(sender, returntype, "repaired long term Words %s @ %s : Greater than 50000",hacc->name->content, hchannel_get_name(ptr->hchan));
2785 }
2786 if (ptr->longterm[i].words < 0)
2787 {
2788 ptr->longterm[i].words = 0;
2789 helpmod_reply(sender, returntype, "repaired long term Words %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2790 }
2791 }
2792 }
2793 helpmod_reply(sender, returntype, "Account statistics repaired");
2794
2795 }
2796
2797 static void helpmod_cmd_statsreset (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2798 {
2799 haccount *hacc = haccounts;
2800 hstat_account *ptr;
2801 hchannel *hchan;
2802 int i, short_del, long_del;
2803
2804 if (argc < 2)
2805 {
2806 helpmod_reply(sender, returntype, "Insufficient parameters");
2807 return;
2808 }
2809
2810 if (sscanf(argv[0], "%d", &short_del) == 0)
2811 {
2812 helpmod_reply(sender, returntype, "Invalid parameter");
2813 return;
2814 }
2815 if (sscanf(argv[1], "%d", &long_del) == 0)
2816 {
2817 helpmod_reply(sender, returntype, "Invalid parameter");
2818 return;
2819 }
2820
2821 for (;hacc;hacc = hacc->next)
2822 for (ptr = hacc->stats;ptr;ptr = ptr->next)
2823 {
2824 for (i = 1;i < short_del + 1;i++)
2825 HSTAT_ACCOUNT_ZERO(ptr->week[(hstat_day() + i) % 7]);
2826 for (i = 1;i < long_del + 1;i++)
2827 HSTAT_ACCOUNT_ZERO(ptr->longterm[(hstat_week() + i) % 10]);
2828 }
2829
2830 for (hchan = hchannels;hchan;hchan = hchan->next)
2831 {
2832 for (i = 1;i < short_del + 1;i++)
2833 HSTAT_CHANNEL_ZERO(hchan->stats->week[(hstat_day() + i) % 7]);
2834 for (i = 1;i < long_del + 1;i++)
2835 HSTAT_CHANNEL_ZERO(hchan->stats->longterm[(hstat_week() + i) % 10]);
2836
2837 }
2838
2839 helpmod_reply(sender, returntype, "Statistics reset complete");
2840 }
2841
2842 static void helpmod_cmd_message (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2843 {
2844 hchannel *hchan;
2845
2846 if (argc < 2)
2847 {
2848 helpmod_reply(sender, returntype, "Cannot send a message: Insufficient arguments");
2849 return;
2850 }
2851 hchan = hchannel_get_by_name(argv[0]);
2852 if (hchan == NULL)
2853 {
2854 helpmod_reply(sender, returntype, "Cannot send a message: Invalid channel %s", argv[0]);
2855 return;
2856 }
2857 SKIP_WORD;
2858 helpmod_message_channel(hchan, "(%s) %s", huser_get_nick(sender), ostr);
2859 helpmod_reply(sender, returntype, "Message sent to %s", hchannel_get_name(hchan));
2860 }
2861
2862 static void helpmod_cmd_version (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2863 {
2864 helpmod_reply(sender, returntype, "HelpMod version " HELPMOD_VERSION " by strutsi (strutsi@quakenet.org)");
2865 }
2866
2867 static void helpmod_cmd_ticketmsg (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2868 {
2869 hchannel *hchan;
2870
2871 DEFINE_HCHANNEL;
2872
2873 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2874
2875 if (hchan == NULL)
2876 {
2877 helpmod_reply(sender, returntype, "Can not view or set ticket message: No channel is specified.");
2878 return;
2879 }
2880
2881 if (argc == 0)
2882 { /* view */
2883 if (hchan->ticket_message == NULL)
2884 helpmod_reply(sender, returntype, "No ticket message is set for channel %s", hchannel_get_name(hchan));
2885 else
2886 helpmod_reply(sender, returntype, "Ticket message for channel %s is: %s", hchannel_get_name(hchan), hchan->ticket_message->content);
2887 return;
2888 }
2889
2890 /* set */
2891 if (hchan->ticket_message != NULL)
2892 freesstring(hchan->ticket_message);
2893
2894 hchan->ticket_message = getsstring(ostr, strlen(ostr));
2895 helpmod_reply(sender, returntype, "Ticket message for channel %s set to: %s", hchannel_get_name(hchan), hchan->ticket_message->content);
2896 }
2897
2898 static void helpmod_cmd_lcedit (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2899 {
2900 hlc_profile *profile;
2901
2902 if (argc == 0)
2903 {
2904 helpmod_reply(sender, returntype, "Can not handle lamer control profiles: Operation not defined");
2905 return;
2906 }
2907
2908 if (!ci_strcmp(argv[0], "list"))
2909 {
2910 if (hlc_profiles == NULL)
2911 {
2912 helpmod_reply(sender, returntype, "Can not list lamer control profiles: No profiles");
2913 return;
2914 }
2915 helpmod_reply(sender, returntype, "Following lamer control profiles are currently available:");
2916 for (profile = hlc_profiles;profile != NULL;profile = profile->next)
2917 helpmod_reply(sender, returntype, "%s", profile->name->content);
2918 }
2919 else if (!ci_strcmp(argv[0], "add"))
2920 {
2921 if (argc < 2)
2922 {
2923 helpmod_reply(sender, returntype, "Can not add a lamer control profile: Profile name not defined");
2924 return;
2925 }
2926
2927 profile = hlc_get(argv[1]);
2928
2929 if (profile != NULL)
2930 {
2931 helpmod_reply(sender, returntype, "Can not add a lamer control profile: Profile named %s already exists", argv[1]);
2932 return;
2933 }
2934 profile = hlc_add(argv[1]);
2935
2936 { /* set the default values */
2937 profile->caps_max_percentage = 40;
2938 profile->caps_min_count = 20;
2939
2940 profile->repeats_max_count = 3;
2941 profile->repeats_min_length = 7;
2942
2943 profile->symbol_repeat_max_count = 6;
2944 profile->character_repeat_max_count = 7;
2945 profile->symbol_max_count = 9;
2946
2947 profile->tolerance_flood = 5;
2948
2949 profile->tolerance_spam = 0.008;
2950 profile->constant_spam = 10;
2951
2952 profile->tolerance_warn = 1;
2953 profile->tolerance_kick = 3;
2954 profile->tolerance_remove = 5;
2955 }
2956
2957 helpmod_reply(sender, returntype, "Lamer control profile %s added", argv[1]);
2958 }
2959 else if (!ci_strcmp(argv[0], "del"))
2960 {
2961 hchannel *hchan;
2962 if (argc < 2)
2963 {
2964 helpmod_reply(sender, returntype, "Can not delete a lamer control profile: Profile name not defined");
2965 return;
2966 }
2967
2968 profile = hlc_get(argv[1]);
2969
2970 if (profile == NULL)
2971 {
2972 helpmod_reply(sender, returntype, "Can not delete a lamer control profile: Profile named %s does not exist", argv[1]);
2973 return;
2974 }
2975 for (hchan = hchannels;hchan != NULL;hchan = hchan->next)
2976 if (hchan->lc_profile == profile)
2977 {
2978 helpmod_reply(sender, returntype, "Can not delete a lamer control profile: Profile %s is in use", argv[1]);
2979 return;
2980 }
2981 hlc_del(profile);
2982 helpmod_reply(sender, returntype, "Lamer control profile %s deleted", argv[1]);
2983 }
2984 else if (!ci_strcmp(argv[0], "view"))
2985 {
2986 if (argc < 2)
2987 {
2988 helpmod_reply(sender, returntype, "Can not view a lamer control profile: Profile name not defined");
2989 return;
2990 }
2991
2992 profile = hlc_get(argv[1]);
2993
2994 if (profile == NULL)
2995 {
2996 helpmod_reply(sender, returntype, "Can not view a lamer control profile: Profile named %s not found", argv[1]);
2997 return;
2998 }
2999
3000 helpmod_reply(sender, returntype, "Lamer control profile %s:", profile->name->content);
3001 helpmod_reply(sender, returntype, "Maximum caps percentage: %d", profile->caps_max_percentage);
3002 helpmod_reply(sender, returntype, "Caps minimum count: %d", profile->caps_min_count);
3003 helpmod_reply(sender, returntype, "Repeat tolerance: %d", profile->repeats_max_count);
3004 helpmod_reply(sender, returntype, "Repeat minimum length: %d", profile->repeats_min_length);
3005 helpmod_reply(sender, returntype, "Symbol repeat tolerance: %d", profile->symbol_repeat_max_count);
3006 helpmod_reply(sender, returntype, "Character repeat tolerance: %d", profile->character_repeat_max_count);
3007 helpmod_reply(sender, returntype, "Continous symbol tolerance: %d", profile->symbol_max_count);
3008 helpmod_reply(sender, returntype, "Flood tolerance: %d", profile->tolerance_flood);
3009 helpmod_reply(sender, returntype, "Spam tolerance: %d", profile->tolerance_spam);
3010 helpmod_reply(sender, returntype, "Spam multiplier: %f", profile->constant_spam);
3011 helpmod_reply(sender, returntype, "Warning limit: %d", profile->tolerance_warn);
3012 helpmod_reply(sender, returntype, "Kick limit: %d", profile->tolerance_kick);
3013 helpmod_reply(sender, returntype, "Ban limit: %d", profile->tolerance_remove);
3014 }
3015 else if (!ci_strcmp(argv[0], "edit"))
3016 {
3017 int int_val = -1;
3018 double dbl_val = -1;
3019
3020 if (argc != 4)
3021 {
3022 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: Syntax error");
3023 return;
3024 }
3025
3026 profile = hlc_get(argv[1]);
3027
3028 if (profile == NULL)
3029 {
3030 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: Profile %s not found", argv[1]);
3031 return;
3032 }
3033
3034 sscanf(argv[3], "%d", &int_val);
3035 sscanf(argv[3], "%lf", &dbl_val);
3036
3037 if (dbl_val < 0)
3038 { /* All int values are also valid double values */
3039 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: Invalid argument");
3040 return;
3041 }
3042
3043 if (!ci_strcmp(argv[2], "caps_percentage"))
3044 profile->caps_max_percentage = int_val;
3045 else if (!ci_strcmp(argv[2], "caps_count"))
3046 profile->caps_min_count = int_val;
3047 else if (!ci_strcmp(argv[2], "repeat_tolerance"))
3048 profile->repeats_max_count = int_val;
3049 else if (!ci_strcmp(argv[2], "repeat_length"))
3050 profile->repeats_min_length = int_val;
3051 else if (!ci_strcmp(argv[2], "symbol_repeat"))
3052 profile->symbol_repeat_max_count = int_val;
3053 else if (!ci_strcmp(argv[2], "character_repeat"))
3054 profile->character_repeat_max_count = int_val;
3055 else if (!ci_strcmp(argv[2], "continuous_symbol"))
3056 profile->symbol_max_count = int_val;
3057 else if (!ci_strcmp(argv[2], "flood_tolerance"))
3058 profile->tolerance_flood = int_val;
3059 else if (!ci_strcmp(argv[2], "spam_tolerance"))
3060 profile->tolerance_spam = int_val;
3061 else if (!ci_strcmp(argv[2], "spam_multiplier"))
3062 profile->constant_spam = dbl_val;
3063 else if (!ci_strcmp(argv[2], "warn_limit"))
3064 profile->tolerance_warn = int_val;
3065 else if (!ci_strcmp(argv[2], "kick_limit"))
3066 profile->tolerance_kick = int_val;
3067 else if (!ci_strcmp(argv[2], "ban_limit"))
3068 profile->tolerance_remove = int_val;
3069 else
3070 {
3071 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: No component named %s", argv[2]);
3072 return;
3073 }
3074 helpmod_reply(sender, returntype, "Lamer control profile component value changed succesfully.");
3075 }
3076 }
3077
3078 static void helpmod_cmd_ged (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3079 {
3080 helpmod_editor *editor;
3081
3082 if (sender->editor == NULL)
3083 { /* Start a new editor */
3084 if (argc == 0)
3085 {
3086 helpmod_reply(sender, returntype, "Can not use ged: Filename not specified");
3087 return;
3088 }
3089 editor = hed_open(sender, argv[0]);
3090 if (editor == NULL)
3091 {
3092 helpmod_reply(sender, returntype, "Can not use ged: Invalid filename %s", argv[0]);
3093 return;
3094 }
3095 if (editor->user != sender)
3096 {
3097 helpmod_reply(sender, returntype, "Can not use ged: File %s is currently being edited by %s", editor->filename, huser_get_nick(editor->user));
3098 return;
3099 }
3100 editor->user = sender;
3101 sender->editor = editor;
3102
3103 helpmod_reply(sender, returntype, "Ged: %d", hed_byte_count(editor));
3104 }
3105 else
3106 {
3107 hed_command(sender, returntype, ostr, argc, argv);
3108 }
3109 }
3110
3111 static void helpmod_cmd_text (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3112 {
3113 hchannel *hchan;
3114 DEFINE_HCHANNEL;
3115 FILE *in;
3116 /*
3117 if (argc == 0)
3118 {
3119 helpmod_reply(sender, returntype, "Can not handle text: No command specified");
3120 return;
3121 }
3122 */
3123 if (argc == 0 || !ci_strcmp(argv[0], "list"))
3124 {
3125 DIR *dir;
3126 struct dirent *dent;
3127 char buffer[384];
3128 int nwritten, bufpos = 0;
3129
3130 dir = opendir(HELPMOD_TEXT_DIR);
3131 assert(dir != NULL);
3132
3133 helpmod_reply(sender, returntype, "Following texts are available:");
3134
3135 for (dent = readdir(dir);dent != NULL;dent = readdir(dir))
3136 {
3137 /* Skip stuff like . and .. */
3138 if (!strncmp(dent->d_name, ".", 1))
3139 continue;
3140
3141 if (bufpos)
3142 {
3143 buffer[bufpos] = ' ';
3144 bufpos++;
3145 }
3146 sprintf(buffer + bufpos, "%s%n", dent->d_name, &nwritten);
3147 bufpos+=nwritten;
3148
3149 if (bufpos > 256)
3150 {
3151 helpmod_reply(sender, returntype, buffer);
3152 bufpos = 0;
3153 }
3154 }
3155 if (bufpos)
3156 helpmod_reply(sender, returntype, buffer);
3157 return;
3158 }
3159 else if (!ci_strcmp(argv[0], "show"))
3160 {
3161 char fname_buffer[128], buffer[512];
3162 if (argc < 2)
3163 {
3164 helpmod_reply(sender, returntype, "Can not show text: Text not specified");
3165 return;
3166 }
3167 if (!hed_is_valid_filename(argv[1]))
3168 {
3169 helpmod_reply(sender, returntype, "Can not show text: Invalid filename");
3170 return;
3171 }
3172 sprintf(fname_buffer, HELPMOD_TEXT_DIR"/%s" ,argv[1]);
3173 in = fopen(fname_buffer, "rwt");
3174 if (in == NULL)
3175 {
3176 helpmod_reply(sender, returntype, "Can not show text: Text %s not found", argv[1]);
3177 return;
3178 }
3179 while (!feof(in))
3180 {
3181 if (!fgets(buffer, 512, in))
3182 break;
3183 if (returntype != NULL && huser_get_level(sender) > H_PEON)
3184 helpmod_message_channel(hchannel_get_by_channel(returntype), "%s", buffer);
3185 else
3186 helpmod_reply(sender, returntype, "%s", buffer);
3187 }
3188 fclose (in);
3189 return;
3190 }
3191
3192 if (huser_get_level(sender) < H_STAFF)
3193 {
3194 helpmod_reply(sender, returntype, "Can not handle text: Insufficient user level");
3195 return;
3196 }
3197
3198 if (!ci_strcmp(argv[0], "add"))
3199 {
3200 char fname_buffer[128];
3201 if (argc < 2)
3202 {
3203 helpmod_reply(sender, returntype, "Can not add text: Text not specified");
3204 return;
3205 }
3206 if (!hed_is_valid_filename(argv[1]))
3207 {
3208 helpmod_reply(sender, returntype, "Can not add text: Invalid filename");
3209 return;
3210 }
3211 sprintf(fname_buffer, HELPMOD_TEXT_DIR"/%s" ,argv[1]);
3212 if ((in = fopen(fname_buffer, "rt")) != NULL)
3213 {
3214 helpmod_reply(sender, returntype, "Can not add text: Text %s already exists", argv[1]);
3215 return;
3216 }
3217 else
3218 {
3219 if ((in = fopen(fname_buffer, "wt")) == NULL)
3220 {
3221 helpmod_reply(sender, returntype, "Can not add text: Unexpected error, please contact strutsi");
3222 return;
3223 }
3224 fclose(in);
3225 }
3226 helpmod_reply(sender, returntype, "Text %s added succesfully", argv[1]);
3227 }
3228 else if (!ci_strcmp(argv[0], "del"))
3229 {
3230 char fname_buffer[128];
3231 if (argc < 2)
3232 {
3233 helpmod_reply(sender, returntype, "Can not delete text: Text not specified");
3234 return;
3235 }
3236 if (!hed_is_valid_filename(argv[1]))
3237 {
3238 helpmod_reply(sender, returntype, "Can not delete text: Invalid filename");
3239 return;
3240 }
3241 sprintf(fname_buffer, HELPMOD_TEXT_DIR"/%s" ,argv[1]);
3242
3243 if (!remove(fname_buffer))
3244 helpmod_reply(sender, returntype, "Text %s removed", argv[1]);
3245 else
3246 helpmod_reply(sender, returntype, "Can not delete text: Text %s does not exist or can not be deleted", argv[1]);
3247 }
3248 else
3249 {
3250 helpmod_reply(sender, returntype, "Can not handle text: Unknown operation %s", argv[0]);
3251 return;
3252 }
3253 }
3254
3255 static void helpmod_cmd_evilhack1 (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3256 {
3257 int tmp;
3258
3259 if (argc == 0)
3260 helpmod_reply(sender, returntype, "hstat_cycle: %d", hstat_cycle);
3261 else
3262 {
3263 if (!sscanf(argv[0], "%d", &tmp) || tmp < 0)
3264 {
3265 helpmod_reply(sender, returntype, "Invalid argument");
3266 return;
3267 }
3268 hstat_cycle = tmp;
3269 helpmod_reply(sender, returntype, "hstat_cycle is now: %d", hstat_cycle);
3270 }
3271 }
3272
3273 static void helpmod_cmd_evilhack2 (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3274 {
3275 haccount *hacc = haccounts;
3276 hchannel *hchan;
3277 hstat_account *ptr;
3278 hstat_account_entry tmp_account;
3279 hstat_channel_entry tmp_channel;
3280 int first, second;
3281
3282 if (argc != 2)
3283 {
3284 helpmod_reply(sender, returntype, "Syntax error: evilhack2 <first> <second>");
3285 return;
3286 }
3287
3288 if (!sscanf(argv[0],"%d", &first) || first < 0 || first > 9)
3289 {
3290 helpmod_reply(sender, returntype, "Syntax error: Invalid first");
3291 return;
3292 }
3293
3294 if (!sscanf(argv[1],"%d", &second) || second < 0 || second > 9)
3295 {
3296 helpmod_reply(sender, returntype, "Syntax error: Invalid second");
3297 return;
3298 }
3299
3300 for (;hacc;hacc = hacc->next)
3301 for (ptr = hacc->stats;ptr;ptr = ptr->next)
3302 {
3303 tmp_account = ptr->longterm[first];
3304 ptr->longterm[first] = ptr->longterm[second];
3305 ptr->longterm[second] = tmp_account;
3306 }
3307
3308 for (hchan = hchannels;hchan;hchan = hchan->next)
3309 {
3310 tmp_channel = hchan->stats->longterm[first];
3311 hchan->stats->longterm[first] = hchan->stats->longterm[second];
3312 hchan->stats->longterm[second] = tmp_channel;
3313 }
3314
3315 helpmod_reply(sender, returntype, "Evilhack2 done: Swapped %d and %d", first, second);
3316 }
3317
3318 /* old H stuff */
3319 void helpmod_cmd_load (huser *sender, channel *returntype, char* arg, int argc, char *argv[])
3320 {
3321 FILE *tmp_file;
3322 char buf[128] = "helpmod/default";
3323
3324 if (!arg)
3325 helpmod_reply(sender, returntype, "Warning: No config specified, using default");
3326 else
3327 {
3328 if (strlen(arg) >= 100)
3329 return;
3330 else
3331 sprintf(buf, "helpmod/%s", arg);
3332 }
3333
3334 if (!(tmp_file = fopen(buf, "rt")))
3335 {
3336 helpmod_reply(sender, returntype, "File %s not found", buf);
3337 return;
3338 }
3339 else
3340 fclose(tmp_file);
3341
3342 helpmod_clear_aliases(&aliases);
3343 helpmod_clear_all_entries();
3344 helpmod_init_entry(&helpmod_base);
3345 huser_reset_states();
3346 helpmod_load_entries(buf);
3347 strcpy(helpmod_db, buf);
3348 helpmod_reply(sender, returntype, "New config loaded and system reset");
3349 }
3350
3351 void helpmod_cmd_status (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3352 {
3353 helpmod_reply(sender, returntype, "HelpMod version %s (built %s, up %s)", HELPMOD_VERSION, __DATE__, helpmod_strtime(time(NULL) - helpmod_startup_time));
3354 helpmod_reply(sender, returntype, "Channels %d", hchannel_count());
3355 helpmod_reply(sender, returntype, "Accounts %d", haccount_count(H_ANY));
3356 helpmod_reply(sender, returntype, "Users %d", huser_count());
3357 helpmod_reply(sender, returntype, "Help entries %d", helpmod_entry_count(helpmod_base));
3358 helpmod_reply(sender, returntype, "Bans %d", hban_count());
3359 helpmod_reply(sender, returntype, "Help provided %d", helpmod_usage);
3360 helpmod_reply(sender, returntype, "Tickets %d", hticket_count());
3361 }
3362
3363 /* not really a command, but help wants this one */
3364 void helpmod_send_help(huser* target)
3365 {
3366 int i;
3367 helpmod_usage++;
3368 for (i=0;i<target->state->text_lines;i++)
3369 helpmod_reply(target, NULL, "%s", target->state->text[i]->content);
3370 for (i=0;i<target->state->option_count;i++)
3371 helpmod_reply(target, NULL, "%d) %s", i+1, target->state->options[i]->description->content);
3372 if (!target->state->option_count)
3373 {
3374 helpmod_reply(target, NULL, "This concludes the help for this topic, if you want to, you can restart the service with the 'help' command, or return to the previous entry by selecting 0");
3375 }
3376 }
3377
3378 void helpmod_cmd_command(huser* sender, channel* returntype, char* arg, int argc, char *argv[])
3379 {
3380 hcommand *hcom;
3381 char buffer[512], *ptr = argv[0];
3382 FILE *in;
3383
3384 if (argc == 0)
3385 {
3386 helpmod_reply(sender, returntype, "Usage: command [name of the command] for a list see 'showcommands'");
3387 return;
3388 }
3389
3390 hcom = hcommand_get(argv[0], huser_get_level(sender));
3391
3392 if (hcom == NULL)
3393 {
3394 helpmod_reply(sender, returntype, "Unknown command '%s'", argv[0]);
3395 return;
3396 }
3397
3398 /* tolower */
3399 while (*(ptr++))
3400 *ptr = tolower(*ptr);
3401
3402 /* ? is handled like this because windows is shit */
3403 if (!ci_strcmp(argv[0], "?"))
3404 sprintf(buffer, "./helpmod2/commands/questionmark");
3405 else
3406 sprintf(buffer, "./helpmod2/commands/%s", argv[0]);
3407
3408 if ((in = fopen(buffer, "rt")) == NULL)
3409 {
3410 helpmod_reply(sender, returntype, "No help available for command '%s' (Ask strutsi to write it)", argv[0]);
3411 return;
3412 }
3413
3414 while (!feof(in))
3415 {
3416 fgets(buffer, 512, in);
3417 if (feof(in))
3418 break;
3419 helpmod_reply(sender, returntype, "%s", buffer);
3420 }
3421
3422 fclose(in);
3423 }
3424
3425 void helpmod_cmd_help (huser* sender, channel* returntype, char* arg, int argc, char *argv[])
3426 {
3427 int hlp_target;
3428
3429 if (helpmod_base == NULL || !helpmod_base->option_count)
3430 {
3431 helpmod_reply(sender, returntype, "The help service is not available at this time, please try again later");
3432 return;
3433 }
3434
3435 if (!argc)
3436 {
3437 sender->state = helpmod_base;
3438 helpmod_send_help(sender);
3439 return;
3440 }
3441 else
3442 if (!sscanf(arg, "%d", &hlp_target))
3443 {
3444 helpmod_entry tmp;
3445
3446 tmp = helpmod_get_alias(arg);
3447 if (!tmp)
3448 helpmod_reply(sender, returntype, "Invalid value. Either use 'help' to restart or give an integer as a valid selection");
3449 else
3450 {
3451 sender->state = tmp;
3452 helpmod_send_help(sender);
3453 }
3454 return;
3455 }
3456
3457 hlp_target--;
3458 if (!helpmod_valid_selection(sender->state, hlp_target))
3459 {
3460 if (!sender->state->option_count)
3461 helpmod_reply(sender, returntype, "There are no more options to choose from, you can restart the service by giving the 'help' command or select 0 to return to the previous entry");
3462 else if (!sender->state->parent)
3463 helpmod_reply(sender, returntype, "Bad selection, please enter your selection as an integer from %d to %d", 1, sender->state->option_count);
3464 else
3465 helpmod_reply(sender, returntype, "Bad selection, please enter your selection as an integer from %d to %d, selecting 0 will take you to the previous entry", 1, sender->state->option_count);
3466 return;
3467 }
3468
3469 sender->state = helpmod_make_selection(sender->state, hlp_target);
3470 helpmod_send_help(sender);
3471
3472 return;
3473 }
3474 /* adds all of the abowe to the system */
3475 void hcommands_add(void)
3476 {
3477 hcommand_add("help", H_PEON, helpmod_cmd_help,"Offers the H1 type help");
3478 hcommand_add("status",H_OPER, helpmod_cmd_status,"Gives service status");
3479 hcommand_add("load", H_OPER, helpmod_cmd_load,"Loads a new help database");
3480 hcommand_add("aliases",H_STAFF, helpmod_cmd_aliases,"Lists all aliases currently in use");
3481 hcommand_add("showcommands", H_LAMER, helpmod_cmd_showcommands,"Lists all commands available to you");
3482
3483 hcommand_add("improper", H_STAFF, helpmod_cmd_improper, "Sets the userlevel of the target to banned (lvl 0). Long term ban.");
3484 hcommand_add("peon", H_STAFF, helpmod_cmd_peon, "Sets the userlevel of the target to peon (lvl 1)");
3485 hcommand_add("trial", H_OPER, helpmod_cmd_trial, "Sets the userlevel of the target to trial staff (lvl 2)");
3486 hcommand_add("staff", H_OPER, helpmod_cmd_staff, "Sets the userlevel of the target to staff (lvl 3)");
3487 hcommand_add("oper", H_OPER, helpmod_cmd_oper, "Sets the userlevel of the target to oper (lvl 4)");
3488 hcommand_add("admin", H_ADMIN, helpmod_cmd_admin, "Sets the userlevel of the target to admin (lvl 5)");
3489 hcommand_add("deluser", H_OPER, helpmod_cmd_deluser, "Removes an account from " HELPMOD_NICK);
3490 hcommand_add("listuser", H_STAFF, helpmod_cmd_listuser, "Lists user accounts of " HELPMOD_NICK);
3491
3492 hcommand_add("chanconf", H_STAFF, helpmod_cmd_chanconf, "Channel configuration");
3493 hcommand_add("acconf", H_TRIAL, helpmod_cmd_acconf, "Personalise " HELPMOD_NICK " behaviour");
3494 hcommand_add("welcome", H_STAFF, helpmod_cmd_welcome, "Views or changes the channel welcome message");
3495 hcommand_add("censor", H_STAFF, helpmod_cmd_censor, "Handles the censored patterns for a channel");
3496
3497 hcommand_add("queue", H_TRIAL, helpmod_cmd_queue, "Handles the channel queue");
3498 hcommand_add("next", H_TRIAL, helpmod_cmd_next, "Same as queue next");
3499 hcommand_add("done", H_TRIAL, helpmod_cmd_done, "Same as queue done");
3500 hcommand_add("enqueue", H_TRIAL, helpmod_cmd_enqueue, "Same as queue on or chanconf +3");
3501 hcommand_add("dequeue", H_TRIAL, helpmod_cmd_dequeue, "Same as queue off or chanconf -3");
3502 hcommand_add("autoqueue", H_TRIAL, helpmod_cmd_autoqueue, "Same as queue maintain");
3503
3504 hcommand_add("?", H_PEON, helpmod_cmd_term_find, "Same as term find with multiple targets");
3505 hcommand_add("?+", H_TRIAL, helpmod_cmd_term_find_plus, "Multitarget term find which advances the queue");
3506 hcommand_add("?-", H_TRIAL, helpmod_cmd_term_find_minus, "Multitarget term find which removes users from queue");
3507 hcommand_add("term", H_STAFF, helpmod_cmd_term, "Term handling");
3508
3509 hcommand_add("klingon", H_OPER, helpmod_cmd_klingon, "Phrases in klingon, both targeted and general");
3510 hcommand_add("out", H_STAFF, helpmod_cmd_out, "Sets the userlevel of the target to banned (lvl 0) for a short while");
3511 hcommand_add("kick", H_TRIAL, helpmod_cmd_kick, "Kicks user(s) from a channel");
3512 hcommand_add("ban", H_STAFF, helpmod_cmd_ban, "Handles global bans");
3513 hcommand_add("chanban", H_TRIAL, helpmod_cmd_chanban, "Handles channel bans");
3514 hcommand_add("dnmo", H_STAFF, helpmod_cmd_dnmo, "DoNotMessageOpers informs the luser of his mistake and sets him to the bottom of the queue");
3515 hcommand_add("lamercontrol", H_OPER, helpmod_cmd_lamercontrol, "Views or changes the channel lamercontrol profile");
3516 hcommand_add("topic", H_STAFF, helpmod_cmd_topic, "Handles the topic of a channel");
3517 hcommand_add("idlekick", H_OPER, helpmod_cmd_idlekick, "Views or sets the idle kick time");
3518 hcommand_add("everyoneout", H_STAFF, helpmod_cmd_everyoneout, "Removes all normal users from a channel and enforces +i");
3519
3520 hcommand_add("stats", H_STAFF, helpmod_cmd_stats, "Shows staff activity statistics");
3521 hcommand_add("chanstats", H_STAFF, helpmod_cmd_chanstats, "Shows channel activity statistics");
3522 hcommand_add("activestaff", H_ADMIN, helpmod_cmd_activestaff, "Shows active staff members for a channel");
3523 hcommand_add("top10", H_STAFF, helpmod_cmd_top10, "Shows the top 10 most active staff");
3524 hcommand_add("report", H_OPER, helpmod_cmd_report, "Sets the channel where to report this channels statistics every 5 minutes");
3525
3526 hcommand_add("whoami", H_LAMER, helpmod_cmd_whoami, "Tells who you are to " HELPMOD_NICK);
3527 hcommand_add("whois", H_STAFF, helpmod_cmd_whois, "Tells you who someone is");
3528 hcommand_add("command", H_LAMER, helpmod_cmd_command, "Gives detailed information on a command");
3529 hcommand_add("addchan", H_ADMIN, helpmod_cmd_addchan, "Joins " HELPMOD_NICK " to a new channel");
3530 hcommand_add("delchan", H_ADMIN, helpmod_cmd_delchan, "Removes " HELPMOD_NICK " permanently from a channel");
3531
3532 hcommand_add("seen", H_STAFF, helpmod_cmd_seen, "Tells when a specific user/account has had activity");
3533 hcommand_add("op", H_STAFF, helpmod_cmd_op, "Sets mode +o on channels");
3534 hcommand_add("deop", H_STAFF, helpmod_cmd_deop, "Sets mode -o on channels");
3535 hcommand_add("voice", H_TRIAL, helpmod_cmd_voice, "Sets mode +v on channels");
3536 hcommand_add("devoice", H_TRIAL, helpmod_cmd_devoice, "Sets mode -v on channels");
3537
3538 hcommand_add("invite", H_PEON, helpmod_cmd_invite, "Invites you to a channel");
3539 hcommand_add("ticket", H_TRIAL, helpmod_cmd_ticket, "Gives a ticket to be used with invite");
3540 hcommand_add("resolve", H_STAFF, helpmod_cmd_resolve, "Resolves (deletes) a ticket");
3541 hcommand_add("tickets", H_STAFF, helpmod_cmd_tickets, "Lists all valid tickets for a channel");
3542 hcommand_add("showticket", H_STAFF, helpmod_cmd_showticket, "Shows the ticket for the user");
3543
3544 hcommand_add("termstats", H_OPER, helpmod_cmd_termstats, "Lists usage statistics for terms");
3545 hcommand_add("checkchannel", H_STAFF, helpmod_cmd_checkchannel, "Shows channel information for any channel");
3546 hcommand_add("message", H_TRIAL, helpmod_cmd_message, "Sends a message to a channel");
3547 hcommand_add("version", H_PEON, helpmod_cmd_version, "G version information");
3548 hcommand_add("ticketmsg", H_STAFF, helpmod_cmd_ticketmsg, "Handle the ticket message for a channel");
3549
3550 hcommand_add("lcedit", H_ADMIN, helpmod_cmd_lcedit, "Lamer control profile manager");
3551 hcommand_add("ged", H_STAFF, helpmod_cmd_ged, "Ged IRC text editor");
3552 hcommand_add("text", H_PEON, helpmod_cmd_text, "Lists or shows text files");
3553
3554 hcommand_add("evilhack1", H_ADMIN, helpmod_cmd_evilhack1, "An evil hack, don't use");
3555 hcommand_add("evilhack2", H_ADMIN, helpmod_cmd_evilhack2, "Another evil hack, don't use");
3556 hcommand_add("statsdump", H_ADMIN, helpmod_cmd_statsdump, "Statistics dump command");
3557 hcommand_add("statsrepair", H_ADMIN, helpmod_cmd_statsrepair, "Statistics repair command");
3558 hcommand_add("statsreset", H_ADMIN, helpmod_cmd_statsreset, "Statistics reset command");
3559
3560
3561 /*hcommand_add("megod", H_PEON, helpmod_cmd_megod, "Gives you userlevel 4, if you see this in the final version, please kill strutsi");*/
3562 /*hcommand_add("test", H_PEON, helpmod_cmd_test, "Gives you userlevel 4, if you see this in the final version, please kill strutsi");*/
3563 }
3564
3565 void helpmod_command(huser *sender, channel* returntype, char *args)
3566 {
3567 int argc = 0, useless_var;
3568 char args_copy[512];
3569 char *parsed_args[H_CMD_MAX_ARGS + 3], *ptr = args_copy;
3570
3571 /* only accept commands from valid sources */
3572 if (huser_get_level(sender) > H_ADMIN)
3573 return;
3574
3575 if (returntype && !strncmp(args, helpmodnick->nick, strlen(helpmodnick->nick)))
3576 {
3577 if (!args[1])
3578 return;
3579 else
3580 args+=strlen(helpmodnick->nick)+1;
3581 }
3582
3583 if (*args == '-' || *args == '?')
3584 args++;
3585
3586 strcpy(args_copy, args);
3587 /* FIX stringituki */
3588 while (argc < 10)
3589 {
3590 while (isspace(*ptr) && *ptr)
3591 ptr++;
3592
3593 if (*ptr == '\0')
3594 break;
3595
3596 if (*ptr == '"' && strchr(ptr+1, '"'))
3597 { /* string support */
3598 parsed_args[argc++] = ptr+1;
3599 ptr = strchr(ptr+1, '"');
3600
3601 *(ptr++) = '\0';
3602
3603 while (!isspace(*ptr) && *ptr)
3604 ptr++;
3605
3606 if (*ptr == '\0')
3607 break;
3608 }
3609 else
3610 {
3611 parsed_args[argc++] = ptr;
3612
3613 while (!isspace(*ptr) && *ptr)
3614 ptr++;
3615
3616 if (*ptr == '\0')
3617 break;
3618
3619 *(ptr++) = '\0';
3620 }
3621 }
3622
3623 if (!argc)
3624 return;
3625
3626 /* old H compatibility */
3627 if (sscanf(parsed_args[0], "%d", &useless_var) && returntype == NULL)
3628 {
3629 helpmod_cmd_help(sender, NULL, parsed_args[0], 1, NULL);
3630 return;
3631 }
3632
3633 {
3634 char *ostr = args, **argv = (char**)&parsed_args;
3635 hcommand *hcom = hcommand_get(parsed_args[0], huser_get_level(sender));
3636
3637 if (hcom == NULL)
3638 {
3639 if ((sender->account == NULL && returntype == NULL) ||
3640 (sender->account != NULL && !(sender->account->flags & H_NO_CMD_ERROR) && returntype == NULL))
3641 helpmod_reply(sender, returntype, "Unknown command '%s', please see showcommands for a list of all commands available to you", parsed_args[0]);
3642 }
3643 else
3644 {
3645 SKIP_WORD;
3646 hcom->function(sender, returntype, ostr, argc, argv);
3647 }
3648 }
3649 }
3650
3651 #undef SKIP_WORD
3652 #undef DEFINE_HCHANNEL
3653 #undef HCHANNEL_VERIFY_AUTHORITY