]> jfr.im git - solanum.git/blob - src/irc_string.c
Various inet* -> rb_inet_*
[solanum.git] / src / irc_string.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * irc_string.c: IRC string functions.
4 *
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
8 *
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.
13 *
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.
18 *
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
22 * USA
23 *
24 * $Id: irc_string.c 678 2006-02-03 20:25:01Z jilles $
25 */
26
27 #include "stdinc.h"
28 #include "sprintf_irc.h"
29 #include "irc_string.h"
30 #include "client.h"
31 #include "setup.h"
32
33 #ifndef INADDRSZ
34 #define INADDRSZ 4
35 #endif
36
37 #ifdef RB_IPV6
38 #ifndef IN6ADDRSZ
39 #define IN6ADDRSZ 16
40 #endif
41 #endif
42
43 #ifndef INT16SZ
44 #define INT16SZ 2
45 #endif
46 /*
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...)
54 *
55 *
56 * Thu Nov 24 18:22:48 1986
57 */
58 const char *
59 myctime(time_t value)
60 {
61 static char buf[32];
62 char *p;
63
64 strcpy(buf, ctime(&value));
65 if((p = strchr(buf, '\n')) != NULL)
66 *p = '\0';
67 return buf;
68 }
69
70
71 /*
72 * clean_string - clean up a string possibly containing garbage
73 *
74 * *sigh* Before the kiddies find this new and exciting way of
75 * annoying opers, lets clean up what is sent to local opers
76 * -Dianora
77 */
78 char *
79 clean_string(char *dest, const unsigned char *src, size_t len)
80 {
81 char *d = dest;
82 s_assert(0 != dest);
83 s_assert(0 != src);
84
85 if(dest == NULL || src == NULL)
86 return NULL;
87
88 len -= 3; /* allow for worst case, '^A\0' */
89
90 while(*src && (len > 0))
91 {
92 if(*src & 0x80) /* if high bit is set */
93 {
94 *d++ = '.';
95 --len;
96 }
97 else if(!IsPrint(*src)) /* if NOT printable */
98 {
99 *d++ = '^';
100 --len;
101 *d++ = 0x40 + *src; /* turn it into a printable */
102 }
103 else
104 *d++ = *src;
105 ++src;
106 --len;
107 }
108 *d = '\0';
109 return dest;
110 }
111
112 /*
113 * strip_tabs(dst, src, length)
114 *
115 * Copies src to dst, while converting all \t (tabs) into spaces.
116 *
117 * NOTE: jdc: I have a gut feeling there's a faster way to do this.
118 */
119 char *
120 strip_tabs(char *dest, const unsigned char *src, size_t len)
121 {
122 char *d = dest;
123 /* Sanity check; we don't want anything nasty... */
124 s_assert(0 != dest);
125 s_assert(0 != src);
126
127 if(dest == NULL || src == NULL)
128 return NULL;
129
130 while(*src && (len > 0))
131 {
132 if(*src == '\t')
133 {
134 *d++ = ' '; /* Translate the tab into a space */
135 }
136 else
137 {
138 *d++ = *src; /* Copy src to dst */
139 }
140 ++src;
141 --len;
142 }
143 *d = '\0'; /* Null terminate, thanks and goodbye */
144 return dest;
145 }
146
147 /*
148 * strtoken - walk through a string of tokens, using a set of separators
149 * argv 9/90
150 *
151 */
152 char *
153 strtoken(char **save, char *str, const char *fs)
154 {
155 char *pos = *save; /* keep last position across calls */
156 char *tmp;
157
158 if(str)
159 pos = str; /* new string scan */
160
161 while(pos && *pos && strchr(fs, *pos) != NULL)
162 ++pos; /* skip leading separators */
163
164 if(!pos || !*pos)
165 return (pos = *save = NULL); /* string contains only sep's */
166
167 tmp = pos; /* now, keep position of the token */
168
169 while(*pos && strchr(fs, *pos) == NULL)
170 ++pos; /* skip content of the token */
171
172 if(*pos)
173 *pos++ = '\0'; /* remove first sep after the token */
174 else
175 pos = NULL; /* end of string */
176
177 *save = pos;
178 return tmp;
179 }
180
181 /*
182 * Copyright (c) 1996-1999 by Internet Software Consortium.
183 *
184 * Permission to use, copy, modify, and distribute this software for any
185 * purpose with or without fee is hereby granted, provided that the above
186 * copyright notice and this permission notice appear in all copies.
187 *
188 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
189 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
190 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
191 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
192 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
193 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
194 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
195 * SOFTWARE.
196 */
197
198 #define SPRINTF(x) ((size_t)rb_sprintf x)
199
200 /*
201 * WARNING: Don't even consider trying to compile this on a system where
202 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
203 */
204
205 static const char *inet_ntop4(const u_char * src, char *dst, unsigned int size);
206 #ifdef RB_IPV6
207 static const char *inet_ntop6(const u_char * src, char *dst, unsigned int size);
208 #endif
209
210 /* const char *
211 * inet_ntop4(src, dst, size)
212 * format an IPv4 address
213 * return:
214 * `dst' (as a const)
215 * notes:
216 * (1) uses no statics
217 * (2) takes a u_char* not an in_addr as input
218 * author:
219 * Paul Vixie, 1996.
220 */
221 static const char *
222 inet_ntop4(const unsigned char *src, char *dst, unsigned int size)
223 {
224 if(size < 16)
225 return NULL;
226 return strcpy(dst, inetntoa((const char *) src));
227 }
228
229 /* const char *
230 * inet_ntop6(src, dst, size)
231 * convert IPv6 binary address into presentation (printable) format
232 * author:
233 * Paul Vixie, 1996.
234 */
235 #ifdef RB_IPV6
236 static const char *
237 inet_ntop6(const unsigned char *src, char *dst, unsigned int size)
238 {
239 /*
240 * Note that int32_t and int16_t need only be "at least" large enough
241 * to contain a value of the specified size. On some systems, like
242 * Crays, there is no such thing as an integer variable with 16 bits.
243 * Keep this in mind if you think this function should have been coded
244 * to use pointer overlays. All the world's not a VAX.
245 */
246 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
247 struct
248 {
249 int base, len;
250 }
251 best, cur;
252 u_int words[IN6ADDRSZ / INT16SZ];
253 int i;
254
255 /*
256 * Preprocess:
257 * Copy the input (bytewise) array into a wordwise array.
258 * Find the longest run of 0x00's in src[] for :: shorthanding.
259 */
260 memset(words, '\0', sizeof words);
261 for(i = 0; i < IN6ADDRSZ; i += 2)
262 words[i / 2] = (src[i] << 8) | src[i + 1];
263 best.base = -1;
264 cur.base = -1;
265 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
266 {
267 if(words[i] == 0)
268 {
269 if(cur.base == -1)
270 cur.base = i, cur.len = 1;
271 else
272 cur.len++;
273 }
274 else
275 {
276 if(cur.base != -1)
277 {
278 if(best.base == -1 || cur.len > best.len)
279 best = cur;
280 cur.base = -1;
281 }
282 }
283 }
284 if(cur.base != -1)
285 {
286 if(best.base == -1 || cur.len > best.len)
287 best = cur;
288 }
289 if(best.base != -1 && best.len < 2)
290 best.base = -1;
291
292 /*
293 * Format the result.
294 */
295 tp = tmp;
296 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
297 {
298 /* Are we inside the best run of 0x00's? */
299 if(best.base != -1 && i >= best.base && i < (best.base + best.len))
300 {
301 if(i == best.base)
302 {
303 if(i == 0)
304 *tp++ = '0';
305 *tp++ = ':';
306 }
307 continue;
308 }
309 /* Are we following an initial run of 0x00s or any real hex? */
310 if(i != 0)
311 *tp++ = ':';
312 /* Is this address an encapsulated IPv4? */
313 if(i == 6 && best.base == 0 &&
314 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
315 {
316 if(!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
317 return (NULL);
318 tp += strlen(tp);
319 break;
320 }
321 tp += SPRINTF((tp, "%x", words[i]));
322 }
323 /* Was it a trailing run of 0x00's? */
324 if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
325 *tp++ = ':';
326 *tp++ = '\0';
327
328 /*
329 * Check for overflow, copy, and we're done.
330 */
331
332 if((unsigned int) (tp - tmp) > size)
333 {
334 return (NULL);
335 }
336 return strcpy(dst, tmp);
337 }
338 #endif
339
340 char *
341 strip_colour(char *string)
342 {
343 char *c = string;
344 char *c2 = string;
345 char *last_non_space = NULL;
346 /* c is source, c2 is target */
347 for(; c && *c; c++)
348 switch (*c)
349 {
350 case 3:
351 if(isdigit(c[1]))
352 {
353 c++;
354 if(isdigit(c[1]))
355 c++;
356 if(c[1] == ',' && isdigit(c[2]))
357 {
358 c += 2;
359 if(isdigit(c[1]))
360 c++;
361 }
362 }
363 break;
364 case 2:
365 case 6:
366 case 7:
367 case 22:
368 case 23:
369 case 27:
370 case 31:
371 break;
372 case 32:
373 *c2++ = *c;
374 break;
375 default:
376 *c2++ = *c;
377 last_non_space = c2;
378 break;
379 }
380 *c2 = '\0';
381 if(last_non_space)
382 *last_non_space = '\0';
383 return string;
384 }