1 /* text_import_regex.c
2  * Regex based text importer
3  * March 2021, Paul Weiß <paulniklasweiss@gmail.com>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Based on text_import.c by Jaap Keuter <jaap.keuter@xs4all.nl>
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13 
14 #include "config.h"
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 
19 #include <glib.h>
20 
21 #include "text_import.h"
22 #include "text_import_regex.h"
23 
24 typedef unsigned int uint;
25 
26 /*--- Options --------------------------------------------------------------------*/
27 
28 static int debug = 0;
29 
30 #define debug_printf(level,  ...) \
31     if (debug >= (level)) { \
32         printf(__VA_ARGS__); \
33     }
34 
text_import_regex(const text_import_info_t * info)35 int text_import_regex(const text_import_info_t* info) {
36     int status = 1;
37     int parsed_packets = 0;
38     debug_printf(1, "starting import...\n");
39 
40     // IO
41     GMappedFile* file = g_mapped_file_ref(info->regex.import_text_GMappedFile);
42     GError* gerror = NULL;
43     gsize f_size = g_mapped_file_get_length(file);
44     guchar* f_content = g_mapped_file_get_contents(file);
45     { /* zero terminate the file */
46         if (f_content[f_size -  1] != '\n') {
47             fprintf(stderr, "Error: file did not end on \\n\n");
48             g_mapped_file_unref(file);
49             return -1;
50         }
51         f_content[f_size] = 0;
52     }
53 
54     // Regex result dissecting
55     gboolean re_time, re_dir, re_seqno;
56     GMatchInfo* match;
57     gint field_start;
58     gint field_end;
59     { /* analyze regex */
60         re_time = g_regex_get_string_number(info->regex.format, "time") >= 0;
61         re_dir = g_regex_get_string_number(info->regex.format, "dir") >= 0;
62         re_seqno = g_regex_get_string_number(info->regex.format, "seqno") >= 0;
63         if (g_regex_get_string_number(info->regex.format, "data") < 0) {
64             /* This should never happen, as the dialog checks for this */
65             fprintf(stderr, "Error could not find data in pattern\n");
66             g_mapped_file_unref(file);
67             return -1;
68         }
69     }
70 
71     debug_printf(1, "regex has %s%s%s\n", re_dir ? "dir, " : "",
72                                           re_time ? "time, " : "",
73                                           re_seqno ? "seqno, " : "");
74     g_regex_match(info->regex.format, f_content, G_REGEX_MATCH_NOTEMPTY, &match);
75     while (g_match_info_matches(match)) {
76         /* parse the data */
77         if (!g_match_info_fetch_named_pos(match, "data", &field_start, &field_end)) {
78             fprintf(stderr, "Warning: could not fetch data on would be packet %d, discarding\n", parsed_packets + 1);
79             continue;
80         }
81         parse_data(f_content + field_start, f_content + field_end, info->regex.encoding);
82 
83         /* parse the auxillary information if present */
84         if (re_time &&
85                 g_match_info_fetch_named_pos(match, "time", &field_start, &field_end)) {
86             parse_time(f_content + field_start, f_content + field_end, info->timestamp_format);
87 	} else {
88             /* No time present, so add a fixed delta. */
89             parse_time(NULL, NULL, NULL);
90         }
91 
92         if (re_dir &&
93                 g_match_info_fetch_named_pos(match, "dir", &field_start, &field_end))
94             parse_dir(f_content + field_start, f_content + field_end, info->regex.in_indication, info->regex.out_indication);
95 
96         if (re_seqno &&
97                 g_match_info_fetch_named_pos(match, "seqno", &field_start, &field_end))
98             parse_seqno(f_content + field_start, f_content + field_end);
99 
100         if (debug >= 2) {
101             g_match_info_fetch_pos(match, 0, &field_start, &field_end);
102             printf("Packet %d at %x to %x: %.*s\n", parsed_packets + 1,
103                     field_start, field_end,
104                     field_end - field_start, f_content + field_start);
105         }
106         flush_packet();
107 
108 
109         /* prepare next packet */
110         ++parsed_packets;
111         g_match_info_next(match, &gerror);
112         if (gerror && gerror->code) {
113             status = -1;
114             g_error_free(gerror);
115             break;
116         }
117     }
118     debug_printf(1, "processed %d packets\n", parsed_packets);
119     g_match_info_unref(match);
120     g_mapped_file_unref(file);
121     return status * parsed_packets;
122 }
123