]> jfr.im git - irc/quakenet/newserv.git/blob - lib/irc_string.c
Someone figured out how to print the ip, nterfacer now shows bad IP connections.
[irc/quakenet/newserv.git] / lib / irc_string.c
1 /* irc_string.c */
2
3 #include "irc_string.h"
4 #include "chattr.tab.c"
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <errno.h>
8
9 /*-
10 * For some sections, the BSD license applies, specifically:
11 * ircd_strcmp ircd_strncmp:
12 *
13 * Copyright (c) 1987
14 * The Regents of the University of California. All rights reserved.
15 *
16 * match/collapse
17 *
18 * Copyright (c) 1998
19 * Andrea Cocito (Nemesi).
20 * Copyright (c)
21 * Run (carlo@runaway.xs4all.nl) 1996
22 *
23 * mmatch/match/collapse
24 *
25 * Copyright (c)
26 * Run (carlo@runaway.xs4all.nl) 1996
27 *
28 * License follows:
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 4. Neither the name of the University/owner? nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 */
54
55
56 static unsigned long crc32_tab[] = {
57 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
58 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
59 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
60 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
61 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
62 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
63 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
64 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
65 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
66 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
67 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
68 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
69 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
70 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
71 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
72 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
73 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
74 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
75 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
76 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
77 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
78 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
79 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
80 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
81 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
82 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
83 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
84 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
85 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
86 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
87 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
88 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
89 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
90 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
91 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
92 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
93 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
94 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
95 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
96 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
97 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
98 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
99 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
100 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
101 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
102 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
103 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
104 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
105 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
106 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
107 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
108 0x2d02ef8dL
109 };
110
111 int match2strings(const char *patrn, const char *string) {
112 return !match(patrn,string);
113 }
114
115 int match2patterns(const char *patrn, const char *string) {
116 return !mmatch(patrn,string);
117 }
118
119 /* This computes a 32 bit CRC of the data in the buffer, and returns the */
120 /* CRC. The polynomial used is 0xedb88320. */
121 /* ============================================================= */
122 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
123 /* code or tables extracted from it, as desired without restriction. */
124 /* Modified by Fox: no more length parameter, always does the whole string */
125 unsigned long crc32(const char *s) {
126 const char *cp;
127 unsigned long crc32val;
128
129 crc32val = 0;
130 for (cp=s;*cp;cp++) {
131 crc32val=crc32_tab[(crc32val^(*cp)) & 0xff] ^ (crc32val >> 8);
132 }
133 return crc32val;
134 }
135
136 /* Case insensitive version of the above */
137 unsigned long crc32i(const char *s) {
138 const char *cp;
139 unsigned long crc32val;
140
141 crc32val = 0;
142 for (cp=s;*cp;cp++) {
143 crc32val=crc32_tab[(crc32val^(ToLower(*cp))) & 0xff] ^ (crc32val >> 8);
144 }
145 return crc32val;
146 }
147
148 /* ircd_strcmp/ircd_strncmp
149 *
150 * Copyright (c) 1987
151 * The Regents of the University of California. All rights reserved.
152 *
153 * BSD license.
154 *
155 * Modified from this version for ircd usage.
156 */
157
158 int ircd_strcmp(const char *s1, const char *s2) {
159 register const char* u1 = s1;
160 register const char* u2 = s2;
161
162 while(ToLower(*u1) == ToLower(*u2)) {
163 if(!*u1++)
164 return 0;
165
166 u2++;
167 }
168 return ToLower(*u1) - ToLower(*u2);
169 }
170
171
172 int ircd_strncmp(const char *s1, const char *s2, size_t len) {
173 register const char* u1 = s1;
174 register const char* u2 = s2;
175 size_t remaining = len - 1;
176
177 if(!remaining)
178 return 0;
179
180 while(ToLower(*u1) == ToLower(*u2)) {
181 if(!*u1++ || !remaining--)
182 return 0;
183
184 u2++;
185 }
186
187 return ToLower(*u1) - ToLower(*u2);
188 }
189
190 /*
191 * delchars: deletes characters occuring in badchars from string
192 */
193
194 char *delchars(char *string, const char *badchars) {
195 char *s,*d;
196 const char *b;
197 int isbad;
198
199 s=d=string;
200 while (*s) {
201 isbad=0;
202 for(b=badchars;*b;b++) {
203 if (*b==*s) {
204 isbad=1;
205 break;
206 }
207 }
208 if (isbad) {
209 s++;
210 } else {
211 *d++=*s++;
212 }
213 }
214 *d='\0';
215
216 return string;
217 }
218
219 /*
220 * IPtostr:
221 * Converts a long into a "p.q.r.s" IP address
222 */
223
224 const char *IPlongtostr(unsigned long IP) {
225 static char buf[16];
226
227 sprintf(buf,"%lu.%lu.%lu.%lu",(IP>>24),(IP>>16)&255,(IP>>8)&255,IP&255);
228
229 return buf;
230 }
231
232 /*
233 * longtoduration:
234 * Converts a specified number of seconds into a duration string.
235 * format: 0 for the "/stats u" compatible output, 1 for more human-friendly output.
236 */
237
238 const char *longtoduration(unsigned long interval, int format) {
239 int days,hours,minutes,seconds;
240 static char outstring[50];
241 int pos=0;
242
243 seconds=interval%60;
244 minutes=(interval%3600)/60;
245 hours=(interval%(3600*24))/3600;
246 days=interval/(3600*24);
247
248 if (format==0 || (days>0 && (hours||minutes||seconds))) {
249 sprintf(outstring,"%d day%s, %02d:%02d:%02d",
250 days,(days==1)?"":"s",hours,minutes,seconds);
251 } else if (days>0) {
252 sprintf(outstring, "%d day%s",days,(days==1)?"":"s");
253 } else {
254 if (hours>0) {
255 pos += sprintf(outstring+pos,"%d hour%s ",hours,hours==1?"":"s");
256 }
257 if (minutes>0 || (hours>0 && seconds>0)) {
258 pos += sprintf(outstring+pos,"%d minute%s ",minutes,minutes==1?"":"s");
259 }
260 if (seconds>0) {
261 pos += sprintf(outstring+pos,"%d second%s ",seconds,seconds==1?"":"s");
262 }
263 }
264
265 return outstring;
266 }
267
268 /*
269 * durationtolong:
270 * Converts the specified string into a number of seconds, as per O
271 */
272
273 int durationtolong(const char *string) {
274 int total=0;
275 int current=0;
276 char *ch=(char *)string,*och;
277
278 while (*ch) {
279 och=ch;
280 current=strtol(ch,&ch,10);
281 if (och==ch) /* No numbers found */
282 break;
283 if (current) {
284 switch (*ch++) {
285 case '\0':
286 ch--;
287 /* Drop through */
288 case 's':
289 total+=current;
290 break;
291
292 case 'm':
293 total+=(current * 60);
294 break;
295
296 case 'h':
297 total+=(current * 3600);
298 break;
299
300 case 'd':
301 total+=(current * 86400);
302 break;
303
304 case 'w':
305 total+=(current * 604800);
306 break;
307
308 case 'M':
309 total+=(current * 2592000);
310 break;
311
312 case 'y':
313 total+=(current * 31557600);
314 }
315 }
316 }
317 return total;
318 }
319
320 /*
321 * mmatch()
322 *
323 * Written by Run (carlo@runaway.xs4all.nl), 25-10-96
324 *
325 *
326 * From: Carlo Wood <carlo@runaway.xs4all.nl>
327 * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
328 * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
329 * To: coder-com@mail.undernet.org (coder committee)
330 * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
331 *
332 * We need a new function `mmatch(const char *old_mask, const char *new_mask)'
333 * which returns `true' likewise the current `match' (start with copying it),
334 * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
335 * as follows: a '*' in `new_mask' does not match a '?' in `old_mask' and
336 * a '?' in `new_mask' does not match a '\?' in `old_mask'.
337 * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
338 * And last but not least, '\?' and '\*' in `new_mask' now become one character.
339 *
340 * Kindly BSD licensed by Run for Newserv.
341 */
342
343 int mmatch(const char *old_mask, const char *new_mask)
344 {
345 const char *m = old_mask;
346 const char *n = new_mask;
347 const char *ma = m;
348 const char *na = n;
349 int wild = 0;
350 int mq = 0, nq = 0;
351
352 while (1)
353 {
354 if (*m == '*')
355 {
356 while (*m == '*')
357 m++;
358 wild = 1;
359 ma = m;
360 na = n;
361 }
362
363 if (!*m)
364 {
365 if (!*n)
366 return 0;
367 for (m--; (m > old_mask) && (*m == '?'); m--)
368 ;
369 if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
370 return 0;
371 if (!wild)
372 return 1;
373 m = ma;
374
375 /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
376 if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
377 ++na;
378
379 n = ++na;
380 }
381 else if (!*n)
382 {
383 while (*m == '*')
384 m++;
385 return (*m != 0);
386 }
387 if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
388 {
389 m++;
390 mq = 1;
391 }
392 else
393 mq = 0;
394
395 /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
396 if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
397 {
398 n++;
399 nq = 1;
400 }
401 else
402 nq = 0;
403
404 /*
405 * This `if' has been changed compared to match() to do the following:
406 * Match when:
407 * old (m) new (n) boolean expression
408 * * any (*m == '*' && !mq) ||
409 * ? any except '*' (*m == '?' && !mq && (*n != '*' || nq)) ||
410 * any except * or ? same as m (!((*m == '*' || *m == '?') && !mq) &&
411 * ToLower(*m) == ToLower(*n) &&
412 * !((mq && !nq) || (!mq && nq)))
413 *
414 * Here `any' also includes \* and \? !
415 *
416 * After reworking the boolean expressions, we get:
417 * (Optimized to use boolean shortcircuits, with most frequently occuring
418 * cases upfront (which took 2 hours!)).
419 */
420 if ((*m == '*' && !mq) ||
421 ((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
422 (*m == '?' && !mq && (*n != '*' || nq)))
423 {
424 if (*m)
425 m++;
426 if (*n)
427 n++;
428 }
429 else
430 {
431 if (!wild)
432 return 1;
433 m = ma;
434
435 /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
436 if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
437 ++na;
438
439 n = ++na;
440 }
441 }
442 }
443
444 /*
445 * Compare if a given string (name) matches the given
446 * mask (which can contain wild cards: '*' - match any
447 * number of chars, '?' - match any single character.
448 *
449 * return 0, if match
450 * 1, if no match
451 */
452
453 /*
454 * match
455 *
456 * Rewritten by Andrea Cocito (Nemesi), November 1998.
457 *
458 * Permission kindly granted by Andrea to be used under the BSD license.
459 *
460 */
461
462 /****************** Nemesi's match() ***************/
463
464 int match(const char *mask, const char *string)
465 {
466 const char *m = mask, *s = string;
467 char ch;
468 const char *bm, *bs; /* Will be reg anyway on a decent CPU/compiler */
469
470 /* Process the "head" of the mask, if any */
471 while ((ch = *m++) && (ch != '*'))
472 switch (ch)
473 {
474 case '\\':
475 if (*m == '?' || *m == '*')
476 ch = *m++;
477 default:
478 if (ToLower(*s) != ToLower(ch))
479 return 1;
480 case '?':
481 if (!*s++)
482 return 1;
483 };
484 if (!ch)
485 return *s;
486
487 /* We got a star: quickly find if/where we match the next char */
488 got_star:
489 bm = m; /* Next try rollback here */
490 while ((ch = *m++))
491 switch (ch)
492 {
493 case '?':
494 if (!*s++)
495 return 1;
496 case '*':
497 bm = m;
498 continue; /* while */
499 case '\\':
500 if (*m == '?' || *m == '*')
501 ch = *m++;
502 default:
503 goto break_while; /* C is structured ? */
504 };
505 break_while:
506 if (!ch)
507 return 0; /* mask ends with '*', we got it */
508 ch = ToLower(ch);
509 while (ToLower(*s++) != ch)
510 if (!*s)
511 return 1;
512 bs = s; /* Next try start from here */
513
514 /* Check the rest of the "chunk" */
515 while ((ch = *m++))
516 {
517 switch (ch)
518 {
519 case '*':
520 goto got_star;
521 case '\\':
522 if (*m == '?' || *m == '*')
523 ch = *m++;
524 default:
525 if (ToLower(*s) != ToLower(ch))
526 {
527 /* If we've run out of string, give up */
528 if (!*bs)
529 return 1;
530 m = bm;
531 s = bs;
532 goto got_star;
533 };
534 case '?':
535 if (!*s++)
536 return 1;
537 };
538 };
539 if (*s)
540 {
541 m = bm;
542 s = bs;
543 goto got_star;
544 };
545 return 0;
546 }
547
548 /*
549 * collapse()
550 * Collapse a pattern string into minimal components.
551 * This particular version is "in place", so that it changes the pattern
552 * which is to be reduced to a "minimal" size.
553 *
554 * (C) Carlo Wood - 6 Oct 1998
555 * Speedup rewrite by Andrea Cocito, December 1998.
556 * Note that this new optimized alghoritm can *only* work in place.
557 *
558 * Permission kindly granted by Andrea to be used under the BSD license.
559 *
560 */
561
562 char *collapse(char *mask)
563 {
564 int star = 0;
565 char *m = mask;
566 char *b;
567
568 if (m)
569 {
570 do
571 {
572 if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
573 {
574 b = m;
575 do
576 {
577 if (*m == '*')
578 star = 1;
579 else
580 {
581 if (star && (*m != '?'))
582 {
583 *b++ = '*';
584 star = 0;
585 };
586 *b++ = *m;
587 if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
588 *b++ = *++m;
589 };
590 }
591 while (*m++);
592 break;
593 }
594 else
595 {
596 if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
597 m++;
598 };
599 }
600 while (*m++);
601 };
602 return mask;
603 }
604
605 /* a protected version of atoi that will return an error if broke/etc */
606 int protectedatoi(char *buf, int *value) {
607 char *ep;
608 long lval;
609
610 errno = 0;
611 lval = strtol(buf, &ep, 10);
612 if (buf[0] == '\0' || *ep != '\0')
613 return 0;
614
615 if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || (lval > INT_MAX || lval < INT_MIN))
616 return 0;
617
618 *value = lval;
619 return 1;
620 }