/* * 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' {"
", "\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; }