diff --git a/configure.ac b/configure.ac index a1a3c1b..33e9cc2 100644 --- a/configure.ac +++ b/configure.ac @@ -189,6 +189,34 @@ AS_IF([test "x$WITH_PCRE" == "xyes"], [ AC_DEFINE([WITH_PCRE],[],[Compile With Perl Compatible regular expressions support]) ], []) +#### +#### PCRE2 Support +#### +AC_ARG_WITH([pcre2], + AS_HELP_STRING([--with-pcre2], [Enable Perl compatible regular expressions (v2)]), + [AC_SUBST(WITH_PCRE2, $withval)], + [AC_SUBST(WITH_PCRE2, no)] +) + +AS_IF([test "x$WITH_PCRE2" == "xyes"], [ + AS_IF([test "x$WITH_PCRE" == "xyes"], [ + AC_MSG_ERROR([libpcre-2 and libpcre-3 can not be enabled at the same time ]) + ], []) + AC_DEFINE([PCRE2_CODE_UNIT_WIDTH], [8], [Required for including pcre2.h]) + AC_SUBST(PCRE2_CODE_UNIT_WIDTH, 8) + m4_ifdef([PKG_CHECK_MODULES], [ + PKG_CHECK_MODULES([PCRE2], [libpcre2-8]) + ], [ + AC_CHECK_HEADER([pcre2.h], [], [ + AC_MSG_ERROR([ You need libpcre2 development files installed to compile with pcre support.]) + ]) + AC_CHECK_LIB([pcre2-8], [pcre2_compile_8], [], [ + AC_MSG_ERROR([ You need libpcre2 library installed to compile with pcre support.]) + ]) + ]) + AC_DEFINE([WITH_PCRE2],[],[Compile With Perl Compatible regular expressions support]) +], []) + #### #### IPv6 Support #### @@ -228,7 +256,8 @@ AS_IF([test "x$USE_EEP" == "xyes"], [ ], []) -# Conditional Source inclusion +# Conditional Source inclusion +AM_CONDITIONAL([WITH_PCRE2], [test "x$WITH_PCRE2" == "xyes"]) AM_CONDITIONAL([WITH_GNUTLS], [test "x$WITH_GNUTLS" == "xyes"]) AM_CONDITIONAL([WITH_OPENSSL], [test "x$WITH_OPENSSL" == "xyes"]) AM_CONDITIONAL([USE_EEP], [test "x$USE_EEP" == "xyes"]) @@ -259,6 +288,7 @@ AC_MSG_NOTICE( GnuTLS Support : ${WITH_GNUTLS} ) AC_MSG_NOTICE( OpenSSL Support : ${WITH_OPENSSL} ) AC_MSG_NOTICE( Unicode Support : ${UNICODE} ) AC_MSG_NOTICE( Perl Expressions Support : ${WITH_PCRE} ) +AC_MSG_NOTICE( Perl Expressions Support (v2): ${WITH_PCRE2} ) AC_MSG_NOTICE( IPv6 Support : ${USE_IPV6} ) AC_MSG_NOTICE( EEP Support : ${USE_EEP} ) AC_MSG_NOTICE( ====================================================== ) diff --git a/src/Makefile.am b/src/Makefile.am index b338273..c6d7a1d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,6 +16,10 @@ sngrep_SOURCES+=capture_openssl.c sngrep_CFLAGS+=$(SSL_CFLAGS) sngrep_LDADD+=$(SSL_LIBS) endif +if WITH_PCRE2 +sngrep_CFLAGS+=$(PCRE2_CFLAGS) +sngrep_LDADD+=$(PCRE2_LIBS) +endif sngrep_SOURCES+=address.c packet.c sip.c sip_call.c sip_msg.c sip_attr.c main.c sngrep_SOURCES+=option.c group.c filter.c keybinding.c media.c setting.c rtp.c sngrep_SOURCES+=util.c hash.c vector.c curses/ui_panel.c curses/scrollbar.c diff --git a/src/filter.c b/src/filter.c index a60f538..a4e7286 100644 --- a/src/filter.c +++ b/src/filter.c @@ -61,7 +61,29 @@ filter_set(int type, const char *expr) // Set new expresion values filters[type].expr = (expr) ? strdup(expr) : NULL; filters[type].regex = regex; +#elifdef WITH_PCRE2 + pcre2_code *regex = NULL; + // If we have an expression, check if compiles before changing the filter + if (expr) { + int re_err = 0; + PCRE2_SIZE err_offset = 0; + uint32_t pcre_options = PCRE2_UNGREEDY | PCRE2_CASELESS; + + // Check if we have a valid expression + if (!(regex = pcre2_compile((PCRE2_SPTR) expr, PCRE2_ZERO_TERMINATED, pcre_options, &re_err, &err_offset, NULL))) + return 1; + } + + // Remove previous value + if (filters[type].expr) { + sng_free(filters[type].expr); + pcre2_code_free(filters[type].regex); + } + + // Set new expresion values + filters[type].expr = (expr) ? strdup(expr) : NULL; + filters[type].regex = regex; #else regex_t regex; // If we have an expression, check if compiles before changing the filter @@ -184,6 +206,11 @@ filter_check_expr(filter_t filter, const char *data) { #ifdef WITH_PCRE return pcre_exec(filter.regex, 0, data, strlen(data), 0, 0, 0, 0); +#elifdef WITH_PCRE2 + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(filter.regex, NULL); + int ret = pcre2_match(filter.regex, (PCRE2_SPTR) data, (PCRE2_SIZE) strlen(data), 0, 0, match_data, NULL); + pcre2_match_data_free(match_data); + return (ret == PCRE2_ERROR_NOMATCH) ? 1 : 0; #else // Call doesn't match this filter return regexec(&filter.regex, data, 0, NULL, 0); diff --git a/src/filter.h b/src/filter.h index 1bc1786..717ea5e 100644 --- a/src/filter.h +++ b/src/filter.h @@ -43,6 +43,8 @@ #include "config.h" #ifdef WITH_PCRE #include +#elifdef WITH_PCRE2 +#include #else #include #endif @@ -82,6 +84,9 @@ struct filter { #ifdef WITH_PCRE //! The filter compiled expression pcre *regex; +#elifdef WITH_PCRE2 + //! The filter compiled expression + pcre2_code *regex; #else //! The filter compiled expression regex_t regex; diff --git a/src/sip.c b/src/sip.c index 643176c..cb9de33 100644 --- a/src/sip.c +++ b/src/sip.c @@ -832,6 +832,17 @@ sip_set_match_expression(const char *expr, int insensitive, int invert) // Check if we have a valid expression calls.match_regex = pcre_compile(expr, pflags, &re_err, &err_offset, 0); return calls.match_regex == NULL; +#elifdef WITH_PCRE2 + int re_err = 0; + PCRE2_SIZE err_offset = 0; + uint32_t pflags = PCRE2_UNGREEDY | PCRE2_CASELESS; + + if (insensitive) + pflags |= PCRE2_CASELESS; + + // Check if we have a valid expression + calls.match_regex = pcre2_compile((PCRE2_SPTR) expr, PCRE2_ZERO_TERMINATED, pflags, &re_err, &err_offset, NULL); + return calls.match_regex == NULL; #else int cflags = REG_EXTENDED; @@ -863,6 +874,16 @@ sip_check_match_expression(const char *payload) return 1 == calls.match_invert; } + return 0 == calls.match_invert; +#elifdef WITH_PCRE2 + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(calls.match_regex, NULL); + int ret = pcre2_match(calls.match_regex, (PCRE2_SPTR) payload, (PCRE2_SIZE) strlen(payload), 0, 0, match_data, NULL); + pcre2_match_data_free(match_data); + + if (ret == PCRE2_ERROR_NOMATCH) { + return 1 == calls.match_invert; + } + return 0 == calls.match_invert; #else // Check if payload matches the given expresion diff --git a/src/sip.h b/src/sip.h index b20be1a..7cbc76b 100644 --- a/src/sip.h +++ b/src/sip.h @@ -37,6 +37,8 @@ #include #ifdef WITH_PCRE #include +#elifdef WITH_PCRE2 +#include #endif #include "sip_call.h" #include "vector.h" @@ -141,6 +143,9 @@ struct sip_call_list { #ifdef WITH_PCRE //! Compiled match expression pcre *match_regex; +#elifdef WITH_PCRE2 + //! Compiled match expression + pcre2_code *match_regex; #else //! Compiled match expression regex_t match_regex;