]> jfr.im git - irc/quakenet/newserv.git/blame - lib/irc_string.c
Add jupe support
[irc/quakenet/newserv.git] / lib / irc_string.c
CommitLineData
c86edd1d
Q
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
abfd7194
CP
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).
4afb8fd8
CP
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
abfd7194
CP
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
c86edd1d
Q
56static 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
c86edd1d
Q
111int match2strings(const char *patrn, const char *string) {
112 return !match(patrn,string);
113}
114
115int match2patterns(const char *patrn, const char *string) {
116 return !mmatch(patrn,string);
117}
c86edd1d
Q
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 */
125unsigned 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 */
137unsigned 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
abfd7194
CP
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.
c86edd1d 156 */
abfd7194
CP
157
158int 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)) {
4afb8fd8 163 if(!*u1++)
c86edd1d 164 return 0;
abfd7194
CP
165
166 u2++;
c86edd1d 167 }
abfd7194 168 return ToLower(*u1) - ToLower(*u2);
c86edd1d
Q
169}
170
abfd7194
CP
171
172int 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)
c86edd1d 178 return 0;
abfd7194
CP
179
180 while(ToLower(*u1) == ToLower(*u2)) {
4afb8fd8 181 if(!*u1++ || !remaining--)
c86edd1d 182 return 0;
abfd7194
CP
183
184 u2++;
c86edd1d 185 }
abfd7194
CP
186
187 return ToLower(*u1) - ToLower(*u2);
c86edd1d
Q
188}
189
190/*
191 * delchars: deletes characters occuring in badchars from string
192 */
193
194char *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
224const char *IPtostr(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
238const 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 (days>0 || format==0) {
249 sprintf(outstring,"%d day%s, %02d:%02d:%02d",
250 days,(days==1)?"":"s",hours,minutes,seconds);
251 } else {
252 if (hours>0) {
253 pos += sprintf(outstring+pos,"%d hour%s ",hours,hours==1?"":"s");
254 }
255 if (minutes>0 || (hours>0 && seconds>0)) {
256 pos += sprintf(outstring+pos,"%d minute%s ",minutes,minutes==1?"":"s");
257 }
258 if (seconds>0) {
259 pos += sprintf(outstring+pos,"%d second%s ",seconds,seconds==1?"":"s");
260 }
261 }
262
263 return outstring;
264}
265
266/*
267 * durationtolong:
268 * Converts the specified string into a number of seconds, as per O
269 */
270
271int durationtolong(const char *string) {
272 int total=0;
273 int current=0;
4afb8fd8 274 char *ch=(char *)string,*och;
c86edd1d
Q
275
276 while (*ch) {
277 och=ch;
278 current=strtol(ch,&ch,10);
279 if (och==ch) /* No numbers found */
280 break;
281 if (current) {
282 switch (*ch++) {
283 case '\0':
284 ch--;
285 /* Drop through */
286 case 's':
287 total+=current;
288 break;
289
290 case 'm':
291 total+=(current * 60);
292 break;
293
294 case 'h':
295 total+=(current * 3600);
296 break;
297
298 case 'd':
299 total+=(current * 86400);
300 break;
301
302 case 'w':
303 total+=(current * 604800);
304 break;
305
306 case 'M':
307 total+=(current * 2592000);
308 break;
309
310 case 'y':
311 total+=(current * 31557600);
312 }
313 }
314 }
315 return total;
316}
e4366dd3 317
4afb8fd8 318/*
c86edd1d
Q
319 * mmatch()
320 *
321 * Written by Run (carlo@runaway.xs4all.nl), 25-10-96
322 *
323 *
324 * From: Carlo Wood <carlo@runaway.xs4all.nl>
325 * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
326 * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
327 * To: coder-com@mail.undernet.org (coder committee)
328 * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
329 *
330 * We need a new function `mmatch(const char *old_mask, const char *new_mask)'
331 * which returns `true' likewise the current `match' (start with copying it),
332 * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
333 * as follows: a '*' in `new_mask' does not match a '?' in `old_mask' and
334 * a '?' in `new_mask' does not match a '\?' in `old_mask'.
335 * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
336 * And last but not least, '\?' and '\*' in `new_mask' now become one character.
4afb8fd8
CP
337 *
338 * Kindly BSD licensed by Run for Newserv.
c86edd1d
Q
339 */
340
341int mmatch(const char *old_mask, const char *new_mask)
342{
343 const char *m = old_mask;
344 const char *n = new_mask;
345 const char *ma = m;
346 const char *na = n;
347 int wild = 0;
348 int mq = 0, nq = 0;
349
350 while (1)
351 {
352 if (*m == '*')
353 {
354 while (*m == '*')
355 m++;
356 wild = 1;
357 ma = m;
358 na = n;
359 }
360
361 if (!*m)
362 {
363 if (!*n)
364 return 0;
365 for (m--; (m > old_mask) && (*m == '?'); m--)
366 ;
367 if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
368 return 0;
369 if (!wild)
370 return 1;
371 m = ma;
372
373 /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
374 if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
375 ++na;
376
377 n = ++na;
378 }
379 else if (!*n)
380 {
381 while (*m == '*')
382 m++;
383 return (*m != 0);
384 }
385 if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
386 {
387 m++;
388 mq = 1;
389 }
390 else
391 mq = 0;
392
393 /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
394 if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
395 {
396 n++;
397 nq = 1;
398 }
399 else
400 nq = 0;
401
402/*
403 * This `if' has been changed compared to match() to do the following:
404 * Match when:
405 * old (m) new (n) boolean expression
406 * * any (*m == '*' && !mq) ||
407 * ? any except '*' (*m == '?' && !mq && (*n != '*' || nq)) ||
408 * any except * or ? same as m (!((*m == '*' || *m == '?') && !mq) &&
409 * ToLower(*m) == ToLower(*n) &&
410 * !((mq && !nq) || (!mq && nq)))
411 *
412 * Here `any' also includes \* and \? !
413 *
414 * After reworking the boolean expressions, we get:
415 * (Optimized to use boolean shortcircuits, with most frequently occuring
416 * cases upfront (which took 2 hours!)).
417 */
418 if ((*m == '*' && !mq) ||
419 ((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
420 (*m == '?' && !mq && (*n != '*' || nq)))
421 {
422 if (*m)
423 m++;
424 if (*n)
425 n++;
426 }
427 else
428 {
429 if (!wild)
430 return 1;
431 m = ma;
432
433 /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
434 if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
435 ++na;
436
437 n = ++na;
438 }
439 }
440}
441
442/*
443 * Compare if a given string (name) matches the given
444 * mask (which can contain wild cards: '*' - match any
445 * number of chars, '?' - match any single character.
446 *
447 * return 0, if match
448 * 1, if no match
449 */
450
e4366dd3 451/*
c86edd1d
Q
452 * match
453 *
454 * Rewritten by Andrea Cocito (Nemesi), November 1998.
455 *
e4366dd3
CP
456 * Permission kindly granted by Andrea to be used under the BSD license.
457 *
c86edd1d
Q
458 */
459
460/****************** Nemesi's match() ***************/
461
462int match(const char *mask, const char *string)
463{
464 const char *m = mask, *s = string;
465 char ch;
466 const char *bm, *bs; /* Will be reg anyway on a decent CPU/compiler */
467
468 /* Process the "head" of the mask, if any */
469 while ((ch = *m++) && (ch != '*'))
470 switch (ch)
471 {
472 case '\\':
473 if (*m == '?' || *m == '*')
474 ch = *m++;
475 default:
476 if (ToLower(*s) != ToLower(ch))
477 return 1;
478 case '?':
479 if (!*s++)
480 return 1;
481 };
482 if (!ch)
483 return *s;
484
485 /* We got a star: quickly find if/where we match the next char */
486got_star:
487 bm = m; /* Next try rollback here */
488 while ((ch = *m++))
489 switch (ch)
490 {
491 case '?':
492 if (!*s++)
493 return 1;
494 case '*':
495 bm = m;
496 continue; /* while */
497 case '\\':
498 if (*m == '?' || *m == '*')
499 ch = *m++;
500 default:
501 goto break_while; /* C is structured ? */
502 };
503break_while:
504 if (!ch)
505 return 0; /* mask ends with '*', we got it */
506 ch = ToLower(ch);
507 while (ToLower(*s++) != ch)
508 if (!*s)
509 return 1;
510 bs = s; /* Next try start from here */
511
512 /* Check the rest of the "chunk" */
513 while ((ch = *m++))
514 {
515 switch (ch)
516 {
517 case '*':
518 goto got_star;
519 case '\\':
520 if (*m == '?' || *m == '*')
521 ch = *m++;
522 default:
523 if (ToLower(*s) != ToLower(ch))
524 {
525 /* If we've run out of string, give up */
526 if (!*bs)
527 return 1;
528 m = bm;
529 s = bs;
530 goto got_star;
531 };
532 case '?':
533 if (!*s++)
534 return 1;
535 };
536 };
537 if (*s)
538 {
539 m = bm;
540 s = bs;
541 goto got_star;
542 };
543 return 0;
544}
545
e4366dd3 546/*
c86edd1d
Q
547 * collapse()
548 * Collapse a pattern string into minimal components.
549 * This particular version is "in place", so that it changes the pattern
550 * which is to be reduced to a "minimal" size.
551 *
552 * (C) Carlo Wood - 6 Oct 1998
553 * Speedup rewrite by Andrea Cocito, December 1998.
554 * Note that this new optimized alghoritm can *only* work in place.
e4366dd3
CP
555 *
556 * Permission kindly granted by Andrea to be used under the BSD license.
557 *
c86edd1d
Q
558 */
559
560char *collapse(char *mask)
561{
562 int star = 0;
563 char *m = mask;
564 char *b;
565
566 if (m)
567 {
568 do
569 {
570 if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
571 {
572 b = m;
573 do
574 {
575 if (*m == '*')
576 star = 1;
577 else
578 {
579 if (star && (*m != '?'))
580 {
581 *b++ = '*';
582 star = 0;
583 };
584 *b++ = *m;
585 if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
586 *b++ = *++m;
587 };
588 }
589 while (*m++);
590 break;
591 }
592 else
593 {
594 if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
595 m++;
596 };
597 }
598 while (*m++);
599 };
600 return mask;
601}
602
603/* a protected version of atoi that will return an error if broke/etc */
604int protectedatoi(char *buf, int *value) {
605 char *ep;
606 long lval;
607
608 errno = 0;
609 lval = strtol(buf, &ep, 10);
610 if (buf[0] == '\0' || *ep != '\0')
611 return 0;
612
613 if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || (lval > INT_MAX || lval < INT_MIN))
614 return 0;
615
616 *value = lval;
617 return 1;
618}