diff options
-rw-r--r-- | charset.c | 74 | ||||
-rw-r--r-- | charset.h | 31 | ||||
-rw-r--r-- | epgfixer/charset.conf | 3 | ||||
-rw-r--r-- | tools.c | 240 | ||||
-rw-r--r-- | tools.h | 82 |
5 files changed, 430 insertions, 0 deletions
diff --git a/charset.c b/charset.c new file mode 100644 index 0000000..0e77ed4 --- /dev/null +++ b/charset.c @@ -0,0 +1,74 @@ +/* + * regexp.c: Regular expression list + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include "charset.h" +#include <unistd.h> + +/* Global instance */ +cEpgfixerList<cCharSet> EpgfixerCharSets; + +cCharSet::cCharSet() +{ + charset = NULL; +} + +cCharSet::~cCharSet(void) +{ + free(charset); +} + +bool cCharSet::ConvertCharSet(cEvent *Event) +{ + 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 (active && enabled) { + cCharSetConv conv(charset, cCharSetConv::SystemCharacterTable()); + Event->SetTitle(conv.Convert(Event->Title())); + Event->SetShortText(conv.Convert(Event->ShortText())); + Event->SetDescription(conv.Convert(Event->Description())); + } + return false; +} + +void cCharSet::SetFromString(char *s, bool Enabled) +{ + Free(); + enabled = Enabled; + if (s[0] == '!') + string = strdup(s+1); + else + string = strdup(s); + if (s[0] == '!' || s[0] == '#') + enabled = false; + char *p = (s[0] == '#') ? s : strchr(s, '='); + if (p) { + if (p[0] != '#') { + *p = 0; + charset = strdup(p + 1); + char *chans = (s[0] == '!') ? s+1 : s; + numchannels = loadChannelsFromString(chans, &channels_num, &channels_str); + } + } +} + +void cCharSet::PrintConfigLineToFile(FILE *f) +{ + if (f) + fprintf(f, "%s%s\n", enabled ? "" : "!", string); +} diff --git a/charset.h b/charset.h new file mode 100644 index 0000000..fd021df --- /dev/null +++ b/charset.h @@ -0,0 +1,31 @@ +/* + * regexp.h: Regular expression list + * + * See the README file for copyright information and how to reach the author. + * + */ + +#ifndef _CHARSET_H_ +#define _CHARSET_H_ + +#include "tools.h" +#include <vdr/epg.h> +#include <vdr/tools.h> +#include <stdio.h> + +class cCharSet : public cListItem +{ +private: + char *charset; +public: + cCharSet(); + virtual ~cCharSet(); + bool ConvertCharSet(cEvent *Event); + void SetFromString(char *string, bool Enabled); + virtual void PrintConfigLineToFile(FILE *f); +}; + +// Global instance +extern cEpgfixerList<cCharSet> EpgfixerCharSets; + +#endif //_REGEXP_H_ diff --git a/epgfixer/charset.conf b/epgfixer/charset.conf new file mode 100644 index 0000000..98cd247 --- /dev/null +++ b/epgfixer/charset.conf @@ -0,0 +1,3 @@ +#C onvert character set of channels 1, 2 and 3 from iso8859-1 to character set +# used by VDR +1,2,3=iso8859-1 @@ -0,0 +1,240 @@ +/* + * tools.c: Tools for handling configuration files and strings + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include "tools.h" + +// +// HTML conversion code taken from RSS Reader plugin for VDR +// http://www.saunalahti.fi/~rahrenbe/vdr/rssreader/ +// by Rolf Ahrenberg +// + +// --- Static ----------------------------------------------------------- + +#define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) + +struct conv_table { + const char *from; + const char *to; +}; + +static struct conv_table pre_conv_table[] = +{ + // 'to' field must be smaller than 'from' + {"<br />", "\n"} +}; + +// Conversion page: http://www.ltg.ed.ac.uk/~richard/utf-8.cgi + +static struct conv_table post_conv_table[] = +{ + // 'to' field must be smaller than 'from' + {""", "\x22"}, + {""", "\x22"}, + {"&", "\x26"}, + {"&", "\x26"}, + {"&", "\x26"}, + {"'", "\x27"}, + {"(", "\x28"}, + {")", "\x29"}, + {":", "\x3a"}, + {"<", "\x3c"}, + {"<", "\x3c"}, + {">", "\x3e"}, + {">", "\x3e"}, + {"[", "\x5b"}, + {"]", "\x5d"}, + {" ", "\xc2\xa0"}, + {" ", "\xc2\xa0"}, + {"°", "\xc2\xb0"}, + {"°", "\xc2\xb0"}, + {"´", "\xc2\xb4"}, + {"´", "\xc2\xb4"}, + {"Ä", "\xc3\x84"}, + {"Ä", "\xc3\x84"}, + {"Å", "\xc3\x85"}, + {"Å", "\xc3\x85"}, + {"Ö", "\xc3\x96"}, + {"Ö", "\xc3\x96"}, + {"Ü", "\xc3\x9c"}, + {"Ü", "\xc3\x9c"}, + {"ß", "\xc3\x9f"}, + {"ß", "\xc3\x9f"}, + {"â", "\xc3\xa2"}, + {"â", "\xc3\xa2"}, + {"ä", "\xc3\xa4"}, + {"ä", "\xc3\xa4"}, + {"å", "\xc3\xa5"}, + {"å", "\xc3\xa5"}, + {"ç", "\xc3\xa7"}, + {"ç", "\xc3\xa7"}, + {"é", "\xc3\xa9"}, + {"é", "\xc3\xa9"}, + {"ê", "\xc3\xaa"}, + {"ê", "\xc3\xaa"}, + {"ö", "\xc3\xb6"}, + {"ö", "\xc3\xb6"}, + {"ü", "\xc3\xbc"}, + {"ü", "\xc3\xbc"}, + {"–", "\xe2\x80\x93"}, + {"–", "\xe2\x80\x93"}, + {"—", "\xe2\x80\x94"}, + {"—", "\xe2\x80\x94"}, + {"‘", "\xe2\x80\x98"}, + {"‘", "\xe2\x80\x98"}, + {"’", "\xe2\x80\x99"}, + {"’", "\xe2\x80\x99"}, + {"‚", "\xe2\x80\x9a"}, + {"‚", "\xe2\x80\x9a"}, + {"“", "\xe2\x80\x9c"}, + {"“", "\xe2\x80\x9c"}, + {"”", "\xe2\x80\x9d"}, + {"”", "\xe2\x80\x9d"}, + {"„", "\xe2\x80\x9e"}, + {"„", "\xe2\x80\x9e"}, + {"′", "\xe2\x80\xb3"}, + {"″", "\xe2\x80\xb3"}, + {"€", "\xe2\x82\xac"}, + {"€", "\xe2\x82\xac"}, + {"\n\n", "\n"}, // let's also strip multiple linefeeds +}; + +static char *htmlcharconv(char *str, struct conv_table *conv, unsigned int elem) +{ + if (str && conv) { + for (unsigned int i = 0; i < elem; ++i) { + char *ptr = strstr(str, conv[i].from); + while (ptr) { + long of = ptr - str; + size_t l = strlen(str); + size_t l1 = strlen(conv[i].from); + size_t l2 = strlen(conv[i].to); + if (l2 > l1) { + esyslog("htmlcharconv(): cannot reallocate string"); + return str; + } + if (l2 != l1) + memmove(str + of + l2, str + of + l1, l - of - l1 + 1); + strncpy(str + of, conv[i].to, l2); + ptr = strstr(str, conv[i].from); + } + } + return str; + } + return NULL; +} + +// --- General functions ------------------------------------------------ + +char *striphtml(char *str) +{ + if (str) { + char *c, t = 0, *r; + str = htmlcharconv(str, pre_conv_table, ELEMENTS(pre_conv_table)); + c = str; + r = str; + while (*str != '\0') { + if (*str == '<') + t++; + else if (*str == '>') + t--; + else if (t < 1) + *(c++) = *str; + str++; + } + *c = '\0'; + return htmlcharconv(r, post_conv_table, ELEMENTS(post_conv_table)); + } + return NULL; +} + +int count(const char *string, const char separator) +{ + int num = 0; + while (string) { + num++; + string = strchr(string+1, separator); + } + return num; +} + +int loadChannelsFromString(const char *string, int **channels_num, char ***channels_str) +{ + int numchannels = count(string, ','); + if (numchannels > 0) { + char *c = strdup(string); + // Use channel numbers + if (atoi(string)) + *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(string)) + (*channels_num)[i] = atoi(pc); + else// use channel IDs + (*channels_str)[i] = strdup(pc); + pc = strtok(NULL, ","); + i++; + } + } + return numchannels; +} + +cListItem::cListItem() +{ + enabled = false; + string = NULL; + numchannels = 0; + channels_num = NULL; + channels_str = NULL; +} + +cListItem::~cListItem(void) +{ + Free(); +} + +void cListItem::Free(void) +{ + free(channels_num); + if (channels_str) { + int i = 0; + while (i < numchannels) { + free(channels_str[i]); + i++; + } + } + free(channels_str); + free(string); + channels_num = NULL; + channels_str = NULL; + string = NULL; +} + +const char *cListItem::GetChannelID(int index) +{ + if (channels_str && index >= 0 && index < numchannels) + return channels_str[index]; + else + return NULL; +} + +int cListItem::GetChannelNum(int index) +{ + if (channels_num && index >= 0 && index < numchannels) + return channels_num[index]; + else + return -1; +} + +void cListItem::ToggleEnabled(void) +{ + enabled = enabled ? 0 : 1; +} @@ -0,0 +1,82 @@ +/* + * tools.h: Tools for handling configure files and strings + * + * See the README file for copyright information and how to reach the author. + * + */ + +#ifndef _STRINGTOOLS_H_ +#define _STRINGTOOLS_H_ + +#include <vdr/tools.h> +#include <unistd.h> +#include <stdio.h> + +char *striphtml(char *str); +int count(const char *string, const char separator); +int loadChannelsFromString(const char *string, int **channels_num, char ***channels_str); + +class cListItem : public cListObject +{ +protected: + bool enabled; + char *string; + int *channels_num; + char **channels_str; + int numchannels; + void Free(); + const char *GetChannelID(int index); + int GetChannelNum(int index); +public: + cListItem(); + virtual ~cListItem(); + void SetFromString(char *string, bool Enabled); + const char *GetString() { return string; } + bool Enabled(void) { return enabled; } + void ToggleEnabled(void); + int NumChannels() { return numchannels; } + virtual void PrintConfigLineToFIle(FILE *f) {} +}; + +template<class T> class cEpgfixerList : public cList<T> +{ +protected: + char *fileName; + bool LoadConfigFile(const char *FileName = NULL, bool AllowComments = true) + { + 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)) { + Add(new T()); + cList<T>::Last()->SetFromString(s, true); + } + } + fclose(f); + } + else { + LOG_ERROR_STR(FileName); + result = false; + } + } + return result; + } + +public: + cEpgfixerList() { fileName = NULL; } + ~cEpgfixerList() { free(fileName); } + void Clear(void) { cList<T>::Clear(); } + bool ReloadConfigFile(bool AllowComments = true) + { + Clear(); + return LoadConfigFile(fileName, AllowComments); + } + void SetConfigFile(const char *FileName) { fileName = strdup(FileName); } + const char *GetConfigFile() { return fileName; } +}; + +#endif //_STRINGTOOLS_H_ |