2 * String utility routines
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 * Given a pointer into a data buffer, and to the end of the buffer,
44 * find the end of the (putative) line at that position in the data
46 * Return a pointer to the EOL character(s) in "*eol".
49 find_line_end(const guchar *data, const guchar *dataend, const guchar **eol)
51 const guchar *lineend;
53 lineend = memchr(data, '\n', dataend - data);
54 if (lineend == NULL) {
56 * No LF - line is probably continued in next TCP segment.
62 * Is the LF at the beginning of the line?
66 * No - is it preceded by a carriage return?
67 * (Perhaps it's supposed to be, but that's not guaranteed....)
69 if (*(lineend - 1) == '\r') {
71 * Yes. The EOL starts with the CR.
76 * No. The EOL starts with the LF.
81 * I seem to remember that we once saw lines ending with LF-CR
82 * in an HTTP request or response, so check if it's *followed*
83 * by a carriage return.
85 if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
87 * It's <non-LF><LF><CR>; say it ends with the CR.
94 * Yes - the EOL starts with the LF.
100 * Point to the character after the last character.
108 * Get the length of the next token in a line, and the beginning of the
109 * next token after that (if any).
110 * Return 0 if there is no next token.
113 get_token_len(const guchar *linep, const guchar *lineend,
114 const guchar **next_token)
116 const guchar *tokenp;
122 * Search for a blank, a CR or an LF, or the end of the buffer.
124 while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
126 token_len = linep - tokenp;
129 * Skip trailing blanks.
131 while (linep < lineend && *linep == ' ')
140 #define INITIAL_FMTBUF_SIZE 128
142 #if GLIB_MAJOR_VERSION >= 2
144 * XXX - "isprint()" can return "true" for non-ASCII characters, but
145 * those don't work with GTK+ 1.3 or later, as they take UTF-8 strings
146 * as input. Until we fix up Wireshark to properly handle non-ASCII
147 * characters in all output (both GUI displays and text printouts)
148 * in those versions of GTK+, we work around the problem by escaping
149 * all characters that aren't printable ASCII.
151 * We don't know what version of GTK+ we're using, as epan doesn't
152 * use any GTK+ stuff; we use GLib as a proxy for that, with GLib 2.x
153 * implying GTK+ 1.3 or later (we don't support GLib 1.3[.x]).
156 #define isprint(c) (c >= 0x20 && c < 0x7f)
160 * Given a string, generate a string from it that shows non-printable
161 * characters as C-style escapes, and return a pointer to it.
164 format_text(const guchar *string, int len)
166 static gchar *fmtbuf[3];
167 static int fmtbuf_len[3];
170 const guchar *stringend = string + len;
177 * Allocate the buffer if it's not already allocated.
179 if (fmtbuf[idx] == NULL) {
180 fmtbuf[idx] = g_malloc(INITIAL_FMTBUF_SIZE);
181 fmtbuf_len[idx] = INITIAL_FMTBUF_SIZE;
184 while (string < stringend) {
186 * Is there enough room for this character, if it expands to
187 * a backslash plus 3 octal digits (which is the most it can
188 * expand to), and also enough room for a terminating '\0'?
190 if (column+3+1 >= fmtbuf_len[idx]) {
192 * Double the buffer's size if it's not big enough.
193 * The size of the buffer starts at 128, so doubling its size
194 * adds at least another 128 bytes, which is more than enough
195 * for one more character plus a terminating '\0'.
197 fmtbuf_len[idx] = fmtbuf_len[idx] * 2;
198 fmtbuf[idx] = g_realloc(fmtbuf[idx], fmtbuf_len[idx]);
203 fmtbuf[idx][column] = c;
206 fmtbuf[idx][column] = '\\';
211 fmtbuf[idx][column] = 'a';
216 fmtbuf[idx][column] = 'b'; /* BS */
221 fmtbuf[idx][column] = 'f'; /* FF */
226 fmtbuf[idx][column] = 'n'; /* NL */
231 fmtbuf[idx][column] = 'r'; /* CR */
236 fmtbuf[idx][column] = 't'; /* tab */
241 fmtbuf[idx][column] = 'v';
247 fmtbuf[idx][column] = i + '0';
250 fmtbuf[idx][column] = i + '0';
253 fmtbuf[idx][column] = i + '0';
259 fmtbuf[idx][column] = '\0';
264 * Given a string, generate a string from it that shows non-printable
265 * characters as C-style escapes except a whitespace character
266 * (space, tab, carriage return, new line, vertical tab, or formfeed)
267 * which will be replaved by a space, and return a pointer to it.
270 format_text_wsp(const guchar *string, int len)
272 static gchar *fmtbuf[3];
273 static int fmtbuf_len[3];
276 const guchar *stringend = string + len;
283 * Allocate the buffer if it's not already allocated.
285 if (fmtbuf[idx] == NULL) {
286 fmtbuf[idx] = g_malloc(INITIAL_FMTBUF_SIZE);
287 fmtbuf_len[idx] = INITIAL_FMTBUF_SIZE;
290 while (string < stringend) {
292 * Is there enough room for this character, if it expands to
293 * a backslash plus 3 octal digits (which is the most it can
294 * expand to), and also enough room for a terminating '\0'?
296 if (column+3+1 >= fmtbuf_len[idx]) {
298 * Double the buffer's size if it's not big enough.
299 * The size of the buffer starts at 128, so doubling its size
300 * adds at least another 128 bytes, which is more than enough
301 * for one more character plus a terminating '\0'.
303 fmtbuf_len[idx] = fmtbuf_len[idx] * 2;
304 fmtbuf[idx] = g_realloc(fmtbuf[idx], fmtbuf_len[idx]);
309 fmtbuf[idx][column] = c;
311 } else if (isspace(c)) {
312 fmtbuf[idx][column] = ' ';
315 fmtbuf[idx][column] = '\\';
320 fmtbuf[idx][column] = 'a';
325 fmtbuf[idx][column] = 'b'; /* BS */
330 fmtbuf[idx][column] = 'f'; /* FF */
335 fmtbuf[idx][column] = 'n'; /* NL */
340 fmtbuf[idx][column] = 'r'; /* CR */
345 fmtbuf[idx][column] = 't'; /* tab */
350 fmtbuf[idx][column] = 'v';
356 fmtbuf[idx][column] = i + '0';
359 fmtbuf[idx][column] = i + '0';
362 fmtbuf[idx][column] = i + '0';
368 fmtbuf[idx][column] = '\0';
372 /* Max string length for displaying byte string. */
373 #define MAX_BYTE_STR_LEN 48
375 /* Turn an array of bytes into a string showing the bytes in hex. */
376 #define N_BYTES_TO_STR_STRINGS 6
378 bytes_to_str(const guint8 *bd, int bd_len) {
379 return bytes_to_str_punct(bd,bd_len,'\0');
382 /* Turn an array of bytes into a string showing the bytes in hex with
383 * punct as a bytes separator.
386 bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
390 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
391 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
393 cur=ep_alloc(MAX_BYTE_STR_LEN+3+1);
395 len = MAX_BYTE_STR_LEN;
396 while (bd_len > 0 && len > 0) {
397 *p++ = hex[(*bd) >> 4];
398 *p++ = hex[(*bd) & 0xF];
402 if(punct && bd_len > 0){
408 /* Note that we're not showing the full string. */
418 is_byte_sep(guint8 c)
420 return (c == '-' || c == ':' || c == '.');
423 /* Turn a string of hex digits with optional separators (defined by
424 * is_byte_sep() into a byte array.
427 hex_str_to_bytes(const char *hex_str, GByteArray *bytes, gboolean force_separators) {
429 const guchar *p, *q, *punct;
433 g_byte_array_set_size(bytes, 0);
437 p = (const guchar *)hex_str;
440 if (*q && isxdigit(*p) && isxdigit(*q)) {
443 two_digits[2] = '\0';
446 * Two or more hex digits in a row.
447 * "strtoul()" will succeed, as it'll see at
448 * least one hex digit.
450 val = (guint8) strtoul(two_digits, NULL, 16);
451 g_byte_array_append(bytes, &val, 1);
455 * Make sure the character after
456 * the second hex digit is a byte
457 * separator, i.e. that we don't have
458 * more than two hex digits, or a
461 if (is_byte_sep(*punct)) {
465 else if (force_separators) {
473 else if (*q && isxdigit(*p) && is_byte_sep(*q)) {
478 * Only one hex digit.
479 * "strtoul()" will succeed, as it'll see that
482 val = (guint8) strtoul(one_digit, NULL, 16);
483 g_byte_array_append(bytes, &val, 1);
487 else if (!*q && isxdigit(*p)) {
492 * Only one hex digit.
493 * "strtoul()" will succeed, as it'll see that
496 val = (guint8) strtoul(one_digit, NULL, 16);
497 g_byte_array_append(bytes, &val, 1);
508 #define SUBID_BUF_LEN 5
510 oid_str_to_bytes(const char *oid_str, GByteArray *bytes) {
511 guint32 subid0, subid, sicnt, i;
513 guint8 buf[SUBID_BUF_LEN];
515 g_byte_array_set_size(bytes, 0);
521 if (!isdigit(*p) && (*p != '.')) return FALSE;
523 if (p == oid_str) return FALSE;
524 if (!*(p+1)) return FALSE;
525 if ((p-1) == dot) return FALSE;
530 if (!dot) return FALSE;
534 subid0 = 0; /* squelch GCC complaints */
537 while (isdigit(*p)) {
544 if (subid0 > 2) return FALSE;
545 } else if (sicnt == 1) {
546 if ((subid0 < 2) && (subid > 39)) return FALSE;
547 subid += 40 * subid0;
553 buf[i] = 0x80 | (subid % 0x80);
555 } while (subid && i);
556 buf[SUBID_BUF_LEN-1] &= 0x7F;
557 g_byte_array_append(bytes, buf + i, SUBID_BUF_LEN - i);
567 /* Return a XML escaped representation of the unescaped string.
568 * The returned string must be freed when no longer in use. */
570 xml_escape(const gchar *unescaped)
572 GString *buffer = g_string_sized_new(128);
575 #if GLIB_MAJOR_VERSION < 2
580 while ( (c = *p++) ) {
583 g_string_append(buffer, "<");
586 g_string_append(buffer, ">");
589 g_string_append(buffer, "&");
592 g_string_append(buffer, "'");
595 g_string_append(buffer, """);
598 g_string_append_c(buffer, c);
602 #if GLIB_MAJOR_VERSION >= 2
603 /* Return the string value contained within the GString
604 * after getting rid of the GString structure.
605 * This is the way to do this, see the GLib reference. */
606 return g_string_free(buffer, FALSE);
608 /* But it's not the way to do it in GLib 1.2[.x], as
609 * 1.2[.x]'s "g_string_free()" doesn't return anything.
610 * This is the way to do this in GLib 1.2[.x]. */
612 g_string_free(buffer, FALSE);
618 /* Return the first occurrence of needle in haystack.
619 * If not found, return NULL.
620 * If either haystack or needle has 0 length, return NULL.
621 * Algorithm copied from GNU's glibc 2.3.2 memcmp() */
623 epan_memmem(const guint8 *haystack, guint haystack_len,
624 const guint8 *needle, guint needle_len)
627 const guint8 *const last_possible
628 = haystack + haystack_len - needle_len;
630 if (needle_len == 0) {
634 if (needle_len > haystack_len) {
638 for (begin = haystack ; begin <= last_possible; ++begin) {
639 if (begin[0] == needle[0] &&
640 !memcmp(&begin[1], needle + 1,
650 * Scan the search string to make sure it's valid hex. Return the
651 * number of bytes in nbytes.
654 convert_string_to_hex(const char *string, size_t *nbytes)
659 guint8 *bytes, *q, byte_val;
668 continue; /* allow white space */
669 if (c==':' || c=='.' || c=='-')
670 continue; /* skip any ':', '.', or '-' between bytes */
672 /* Not a valid hex digit - fail */
677 * We can only match bytes, not nibbles; we must have a valid
678 * hex digit immediately after that hex digit.
684 /* 2 hex digits = 1 byte */
689 * Were we given any hex digits?
697 * OK, it's valid, and it generates "n_bytes" bytes; generate the
700 bytes = g_malloc(n_bytes);
708 continue; /* allow white space */
709 if (c==':' || c=='.' || c=='-')
710 continue; /* skip any ':', '.', or '-' between bytes */
711 /* From the loop above, we know this is a hex digit */
715 byte_val = (c - 'a') + 10;
717 byte_val = (c - 'A') + 10;
720 /* We also know this is a hex digit */
725 byte_val |= (c - 'a') + 10;
727 byte_val |= (c - 'A') + 10;
736 * Copy if if it's a case-sensitive search; uppercase it if it's
737 * a case-insensitive search.
740 convert_string_case(const char *string, gboolean case_insensitive)
747 if (case_insensitive) {
748 out_string = g_malloc(strlen(string) + 1);
749 for (p = &string[0], q = &out_string[0]; (c = *p) != '\0'; p++, q++)
750 *q = toupper((unsigned char)*p);
753 out_string = g_strdup(string);
757 /* g_strlcat() does not exist in GLib 1.2[.x] */
758 #if GLIB_MAJOR_VERSION < 2
760 g_strlcat(gchar *dst, gchar *src, gsize size)
766 g_snprintf(dst+strl, size-strl, "%s", src);