*** VERSION 5.2.0 ***
[NeonServV5.git] / src / cmd_neonserv_trace.c
1 /* cmd_neonserv_trace.c - NeonServ v5.2
2  * Copyright (C) 2011  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonserv.h"
19
20 #define NS_TRACE_CRITERIA_AUTHED  0x01
21 #define NS_TRACE_CRITERIA_NUMCHAN 0x02
22
23 struct neonserv_cmd_trace_criteria {
24     char *mask;
25     char *nick;
26     char *ident;
27     char *host;
28     char *account;
29     unsigned int flags : 4;
30     unsigned int authed : 1;
31     unsigned int used_channel : 5; //32 max
32     char *channel[10];
33     unsigned int numchannels;
34     unsigned int limit : 16;
35 };
36
37 CMD_BIND(neonserv_cmd_trace) {
38     //ok parse the criterias
39     struct neonserv_cmd_trace_criteria *criteria = malloc(sizeof(*criteria));
40     if (!criteria) {
41         perror("malloc() failed");
42         return;
43     }
44     memset(criteria, 0, sizeof(*criteria));
45     criteria->limit = 50;
46     int i, show_user = 0;
47     if(!stricmp(argv[0], "print")) {
48         show_user = 1;
49     }
50     for(i = 1; i < argc; i += 2) {
51         if(argc <= i+1) {
52             reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT");
53             return;
54         }
55         if(!stricmp(argv[i], "mask")) criteria->mask = argv[i+1];
56         else if(!stricmp(argv[i], "nick")) criteria->nick = argv[i+1];
57         else if(!stricmp(argv[i], "ident")) criteria->ident = argv[i+1];
58         else if(!stricmp(argv[i], "host")) criteria->host = argv[i+1];
59         else if(!stricmp(argv[i], "account")) criteria->account = argv[i+1];
60         else if(!stricmp(argv[i], "authed")) {
61             if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) {
62                 criteria->authed = 1;
63             } else if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) {
64                 criteria->authed = 0;
65             } else {
66                 reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[i+1]);
67                 return;
68             }
69             criteria->flags |= NS_TRACE_CRITERIA_AUTHED;
70         }
71         else if(!stricmp(argv[i], "channel")) criteria->channel[criteria->used_channel++] = argv[i+1];
72         else if(!stricmp(argv[i], "numchannels")) {
73             criteria->numchannels = atoi(argv[i+1]);
74             criteria->flags |= NS_TRACE_CRITERIA_NUMCHAN;
75         }
76         else if(!stricmp(argv[i], "limit")) {
77             criteria->limit = atoi(argv[i+1]);
78         }
79     }
80     char tmp[MAXLEN];
81     int matches = 0;
82     struct UserNode *cuser;
83     reply(getTextBot(), user, "NS_TRACE_HEADER");
84     for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) {
85         if(show_user && matches == criteria->limit) {
86             //too many
87             break;
88         }
89         if(criteria->mask) {
90             sprintf(tmp, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
91             if(match(criteria->mask, tmp)) continue;
92         }
93         if(criteria->nick && match(criteria->nick, cuser->nick)) continue;
94         if(criteria->ident && match(criteria->ident, cuser->ident)) continue;
95         if(criteria->host && match(criteria->host, cuser->host)) continue;
96         if(criteria->account && (!(cuser->flags & USERFLAG_ISAUTHED) || match(criteria->account, cuser->auth))) continue;
97         if((criteria->flags & NS_TRACE_CRITERIA_AUTHED) && (criteria->authed ^ (cuser->flags & USERFLAG_ISAUTHED))) continue;
98         if((criteria->flags & NS_TRACE_CRITERIA_NUMCHAN)) {
99             int ccount = 0;
100             struct ChanUser *chanuser;
101             for(chanuser = getUserChannels(cuser, NULL); chanuser; chanuser = getUserChannels(cuser, chanuser))
102                 ccount++;
103             if(ccount < criteria->numchannels)
104                 continue;
105         }
106         matches++;
107         //output
108         if(show_user) {
109             reply(getTextBot(), user, "%s!%s@%s %s", cuser->nick, cuser->ident, cuser->host, ((cuser->flags & USERFLAG_ISAUTHED) ? cuser->auth : "*"));
110         }
111     }
112     reply(getTextBot(), user, "NS_TABLE_COUNT", matches);
113 }