master
c 149 lines 4.15 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "log2journal.h"
4
5 #define PCRE2_ERROR_LINE_MAX 1024
6 #define PCRE2_KEY_MAX 1024
7
8 struct pcre2_state {
9 LOG_JOB *jb;
10
11 const char *line;
12 uint32_t pos;
13 uint32_t key_start;
14
15 pcre2_code *re;
16 pcre2_match_data *match_data;
17
18 char key[PCRE2_KEY_MAX];
19 char msg[PCRE2_ERROR_LINE_MAX];
20 };
21
22 static inline void copy_and_convert_key(PCRE2_STATE *pcre2, const char *key) {
23 char *d = &pcre2->key[pcre2->key_start];
24 size_t remaining = sizeof(pcre2->key) - pcre2->key_start;
25
26 while(remaining >= 2 && *key) {
27 *d = journal_key_characters_map[(unsigned char)*key];
28 remaining--;
29 key++;
30 d++;
31 }
32
33 *d = '\0';
34 }
35
36 static inline void jb_traverse_pcre2_named_groups_and_send_keys(PCRE2_STATE *pcre2, pcre2_code *re, pcre2_match_data *match_data, char *line) {
37 PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
38 uint32_t names_count;
39 pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &names_count);
40
41 if (names_count > 0) {
42 PCRE2_SPTR name_table;
43 pcre2_pattern_info(re, PCRE2_INFO_NAMETABLE, &name_table);
44 uint32_t name_entry_size;
45 pcre2_pattern_info(re, PCRE2_INFO_NAMEENTRYSIZE, &name_entry_size);
46
47 const unsigned char *table_ptr = name_table;
48 for (uint32_t i = 0; i < names_count; i++) {
49 int n = (table_ptr[0] << 8) | table_ptr[1];
50 const char *group_name = (const char *)(table_ptr + 2);
51
52 PCRE2_SIZE start_offset = ovector[2 * n];
53 PCRE2_SIZE end_offset = ovector[2 * n + 1];
54 PCRE2_SIZE group_length = end_offset - start_offset;
55
56 copy_and_convert_key(pcre2, group_name);
57 log_job_send_extracted_key_value(pcre2->jb, pcre2->key, line + start_offset, group_length);
58
59 table_ptr += name_entry_size;
60 }
61 }
62 }
63
64 void pcre2_get_error_in_buffer(char *msg, size_t msg_len, int rc, int pos) {
65 int l;
66
67 if(pos >= 0)
68 l = snprintf(msg, msg_len, "PCRE2 error %d at pos %d on: ", rc, pos);
69 else
70 l = snprintf(msg, msg_len, "PCRE2 error %d on: ", rc);
71
72 pcre2_get_error_message(rc, (PCRE2_UCHAR *)&msg[l], msg_len - l);
73 }
74
75 static void pcre2_error_message(PCRE2_STATE *pcre2, int rc, int pos) {
76 pcre2_get_error_in_buffer(pcre2->msg, sizeof(pcre2->msg), rc, pos);
77 }
78
79 bool pcre2_has_error(PCRE2_STATE *pcre2) {
80 return !pcre2->re || pcre2->msg[0];
81 }
82
83 PCRE2_STATE *pcre2_parser_create(LOG_JOB *jb) {
84 PCRE2_STATE *pcre2 = mallocz(sizeof(PCRE2_STATE));
85 memset(pcre2, 0, sizeof(PCRE2_STATE));
86 pcre2->jb = jb;
87
88 if(jb->prefix)
89 pcre2->key_start = copy_to_buffer(pcre2->key, sizeof(pcre2->key), pcre2->jb->prefix, strlen(pcre2->jb->prefix));
90
91 int rc;
92 PCRE2_SIZE pos;
93 pcre2->re = pcre2_compile((PCRE2_SPTR)jb->pattern, PCRE2_ZERO_TERMINATED, 0, &rc, &pos, NULL);
94 if (!pcre2->re) {
95 pcre2_error_message(pcre2, rc, pos);
96 return pcre2;
97 }
98
99 pcre2->match_data = pcre2_match_data_create_from_pattern(pcre2->re, NULL);
100
101 return pcre2;
102 }
103
104 void pcre2_parser_destroy(PCRE2_STATE *pcre2) {
105 if(pcre2) {
106 if(pcre2->re)
107 pcre2_code_free(pcre2->re);
108
109 if(pcre2->match_data)
110 pcre2_match_data_free(pcre2->match_data);
111
112 freez(pcre2);
113 }
114 }
115
116 const char *pcre2_parser_error(PCRE2_STATE *pcre2) {
117 return pcre2->msg;
118 }
119
120 bool pcre2_parse_document(PCRE2_STATE *pcre2, const char *txt, size_t len) {
121 pcre2->line = txt;
122 pcre2->pos = 0;
123 pcre2->msg[0] = '\0';
124
125 if(!len)
126 len = strlen(txt);
127
128 int rc = pcre2_match(pcre2->re, (PCRE2_SPTR)pcre2->line, len, 0, 0, pcre2->match_data, NULL);
129 if(rc < 0) {
130 pcre2_error_message(pcre2, rc, -1);
131 return false;
132 }
133
134 jb_traverse_pcre2_named_groups_and_send_keys(pcre2, pcre2->re, pcre2->match_data, (char *)pcre2->line);
135
136 return true;
137 }
138
139 void pcre2_test(void) {
140 LOG_JOB jb = { 0 };
141 log_job_init(&jb);
142 log_job_key_prefix_set(&jb, "NGINX_", 6);
143 PCRE2_STATE *pcre2 = pcre2_parser_create(&jb);
144
145 pcre2_parse_document(pcre2, "{\"value\":\"\\u\\u039A\\u03B1\\u03BB\\u03B7\\u03BC\\u03AD\\u03C1\\u03B1\"}", 0);
146
147 pcre2_parser_destroy(pcre2);
148 log_job_cleanup(&jb);
149 }