Skip to content

Commit c9a6b5a

Browse files
committed
event_flatstore: add escape_delimiter parameter to replace delimiters inside field values
1 parent 0adcc69 commit c9a6b5a

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

modules/event_flatstore/doc/event_flatstore_admin.xml

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,35 @@ modparam("event_flatstore", "delimiter", ";")
106106
</programlisting>
107107
</example>
108108
</section>
109+
<section id="param_escape_delimiter" xreflabel="escape_delimiter">
110+
<title><varname>escape_delimiter</varname> (string)</title>
111+
<para>
112+
Optional replacement sequence that will be written <emphasis>instead
113+
of</emphasis> the <link linkend="param_delimiter"><varname>delimiter</varname></link>
114+
whenever this character (or sequence) occurs inside a string
115+
parameter.
116+
This allows you to keep the log file parse-friendly even when user
117+
data itself may contain delimiter symbols.
118+
</para>
119+
<para>
120+
If set, its length <emphasis>must be exactly equal</emphasis> to the
121+
length of <varname>delimiter</varname>.
122+
</para>
123+
<para>
124+
<emphasis>
125+
Default value is <quote>""</quote> (escaping disabled).
126+
</emphasis>
127+
</para>
128+
<example>
129+
<title>Enable escaping of ',' with '|'</title>
130+
<programlisting format="linespecific">
131+
...
132+
modparam("event_flatstore", "delimiter", ",")
133+
modparam("event_flatstore", "escape_delimiter", "|")
134+
...
135+
</programlisting>
136+
</example>
137+
</section>
109138
<section id="param_file_permissions" xreflabel="file_permissions">
110139
<title><varname>file_permissions</varname> (string)</title>
111140
<para>
@@ -260,9 +289,7 @@ modparam("event_flatstore", "suffix", "$time(%Y)")
260289
MI FIFO Command Format:
261290
</para>
262291
<programlisting format="linespecific">
263-
...
264292
opensips-cli -x mi evi_flat_rotate _path_to_log_file_
265-
...
266293
</programlisting>
267294
</section>
268295
</section>
@@ -298,7 +325,8 @@ opensips-cli -x mi evi_flat_rotate _path_to_log_file_
298325
<emphasis>filename</emphasis> – full path of the new log file.
299326
</para></listitem>
300327
<listitem><para>
301-
<emphasis>old_filename</emphasis> – full path of the previous log file.
328+
<emphasis>old_filename</emphasis> – full path of the previous
329+
log file, or empty string if none existed.
302330
</para></listitem>
303331
</itemizedlist>
304332
</section>

modules/event_flatstore/event_flatstore.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static unsigned long file_rotate_count;
8282
static unsigned long file_rotate_size;
8383
static str file_suffix;
8484
static pv_elem_p file_suffix_format;
85+
static str escape_delimiter = {0, 0};
8586

8687
static void raise_rotation_event(struct flat_file *file, const char *reason);
8788
static void update_counters_and_rotate(struct flat_file *file,
@@ -114,6 +115,7 @@ static const param_export_t mod_params[] = {
114115
{"rotate_count", INT_PARAM|STR_PARAM|USE_FUNC_PARAM, (void*)rotate_count_param},
115116
{"rotate_size", INT_PARAM|STR_PARAM|USE_FUNC_PARAM, (void*)rotate_size_param},
116117
{"suffix", STR_PARAM, &file_suffix.s},
118+
{"escape_delimiter", STR_PARAM, &escape_delimiter.s},
117119
{0,0,0}
118120
};
119121

@@ -281,6 +283,17 @@ static int mod_init(void) {
281283
LM_DBG("The delimiter for separating columns in files was set at %.*s\n", delimiter.len, delimiter.s);
282284
}
283285

286+
if (escape_delimiter.s) {
287+
escape_delimiter.len = strlen(escape_delimiter.s);
288+
if (escape_delimiter.len != delimiter.len) {
289+
LM_ERR("\"escape_delimiter\" length (%d) must match \"delimiter\" length (%d)\n",
290+
escape_delimiter.len, delimiter.len);
291+
return -1;
292+
}
293+
LM_DBG("Delimiter escaping enabled: \"%.*s\" → \"%.*s\"\n",
294+
delimiter.len, delimiter.s, escape_delimiter.len, escape_delimiter.s);
295+
}
296+
284297
if (initial_capacity <= 0 || initial_capacity > 65535) {
285298
LM_WARN("bad value for maximum open sockets (%d)\n", initial_capacity);
286299
initial_capacity = FLAT_DEFAULT_MAX_FD;
@@ -878,6 +891,27 @@ static int flat_raise(struct sip_msg *msg, str* ev_name, evi_reply_sock *sock,
878891
}
879892
}
880893

894+
/* if escape_delimiter is configured, replace any in-value
895+
* occurrences of the delimiter with the escape sequence */
896+
if (escape_delimiter.s) {
897+
if (delimiter.len == 1) { /* fast single-char */
898+
for (i = 0; i < param->val.s.len; i++)
899+
if (param->val.s.s[i] == delimiter.s[0])
900+
param->val.s.s[i] = escape_delimiter.s[0];
901+
} else { /* multi-char delim */
902+
char *p = param->val.s.s;
903+
char *end = p + param->val.s.len - delimiter.len;
904+
while (p <= end) {
905+
if (memcmp(p, delimiter.s, delimiter.len) == 0) {
906+
memcpy(p, escape_delimiter.s, delimiter.len);
907+
p += delimiter.len;
908+
end = param->val.s.s + param->val.s.len - delimiter.len;
909+
} else {
910+
p++;
911+
}
912+
}
913+
}
914+
}
881915
io_param[idx].iov_base = param->val.s.s;
882916
io_param[idx].iov_len = param->val.s.len;
883917
idx++;

0 commit comments

Comments
 (0)