summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2011-07-24 16:50:37 +0200
committerJochen Dolze <vdr@dolze.de>2011-07-24 16:50:37 +0200
commit653b36f3db380683e73cb0ae3c17ddc28bd41fa1 (patch)
tree15cfb0b6299213d92bbfc2869607b1263146a3e4
parent107836c3b0f013e73c6cf572d8947c8d9133d39d (diff)
downloadvdr-plugin-xmltv2vdr-653b36f3db380683e73cb0ae3c17ddc28bd41fa1.tar.gz
vdr-plugin-xmltv2vdr-653b36f3db380683e73cb0ae3c17ddc28bd41fa1.tar.bz2
Added epgdata importer
-rw-r--r--dist/epgdata2xmltv/Makefile83
-rw-r--r--dist/epgdata2xmltv/epgdata2xmltv.cpp588
-rw-r--r--dist/epgdata2xmltv/epgdata2xmltv.dist109
-rw-r--r--dist/epgdata2xmltv/epgdata2xmltv.h52
-rw-r--r--dist/epgdata2xmltv/epgdata2xmltv.xsl238
-rw-r--r--xmltv2vdr.cpp4
6 files changed, 1072 insertions, 2 deletions
diff --git a/dist/epgdata2xmltv/Makefile b/dist/epgdata2xmltv/Makefile
new file mode 100644
index 0000000..7c63b0c
--- /dev/null
+++ b/dist/epgdata2xmltv/Makefile
@@ -0,0 +1,83 @@
+#
+# Makefile for epgdata2xmltv
+#
+
+### The C++ compiler and options:
+
+CXX ?= g++
+CXXFLAGS ?= -g -rdynamic -O2 -Wall -Wextra -Woverloaded-virtual -Wno-parentheses
+PKG-CONFIG ?= pkg-config
+STRIP ?= strip
+
+### Includes and Defines (add further entries here):
+
+PKG-LIBS += libxml-2.0 libxslt libexslt libcurl libzip
+PKG-INCLUDES += libxml-2.0 libxslt libexslt libcurl libzip
+
+DEFINES += -D_GNU_SOURCE
+DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+DEFINES += -D__STDC_CONSTANT_MACROS -D__USE_XOPEN_EXTENDED
+
+INCLUDES += $(shell $(PKG-CONFIG) --cflags $(PKG-INCLUDES))
+LIBS += $(shell $(PKG-CONFIG) --libs $(PKG-LIBS))
+
+INCLUDES += -I..
+
+### directory environment
+
+TMPDIR = /tmp
+
+### install directory ###
+
+INSTALL = /usr/bin
+
+### The object files (add further files here):
+
+OBJS = epgdata2xmltv.o
+
+### The main target:
+
+all: epgdata2xmltv_xsl epgdata2xmltv
+
+### Implicit rules:
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+### Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.cpp) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+epgdata2xmltv_xsl:
+ echo -n "char xsl[]=\"" > epgdata2xmltv_xsl.h
+ sed -e "s/\"/\\\\\"/g;" epgdata2xmltv.xsl | awk '{ printf("%s",$$0); }' >> epgdata2xmltv_xsl.h
+ echo "\";" >> epgdata2xmltv_xsl.h
+
+epgdata2xmltv: $(OBJS)
+ $(CXX) $(CXXFLAGS) $(OBJS) $(LIBS) -o $@
+
+install: epgdata2xmltv_xsl epgdata2xmltv
+ @cp epgdata2xmltv $(INSTALL)
+ $(STRIP) $(INSTALL)/epgdata2xmltv
+ @mkdir -p /var/lib/epgsources
+ @cp epgdata2xmltv.dist /var/lib/epgsources/epgdata2xmltv
+
+dist: clean
+ @-rm -rf $(TMPDIR)/epgdata2xmltv
+ @mkdir $(TMPDIR)/epgdata2xmltv
+ @cp -a *.cpp *.h *.xsl epgdata2xmltv.dist Makefile $(TMPDIR)/epgdata2xmltv
+ @tar cfz epgdata2xmltv.tgz -C $(TMPDIR) epgdata2xmltv
+ @-rm -rf $(TMPDIR)/epgdata2xmltv
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) epgdata2xmltv epgdata2xmltv_xsl.h
+
+distclean: clean
+ @-rm -f *~ *.tgz
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.cpp b/dist/epgdata2xmltv/epgdata2xmltv.cpp
new file mode 100644
index 0000000..0ccc1d9
--- /dev/null
+++ b/dist/epgdata2xmltv/epgdata2xmltv.cpp
@@ -0,0 +1,588 @@
+/*
+ * epgdata2xmltv.cpp: a grabber for the xmltv2vdr plugin
+ *
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <locale.h>
+#include <zip.h>
+#include "epgdata2xmltv.h"
+#include "epgdata2xmltv_xsl.h"
+
+#include <fcntl.h>
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+int SysLogLevel=1;
+
+void syslog_with_tid(const char *format, ...)
+{
+ va_list ap;
+ char fmt[255];
+ snprintf(fmt, sizeof(fmt), "%s", format);
+ va_start(ap, format);
+ vfprintf(stderr,fmt,ap);
+ va_end(ap);
+ fprintf(stderr,"\n");
+ fflush(stderr);
+}
+
+cepgdata2xmltv::cepgdata2xmltv ()
+{
+ data.size = 0;
+ data.fd=-1;
+ pxsltStylesheet = NULL;
+ sxmlDoc=NULL;
+}
+
+cepgdata2xmltv::~cepgdata2xmltv ()
+{
+ if (pxsltStylesheet)
+ {
+ xsltFreeStylesheet(pxsltStylesheet);
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+ }
+}
+
+void cepgdata2xmltv::LoadXSLT()
+{
+ if (pxsltStylesheet) return;
+ xmlSubstituteEntitiesDefault (1);
+ xmlLoadExtDtdDefaultValue = 1;
+ exsltRegisterAll();
+
+ if ((sxmlDoc = xmlReadMemory (xsl, sizeof(xsl), NULL,NULL,0)) != NULL)
+ {
+ pxsltStylesheet=xsltParseStylesheetDoc(sxmlDoc);
+ if (!pxsltStylesheet)
+ {
+ esyslog("can't parse stylesheet");
+ xmlFreeDoc (sxmlDoc);
+ sxmlDoc=NULL;
+ }
+ }
+}
+
+static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *dataptr)
+{
+ struct data *data = (struct data *) dataptr;
+ size_t realsize = size * nmemb;
+ if (data->fd!=-1)
+ {
+ write(data->fd,ptr,realsize);
+ data->size+=realsize;
+ }
+ return realsize;
+}
+
+
+int cepgdata2xmltv::DownloadData(const char *url)
+{
+ CURL *curl_handle;
+ data.size=0;
+
+ int ret;
+ ret=curl_global_init(CURL_GLOBAL_NOTHING);
+ if (ret) return ret;
+
+ curl_handle = curl_easy_init();
+ if (!curl_handle) return -40; // unused curl error
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url); // Specify URL to get
+ curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 0); // don't follow redirects
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); // Send all data to this function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &data); // Pass our 'data' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_MAXFILESIZE, 20971520); // Set maximum file size to get (bytes)
+ curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1); // No progress meter
+ curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); // No signaling
+ curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 240); // Set timeout to 240 seconds
+ curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, EPGDATA2XMLTV_USERAGENT); // Some servers don't like requests that are made without a user-agent field
+
+ ret=curl_easy_perform(curl_handle);
+ if (!ret)
+ {
+ long code;
+ curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code);
+ if (code==407)
+ {
+ ret=10;
+ }
+ else
+ {
+ if (code!=200) ret=22;
+ }
+ }
+
+ if ((data.size<120) && (!ret)) ret=22;
+
+ curl_easy_cleanup(curl_handle); // Cleanup curl stuff
+ curl_global_cleanup();
+ return -ret;
+}
+
+int cepgdata2xmltv::Fetch(const char *dest, const char *pin, int day)
+{
+ char *url = NULL;
+ char *filename = NULL;
+
+ if (asprintf (&filename, "%i&pin=%s",day,pin)==-1)
+ {
+ esyslog("failed to allocate string");
+ return 1;
+ }
+ if (asprintf (&url, EPGDATA2XMLTV_URL, filename) == -1)
+ {
+ esyslog("failed to allocate string");
+ free(filename);
+ return 1;
+ }
+ if (filename) free(filename);
+
+ data.fd=open(dest,O_CREAT|O_TRUNC|O_WRONLY,0664);
+ if (data.fd==-1)
+ {
+ esyslog("failed to open %s",dest);
+ return 1;
+ }
+
+ int ret=DownloadData(url);
+ close(data.fd);
+ if (ret) unlink(dest);
+ data.fd=-1;
+
+ free (url);
+ // -40 fatal curl error
+ // -10 wrong proxy auth
+ // -7 couldn't connect
+ // -6 couldn't resolve host (proxy)
+ // -22 not found
+ if (ret==-40)
+ {
+ esyslog("fatal curl error");
+ return 1;
+ }
+ if (ret==-28)
+ {
+ esyslog("timeout");
+ return 1;
+ }
+ if (ret==-10)
+ {
+ esyslog("wrong proxy auth");
+ return 1;
+ }
+ if (ret==-7)
+ {
+ esyslog("failed to connect");
+ return 2;
+ }
+ if (ret==-6)
+ {
+ esyslog("failed to resolve host");
+ return 2;
+ }
+ if (ret==-22)
+ {
+ esyslog("wrong pin");
+ return 1;
+
+ }
+ return 0;
+}
+
+char *cepgdata2xmltv::strreplace(char *s, const char *s1, const char *s2)
+{
+ char *p = strstr(s, s1);
+ if (p)
+ {
+ int of = p - s;
+ int l = strlen(s);
+ int l1 = strlen(s1);
+ int l2 = strlen(s2);
+ if (l2 > l1)
+ s = (char *)realloc(s, l + l2 - l1 + 1);
+ char *sof = s + of;
+ if (l2 != l1)
+ memmove(sof + l2, sof + l1, l - of - l1 + 1);
+ strncpy(sof, s2, l2);
+ }
+ return s;
+}
+
+int cepgdata2xmltv::Process(int argc, char *argv[])
+{
+ FILE *f=fopen("/var/lib/epgsources/epgdata2xmltv","r");
+ if (!f)
+ {
+ esyslog("failed to open epgdata2xmltv config");
+ return 1;
+ }
+ char *line=NULL,*lptr=NULL;
+ size_t size;
+ getline(&line,&size,f);
+ getline(&line,&size,f);
+ char *sc=strchr(line,';');
+ if (sc)
+ {
+ *sc=0;
+ sc++;
+ }
+ else
+ {
+ sc=line;
+ }
+ int daysmax=atoi(sc);
+ if (daysmax<0) daysmax=1;
+ int daysinadvance=atoi(argv[1]);
+ if (daysinadvance<0) daysinadvance=1;
+ if (daysinadvance>daysmax) daysinadvance=daysmax;
+
+ bool head=false;
+ char *xmlmem=NULL;
+
+ time_t t=time(NULL);
+
+ for (int day=0; day<=daysinadvance; day++)
+ {
+ time_t td=t+(day*86400);
+ struct tm *tm;
+ tm=localtime(&td);
+ char vgl[10];
+ sprintf(vgl,"%04i%02i%02i",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday);
+
+ char *dest=NULL;
+ if (asprintf(&dest,"/tmp/epgdata_%02i.zip",day)==-1)
+ {
+ esyslog("failed to allocate string");
+ continue;
+ }
+
+ bool ok=false;
+ do
+ {
+ bool offline=true;
+ struct stat statbuf;
+ if (stat(dest,&statbuf)==-1)
+ {
+ if (Fetch(dest,argv[2],day))
+ {
+ ok=true;
+ break;
+ }
+ offline=false;
+ }
+
+ struct zip *zip=zip_open(dest,0,NULL);
+ if (!zip)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ esyslog("cannot unlink %s",dest);
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ esyslog("failed to open %s",dest);
+ ok=true;
+ break;
+ }
+
+ int i=zip_name_locate(zip,"qy.dtd",ZIP_FL_NOCASE);
+ if (i==-1)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ esyslog("cannot unlink %s",dest);
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ esyslog("failed read qy.dtd in %s",dest);
+ ok=true;
+ break;
+ }
+
+ struct zip_file *zfile=zip_fopen_index(zip,i,0);
+ if (!zfile)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ esyslog("cannot unlink %s",dest);
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ esyslog("failed to read qy.dtd from %s",dest);
+ ok=true;
+ break;
+ }
+ struct zip_stat sb;
+ memset(&sb,0,sizeof(sb));
+ if (zip_stat_index(zip,i,ZIP_FL_UNCHANGED,&sb)==-1)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ zip_fclose(zfile);
+ esyslog("cannot unlink %s",dest);
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ zip_fclose(zfile);
+ esyslog("failed to stat qy.dtd in %s",dest);
+ ok=true;
+ break;
+ }
+ if (sizeof(sb.size>4)) sb.size &= 0x00FFFFFF; // just to be sure
+ xmlmem=(char *) malloc(sb.size+1);
+ int size=zip_fread(zfile,xmlmem,sb.size);
+ if (size!=sb.size)
+ {
+ zip_fclose(zfile);
+ esyslog("failed to read qy.dtd from %s",dest);
+ ok=true;
+ break;
+ }
+ xmlmem[size]=0;
+ zip_fclose(zfile);
+ xmlmem=strreplace(xmlmem,"?>\n","?>\n<!DOCTYPE pack [\n");
+
+ int entries=zip_get_num_files(zip);
+ for (int i=0; i<entries; i++)
+ {
+ const char *name=zip_get_name(zip,i,0);
+ if (strstr(name,"xml"))
+ {
+ // check date of xml
+ if (strstr(name,vgl))
+ {
+ struct zip_file *zfile=zip_fopen_index(zip,i,0);
+ if (!zfile)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ esyslog("cannot unlink %s",dest);
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ esyslog("failed to read %s from %s",name,dest);
+ ok=true;
+ break;
+ }
+ struct zip_stat sb;
+ memset(&sb,0,sizeof(sb));
+ if (zip_stat_index(zip,i,ZIP_FL_UNCHANGED,&sb)==-1)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ esyslog("cannot unlink %s",dest);
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ esyslog("failed to stat %s in %s",name,dest);
+ ok=true;
+ break;
+ }
+ if (sizeof(sb.size>4)) sb.size &= 0x00FFFFFF; // just to be sure
+ int lpos=strlen(xmlmem);
+ char *nptr=(char *) realloc(xmlmem,lpos+sb.size+1);
+ if (nptr)
+ {
+ xmlmem=nptr;
+ }
+ else
+ {
+ zip_fclose(zfile);
+ free(xmlmem);
+ xmlmem=NULL;
+ esyslog("out of memory");
+ ok=true;
+ break;
+ }
+ int size=zip_fread(zfile,xmlmem+lpos,sb.size);
+ if (size!=sb.size)
+ {
+ zip_fclose(zfile);
+ free(xmlmem);
+ xmlmem=NULL;
+ esyslog("failed to read %s from %s",name,dest);
+ ok=true;
+ break;
+ }
+ zip_fclose(zfile);
+ xmlmem[lpos+size]=0;
+ xmlmem[lpos++]=']';
+ xmlmem[lpos++]='>';
+ xmlmem[lpos++]='\n';
+ while (xmlmem[lpos]!='?')
+ {
+ xmlmem[lpos]=' ';
+ lpos++;
+ }
+ xmlmem[lpos++]=' ';
+ xmlmem[lpos++]=' ';
+ while (xmlmem[lpos]!='>')
+ {
+ xmlmem[lpos]=' ';
+ lpos++;
+ }
+ xmlmem[lpos++]=' ';
+ ok=true;
+ }
+ }
+ }
+ zip_close(zip);
+ if (!ok)
+ {
+ if (offline)
+ {
+ if (unlink(dest)==-1)
+ {
+ ok=true;
+ break;
+ }
+ continue;
+ }
+ else
+ {
+ esyslog("found no valid data in %s",dest);
+ if (xmlmem) free(xmlmem);
+ xmlmem=NULL;
+ ok=true;
+ break;
+ }
+ }
+ }
+ while (ok==false);
+ free(dest);
+
+ if (!line)
+ {
+ line=(char *) malloc(81);
+ size=80;
+ }
+ if (!xmlmem) continue;
+ long offset=ftell(f);
+
+ xmlDocPtr pxmlDoc;
+ if (!pxsltStylesheet) LoadXSLT();
+ if ((pxmlDoc=xmlParseMemory(xmlmem,strlen(xmlmem)))==NULL)
+ {
+ esyslog("failed parsing xml");
+ free(xmlmem);
+ continue;
+ }
+
+ for (;;)
+ {
+ lptr=line+1;
+ line[0]=' ';
+ if (getline(&lptr,&size,f)==-1) break;
+ char *channel=line;
+ char *sc=strchr(channel,';');
+ if (sc) *sc=0;
+
+ bool use=false;
+ for (int i=3; i<argc; i++)
+ {
+ if (!strcasecmp(lptr,argv[i]))
+ {
+ use=true;
+ break;
+ }
+ }
+
+ if (use)
+ {
+ if (!head)
+ {
+ printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ printf("<tv generator-info-name=\"epgdata2xmltv\">\n");
+
+ for (int i=3; i<argc; i++)
+ {
+ printf("<channel id=\"%s\">\n",argv[i]);
+ printf("<display-name lang=\"de\">%s</display-name>\n",argv[i]);
+ printf("</channel>\n");
+ }
+ head=true;
+ }
+
+ int num=atoi(sc+1);
+ if (num>0)
+ {
+ char *channelnum=strdup(sc+1);
+ char *lf=strchr(channelnum,10);
+ if (lf) *lf=0;
+ channel[0]='"';
+ *sc++='"';
+ *sc=0;
+ const char *params[5] =
+ {
+ "channelid", channel, "channelnum",channelnum,NULL
+ };
+ Translate(pxmlDoc,params);
+ if (channelnum) free(channelnum);
+ }
+ }
+ }
+ xmlFreeDoc (pxmlDoc);
+ fseek(f,offset,SEEK_SET);
+ if (xmlmem) free(xmlmem);
+ xmlmem=NULL;
+ }
+ if (line) free(line);
+ fclose(f);
+
+ if (head) printf("</tv>\n");
+ return head ? 0 : 1;
+}
+
+bool cepgdata2xmltv::Translate(xmlDocPtr pxmlDoc, const char **params)
+{
+ xmlDocPtr res=NULL;
+ if ((res = xsltApplyStylesheet (pxsltStylesheet, pxmlDoc, (const char **)params)) == NULL)
+ {
+ dsyslog("error applying xslt stylesheet");
+ return false;
+ }
+ else
+ {
+ xsltSaveResultToFile(stdout,res,pxsltStylesheet);
+ xmlFreeDoc (res);
+ }
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc<4) return 132;
+ cepgdata2xmltv *epgdata2xmltv = new cepgdata2xmltv;
+ int ret=epgdata2xmltv->Process(argc, argv);
+ delete epgdata2xmltv;
+ return ret;
+}
+
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.dist b/dist/epgdata2xmltv/epgdata2xmltv.dist
new file mode 100644
index 0000000..110eeb0
--- /dev/null
+++ b/dist/epgdata2xmltv/epgdata2xmltv.dist
@@ -0,0 +1,109 @@
+pipe;00:00;1
+17
+ard.de;71
+zdf.de;37
+arte.de;58
+3sat.de;56
+br-alpha.de;104
+einsmuxx.de;475
+einsfestival.de;146
+einsextra.de;100
+zdfinfo.de;276
+zdf-theaterkanal.de;275
+zdfneo.de;659
+phoenix.de;194
+bayern3.de;51
+hessen3.de;49
+rbb.de;52
+swr.de;50
+wdr.de;46
+ndr.de;47
+kika.de;57
+mdr.de;48
+rtl.de;38
+sat1.de;39
+rtl2.de;41
+prosieben.de;40
+superrtl.de;43
+kabel1.de;44
+vox.de;42
+sixx.de;694
+das-vierte.de;486
+tele5.de;277
+9live.de;1179
+ntv.de;66
+euronews.de;68
+n24.de;175
+bloombergtv.de;127
+cnn.de;69
+eurosport.de;65
+dsf.de;64
+nickcomedy.de;589
+dmax.de;507
+hse24.de;159
+qvc.de;208
+bibeltv.de;280
+timm.de;588
+orf1.at;54
+orf2.at;55
+atvplus.at;115
+tw1.at;265
+viva.de;266
+mtv.de;70
+gotv.at;391
+fashiontv.fr;455
+
+ Sky Deutschland
+610 = S19.2E-133-2-10 Sky Cinema,Cinema;SKY
+611 = S19.2E-133-2-11 Sky Cinema +1,Cinema1;SKY
+612 = S19.2E-133-2-43 Sky Cinema +24,Cinema24;SKY
+613 = S19.2E-133-2-9 Sky Action,Action;SKY
+617 = S19.2E-133-2-8 Sky Comedy,Comedy;SKY
+616 = S19.2E-133-2-20 Sky Emotion,Emotion;SKY
+614 = S19.2E-133-3-516 Sky Nostalgie,Nostalgie;SKY
+618 = S19.2E-133-3-41 Sky Cinema Hits,CineHits;SKY
+630 = S19.2E-133-3-25 Disney Cinemagic,Cinemagic;SKY
+1196 = S19.2E-133-3-515 MGM;SKY
+138 = S19.2E-133-4-14 Discovery Channel,Discovery;SKY
+453 = S19.2E-133-4-13 National Geographic,NatGeo;SKY
+626 = S19.2E-133-4-12 NatGeo Wild,NG Wild;SKY
+625 = S19.2E-133-4-52 Spiegel Geschichte,SpiegelG;SKY
+627 = S19.2E-133-1-168 Motorvision TV,Motorvis;SKY
+476 = S19.2E-133-4-15 Focus Gesundheit,Focus;SKY
+615 = S19.2E-133-1-23 Sky Krimi,SkyKrimi;SKY
+527 = S19.2E-133-1-27 RTL Crime,RTLCrime;SKY
+471 = S19.2E-133-1-42 13th Street,13Street;SKY
+472 = S19.2E-133-17-36 SciFi;SKY
+565 = S19.2E-133-1-16 Fox Serie,Fox;SKY
+590 = S19.2E-133-1-50 TNT Serie,TNTSerie;SKY
+529 = S19.2E-133-1-29 RTL Passion,Passion;SKY
+154 = S19.2E-133-17-22 Heimatkanal,Heimat;SKY
+139 = S19.2E-133-17-34 Disney Channel,Disney;SKY
+460 = S19.2E-133-17-26 Playhouse Disney,Playhouse;SKY ???
+160 = S19.2E-133-17-19 Junior;SKY
+ = S19.2E-133-17-28 Disney XD,DisneyXD;SKY ???
+152 = S19.2E-133-17-518 Goldstar TV,Goldstar;SKY
+133 = S19.2E-133-17-24 Classica;SKY
+123 = S19.2E-133-17-21 Beate-Uhse.TV,BeateU;SKY
+491 = S19.2E-1-1107-17505 Sat.1 Comedy;ProSiebenSat.1
+468 = S19.2E-133-9-62 AXN Action,AXN;arena/SKY
+633 = S19.2E-133-9-61 TNT Film (TCM),TNT Film;arena/SKY
+492 = S19.2E-1-1107-17506 kabel eins classics;ProSiebenSat.1
+450 = S19.2E-133-9-60 Kinowelt TV,Kinowelt;SKY ???
+552 = S19.2E-133-9-63 Romance TV,Romance;SKY ???
+551 = S19.2E-1-1078-28682 NICK PREMIUM (S);MTV Networks Europe ???
+493 = S19.2E-133-9-66 Boomerang;arena/SKY ???
+132 = S19.2E-1-1102-13204 Cartoon Network (a/S);arena/SKY
+452 = S19.2E-133-9-68 History;SKY
+536 = S19.2E-1-1102-13208 Biography Channel;arena/SKY ???
+528 = S19.2E-1-1102-13207 RTL Living;arena/SKY
+ = S19.2E-133-9-67 e.clips;SKY ???
+539 = S19.2E-1-1102-13203 ANIMAX;arena/SKY
+553 = S19.2E-1-1078-28681 MTV ENTERTAINMENT (S);MTV Networks Europe ???
+496 = S19.2E-1-1066-28657 VH1 Classic;MTV Networks Europe ???
+504 = S19.2E-1-1102-13205 EuroSport 2 (a/S);arena/SKY
+591 = S19.2E-1-1115-13105 ESPN America (S);SKY
+622 = S19.2E-133-7-53 Sky Sport Austria,SportAut;SKY
+628 = S19.2E-133-4-18 Sky Select,SkySel;SKY
+
+ Musik
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.h b/dist/epgdata2xmltv/epgdata2xmltv.h
new file mode 100644
index 0000000..3748c5d
--- /dev/null
+++ b/dist/epgdata2xmltv/epgdata2xmltv.h
@@ -0,0 +1,52 @@
+/*
+ * epgdata2xmltv.h: a grabber for the xmltv2vdr plugin
+ *
+ */
+
+#ifndef __EPGDATA2XMLTV_H
+#define __EPGDATA2XMLTV_H
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libexslt/exslt.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define esyslog(a...) void( (SysLogLevel > 0) ? syslog_with_tid(a) : void() )
+#define isyslog(a...) void( (SysLogLevel > 1) ? syslog_with_tid(a) : void() )
+#define dsyslog(a...) void( (SysLogLevel > 2) ? syslog_with_tid(a) : void() )
+#define tsyslog(a...) void( (SysLogLevel > 3) ? syslog_with_tid(a) : void() )
+
+#define EPGDATA2XMLTV_USERAGENT "libcurl-agent/1.0"
+#define EPGDATA2XMLTV_URL "http://www.epgdata.com/index.php?action=sendPackage&iOEM=VDR&dataType=xml&dayOffset=%s"
+
+struct data
+{
+ size_t size;
+ int fd;
+};
+
+class cepgdata2xmltv
+{
+private:
+ struct data data;
+ xsltStylesheetPtr pxsltStylesheet;
+ xmlDocPtr sxmlDoc;
+ char *strreplace(char *s, const char *s1, const char *s2);
+ int Fetch(const char *path, const char *pin, int day);
+ int DownloadData(const char *url);
+ bool Translate(xmlDocPtr pxmlDoc, const char **params);
+ void LoadXSLT();
+public:
+ cepgdata2xmltv();
+ ~cepgdata2xmltv();
+ int Process(int argc, char *argv[]);
+};
+
+#endif //__EPGDATA2XMLTV_H
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.xsl b/dist/epgdata2xmltv/epgdata2xmltv.xsl
new file mode 100644
index 0000000..a85e0c2
--- /dev/null
+++ b/dist/epgdata2xmltv/epgdata2xmltv.xsl
@@ -0,0 +1,238 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:date="http://exslt.org/dates-and-times"
+ xmlns:str="http://exslt.org/strings">
+<xsl:output method="xml" omit-xml-declaration="yes" encoding='utf-8'/>
+
+<xsl:template match="/">
+<xsl:for-each select="//data[d2=$channelnum]">
+
+<!--
+<xsl:variable name="start_xmltv">
+<xsl:value-of select="d4"/>
+</xsl:variable>
+
+<xsl:variable name="stop_xmltv">
+<xsl:value-of select="d5"/>
+</xsl:variable>
+
+<xsl:variable name="vps_xmltv">
+<xsl:value-of select="d8"/>
+</xsl:variable>
+-->
+
+<xsl:variable name="EVENTID">
+<xsl:value-of select="d0"/>
+</xsl:variable>
+
+<xsl:variable name="INHALT">
+<xsl:value-of select="translate(d22,'|','&#x0A;')"/>
+</xsl:variable>
+
+<xsl:variable name="THEMEN">
+<xsl:value-of select="translate(d24,'|','&#x0A;')"/>
+</xsl:variable>
+
+<xsl:variable name="JAHR">
+<xsl:value-of select="d33"/>
+</xsl:variable>
+
+<xsl:variable name="LAND">
+<xsl:value-of select="translate(d32,'|','/')"/>
+</xsl:variable>
+
+<xsl:variable name="GENRE">
+G <xsl:value-of select="d25"/>
+</xsl:variable>
+
+<xsl:variable name="CREW">
+
+<xsl:if test="string-length(d36)">
+<xsl:call-template name="output-tokens">
+<xsl:with-param name="list"><xsl:value-of select="d36"/></xsl:with-param>
+<xsl:with-param name="tag">director</xsl:with-param>
+<xsl:with-param name="delimiter">|</xsl:with-param>
+</xsl:call-template>
+</xsl:if>
+
+<xsl:if test="string-length(d37)">
+<xsl:call-template name="output-tokens">
+<xsl:with-param name="list"><xsl:value-of select="d37"/></xsl:with-param>
+<xsl:with-param name="tag">actor</xsl:with-param>
+<xsl:with-param name="delimiter"> - </xsl:with-param>
+</xsl:call-template>
+</xsl:if>
+
+<xsl:if test="string-length(d34)">
+<xsl:call-template name="output-tokens">
+<xsl:with-param name="list"><xsl:value-of select="d34"/></xsl:with-param>
+<xsl:with-param name="tag">presenter</xsl:with-param>
+<xsl:with-param name="delimiter">|</xsl:with-param>
+</xsl:call-template>
+</xsl:if>
+
+<xsl:if test="string-length(d35)">
+<xsl:call-template name="output-tokens">
+<xsl:with-param name="list"><xsl:value-of select="d35"/></xsl:with-param>
+<xsl:with-param name="tag">guest</xsl:with-param>
+<xsl:with-param name="delimiter"> - </xsl:with-param>
+</xsl:call-template>
+</xsl:if>
+
+</xsl:variable>
+
+<xsl:variable name="VIDEO">
+</xsl:variable>
+
+<xsl:variable name="AUDIO">
+</xsl:variable>
+
+
+<xsl:variable name="vps_iso8601">
+<xsl:if test="string-length(d8)">
+<xsl:call-template name="date2UTC">
+<xsl:with-param name="date" select="concat(substring-before(d4,' '),'T',d8,':00')"/>
+</xsl:call-template>
+</xsl:if>
+</xsl:variable>
+
+<xsl:variable name="start_iso8601">
+<xsl:call-template name="date2UTC">
+<xsl:with-param name="date" select="concat(substring-before(d4,' '),'T',substring-after(d4,' '))"/>
+</xsl:call-template>
+</xsl:variable>
+
+<xsl:variable name="stop_iso8601">
+<xsl:call-template name="date2UTC">
+<xsl:with-param name="date" select="concat(substring-before(d5,' '),'T',substring-after(d5,' '))"/>
+</xsl:call-template>
+</xsl:variable>
+
+<xsl:variable name="start_xmltv">
+<xsl:value-of select="concat(translate($start_iso8601,'-:ZT',''),' +0000')"/>
+</xsl:variable>
+
+<xsl:variable name="vps_xmltv">
+<xsl:if test="string-length($vps_iso8601)">
+<xsl:value-of select="concat(translate($vps_iso8601,'-:ZT',''),' +0000')"/>
+</xsl:if>
+</xsl:variable>
+
+<xsl:variable name="stop_xmltv">
+<xsl:value-of select="concat(translate($stop_iso8601,'-:ZT',''),' +0000')"/>
+</xsl:variable>
+
+<xsl:element name="programme">
+<xsl:attribute name="start">
+<xsl:value-of select="$start_xmltv"/>
+</xsl:attribute>
+<xsl:attribute name="stop">
+<xsl:value-of select="$stop_xmltv"/>
+</xsl:attribute>
+<xsl:if test="string-length($vps_xmltv)">
+<xsl:attribute name="vps-start">
+<xsl:value-of select="$vps_xmltv"/>
+</xsl:attribute>
+</xsl:if>
+<xsl:attribute name="channel">
+<xsl:value-of select="$channelid"/>
+</xsl:attribute>
+<xsl:text>&#x0A;</xsl:text>
+
+<title lang="de"><xsl:value-of select="d19"/></title><xsl:text>&#x0A;</xsl:text>
+<xsl:if test="string-length(d20)">
+<sub-title lang="de"><xsl:value-of select="d20"/></sub-title><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($THEMEN)">
+<desc lang="de"><xsl:value-of select="$THEMEN"/></desc><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($INHALT)">
+<desc lang="de"><xsl:value-of select="$INHALT"/></desc><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($CREW)">
+<credits><xsl:text>&#x0A;</xsl:text><xsl:copy-of select="$CREW"/></credits><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($JAHR)">
+<date><xsl:value-of select="$JAHR"/></date><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($GENRE)">
+<category lang="de"><xsl:value-of select="$GENRE"/></category><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($EVENTID)">
+<category lang="de"><xsl:value-of select="$EVENTID"/></category><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($LAND)">
+<country><xsl:value-of select="$LAND"/></country><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($VIDEO)">
+<video><xsl:text>&#x0A;</xsl:text><xsl:copy-of select="$VIDEO"/></video><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+<xsl:if test="string-length($AUDIO)">
+<audio><xsl:text>&#x0A;</xsl:text><stereo><xsl:value-of select="$AUDIO"/></stereo><xsl:text>&#x0A;</xsl:text></audio><xsl:text>&#x0A;</xsl:text>
+</xsl:if>
+
+</xsl:element>
+<xsl:text>&#x0A;</xsl:text>
+</xsl:for-each>
+</xsl:template>
+
+<xsl:template name="date2UTC">
+ <xsl:param name="date"/>
+
+ <xsl:variable name="dststart">
+ <xsl:value-of select="concat(date:year($date),'-03-',32-date:day-in-week(concat(date:year($date),'-03-31')),'T02:00:00')"/>
+ </xsl:variable>
+
+ <xsl:variable name="dstend">
+ <xsl:value-of select="concat(date:year($date),'-10-',32-date:day-in-week(concat(date:year($date),'-10-31')),'T03:00:00')"/>
+ </xsl:variable>
+
+ <xsl:variable name="tz">
+ <xsl:choose>
+ <xsl:when test="date:seconds(date:difference($dststart,$date)) &gt;= 0">
+ <xsl:choose>
+ <xsl:when test="date:seconds(date:difference($date,$dstend)) &gt;= 0">-PT2H</xsl:when>
+ <xsl:otherwise>-PT1H</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>-PT1H</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="date:add($date,$tz)"/>
+</xsl:template>
+
+<xsl:template name="output-tokens">
+ <xsl:param name="list" />
+ <xsl:param name="delimiter" />
+ <xsl:param name="tag" />
+ <xsl:param name="last"/>
+ <xsl:variable name="newlist">
+ <xsl:choose>
+ <xsl:when test="contains($list, $delimiter)"><xsl:value-of select="normalize-space($list)" /></xsl:when>
+
+ <xsl:otherwise><xsl:value-of select="concat(normalize-space($list), $delimiter)"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="first" select="substring-before($newlist, $delimiter)" />
+ <xsl:variable name="remaining" select="substring-after($newlist, $delimiter)" />
+ <xsl:if test="$first != $last">
+ <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="$tag"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
+ <xsl:value-of select="$first" />
+ <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="$tag"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
+ <xsl:text>&#x0A;</xsl:text>
+ </xsl:if>
+ <xsl:if test="$remaining">
+ <xsl:call-template name="output-tokens">
+ <xsl:with-param name="list" select="$remaining" />
+ <xsl:with-param name="delimiter"><xsl:value-of select="$delimiter"/></xsl:with-param>
+ <xsl:with-param name="tag" select="$tag"/>
+ <xsl:with-param name="last" select="$first"/>
+ </xsl:call-template>
+ </xsl:if>
+</xsl:template>
+
+
+
+</xsl:stylesheet>
diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp
index 9f79c01..b225274 100644
--- a/xmltv2vdr.cpp
+++ b/xmltv2vdr.cpp
@@ -104,7 +104,7 @@ bool cEPGSource::ReadConfig()
esyslog("xmltv2vdr: '%s' out of memory",name);
return false;
}
- FILE *f=fopen(fname,"r+");
+ FILE *f=fopen(fname,"r");
if (!f)
{
esyslog("xmltv2vdr: '%s' ERROR cannot read config file %s",name,fname);
@@ -542,7 +542,7 @@ void cPluginXmltv2vdr::ReadInEPGSources(bool Reload)
char *path=NULL;
if (asprintf(&path,"%s/%s",EPGSOURCES,dirent->d_name)!=-1)
{
- if (access(path,R_OK|W_OK)!=-1)
+ if (access(path,R_OK)!=-1)
{
int fd=open(path,O_RDONLY);
if (fd!=-1)