]>
jfr.im git - irc/quakenet/newserv.git/blob - fakeusers/fakeusers.c
1291813374928503ddde7e045873f8f44365f76b
2 * NOperserv Fakeuser module
4 * Allows fakeusers to be added so as to block nicks, for example.
6 * Copyright (c) Tim Gordon 2006.
9 #include "../core/schedule.h"
10 #include "../localuser/localuser.h"
11 #include "../localuser/localuserchannel.h"
12 #include "../irc/irc_config.h"
13 #include "../lib/irc_string.h"
14 #include "../control/control.h"
15 #include "../channel/channel.h"
16 #include "../dbapi2/dbapi2.h"
17 #include "../lib/strlfunc.h"
18 #include "../lib/version.h"
24 /* #define SIT_CHANNEL "#qnet.fakeusers" */
28 typedef struct fakeuser
{
31 struct fakeuser
* next
;
34 typedef struct user_details
{
35 char nick
[ NICKLEN
+ 1 ];
36 char ident
[ USERLEN
+ 1 ];
37 char host
[ HOSTLEN
+ 1 ];
38 char realname
[ REALLEN
+ 1 ];
40 struct user_details
* next
;
44 fakeuser
* fakeuserlist
= NULL
;
45 user_details
* killeduserlist
= NULL
;
46 int fakeusercount
= 0 ;
47 int killedusercount
= 0 ;
49 void fakeuser_cleanup ();
50 int fakeuser_loaddb ();
51 void fakeusers_load ( const DBAPIResult
* res
, void * arg
);
52 void fakeuser_handler ( nick
* user
, int command
, void ** params
);
53 int fakeadd ( void * sender
, int cargc
, char ** cargv
);
54 int fakelist ( void * sender
, int cargc
, char ** cargv
);
55 int fakekill ( void * sender
, int cargc
, char ** cargv
);
56 void reconnectfake ( void * details
);
59 static DBAPIConn
* nofudb
;
62 if (! fakeuser_loaddb ())
64 Error ( "fakeuser" , ERR_FATAL
, "Cannot load database" );
67 registercontrolhelpcmd ( "fakeuser" , NO_OPER
, 4 , & fakeadd
, "Usage: FAKEUSER nick <ident> <host> <realname> \n Creates a fake user." );
68 registercontrolhelpcmd ( "fakelist" , NO_OPER
, 0 , & fakelist
, "Usage: FAKELIST \n Lists all fake users." );
69 registercontrolhelpcmd ( "fakekill" , NO_OPER
, 2 , & fakekill
, "Usage: FAKEKILL nick <reason> \n Removes a fake user" );
74 deregistercontrolcmd ( "fakeuser" , & fakeadd
);
75 deregistercontrolcmd ( "fakelist" , & fakelist
);
76 deregistercontrolcmd ( "fakekill" , & fakekill
);
79 void fakeuser_cleanup ()
84 for ( fake
= fakeuserlist
; fake
; fake
= next
)
86 deregisterlocaluser ( fake
-> user
, "Signing off" );
90 for ( killed
= killeduserlist
; killed
; killed
= next
)
92 deleteschedule ( killed
-> schedule
, & reconnectfake
, killed
);
99 killeduserlist
= NULL
;
102 int fakeuser_loaddb ()
105 nofudb
= dbapi2open ( DBAPI2_DEFAULT
, "fakeusers" );
107 Error ( "fakeuser" , ERR_STOP
, "Could not connect to database." );
114 nofudb
-> createtable ( nofudb
, NULL
, NULL
,
116 "nick VARCHAR(?) NOT NULL,"
117 "ident VARCHAR(?) NOT NULL,"
118 "host VARCHAR(?) NOT NULL,"
119 "realname VARCHAR(?) NOT NULL,"
120 "PRIMARY KEY (nick))" , "Tdddd" , "fakeusers" , NICKLEN
, USERLEN
, HOSTLEN
, REALLEN
);
122 nofudb
-> query ( nofudb
, fakeusers_load
, NULL
,
123 "SELECT nick, ident, host, realname FROM ?" , "T" , "fakeusers" );
128 void fakeusers_load ( const DBAPIResult
* res
, void * arg
) {
129 user_details details
;
135 Error ( "fakeuser" , ERR_ERROR
, "Error loading fakeuser list." );
140 details
. lastkill
= 0 ;
141 details
. schedule
= NULL
;
142 while ( res
-> next ( res
)) {
143 strlcpy ( details
. nick
, res
-> get ( res
, 0 ), NICKLEN
+ 1 );
144 strlcpy ( details
. ident
, res
-> get ( res
, 1 ), USERLEN
+ 1 );
145 strlcpy ( details
. host
, res
-> get ( res
, 2 ), HOSTLEN
+ 1 );
146 strlcpy ( details
. realname
, res
-> get ( res
, 3 ), REALLEN
+ 1 );
147 reconnectfake (& details
);
153 user_details
* getdetails ( nick
* user
)
155 user_details
* details
;
156 details
= malloc ( sizeof ( user_details
));
159 strlcpy ( details
-> nick
, user
-> nick
, NICKLEN
+ 1 );
160 strlcpy ( details
-> ident
, user
-> ident
, USERLEN
+ 1 );
161 strlcpy ( details
-> host
, user
-> host
-> name
-> content
, HOSTLEN
+ 1 );
162 strlcpy ( details
-> realname
, user
-> realname
-> name
-> content
, REALLEN
+ 1 );
163 details
-> schedule
= NULL
;
164 details
-> lastkill
= 0 ;
170 #define ERR_WONTKILL 3
173 nick
* register_fakeuser ( user_details
* details
)
176 if (( user
= getnickbynick ( details
-> nick
)) && ( IsOper ( user
) || IsService ( user
) || IsXOper ( user
))) {
177 err_code
= ERR_WONTKILL
;
182 return registerlocaluser ( details
-> nick
, details
-> ident
, details
-> host
, details
-> realname
,
183 NULL
, UMODE_INV
| UMODE_DEAF
, & fakeuser_handler
);
186 fakeuser
* ll_add ( user_details
* details
)
187 // Adds to the (sorted) linked list
189 fakeuser
* fake
, * newfake
;
194 cmp
= ircd_strcmp ( details
-> nick
, fakeuserlist
-> user
-> nick
);
197 err_code
= ERR_EXISTS
;
205 newfake
= malloc ( sizeof ( fakeuser
));
211 newfake
-> user
= register_fakeuser ( details
);
215 return NULL
; //errcode already set by register_fakeuser
217 newfake
-> lastkill
= details
-> lastkill
;
218 newfake
-> next
= fakeuserlist
;
219 fakeuserlist
= newfake
;
223 for ( fake
= fakeuserlist
; fake
-> next
; fake
= fake
-> next
)
225 cmp
= ircd_strcmp ( details
-> nick
, fake
-> next
-> user
-> nick
);
228 err_code
= ERR_EXISTS
;
233 newfake
= malloc ( sizeof ( fakeuser
));
239 newfake
-> user
= register_fakeuser ( details
);
243 return NULL
; //errcode already set by register_fakeuser
245 newfake
-> lastkill
= details
-> lastkill
;
246 newfake
-> next
= fake
-> next
;
247 fake
-> next
= newfake
;
252 newfake
= malloc ( sizeof ( fakeuser
));
258 newfake
-> user
= register_fakeuser ( details
);
262 return NULL
; //errcode already set by register_fakeuser
264 newfake
-> lastkill
= details
-> lastkill
;
265 newfake
-> next
= NULL
;
266 fake
-> next
= newfake
;
271 void kll_add ( user_details
* details
)
272 //Adds to the (sorted) linked list of killed users
275 user_details
* killed
;
278 cmp
= ircd_strcmp ( details
-> nick
, killeduserlist
-> nick
);
281 if ( cmp
< 0 ) //Add to the start of the list
283 details
-> next
= killeduserlist
;
284 killeduserlist
= details
;
288 for ( killed
= killeduserlist
; killed
-> next
; killed
= killed
-> next
)
290 cmp
= ircd_strcmp ( details
-> nick
, killed
-> next
-> nick
);
293 details
-> next
= killed
-> next
;
294 killed
-> next
= details
;
299 details
-> next
= NULL
;
300 killed
-> next
= details
;
305 fakeuser
* ll_remove ( char * nickname
)
306 //Removes from the linked list
308 fakeuser
* fake
, * rmfake
;
313 cmp
= ircd_strcmp ( nickname
, fakeuserlist
-> user
-> nick
);
318 rmfake
= fakeuserlist
;
319 fakeuserlist
= fakeuserlist
-> next
;
324 for ( fake
= fakeuserlist
; fake
-> next
; fake
= fake
-> next
)
327 cmp
= ircd_strcmp ( nickname
, rmfake
-> user
-> nick
);
332 fake
-> next
= rmfake
-> next
;
341 user_details
* kll_remove ( char * nickname
) //Removes from the killed user linked list
343 user_details
* details
, * rmdetails
;
348 cmp
= ircd_strcmp ( nickname
, killeduserlist
-> nick
);
353 rmdetails
= killeduserlist
;
354 killeduserlist
= killeduserlist
-> next
;
355 rmdetails
-> next
= NULL
;
359 for ( details
= killeduserlist
; details
-> next
; details
= details
-> next
)
361 rmdetails
= details
-> next
;
362 cmp
= ircd_strcmp ( nickname
, rmdetails
-> nick
);
367 details
-> next
= rmdetails
-> next
;
368 rmdetails
-> next
= NULL
;
376 void fakeuser_handler ( nick
* user
, int command
, void ** params
)
378 if ( command
== LU_KILLED
)
380 user_details
* details
;
382 time_t timenow
= time ( NULL
);
384 details
= getdetails ( user
);
385 item
= ll_remove ( details
-> nick
);
388 controlwall ( NO_OPER
, NL_FAKEUSERS
, "Error: A fakeuser was killed, but wasn't found in the list" );
389 Error ( "fakeuser" , ERR_ERROR
, "A fakeuser was killed, but wasn't found in the list" );
393 details
-> lastkill
= item
-> lastkill
;
396 if ( timenow
- details
-> lastkill
< KILL_TIME
) {
397 controlwall ( NO_OPER
, NL_FAKEUSERS
, "Fake user %s ! %s @ %s ( %s ) KILL'ed twice under in %d seconds. Removing." , details
-> nick
, details
-> ident
, details
-> host
, details
-> realname
, KILL_TIME
);
398 nofudb
-> squery ( nofudb
, "DELETE FROM ? WHERE nick = ?" , "Ts" , "fakeusers" , details
-> nick
);
401 details
-> lastkill
= timenow
;
403 details
-> schedule
= scheduleoneshot ( time ( NULL
) + KILL_WAIT
, & reconnectfake
, details
);
404 if (! details
-> schedule
)
406 Error ( "fakeuser" , ERR_ERROR
, "Couldn't reschedule fakeuser for reconnect" );
414 //Usage: FAKEUSER nick <ident> <host> <realname>
415 int fakeadd ( void * sender
, int cargc
, char ** cargv
)
417 user_details details
, * killed
;
423 strlcpy ( details
. nick
, cargv
[ 0 ], NICKLEN
+ 1 );
425 strlcpy ( details
. realname
, cargv
[ 0 ], REALLEN
+ 1 );
427 strlcpy ( details
. realname
, cargv
[ 3 ], REALLEN
+ 1 );
430 strlcpy ( details
. host
, cargv
[ 0 ], NICKLEN
+ 1 );
431 strlcat ( details
. host
, ".fakeusers.quakenet.org" , HOSTLEN
+ 1 );
434 strlcpy ( details
. host
, cargv
[ 2 ], HOSTLEN
+ 1 );
436 strlcpy ( details
. ident
, cargv
[ 0 ], USERLEN
+ 1 );
438 strlcpy ( details
. ident
, cargv
[ 1 ], USERLEN
+ 1 );
440 details
. lastkill
= 0 ;
442 newfake
= ll_add (& details
);
445 if ( err_code
== ERR_EXISTS
)
446 controlreply ( sender
, "Error: fakeuser already exists" );
447 else if ( err_code
== ERR_MEM
)
449 controlreply ( sender
, "Error: memory error!!" );
450 Error ( "fakeuser" , ERR_STOP
, "malloc error" );
452 else if ( err_code
== ERR_WONTKILL
)
453 controlreply ( sender
, "Nick already exists and I won't kill it" );
456 controlreply ( sender
, "Unknown error when adding fakeuser" );
457 Error ( "fakeuser" , ERR_ERROR
, "Unknown error when adding fakeuser" );
461 newnick
= newfake
-> user
;
462 if (( killed
= kll_remove ( newnick
-> nick
))) //Is this nickname scheduled to reconnect?
464 deleteschedule ( killed
-> schedule
, & reconnectfake
, killed
);
466 nofudb
-> squery ( nofudb
, "UPDATE ? SET ident=?, host=?, realname=? WHERE nick = ?" , "Tssss" , "fakeusers" , newnick
-> ident
, newnick
-> host
-> name
-> content
, newnick
-> realname
-> name
-> content
, newnick
-> nick
);
469 nofudb
-> squery ( nofudb
, "INSERT INTO ? (nick, ident, host, realname) VALUES (?,?,?,?)" , "Tssss" , "fakeusers" , newnick
-> nick
, newnick
-> ident
, newnick
-> host
-> name
-> content
, newnick
-> realname
-> name
-> content
);
470 controlreply ( sender
, "Added fake user %s " , newnick
-> nick
);
471 controlwall ( NO_OPER
, NL_FAKEUSERS
, "Fake user %s ! %s @ %s ( %s ) added by %s / %s " , newnick
-> nick
, newnick
-> ident
,
472 newnick
-> host
-> name
-> content
, newnick
-> realname
-> name
-> content
, (( nick
*) sender
)-> nick
, (( nick
*) sender
)-> authname
);
476 if (!( sitchannel
= findchannel ( SIT_CHANNEL
)))
477 sitchannel
= createchannel ( SIT_CHANNEL
);
478 localjoinchannel ( newnick
, sitchannel
);
485 int fakelist ( void * sender
, int cargc
, char ** cargv
)
488 if ( fakeusercount
== 1 )
489 controlreply ( sender
, "1 fakeuser is currently connected" );
491 controlreply ( sender
, " %d fakeusers are currently connected" , fakeusercount
);
492 for ( fake
= fakeuserlist
; fake
; fake
= fake
-> next
)
493 controlreply ( sender
, " %s ! %s @ %s ( %s )" , fake
-> user
-> nick
, fake
-> user
-> ident
,
494 fake
-> user
-> host
-> name
-> content
, fake
-> user
-> realname
-> name
-> content
);
497 user_details
* k_fake
;
498 if ( fakeusercount
== 1 )
499 controlreply ( sender
, "1 fakeuser is currently waiting to reconnect" );
501 controlreply ( sender
, " %d fakeusers are currently waiting to reconnect" , killedusercount
);
502 for ( k_fake
= killeduserlist
; k_fake
; k_fake
= k_fake
-> next
)
503 controlreply ( sender
, " %s ! %s @ %s ( %s )" , k_fake
-> nick
, k_fake
-> ident
, k_fake
-> host
, k_fake
-> realname
);
508 //Usage: FAKEKILL nick <reason>
509 int fakekill ( void * sender
, int cargc
, char ** cargv
)
512 user_details
* k_fake
;
515 if (( fake
= ll_remove ( cargv
[ 0 ])))
517 nofudb
-> squery ( nofudb
, "DELETE FROM ? WHERE nick = ?" , "Ts" , "fakeusers" , fake
-> user
-> nick
);
518 controlreply ( sender
, "Killed fake user %s " , fake
-> user
-> nick
);
519 controlwall ( NO_OPER
, NL_FAKEUSERS
, "Fake user %s ! %s @ %s ( %s ) removed by %s / %s " , fake
-> user
-> nick
, fake
-> user
-> ident
,
520 fake
-> user
-> host
-> name
-> content
, fake
-> user
-> realname
-> name
-> content
, (( nick
*) sender
)-> nick
, (( nick
*) sender
)-> authname
);
522 deregisterlocaluser ( fake
-> user
, cargv
[ 1 ]);
524 deregisterlocaluser ( fake
-> user
, "Signing off" );
528 if (( k_fake
= kll_remove ( cargv
[ 0 ]))) //Fakeuser might be waiting to rejoin
530 nofudb
-> squery ( nofudb
, "DELETE FROM ? WHERE nick = ?" , "Ts" , "fakeusers" , k_fake
-> nick
);
531 controlreply ( sender
, "Killed fake user %s " , k_fake
-> nick
);
532 controlwall ( NO_OPER
, NL_FAKEUSERS
, "Fake user %s ! %s @ %s ( %s ) removed by %s / %s " , k_fake
-> nick
,
533 k_fake
-> ident
, k_fake
-> host
, k_fake
-> realname
, (( nick
*) sender
)-> nick
, (( nick
*) sender
)-> authname
);
537 controlreply ( sender
, "No fakeuser with that nick exists" );
541 void reconnectfake ( void * details
)
542 //Called after the timeout period has expired since a fakeuser was killed, or on load
545 user_details
* u_details
= details
;
546 if ( u_details
-> schedule
)
547 kll_remove ( u_details
-> nick
); //Fakeuser was /kill'd
548 fake
= ll_add ( u_details
);
549 if ( u_details
-> schedule
)
556 if (!( sitchannel
= findchannel ( SIT_CHANNEL
)))
557 sitchannel
= createchannel ( SIT_CHANNEL
);
558 localjoinchannel ( fake
-> user
, sitchannel
);