]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
regex - move related code to tvhregex.h/wrappers.c
authorJaroslav Kysela <perex@perex.cz>
Wed, 17 May 2017 07:19:52 +0000 (09:19 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 17 May 2017 07:37:05 +0000 (09:37 +0200)
- remove PCRE column from DVR, use PCRE automatically
- disable autorec when the regex is wrong (cannot be compiled)

src/dvr/dvr.h
src/dvr/dvr_autorec.c
src/tvhregex.h [new file with mode: 0644]
src/webui/static/app/dvr.js
src/wrappers.c

index 0a828b954e6073c15f6ad1617e118fec724b1696..f1bb2eb4f9a7fd9ef53be61a89093a4787b67947 100644 (file)
 #ifndef DVR_H
 #define DVR_H
 
-#include <regex.h>
-#if ENABLE_PCRE
-#include <pcre.h>
-#endif
-#if ENABLE_PCRE2
-#define PCRE2_CODE_UNIT_WIDTH 8
-#include <pcre2.h>
-#endif
+#include "tvhregex.h"
 #include "epg.h"
 #include "channels.h"
 #include "subscriptions.h"
@@ -340,20 +333,13 @@ typedef struct dvr_autorec_entry {
   LIST_ENTRY(dvr_autorec_entry) dae_config_link;
 
   int dae_enabled;
+  int dae_error;
   char *dae_owner;
   char *dae_creator;
   char *dae_comment;
 
   char *dae_title;
-  int dae_pcre;
-  regex_t dae_title_preg;
-#if ENABLE_PCRE
-  pcre *dae_title_pcre;
-  pcre_extra *dae_title_pcre_extra;
-#elif ENABLE_PCRE2
-  pcre2_code *dae_title_pcre;
-  pcre2_match_data *dae_title_pcre_match;
-#endif
+  tvh_regex_t dae_title_regex;
   int dae_fulltext;
   
   uint32_t dae_content_type;
index 5eb5a9eef3b383afcc27726c902b48bf1c5981b8..a1fbe4e8d9d47c7e9477c0e1e6344b564435390f 100644 (file)
 #include "epg.h"
 #include "htsp_server.h"
 
-#ifndef PCRE_STUDY_JIT_COMPILE
-#define PCRE_STUDY_JIT_COMPILE 0
-#endif
-
 struct dvr_autorec_entry_queue autorec_entries;
 
-/*
- *
- */
-static inline int autorec_regexec(dvr_autorec_entry_t *dae, const char *str)
-{
-#if ENABLE_PCRE
-  if (dae->dae_pcre) {
-    int r, vec[30];
-    r = pcre_exec(dae->dae_title_pcre, dae->dae_title_pcre_extra,
-                  str, strlen(str), 0, 0, vec, ARRAY_SIZE(vec));
-    return r < 0;
-  } else
-#elif ENABLE_PCRE2
-    int r;
-    r = pcre2_match(dae->dae_title_pcre, (PCRE2_SPTR8)str, -1, 0, 0,
-                    dae->dae_title_pcre_match, NULL);
-    return r <= 0;
-#endif
-  {
-    return regexec(&dae->dae_title_preg, str, 0, NULL, 0);
-  }
-}
-
-/*
- *
- */
 static void autorec_regfree(dvr_autorec_entry_t *dae)
 {
   if (dae->dae_title) {
-#if ENABLE_PCRE
-    if (dae->dae_pcre) {
-#ifdef PCRE_CONFIG_JIT
-      pcre_free_study(dae->dae_title_pcre_extra);
-#else
-      pcre_free(dae->dae_title_pcre_extra);
-#endif
-      pcre_free(dae->dae_title_pcre);
-      dae->dae_title_pcre_extra = NULL;
-      dae->dae_title_pcre = NULL;
-    } else
-#elif ENABLE_PCRE2
-    if (dae->dae_pcre) {
-      pcre2_match_data_free(dae->dae_title_pcre_match);
-      dae->dae_title_pcre_match = NULL;
-      dae->dae_title_pcre = NULL;
-    } else
-#endif
-    {
-      regfree(&dae->dae_title_preg);
-    }
+    regex_free(&dae->dae_title_regex);
     free(dae->dae_title);
     dae->dae_title = NULL;
   }
@@ -310,21 +260,21 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e)
     if (!dae->dae_fulltext) {
       if(!e->episode->title) return 0;
       RB_FOREACH(ls, e->episode->title, link)
-        if (!autorec_regexec(dae, ls->str)) break;
+        if (!regex_match(&dae->dae_title_regex, ls->str)) break;
     } else {
       ls = NULL;
       if (e->episode->title)
         RB_FOREACH(ls, e->episode->title, link)
-          if (!autorec_regexec(dae, ls->str)) break;
+          if (!regex_match(&dae->dae_title_regex, ls->str)) break;
       if (!ls && e->episode->subtitle)
         RB_FOREACH(ls, e->episode->subtitle, link)
-          if (!autorec_regexec(dae, ls->str)) break;
+          if (!regex_match(&dae->dae_title_regex, ls->str)) break;
       if (!ls && e->summary)
         RB_FOREACH(ls, e->summary, link)
-          if (!autorec_regexec(dae, ls->str)) break;
+          if (!regex_match(&dae->dae_title_regex, ls->str)) break;
       if (!ls && e->description)
         RB_FOREACH(ls, e->description, link)
-          if (!autorec_regexec(dae, ls->str)) break;
+          if (!regex_match(&dae->dae_title_regex, ls->str)) break;
     }
     if (!ls) return 0;
   }
@@ -359,9 +309,6 @@ dvr_autorec_create(const char *uuid, htsmsg_t *conf)
 
   TAILQ_INSERT_TAIL(&autorec_entries, dae, dae_link);
 
-  /* PCRE flag must be set before load (order issue) */
-  if (conf)
-    dae->dae_pcre = htsmsg_get_bool_or_default(conf, "pcre", 0);
   idnode_load(&dae->dae_id, conf);
 
   htsp_autorec_entry_add(dae);
@@ -487,6 +434,8 @@ dvr_autorec_entry_class_changed(idnode_t *self)
 {
   dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)self;
 
+  if (dae->dae_error)
+    dae->dae_enabled = 0;
   dvr_autorec_changed(dae, 1);
   dvr_autorec_completed(dae, 0);
   htsp_autorec_entry_update(dae);
@@ -588,66 +537,11 @@ dvr_autorec_entry_class_title_set(void *o, const void *v)
   if (strcmp(title, dae->dae_title ?: "")) {
     if (dae->dae_title)
       autorec_regfree(dae);
-    if (title[0] != '\0') {
-#if ENABLE_PCRE
-      if (dae->dae_pcre) {
-        const char *estr;
-        int eoff;
-        dae->dae_title_pcre = pcre_compile(title, PCRE_CASELESS | PCRE_UTF8,
-                                           &estr, &eoff, NULL);
-        if (dae->dae_title_pcre == NULL) {
-          tvherror(LS_DVR, "Unable to compile PCRE '%s': %s", title, estr);
-        } else {
-          dae->dae_title_pcre_extra = pcre_study(dae->dae_title_pcre,
-                                                 PCRE_STUDY_JIT_COMPILE, &estr);
-          if (dae->dae_title_pcre_extra == NULL && estr)
-            tvherror(LS_DVR, "Unable to study PCRE '%s': %s", title, estr);
-          else
-            dae->dae_title = strdup(title);
-        }
-      } else
-#elif ENABLE_PCRE2
-      if (dae->dae_pcre) {
-        PCRE2_UCHAR8 ebuf[128];
-        int ecode;
-        PCRE2_SIZE eoff;
-        dae->dae_title_pcre = pcre2_compile((PCRE2_SPTR8)title, -1,
-                                            PCRE2_CASELESS | PCRE2_UTF,
-                                            &ecode, &eoff, NULL);
-        if (dae->dae_title_pcre == NULL) {
-          (void)pcre2_get_error_message(ecode, ebuf, 120);
-          tvherror(LS_DVR, "Unable to compile PCRE2 '%s': %s", title, ebuf);
-        } else {
-          dae->dae_title_pcre_match = pcre2_match_data_create(20, NULL);
-          dae->dae_title = strdup(title);
-        }
-      } else
-#endif
-      {
-        if (!regcomp(&dae->dae_title_preg, title,
-                     REG_ICASE | REG_EXTENDED | REG_NOSUB))
-          dae->dae_title = strdup(title);
-        else
-          tvherror(LS_DVR, "Unable to compile regex '%s'", title);
-      }
-    }
-    return 1;
-  }
-  return 0;
-}
-
-static int
-dvr_autorec_entry_class_pcre_set(void *o, const void *v)
-{
-  dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)o;
-  int pcre = v ? *(int *)v : 0;
-  char *title;
-  if (dae->dae_pcre != pcre) {
-    title = dae->dae_title ? strdup(dae->dae_title) : NULL;
-    autorec_regfree(dae);
-    dae->dae_pcre = pcre;
-    dvr_autorec_entry_class_title_set(o, title);
-    free(title);
+    dae->dae_error = 0;
+    if (!regex_compile(&dae->dae_title_regex, title, LS_DVR))
+      dae->dae_title = strdup(title);
+    else
+      dae->dae_error = 1;
     return 1;
   }
   return 0;
@@ -1161,15 +1055,6 @@ const idclass_t dvr_autorec_entry_class = {
                      "matched against title, subtitle, summary and description."),
       .off      = offsetof(dvr_autorec_entry_t, dae_fulltext),
     },
-    {
-      .type     = PT_BOOL,
-      .id       = "pcre",
-      .name     = N_("PCRE"),
-      .desc     = N_("Use PCRE regular expression library instead posix "
-                     "extended regular expressions."),
-      .set      = dvr_autorec_entry_class_pcre_set,
-      .off      = offsetof(dvr_autorec_entry_t, dae_pcre),
-    },
     {
       .type     = PT_STR,
       .id       = "channel",
diff --git a/src/tvhregex.h b/src/tvhregex.h
new file mode 100644 (file)
index 0000000..56a3bef
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  TVheadend - regex wrapper
+ *
+ *  Copyright (C) 2017 Jaroslav Kysela
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TVHREGEX_H__
+#define __TVHREGEX_H__
+
+#if ENABLE_PCRE
+
+#  include <pcre.h>
+#  ifndef PCRE_STUDY_JIT_COMPILE
+#  define PCRE_STUDY_JIT_COMPILE 0
+#  endif
+
+#elif ENABLE_PCRE2
+
+#  define PCRE2_CODE_UNIT_WIDTH 8
+#  include <pcre2.h>
+
+#else
+
+#  include <regex.h>
+
+#endif
+
+typedef struct {
+#if ENABLE_PCRE
+  pcre *re_code;
+  pcre_extra *re_extra;
+#elif ENABLE_PCRE2
+  pcre2_code *re_code;
+  pcre2_match_data *re_match;
+#else
+  regex_t re_code;
+#endif
+} tvh_regex_t;
+
+static inline int regex_match(tvh_regex_t *regex, const char *str)
+{
+#if ENABLE_PCRE
+  int vec[30];
+  return pcre_exec(regex->re_code, re->re_extra,
+                str, strlen(str), 0, 0, vec, ARRAY_SIZE(vec)) < 0;
+#elif ENABLE_PCRE2
+  return pcre2_match(regex->re_code, (PCRE2_SPTR8)str, -1, 0, 0,
+                     regex->re_match, NULL) <= 0;
+#else
+  return regexec(&regex->re_code, str, 0, NULL, 0);
+#endif
+}
+
+void regex_free(tvh_regex_t *regex);
+int regex_compile(tvh_regex_t *regex, const char *re_str, int subsys);
+
+#endif /* __TVHREGEX_H__ */
index c48180b7afe482b006b90eaf67dccfa4b11bc4b8..bd6130e6d86733cb053692410422626e705657cd 100644 (file)
@@ -723,7 +723,7 @@ tvheadend.dvr_settings = function(panel, index) {
  */
 tvheadend.autorec_editor = function(panel, index) {
 
-    var list = 'name,title,fulltext,pcre,channel,start,start_window,weekdays,' +
+    var list = 'name,title,fulltext,channel,start,start_window,weekdays,' +
                'record,tag,btype,content_type,minduration,maxduration,' +
                'dedup,directory,config_name,comment';
     var elist = 'enabled,start_extra,stop_extra,' +
@@ -742,7 +742,6 @@ tvheadend.autorec_editor = function(panel, index) {
             directory:    { width: 200 },
             title:        { width: 300 },
             fulltext:     { width: 70 },
-            pcre:         { width: 70 },
             channel:      { width: 200 },
             tag:          { width: 200 },
             btype:        { width: 50 },
@@ -782,7 +781,7 @@ tvheadend.autorec_editor = function(panel, index) {
             },
         },
         del: true,
-        list: 'enabled,name,title,fulltext,pcre,channel,tag,start,start_window,' +
+        list: 'enabled,name,title,fulltext,channel,tag,start,start_window,' +
               'weekdays,minduration,maxduration,btype,content_type,' +
               'pri,dedup,directory,config_name,owner,creator,comment',
         sort: {
index a354f2ee7b0f5afbf8f31b554f399e2aa9fd7b6d..c9a550792c949920fc6190b85198719dbea044d8 100644 (file)
@@ -18,6 +18,8 @@
 #include <pthread_np.h>
 #endif
 
+#include "tvhregex.h"
+
 /*
  * filedescriptor routines
  */
@@ -381,3 +383,67 @@ tvh_qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, c
     qsort_r(base, nmemb, size, compar, arg);
 #endif
 }
+
+/*
+ * Regex stuff
+ */
+void regex_free(tvh_regex_t *regex)
+{
+#if ENABLE_PCRE
+#ifdef PCRE_CONFIG_JIT
+  pcre_free_study(regex->re_extra);
+#else
+  pcre_free(regex->re_extra);
+#endif
+  pcre_free(regex->re_comp);
+  regex->re_extra = NULL;
+  regex->re_comp = NULL;
+#elif ENABLE_PCRE2
+  pcre2_match_data_free(regex->re_match);
+  pcre2_code_free(regex->re_code);
+#else
+  regfree(&regex->re_code);
+#endif
+}
+
+int regex_compile(tvh_regex_t *regex, const char *re_str, int subsys)
+{
+#if ENABLE_PCRE
+  const char *estr;
+  int eoff;
+  regex->re_code = pcre_compile(re_str, PCRE_CASELESS | PCRE_UTF8,
+                                &estr, &eoff, NULL);
+  if (regex->re_code == NULL) {
+    tvherror(subsys, "Unable to compile PCRE '%s': %s", re_str, estr);
+  } else {
+    regex->re_code_extra = pcre_study(regex->re_code,
+                                      PCRE_STUDY_JIT_COMPILE, &estr);
+    if (regex->re_code_extra == NULL && estr)
+      tvherror(subsys, "Unable to study PCRE '%s': %s", re_str, estr);
+    else
+      return 0;
+  }
+  return -1;
+#elif ENABLE_PCRE2
+  PCRE2_UCHAR8 ebuf[128];
+  int ecode;
+  PCRE2_SIZE eoff;
+  regex->re_code = pcre2_compile((PCRE2_SPTR8)re_str, -1,
+                                 PCRE2_CASELESS | PCRE2_UTF,
+                                 &ecode, &eoff, NULL);
+  if (regex->re_code == NULL) {
+    (void)pcre2_get_error_message(ecode, ebuf, 120);
+    tvherror(subsys, "Unable to compile PCRE2 '%s': %s", re_str, ebuf);
+  } else {
+    regex->re_match = pcre2_match_data_create(20, NULL);
+    return 0;
+  }
+  return -1;
+#else
+  if (!regcomp(&regex->re_code, re_str,
+               REG_ICASE | REG_EXTENDED | REG_NOSUB))
+    return 0;
+  tvherror(subsys, "Unable to compile regex '%s'", title);
+  return -1;
+#endif
+}