]>
jfr.im git - irc/quakenet/newserv.git/blob - request/request.c
1 /* shroud's service request */
5 #include "../localuser/localuser.h"
6 #include "../localuser/localuserchannel.h"
7 #include "../core/schedule.h"
8 #include "../lib/irc_string.h"
9 #include "../lib/splitline.h"
10 #include "../lib/version.h"
11 #include "../control/control.h"
12 #include "../splitlist/splitlist.h"
14 #include "request_block.h"
16 #include "sqrequest.h"
22 CommandTree
*rqcommands
;
24 void rq_registeruser(void);
25 void rq_handler(nick
*target
, int type
, void **args
);
27 int rqcmd_showcommands(void *user
, int cargc
, char **cargv
);
28 int rqcmd_request(void *user
, int cargc
, char **cargv
);
29 int rqcmd_requestspamscan(void *user
, int cargc
, char **cargv
);
30 int rqcmd_addblock(void *user
, int cargc
, char **cargv
);
31 int rqcmd_delblock(void *user
, int cargc
, char **cargv
);
32 int rqcmd_listblocks(void *user
, int cargc
, char **cargv
);
33 int rqcmd_stats(void *user
, int cargc
, char **cargv
);
34 int rqcmd_requestop(void *user
, int cargc
, char **cargv
);
36 int rqcmd_adduser(void *user
, int cargc
, char **cargv
);
37 int rqcmd_deluser(void *user
, int cargc
, char **cargv
);
38 int rqcmd_changelev(void *user
, int cargc
, char **cargv
);
39 int rqcmd_userlist(void *user
, int cargc
, char **cargv
);
41 #define min(a,b) ((a > b) ? b : a)
52 static int extloaded
= 0;
60 rqcommands
= newcommandtree();
62 addcommandtotree(rqcommands
, "showcommands", RQU_ANY
, 1, &rqcmd_showcommands
);
63 addcommandtotree(rqcommands
, "requestbot", RQU_ANY
, 1, &rqcmd_request
);
64 addcommandtotree(rqcommands
, "requestspamscan", RQU_ANY
, 1, &rqcmd_requestspamscan
);
65 addcommandtotree(rqcommands
, "requestop", RQU_ANY
, 2, &rqcmd_requestop
);
67 addcommandtotree(rqcommands
, "addblock", RQU_ACCOUNT
, 3, &rqcmd_addblock
);
68 addcommandtotree(rqcommands
, "delblock", RQU_ACCOUNT
, 1, &rqcmd_delblock
);
69 addcommandtotree(rqcommands
, "listblocks", RQU_ACCOUNT
, 1, &rqcmd_listblocks
);
70 addcommandtotree(rqcommands
, "stats", RQU_ACCOUNT
, 1, &rqcmd_stats
);
72 addcommandtotree(rqcommands
, "adduser", RQU_OPER
, 2, &rqcmd_adduser
);
73 addcommandtotree(rqcommands
, "deluser", RQU_OPER
, 1, &rqcmd_deluser
);
74 addcommandtotree(rqcommands
, "changelev", RQU_OPER
, 2, &rqcmd_changelev
);
75 addcommandtotree(rqcommands
, "userlist", RQU_OPER
, 1, &rqcmd_userlist
);
80 rq_logfd
= fopen(RQ_LOGFILE
, "a");
82 scheduleoneshot(time(NULL
) + 1, (ScheduleCallback
)&rq_registeruser
, NULL
);
89 deregisterlocaluser(rqnick
, NULL
);
91 deletecommandfromtree(rqcommands
, "showcommands", &rqcmd_showcommands
);
92 deletecommandfromtree(rqcommands
, "requestbot", &rqcmd_request
);
93 deletecommandfromtree(rqcommands
, "requestspamscan", &rqcmd_requestspamscan
);
94 deletecommandfromtree(rqcommands
, "requestop", &rqcmd_requestop
);
96 deletecommandfromtree(rqcommands
, "addblock", &rqcmd_addblock
);
97 deletecommandfromtree(rqcommands
, "delblock", &rqcmd_delblock
);
98 deletecommandfromtree(rqcommands
, "listblocks", &rqcmd_listblocks
);
99 deletecommandfromtree(rqcommands
, "stats", &rqcmd_stats
);
101 deletecommandfromtree(rqcommands
, "adduser", &rqcmd_adduser
);
102 deletecommandfromtree(rqcommands
, "deluser", &rqcmd_deluser
);
103 deletecommandfromtree(rqcommands
, "changelev", &rqcmd_changelev
);
104 deletecommandfromtree(rqcommands
, "userlist", &rqcmd_userlist
);
106 destroycommandtree(rqcommands
);
112 if (rq_logfd
!= NULL
)
115 deleteallschedules((ScheduleCallback
)&rq_registeruser
);
118 void rq_registeruser(void) {
121 rqnick
= registerlocaluserflags(RQ_REQUEST_NICK
, RQ_REQUEST_USER
, RQ_REQUEST_HOST
,
122 RQ_REQUEST_REAL
, RQ_REQUEST_AUTH
, 1780711, 0,
123 UMODE_ACCOUNT
| UMODE_SERVICE
| UMODE_OPER
,
126 cp
= findchannel(RQ_TLZ
);
129 localcreatechannel(rqnick
, RQ_TLZ
);
131 localjoinchannel(rqnick
, cp
);
134 char *rq_longtoduration(unsigned long interval
) {
135 static char buf
[100];
137 strncpy(buf
, longtoduration(interval
, 0), sizeof(buf
));
139 /* chop off last character if it's a space */
140 if (buf
[strlen(buf
)] == ' ')
141 buf
[strlen(buf
)] = '\0';
146 void rq_handler(nick
*target
, int type
, void **params
) {
158 cargc
= splitline(line
, cargv
, 30, 0);
163 cmd
= findcommandintree(rqcommands
, cargv
[0], 1);
166 sendnoticetouser(rqnick
, user
, "Unknown command.");
171 if ((cmd
->level
& RQU_OPER
) && !IsOper(user
)) {
172 sendnoticetouser(rqnick
, user
, "Sorry, this command is not "
173 "available to you.");
178 if ((cmd
->level
& RQU_ACCOUNT
) && (!IsAccount(user
) || ru_getlevel(user
) == 0) && !IsOper(user
)) {
179 sendnoticetouser(rqnick
, user
, "Sorry, this command is not "
180 "available to you.");
185 if (cargc
- 1 > cmd
->maxparams
)
186 rejoinline(cargv
[cmd
->maxparams
], cargc
- cmd
->maxparams
);
188 /* handle the command */
189 cmd
->handler((void*)user
, min(cargc
- 1, cmd
->maxparams
), &(cargv
[1]));
193 scheduleoneshot(time(NULL
) + 5, (ScheduleCallback
)&rq_registeruser
, NULL
);
197 qr_handle_notice(params
[0], params
[1]);
203 int rqcmd_showcommands(void *user
, int cargc
, char **cargv
) {
204 nick
* np
= (nick
*)user
;
206 Command
* cmdlist
[50];
208 n
= getcommandlist(rqcommands
, cmdlist
, 50);
210 sendnoticetouser(rqnick
, np
, "Available commands:");
211 sendnoticetouser(rqnick
, np
, "-------------------");
213 for (i
= 0; i
< n
; i
++) {
214 if ((cmdlist
[i
]->level
& RQU_OPER
) && !IsOper(np
))
217 if ((cmdlist
[i
]->level
& RQU_ACCOUNT
) && !(IsOper(np
) || (IsAccount(np
) && ru_getlevel(np
) > 0)))
220 sendnoticetouser(rqnick
, np
, "%s", cmdlist
[i
]->command
->content
);
223 sendnoticetouser(rqnick
, np
, "End of SHOWCOMMANDS");
228 int rq_genericrequestcheck(nick
*np
, char *channelname
, channel
**cp
, nick
**qnick
) {
229 unsigned long *userhand
;
232 if (!IsAccount(np
)) {
233 sendnoticetouser(rqnick
, np
, "Error: You must be authed to perform a service request.");
238 *cp
= findchannel(channelname
);
241 sendnoticetouser(rqnick
, np
, "Error: Channel '%s' does not exist on the network.",
247 *qnick
= getnickbynick(RQ_QNICK
);
249 if (*qnick
== NULL
|| findserver(RQ_QSERVER
) < 0) {
250 sendnoticetouser(rqnick
, np
, "Error: %s does not seem to be online. "
251 "Please try again later.", RQ_QNICK
);
256 userhand
= getnumerichandlefromchanhash((*cp
)->users
, np
->numeric
);
258 if (userhand
== NULL
) {
259 sendnoticetouser(rqnick
, np
, "Error: You're not on that channel.");
264 if ((*userhand
& CUMODE_OP
) == 0) {
265 sendnoticetouser(rqnick
, np
, "Error: You must be op'd on the channel to "
266 "request a service.");
271 block
= rq_findblock(channelname
);
274 /* only say when block expires if <7 days */
275 if ( block
->expires
< getnettime() + 3600 * 24 * 7) {
276 sendnoticetouser(rqnick
, np
, "Error: You are not allowed to request a "
277 "service to '%s'. Keep waiting for at least %s before you try again.",
278 channelname
, rq_longtoduration(block
->expires
- getnettime()));
279 /* give them another 5 minutes to think about it */
280 block
->expires
+= 300;
283 sendnoticetouser(rqnick
, np
, "Error: You are not allowed to request a "
284 "service to '%s'.", channelname
);
286 sendnoticetouser(rqnick
, np
, "Reason: %s", block
->reason
->content
);
293 block
= rq_findblock(np
->authname
);
295 /* only tell the user if the block is going to expire in the next 48 hours
296 so we can have our fun with longterm blocks.
297 the request subsystems should deal with longterm blocks on their own */
298 if (block
!= NULL
&& block
->expires
< getnettime() + 3600 * 24 * 2) {
299 sendnoticetouser(rqnick
, np
, "Error: You are not allowed to request a "
300 "service. Keep waiting for at least %s before you try again.",
301 rq_longtoduration(block
->expires
- getnettime()));
303 sendnoticetouser(rqnick
, np
, "Reason: %s", block
->reason
->content
);
305 /* give them another 5 minutes to think about it */
306 block
->expires
+= 300;
317 int rqcmd_request(void *user
, int cargc
, char **cargv
) {
318 nick
*np
= (nick
*)user
;
320 unsigned long *qhand
;
327 sendnoticetouser(rqnick
, np
, "Syntax: requestbot <#channel>");
334 if (rq_genericrequestcheck(np
, cargv
[0], &cp
, &qnick
) == RQ_ERROR
) {
340 qhand
= getnumerichandlefromchanhash(cp
->users
, qnick
->numeric
);
343 sendnoticetouser(rqnick
, np
, "Error: %s is already on that channel.", RQ_QNICK
);
352 retval
= lr_requestl(rqnick
, np
, cp
, qnick
);
354 if (rq_logfd
!= NULL
) {
357 strftime(now
, sizeof(now
), "%c", localtime(&now_ts
));
359 fprintf(rq_logfd
, "%s: request (%s) for %s from %s!%s@%s%s%s: Request was %s.\n",
360 now
, RQ_QNICK
, cp
->index
->name
->content
,
361 np
->nick
, np
->ident
, np
->host
->name
->content
, IsAccount(np
)?"/":"", IsAccount(np
)?np
->authname
:"",
362 (retval
== RQ_OK
) ? "accepted" : "denied");
366 if (retval
== RQ_ERROR
)
368 else if (retval
== RQ_OK
)
374 int rqcmd_requestspamscan(void *user
, int cargc
, char **cargv
) {
375 nick
*np
= (nick
*)user
;
378 unsigned long *qhand
, *shand
;
382 sendnoticetouser(rqnick
, np
, "Syntax: requestspamscan <#channel>");
389 if (rq_genericrequestcheck(np
, cargv
[0], &cp
, &qnick
) == RQ_ERROR
) {
395 snick
= getnickbynick(RQ_SNICK
);
397 if (snick
== NULL
|| findserver(RQ_SSERVER
) < 0) {
398 sendnoticetouser(rqnick
, np
, "Error: %s does not seem to be online. "
399 "Please try again later.", RQ_SNICK
);
406 /* does the user already have S on that channel? */
407 shand
= getnumerichandlefromchanhash(cp
->users
, snick
->numeric
);
410 sendnoticetouser(rqnick
, np
, "Error: %s is already on that channel.", RQ_SNICK
);
418 qhand
= getnumerichandlefromchanhash(cp
->users
, qnick
->numeric
);
421 /* great, now try to request */
422 retval
= qr_requests(rqnick
, np
, cp
, qnick
);
426 else if (retval
== RQ_ERROR
)
431 /* channel apparently doesn't have Q */
433 sendnoticetouser(rqnick
, np
, "Error: You need %s in order to be "
434 "able to request %s.", RQ_QNICK
, RQ_SNICK
);
442 int rqcmd_requestop(void *source
, int cargc
, char **cargv
) {
443 nick
*np2
, *np
= (nick
*)source
;
451 sendnoticetouser(rqnick
, np
, "Syntax: requestop <#channel> [nick]");
456 cp
= findchannel(cargv
[0]);
459 sendnoticetouser(rqnick
, np
, "Error: Channel '%s' does not exist on the network.",
466 user
= getnickbynick(cargv
[1]);
469 sendnoticetouser(rqnick
, np
, "Error: No such user.");
475 if (getnettime() - np
->timestamp
< 300) {
476 sendnoticetouser(rqnick
, np
, "Error: You connected %s ago. To"
477 " request ops you must have been on the network for"
478 " at least 5 minutes.",
479 rq_longtoduration(getnettime() - np
->timestamp
));
484 if (getnettime() - user
->timestamp
< 300) {
485 sendnoticetouser(rqnick
, np
, "Error: The nick you requested op for"
486 " connected %s ago. To request op, it must have"
487 "been on the network for at least 5 minutes.",
488 rq_longtoduration(getnettime() - user
->timestamp
));
493 hand
= getnumerichandlefromchanhash(cp
->users
, user
->numeric
);
496 sendnoticetouser(rqnick
, np
, "Error: User %s is not on channel '%s'.", user
->nick
, cargv
[0]);
504 localsetmodeinit(&changes
, cp
, rqnick
);
506 /* reop any services first */
507 for(a
=0;a
<cp
->users
->hashsize
;a
++) {
508 if(cp
->users
->content
[a
] != nouser
) {
509 np2
= getnickbynumeric(cp
->users
->content
[a
]);
511 if (IsService(np2
) && (np2
->nick
[1] == '\0') && !(cp
->users
->content
[a
] & CUMODE_OP
)) {
512 localdosetmode_nick(&changes
, np2
, MC_OP
);
518 localsetmodeflush(&changes
, 1);
522 sendnoticetouser(rqnick
, np
, "1 service was reopped.");
524 sendnoticetouser(rqnick
, np
, "%d services were reopped.", count
);
529 for (a
=0;a
<cp
->users
->hashsize
;a
++) {
530 if ((cp
->users
->content
[a
] != nouser
) && (cp
->users
->content
[a
] & CUMODE_OP
)) {
531 sendnoticetouser(rqnick
, np
, "There are ops on channel '%s'. This command can only be"
532 " used if there are no ops.", cargv
[0]);
538 if (sp_countsplitservers() > 0) {
539 sendnoticetouser(rqnick
, np
, "One or more servers are currently split. Wait until the"
540 " netsplit is over and try again.");
545 if (cf_wouldreop(user
, cp
)) {
546 localsetmodeinit(&changes
, cp
, rqnick
);
547 localdosetmode_nick(&changes
, user
, MC_OP
);
548 localsetmodeflush(&changes
, 1);
550 sendnoticetouser(rqnick
, np
, "Chanfix opped you on the specified channel.");
552 ret
= cf_fixchannel(cp
);
554 if (ret
== CFX_NOUSERSAVAILABLE
)
555 sendnoticetouser(rqnick
, np
, "Chanfix knows regular ops for that channel. They will"
556 " be opped when they return.");
558 sendnoticetouser(rqnick
, np
, "Chanfix has opped known ops for that channel.");
565 int rqcmd_addblock(void *user
, int cargc
, char **cargv
) {
566 nick
*np
= (nick
*)user
;
570 int level
= ru_getlevel(np
);
573 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
579 sendnoticetouser(rqnick
, np
, "Syntax: addblock <mask> <duration> <reason>");
584 block
= rq_findblock(cargv
[0]);
587 sendnoticetouser(rqnick
, np
, "That mask is already blocked by %s "
588 "(reason: %s).", block
->creator
->content
, block
->reason
->content
);
594 account
= np
->authname
;
598 expires
= getnettime() + durationtolong(cargv
[1]);
600 if (expires
> getnettime() + RQU_HELPER_MAXEXPIRE
&& level
< 30) {
601 sendnoticetouser(rqnick
, np
, "Maximum expiry time is %s.", rq_longtoduration(RQU_HELPER_MAXEXPIRE
));
606 rq_addblock(cargv
[0], cargv
[2], account
, 0, expires
);
608 sendnoticetouser(rqnick
, np
, "Blocked channels/accounts matching '%s' from "
609 "requesting a service.", cargv
[0]);
614 int rqcmd_delblock(void *user
, int cargc
, char **cargv
) {
615 nick
*np
= (nick
*)user
;
619 level
= ru_getlevel(np
);
622 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
628 sendnoticetouser(rqnick
, np
, "Syntax: delblock <mask>");
633 block
= rq_findblock(cargv
[0]);
635 if (block
!= NULL
&& level
< 50) {
636 if (ircd_strcmp(block
->creator
->content
, np
->authname
) != 0) {
637 sendnoticetouser(rqnick
, np
, "This block was created by someone else. You cannot remove it.");
643 result
= rq_removeblock(cargv
[0]);
646 sendnoticetouser(rqnick
, np
, "Block for '%s' was removed.", cargv
[0]);
650 sendnoticetouser(rqnick
, np
, "There is no such block.");
656 int rqcmd_listblocks(void *user
, int cargc
, char **cargv
) {
657 nick
*np
= (nick
*)user
;
661 level
= ru_getlevel(np
);
664 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
669 sendnoticetouser(rqnick
, np
, "Mask By Expires"
672 for (i
= 0; i
< rqblocks
.cursi
; i
++) {
673 block
= ((rq_block
*)rqblocks
.content
)[i
];
675 if (block
.expires
!= 0 && block
.expires
< getnettime())
676 continue; /* ignore blocks which have already expired,
677 rq_findblock will deal with them later on */
679 if (cargc
< 1 || match2strings(block
.pattern
->content
, cargv
[0]))
680 sendnoticetouser(rqnick
, np
, "%-11s %-9s %-25s %s",
681 block
.pattern
->content
, block
.creator
->content
,
682 rq_longtoduration(block
.expires
- getnettime()),
683 block
.reason
->content
);
686 sendnoticetouser(rqnick
, np
, "--- End of blocklist");
691 int rqcmd_stats(void *user
, int cargc
, char **cargv
) {
692 nick
*np
= (nick
*)user
;
693 int level
= ru_getlevel(np
);
696 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
701 sendnoticetouser(rqnick
, np
, "Total requests: %d", rq_count
);
702 sendnoticetouser(rqnick
, np
, "Successful requests: %d", rq_success
);
703 sendnoticetouser(rqnick
, np
, "Failed requests: %d", rq_failed
);
704 sendnoticetouser(rqnick
, np
, "- Blocked: %d", rq_blocked
);
706 lr_requeststats(rqnick
, np
);
707 qr_requeststats(rqnick
, np
);
712 int rqcmd_adduser(void *user
, int cargc
, char **cargv
) {
713 nick
*np
= (nick
*)user
;
717 sendnoticetouser(rqnick
, np
, "Syntax: adduser <account> <level>");
722 level
= atoi(cargv
[1]);
725 sendnoticetouser(rqnick
, np
, "Level must be a positive integer.");
730 result
= ru_create(cargv
[0], level
);
733 sendnoticetouser(rqnick
, np
, "User '%s' was added with level '%d'.", cargv
[0], level
);
737 sendnoticetouser(rqnick
, np
, "Something strange happened. Contact shroud.");
743 int rqcmd_deluser(void *user
, int cargc
, char **cargv
) {
744 nick
*np
= (nick
*)user
;
748 sendnoticetouser(rqnick
, np
, "Syntax: deluser <account>");
753 level
= ru_getlevel_str(cargv
[0]);
756 sendnoticetouser(rqnick
, np
, "There is no such user.");
761 ru_destroy(cargv
[0]);
763 sendnoticetouser(rqnick
, np
, "Done.");
768 int rqcmd_changelev(void *user
, int cargc
, char **cargv
) {
769 nick
*np
= (nick
*)user
;
773 sendnoticetouser(rqnick
, np
, "Syntax: changelev <account> <level>");
778 level
= atoi(cargv
[1]);
781 sendnoticetouser(rqnick
, np
, "Level must be a positive integer.");
786 if (ru_getlevel_str(cargv
[0]) <= 0) {
787 sendnoticetouser(rqnick
, np
, "Unknown user.");
792 result
= ru_setlevel(cargv
[0], level
);
795 sendnoticetouser(rqnick
, np
, "Done.");
799 sendnoticetouser(rqnick
, np
, "Something strange happened. Contact shroud.");
805 int rqcmd_userlist(void *user
, int cargc
, char **cargv
) {
806 nick
*np
= (nick
*)user
;
807 r_user_t
*userp
= r_userlist
;
809 sendnoticetouser(rqnick
, np
, "User Level");
812 sendnoticetouser(rqnick
, np
, "%s %d", userp
->name
, userp
->level
);
816 sendnoticetouser(rqnick
, np
, "--- End of USERS.");