]>
jfr.im git - irc/rqf/shadowircd.git/blob - src/irc_string.c
2 * ircd-ratbox: A slightly useful ircd.
3 * irc_string.c: IRC string functions.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 * $Id: irc_string.c 678 2006-02-03 20:25:01Z jilles $
28 #include "sprintf_irc.h"
29 #include "irc_string.h"
47 * myctime - This is like standard ctime()-function, but it zaps away
48 * the newline from the end of that string. Also, it takes
49 * the time value as parameter, instead of pointer to it.
50 * Note that it is necessary to copy the string to alternate
51 * buffer (who knows how ctime() implements it, maybe it statically
52 * has newline there and never 'refreshes' it -- zapping that
53 * might break things in other places...)
56 * Thu Nov 24 18:22:48 1986
64 strcpy(buf
, ctime(&value
));
65 if((p
= strchr(buf
, '\n')) != NULL
)
72 * clean_string - clean up a string possibly containing garbage
74 * *sigh* Before the kiddies find this new and exciting way of
75 * annoying opers, lets clean up what is sent to local opers
79 clean_string(char *dest
, const unsigned char *src
, size_t len
)
85 if(dest
== NULL
|| src
== NULL
)
88 len
-= 3; /* allow for worst case, '^A\0' */
90 while(*src
&& (len
> 0))
92 if(*src
& 0x80) /* if high bit is set */
97 else if(!IsPrint(*src
)) /* if NOT printable */
101 *d
++ = 0x40 + *src
; /* turn it into a printable */
113 * strip_tabs(dst, src, length)
115 * Copies src to dst, while converting all \t (tabs) into spaces.
117 * NOTE: jdc: I have a gut feeling there's a faster way to do this.
120 strip_tabs(char *dest
, const unsigned char *src
, size_t len
)
123 /* Sanity check; we don't want anything nasty... */
127 if(dest
== NULL
|| src
== NULL
)
130 while(*src
&& (len
> 0))
134 *d
++ = ' '; /* Translate the tab into a space */
138 *d
++ = *src
; /* Copy src to dst */
143 *d
= '\0'; /* Null terminate, thanks and goodbye */
148 * strtoken - walk through a string of tokens, using a set of separators
153 strtoken(char **save
, char *str
, const char *fs
)
155 char *pos
= *save
; /* keep last position across calls */
159 pos
= str
; /* new string scan */
161 while(pos
&& *pos
&& strchr(fs
, *pos
) != NULL
)
162 ++pos
; /* skip leading separators */
165 return (pos
= *save
= NULL
); /* string contains only sep's */
167 tmp
= pos
; /* now, keep position of the token */
169 while(*pos
&& strchr(fs
, *pos
) == NULL
)
170 ++pos
; /* skip content of the token */
173 *pos
++ = '\0'; /* remove first sep after the token */
175 pos
= NULL
; /* end of string */
181 static const char base64_table
[] =
182 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
183 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
184 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
185 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
186 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
189 static const char base64_pad
= '=';
191 static const short base64_reverse_table
[256] = {
192 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
193 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
194 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
195 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
196 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
197 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
198 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
199 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
200 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
201 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
202 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
203 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
204 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
205 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
206 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
207 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
211 * From: Thomas Helvey <tomh@inxpress.net>
213 static const char *IpQuadTab
[] = {
214 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
215 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
216 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
217 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
218 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
219 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
220 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
221 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
222 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
223 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
224 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
225 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
226 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
227 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
228 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
229 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
230 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
231 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
232 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
233 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
234 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
235 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
236 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
237 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
238 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
239 "250", "251", "252", "253", "254", "255"
243 * inetntoa - in_addr to string
244 * changed name to remove collision possibility and
245 * so behaviour is guaranteed to take a pointer arg.
247 * inet_ntoa -- returned the dotted notation of a given
250 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
254 inetntoa(const char *in
)
258 const unsigned char *a
= (const unsigned char *) in
;
281 * Copyright (c) 1996-1999 by Internet Software Consortium.
283 * Permission to use, copy, modify, and distribute this software for any
284 * purpose with or without fee is hereby granted, provided that the above
285 * copyright notice and this permission notice appear in all copies.
287 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
288 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
289 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
290 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
291 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
292 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
293 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
297 #define SPRINTF(x) ((size_t)rb_sprintf x)
300 * WARNING: Don't even consider trying to compile this on a system where
301 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
304 static const char *inet_ntop4(const u_char
* src
, char *dst
, unsigned int size
);
306 static const char *inet_ntop6(const u_char
* src
, char *dst
, unsigned int size
);
310 * inet_ntop4(src, dst, size)
311 * format an IPv4 address
315 * (1) uses no statics
316 * (2) takes a u_char* not an in_addr as input
321 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
325 return strcpy(dst
, inetntoa((const char *) src
));
329 * inet_ntop6(src, dst, size)
330 * convert IPv6 binary address into presentation (printable) format
336 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
339 * Note that int32_t and int16_t need only be "at least" large enough
340 * to contain a value of the specified size. On some systems, like
341 * Crays, there is no such thing as an integer variable with 16 bits.
342 * Keep this in mind if you think this function should have been coded
343 * to use pointer overlays. All the world's not a VAX.
345 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
351 u_int words
[IN6ADDRSZ
/ INT16SZ
];
356 * Copy the input (bytewise) array into a wordwise array.
357 * Find the longest run of 0x00's in src[] for :: shorthanding.
359 memset(words
, '\0', sizeof words
);
360 for(i
= 0; i
< IN6ADDRSZ
; i
+= 2)
361 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
364 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
369 cur
.base
= i
, cur
.len
= 1;
377 if(best
.base
== -1 || cur
.len
> best
.len
)
385 if(best
.base
== -1 || cur
.len
> best
.len
)
388 if(best
.base
!= -1 && best
.len
< 2)
395 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
397 /* Are we inside the best run of 0x00's? */
398 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
408 /* Are we following an initial run of 0x00s or any real hex? */
411 /* Is this address an encapsulated IPv4? */
412 if(i
== 6 && best
.base
== 0 &&
413 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
415 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
420 tp
+= SPRINTF((tp
, "%x", words
[i
]));
422 /* Was it a trailing run of 0x00's? */
423 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
428 * Check for overflow, copy, and we're done.
431 if((unsigned int) (tp
- tmp
) > size
)
435 return strcpy(dst
, tmp
);
440 inetpton_sock(const char *src
, struct sockaddr
*dst
)
442 if(inetpton(AF_INET
, src
, &((struct sockaddr_in
*) dst
)->sin_addr
))
444 ((struct sockaddr_in
*) dst
)->sin_port
= 0;
445 ((struct sockaddr_in
*) dst
)->sin_family
= AF_INET
;
446 SET_SS_LEN((struct rb_sockaddr_storage
*) dst
, sizeof(struct sockaddr_in
));
450 else if(inetpton(AF_INET6
, src
, &((struct sockaddr_in6
*) dst
)->sin6_addr
))
452 ((struct sockaddr_in6
*) dst
)->sin6_port
= 0;
453 ((struct sockaddr_in6
*) dst
)->sin6_family
= AF_INET6
;
454 SET_SS_LEN((struct rb_sockaddr_storage
*) dst
, sizeof(struct sockaddr_in6
));
462 inetntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
464 switch (src
->sa_family
)
467 return (inetntop(AF_INET
, &((struct sockaddr_in
*) src
)->sin_addr
, dst
, size
));
471 return (inetntop(AF_INET6
, &((struct sockaddr_in6
*) src
)->sin6_addr
, dst
, size
));
481 * inetntop(af, src, dst, size)
482 * convert a network format address to presentation format.
484 * pointer to presentation format address (`dst'), or NULL (see errno).
489 inetntop(int af
, const void *src
, char *dst
, unsigned int size
)
494 return (inet_ntop4(src
, dst
, size
));
497 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*) src
) ||
498 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*) src
))
500 ((const unsigned char *)
501 &((const struct in6_addr
*) src
)->s6_addr
[12], dst
, size
));
503 return (inet_ntop6(src
, dst
, size
));
514 * WARNING: Don't even consider trying to compile this on a system where
515 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
519 * inetpton(af, src, dst)
520 * convert from presentation format (which usually means ASCII printable)
521 * to network format (which is usually some kind of binary format).
523 * 1 if the address was valid for the specified address family
524 * 0 if the address wasn't valid (`dst' is untouched in this case)
525 * -1 if some other error occurred (`dst' is untouched in this case, too)
531 * inet_pton4(src, dst)
532 * like inet_aton() but without all the hexadecimal and shorthand.
534 * 1 if `src' is a valid dotted quad, else 0.
536 * does not touch `dst' unless it's returning 1.
545 int saw_digit
, octets
, ch
;
546 u_char tmp
[INADDRSZ
], *tp
;
551 while((ch
= *src
++) != '\0')
554 if(ch
>= '0' && ch
<= '9')
556 u_int
new = *tp
* 10 + (ch
- '0');
568 else if(ch
== '.' && saw_digit
)
580 memcpy(dst
, tmp
, INADDRSZ
);
586 * inet_pton6(src, dst)
587 * convert presentation level address to network order binary form.
589 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
591 * (1) does not touch `dst' unless it's returning 1.
592 * (2) :: in a full address is silently ignored.
594 * inspired by Mark Andrews.
604 static const char xdigits
[] = "0123456789abcdef";
605 u_char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
610 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
611 endp
= tp
+ IN6ADDRSZ
;
613 /* Leading :: requires some special handling. */
620 while((ch
= tolower(*src
++)) != '\0')
624 pch
= strchr(xdigits
, ch
);
628 val
|= (pch
- xdigits
);
644 else if(*src
== '\0')
648 if(tp
+ INT16SZ
> endp
)
650 *tp
++ = (u_char
) (val
>> 8) & 0xff;
651 *tp
++ = (u_char
) val
& 0xff;
656 if(*src
!= '\0' && ch
== '.')
658 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
662 break; /* '\0' was seen by inet_pton4(). */
671 if(tp
+ INT16SZ
> endp
)
673 *tp
++ = (u_char
) (val
>> 8) & 0xff;
674 *tp
++ = (u_char
) val
& 0xff;
679 * Since some memmove()'s erroneously fail to handle
680 * overlapping regions, we'll do the shift by hand.
682 const int n
= tp
- colonp
;
687 for(i
= 1; i
<= n
; i
++)
689 endp
[-i
] = colonp
[n
- i
];
696 memcpy(dst
, tmp
, IN6ADDRSZ
);
701 inetpton(af
, src
, dst
)
709 return (inet_pton4(src
, dst
));
712 /* Somebody might have passed as an IPv4 address this is sick but it works */
713 if(inet_pton4(src
, dst
))
716 rb_sprintf(tmp
, "::ffff:%s", src
);
717 return (inet_pton6(tmp
, dst
));
720 return (inet_pton6(src
, dst
));
729 strip_colour(char *string
)
733 char *last_non_space
= NULL
;
734 /* c is source, c2 is target */
744 if(c
[1] == ',' && isdigit(c
[2]))
770 *last_non_space
= '\0';