#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;
}
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;
}
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);
{
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);
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;
"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",
--- /dev/null
+/*
+ * 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(®ex->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__ */
*/
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,' +
directory: { width: 200 },
title: { width: 300 },
fulltext: { width: 70 },
- pcre: { width: 70 },
channel: { width: 200 },
tag: { width: 200 },
btype: { width: 50 },
},
},
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: {
#include <pthread_np.h>
#endif
+#include "tvhregex.h"
+
/*
* filedescriptor routines
*/
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(®ex->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(®ex->re_code, re_str,
+ REG_ICASE | REG_EXTENDED | REG_NOSUB))
+ return 0;
+ tvherror(subsys, "Unable to compile regex '%s'", title);
+ return -1;
+#endif
+}