diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d0cf4bef..e7226217b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,7 +193,7 @@ set(ZM_ONVIF "ON" CACHE BOOL "Set to ON to enable basic ONVIF support. This is EXPERIMENTAL and may not work with all cameras claiming to be ONVIF compliant. default: ON") set(ZM_NO_PCRE "OFF" CACHE BOOL - "Set to ON to skip libpcre3 checks and force building ZM without libpcre3. default: OFF") + "Set to ON to skip libpcre2 checks and force building ZM without libpcre2. default: OFF") set(ZM_NO_RTSPSERVER "OFF" CACHE BOOL "Set to ON to skip building ZM with rtsp server support. default: OFF") set(ZM_PERL_MM_PARMS INSTALLDIRS=vendor NO_PACKLIST=1 NO_PERLLOCAL=1 CACHE STRING @@ -424,17 +424,17 @@ endif() # Do not check for cURL if ZM_NO_CURL is on if(NOT ZM_NO_PRCE) # pcre (using find_library and find_path) - find_library(PCRE_LIBRARIES pcre) + find_library(PCRE_LIBRARIES pcre2-8) if(PCRE_LIBRARIES) set(HAVE_LIBPCRE 1) list(APPEND ZM_BIN_LIBS "${PCRE_LIBRARIES}") - find_path(PCRE_INCLUDE_DIR pcre.h) + find_path(PCRE_INCLUDE_DIR pcre2.h) if(PCRE_INCLUDE_DIR) include_directories("${PCRE_INCLUDE_DIR}") set(CMAKE_REQUIRED_INCLUDES "${PCRE_INCLUDE_DIR}") endif() mark_as_advanced(FORCE PCRE_LIBRARIES PCRE_INCLUDE_DIR) - check_include_file("pcre.h" HAVE_PCRE_H) + check_include_file("pcre2.h" HAVE_PCRE2_H -DPCRE2_CODE_UNIT_WIDTH=8) set(optlibsfound "${optlibsfound} PCRE") else() set(optlibsnotfound "${optlibsnotfound} PCRE") diff --git a/src/zm_regexp.cpp b/src/zm_regexp.cpp index 80e9a6a8b..a692a10d0 100644 --- a/src/zm_regexp.cpp +++ b/src/zm_regexp.cpp @@ -24,21 +24,17 @@ #if HAVE_LIBPCRE -RegExpr::RegExpr( const char *pattern, int flags, int p_max_matches ) : max_matches( p_max_matches ), match_buffers( nullptr ), match_lengths( nullptr ), match_valid( nullptr ) { - const char *errstr; - int erroffset = 0; - if ( !(regex = pcre_compile( pattern, flags, &errstr, &erroffset, 0 )) ) { - Panic( "pcre_compile(%s): %s at %d", pattern, errstr, erroffset ); - } - - regextra = pcre_study( regex, 0, &errstr ); - if ( errstr ) { - Panic( "pcre_study(%s): %s", pattern, errstr ); +RegExpr::RegExpr( const char *pattern, uint32_t flags, int p_max_matches ) : max_matches( p_max_matches ), match_buffers( nullptr ), match_lengths( nullptr ), match_valid( nullptr ) { + char errstr[120]; + int err; + PCRE2_SIZE erroffset; + if ( !(regex = pcre2_compile( (PCRE2_SPTR)pattern, strlen( pattern ), flags, &err, &erroffset, NULL )) ) { + pcre2_get_error_message( err, (PCRE2_UCHAR *)errstr, sizeof(errstr) ); + Panic( "pcre2_compile(%s): %s at %zu", pattern, errstr, erroffset ); } if ( (ok = (bool)regex) ) { - match_vectors = new int[3*max_matches]; - memset( match_vectors, 0, sizeof(*match_vectors)*3*max_matches ); + match_data = pcre2_match_data_create( 3*max_matches, NULL ); match_buffers = new char *[max_matches]; memset( match_buffers, 0, sizeof(*match_buffers)*max_matches ); match_lengths = new int[max_matches]; @@ -61,16 +57,18 @@ RegExpr::~RegExpr() { delete[] match_valid; delete[] match_lengths; delete[] match_buffers; - delete[] match_vectors; + pcre2_match_data_free( match_data ); + pcre2_code_free( regex ); } -int RegExpr::Match( const char *subject_string, int subject_length, int flags ) { +int RegExpr::Match( const char *subject_string, PCRE2_SIZE subject_length, uint32_t flags ) { match_string = subject_string; - n_matches = pcre_exec( regex, regextra, subject_string, subject_length, 0, flags, match_vectors, 2*max_matches ); + n_matches = pcre2_match( regex, (PCRE2_SPTR)subject_string, subject_length, 0, flags, match_data, NULL ); + match_vectors = pcre2_get_ovector_pointer( match_data ); if ( n_matches <= 0 ) { - if ( n_matches < PCRE_ERROR_NOMATCH ) { + if ( n_matches != PCRE2_ERROR_NOMATCH ) { Error( "Error %d executing regular expression", n_matches ); } return( n_matches = 0 ); @@ -87,7 +85,7 @@ const char *RegExpr::MatchString( int match_index ) const { return( 0 ); } if ( !match_valid[match_index] ) { - int match_len = match_vectors[(2*match_index)+1]-match_vectors[2*match_index]; + int match_len = (int)(match_vectors[(2*match_index)+1]-match_vectors[2*match_index]); if ( match_lengths[match_index] < (match_len+1) ) { delete[] match_buffers[match_index]; match_buffers[match_index] = new char[match_len+1]; @@ -104,7 +102,7 @@ int RegExpr::MatchLength( int match_index ) const { if ( match_index > n_matches ) { return( 0 ); } - return( match_vectors[(2*match_index)+1]-match_vectors[2*match_index] ); + return( (int)(match_vectors[(2*match_index)+1]-match_vectors[2*match_index]) ); } #endif // HAVE_LIBPCRE diff --git a/src/zm_regexp.h b/src/zm_regexp.h index 0568d441b..e416132ba 100644 --- a/src/zm_regexp.h +++ b/src/zm_regexp.h @@ -24,20 +24,19 @@ #if HAVE_LIBPCRE -#if HAVE_PCRE_H -#include -#elif HAVE_PCRE_PCRE_H -#include +#if HAVE_PCRE2_H +#define PCRE2_CODE_UNIT_WIDTH 8 +#include #else -#error Unable to locate pcre.h, please do 'locate pcre.h' and report location to zoneminder.com +#error Unable to locate pcre2.h, please do 'locate pcre2.h' and report location to zoneminder.com #endif class RegExpr { protected: - pcre *regex; - pcre_extra *regextra; + pcre2_code *regex; + pcre2_match_data *match_data; int max_matches; - int *match_vectors; + PCRE2_SIZE *match_vectors; mutable char **match_buffers; int *match_lengths; bool *match_valid; @@ -50,11 +49,11 @@ class RegExpr { bool ok; public: - explicit RegExpr( const char *pattern, int cflags=0, int p_max_matches=32 ); + explicit RegExpr( const char *pattern, uint32_t cflags=0, int p_max_matches=32 ); ~RegExpr(); bool Ok() const { return( ok ); } int MatchCount() const { return( n_matches ); } - int Match( const char *subject_string, int subject_length, int flags=0 ); + int Match( const char *subject_string, PCRE2_SIZE subject_length, uint32_t flags=0 ); const char *MatchString( int match_index ) const; int MatchLength( int match_index ) const; }; diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp index 233a5dae2..657704325 100644 --- a/src/zm_remote_camera_http.cpp +++ b/src/zm_remote_camera_http.cpp @@ -131,15 +131,15 @@ void RemoteCameraHttp::Initialise() { #if HAVE_LIBPCRE if ( method == REGEXP ) { if ( !header_expr ) - header_expr = new RegExpr("^(.+?\r?\n\r?\n)", PCRE_DOTALL); + header_expr = new RegExpr("^(.+?\r?\n\r?\n)", PCRE2_DOTALL); if ( !status_expr ) - status_expr = new RegExpr("^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE_CASELESS); + status_expr = new RegExpr("^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE2_CASELESS); if ( !connection_expr ) - connection_expr = new RegExpr("Connection: ?(.+?)\r?\n", PCRE_CASELESS); + connection_expr = new RegExpr("Connection: ?(.+?)\r?\n", PCRE2_CASELESS); if ( !content_length_expr ) - content_length_expr = new RegExpr("Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS); + content_length_expr = new RegExpr("Content-length: ?([0-9]+)\r?\n", PCRE2_CASELESS); if ( !content_type_expr ) - content_type_expr = new RegExpr("Content-type: ?(.+?)(?:; ?boundary=\x22?(.+?)\x22?)?\r?\n", PCRE_CASELESS); + content_type_expr = new RegExpr("Content-type: ?(.+?)(?:; ?boundary=\x22?(.+?)\x22?)?\r?\n", PCRE2_CASELESS); } #endif } // end void RemoteCameraHttp::Initialise() @@ -465,7 +465,7 @@ int RemoteCameraHttp::GetResponse() { if ( !subheader_expr ) { char subheader_pattern[256] = ""; snprintf( subheader_pattern, sizeof(subheader_pattern), "^((?:\r?\n){0,2}?(?:--)?%s\r?\n.+?\r?\n\r?\n)", content_boundary ); - subheader_expr = new RegExpr( subheader_pattern, PCRE_DOTALL ); + subheader_expr = new RegExpr( subheader_pattern, PCRE2_DOTALL ); } if ( subheader_expr->Match( (char *)buffer, (int)buffer ) == 2 ) { subheader = subheader_expr->MatchString( 1 ); @@ -473,14 +473,14 @@ int RemoteCameraHttp::GetResponse() { Debug( 4, "Captured subheader (%d bytes):'%s'", subheader_len, subheader ); if ( !subcontent_length_expr ) - subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); + subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE2_CASELESS ); if ( subcontent_length_expr->Match( subheader, subheader_len ) == 2 ) { content_length = atoi( subcontent_length_expr->MatchString( 1 ) ); Debug( 3, "Got subcontent length '%d'", content_length ); } if ( !subcontent_type_expr ) - subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE_CASELESS ); + subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE2_CASELESS ); if ( subcontent_type_expr->Match( subheader, subheader_len ) == 2 ) { content_type = subcontent_type_expr->MatchString( 1 ); Debug( 3, "Got subcontent type '%s'", content_type ); @@ -545,7 +545,7 @@ int RemoteCameraHttp::GetResponse() { if (!content_expr) { char content_pattern[256] = ""; snprintf(content_pattern, sizeof(content_pattern), "^(.+?)(?:\r?\n)*(?:--)?%s\r?\n", content_boundary); - content_expr = new RegExpr(content_pattern, PCRE_DOTALL); + content_expr = new RegExpr(content_pattern, PCRE2_DOTALL); } if (content_expr->Match( buffer, buffer.size()) == 2) { content_length = content_expr->MatchLength( 1 ); diff --git a/zoneminder-config.cmake b/zoneminder-config.cmake index e3680197b..028762d3e 100644 --- a/zoneminder-config.cmake +++ b/zoneminder-config.cmake @@ -30,7 +30,7 @@ #cmakedefine HAVE_LIBPTHREAD 1 #cmakedefine HAVE_PTHREAD_H #cmakedefine HAVE_LIBPCRE 1 -#cmakedefine HAVE_PCRE_H 1 +#cmakedefine HAVE_PCRE2_H 1 #cmakedefine HAVE_LIBGNUTLS 1 #cmakedefine HAVE_LIBMYSQLCLIENT 1 #cmakedefine HAVE_MYSQL_H 1