]>
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.");
238 *cp
= findchannel(channelname
);
241 sendnoticetouser(rqnick
, np
, "Error: Channel %s does not exist.",
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 "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 this channel. Keep waiting for at least %s before you try again.",
278 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 this channel.");
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: Request was %s.\n", now
, RQ_QNICK
, cp
->index
->name
->content
, np
->nick
, (retval
== RQ_OK
) ? "accepted" : "denied");
363 if (retval
== RQ_ERROR
)
365 else if (retval
== RQ_OK
)
371 int rqcmd_requestspamscan(void *user
, int cargc
, char **cargv
) {
372 nick
*np
= (nick
*)user
;
375 unsigned long *qhand
, *shand
;
379 sendnoticetouser(rqnick
, np
, "Syntax: requestspamscan <#channel>");
386 if (rq_genericrequestcheck(np
, cargv
[0], &cp
, &qnick
) == RQ_ERROR
) {
392 snick
= getnickbynick(RQ_SNICK
);
394 if (snick
== NULL
|| findserver(RQ_SSERVER
) < 0) {
395 sendnoticetouser(rqnick
, np
, "Error: %s does not seem to be online. "
396 "Try again later.", RQ_SNICK
);
403 /* does the user already have S on that channel? */
404 shand
= getnumerichandlefromchanhash(cp
->users
, snick
->numeric
);
407 sendnoticetouser(rqnick
, np
, "Error: %s is already on that channel.", RQ_SNICK
);
415 qhand
= getnumerichandlefromchanhash(cp
->users
, qnick
->numeric
);
418 /* great, now try to request */
419 retval
= qr_requests(rqnick
, np
, cp
, qnick
);
423 else if (retval
== RQ_ERROR
)
428 /* channel apparently doesn't have Q */
430 sendnoticetouser(rqnick
, np
, "Error: You need %s in order to be "
431 "able to request %s.", RQ_QNICK
, RQ_SNICK
);
439 int rqcmd_requestop(void *source
, int cargc
, char **cargv
) {
440 nick
*np2
, *np
= (nick
*)source
;
448 sendnoticetouser(rqnick
, np
, "Syntax: requestop <#channel> [nick]");
453 cp
= findchannel(cargv
[0]);
456 sendnoticetouser(rqnick
, np
, "Error: No such channel.");
462 user
= getnickbynick(cargv
[1]);
465 sendnoticetouser(rqnick
, np
, "Error: No such user.");
471 if (getnettime() - np
->timestamp
< 300) {
472 sendnoticetouser(rqnick
, np
, "Error: You connected %s ago. To"
473 " request ops you must have been on the network for"
474 " at least 5 minutes.",
475 rq_longtoduration(getnettime() - np
->timestamp
));
480 if (getnettime() - user
->timestamp
< 300) {
481 sendnoticetouser(rqnick
, np
, "Error: The nick you requested op for"
482 " connected %s ago. To request op, it must have"
483 "been on the network for at least 5 minutes.",
484 rq_longtoduration(getnettime() - user
->timestamp
));
489 hand
= getnumerichandlefromchanhash(cp
->users
, user
->numeric
);
492 sendnoticetouser(rqnick
, np
, "Error: User %s is not on channel %s.", user
->nick
, cargv
[0]);
500 localsetmodeinit(&changes
, cp
, rqnick
);
502 /* reop any services first */
503 for(a
=0;a
<cp
->users
->hashsize
;a
++) {
504 if(cp
->users
->content
[a
] != nouser
) {
505 np2
= getnickbynumeric(cp
->users
->content
[a
]);
507 if (IsService(np2
) && (np2
->nick
[1] == '\0') && !(cp
->users
->content
[a
] & CUMODE_OP
)) {
508 localdosetmode_nick(&changes
, np2
, MC_OP
);
514 localsetmodeflush(&changes
, 1);
518 sendnoticetouser(rqnick
, np
, "1 service was reopped.");
520 sendnoticetouser(rqnick
, np
, "%d services were reopped.", count
);
525 for (a
=0;a
<cp
->users
->hashsize
;a
++) {
526 if ((cp
->users
->content
[a
] != nouser
) && (cp
->users
->content
[a
] & CUMODE_OP
)) {
527 sendnoticetouser(rqnick
, np
, "There are ops on channel %s. This command can only be"
528 " used if there are no ops.", cargv
[0]);
534 if (sp_countsplitservers() > 0) {
535 sendnoticetouser(rqnick
, np
, "One or more servers are currently split. Wait until the"
536 " netsplit is over and try again.");
541 if (cf_wouldreop(user
, cp
)) {
542 localsetmodeinit(&changes
, cp
, rqnick
);
543 localdosetmode_nick(&changes
, user
, MC_OP
);
544 localsetmodeflush(&changes
, 1);
546 sendnoticetouser(rqnick
, np
, "Chanfix opped you on the specified channel.");
548 ret
= cf_fixchannel(cp
);
550 if (ret
== CFX_NOUSERSAVAILABLE
)
551 sendnoticetouser(rqnick
, np
, "Chanfix knows regular ops for that channel. They will"
552 " be opped when they return.");
554 sendnoticetouser(rqnick
, np
, "Chanfix has opped known ops for that channel.");
561 int rqcmd_addblock(void *user
, int cargc
, char **cargv
) {
562 nick
*np
= (nick
*)user
;
566 int level
= ru_getlevel(np
);
569 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
575 sendnoticetouser(rqnick
, np
, "Syntax: addblock <mask> <duration> <reason>");
580 block
= rq_findblock(cargv
[0]);
583 sendnoticetouser(rqnick
, np
, "That mask is already blocked by %s "
584 "(reason: %s).", block
->creator
->content
, block
->reason
->content
);
590 account
= np
->authname
;
594 expires
= getnettime() + durationtolong(cargv
[1]);
596 if (expires
> getnettime() + RQU_HELPER_MAXEXPIRE
&& level
< 30) {
597 sendnoticetouser(rqnick
, np
, "Maximum expiry time is %s.", rq_longtoduration(RQU_HELPER_MAXEXPIRE
));
602 rq_addblock(cargv
[0], cargv
[2], account
, 0, expires
);
604 sendnoticetouser(rqnick
, np
, "Blocked channels/accounts matching '%s' from "
605 "requesting a service.", cargv
[0]);
610 int rqcmd_delblock(void *user
, int cargc
, char **cargv
) {
611 nick
*np
= (nick
*)user
;
615 level
= ru_getlevel(np
);
618 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
624 sendnoticetouser(rqnick
, np
, "Syntax: delblock <mask>");
629 block
= rq_findblock(cargv
[0]);
631 if (block
!= NULL
&& level
< 50) {
632 if (ircd_strcmp(block
->creator
->content
, np
->authname
) != 0) {
633 sendnoticetouser(rqnick
, np
, "This block was created by someone else. You cannot remove it.");
639 result
= rq_removeblock(cargv
[0]);
642 sendnoticetouser(rqnick
, np
, "Block for '%s' was removed.", cargv
[0]);
646 sendnoticetouser(rqnick
, np
, "There is no such block.");
652 int rqcmd_listblocks(void *user
, int cargc
, char **cargv
) {
653 nick
*np
= (nick
*)user
;
657 level
= ru_getlevel(np
);
660 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
665 sendnoticetouser(rqnick
, np
, "Mask By Expires"
668 for (i
= 0; i
< rqblocks
.cursi
; i
++) {
669 block
= ((rq_block
*)rqblocks
.content
)[i
];
671 if (block
.expires
!= 0 && block
.expires
< getnettime())
672 continue; /* ignore blocks which have already expired,
673 rq_findblock will deal with them later on */
675 if (cargc
< 1 || match2strings(block
.pattern
->content
, cargv
[0]))
676 sendnoticetouser(rqnick
, np
, "%-11s %-9s %-25s %s",
677 block
.pattern
->content
, block
.creator
->content
,
678 rq_longtoduration(block
.expires
- getnettime()),
679 block
.reason
->content
);
682 sendnoticetouser(rqnick
, np
, "--- End of blocklist");
687 int rqcmd_stats(void *user
, int cargc
, char **cargv
) {
688 nick
*np
= (nick
*)user
;
689 int level
= ru_getlevel(np
);
692 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
697 sendnoticetouser(rqnick
, np
, "Total requests: %d", rq_count
);
698 sendnoticetouser(rqnick
, np
, "Successful requests: %d", rq_success
);
699 sendnoticetouser(rqnick
, np
, "Failed requests: %d", rq_failed
);
700 sendnoticetouser(rqnick
, np
, "- Blocked: %d", rq_blocked
);
702 lr_requeststats(rqnick
, np
);
703 qr_requeststats(rqnick
, np
);
708 int rqcmd_adduser(void *user
, int cargc
, char **cargv
) {
709 nick
*np
= (nick
*)user
;
713 sendnoticetouser(rqnick
, np
, "Syntax: adduser <account> <level>");
718 level
= atoi(cargv
[1]);
721 sendnoticetouser(rqnick
, np
, "Level must be a positive integer.");
726 result
= ru_create(cargv
[0], level
);
729 sendnoticetouser(rqnick
, np
, "User '%s' was added with level '%d'.", cargv
[0], level
);
733 sendnoticetouser(rqnick
, np
, "Something strange happened. Contact shroud.");
739 int rqcmd_deluser(void *user
, int cargc
, char **cargv
) {
740 nick
*np
= (nick
*)user
;
744 sendnoticetouser(rqnick
, np
, "Syntax: deluser <account>");
749 level
= ru_getlevel_str(cargv
[0]);
752 sendnoticetouser(rqnick
, np
, "There is no such user.");
757 ru_destroy(cargv
[0]);
759 sendnoticetouser(rqnick
, np
, "Done.");
764 int rqcmd_changelev(void *user
, int cargc
, char **cargv
) {
765 nick
*np
= (nick
*)user
;
769 sendnoticetouser(rqnick
, np
, "Syntax: changelev <account> <level>");
774 level
= atoi(cargv
[1]);
777 sendnoticetouser(rqnick
, np
, "Level must be a positive integer.");
782 if (ru_getlevel_str(cargv
[0]) <= 0) {
783 sendnoticetouser(rqnick
, np
, "Unknown user.");
788 result
= ru_setlevel(cargv
[0], level
);
791 sendnoticetouser(rqnick
, np
, "Done.");
795 sendnoticetouser(rqnick
, np
, "Something strange happened. Contact shroud.");
801 int rqcmd_userlist(void *user
, int cargc
, char **cargv
) {
802 nick
*np
= (nick
*)user
;
803 r_user_t
*userp
= r_userlist
;
805 sendnoticetouser(rqnick
, np
, "User Level");
808 sendnoticetouser(rqnick
, np
, "%s %d", userp
->name
, userp
->level
);
812 sendnoticetouser(rqnick
, np
, "--- End of USERS.");