]>
jfr.im git - irc/quakenet/newserv.git/blob - glines/glines_commands.c
7ddb732a80589b1864d6f33ee1ee190288edfef8
4 #include "../lib/version.h"
5 #include "../control/control.h"
6 #include "../lib/irc_string.h"
7 #include "../lib/splitline.h"
8 #include "../lib/strlfunc.h"
9 #include "../core/nsmalloc.h"
10 #include "../irc/irc.h"
11 #include "../localuser/localuser.h"
12 #include "../localuser/localuserchannel.h"
14 #include "../trusts/trusts.h"
16 #define BLOCK_CHASE_MIN 5 /* seconds to chase nicknames in block without -c */
17 #define BLOCK_CHASE_MAX 1800 /* seconds to chase nicknames in block with -c */
21 static void registercommands ( int , void *);
22 static void deregistercommands ( int , void *);
24 static int parse_gline_flags ( nick
* sender
, const char * flagparam
, int * overridesanity
, int * overridelimit
, int * simulate
, int * chase
, int * coff
) {
35 if ( flagparam
[ 0 ] == '-' ) {
38 for ( pos
= flagparam
+ 1 ; * pos
; pos
++) {
64 controlreply ( sender
, "Invalid flag specified: %c " , * pos
);
68 static int glines_cmdblock ( void * source
, int cargc
, char ** cargv
) {
69 nick
* sender
= source
;
72 int hits
, duration
, id
;
73 int coff
, overridesanity
, overridelimit
, simulate
, chase
;
82 if (! parse_gline_flags ( sender
, cargv
[ 0 ], & overridesanity
, & overridelimit
, & simulate
, & chase
, & coff
))
88 duration
= durationtolong ( cargv
[ coff
+ 1 ]);
91 controlreply ( sender
, "Invalid duration specified." );
95 target
= getnickbynick ( cargv
[ coff
]);
98 ww
= whowas_chase ( cargv
[ coff
], chase
? BLOCK_CHASE_MAX
: BLOCK_CHASE_MIN
);
101 controlreply ( sender
, "Sorry, couldn't find that user. %s " , chase
? "" : " Use -c to chase whowas entries." );
107 controlreply ( sender
, "Found matching whowas record:" );
108 controlreply ( sender
, " %s " , whowas_format ( ww
));
110 ww
= whowas_fromnick ( target
, 1 );
116 if ( sender
!= target
&& ( IsService ( wnp
) || IsOper ( wnp
) || NickOnServiceServer ( wnp
))) {
117 controlreply ( sender
, "Target user ' %s ' is an oper or a service. Not setting G-Lines." , wnp
-> nick
);
121 rejoinline ( cargv
[ coff
+ 2 ], cargc
- coff
- 2 );
122 reason
= cargv
[ coff
+ 2 ];
124 snprintf ( creator
, sizeof ( creator
), "# %s " , sender
-> authname
);
126 glinebufinit (& gbuf
, 0 );
127 glinebufcommentv (& gbuf
, "BLOCK" , cargc
+ coff
- 1 , cargv
);
128 glinebufaddbywhowas (& gbuf
, ww
, 0 , creator
, reason
, getnettime () + duration
, getnettime (), getnettime () + duration
);
130 glinebufspew (& gbuf
, sender
);
132 if (! glinebufchecksane (& gbuf
, sender
, overridesanity
, overridelimit
)) {
133 glinebufabort (& gbuf
);
136 controlreply ( sender
, "G-Lines failed sanity checks. Not setting G-Lines." );
141 glinebufabort (& gbuf
);
144 controlreply ( sender
, "Simulation complete. Not setting G-Lines." );
148 glinebufcounthits (& gbuf
, & hits
, NULL
);
149 id
= glinebufcommit (& gbuf
, 1 );
151 controlwall ( NO_OPER
, NL_GLINES
, " %s BLOCK'ed user ' %s ! %s @ %s ' for %s with reason ' %s ' ( %d hits)" , controlid ( sender
),
152 wnp
-> nick
, wnp
-> ident
, wnp
-> host
-> name
-> content
,
153 longtoduration ( duration
, 0 ), reason
, hits
);
158 controlreply ( sender
, "Done. G-Line transaction ID: %d " , id
);
163 static int glines_cmdgline ( void * source
, int cargc
, char ** cargv
) {
164 nick
* sender
= source
;
165 int duration
, users
, channels
, id
;
168 int coff
, overridesanity
, overridelimit
, simulate
;
170 #if SNIRCD_VERSION < 140
172 #endif /* SNIRCD_VERSION */
177 if (! parse_gline_flags ( sender
, cargv
[ 0 ], & overridesanity
, & overridelimit
, & simulate
, NULL
, & coff
))
180 if ( cargc
< 3 + coff
)
185 duration
= durationtolong ( cargv
[ coff
+ 1 ]);
188 controlreply ( sender
, "Invalid duration specified." );
192 rejoinline ( cargv
[ coff
+ 2 ], cargc
- coff
- 2 );
193 reason
= cargv
[ coff
+ 2 ];
195 #if SNIRCD_VERSION < 140
196 gl
= findgline ( mask
);
199 /* warn opers that they can't modify this gline */
200 if ( gl
-> flags
& GLINE_ACTIVE
) {
201 controlreply ( sender
, "Active G-Line already exists on %s - unable to modify" , mask
);
205 controlreply ( sender
, "Reactivating existing gline on %s " , mask
);
207 #endif /* SNIRCD_VERSION */
209 snprintf ( creator
, sizeof ( creator
), "# %s " , sender
-> authname
);
211 glinebufinit (& gbuf
, 0 );
212 glinebufcommentv (& gbuf
, "GLINE" , cargc
+ coff
- 1 , cargv
);
214 if (! glinebufadd (& gbuf
, mask
, creator
, reason
, getnettime () + duration
, getnettime (), getnettime () + duration
)) {
215 controlreply ( sender
, "Invalid G-Line mask." );
219 glinebufspew (& gbuf
, sender
);
221 if (! glinebufchecksane (& gbuf
, sender
, overridesanity
, overridelimit
)) {
222 glinebufabort (& gbuf
);
223 controlreply ( sender
, "G-Lines failed sanity checks. Not setting G-Lines." );
228 glinebufabort (& gbuf
);
229 controlreply ( sender
, "Simulation complete. Not setting G-Lines." );
233 glinebufcounthits (& gbuf
, & users
, & channels
);
234 id
= glinebufcommit (& gbuf
, 1 );
236 controlwall ( NO_OPER
, NL_GLINES
, " %s GLINE'd mask ' %s ' for %s with reason ' %s ' (hits %d users/ %d channels)" ,
237 controlid ( sender
), mask
, longtoduration ( duration
, 0 ), reason
, users
, channels
);
239 controlreply ( sender
, "Done. G-Line transaction ID: %d " , id
);
244 static int glines_cmdsmartgline ( void * source
, int cargc
, char ** cargv
) {
245 nick
* sender
= source
;
248 char * p
, * user
, * host
;
249 struct irc_in_addr ip
;
252 int coff
, overridesanity
, overridelimit
, simulate
, id
;
260 if (! parse_gline_flags ( sender
, cargv
[ 0 ], & overridesanity
, & overridelimit
, & simulate
, NULL
, & coff
))
263 if ( cargc
< 3 + coff
)
266 origmask
= cargv
[ coff
];
268 if ( origmask
[ 0 ] == '#' || origmask
[ 0 ] == '&' || origmask
[ 0 ] == '$' ) {
269 controlreply ( sender
, "Please use \" gline \" for badchan or realname glines." );
273 duration
= durationtolong ( cargv
[ coff
+ 1 ]);
276 controlreply ( sender
, "Invalid duration specified." );
280 rejoinline ( cargv
[ coff
+ 2 ], cargc
- coff
- 2 );
281 reason
= cargv
[ coff
+ 2 ];
283 strncpy ( mask
, origmask
, sizeof ( mask
));
285 if ( strchr ( mask
, '!' )) {
286 controlreply ( sender
, "Use \" gline \" to place nick glines." );
290 p
= strchr ( mask
, '@' );
293 controlreply ( sender
, "Mask must contain a username (e.g. user@ip)." );
301 if ( strchr ( user
, '*' ) || strchr ( user
, '?' )) {
302 controlreply ( sender
, "Usernames may not contain wildcards." );
306 if (! ipmask_parse ( host
, & ip
, & bits
)) {
307 controlreply ( sender
, "Invalid CIDR mask." );
311 snprintf ( creator
, sizeof ( creator
), "# %s " , sender
-> authname
);
313 glinebufinit (& gbuf
, 0 );
314 glinebufcommentv (& gbuf
, "SMARTGLINE" , cargc
+ coff
- 1 , cargv
);
315 glinebufaddbyip (& gbuf
, user
, & ip
, 128 , 0 , creator
, reason
, getnettime () + duration
, getnettime (), getnettime () + duration
);
317 glinebufspew (& gbuf
, sender
);
319 if (! glinebufchecksane (& gbuf
, sender
, overridesanity
, overridelimit
)) {
320 glinebufabort (& gbuf
);
321 controlreply ( sender
, "G-Lines failed sanity checks. Not setting G-Lines." );
326 glinebufabort (& gbuf
);
327 controlreply ( sender
, "Simulation complete. Not setting G-Lines." );
331 glinebufcounthits (& gbuf
, & hits
, NULL
);
332 id
= glinebufcommit (& gbuf
, 1 );
334 controlwall ( NO_OPER
, NL_GLINES
, " %s SMARTGLINE'd mask ' %s ' for %s with reason ' %s ' ( %d hits)" ,
335 controlid ( sender
), cargv
[ 0 ], longtoduration ( duration
, 0 ), reason
, hits
);
337 controlreply ( sender
, "Done. G-Line transaction ID: %d " , id
);
342 static int glines_cmdungline ( void * source
, int cargc
, char ** cargv
) {
343 nick
* sender
= source
;
349 gl
= findgline ( cargv
[ 0 ]);
352 controlreply ( sender
, "No such G-Line." );
356 if (!( gl
-> flags
& GLINE_ACTIVE
)) {
357 controlreply ( sender
, "G-Line was already deactivated." );
361 gline_deactivate ( gl
, 0 , 1 );
363 controlwall ( NO_OPER
, NL_GLINES
, " %s UNGLINE'd mask ' %s '" , controlid ( sender
), cargv
[ 0 ]);
365 controlreply ( sender
, "G-Line deactivated." );
370 static int glines_cmddestroygline ( void * source
, int cargc
, char ** cargv
) {
371 nick
* sender
= source
;
377 gl
= findgline ( cargv
[ 0 ]);
380 controlreply ( sender
, "No such G-Line." );
384 gline_destroy ( gl
, 0 , 1 );
386 controlwall ( NO_OPER
, NL_GLINES
, " %s DESTROYGLINE'd mask ' %s '" , controlid ( sender
), cargv
[ 0 ]);
388 controlreply ( sender
, "G-Line destroyed." );
393 static int glines_cmdclearchan ( void * source
, int cargc
, char ** cargv
) {
394 nick
* sender
= source
;
397 char * reason
= "Clearing channel." ;
398 int mode
, duration
, i
, slot
, hits
, id
;
399 int coff
, overridesanity
, overridelimit
, simulate
;
407 if (! parse_gline_flags ( sender
, cargv
[ 0 ], & overridesanity
, & overridelimit
, & simulate
, NULL
, & coff
))
410 if ( cargc
< 2 + coff
)
413 cp
= findchannel ( cargv
[ coff
]);
416 controlreply ( sender
, "Couldn't find that channel." );
420 if ( strcmp ( cargv
[ coff
+ 1 ], "kick" ) == 0 )
422 else if ( strcmp ( cargv
[ coff
+ 1 ], "kill" ) == 0 )
424 else if ( strcmp ( cargv
[ coff
+ 1 ], "gline" ) == 0 )
426 else if ( strcmp ( cargv
[ coff
+ 1 ], "glineall" ) == 0 )
431 if ( mode
== 0 || mode
== 1 ) {
433 rejoinline ( cargv
[ coff
+ 2 ], cargc
- coff
- 2 );
434 reason
= cargv
[ coff
+ 2 ];
437 if ( cargc
< 3 + coff
)
440 duration
= durationtolong ( cargv
[ coff
+ 2 ]);
443 controlreply ( sender
, "Invalid duration specified." );
447 if ( cargc
>= 4 + coff
) {
448 rejoinline ( cargv
[ coff
+ 3 ], cargc
- coff
- 3 );
449 reason
= cargv
[ coff
+ 3 ];
453 array_init (& victims
, sizeof ( nick
*));
455 /* we need to make a list of the channel users here because
456 * kicking/killing them will affect their position in the channel's
458 for ( i
= 0 ; i
< cp
-> users
-> hashsize
; i
++) {
459 if ( cp
-> users
-> content
[ i
] == nouser
)
462 np
= getnickbynumeric ( cp
-> users
-> content
[ i
]);
467 if ( IsService ( np
) || IsOper ( np
) || NickOnServiceServer ( np
))
470 slot
= array_getfreeslot (& victims
);
471 ((( nick
**) victims
. content
)[ slot
]) = np
;
474 snprintf ( creator
, sizeof ( creator
), "# %s " , sender
-> authname
);
476 glinebufinit (& gbuf
, 0 );
477 glinebufcommentv (& gbuf
, "CLEARCHAN" , cargc
+ coff
- 1 , cargv
);
479 for ( i
= 0 ; i
< victims
. cursi
; i
++) {
480 np
= (( nick
**) victims
. content
)[ i
];
485 controlreply ( sender
, "user: %s ! %s @ %s r( %s )" , np
-> nick
, np
-> ident
, np
-> host
-> name
-> content
, np
-> realname
-> name
-> content
);
487 localkickuser ( NULL
, cp
, np
, reason
);
492 controlreply ( sender
, "user: %s ! %s @ %s r( %s )" , np
-> nick
, np
-> ident
, np
-> host
-> name
-> content
, np
-> realname
-> name
-> content
);
494 killuser ( NULL
, np
, " %s " , reason
);
502 glinebufaddbynick (& gbuf
, np
, 0 , creator
, reason
, getnettime () + duration
, getnettime (), getnettime () + duration
);
509 if ( mode
!= 0 && mode
!= 1 ) {
510 glinebufspew (& gbuf
, sender
);
512 if (! glinebufchecksane (& gbuf
, sender
, overridesanity
, overridelimit
)) {
513 glinebufabort (& gbuf
);
514 controlreply ( sender
, "G-Line failed sanity checks. Not setting G-Line." );
520 glinebufabort (& gbuf
);
521 controlreply ( sender
, "Simulation complete. Not clearing channel." );
525 glinebufmerge (& gbuf
);
526 glinebufcounthits (& gbuf
, & hits
, NULL
);
527 id
= glinebufcommit (& gbuf
, 1 );
529 array_free (& victims
);
531 if ( mode
== 0 || mode
== 1 ) {
532 controlwall ( NO_OPER
, NL_GLINES
, " %s CLEARCHAN'd channel ' %s ' with mode ' %s ' and reason ' %s '" ,
533 controlid ( sender
), cp
-> index
-> name
-> content
, cargv
[ 1 ], reason
);
534 controlreply ( sender
, "Done." );
536 controlwall ( NO_OPER
, NL_GLINES
, " %s CLEARCHAN'd channel ' %s ' with mode ' %s ', duration %s and reason ' %s ' ( %d hits)" ,
537 controlid ( sender
), cp
-> index
-> name
-> content
, cargv
[ 1 ], longtoduration ( duration
, 0 ), reason
, hits
);
538 controlreply ( sender
, "Done. G-Line transaction ID: %d " , id
);
544 static int glines_cmdtrustgline ( void * source
, int cargc
, char ** cargv
) {
545 nick
* sender
= source
;
549 int coff
, overridesanity
, overridelimit
, simulate
, id
;
558 if (! parse_gline_flags ( sender
, cargv
[ 0 ], & overridesanity
, & overridelimit
, & simulate
, NULL
, & coff
))
561 if ( cargc
< 4 + coff
)
564 tg
= tg_strtotg ( cargv
[ coff
]);
567 controlreply ( sender
, "Invalid trust group specified." );
571 if (!( tg
-> flags
& TRUST_RELIABLE_USERNAME
)) {
572 controlreply ( sender
, "Sorry, that trust group does not have the \" reliable username \" flag." );
576 duration
= durationtolong ( cargv
[ coff
+ 2 ]);
579 controlreply ( sender
, "Invalid duration specified." );
583 rejoinline ( cargv
[ coff
+ 3 ], cargc
- coff
- 3 );
584 reason
= cargv
[ coff
+ 3 ];
586 snprintf ( creator
, sizeof ( creator
), "# %s " , sender
-> authname
);
588 glinebufinit (& gbuf
, 0 );
589 glinebufcommentv (& gbuf
, "TRUSTGLINE" , cargc
+ coff
- 1 , cargv
);
591 for ( th
= tg
-> hosts
; th
; th
= th
-> next
) {
592 snprintf ( mask
, sizeof ( mask
), "*! %s @ %s " , cargv
[ 1 ], CIDRtostr ( th
-> ip
, th
-> bits
));
593 glinebufadd (& gbuf
, mask
, creator
, reason
, getnettime () + duration
, getnettime (), getnettime () + duration
);
596 glinebufspew (& gbuf
, sender
);
598 if (! glinebufchecksane (& gbuf
, sender
, overridesanity
, overridelimit
)) {
599 glinebufabort (& gbuf
);
600 controlreply ( sender
, "G-Line failed sanity checks. Not setting G-Line." );
605 glinebufabort (& gbuf
);
606 controlreply ( sender
, "Simulation complete. Not setting G-Lines." );
610 glinebufcounthits (& gbuf
, & hits
, NULL
);
611 id
= glinebufcommit (& gbuf
, 1 );
613 controlwall ( NO_OPER
, NL_GLINES
, " %s TRUSTGLINE'd user ' %s ' on trust group ' %s ' for %s with reason ' %s ' ( %d hits)" ,
614 controlid ( sender
), cargv
[ 1 ], tg
-> name
-> content
, longtoduration ( duration
, 0 ), reason
, hits
);
616 controlreply ( sender
, "Done. G-Line transaction ID: %d " , id
);
621 static int glines_cmdtrustungline ( void * source
, int cargc
, char ** cargv
) {
622 nick
* sender
= source
;
632 tg
= tg_strtotg ( cargv
[ 0 ]);
635 controlreply ( sender
, "Invalid trust group specified." );
639 if (!( tg
-> flags
& TRUST_RELIABLE_USERNAME
)) {
640 controlreply ( sender
, "Sorry, that trust group does not have the \" reliable username \" flag." );
646 for ( th
= tg
-> hosts
; th
; th
= th
-> next
) {
647 snprintf ( mask
, sizeof ( mask
), "*! %s @ %s " , cargv
[ 1 ], CIDRtostr ( th
-> ip
, th
-> bits
));
649 gl
= findgline ( mask
);
651 if ( gl
&& ( gl
-> flags
& GLINE_ACTIVE
)) {
652 gline_deactivate ( gl
, 0 , 1 );
657 controlwall ( NO_OPER
, NL_GLINES
, " %s TRUSTUNGLINE'd user ' %s ' on trust group ' %s ' ( %d G-Lines deactivated)" ,
658 controlid ( sender
), cargv
[ 1 ], tg
-> name
-> content
, count
);
660 controlreply ( sender
, "Done." );
665 static int glines_cmdglstats ( void * source
, int cargc
, char ** cargv
) {
666 nick
* sender
= ( nick
*) source
;
668 time_t curtime
= getnettime ();
669 int glinecount
= 0 , hostglinecount
= 0 , ipglinecount
= 0 , badchancount
= 0 , rnglinecount
= 0 ;
670 int deactivecount
= 0 , activecount
= 0 ;
672 for ( gl
= glinelist
; gl
; gl
= next
) {
675 if ( gl
-> lifetime
<= curtime
) {
678 } else if ( gl
-> expire
<= curtime
) {
679 gl
-> flags
&= ~ GLINE_ACTIVE
;
682 if ( gl
-> flags
& GLINE_ACTIVE
) {
688 if ( gl
-> flags
& GLINE_IPMASK
)
690 else if ( gl
-> flags
& GLINE_HOSTMASK
)
692 else if ( gl
-> flags
& GLINE_REALNAME
)
694 else if ( gl
-> flags
& GLINE_BADCHAN
)
699 controlreply ( sender
, "Total G-Lines set: %d " , glinecount
);
700 controlreply ( sender
, "Hostmask G-Lines: %d " , hostglinecount
);
701 controlreply ( sender
, "IPMask G-Lines: %d " , ipglinecount
);
702 controlreply ( sender
, "Channel G-Lines: %d " , badchancount
);
703 controlreply ( sender
, "Realname G-Lines: %d " , rnglinecount
);
705 controlreply ( sender
, "Active G-Lines: %d " , activecount
);
706 controlreply ( sender
, "Inactive G-Lines: %d " , deactivecount
);
708 /* TODO show top 10 creators here */
709 /* TODO show unique creators count */
710 /* TODO show glines per create %8.1f", ccount?((float)gcount/(float)ccount):0 */
714 static int glines_cmdglist ( void * source
, int cargc
, char ** cargv
) {
715 nick
* sender
= ( nick
*) source
;
717 time_t curtime
= time ( NULL
);
722 char expirestr
[ 250 ], idstr
[ 250 ];
724 if ( cargc
< 1 || ( cargc
== 1 && cargv
[ 0 ][ 0 ] == '-' )) {
725 controlreply ( sender
, "Syntax: glist [-flags] <mask>" );
726 controlreply ( sender
, "Valid flags are:" );
727 controlreply ( sender
, "-c: Count G-Lines." );
728 controlreply ( sender
, "-f: Find G-Lines active on <mask>." );
729 controlreply ( sender
, "-x: Find G-Lines matching <mask> exactly." );
730 controlreply ( sender
, "-R: Find G-lines on realnames." );
731 controlreply ( sender
, "-o: Search for glines by owner." );
732 controlreply ( sender
, "-r: Search for glines by reason." );
733 controlreply ( sender
, "-i: Include inactive glines." );
746 flags
|= GLIST_COUNT
;
754 flags
|= GLIST_EXACT
;
758 flags
|= GLIST_REASON
;
761 flags
|= GLIST_OWNER
;
765 flags
|= GLIST_REALNAME
;
769 flags
|= GLIST_INACTIVE
;
773 controlreply ( sender
, "Invalid flag ' %c '." , * ch
);
782 if (( flags
& ( GLIST_EXACT
| GLIST_FIND
)) == ( GLIST_EXACT
| GLIST_FIND
)) {
783 controlreply ( sender
, "You cannot use -x and -f flags together." );
787 if (!( flags
& GLIST_COUNT
))
788 controlreply ( sender
, "%-50s %-19s %-15s %-25s %s " , "Mask:" , "Expires in:" , "Transaction ID:" , "Creator:" , "Reason:" );
790 gline
* searchgl
= makegline ( mask
);
793 controlreply ( sender
, "Invalid G-line mask specified." );
797 for ( gl
= glinelist
; gl
; gl
= next
) {
800 if ( gl
-> lifetime
<= curtime
) {
803 } else if ( gl
-> expire
<= curtime
) {
804 gl
-> flags
&= ~ GLINE_ACTIVE
;
807 if (!( gl
-> flags
& GLINE_ACTIVE
)) {
808 if (!( flags
& GLIST_INACTIVE
)) {
813 if ( flags
& GLIST_REALNAME
) {
814 if (!( gl
-> flags
& GLINE_REALNAME
))
816 if ( flags
& GLIST_EXACT
) {
817 if (! glineequal ( searchgl
, gl
))
819 } else if ( flags
& GLIST_FIND
) {
820 if (! gline_match_mask ( gl
, searchgl
))
823 if (! match2strings ( mask
, glinetostring ( gl
)))
827 if ( gl
-> flags
& GLINE_REALNAME
)
830 if ( flags
& GLIST_REASON
) {
831 if ( flags
& GLIST_EXACT
) {
832 if (! gl
-> reason
|| ircd_strcmp ( mask
, gl
-> reason
-> content
) != 0 )
834 } else if ( flags
& GLIST_FIND
) {
835 if (! gl
-> reason
|| ! match2strings ( gl
-> reason
-> content
, mask
))
837 } else if (! gl
-> reason
|| ! match2strings ( mask
, gl
-> reason
-> content
))
839 } else if ( flags
& GLIST_OWNER
) {
840 if ( flags
& GLIST_EXACT
) {
841 if (! gl
-> creator
|| ircd_strcmp ( mask
, gl
-> creator
-> content
) != 0 )
843 } else if ( flags
& GLIST_FIND
) {
844 if (! gl
-> creator
|| ! match2strings ( gl
-> creator
-> content
, mask
))
846 } else if (! gl
-> creator
|| ! match2strings ( mask
, gl
-> creator
-> content
))
849 if ( flags
& GLIST_EXACT
) {
850 if (! glineequal ( searchgl
, gl
))
852 } else if ( flags
& GLIST_FIND
) {
853 if (! gline_match_mask ( gl
, searchgl
))
856 if (! match2strings ( mask
, glinetostring ( gl
)))
862 if ( count
== limit
&& !( flags
& GLIST_COUNT
))
863 controlreply ( sender
, "More than %d matches, list truncated." , limit
);
867 if (!( flags
& GLIST_COUNT
) && count
< limit
) {
868 snprintf ( expirestr
, sizeof ( expirestr
), " %s " , glinetostring ( gl
));
869 snprintf ( idstr
, sizeof ( idstr
), " %d " , gl
-> glinebufid
);
870 controlreply ( sender
, " %s %-49s %-19s %-15s %-25s %s " ,
871 ( gl
-> flags
& GLINE_ACTIVE
) ? "+" : "-" ,
873 ( gl
-> flags
& GLINE_ACTIVE
) ? ( char *) longtoduration ( gl
-> expire
- curtime
, 0 ) : "<inactive>" ,
874 gl
-> glinebufid
? idstr
: "" ,
875 gl
-> creator
? gl
-> creator
-> content
: "" ,
876 gl
-> reason
? gl
-> reason
-> content
: "" );
880 controlreply ( sender
, " %s%d G-Line %s found." , ( flags
& GLIST_COUNT
) ? "" : "End of list - " , count
, count
== 1 ? "" : "s" );
885 static int glines_cmdglinelog ( void * source
, int cargc
, char ** cargv
) {
886 nick
* sender
= source
;
898 controlreply ( sender
, "Invalid log ID." );
903 controlreply ( sender
, "Time ID G-Lines User Hits Channel Hits Comment" );
905 for ( i
= 0 ; i
< MAXGLINELOG
; i
++) {
906 gbl
= glinebuflog
[( i
+ glinebuflogoffset
+ 1 ) % MAXGLINELOG
];
911 if ( id
== 0 || gbl
-> id
== id
) {
914 for ( gl
= gbl
-> glines
; gl
; gl
= gl
-> next
)
917 strftime ( timebuf
, sizeof ( timebuf
), " %d / %m / %y %H : %M : %S " , localtime (( gbl
-> amend
) ? & gbl
-> amend
: & gbl
-> commit
));
918 strncat ( timebuf
, ( gbl
-> amend
) ? "*" : " " , sizeof ( timebuf
));
919 controlreply ( sender
, "%-20s %-10d %-10d %-15d %-15d %s " , timebuf
, gbl
-> id
, count
, gbl
-> userhits
, gbl
-> channelhits
, gbl
-> comment
? gbl
-> comment
-> content
: "(no comment)" );
922 if ( id
!= 0 && gbl
-> id
== id
) {
923 glinebufspew ( gbl
, sender
);
924 controlreply ( sender
, "Done." );
930 controlreply ( sender
, "Done." );
932 controlreply ( sender
, "Log entry for ID %d not found." , id
);
938 static int glines_cmdglineundo ( void * source
, int cargc
, char ** cargv
) {
939 nick
* sender
= source
;
947 if ( id
== 0 || ! glinebufundo ( id
)) {
948 controlreply ( sender
, "Invalid log ID." );
952 controlreply ( sender
, "Done." );
957 static int glines_cmdsyncglines ( void * source
, int cargc
, char ** cargv
) {
958 nick
* sender
= source
;
964 for ( gl
= glinelist
; gl
; gl
= gl
-> next
) {
969 controlwall ( NO_OPER
, NL_GLINES
, " %s SYNCGLINE'd %d G-Lines." ,
970 controlid ( sender
), count
);
972 controlreply ( sender
, "Done." );
977 static int glines_cmdcleanupglines ( void * source
, int cargc
, char ** cargv
) {
978 nick
* sender
= source
;
986 for ( pnext
= & glinelist
; * pnext
;) {
989 /* Remove inactivate glines that have been last changed more than a week ago */
990 if (!( gl
-> flags
& GLINE_ACTIVE
) && gl
-> lastmod
< now
- 7 * 24 * 60 * 60 ) {
991 gline_destroy ( gl
, 0 , 1 );
994 pnext
= &((* pnext
)-> next
);
1001 controlwall ( NO_OPER
, NL_GLINES
, " %s CLEANUPGLINES'd %d G-Lines." ,
1002 controlid ( sender
), count
);
1004 controlreply ( sender
, "Done." );
1009 static int commandsregistered
;
1011 static void registercommands ( int hooknum
, void * arg
) {
1012 if ( commandsregistered
)
1014 commandsregistered
= 1 ;
1016 registercontrolhelpcmd ( "block" , NO_OPER
, 4 , glines_cmdblock
, "Usage: block ?flags? <nick> <duration> <reason> \n Sets a gline using an appropriate mask given the user's nickname. \n Flags can be one or more of: \n -f - bypass sanity checks \n -l - bypass hit limits \n -S - simulate who the glines would hit \n -c - chase nick across quits/kills/nick changes" );
1017 registercontrolhelpcmd ( "gline" , NO_OPER
, 4 , glines_cmdgline
, "Usage: gline ?flags? <mask> <duration> <reason> \n Sets a gline. \n Flags can be one or more of: \n -f - bypass sanity checks \n -l - bypass hit limits \n -S - simulate who the glines would hit" );
1018 registercontrolhelpcmd ( "smartgline" , NO_OPER
, 4 , glines_cmdsmartgline
, "Usage: smartgline ?flags? <user@host> <duration> <reason> \n Sets a gline. Automatically adjusts the mask depending on whether the specified mask is trusted. \n Flags can be one or more of: \n -f - bypass sanity checks \n -l - bypass hit limits \n -S - simulate who the glines would hit" );
1019 registercontrolhelpcmd ( "ungline" , NO_OPER
, 1 , glines_cmdungline
, "Usage: ungline <mask> \n Deactivates a gline." );
1020 registercontrolhelpcmd ( "destroygline" , NO_DEVELOPER
, 1 , glines_cmddestroygline
, "Usage: destroygline <mask> \n Destroys a gline." );
1021 registercontrolhelpcmd ( "clearchan" , NO_OPER
, 5 , glines_cmdclearchan
, "Usage: clearchan ?flags? <#channel> <how> <duration> ?reason? \n Clears a channel. \n how can be one of: \n kick - Kicks users. \n kill - Kills users. \n gline - Glines non-authed users (using an appropriate mask). \n glineall - Glines users. \n Duration is only valid when glining users. Reason defaults to \" Clearing channel. \" . \n Flags (for glines) can be one or more of: \n -f - bypass sanity checks \n -l - bypass hit limits \n -S - simulate who the glines would hit" );
1022 registercontrolhelpcmd ( "trustgline" , NO_OPER
, 5 , glines_cmdtrustgline
, "Usage: trustgline ?flags? <#id|name> <user> <duration> <reason> \n Sets a gline on the specified username for each host in the specified trust group. The username may contain wildcards. \n Flags can be one or more of: \n -f - bypass sanity checks \n -l - bypass hit limits \n -S - simulate who the glines would hit" );
1023 registercontrolhelpcmd ( "trustungline" , NO_OPER
, 2 , glines_cmdtrustungline
, "Usage: trustungline <#id|name> <user> \n Removes a gline that was previously set with trustgline." );
1024 registercontrolhelpcmd ( "glstats" , NO_OPER
, 0 , glines_cmdglstats
, "Usage: glstat \n Shows statistics about G-Lines." );
1025 registercontrolhelpcmd ( "glist" , NO_OPER
, 2 , glines_cmdglist
, "Usage: glist [-flags] <mask> \n Lists matching G-Lines. \n Valid flags are: \n -c: Count G-Lines. \n -f: Find G-Lines active on <mask>. \n -x: Find G-Lines matching <mask> exactly. \n -R: Find G-lines on realnames. \n -o: Search for glines by owner. \n -r: Search for glines by reason. \n -i: Include inactive glines." );
1026 registercontrolhelpcmd ( "glinelog" , NO_OPER
, 1 , glines_cmdglinelog
, "Usage: glinelog ?id? \n Shows information about previous gline transactions." );
1027 registercontrolhelpcmd ( "glineundo" , NO_OPER
, 1 , glines_cmdglineundo
, "Usage: glineundo ?id? \n Undoes a gline transaction." );
1028 registercontrolhelpcmd ( "syncglines" , NO_DEVELOPER
, 0 , glines_cmdsyncglines
, "Usage: syncglines \n Sends all G-Lines to all other servers." );
1029 registercontrolhelpcmd ( "cleanupglines" , NO_DEVELOPER
, 0 , glines_cmdcleanupglines
, "Usage: cleanupglines \n Destroys all deactivated G-Lines." );
1032 static void deregistercommands ( int hooknum
, void * arg
) {
1033 if (! commandsregistered
)
1035 commandsregistered
= 0 ;
1037 deregistercontrolcmd ( "block" , glines_cmdblock
);
1038 deregistercontrolcmd ( "gline" , glines_cmdgline
);
1039 deregistercontrolcmd ( "smartgline" , glines_cmdsmartgline
);
1040 deregistercontrolcmd ( "ungline" , glines_cmdungline
);
1041 deregistercontrolcmd ( "destroygline" , glines_cmddestroygline
);
1042 deregistercontrolcmd ( "clearchan" , glines_cmdclearchan
);
1043 deregistercontrolcmd ( "trustgline" , glines_cmdtrustgline
);
1044 deregistercontrolcmd ( "trustungline" , glines_cmdtrustungline
);
1045 deregistercontrolcmd ( "glstats" , glines_cmdglstats
);
1046 deregistercontrolcmd ( "glist" , glines_cmdglist
);
1047 deregistercontrolcmd ( "glinelog" , glines_cmdglinelog
);
1048 deregistercontrolcmd ( "glineundo" , glines_cmdglineundo
);
1049 deregistercontrolcmd ( "syncglines" , glines_cmdsyncglines
);
1050 deregistercontrolcmd ( "cleanupglines" , glines_cmdcleanupglines
);
1054 registerhook ( HOOK_TRUSTS_DB_LOADED
, registercommands
);
1055 registerhook ( HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
1058 registercommands ( 0 , NULL
);
1062 deregisterhook ( HOOK_TRUSTS_DB_LOADED
, registercommands
);
1063 deregisterhook ( HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
1065 deregistercommands ( 0 , NULL
);