diff options
-rw-r--r-- | HISTORY | 4 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README | 21 | ||||
-rw-r--r-- | charset.c | 2 | ||||
-rw-r--r-- | charset.h | 2 | ||||
-rw-r--r-- | config.c | 2 | ||||
-rw-r--r-- | config.h | 1 | ||||
-rw-r--r-- | epgfixer.c | 19 | ||||
-rw-r--r-- | epgfixer/charset.conf | 2 | ||||
-rw-r--r-- | epghandler.c | 163 | ||||
-rw-r--r-- | epghandler.h | 4 | ||||
-rw-r--r-- | po/fi_FI.po | 18 | ||||
-rw-r--r-- | regexp.c | 299 | ||||
-rw-r--r-- | regexp.h | 55 | ||||
-rw-r--r-- | setup_menu.c | 287 |
15 files changed, 407 insertions, 474 deletions
@@ -1,5 +1,9 @@ VDR Plugin 'epgfixer' Revision History -------------------------------------- +2012-xx-xx: Version 0.0.6 + +- Support for character set conversion for selected channels. +- Support for stripping HTML entities. 2012-04-13: Version 0.0.5 @@ -57,7 +57,7 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = $(PLUGIN).o config.o epghandler.o setup_menu.o regexp.o +OBJS = $(PLUGIN).o charset.o config.o epghandler.o regexp.o setup_menu.o tools.o ifeq ($(REGEXLIB), pcre) LIBS += $(shell pcre-config --libs-posix) @@ -25,16 +25,17 @@ Requirements: Usage: +General syntax of configuration files: +- Lines beginning with # are regarded as comments. +- Lines beginning with ! are regarded as disabled lines. +- Channel_list is optional comma separated list of channels for which the line + is used. If no list of channels is given the line is used for all channels. +- Channel_list can contain either channel IDs (e.g. S19.2E-1-1089-12003-0) or + numbers but not both. + All regular expressions are placed to VDRPLUGINCONFDIR/epgfixer/regexp.conf. Syntax of regexp.conf line is "Channel_list:Parsed_epg_field=Regexp" with: -- Lines beginning with # are regarded as comments. -- Lines beginning with ! are regarded as disabled regular expressions. -- Channel_list is optional comma separated list of channels for which the - regular expression is used. If no list of channels is given the regular - expression is used for all channels. -- Channel_list for a regular expression can contain either channel IDs - (e.g. S19.2E-1-1089-12003-0) or numbers but not both. - Parsed_epg_field is the EPG field for which the regular expression is applied with available field names title, shorttext and description. - Regular expressions use named backreferences with either title, shorttext, @@ -44,6 +45,12 @@ Syntax of regexp.conf line is "Channel_list:Parsed_epg_field=Regexp" with: content of the target EPG field, respectively. - Several regular expressions may be applied to same field. +All character set conversions are placed to +VDRPLUGINCONFDIR/epgfixer/charset.conf. + +Syntax of charset.conf line is "Channel_list=OriginalCharSet" with: +- OriginalCharSet is a name of a character set (e.g. iso8859-1). + Examples of regexp.conf: # Example of disabled regexp: @@ -1,5 +1,5 @@ /* - * regexp.c: Regular expression list + * charset.c: Character set list item * * See the README file for copyright information and how to reach the author. * @@ -1,5 +1,5 @@ /* - * regexp.h: Regular expression list + * charset.h: Character set list item * * See the README file for copyright information and how to reach the author. * @@ -22,6 +22,7 @@ cEpgfixerSetup::cEpgfixerSetup() equalshorttextanddescription = 0; nobackticks = 0; components = 0; + striphtml = 0; } cString cEpgfixerSetup::m_ProcessedArgs; @@ -59,6 +60,7 @@ bool cEpgfixerSetup::SetupParse(const char *Name, const char *Value) else if (!strcasecmp(Name, "PreventEqualShortTextAndDescription")) equalshorttextanddescription = atoi(Value); else if (!strcasecmp(Name, "ReplaceBackticksWithSingleQuotes")) nobackticks = atoi(Value); else if (!strcasecmp(Name, "FixStreamComponentDescriptions")) components = atoi(Value); + else if (!strcasecmp(Name, "StripHTMLentities")) striphtml = atoi(Value); else return false; @@ -22,6 +22,7 @@ public: int equalshorttextanddescription; int nobackticks; int components; + int striphtml; cEpgfixerSetup(); bool SetupParse(const char *Name, const char *Value); @@ -7,6 +7,7 @@ #include <vdr/plugin.h> #include <vdr/i18n.h> +#include "charset.h" #include "regexp.h" #include "setup_menu.h" #include "epghandler.h" @@ -71,8 +72,10 @@ bool cPluginEpgfixer::ProcessArgs(int argc, char *argv[]) bool cPluginEpgfixer::Initialize(void) { // Initialize any background activities the plugin shall perform. - EpgfixerRegexps.SetRegexpConfigFile(AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "regexp.conf")); // allowed only via main thread!); - EpgfixerRegexps.ReloadRegexps(); + EpgfixerRegexps.SetConfigFile(AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "regexp.conf")); // allowed only via main thread!); + EpgfixerRegexps.ReloadConfigFile(); + EpgfixerCharSets.SetConfigFile(AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "charset.conf")); // allowed only via main thread!); + EpgfixerCharSets.ReloadConfigFile(); return new cEpgfixerEpgHandler(); } @@ -144,6 +147,8 @@ const char **cPluginEpgfixer::SVDRPHelpPages(void) static const char *HelpPages[] = { "RLRE\n" " Reload regexp.conf.", + "RLCH\n" + " Reload charset.conf.", NULL }; return HelpPages; @@ -152,13 +157,21 @@ const char **cPluginEpgfixer::SVDRPHelpPages(void) cString cPluginEpgfixer::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { if (strcasecmp(Command, "RLRE") == 0) { - if (EpgfixerRegexps.ReloadRegexps()) { + if (EpgfixerRegexps.ReloadConfigFile()) { return cString("Reloaded regexp.conf"); } else { ReplyCode = 554; // Requested action failed return cString("Reloading regexp.conf failed"); } } + else if (strcasecmp(Command, "RLCH") == 0) { + if (EpgfixerCharSets.ReloadConfigFile()) { + return cString("Reloaded charset.conf"); + } else { + ReplyCode = 554; // Requested action failed + return cString("Reloading charset.conf failed"); + } + } return NULL; } diff --git a/epgfixer/charset.conf b/epgfixer/charset.conf index 98cd247..bd84ae6 100644 --- a/epgfixer/charset.conf +++ b/epgfixer/charset.conf @@ -1,3 +1,3 @@ -#C onvert character set of channels 1, 2 and 3 from iso8859-1 to character set +# Convert character set of channels 1, 2 and 3 from iso8859-1 to character set # used by VDR 1,2,3=iso8859-1 diff --git a/epghandler.c b/epghandler.c index ab837a0..c9db409 100644 --- a/epghandler.c +++ b/epghandler.c @@ -7,15 +7,11 @@ #include "epghandler.h" #include "config.h" +#include "charset.h" +#include "regexp.h" #include <vdr/tools.h> #include <string.h> -#ifdef HAVE_PCREPOSIX -#include <pcre.h> -#endif - -typedef enum { ATITLE,PTITLE,TITLE,ASHORTTEXT,PSHORTTEXT,SHORTTEXT,ADESCRIPTION,PDESCRIPTION,DESCRIPTION,RATING } backrefs; -const char *strBackrefs[] = { "atitle","ptitle","title","ashorttext","pshorttext","shorttext","adescription","pdescription","description","rating" }; void cEpgfixerEpgHandler::FixOriginalEpgBugs(cEvent *event) { @@ -237,135 +233,66 @@ void cEpgfixerEpgHandler::FixOriginalEpgBugs(cEvent *event) } } -bool cEpgfixerEpgHandler::ApplyRegexp(cRegexp *regexp, cEvent *Event, const char *input) +bool cEpgfixerEpgHandler::FixBugs(cEvent *Event) { - bool active = true; - if (regexp->NumChannels() > 0) { - bool found = false; - int i = 0; - while (i < regexp->NumChannels() && !found) { - if (Channels.GetByChannelID(Event->ChannelID())->Number() == regexp->GetChannelNum(i)) - found = true; - if (regexp->GetChannelID(i) && strcmp(*(Event->ChannelID().ToString()), regexp->GetChannelID(i)) == 0) - found = true; - i++; - } - if (!found) - active = false; - } - if (active && regexp->Enabled() && regexp->GetRe()) { - const char *string; - int ovector[20]; - int rc; - rc = pcre_exec(regexp->GetRe(), regexp->GetSd(), input, strlen(input), 0, 0, ovector, 20); - if (rc > 0) { - int i = 0; - while (i < 10) { - if (pcre_get_named_substring(regexp->GetRe(), input, ovector, rc, strBackrefs[i], &string) != PCRE_ERROR_NOSUBSTRING) { - char *tempstring = 0; - switch (i) { - case TITLE: - Event->SetTitle(string); - break; - case ATITLE: - tempstring = (char *)malloc(strlen(Event->Title())+strlen(string)+1); - strcpy(tempstring, Event->Title()); - strcat(tempstring, string); - Event->SetTitle(tempstring); - break; - case PTITLE: - tempstring = (char *)malloc(strlen(Event->Title())+strlen(string)+1); - strcpy(tempstring, string); - strcat(tempstring, Event->Title()); - Event->SetTitle(tempstring); - break; - case SHORTTEXT: - Event->SetShortText(string); - break; - case ASHORTTEXT: - tempstring = (char *)malloc(strlen(Event->ShortText())+strlen(string)+1); - strcpy(tempstring, Event->ShortText()); - strcat(tempstring, string); - Event->SetShortText(tempstring); - break; - case PSHORTTEXT: - tempstring = (char *)malloc(strlen(Event->ShortText())+strlen(string)+1); - strcpy(tempstring, string); - strcat(tempstring, Event->ShortText()); - Event->SetShortText(tempstring); - break; - case DESCRIPTION: - Event->SetDescription(string); - break; - case ADESCRIPTION: - tempstring = (char *)malloc(strlen(Event->Description())+strlen(string)+1); - strcpy(tempstring, Event->Description()); - strcat(tempstring, string); - Event->SetDescription(tempstring); - break; - case PDESCRIPTION: - tempstring = (char *)malloc(strlen(Event->Description())+strlen(string)+1); - strcpy(tempstring, string); - strcat(tempstring, Event->Description()); - Event->SetDescription(tempstring); - break; - case RATING: - Event->SetParentalRating(atoi(string)); - break; - default: - break; - } - pcre_free_substring(string); - free(tempstring); - } - i++; + int res = false; + cRegexp *regex = (cRegexp *)EpgfixerRegexps.First(); + while (regex) { + if (regex->Enabled()) { + int ret = regex->Apply(Event); + if (ret && !res) + res = true; } - return true; + regex = (cRegexp *)regex->Next(); } - } - return false; + return res; } -bool cEpgfixerEpgHandler::FixBugs(cEvent *Event) +bool cEpgfixerEpgHandler::FixCharSets(cEvent *Event) { int res = false; - char *tmpstring; - cRegexp *regex = (cRegexp *)EpgfixerRegexps.regexps->First(); - while (regex) { - if (regex->Enabled()) { - switch (regex->GetSource()) { - case REGEXP_TITLE: - tmpstring = strdup(Event->Title()); - break; - case REGEXP_SHORTTEXT: - if (Event->ShortText()) - tmpstring = strdup(Event->ShortText()); - else - tmpstring = strdup(""); - break; - case REGEXP_DESCRIPTION: - if (Event->Description()) - tmpstring = strdup(Event->Description()); - else - tmpstring = strdup(""); - break; - default: - tmpstring = strdup(""); - break; - } - int ret = ApplyRegexp(regex, Event, tmpstring); + cCharSet *charset = (cCharSet *)EpgfixerCharSets.First(); + while (charset) { + if (charset->Enabled()) { + int ret = charset->ConvertCharSet(Event); if (ret && !res) res = true; - free(tmpstring); } - regex = (cRegexp *)regex->Next(); + charset = (cCharSet *)charset->Next(); } return res; } +void cEpgfixerEpgHandler::StripHTML(cEvent *Event) +{ + if (EpgfixerSetup.striphtml) { + char *tmpstring; + if (Event->Title()) + tmpstring = strdup(Event->Title()); + else + tmpstring = strdup(""); + Event->SetTitle(striphtml(tmpstring)); + free(tmpstring); + if (Event->ShortText()) + tmpstring = strdup(Event->ShortText()); + else + tmpstring = strdup(""); + Event->SetShortText(striphtml(tmpstring)); + free(tmpstring); + if (Event->Description()) + tmpstring = strdup(Event->Description()); + else + tmpstring = strdup(""); + Event->SetDescription(striphtml(tmpstring)); + free(tmpstring); + } +} + bool cEpgfixerEpgHandler::FixEpgBugs(cEvent *Event) { FixOriginalEpgBugs(Event); + FixCharSets(Event); + StripHTML(Event); FixBugs(Event); return false; } diff --git a/epghandler.h b/epghandler.h index 8971f20..cc38378 100644 --- a/epghandler.h +++ b/epghandler.h @@ -9,14 +9,14 @@ #define __EPGFIXER_EPGHANDLER_H #include <vdr/epg.h> -#include "regexp.h" class cEpgfixerEpgHandler : public cEpgHandler { private: - bool ApplyRegexp(cRegexp *regexp, cEvent *Event, const char *input); void FixOriginalEpgBugs(cEvent *event); + bool FixCharSets(cEvent *Event); bool FixBugs(cEvent *Event); + void StripHTML(cEvent *Event); public: cEpgfixerEpgHandler(void) {}; virtual bool FixEpgBugs(cEvent *Event); diff --git a/po/fi_FI.po b/po/fi_FI.po index 963dd15..770b25c 100644 --- a/po/fi_FI.po +++ b/po/fi_FI.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: vdr-epgfixer 0.0.3\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2012-03-25 14:46+0300\n" -"PO-Revision-Date: 2012-03-25 15:20+0300\n" +"POT-Creation-Date: 2012-05-03 21:34+0300\n" +"PO-Revision-Date: 2012-05-03 22:20+0300\n" "Last-Translator: Matti Lehtimäki <matti.lehtimaki@gmail.com>\n" "Language-Team: Finnish <vdr@linuxtv.org>\n" "MIME-Version: 1.0\n" @@ -31,6 +31,12 @@ msgstr "Poista" msgid "Cancel" msgstr "Peru" +msgid "Regular expressions" +msgstr "Säännölliset lausekkeet" + +msgid "Character set conversions" +msgstr "Merkistömuunnokset" + msgid "Remove quotes from ShortText" msgstr "Poista lainaukset lyhyestä kuvauksesta" @@ -58,11 +64,11 @@ msgstr "Korvaa gravis heittomerkillä" msgid "Fix stream component descriptions" msgstr "Korjaa lähetekomponenttien kuvaukset" -msgid "Regular expressions" -msgstr "Säännölliset lausekkeet" +msgid "Strip HTML entities" +msgstr "Poista HTML-merkit" -msgid "Reload regexp.conf" -msgstr "Lataa uudelleen regexp.conf" +msgid "Reload files" +msgstr "Lataa uudelleen tiedostot" msgid "Clear EPG data" msgstr "Tyhjennä EPG tiedot" @@ -1,5 +1,5 @@ /* - * regexp.c: Regular expression list + * regexp.c: Regular expression list item * * See the README file for copyright information and how to reach the author. * @@ -9,78 +9,74 @@ #include <unistd.h> /* Global instance */ -cEpgfixerRegexps EpgfixerRegexps; +cEpgfixerList<cRegexp> EpgfixerRegexps; const char *strSources[] = { "title","shorttext","description","undefined" }; +typedef enum { ATITLE,PTITLE,TITLE,ASHORTTEXT,PSHORTTEXT,SHORTTEXT,ADESCRIPTION,PDESCRIPTION,DESCRIPTION,RATING } backrefs; +const char *strBackrefs[] = { "atitle","ptitle","title","ashorttext","pshorttext","shorttext","adescription","pdescription","description","rating" }; + cRegexp::cRegexp() { - enabled = false; regexp = NULL; - string = NULL; source = REGEXP_UNDEFINED; re = NULL; sd = NULL; - numchannels = 0; - channels_num = NULL; - channels_str = NULL; } cRegexp::~cRegexp(void) { Free(); -} - -void cRegexp::Free(void) -{ - free(channels_num); - if (channels_str) { - int i = 0; - while (i < numchannels) { - free(channels_str[i]); - i++; - } - } - free(channels_str); free(regexp); - free(string); - channels_num = NULL; - channels_str = NULL; regexp = NULL; - string = NULL; FreeCompiled(); } -int cRegexp::GetChannelNum(int index) -{ - if (channels_num && index >= 0 && index < numchannels) - return channels_num[index]; - else - return -1; -} - -const char *cRegexp::GetChannelID(int index) +void cRegexp::Compile() { - if (channels_str && index >= 0 && index < numchannels) - return channels_str[index]; - else - return NULL; + FreeCompiled(); + const char *error; + int erroffset; + re = pcre_compile(regexp, 0, &error, &erroffset, NULL); + if (error) { + esyslog("PCRE compile error: %s at offset %i", error, erroffset); + enabled = false; + } + else { + sd = pcre_study(re, 0, (const char **)&error); + if (error) + esyslog("PCRE study error: %s", error); + } } -void cRegexp::ToggleEnabled(void) +void cRegexp::FreeCompiled() { - enabled = enabled ? 0 : 1; + if (re) { + pcre_free(re); + re = NULL; + } + if (sd) { +#ifdef PCRE_CONFIG_JIT + pcre_free_study(sd); +#else + pcre_free(sd); +#endif + sd = NULL; + } } -void cRegexp::SetFromString(char *s, bool Enabled, bool Precompile) +void cRegexp::SetFromString(char *s, bool Enabled) { Free(); - string = strdup(s); enabled = Enabled; - bool precompile = Precompile; + if (s[0] == '!') + string = strdup(s+1); + else + string = strdup(s); + bool compile = true; if (s[0] == '!' || s[0] == '#') { enabled = false; - precompile = false; + compile = false; } char *p = (s[0] == '#') ? s : strchr(s, '='); if (p) { @@ -95,31 +91,7 @@ void cRegexp::SetFromString(char *s, bool Enabled, bool Precompile) if (f) { *f = 0; field = f+1; - char *c = chanfield; - numchannels = 0; - while (c) { - numchannels++; - c = strchr(c+1, ','); - } - if (numchannels > 0) { - c = chanfield; - // Use channel numbers - if (atoi(chanfield)) - channels_num = (int *)malloc(sizeof(int)*numchannels); - else// use channel IDs - channels_str = (char **)malloc(sizeof(char *)*numchannels); - int i = 0; - char *pc = strtok(c, ","); - while (i < numchannels) { - // Use channel numbers - if (atoi(chanfield)) - channels_num[i] = atoi(pc); - else// use channel IDs - channels_str[i] = strdup(pc); - pc = strtok(NULL, ","); - i++; - } - } + numchannels = loadChannelsFromString(chanfield, &channels_num, &channels_str); } if (strcmp(field, "title") == 0) source = REGEXP_TITLE; @@ -127,93 +99,136 @@ void cRegexp::SetFromString(char *s, bool Enabled, bool Precompile) source = REGEXP_SHORTTEXT; if (strcmp(field, "description") == 0) source = REGEXP_DESCRIPTION; - if (precompile) + if (compile) Compile(); } } } -void cRegexp::FreeCompiled() +bool cRegexp::Apply(cEvent *Event) { - if (re) { - pcre_free(re); - re = NULL; + bool active = true; + if (numchannels > 0) { + bool found = false; + int i = 0; + while (i < numchannels && !found) { + if (Channels.GetByChannelID(Event->ChannelID())->Number() == GetChannelNum(i)) + found = true; + if (GetChannelID(i) && strcmp(*(Event->ChannelID().ToString()), GetChannelID(i)) == 0) + found = true; + i++; + } + if (!found) + active = false; } - if (sd) { -#ifdef PCRE_CONFIG_JIT - pcre_free_study(sd); -#else - pcre_free(sd); -#endif - sd = NULL; + if (active && enabled && re) { + char *tmpstring; + switch (source) { + case REGEXP_TITLE: + tmpstring = strdup(Event->Title()); + break; + case REGEXP_SHORTTEXT: + if (Event->ShortText()) + tmpstring = strdup(Event->ShortText()); + else + tmpstring = strdup(""); + break; + case REGEXP_DESCRIPTION: + if (Event->Description()) + tmpstring = strdup(Event->Description()); + else + tmpstring = strdup(""); + break; + default: + tmpstring = strdup(""); + break; + } + const char *string; + int ovector[20]; + int rc; + rc = pcre_exec(re, sd, tmpstring, strlen(tmpstring), 0, 0, ovector, 20); + if (rc > 0) { + int i = 0; + while (i < 10) { + if (pcre_get_named_substring(re, tmpstring, ovector, rc, strBackrefs[i], &string) != PCRE_ERROR_NOSUBSTRING) { + char *tempstring = 0; + switch (i) { + case TITLE: + Event->SetTitle(string); + break; + case ATITLE: + tempstring = (char *)malloc(strlen(Event->Title())+strlen(string)+1); + strcpy(tempstring, Event->Title()); + strcat(tempstring, string); + Event->SetTitle(tempstring); + break; + case PTITLE: + tempstring = (char *)malloc(strlen(Event->Title())+strlen(string)+1); + strcpy(tempstring, string); + strcat(tempstring, Event->Title()); + Event->SetTitle(tempstring); + break; + case SHORTTEXT: + Event->SetShortText(string); + break; + case ASHORTTEXT: + tempstring = (char *)malloc(strlen(Event->ShortText())+strlen(string)+1); + strcpy(tempstring, Event->ShortText()); + strcat(tempstring, string); + Event->SetShortText(tempstring); + break; + case PSHORTTEXT: + tempstring = (char *)malloc(strlen(Event->ShortText())+strlen(string)+1); + strcpy(tempstring, string); + strcat(tempstring, Event->ShortText()); + Event->SetShortText(tempstring); + break; + case DESCRIPTION: + Event->SetDescription(string); + break; + case ADESCRIPTION: + tempstring = (char *)malloc(strlen(Event->Description())+strlen(string)+1); + strcpy(tempstring, Event->Description()); + strcat(tempstring, string); + Event->SetDescription(tempstring); + break; + case PDESCRIPTION: + tempstring = (char *)malloc(strlen(Event->Description())+strlen(string)+1); + strcpy(tempstring, string); + strcat(tempstring, Event->Description()); + Event->SetDescription(tempstring); + break; + case RATING: + Event->SetParentalRating(atoi(string)); + break; + default: + break; + } + pcre_free_substring(string); + free(tempstring); + } + i++; + } + free(tmpstring); + return true; + } + free(tmpstring); } + return false; } -void cRegexp::Compile() +void cRegexp::PrintConfigLineToFile(FILE *f) { - FreeCompiled(); - const char *error; - int erroffset; - re = pcre_compile(regexp, 0, &error, &erroffset, NULL); - if (error) { - esyslog("PCRE compile error: %s at offset %i", error, erroffset); - enabled = false; - } - else { - sd = pcre_study(re, 0, (const char **)&error); - if (error) - esyslog("PCRE study error: %s", error); + if (f) { + if (source == REGEXP_UNDEFINED) + fprintf(f, "%s\n", string); + else + fprintf(f, "%s%s\n", enabled ? "" : "!", string); } } -cEpgfixerRegexps::cEpgfixerRegexps() -{ - fileName = NULL; - regexps = new cRegexpList(); -} - -cEpgfixerRegexps::~cEpgfixerRegexps() -{ - free(fileName); - delete regexps; -} - -void cEpgfixerRegexps::SetRegexpConfigFile(const char *FileName) -{ - fileName = strdup(FileName); -} - -const char *cEpgfixerRegexps::RegexpConfigFile() -{ - return fileName; -} - -bool cEpgfixerRegexps::ReloadRegexps(bool AllowComments, bool Precompile) -{ - regexps->Clear(); - return LoadRegexps(fileName, AllowComments, Precompile); -} - -bool cEpgfixerRegexps::LoadRegexps(const char *FileName, bool AllowComments, bool Precompile) +void cRegexp::ToggleEnabled(void) { - bool result = false; - if (FileName && access(FileName, F_OK) == 0) { - FILE *f = fopen(FileName, "r"); - if (f) { - char *s; - cReadLine ReadLine; - while ((s = ReadLine.Read(f)) != NULL) { - if (!isempty(s)) { - regexps->Add(new cRegexp()); - regexps->Last()->SetFromString(s, true, Precompile); - } - } - fclose(f); - } - else { - LOG_ERROR_STR(FileName); - result = false; - } - } - return result; + if (source != REGEXP_UNDEFINED) + enabled = enabled ? 0 : 1; } @@ -1,5 +1,5 @@ /* - * regexp.h: Regular expression list + * regexp.h: Regular expression list item * * See the README file for copyright information and how to reach the author. * @@ -8,68 +8,37 @@ #ifndef _REGEXP_H_ #define _REGEXP_H_ +#include "tools.h" +#include <vdr/epg.h> #include <vdr/tools.h> +#include <stdio.h> #ifdef HAVE_PCREPOSIX #include <pcre.h> #endif typedef enum { REGEXP_TITLE,REGEXP_SHORTTEXT,REGEXP_DESCRIPTION,REGEXP_UNDEFINED } sources; -extern const char *strSources[]; -class cRegexp : public cListObject +class cRegexp : public cListItem { private: - bool enabled; char *regexp; - char *string; - int *channels_num; - char **channels_str; - int numchannels; int source; pcre *re; pcre_extra *sd; - void Free(); + void Compile(); + void FreeCompiled(); public: cRegexp(); - cRegexp(int Source, const char *Regex, bool Enabled, bool Precompile); virtual ~cRegexp(); - void SetFromString(char *string, bool Enabled, bool Precompile); - const char *GetString() { return string; } - void Compile(); - void FreeCompiled(); - bool Enabled(void) { return enabled; } + bool Apply(cEvent *Event); + void SetFromString(char *string, bool Enabled); + int GetSource() { return source; }; void ToggleEnabled(void); - int NumChannels() { return numchannels; } - int GetChannelNum(int index); - const char *GetChannelID(int index); - int GetSource(void) { return source; } - pcre *GetRe(void) { return re; } - pcre_extra *GetSd(void) { return sd; } -}; - -class cRegexpList : public cList<cRegexp> -{ -public: - void Clear(void) { cList<cRegexp>::Clear(); } - cRegexpList(void) {} -}; - -class cEpgfixerRegexps -{ -private: - bool LoadRegexps(const char *FileName = NULL, bool AllowComments = true, bool Precompile = true); - char *fileName; -public: - cRegexpList *regexps; - cEpgfixerRegexps(); - ~cEpgfixerRegexps(); - void SetRegexpConfigFile(const char *FileName); - const char *RegexpConfigFile(); - bool ReloadRegexps(bool AllowComments = true, bool Precompile = true); + virtual void PrintConfigLineToFile(FILE *f); }; // Global instance -extern cEpgfixerRegexps EpgfixerRegexps; +extern cEpgfixerList<cRegexp> EpgfixerRegexps; #endif //_REGEXP_H_ diff --git a/setup_menu.c b/setup_menu.c index eb8032d..a90030d 100644 --- a/setup_menu.c +++ b/setup_menu.c @@ -8,164 +8,147 @@ #include "setup_menu.h" #include <vdr/config.h> #include <vdr/i18n.h> +#include "tools.h" +#include "charset.h" #include "regexp.h" -//--- cMenuSetupRegexp ------------------------------------------------------ +//--- cMenuSetupConfigEditor ------------------------------------------------------ #define MAXREGEXPLENGTH 512 const char *RegexpChars = - " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=.,*%$^<>~:;\\/?!()[]{}#"; + " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%~\\/?!()[]{}<>$^*.,:;-=#"; -class cMenuSetupRegexp : public cMenuSetupPage +template<class T> class cMenuSetupConfigEditor : public cMenuSetupPage { private: + cEpgfixerList<T> *list; const char *fileName; char **lines; char **numlines; - void LoadRegexpArray(); - void FreeRegexpArray(); - void Save(); + virtual void LoadListToArray(void) + { + lines = (char **)malloc(sizeof(char *)*(list->Count())); + int i = 0; + T *item = (T *)list->First(); + while (item) { + lines[i] = (char *)malloc(sizeof(char)*MAXREGEXPLENGTH); + snprintf(lines[i], MAXREGEXPLENGTH, "%s", item->GetString()); + item = (T *)item->Next(); + i++; + } + } + void FreeArray() + { + int i = 0; + while (i < list->Count()) { + free(lines[i]); + i++; + } + free(lines); + } + void Save() + { + // Store regular expressions to config file + if (fileName && access(fileName, F_OK) == 0) { + FILE *f = fopen(fileName, "w"); + if (f) { + T *item = (T *)list->First(); + while (item) { + item->PrintConfigLineToFile(f); + item = (T *)item->Next(); + } + fclose(f); + } + } + } protected: - virtual void Store(void); - void Set(void); + virtual void Store(void) + { + // Store regular expressions back to list + int i = 0; + T *item = (T *)list->First(); + while (i < list->Count()) { + item->SetFromString(lines[i], item->Enabled()); + item = (T *)item->Next(); + i++; + } + } + void Set(void) + { + Clear(); + int i = 0; + T *item = (T *)list->First(); + while (i < list->Count()) { + Add(new cMenuEditStrItem(item->Enabled() ? "+" : "-", lines[i], MAXREGEXPLENGTH, RegexpChars)); + item = (T *)item->Next(); + i++; + } + SetHelp(tr("Toggle state"), tr("Add"), tr("Delete"), tr("Cancel")); + Display(); + } public: - cMenuSetupRegexp(void); - ~cMenuSetupRegexp(void); - virtual eOSState ProcessKey(eKeys Key); -}; - -void cMenuSetupRegexp::LoadRegexpArray() -{ - lines = (char **)malloc(sizeof(char *)*(EpgfixerRegexps.regexps->Count())); - int i = 0; - cRegexp *regex = (cRegexp *)EpgfixerRegexps.regexps->First(); - while (regex) { - lines[i] = (char *)malloc(sizeof(char)*MAXREGEXPLENGTH); - snprintf(lines[i], MAXREGEXPLENGTH, "%s", regex->GetString()); - regex = (cRegexp *)regex->Next(); - i++; - } -} - -cMenuSetupRegexp::cMenuSetupRegexp(void) -{ - cEitFilter::SetDisableUntil(time(NULL) + 1000); - SetCols(2); - fileName = EpgfixerRegexps.RegexpConfigFile(); - LoadRegexpArray(); - Set(); -} - -void cMenuSetupRegexp::FreeRegexpArray(void) -{ - int i = 0; - while (i < EpgfixerRegexps.regexps->Count()) { - free(lines[i]); - i++; - } - free(lines); -} - -cMenuSetupRegexp::~cMenuSetupRegexp(void) -{ - FreeRegexpArray(); - cEitFilter::SetDisableUntil(time(NULL) + 5); -} - -void cMenuSetupRegexp::Set(void) -{ - Clear(); - int i = 0; - cRegexp *regex = (cRegexp *)EpgfixerRegexps.regexps->First(); - while (i < EpgfixerRegexps.regexps->Count()) { - Add(new cMenuEditStrItem(regex->Enabled() ? "+" : "-", lines[i], MAXREGEXPLENGTH, RegexpChars)); - regex = (cRegexp *)regex->Next(); - i++; - } - SetHelp(tr("Toggle state"), tr("Add"), tr("Delete"), tr("Cancel")); - Display(); -} - -void cMenuSetupRegexp::Store(void) -{ - // Store regular expressions back to list - int i = 0; - cRegexp *regex = (cRegexp *)EpgfixerRegexps.regexps->First(); - while (i < EpgfixerRegexps.regexps->Count()) { - regex->SetFromString(lines[i], regex->Enabled(), true); - regex = (cRegexp *)regex->Next(); - i++; - } -} - -void cMenuSetupRegexp::Save(void) -{ - // Store regular expressions to regxep.conf - if (fileName && access(fileName, F_OK) == 0) { - FILE *f = fopen(fileName, "w"); - if (f) { - cRegexp *regex = (cRegexp *)EpgfixerRegexps.regexps->First(); - while (regex) { - if (regex->GetSource() == REGEXP_UNDEFINED) - fprintf(f, "%s\n", regex->GetString()); - else - fprintf(f, "%s%s\n", regex->Enabled() ? "" : "!", regex->GetString()); - regex = (cRegexp *)regex->Next(); - } - fclose(f); - } - } -} - -eOSState cMenuSetupRegexp::ProcessKey(eKeys Key) -{ - eOSState state = cOsdMenu::ProcessKey(Key); - - if (state == osUnknown) { - switch (Key) { - case kRed: - if (EpgfixerRegexps.regexps->Get(Current())->GetSource() != REGEXP_UNDEFINED) { - EpgfixerRegexps.regexps->Get(Current())->ToggleEnabled(); - Set(); - Display(); - } - state = osContinue; - break; - case kGreen: - Store(); - FreeRegexpArray(); - EpgfixerRegexps.regexps->Add(new cRegexp()); - LoadRegexpArray(); - Set(); - Display(); - state = osContinue; - break; - case kYellow: - Store(); - FreeRegexpArray(); - EpgfixerRegexps.regexps->Del(EpgfixerRegexps.regexps->Get(Current()),true); - LoadRegexpArray(); - Set(); - Display(); - state = osContinue; - break; - case kBlue: - EpgfixerRegexps.ReloadRegexps(); - state = osBack; - break; - case kOk: - Store(); - Save(); - EpgfixerRegexps.ReloadRegexps(); - state = osBack; - break; - default: - break; + cMenuSetupConfigEditor(cEpgfixerList<T> *l) + { + list = l; + cEitFilter::SetDisableUntil(time(NULL) + 1000); + SetCols(2); + fileName = list->GetConfigFile(); + LoadListToArray(); + Set(); + } + ~cMenuSetupConfigEditor(void) + { + FreeArray(); + cEitFilter::SetDisableUntil(time(NULL) + 5); + } + virtual eOSState ProcessKey(eKeys Key) + { + eOSState state = cOsdMenu::ProcessKey(Key); + + if (state == osUnknown) { + switch (Key) { + case kRed: + list->Get(Current())->ToggleEnabled(); + Set(); + Display(); + state = osContinue; + break; + case kGreen: + Store(); + FreeArray(); + list->Add(new T()); + LoadListToArray(); + Set(); + Display(); + state = osContinue; + break; + case kYellow: + Store(); + FreeArray(); + list->Del(list->Get(Current()),true); + LoadListToArray(); + Set(); + Display(); + state = osContinue; + break; + case kBlue: + list->ReloadConfigFile(); + state = osBack; + break; + case kOk: + Store(); + Save(); + list->ReloadConfigFile(); + state = osBack; + break; + default: + break; + } } - } - return state; -} + return state; + } +}; //--- cMenuSetupEpgfixer ------------------------------------------------------ @@ -178,6 +161,8 @@ cMenuSetupEpgfixer::cMenuSetupEpgfixer(void) void cMenuSetupEpgfixer::Set(void) { Clear(); + Add(new cOsdItem(tr("Regular expressions"), osUser1)); + Add(new cOsdItem(tr("Character set conversions"), osUser2)); Add(new cMenuEditBoolItem(tr("Remove quotes from ShortText"), &newconfig.quotedshorttext)); @@ -197,8 +182,9 @@ void cMenuSetupEpgfixer::Set(void) &newconfig.nobackticks)); Add(new cMenuEditBoolItem(tr("Fix stream component descriptions"), &newconfig.components)); - Add(new cOsdItem(tr("Regular expressions"), osUser1)); - SetHelp(tr("Reload regexp.conf"),NULL,NULL, tr("Clear EPG data")); + Add(new cMenuEditBoolItem(tr("Strip HTML entities"), + &newconfig.striphtml)); + SetHelp(tr("Reload files"),NULL,NULL, tr("Clear EPG data")); Display(); } @@ -215,6 +201,7 @@ void cMenuSetupEpgfixer::Store(void) SetupStore("PreventEqualShortTextAndDescription", EpgfixerSetup.equalshorttextanddescription); SetupStore("ReplaceBackticksWithSingleQuotes", EpgfixerSetup.nobackticks); SetupStore("FixStreamComponentDescriptions", EpgfixerSetup.components); + SetupStore("StripHTMLentities", EpgfixerSetup.striphtml); Setup.Save(); } @@ -226,14 +213,14 @@ eOSState cMenuSetupEpgfixer::ProcessKey(eKeys Key) if (state == osUnknown) { switch (Key) { case kRed: - EpgfixerRegexps.ReloadRegexps(); + EpgfixerRegexps.ReloadConfigFile(); + EpgfixerCharSets.ReloadConfigFile(); state = osContinue; break; case kBlue: cEitFilter::SetDisableUntil(time(NULL) + 10); - if (cSchedules::ClearAll()) { + if (cSchedules::ClearAll()) cEitFilter::SetDisableUntil(time(NULL) + 10); - } state = osContinue; break; default: @@ -241,6 +228,8 @@ eOSState cMenuSetupEpgfixer::ProcessKey(eKeys Key) } } else if (state == osUser1) - return AddSubMenu(new cMenuSetupRegexp()); + return AddSubMenu(new cMenuSetupConfigEditor<cRegexp>(&EpgfixerRegexps)); + else if (state == osUser2) + return AddSubMenu(new cMenuSetupConfigEditor<cCharSet>(&EpgfixerCharSets)); return state; } |