]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands.cpp
Remove an extern, partly because it's unused, partly because it then gets shadowed...
[user/henk/code/inspircd.git] / src / commands.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd_config.h"
18 #include "inspircd.h"
19 #include "configreader.h"
20 #include <unistd.h>
21 #include <sys/errno.h>
22 #include <sys/ioctl.h>
23 #include <sys/utsname.h>
24 #include <cstdio>
25 #include <time.h>
26 #include <string>
27 #include <sstream>
28 #include <vector>
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #ifdef THREADED_DNS
33 #include <pthread.h>
34 #endif
35 #ifndef RUSAGE_SELF
36 #define   RUSAGE_SELF     0
37 #define   RUSAGE_CHILDREN     -1
38 #endif
39 #include "users.h"
40 #include "ctables.h"
41 #include "globals.h"
42 #include "modules.h"
43 #include "dynamic.h"
44 #include "wildcard.h"
45 #include "message.h"
46 #include "commands.h"
47 #include "mode.h"
48 #include "xline.h"
49 #include "inspstring.h"
50 #include "dnsqueue.h"
51 #include "helperfuncs.h"
52 #include "hashcomp.h"
53 #include "socketengine.h"
54 #include "typedefs.h"
55 #include "command_parse.h"
56
57 extern ServerConfig* Config;
58 extern InspIRCd* ServerInstance;
59
60 extern int MODCOUNT;
61 extern ModuleList modules;
62 extern FactoryList factory;
63 extern time_t TIME;
64
65 const long duration_m = 60;
66 const long duration_h = duration_m * 60;
67 const long duration_d = duration_h * 24;
68 const long duration_w = duration_d * 7;
69 const long duration_y = duration_w * 52;
70
71 extern user_hash clientlist;
72 extern chan_hash chanlist;
73
74 extern std::vector<userrec*> all_opers;
75 extern std::vector<userrec*> local_users;
76
77 // This table references users by file descriptor.
78 // its an array to make it VERY fast, as all lookups are referenced
79 // by an integer, meaning there is no need for a scan/search operation.
80 extern userrec* fd_ref_table[MAX_DESCRIPTORS];
81
82
83 void split_chlist(userrec* user, userrec* dest, const std::string &cl)
84 {
85         std::string line;
86         std::ostringstream prefix;
87         std::string::size_type start, pos, length;
88         
89         prefix << ":" << Config->ServerName << " 319 " << user->nick << " " << dest->nick << " :";
90         line = prefix.str();
91         
92         for (start = 0; pos = cl.find(' ', start); start = pos+1)
93         {
94                 length = (pos == std::string::npos) ? cl.length() : pos;
95                 
96                 if (line.length() + length - start > 510)
97                 {
98                         Write_NoFormat(user->fd, line.c_str());
99                         line = prefix.str();
100                 }
101                 
102                 if(pos == std::string::npos)
103                 {
104                         line += cl.substr(start, length - start);
105                         break;
106                 }
107                 else
108                 {
109                         line += cl.substr(start, length - start + 1);
110                 }
111         }
112         
113         if (line.length())
114         {
115                 Write_NoFormat(user->fd, line.c_str());
116         }
117 }
118
119 /* XXX - these really belong in helperfuncs perhaps -- w00t */
120 bool is_uline(const char* server)
121 {
122         if (!server)
123                 return false;
124         if (!*server)
125                 return true;
126
127         return (find(Config->ulines.begin(),Config->ulines.end(),server) != Config->ulines.end());
128 }
129
130 int operstrcmp(char* data,char* input)
131 {
132         int MOD_RESULT = 0;
133         FOREACH_RESULT(I_OnOperCompare,OnOperCompare(data,input))
134         log(DEBUG,"operstrcmp: %d",MOD_RESULT);
135         if (MOD_RESULT == 1)
136                 return 0;
137         if (MOD_RESULT == -1)
138                 return 1;
139         log(DEBUG,"strcmp fallback: '%s' '%s' %d",data,input,strcmp(data,input));
140         return strcmp(data,input);
141 }
142
143 long duration(const char* str)
144 {
145         char n_field[MAXBUF];
146         long total = 0;
147         n_field[0] = 0;
148
149         if ((!strchr(str,'s')) && (!strchr(str,'m')) && (!strchr(str,'h')) && (!strchr(str,'d')) && (!strchr(str,'w')) && (!strchr(str,'y')))
150         {
151                 std::string n = str;
152                 n += 's';
153                 return duration(n.c_str());
154         }
155         
156         for (char* i = (char*)str; *i; i++)
157         {
158                 // if we have digits, build up a string for the value in n_field,
159                 // up to 10 digits in size.
160                 if ((*i >= '0') && (*i <= '9'))
161                 {
162                         strlcat(n_field,i,10);
163                 }
164                 else
165                 {
166                         // we dont have a digit, check for numeric tokens
167                         switch (tolower(*i))
168                         {
169                                 case 's':
170                                         total += atoi(n_field);
171                                 break;
172
173                                 case 'm':
174                                         total += (atoi(n_field)*duration_m);
175                                 break;
176
177                                 case 'h':
178                                         total += (atoi(n_field)*duration_h);
179                                 break;
180
181                                 case 'd':
182                                         total += (atoi(n_field)*duration_d);
183                                 break;
184
185                                 case 'w':
186                                         total += (atoi(n_field)*duration_w);
187                                 break;
188
189                                 case 'y':
190                                         total += (atoi(n_field)*duration_y);
191                                 break;
192                         }
193                         n_field[0] = 0;
194                 }
195         }
196         // add trailing seconds
197         total += atoi(n_field);
198         
199         return total;
200 }
201
202 /* All other ircds when doing this check usually just look for a string of *@* or *. We're smarter than that, though. */
203
204 bool host_matches_everyone(const std::string &mask, userrec* user)
205 {
206         char buffer[MAXBUF];
207         char itrigger[MAXBUF];
208         long matches = 0;
209         
210         if (!Config->ConfValue(Config->config_data, "insane","trigger", 0, itrigger, MAXBUF))
211                 strlcpy(itrigger,"95.5",MAXBUF);
212         
213         if (Config->ConfValueBool(Config->config_data, "insane","hostmasks", 0))
214                 return false;
215         
216         for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
217         {
218                 strlcpy(buffer,u->second->ident,MAXBUF);
219                 charlcat(buffer,'@',MAXBUF);
220                 strlcat(buffer,u->second->host,MAXBUF);
221                 if (match(buffer,mask.c_str()))
222                         matches++;
223         }
224         float percent = ((float)matches / (float)clientlist.size()) * 100;
225         if (percent > (float)atof(itrigger))
226         {
227                 WriteOpers("*** \2WARNING\2: %s tried to set a G/K/E line mask of %s, which covers %.2f%% of the network!",user->nick,mask.c_str(),percent);
228                 return true;
229         }
230         return false;
231 }
232
233 bool ip_matches_everyone(const std::string &ip, userrec* user)
234 {
235         char itrigger[MAXBUF];
236         long matches = 0;
237         
238         if (!Config->ConfValue(Config->config_data, "insane","trigger",0,itrigger,MAXBUF))
239                 strlcpy(itrigger,"95.5",MAXBUF);
240         
241         if (Config->ConfValueBool(Config->config_data, "insane","ipmasks",0))
242                 return false;
243         
244         for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
245         {
246                 if (match((char*)inet_ntoa(u->second->ip4),ip.c_str()))
247                         matches++;
248         }
249         
250         float percent = ((float)matches / (float)clientlist.size()) * 100;
251         if (percent > (float)atof(itrigger))
252         {
253                 WriteOpers("*** \2WARNING\2: %s tried to set a Z line mask of %s, which covers %.2f%% of the network!",user->nick,ip.c_str(),percent);
254                 return true;
255         }
256         return false;
257 }
258
259 bool nick_matches_everyone(const std::string &nick, userrec* user)
260 {
261         char itrigger[MAXBUF];
262         long matches = 0;
263         
264         if (!Config->ConfValue(Config->config_data, "insane","trigger",0,itrigger,MAXBUF))
265                 strlcpy(itrigger,"95.5",MAXBUF);
266         
267         if (Config->ConfValueBool(Config->config_data, "insane","nickmasks",0))
268                 return false;
269
270         for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
271         {
272                 if (match(u->second->nick,nick.c_str()))
273                         matches++;
274         }
275         
276         float percent = ((float)matches / (float)clientlist.size()) * 100;
277         if (percent > (float)atof(itrigger))
278         {
279                 WriteOpers("*** \2WARNING\2: %s tried to set a Q line mask of %s, which covers %.2f%% of the network!",user->nick,nick.c_str(),percent);
280                 return true;
281         }
282         return false;
283 }