1 /* tools.c - NeonServ v5.6
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
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.
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.
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/>.
21 #include "ClientSocket.h"
24 static const struct default_language_entry msgtab[] = {
25 {"TIME_MASK_2_ITEMS", "%s and %s"}, /* {ARGS: "2 days", "1 hour"} */
26 {"TIME_MASK_3_ITEMS", "%s, %s and %s"}, /* {ARGS: "2 days", "1 hour", "20 minutes"} */
27 {"TIME_YEAR", "year"},
28 {"TIME_YEARS", "years"},
29 {"TIME_MONTH", "month"},
30 {"TIME_MONTHS", "months"},
31 {"TIME_WEEK", "week"},
32 {"TIME_WEEKS", "weeks"},
34 {"TIME_DAYS", "days"},
35 {"TIME_HOUR", "hour"},
36 {"TIME_HOURS", "hours"},
37 {"TIME_MINUTE", "minute"},
38 {"TIME_MINUTES", "minutes"},
39 {"TIME_SECOND", "second"},
40 {"TIME_SECONDS", "seconds"},
44 /* copied from IRCU 2.10.12 match.c */
46 * Compare if a given string (name) matches the given
47 * mask (which can contain wild cards: '*' - match any
48 * number of chars, '?' - match any single character.
53 * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
54 * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
56 int match(const char *mask, const char *name)
58 const char *m = mask, *n = name;
59 const char *m_tmp = mask, *n_tmp = name;
62 for (;;) switch (*m) {
76 /* allow escaping to force capitalization */
81 for (star_p = 0; ; m++) {
92 else if (*m == '\\') {
96 for (n_tmp = n; *n && *n != *m; n++) ;
99 for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
102 /* and fall through */
106 if (tolower(*m) != tolower(*n))
116 struct Table *table_init(int width, int length, int flags) {
118 struct Table *table = malloc(sizeof(*table));
119 table->contents = malloc(length * sizeof(*table->contents));
120 for(row = 0; row < length; row++) {
121 table->contents[row] = calloc(width, sizeof(*table->contents[row]));
123 table->length = length;
124 table->width = width;
125 table->flags = flags;
126 table->col_flags = calloc(width, sizeof(int));
128 table->maxwidth = calloc(width, sizeof(int));
129 table->table_lines = NULL;
133 int table_add(struct Table *table, char **entry) {
135 if(table->entrys == table->length) return 0;
136 for(col = 0; col < table->width; col++) {
137 table->contents[table->entrys][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
138 if(table->contents[table->entrys][col])
139 table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
140 if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
141 table->maxwidth[col] = strlen(entry[col]);
147 int table_change(struct Table *table, int row, char **entry) {
149 if(row >= table->length) return 0;
150 for(col = 0; col < table->width; col++) {
151 if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
152 free(table->contents[row][col]);
153 table->contents[row][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
154 if(table->contents[row][col])
155 table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
156 if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
157 table->maxwidth[col] = strlen(entry[col]);
162 int table_change_field(struct Table *table, int row, int col, char *entry) {
163 if(row >= table->length) return 0;
164 if(col >= table->width) return 0;
165 if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
166 free(table->contents[row][col]);
167 table->contents[row][col] = (((table->flags & TABLE_FLAG_USE_POINTER) || !entry) ? entry : strdup(entry));
168 if(table->contents[row][col])
169 table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
170 if(entry && strlen(entry) > table->maxwidth[col])
171 table->maxwidth[col] = strlen(entry);
175 int table_set_bold(struct Table *table, int collum, int bold) {
177 table->col_flags[collum] |= TABLE_FLAG_COL_BOLD;
179 table->col_flags[collum] &= ~TABLE_FLAG_COL_BOLD;
183 char **table_end(struct Table *table) {
184 int row, col, tablewidth = 0, pos,i,j,k;
185 if(!table->entrys) return NULL;
186 for(col = 0; col < table->width; col++) {
187 tablewidth += table->maxwidth[col]+1;
188 if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
191 table->table_lines = malloc(table->entrys * sizeof(table->table_lines));
192 for(row = 0; row < table->entrys; row++) {
193 table->table_lines[row] = malloc(tablewidth * sizeof(*table->table_lines[row]));
195 for(col = 0; col < table->width; col++) {
196 if(!(table->col_flags[col] & TABLE_FLAG_COL_CONTENTS)) continue;
197 if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
198 table->table_lines[row][pos++] = '\002';
201 if(table->contents[row][col]) {
202 for(; i < strlen(table->contents[row][col]); i++) {
203 table->table_lines[row][pos++] = table->contents[row][col][i];
204 if(table->contents[row][col][i] == '\002') j++;
205 else if(table->contents[row][col][i] == '\003') {
207 for(k = 1; k <= 2; k++) {
208 if(isdigit(table->contents[row][col][i+k]))
215 } else if(table->col_flags[col] & TABLE_FLAG_COL_SKIP_NULL)
218 if(col < table->width-1) {
219 for(;i < table->maxwidth[col]; i++) {
220 table->table_lines[row][pos++] = ' ';
222 table->table_lines[row][pos++] = ' ';
224 table->table_lines[row][pos++] = '\0';
226 if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
227 table->table_lines[row][pos++] = '\002';
230 return table->table_lines;
233 void table_free(struct Table *table) {
235 for(row = 0; row < table->length; row++) {
236 if(!(table->flags & TABLE_FLAG_USE_POINTER) && table->entrys > row) {
237 for(col = 0; col < table->width; col++) {
238 if(table->contents[row][col])
239 free(table->contents[row][col]);
242 free(table->contents[row]);
244 free(table->contents);
245 free(table->col_flags);
246 free(table->maxwidth);
247 if(table->table_lines) {
248 for(row = 0; row < table->entrys; row++) {
249 free(table->table_lines[row]);
251 free(table->table_lines);
256 char* timeToStr(struct UserNode *user, int seconds, int items, char *buf) {
257 char item[items][MAXLEN];
259 if(citem != items && seconds >= 31536000) { //60*60*24*365 = 31536000
261 tmp = seconds / 31536000;
262 sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_YEAR" : "TIME_YEARS"));
263 seconds -= tmp * 31536000;
265 if(citem != items && seconds >= 86400) { //60*60*24 = 86400
266 tmp = seconds / 86400;
267 sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_DAY" : "TIME_DAYS"));
268 seconds -= tmp * 86400;
270 if(citem != items && seconds >= 3600) { //60*60 = 3600
271 tmp = seconds / 3600;
272 sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_HOUR" : "TIME_HOURS"));
273 seconds -= tmp * 3600;
275 if(citem != items && seconds >= 60) {
277 sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_MINUTE" : "TIME_MINUTES"));
280 if(citem != items && seconds >= 1) {
281 sprintf(item[citem++], "%d %s", seconds, get_language_string(user, seconds == 1 ? "TIME_SECOND" : "TIME_SECONDS"));
284 build_language_string(user, buf, "TIME_MASK_2_ITEMS", item[0], item[1]);
285 } else if(citem == 3) {
286 build_language_string(user, buf, "TIME_MASK_3_ITEMS", item[0], item[1], item[2]);
289 for(i = 0; i < citem; i++) {
290 for(ii = 0; ii < strlen(item[i]); ii++) {
291 buf[p++] = item[i][ii];
295 buf[(p ? p-1 : 0)] = '\0';
300 int strToTime(struct UserNode *user, char *str) {
302 * y = year = 365 days
303 * M = month = 30 days
310 int total_time = 0, cvalue;
312 int unit_multiplikator;
315 while(*p && !isdigit(*p)) //skip leading chars
318 while(*p && isdigit(*p)) //get the value
322 cvalue = isdigit(*str) ? atoi(str) : 0;
324 while(*p == ' ') //skip spaces
327 while(*p && !isdigit(*p)) //get the unit
331 if(p - str > 1) { //unit has more than one char
332 if(!stricmp(str, "year") || !stricmp(str, "year") || !stricmp(str, get_language_string(user, "TIME_YEAR")) || !stricmp(str, get_language_string(user, "TIME_YEARS")))
333 unit_multiplikator = 31536000; //60*60*24*365 = 31536000
334 else if(!stricmp(str, "month") || !stricmp(str, "months") || !stricmp(str, get_language_string(user, "TIME_MONTH")) || !stricmp(str, get_language_string(user, "TIME_MONTHS")))
335 unit_multiplikator = 2592000; //60*60*24*30 = 2592000
336 else if(!stricmp(str, "week") || !stricmp(str, "weeks") || !stricmp(str, get_language_string(user, "TIME_WEEK")) || !stricmp(str, get_language_string(user, "TIME_WEEKS")))
337 unit_multiplikator = 604800; //60*60*24*7 = 604800
338 else if(!stricmp(str, "day") || !stricmp(str, "days") || !stricmp(str, get_language_string(user, "TIME_DAY")) || !stricmp(str, get_language_string(user, "TIME_DAYS")))
339 unit_multiplikator = 86400; //60*60*24 = 86400
340 else if(!stricmp(str, "hour") || !stricmp(str, "hours") || !stricmp(str, get_language_string(user, "TIME_HOUR")) || !stricmp(str, get_language_string(user, "TIME_HOURS")))
341 unit_multiplikator = 3600; //60*60 = 3600
342 else if(!stricmp(str, "minute") || !stricmp(str, "minutes") || !stricmp(str, "min") || !stricmp(str, "mins") || !stricmp(str, get_language_string(user, "TIME_MINUTE")) || !stricmp(str, get_language_string(user, "TIME_MINUTES")))
343 unit_multiplikator = 60;
345 unit_multiplikator = 1;
349 unit_multiplikator = 31536000; //60*60*24*365 = 31536000
352 unit_multiplikator = 2592000; //60*60*24*30 = 2592000
355 unit_multiplikator = 604800; //60*60*24*7 = 604800
358 unit_multiplikator = 86400; //60*60*24 = 86400
361 unit_multiplikator = 3600; //60*60 = 3600
364 unit_multiplikator = 60;
367 unit_multiplikator = 1;
371 total_time += (cvalue * unit_multiplikator);
378 int getCurrentSecondsOfDay() {
379 time_t now = time(0);
380 struct tm *timeofday = localtime(&now);
382 seconds += timeofday->tm_hour * 3600;
383 seconds += timeofday->tm_min * 60;
384 seconds += timeofday->tm_sec;
388 struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan) {
389 struct ModeBuffer *modeBuf = malloc(sizeof(*modeBuf));
391 perror("malloc() failed");
394 modeBuf->client = client;
395 modeBuf->chan = chan;
396 modeBuf->addCount = 0;
397 modeBuf->delCount = 0;
401 void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param) {
403 modeBuf->addModes[modeBuf->addCount] = mode;
404 modeBuf->addModesParams[modeBuf->addCount] = (param ? strdup(param) : NULL);
406 modeBuf->addModes[modeBuf->addCount] = '\0';
408 modeBuf->delModes[modeBuf->delCount] = mode;
409 modeBuf->delModesParams[modeBuf->delCount] = (param ? strdup(param) : NULL);
411 modeBuf->delModes[modeBuf->delCount] = '\0';
413 if(modeBuf->addCount + modeBuf->delCount == MAXMODES)
414 flushModeBuffer(modeBuf);
417 void flushModeBuffer(struct ModeBuffer *modeBuf) {
418 char modeStr[MAXMODES+3];
420 char paramStr[MAXLEN];
424 if(modeBuf->addCount) {
425 modeStr[modePos++] = '+';
426 for(i = 0; i < modeBuf->addCount; i++) {
427 modeStr[modePos++] = modeBuf->addModes[i];
428 if(modeBuf->addModesParams[i]) {
429 paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->addModesParams[i]);
430 free(modeBuf->addModesParams[i]);
431 modeBuf->addModesParams[i] = NULL;
434 modeBuf->addCount = 0;
436 if(modeBuf->delCount) {
437 modeStr[modePos++] = '-';
438 for(i = 0; i < modeBuf->delCount; i++) {
439 modeStr[modePos++] = modeBuf->delModes[i];
440 if(modeBuf->delModesParams[i]) {
441 paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->delModesParams[i]);
442 free(modeBuf->delModesParams[i]);
443 modeBuf->delModesParams[i] = NULL;
446 modeBuf->delCount = 0;
448 modeStr[modePos++] = '\0';
449 putsock(modeBuf->client, "MODE %s %s%s", modeBuf->chan->name, modeStr, paramStr);
452 void freeModeBuffer(struct ModeBuffer *modeBuf) {
453 if(modeBuf->addCount + modeBuf->delCount)
454 flushModeBuffer(modeBuf);
458 int is_ircmask(const char *text) {
459 while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text)))
463 while (*text && *text != '@' && !isspace((char)*text))
467 while (*text && !isspace((char)*text))
472 char* generate_banmask(struct UserNode *user, char *buffer) {
473 char *userhost = user->host;
475 if(isFakeHost(user->host)) {
476 sprintf(buffer, "*!*@%s", userhost);
480 //check if the hostname has more than 4 connections (trusted host)
481 if(countUsersWithHost(userhost) > 4) {
482 sprintf(buffer, "*!%s@%s", user->ident, userhost);
485 sprintf(buffer, "*!*@%s", userhost);
490 char* make_banmask(char *input, char* buffer) {
491 char *nick = NULL, *ident = NULL, *host = NULL;
494 if((p = strstr(input, "!"))) {
498 if((p = strstr(ident, "@"))) {
502 } else if((p = strstr(input, "@"))) {
506 } else if((p = strstr(input, ".")) || (p = strstr(input, ":"))) {
508 } else if(*input == '*' && input[1] != '\0' && !strstr(input+1, "*")) {
510 p = getAuthFakehost(input+1);
514 sprintf(tmp, "%s.*", input+1);
518 struct UserNode *user = searchUserByNick(input);
520 return generate_banmask(user, buffer);
524 if(nick && *nick == '\0') nick = NULL;
525 if(ident && *ident == '\0') ident = NULL;
526 if(host && *host == '\0') host = NULL;
527 sprintf(buffer, "%s!%s@%s", (nick ? nick : "*"), (ident ? ident : "*"), (host ? host : "*"));
531 int isFakeHost(char *host) {
532 char *p1, *p2 = host;
534 //find the last dot to identify if the hostmask is a fake host
535 while((p1 = strchr(p2, '.'))) {
538 //TLD database: http://www.iana.org/domains/root/db/
539 //the longest TLD i found was 6 chars long (ignoring the stange exotic ones :D)
540 //but we even ignore '.museum' and '.travel' so we can say that the TLD of our mask needs to be less than 4 chars to be a real domain
541 return (strlen(p2+1) > 4);
544 int mask_match(char *mask, struct UserNode *user) {
545 char usermask[NICKLEN+USERLEN+HOSTLEN+3];
546 char matchmask[strlen(mask)+3];
547 strcpy(matchmask, mask);
548 char *host = strchr(mask, '@');
550 struct IPNode *ip = createIPNode(host);
551 int bits = (ip->flags & IPNODE_IS_IPV6 ? 128 : 32);
552 if((host = strchr(host, '/'))) {
555 if(ip && user->ip&& !ipmatch(user->ip, ip, bits)) {
560 sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
561 return match(matchmask, usermask);
564 static unsigned long crc_table[256];
566 static void crc32_init() {
569 for(i = 0; i < 256; i++) {
571 for(j = 8; j > 0; j--) {
573 crc = (crc >> 1) ^ 0xEDB88320L;
581 unsigned long crc32(const char *text) {
582 register unsigned long crc = 0xFFFFFFFF;
583 unsigned int c, i = 0;
584 while((c = (unsigned int)text[i++]) != 0)
585 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_table[(crc^c) & 0xFF];
586 return (crc^0xFFFFFFFF);
589 int stricmp (const char *s1, const char *s2) {
590 return stricmplen(s1, s2, -1);
593 int stricmplen(const char *s1, const char *s2, int len) {
595 return (s2 == NULL ? 0 : -(*s2));
600 while ((c1 = tolower(*s1)) == (c2 = tolower(*s2))) {
606 if(len != -1 && i == len) break;
612 register_default_language_table(msgtab);