summaryrefslogtreecommitdiff
path: root/PLUGINS/epgdata
diff options
context:
space:
mode:
Diffstat (limited to 'PLUGINS/epgdata')
-rw-r--r--PLUGINS/epgdata/Makefile52
-rw-r--r--PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra176
-rw-r--r--PLUGINS/epgdata/configs/epgd.conf10
-rw-r--r--PLUGINS/epgdata/configs/epgdata-category.xml143
-rw-r--r--PLUGINS/epgdata/configs/epgdata-genre.xml507
-rw-r--r--PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl8
-rw-r--r--PLUGINS/epgdata/configs/epgdata-utf-8.xsl8
-rw-r--r--PLUGINS/epgdata/configs/epgdata.xsl208
-rw-r--r--PLUGINS/epgdata/epgdata.c760
-rw-r--r--PLUGINS/epgdata/epgdata.h52
-rwxr-xr-xPLUGINS/epgdata/scripts/getepgdataids37
-rwxr-xr-xPLUGINS/epgdata/scripts/getincludes6
12 files changed, 1967 insertions, 0 deletions
diff --git a/PLUGINS/epgdata/Makefile b/PLUGINS/epgdata/Makefile
new file mode 100644
index 0000000..837c3c1
--- /dev/null
+++ b/PLUGINS/epgdata/Makefile
@@ -0,0 +1,52 @@
+#
+# Makefile
+#
+# See the README file for copyright information and how to reach the author.
+#
+#
+
+EPGD_SRC ?= ../..
+
+include $(EPGD_SRC)/Make.config
+
+PLUGIN = epgdata
+
+SOFILE = libepgd-epgdata.so
+OBJS = epgdata.o
+
+CFLAGS += -I$(EPGD_SRC)
+
+all: $(SOFILE)
+
+$(SOFILE): $(OBJS)
+ $(CC) $(CFLAGS) -shared $(OBJS) $(LIBS) -o $@
+
+install: $(SOFILE) install-config
+ install -D $(SOFILE) $(_PLGDEST)/
+
+clean:
+ @-rm -f $(OBJS) core* *~ *.so
+
+install-config:
+ if ! test -d $(CONFDEST); then \
+ mkdir -p $(CONFDEST); \
+ chmod a+rx $(CONFDEST); \
+ fi
+ if ! test -f $(CONFDEST)/channelmap.conf-epgdata-astra; then \
+ install --mode=644 -D ./configs/channelmap.conf-epgdata-astra $(CONFDEST)/; \
+ fi
+ for i in $(wildcard ./configs/epgdata*.xml) $(wildcard ./configs/*.xsl); do\
+ if ! test -f "$(CONFDEST)/`basename $$i`"; then\
+ install --mode=644 -D "$$i" $(CONFDEST)/; \
+ fi;\
+ done;
+ if ! grep -q "^epgdata" $(CONFDEST)/epgd.conf; then \
+ cat ./configs/epgd.conf >> $(CONFDEST)/epgd.conf; \
+ fi
+
+
+#***************************************************************************
+# dependencies
+#***************************************************************************
+
+epgdata.o : epgdata.c epgdata.h
diff --git a/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra b/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra
new file mode 100644
index 0000000..7a3af70
--- /dev/null
+++ b/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra
@@ -0,0 +1,176 @@
+epgdata:71 = S19.2E-1-1019-10301 // Das Erste HD
+epgdata:37 = S19.2E-1-1011-11110 // ZDF HD
+epgdata:194 = S19.2E-1-1025-10331 // PHOENIX HD
+epgdata:56 = S19.2E-1-1010-11150 // 3sat HD
+epgdata:58 = S19.2E-1-1019-10302 // arte HD
+epgdata:146 = S19.2E-1-1201-28396 // Einsfestival HD
+epgdata:57 = S19.2E-1-1010-11160 // KiKA HD
+epgdata:275 = S19.2E-1-1011-11140 // zdf.kultur HD
+epgdata:276 = S19.2E-1-1010-11170 // ZDFinfo HD
+epgdata:659 = S19.2E-1-1011-11130 // zdf_neo HD
+
+epgdata:71 = S19.2E-1-1101-28106 // Das Erste
+epgdata:37 = S19.2E-1-1079-28006 // ZDF
+epgdata:194 = S19.2E-1-1051-28725 // PHOENIX
+epgdata:56 = S19.2E-1-1079-28007 // 3sat
+epgdata:58 = S19.2E-1-1051-28724 // arte
+epgdata:146 = S19.2E-1-1051-28722 // Einsfestival
+epgdata:475 = S19.2E-1-1051-28723 // EinsPlus
+epgdata:57 = S19.2E-1-1079-28008 // KiKA
+epgdata:100 = S19.2E-1-1051-28721 // tagesschau24
+epgdata:275 = S19.2E-1-1079-28016 // zdf.kultur
+epgdata:276 = S19.2E-1-1079-28011 // ZDFinfo
+epgdata:659 = S19.2E-1-1079-28014 // zdf_neo
+
+epgdata:38 = S19.2E-1-1089-12003 // RTL Television
+epgdata:41 = S19.2E-1-1089-12020 // RTL2
+epgdata:43 = S19.2E-1-1089-12040 // SUPER RTL
+epgdata:763 = S19.2E-1-1089-12061 // RTLNITRO
+epgdata:39 = S19.2E-1-1107-17500 // SAT.1
+epgdata:774 = S19.2E-1-1107-17504 // SAT.1 Gold
+epgdata:40 = S19.2E-1-1107-17501 // ProSieben
+epgdata:44 = S19.2E-1-1107-17502 // kabel eins
+epgdata:507 = S19.2E-133-33-63 // DMAX
+epgdata:694 = S19.2E-133-5-776 // SIXX
+epgdata:42 = S19.2E-1-1089-12060 // VOX
+epgdata:660 = S19.2E-1-1115-13110 // ServusTV Deutschland
+epgdata:64 = S19.2E-133-33-9001 // SPORT1
+epgdata:65 = S19.2E-1-1091-31200 // Eurosport Deutschland
+epgdata:66 = S19.2E-1-1089-12090 // n-tv
+epgdata:175 = S19.2E-1-1107-17503 // N24
+epgdata:391 = S19.2E-1-1115-13102 // GoTV
+// = S19.2E-133-7-65 // DELUXE MUSIC
+// = S19.2E-1-1078-28676 // VIVA Germany
+// = S19.2E-1-1021-4600 // a.tv
+
+epgdata:471 = S19.2E-133-1-42 // 13th Street
+epgdata:123 = S19.2E-133-17-21 // Beate-Uhse.TV
+epgdata:133 = S19.2E-133-17-24 // Classica
+epgdata:138 = S19.2E-133-4-14 // Discovery Channel
+epgdata:139 = S19.2E-133-17-34 // Disney Channel
+epgdata:460 = S19.2E-133-17-26 // Disney Junior
+epgdata:657 = S19.2E-133-17-28 // Disney XD
+// = S19.2E-133-1-16 // Fox Serie
+epgdata:152 = S19.2E-133-17-518 // Goldstar TV
+epgdata:154 = S19.2E-133-17-22 // Heimatkanal
+epgdata:160 = S19.2E-133-17-19 // Junior
+epgdata:627 = S19.2E-133-1-168 // Motorvision TV
+epgdata:626 = S19.2E-133-4-12 // NatGeo Wild
+epgdata:453 = S19.2E-133-4-13 // National Geographic Channel
+epgdata:527 = S19.2E-133-1-27 // RTL Crime
+epgdata:529 = S19.2E-133-1-29 // RTL Passion
+epgdata:701 = S19.2E-133-10-117 // Sky 3D
+epgdata:615 = S19.2E-133-1-23 // Sky Krimi
+epgdata:625 = S19.2E-133-4-52 // Spiegel Geschichte
+epgdata:472 = S19.2E-133-17-36 // Syfy
+epgdata:590 = S19.2E-133-1-50 // TNT Serie
+
+// = S19.2E-133-13-127 // 13th Street HD
+// = S19.2E-133-10-125 // AXN HD
+epgdata:490 = S19.2E-133-6-130 // Discovery HD
+// = S19.2E-133-11-116 // Disney Channel HD
+// = S19.2E-133-14-128 // E! Entertainm. HD
+// = S19.2E-133-10-124 // Fox HD
+epgdata:632 = S19.2E-133-11-113 // History HD
+// = S19.2E-133-6-118 // Nat Geo Wild HD
+// = S19.2E-133-13-112 // NatGeo HD
+epgdata:762 = S19.2E-133-12-108 // Sky Sport News HD
+// = S19.2E-133-12-126 // Syfy HD
+// = S19.2E-133-11-123 // TNT Serie HD
+// = S19.2E-133-14-101 // Universal HD
+epgdata:10058 = S19.2E-133-10-106 // Sky Action HDD
+epgdata:10059 = S19.2E-133-12-107 // Sky Hits HD
+
+epgdata:539 = S19.2E-1-1037-5253 // Animax
+// = S19.2E-133-15-37 // AXN Action
+epgdata:536 = S19.2E-133-15-57 // Biography Channel
+epgdata:127 = S19.2E-133-15-56 // Bloomberg TV
+epgdata:531 = S19.2E-133-15-39 // Cartoon Network (S)
+// = S19.2E-1-1115-13105 // ESPN America (S)
+epgdata:452 = S19.2E-133-15-58 // History
+epgdata:492 = S19.2E-1-1107-17506 // kabel eins classics
+epgdata:450 = S19.2E-133-15-33 // Kinowelt TV
+// = S19.2E-133-15-38 // Romance TV
+epgdata:528 = S19.2E-1-1089-12030 // RTL Living
+epgdata:766 = S19.2E-1-1015-4701 // SAT.1 emotions
+// = S19.2E-1-1107-17505 // ProSieben MAXX
+epgdata:633 = S19.2E-133-15-35 // TNT Film (TCM)
+
+epgdata:631 = S19.2E-133-13-111 // Disney Cinemagic HD
+// = S19.2E-133-12-115 // MGM HD
+// = S19.2E-133-10-106 // Sky Action HD
+epgdata:767 = S19.2E-133-13-110 // Sky Atlantic HD
+epgdata:629 = S19.2E-133-6-131 // Sky Cinema HD
+// = S19.2E-133-12-107 // Sky Hits HD
+
+epgdata:610 = S19.2E-133-2-10 // Sky Cinema
+epgdata:611 = S19.2E-133-2-11 // Sky Cinema +1
+epgdata:612 = S19.2E-133-2-43 // Sky Cinema +24
+epgdata:630 = S19.2E-133-3-25 // Disney Cinemagic
+epgdata:1196 = S19.2E-133-3-515 // MGM
+epgdata:613 = S19.2E-133-2-9 // Sky Action
+epgdata:617 = S19.2E-133-2-8 // Sky Comedy
+epgdata:616 = S19.2E-133-2-20 // Sky Emotion
+epgdata:618 = S19.2E-133-3-41 // Sky Hits
+epgdata:614 = S19.2E-133-3-516 // Sky Nostalgie
+// = S19.2E-133-3-17 // Sky Sport News
+
+epgdata:784 = S19.2E-133-14-119 // Sport1 US HD
+epgdata:621 = S19.2E-133-6-129 // Sky Sport HD 1
+epgdata:697 = S19.2E-133-13-114 // Sky Sport HD 2
+// = S19.2E-133-6-268 // Sky Sport HD 3
+// = S19.2E-133-11-122 // Sport1+ HD
+epgdata:619 = S19.2E-133-4-221 // Sky Sport 1
+epgdata:620 = S19.2E-133-4-222 // Sky Sport 2
+epgdata:564 = S19.2E-133-15-59 // sportdigital
+
+// = S19.2E-133-11-132 // Eurosport HD
+// = S19.2E-133-14-109 // Eurosport 2 HD
+
+epgdata:54 = S19.2E-1-1117-13001 // ORF1
+epgdata:55 = S19.2E-1-1117-13002 // ORF2
+epgdata:757 = S19.2E-1-1115-13101 // ORF III
+epgdata:759 = S19.2E-1-1003-13221 // ORF SPORT+
+
+epgdata:115 = S19.2E-1-1117-13012 // ATV
+epgdata:761 = S19.2E-1-1003-13223 // ATV2
+// = S19.2E-1-1082-20007 // PULS 4 Austria
+epgdata:622 = S19.2E-133-1-30 // Sky Sport Austria
+// = S19.2E-1-1115-13104 // LT1-OOE
+// = S19.2E-1-1115-13111 // ServusTV Oesterreich
+
+// epgdata:10100 // Sat.1 Emotions HD
+epgdata:104 = S19.2E-1-1093-28487 // BR alpha
+
+// epgdata:1183 = // Animal Planet
+// epgdata:211 = // Rhein-Neckar-Fernsehen
+// epgdata:266 = // VIVA
+epgdata:277 = S19.2E-133-33-51 // Tele 5
+// epgdata:455 = // Fashion TV
+// epgdata:465 = // MTV Dance
+// epgdata:466 = // MTV Hits UK
+// epgdata:468 = // AXN
+// epgdata:469 = // Extreme Sports Channel
+// epgdata:46 = // WDR
+// epgdata:473 = // ESPN Classic
+// epgdata:47 = // NDR
+epgdata:486 = S19.2E-133-5-1793 // Das VIERTE
+// epgdata:48 = // MDR
+// epgdata:49 = // HR
+// epgdata:504 = // Eurosport 2
+// epgdata:50 = // SWR
+// epgdata:51 = // BR
+// epgdata:52 = // RBB
+// epgdata:537 = // Anixe HD
+// epgdata:590 = // TNT Serie
+
+// epgdata:623 = // Sky Bundesliga
+// epgdata:624 = // National Geographic Channel HD
+// epgdata:628 = // Sky Select
+// epgdata:698 = // SPORT1+
+// epgdata:743 = // Sky Sport HD Extra
+// epgdata:756 = // Spiegel TV Wissen
+// epgdata:758 = // E! Entertainment
+
+
+
diff --git a/PLUGINS/epgdata/configs/epgd.conf b/PLUGINS/epgdata/configs/epgd.conf
new file mode 100644
index 0000000..e5c2073
--- /dev/null
+++ b/PLUGINS/epgdata/configs/epgd.conf
@@ -0,0 +1,10 @@
+
+# ---------------
+# epgdata plugin
+# ---------------
+
+epgdata.url = http://www.epgdata.com
+epgdata.pin = insert-your-pin-here
+
+# Download timeout in seconds (default 180)
+#epgdata.timeout = 180
diff --git a/PLUGINS/epgdata/configs/epgdata-category.xml b/PLUGINS/epgdata/configs/epgdata-category.xml
new file mode 100644
index 0000000..c047314
--- /dev/null
+++ b/PLUGINS/epgdata/configs/epgdata-category.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!DOCTYPE category [
+<!ELEMENT category (data)+>
+<!ELEMENT data (ca0,ca1,ca2)>
+<!ENTITY nbsp "&#160;" >
+<!ENTITY iexcl "&#161;" >
+<!ENTITY cent "&#162;" >
+<!ENTITY pound "&#163;" >
+<!ENTITY curren "&#164;" >
+<!ENTITY yen "&#165;" >
+<!ENTITY brvbar "&#166;" >
+<!ENTITY sect "&#167;" >
+<!ENTITY uml "&#168;" >
+<!ENTITY copy "&#169;" >
+<!ENTITY ordf "&#170;" >
+<!ENTITY laquo "&#171;" >
+<!ENTITY not "&#172;" >
+<!ENTITY shy "&#173;" >
+<!ENTITY reg "&#174;" >
+<!ENTITY macr "&#175;" >
+<!ENTITY deg "&#176;" >
+<!ENTITY plusmn "&#177;" >
+<!ENTITY sup2 "&#178;" >
+<!ENTITY sup3 "&#179;" >
+<!ENTITY acute "&#180;" >
+<!ENTITY micro "&#181;" >
+<!ENTITY para "&#182;" >
+<!ENTITY middot "&#183;" >
+<!ENTITY cedil "&#184;" >
+<!ENTITY sup1 "&#185;" >
+<!ENTITY ordm "&#186;" >
+<!ENTITY raquo "&#187;" >
+<!ENTITY frac14 "&#188;" >
+<!ENTITY frac12 "&#189;" >
+<!ENTITY frac34 "&#190;" >
+<!ENTITY iquest "&#191;" >
+<!ENTITY Agrave "&#192;" >
+<!ENTITY Aacute "&#193;" >
+<!ENTITY Acirc "&#194;" >
+<!ENTITY Atilde "&#195;" >
+<!ENTITY Auml "&#196;" >
+<!ENTITY Aring "&#197;" >
+<!ENTITY AElig "&#198;" >
+<!ENTITY Ccedil "&#199;" >
+<!ENTITY Egrave "&#200;" >
+<!ENTITY Eacute "&#201;" >
+<!ENTITY Ecirc "&#202;" >
+<!ENTITY Euml "&#203;" >
+<!ENTITY Igrave "&#204;" >
+<!ENTITY Iacute "&#205;" >
+<!ENTITY Icirc "&#206;" >
+<!ENTITY Iuml "&#207;" >
+<!ENTITY ETH "&#208;" >
+<!ENTITY Ntilde "&#209;" >
+<!ENTITY Ograve "&#210;" >
+<!ENTITY Oacute "&#211;" >
+<!ENTITY Ocirc "&#212;" >
+<!ENTITY Otilde "&#213;" >
+<!ENTITY Ouml "&#214;" >
+<!ENTITY times "&#215;" >
+<!ENTITY Oslash "&#216;" >
+<!ENTITY Ugrave "&#217;" >
+<!ENTITY Uacute "&#218;" >
+<!ENTITY Ucirc "&#219;" >
+<!ENTITY Uuml "&#220;" >
+<!ENTITY Yacute "&#221;" >
+<!ENTITY THORN "&#222;" >
+<!ENTITY szlig "&#223;" >
+<!ENTITY agrave "&#224;" >
+<!ENTITY aacute "&#225;" >
+<!ENTITY acirc "&#226;" >
+<!ENTITY atilde "&#227;" >
+<!ENTITY auml "&#228;" >
+<!ENTITY aring "&#229;" >
+<!ENTITY aelig "&#230;" >
+<!ENTITY ccedil "&#231;" >
+<!ENTITY egrave "&#232;" >
+<!ENTITY eacute "&#233;" >
+<!ENTITY ecirc "&#234;" >
+<!ENTITY euml "&#235;" >
+<!ENTITY igrave "&#236;" >
+<!ENTITY iacute "&#237;" >
+<!ENTITY icirc "&#238;" >
+<!ENTITY iuml "&#239;" >
+<!ENTITY eth "&#240;" >
+<!ENTITY ntilde "&#241;" >
+<!ENTITY ograve "&#242;" >
+<!ENTITY oacute "&#243;" >
+<!ENTITY ocirc "&#244;" >
+<!ENTITY otilde "&#245;" >
+<!ENTITY ouml "&#246;" >
+<!ENTITY divide "&#247;" >
+<!ENTITY oslash "&#248;" >
+<!ENTITY ugrave "&#249;" >
+<!ENTITY uacute "&#250;" >
+<!ENTITY ucirc "&#251;" >
+<!ENTITY uuml "&#252;" >
+<!ENTITY yacute "&#253;" >
+<!ENTITY thorn "&#254;" >
+<!ENTITY yuml "&#255;" >
+<!ENTITY quot "&#34;" >
+<!ELEMENT ca0 (#PCDATA)> <!-- category_de -->
+<!ELEMENT ca1 (#PCDATA)> <!-- category_long_de -->
+<!ELEMENT ca2 (#PCDATA)> <!-- category_short_de -->
+]>
+
+<category>
+ <data>
+ <ca0>100</ca0>
+ <ca1>Spielfilm</ca1>
+ <ca2>Spielfilm</ca2>
+ </data>
+ <data>
+ <ca0>200</ca0>
+ <ca1>Serie</ca1>
+ <ca2>Serie</ca2>
+ </data>
+ <data>
+ <ca0>300</ca0>
+ <ca1>Sport</ca1>
+ <ca2>Sport</ca2>
+ </data>
+ <data>
+ <ca0>400</ca0>
+ <ca1>Show</ca1>
+ <ca2>Show</ca2>
+ </data>
+ <data>
+ <ca0>500</ca0>
+ <ca1>Information</ca1>
+ <ca2>Information</ca2>
+ </data>
+ <data>
+ <ca0>600</ca0>
+ <ca1>Musik</ca1>
+ <ca2>Musik</ca2>
+ </data>
+ <data>
+ <ca0>700</ca0>
+ <ca1>Kinder</ca1>
+ <ca2>Kinder</ca2>
+ </data>
+</category> \ No newline at end of file
diff --git a/PLUGINS/epgdata/configs/epgdata-genre.xml b/PLUGINS/epgdata/configs/epgdata-genre.xml
new file mode 100644
index 0000000..ff63eaf
--- /dev/null
+++ b/PLUGINS/epgdata/configs/epgdata-genre.xml
@@ -0,0 +1,507 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!DOCTYPE genre [
+<!ELEMENT genre (data)+>
+<!ELEMENT data (g0,g1)>
+<!ENTITY nbsp "&#160;" >
+<!ENTITY iexcl "&#161;" >
+<!ENTITY cent "&#162;" >
+<!ENTITY pound "&#163;" >
+<!ENTITY curren "&#164;" >
+<!ENTITY yen "&#165;" >
+<!ENTITY brvbar "&#166;" >
+<!ENTITY sect "&#167;" >
+<!ENTITY uml "&#168;" >
+<!ENTITY copy "&#169;" >
+<!ENTITY ordf "&#170;" >
+<!ENTITY laquo "&#171;" >
+<!ENTITY not "&#172;" >
+<!ENTITY shy "&#173;" >
+<!ENTITY reg "&#174;" >
+<!ENTITY macr "&#175;" >
+<!ENTITY deg "&#176;" >
+<!ENTITY plusmn "&#177;" >
+<!ENTITY sup2 "&#178;" >
+<!ENTITY sup3 "&#179;" >
+<!ENTITY acute "&#180;" >
+<!ENTITY micro "&#181;" >
+<!ENTITY para "&#182;" >
+<!ENTITY middot "&#183;" >
+<!ENTITY cedil "&#184;" >
+<!ENTITY sup1 "&#185;" >
+<!ENTITY ordm "&#186;" >
+<!ENTITY raquo "&#187;" >
+<!ENTITY frac14 "&#188;" >
+<!ENTITY frac12 "&#189;" >
+<!ENTITY frac34 "&#190;" >
+<!ENTITY iquest "&#191;" >
+<!ENTITY Agrave "&#192;" >
+<!ENTITY Aacute "&#193;" >
+<!ENTITY Acirc "&#194;" >
+<!ENTITY Atilde "&#195;" >
+<!ENTITY Auml "&#196;" >
+<!ENTITY Aring "&#197;" >
+<!ENTITY AElig "&#198;" >
+<!ENTITY Ccedil "&#199;" >
+<!ENTITY Egrave "&#200;" >
+<!ENTITY Eacute "&#201;" >
+<!ENTITY Ecirc "&#202;" >
+<!ENTITY Euml "&#203;" >
+<!ENTITY Igrave "&#204;" >
+<!ENTITY Iacute "&#205;" >
+<!ENTITY Icirc "&#206;" >
+<!ENTITY Iuml "&#207;" >
+<!ENTITY ETH "&#208;" >
+<!ENTITY Ntilde "&#209;" >
+<!ENTITY Ograve "&#210;" >
+<!ENTITY Oacute "&#211;" >
+<!ENTITY Ocirc "&#212;" >
+<!ENTITY Otilde "&#213;" >
+<!ENTITY Ouml "&#214;" >
+<!ENTITY times "&#215;" >
+<!ENTITY Oslash "&#216;" >
+<!ENTITY Ugrave "&#217;" >
+<!ENTITY Uacute "&#218;" >
+<!ENTITY Ucirc "&#219;" >
+<!ENTITY Uuml "&#220;" >
+<!ENTITY Yacute "&#221;" >
+<!ENTITY THORN "&#222;" >
+<!ENTITY szlig "&#223;" >
+<!ENTITY agrave "&#224;" >
+<!ENTITY aacute "&#225;" >
+<!ENTITY acirc "&#226;" >
+<!ENTITY atilde "&#227;" >
+<!ENTITY auml "&#228;" >
+<!ENTITY aring "&#229;" >
+<!ENTITY aelig "&#230;" >
+<!ENTITY ccedil "&#231;" >
+<!ENTITY egrave "&#232;" >
+<!ENTITY eacute "&#233;" >
+<!ENTITY ecirc "&#234;" >
+<!ENTITY euml "&#235;" >
+<!ENTITY igrave "&#236;" >
+<!ENTITY iacute "&#237;" >
+<!ENTITY icirc "&#238;" >
+<!ENTITY iuml "&#239;" >
+<!ENTITY eth "&#240;" >
+<!ENTITY ntilde "&#241;" >
+<!ENTITY ograve "&#242;" >
+<!ENTITY oacute "&#243;" >
+<!ENTITY ocirc "&#244;" >
+<!ENTITY otilde "&#245;" >
+<!ENTITY ouml "&#246;" >
+<!ENTITY divide "&#247;" >
+<!ENTITY oslash "&#248;" >
+<!ENTITY ugrave "&#249;" >
+<!ENTITY uacute "&#250;" >
+<!ENTITY ucirc "&#251;" >
+<!ENTITY uuml "&#252;" >
+<!ENTITY yacute "&#253;" >
+<!ENTITY thorn "&#254;" >
+<!ENTITY yuml "&#255;" >
+<!ENTITY quot "&#34;" >
+<!ELEMENT g0 (#PCDATA)> <!-- genreid -->
+<!ELEMENT g1 (#PCDATA)> <!-- genre -->
+]>
+
+<genre>
+ <data>
+ <g0>101</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>102</g0>
+ <g1>Abenteuer</g1>
+ </data>
+ <data>
+ <g0>103</g0>
+ <g1>Action</g1>
+ </data>
+ <data>
+ <g0>104</g0>
+ <g1>Dokumentarfilm</g1>
+ </data>
+ <data>
+ <g0>105</g0>
+ <g1>Drama</g1>
+ </data>
+ <data>
+ <g0>106</g0>
+ <g1>Erotik</g1>
+ </data>
+ <data>
+ <g0>108</g0>
+ <g1>Fantasy</g1>
+ </data>
+ <data>
+ <g0>109</g0>
+ <g1>Heimat</g1>
+ </data>
+ <data>
+ <g0>110</g0>
+ <g1>Humor</g1>
+ </data>
+ <data>
+ <g0>112</g0>
+ <g1>Krimi</g1>
+ </data>
+ <data>
+ <g0>113</g0>
+ <g1>Kultur</g1>
+ </data>
+ <data>
+ <g0>114</g0>
+ <g1>Kurzfilm</g1>
+ </data>
+ <data>
+ <g0>115</g0>
+ <g1>Musik</g1>
+ </data>
+ <data>
+ <g0>116</g0>
+ <g1>Mystery + Horror</g1>
+ </data>
+ <data>
+ <g0>117</g0>
+ <g1>Romantik/Liebe</g1>
+ </data>
+ <data>
+ <g0>119</g0>
+ <g1>Science Fiction</g1>
+ </data>
+ <data>
+ <g0>121</g0>
+ <g1>Thriller</g1>
+ </data>
+ <data>
+ <g0>122</g0>
+ <g1>Western</g1>
+ </data>
+ <data>
+ <g0>123</g0>
+ <g1>Zeichentrick</g1>
+ </data>
+ <data>
+ <g0>201</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>202</g0>
+ <g1>Abenteuer</g1>
+ </data>
+ <data>
+ <g0>203</g0>
+ <g1>Action</g1>
+ </data>
+ <data>
+ <g0>205</g0>
+ <g1>Drama</g1>
+ </data>
+ <data>
+ <g0>206</g0>
+ <g1>Erotik</g1>
+ </data>
+ <data>
+ <g0>207</g0>
+ <g1>Familie</g1>
+ </data>
+ <data>
+ <g0>208</g0>
+ <g1>Fantasy</g1>
+ </data>
+ <data>
+ <g0>210</g0>
+ <g1>Humor</g1>
+ </data>
+ <data>
+ <g0>211</g0>
+ <g1>Krankenhaus</g1>
+ </data>
+ <data>
+ <g0>212</g0>
+ <g1>Krimi</g1>
+ </data>
+ <data>
+ <g0>214</g0>
+ <g1>Jugend</g1>
+ </data>
+ <data>
+ <g0>216</g0>
+ <g1>Mystery + Horror</g1>
+ </data>
+ <data>
+ <g0>218</g0>
+ <g1>Reality</g1>
+ </data>
+ <data>
+ <g0>219</g0>
+ <g1>Science Fiction</g1>
+ </data>
+ <data>
+ <g0>220</g0>
+ <g1>Soap</g1>
+ </data>
+ <data>
+ <g0>221</g0>
+ <g1>Thriller</g1>
+ </data>
+ <data>
+ <g0>222</g0>
+ <g1>Western</g1>
+ </data>
+ <data>
+ <g0>223</g0>
+ <g1>Zeichentrick</g1>
+ </data>
+ <data>
+ <g0>301</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>331</g0>
+ <g1>Boxen</g1>
+ </data>
+ <data>
+ <g0>332</g0>
+ <g1>Eishockey</g1>
+ </data>
+ <data>
+ <g0>334</g0>
+ <g1>Fußball</g1>
+ </data>
+ <data>
+ <g0>335</g0>
+ <g1>Olympia</g1>
+ </data>
+ <data>
+ <g0>336</g0>
+ <g1>Golf</g1>
+ </data>
+ <data>
+ <g0>337</g0>
+ <g1>Gymnastik</g1>
+ </data>
+ <data>
+ <g0>338</g0>
+ <g1>Handball</g1>
+ </data>
+ <data>
+ <g0>339</g0>
+ <g1>Motorsport</g1>
+ </data>
+ <data>
+ <g0>340</g0>
+ <g1>Radsport</g1>
+ </data>
+ <data>
+ <g0>341</g0>
+ <g1>Tennis</g1>
+ </data>
+ <data>
+ <g0>342</g0>
+ <g1>Wassersport</g1>
+ </data>
+ <data>
+ <g0>343</g0>
+ <g1>Wintersport</g1>
+ </data>
+ <data>
+ <g0>344</g0>
+ <g1>US-Sport</g1>
+ </data>
+ <data>
+ <g0>345</g0>
+ <g1>Leichtathletik</g1>
+ </data>
+ <data>
+ <g0>346</g0>
+ <g1>Volleyball</g1>
+ </data>
+ <data>
+ <g0>347</g0>
+ <g1>Extremsport</g1>
+ </data>
+ <data>
+ <g0>348</g0>
+ <g1>Reportagen</g1>
+ </data>
+ <data>
+ <g0>401</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>406</g0>
+ <g1>Erotik</g1>
+ </data>
+ <data>
+ <g0>418</g0>
+ <g1>Reality</g1>
+ </data>
+ <data>
+ <g0>450</g0>
+ <g1>Comedy</g1>
+ </data>
+ <data>
+ <g0>451</g0>
+ <g1>Familien-Show</g1>
+ </data>
+ <data>
+ <g0>452</g0>
+ <g1>Spielshows</g1>
+ </data>
+ <data>
+ <g0>453</g0>
+ <g1>Talkshows</g1>
+ </data>
+ <data>
+ <g0>454</g0>
+ <g1>Gerichtsshow</g1>
+ </data>
+ <data>
+ <g0>455</g0>
+ <g1>Homeshopping</g1>
+ </data>
+ <data>
+ <g0>456</g0>
+ <g1>Kochshow</g1>
+ </data>
+ <data>
+ <g0>457</g0>
+ <g1>Heimwerken</g1>
+ </data>
+ <data>
+ <g0>501</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>560</g0>
+ <g1>Geschichte</g1>
+ </data>
+ <data>
+ <g0>561</g0>
+ <g1>Magazin</g1>
+ </data>
+ <data>
+ <g0>564</g0>
+ <g1>Gesundheit</g1>
+ </data>
+ <data>
+ <g0>565</g0>
+ <g1>Motor + Verkehr</g1>
+ </data>
+ <data>
+ <g0>566</g0>
+ <g1>Nachrichten</g1>
+ </data>
+ <data>
+ <g0>567</g0>
+ <g1>Natur</g1>
+ </data>
+ <data>
+ <g0>568</g0>
+ <g1>Politik</g1>
+ </data>
+ <data>
+ <g0>569</g0>
+ <g1>Ratgeber</g1>
+ </data>
+ <data>
+ <g0>570</g0>
+ <g1>Reise</g1>
+ </data>
+ <data>
+ <g0>571</g0>
+ <g1>Wirtschaft</g1>
+ </data>
+ <data>
+ <g0>572</g0>
+ <g1>Wissen</g1>
+ </data>
+ <data>
+ <g0>573</g0>
+ <g1>Dokumentation</g1>
+ </data>
+ <data>
+ <g0>601</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>680</g0>
+ <g1>Jazz</g1>
+ </data>
+ <data>
+ <g0>681</g0>
+ <g1>Klassik</g1>
+ </data>
+ <data>
+ <g0>682</g0>
+ <g1>Musical</g1>
+ </data>
+ <data>
+ <g0>683</g0>
+ <g1>Rock</g1>
+ </data>
+ <data>
+ <g0>684</g0>
+ <g1>Volksmusik</g1>
+ </data>
+ <data>
+ <g0>685</g0>
+ <g1>Alternative</g1>
+ </data>
+ <data>
+ <g0>686</g0>
+ <g1>Pop</g1>
+ </data>
+ <data>
+ <g0>687</g0>
+ <g1>Clips</g1>
+ </data>
+ <data>
+ <g0>688</g0>
+ <g1>Show</g1>
+ </data>
+ <data>
+ <g0>689</g0>
+ <g1>Interview</g1>
+ </data>
+ <data>
+ <g0>690</g0>
+ <g1>Theater</g1>
+ </data>
+ <data>
+ <g0>691</g0>
+ <g1>Kino</g1>
+ </data>
+ <data>
+ <g0>692</g0>
+ <g1>Kultur</g1>
+ </data>
+ <data>
+ <g0>701</g0>
+ <g1>Verschiedenes</g1>
+ </data>
+ <data>
+ <g0>790</g0>
+ <g1>Filme</g1>
+ </data>
+ <data>
+ <g0>791</g0>
+ <g1>Nachrichten</g1>
+ </data>
+ <data>
+ <g0>792</g0>
+ <g1>Serien</g1>
+ </data>
+ <data>
+ <g0>793</g0>
+ <g1>Shows</g1>
+ </data>
+ <data>
+ <g0>795</g0>
+ <g1>Zeichentrick</g1>
+ </data>
+ <data>
+ <g0>796</g0>
+ <g1>Anime</g1>
+ </data>
+</genre> \ No newline at end of file
diff --git a/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl b/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl
new file mode 100644
index 0000000..24024ac
--- /dev/null
+++ b/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/TR/xhtml1/strict">
+<xsl:output method="xml" omit-xml-declaration="no" encoding='iso-8859-15'/>
+
+<xsl:include href="epgdata.xsl" />
+
+</xsl:stylesheet>
diff --git a/PLUGINS/epgdata/configs/epgdata-utf-8.xsl b/PLUGINS/epgdata/configs/epgdata-utf-8.xsl
new file mode 100644
index 0000000..96a7b92
--- /dev/null
+++ b/PLUGINS/epgdata/configs/epgdata-utf-8.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/TR/xhtml1/strict">
+<xsl:output method="xml" omit-xml-declaration="no" encoding='utf-8'/>
+
+<xsl:include href="epgdata.xsl" />
+
+</xsl:stylesheet>
diff --git a/PLUGINS/epgdata/configs/epgdata.xsl b/PLUGINS/epgdata/configs/epgdata.xsl
new file mode 100644
index 0000000..d5795ee
--- /dev/null
+++ b/PLUGINS/epgdata/configs/epgdata.xsl
@@ -0,0 +1,208 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/TR/xhtml1/strict"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:date="http://exslt.org/dates-and-times"
+ xmlns:str="http://exslt.org/strings">
+
+
+<xsl:template match="/">
+
+ <events>
+
+ <xsl:for-each select="//data">
+
+ <event>
+ <xsl:attribute name="id"><xsl:value-of select="d0"/></xsl:attribute>
+ <xsl:attribute name="provid"><xsl:value-of select="d2"/></xsl:attribute>
+
+ <starttime>
+ <xsl:call-template name="date2UTC">
+ <xsl:with-param name="date" select="str:replace(d4,' ','T')"/>
+ </xsl:call-template>
+ </starttime>
+
+ <duration><xsl:value-of select="d7*60"/></duration>
+
+ <xsl:if test="string-length(d8)">
+ <vps>
+ <xsl:call-template name="date2UTC">
+ <xsl:with-param name="date" select="concat(substring-before(d4,' '),'T',d8,':00')"/>
+ </xsl:call-template>
+ </vps>
+ </xsl:if>
+
+ <title><xsl:value-of select="d19"/></title>
+ <xsl:if test="string-length(d20)"><shorttext><xsl:value-of select="d20"/></shorttext></xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="d19='Tatort'">
+ <category><xsl:text>Serie</xsl:text></category>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="d10 &gt; 0"><category><xsl:call-template name="getCATEGORY"><xsl:with-param name="categoryid" select="d10"/></xsl:call-template></category></xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="string-length(d25)"><genre><xsl:call-template name="getGenre"><xsl:with-param name="genreid" select="d25"/></xsl:call-template></genre></xsl:if>
+
+ <xsl:if test="string-length(d16)"><parentalrating><xsl:value-of select="d16"/></parentalrating></xsl:if>
+
+ <xsl:if test="string-length(d21)"><longdescription><xsl:value-of select="d21"/></longdescription></xsl:if>
+
+ <xsl:if test="string-length(d1)"><movieid><xsl:value-of select="d1"/></movieid></xsl:if>
+
+ <xsl:variable name="TIPP">
+ <xsl:if test="d18 = 1"><xsl:text>TagesTipp</xsl:text></xsl:if>
+ <xsl:if test="d18 = 2"><xsl:text>TopTipp</xsl:text></xsl:if>
+ </xsl:variable>
+ <xsl:if test="d18 &gt; 0"><tipp><xsl:value-of select="$TIPP"/></tipp></xsl:if>
+
+ <xsl:if test="string-length(d30) and d30 &gt; 0">
+ <xsl:choose>
+ <xsl:when test="d30 &gt; 1"><numrating><xsl:value-of select="d30 -1"/></numrating></xsl:when>
+ <xsl:otherwise><numrating><xsl:value-of select="d30"/></numrating></xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="d30 = 5">
+ <txtrating>Sehr empfehlenswert</txtrating>
+ </xsl:when>
+ <xsl:when test="d30 = 4">
+ <txtrating>Empfehlenswert</txtrating>
+ </xsl:when>
+ <xsl:when test="d30 = 3">
+ <txtrating>Eher durchschnittlich</txtrating>
+ </xsl:when>
+ <xsl:when test="d30 = 2 or d30 = 1">
+ <txtrating>Eher uninteressant</txtrating>
+ </xsl:when>
+ </xsl:choose>
+
+<!--
+ <xsl:if test="d30 &gt; 0"><rating><xsl:call-template name="getRATING"><xsl:with-param name="ratingid" select="d30"/></xsl:call-template></rating></xsl:if>
+-->
+ <xsl:if test="string-length(d32)"><country><xsl:value-of select="str:replace(d32,'|','/')"/></country></xsl:if>
+ <xsl:if test="string-length(d33)"><year><xsl:value-of select="d33"/></year></xsl:if>
+ <xsl:if test="string-length(d34)"><moderator><xsl:value-of select="str:replace(d34,'|',', ')"/></moderator></xsl:if>
+ <xsl:if test="string-length(d35)"><guest><xsl:value-of select="str:replace(d35,' -',',')"/></guest></xsl:if>
+ <xsl:if test="string-length(d36)"><director><xsl:value-of select="str:replace(d36,'|',', ')"/></director></xsl:if>
+ <xsl:if test="string-length(d37)"><actor><xsl:value-of select="str:replace(str:replace(d37,') -','), '),' ',' ')"/></actor></xsl:if>
+
+ <xsl:variable name="AUDIO">
+ <xsl:if test="d28=1"><xsl:text> DolbyDigital</xsl:text></xsl:if>
+ <xsl:if test="d27=1"><xsl:text> Stereo</xsl:text></xsl:if>
+ <xsl:if test="d12=1"><xsl:text> Zweikanal</xsl:text></xsl:if>
+ </xsl:variable>
+
+ <xsl:if test="string-length($AUDIO)">
+ <audio><xsl:value-of select="normalize-space($AUDIO)"/></audio>
+ </xsl:if>
+
+ <xsl:variable name="FLAGS">
+ <xsl:if test="d9=1"><xsl:text> [PrimeTime]</xsl:text></xsl:if>
+ <xsl:if test="d11=1"><xsl:text> [SchwarzWeiss]</xsl:text></xsl:if>
+ <xsl:if test="d13=1"><xsl:text> [Untertitel]</xsl:text></xsl:if>
+ <xsl:if test="d14=1"><xsl:text> [PayTV]</xsl:text></xsl:if>
+ <xsl:if test="d15=1"><xsl:text> [Hörfilm]</xsl:text></xsl:if>
+ <xsl:if test="d29=1"><xsl:text> [16:9]</xsl:text></xsl:if>
+ </xsl:variable>
+
+ <xsl:if test="string-length($FLAGS)">
+ <flags><xsl:value-of select="normalize-space($FLAGS)"/></flags>
+ </xsl:if>
+
+ <xsl:if test="d26 &gt; 0"><extepnum><xsl:value-of select="d26"/></extepnum></xsl:if>
+
+ <xsl:if test="string-length(d40)">
+ <images><xsl:value-of select="substring-before(d40,'.jpg')"/></images>
+ <imagetype><xsl:text>jpg</xsl:text></imagetype>
+ </xsl:if>
+
+<!--
+-->
+
+ </event>
+ </xsl:for-each>
+ </events>
+</xsl:template>
+
+
+
+<xsl:template name="getRATING">
+ <xsl:param name="ratingid"/>
+
+ <xsl:variable name="RATING">
+ <xsl:choose>
+ <xsl:when test="$ratingid=1"><xsl:text> / Allgemein *</xsl:text></xsl:when>
+ <xsl:when test="$ratingid=2"><xsl:text> / Allgemein **</xsl:text></xsl:when>
+ <xsl:when test="$ratingid=3"><xsl:text> / Allgemein ***</xsl:text></xsl:when>
+ <xsl:when test="$ratingid=4"><xsl:text> / Allgemein ****</xsl:text></xsl:when>
+ <xsl:when test="$ratingid=5"><xsl:text> / Allgemein *****</xsl:text></xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="$RATING"/>
+</xsl:template>
+
+
+<xsl:template name="getCATEGORY">
+ <xsl:param name="categoryid"/>
+
+ <xsl:variable name="CATEGORY">
+
+ <xsl:for-each select="document('epgdata-category.xml')//data">
+ <xsl:choose>
+ <xsl:when test="$categoryid=ca0"><xsl:value-of select="ca1"/></xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:value-of disable-output-escaping="yes" select="$CATEGORY"/>
+</xsl:template>
+
+
+<xsl:template name="getGenre">
+ <xsl:param name="genreid"/>
+
+ <xsl:variable name="GENRE">
+
+ <xsl:for-each select="document('epgdata-genre.xml')//data">
+ <xsl:choose>
+ <xsl:when test="$genreid=g0"><xsl:value-of select="g1"/></xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:value-of select="$GENRE"/>
+</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">+02:00</xsl:when>
+ <xsl:otherwise>+01:00</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>+01:00</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="date:seconds(concat($date,$tz))"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/PLUGINS/epgdata/epgdata.c b/PLUGINS/epgdata/epgdata.c
new file mode 100644
index 0000000..3cf31ef
--- /dev/null
+++ b/PLUGINS/epgdata/epgdata.c
@@ -0,0 +1,760 @@
+/*
+ * epgdata.c
+ *
+ * See the README file for copyright information
+ *
+ */
+
+#include <dirent.h>
+#include <unistd.h>
+
+#include "epgdata.h"
+
+//***************************************************************************
+// Epgdata
+//***************************************************************************
+
+Epgdata::Epgdata()
+ : Plugin()
+{
+ pxsltStylesheet = 0;
+ stmtByFileRef = 0;
+ stmtCleanDouble = 0;
+ stmtMarkOldEvents = 0;
+ selectByDate = 0;
+ selectId = 0;
+
+ pin = 0;
+ timeout = 3 * tmeSecondsPerMinute;
+ baseurl = strdup("http://www.epgdata.com");
+}
+
+Epgdata::~Epgdata()
+{
+ if (pxsltStylesheet)
+ xsltFreeStylesheet(pxsltStylesheet);
+
+ delete stmtByFileRef;
+ delete selectByDate;
+ delete stmtCleanDouble;
+ delete stmtMarkOldEvents;
+
+ free(baseurl);
+ free(pin);
+}
+
+int Epgdata::init(cEpgd* aObject, int aUtf8)
+{
+ Plugin::init(aObject, aUtf8);
+
+ pxsltStylesheet = loadXSLT(getSource(), confDir, utf8);
+
+ return done;
+}
+
+int Epgdata::initDb()
+{
+ int status = success;
+
+ // --------
+ // by fileref (for pictures)
+ // select name from fileref
+ // where source = ? and fileref = ?
+
+ stmtByFileRef = new cDbStatement(obj->fileDb);
+
+ stmtByFileRef->build("select ");
+ stmtByFileRef->bind("NAME", cDBS::bndOut);
+ stmtByFileRef->build(" from %s where ", obj->fileDb->TableName());
+ stmtByFileRef->bind("SOURCE", cDBS::bndIn | cDBS::bndSet);
+ stmtByFileRef->bind("FILEREF", cDBS::bndIn | cDBS::bndSet, " and ");
+
+ status += stmtByFileRef->prepare();
+
+ // ---------------
+ // (for cleanup double)
+ // select name from fileref
+ // where source = ? order by name desc
+
+ stmtCleanDouble = new cDbStatement(obj->fileDb);
+
+ stmtCleanDouble->build("select ");
+ stmtCleanDouble->bind("NAME", cDBS::bndOut);
+ stmtCleanDouble->build(" from %s where ", obj->fileDb->TableName());
+ stmtCleanDouble->bind("SOURCE", cDBS::bndIn | cDBS::bndSet);
+ stmtCleanDouble->build(" order by name desc");
+
+ status += stmtCleanDouble->prepare();
+
+ // ---------
+ // select channelid, merge, mergesp from channelmap
+ // where source = ? and extid = ?
+
+ selectId = new cDbStatement(obj->mapDb);
+
+ selectId->build("select ");
+ selectId->bind("CHANNELID", cDBS::bndOut);
+ selectId->bind("MERGESP", cDBS::bndOut, ", ");
+ selectId->bind("MERGE", cDBS::bndOut, ", ");
+ selectId->build(" from %s where ", obj->mapDb->TableName());
+ selectId->bind("SOURCE", cDBS::bndIn | cDBS::bndSet);
+ selectId->bind("EXTERNALID", cDBS::bndIn | cDBS::bndSet, " and ");
+
+ status += selectId->prepare();
+
+ // ---------
+ // select name, tag from filerf
+ // where source = 'epgdata'
+ // and name like ?
+
+ valueName.setField(obj->fileDb->getField("NAME"));
+ valueNameLike.setField(obj->fileDb->getField("NAME"));
+
+ selectByDate = new cDbStatement(obj->fileDb);
+
+ selectByDate->build("select ");
+ selectByDate->bind(&valueName, cDBS::bndOut);
+ selectByDate->bind("FILEREF", cDBS::bndOut, ", ");
+ selectByDate->build(" from %s where source = '%s' and ",
+ obj->fileDb->TableName(), getSource());
+ selectByDate->bindCmp(0, &valueNameLike, "like");
+
+ status += selectByDate->prepare();
+
+// // --------
+// // update events set delflg = ?, updflg = ?, fileref = ?, updsp = ?
+// // where fileref = ?
+// // and source = ?;
+// // and updflg in (....)
+
+// valueFileRef.setField(obj->eventsDb->getField("FileRef"));
+// stmtSetDelByFileref = new cDbStatement(obj->eventsDb);
+
+// stmtSetDelByFileref->build("update %s set ", obj->eventsDb->TableName());
+// stmtSetDelByFileref->bind("DelFlg", cDbService::bndIn |cDbService:: bndSet);
+// stmtSetDelByFileref->bind("UpdFlg", cDbService::bndIn |cDbService:: bndSet, ", ");
+// stmtSetDelByFileref->bind("FileRef", cDbService::bndIn | cDbService::bndSet, ", ");
+// stmtSetDelByFileref->bind("UpdSp", cDbService::bndIn | cDbService::bndSet, ", ");
+// stmtSetDelByFileref->build( " where ");
+// stmtSetDelByFileref->bind(&valueFileRef, cDbService::bndIn |cDbService:: bndSet);
+// stmtSetDelByFileref->bind("Source", cDbService::bndIn | cDbService::bndSet, " and ");
+// stmtSetDelByFileref->build(" and updflg in (%s)", Us::getDeletable());
+
+// status += stmtSetDelByFileref->prepare();
+
+ // ----------
+ // update events
+ // set updflg = case when updflg in (...) then 'D' else updflg end,
+ // delflg = 'Y',
+ // updsp = unix_timestamp()
+ // where source = '...'
+ // and (source, fileref) not in (select source,fileref from fileref)
+
+ stmtMarkOldEvents = new cDbStatement(obj->eventsDb);
+
+ stmtMarkOldEvents->build("update %s set ", obj->eventsDb->TableName());
+ stmtMarkOldEvents->build("updflg = case when updflg in (%s) then 'D' else updflg end, ", cEventState::getDeletable());
+ stmtMarkOldEvents->build("delflg = 'Y', updsp = unix_timestamp()");
+ stmtMarkOldEvents->build(" where source = '%s'", getSource());
+ stmtMarkOldEvents->build(" and (source, fileref) not in (select source,fileref from fileref)");
+
+ status += stmtMarkOldEvents->prepare();
+
+ // ----------
+ // if no epgdata entry in fileref read files from FS to table
+
+ int count = 0;
+ obj->fileDb->countWhere("source = 'epgdata'", count);
+
+ if (!count)
+ {
+ char* path = 0;
+ DIR* dir;
+ dirent* dp;
+
+ asprintf(&path, "%s/%s", EpgdConfig.cachePath, getSource());
+ chkDir(path);
+
+ if (!(dir = opendir(path)))
+ {
+ tell(0, "Error: Opening cache path '%s' failed, %s", path, strerror(errno));
+ free(path);
+ return fail;
+ }
+
+ while ((dp = readdir(dir)))
+ {
+ char* fileRef = 0;
+ char* file = 0;
+ char* tag = 0;
+ struct stat sb;
+
+ if (!strstr(dp->d_name, "_de_qy.zip"))
+ continue;
+
+ asprintf(&file, "%s/%s", path, dp->d_name);
+ stat(file, &sb);
+ free(file);
+
+ asprintf(&tag, "%ld", sb.st_size);
+ asprintf(&fileRef, "%s-%s", dp->d_name, tag);
+
+ // store file and let tag NULL to indicate that processing is needed
+
+ obj->fileDb->clear();
+ obj->fileDb->setValue("NAME", dp->d_name);
+ obj->fileDb->setValue("SOURCE", getSource());
+ obj->fileDb->setValue("EXTERNALID", "0");
+ obj->fileDb->setValue("FILEREF", fileRef);
+ obj->fileDb->store();
+
+ tell(1, "Added '%s' to table fileref", dp->d_name);
+ free(fileRef);
+ free(tag);
+ }
+
+ free(path);
+ closedir(dir);
+ }
+
+ return success;
+}
+
+int Epgdata::exitDb()
+{
+ delete stmtByFileRef; stmtByFileRef = 0;
+ delete stmtCleanDouble; stmtCleanDouble = 0;
+ delete selectByDate; selectByDate = 0;
+ delete selectId; selectId = 0;
+ delete stmtMarkOldEvents; stmtMarkOldEvents = 0;
+
+ return success;
+}
+
+//***************************************************************************
+// At Config Item
+//***************************************************************************
+
+int Epgdata::atConfigItem(const char* Name, const char* Value)
+{
+ if (!strcasecmp(Name, "Url")) { free(baseurl); baseurl = strdup(Value); }
+ else if (!strcasecmp(Name, "Pin")) { free(pin); pin = strdup(Value); }
+ else if (!strcasecmp(Name, "Timeout")) { timeout = atoi(Value); }
+
+ else return fail;
+
+ return success;
+}
+
+//***************************************************************************
+// Ready
+//***************************************************************************
+
+int Epgdata::ready()
+{
+ static int count = na;
+
+ if (isEmpty(pin))
+ return no;
+
+ if (count == na)
+ {
+ char* where;
+
+ asprintf(&where, "source = '%s'", getSource());
+
+ if (obj->mapDb->countWhere(where, count) != success)
+ count = na;
+
+ free(where);
+ }
+
+ return count > 0;
+}
+
+//***************************************************************************
+// Process Day
+//***************************************************************************
+
+int Epgdata::processDay(int day, int fullupdate, Statistic* statistic)
+{
+ char* directory = 0;
+ char* fspath = 0;
+ char* path = 0; // name of the zip file including the path
+ int haveOneForThisDay = no;
+ MemoryStruct data;
+ int fileSize = 0;
+ char* fileRef = 0;
+ char* url = 0;
+ char* logurl = 0;
+ int load = yes;
+ char* like = 0;
+ int bSize = 0;
+ char entryName[200+TB];
+ MemoryStruct uzdata;
+ // char* oldFileRef = 0;
+
+ int status;
+
+ // path to zip files, url, ..
+
+ asprintf(&directory, "%s/%s", EpgdConfig.cachePath, getSource());
+ chkDir(directory);
+ asprintf(&url, "%s/index.php?action=sendPackage&iOEM=VDR&pin=%s&dayOffset=%d&dataType=xml", baseurl, pin, day);
+ asprintf(&logurl, "%s/index.php?action=sendPackage&iOEM=VDR&pin=%s&dayOffset=%d&dataType=xml", baseurl, "insert-your-pin-here", day);
+
+ // first get the http header
+
+ data.clear();
+ data.headerOnly = yes;
+
+ status = obj->downloadFile(url, fileSize, &data);
+
+ if (status != success || isEmpty(data.name))
+ {
+ tell(1, "Download header for day (%d) at '%s' failed, aborting, got name '%s', status was %d",
+ day, logurl, data.name ? data.name : "", status);
+ status = fail;
+ goto Exit;
+ }
+
+ tell(2, "Got info for day (%d), file '%s' with tag '%s'", day, data.name, data.tag);
+
+ asprintf(&fileRef, "%s-%s", data.name, data.tag);
+ asprintf(&path, "%s/%s", directory, data.name);
+
+ // lookup file
+
+ obj->fileDb->clear();
+ obj->fileDb->setValue("NAME", data.name);
+ obj->fileDb->setValue("SOURCE", getSource());
+
+ // 1:1 match ?
+
+ obj->fileDb->find();
+
+ asprintf(&like, "%.8s_%%", data.name);
+ valueNameLike.setValue(like);
+ free(like);
+
+ // check for update
+
+ if (selectByDate->find())
+ {
+ haveOneForThisDay = yes;
+ // oldFileRef = strdup(obj->fileDb->getStrValue("FileRef"));
+ }
+
+ if (haveOneForThisDay && day >= EpgdConfig.upddays)
+ {
+ // don't check for update of existing files more than 'upddays' in the future
+
+ tell(2, "Skipping update check of file '%s' for day %d", data.name, day);
+
+ statistic->nonUpdates++;
+ status = success;
+ load = no;
+ }
+ else if (haveOneForThisDay && obj->fileDb->hasValue("FileRef", fileRef))
+ {
+ tell(2, "Skipping download of day (%d) due to non-update", day);
+ statistic->nonUpdates++;
+ status = success;
+ load = no;
+ }
+
+ if (!load && !obj->fileDb->getRow()->getValue("Tag")->isNull())
+ goto Exit;
+
+ // not exist, update or not processed -> work
+
+ // first check if we have it already on fs
+
+ asprintf(&fspath, "%s/%s", directory, valueName.getStrValue());
+
+ if (!load && fileExists(fspath))
+ {
+ tell(1, "File '%s' exist, loading from filesystem", fspath);
+
+ obj->loadFromFs(&data, valueName.getStrValue(), getSource());
+
+ free(fileRef);
+ free(path);
+ path = strdup(fspath);
+ asprintf(&fileRef, "%s-%s", valueName.getStrValue(), data.tag);
+
+ obj->fileDb->clear();
+ obj->fileDb->setValue("NAME", valueName.getStrValue());
+ obj->fileDb->setValue("SOURCE", getSource());
+ }
+
+ free(fspath);
+
+ if (load)
+ {
+ tell(0, "Download file: '%s' to '%s", logurl, data.name);
+
+ data.clear();
+
+ if (obj->downloadFile(url, fileSize, &data, timeout) != success)
+ {
+ tell(0, "Download of day (%d) from '%s' failed", day, logurl);
+ status = fail;
+ goto Exit;
+ }
+
+ statistic->bytes += data.size;
+ statistic->files++;
+
+ // store zip to FS
+
+ obj->storeToFs(&data, data.name, getSource());
+ }
+
+ if (data.isEmpty())
+ goto Exit;
+
+ // unzip ...
+
+ uzdata.clear();
+
+ if (unzip(path, /*filter*/ ".xml", uzdata.memory, bSize, entryName) == success)
+ {
+ tell(0, "Processing file '%s' for day %d (%d/%d)",
+ fileRef, day, haveOneForThisDay, load);
+
+ uzdata.size = bSize;
+
+ // store ?
+
+ if (EpgdConfig.storeXmlToFs)
+ obj->storeToFs(&uzdata, entryName, getSource());
+
+ // process file ..
+
+ obj->connection->startTransaction();
+
+ if ((status = processFile(uzdata.memory, uzdata.size, fileRef)) != success)
+ statistic->rejected++;
+
+ if (!obj->dbConnected())
+ {
+ status = fail;
+ goto Exit;
+ }
+
+// we can use this code instead of "stmtMarkOldEvents" !!
+// but we have to complete it like tvm plugin!
+// if (haveOneForThisDay && load && strcmp(oldFileRef, fileRef) != 0)
+// {
+// // mark 'old' entrys in events table as deleted
+// // and 'fake' fileref to new to avoid deletion at cleanup
+
+// tell(0, "Removing events of fileref '%s' for day %d", oldFileRef, day);
+
+// obj->eventsDb->clear();
+// obj->eventsDb->setValue("DelFlg", "Y");
+// obj->eventsDb->setValue("UpdFlg", "D");
+// obj->eventsDb->setValue("FileRef", fileRef); // fake to new fileref
+// obj->eventsDb->setValue("UpdSp", time(0));
+// obj->eventsDb->setValue("Source", getSource());
+// valueFileRef.setValue(oldFileRef); // old fileref
+// stmtSetDelByFileref->execute();
+// }
+
+ // Confirm processing of file
+
+ obj->fileDb->setValue("EXTERNALID", "0");
+ obj->fileDb->setValue("TAG", data.tag);
+ obj->fileDb->setValue("FILEREF", fileRef);
+ obj->fileDb->store();
+
+ obj->connection->commit();
+ }
+
+ Exit:
+
+ // free(oldFileRef);
+ obj->fileDb->reset();
+ selectByDate->freeResult();
+
+ uzdata.clear();
+ free(url);
+ free(logurl);
+ free(fileRef);
+ free(directory);
+ free(path);
+
+ return status;
+}
+
+//***************************************************************************
+// Process File
+//***************************************************************************
+
+int Epgdata::processFile(const char* data, int size, const char* fileRef)
+{
+ xmlDocPtr transformedDoc;
+ xmlNodePtr xmlRoot;
+ int count = 0;
+
+ if ((transformedDoc = obj->transformXml(data, size, pxsltStylesheet, fileRef)) == 0)
+ {
+ tell(0, "XSLT transformation for '%s' failed, ignoring", fileRef);
+ return fail;
+ }
+
+ if (!(xmlRoot = xmlDocGetRootElement(transformedDoc)))
+ {
+ tell(0, "Invalid xml document returned from xslt for '%s', ignoring", fileRef);
+ return fail;
+ }
+
+ // DEBUG: xmlSaveFile("/tmp/test.xml", transformedDoc);
+
+ for (xmlNodePtr node = xmlRoot->xmlChildrenNode; node && obj->dbConnected(); node = node->next)
+ {
+ char* prop = 0;
+ tEventId eventid;
+ char* extid = 0;
+
+ // skip all unexpected elements
+
+ if (node->type != XML_ELEMENT_NODE || strcmp((char*)node->name, "event") != 0)
+ continue;
+
+ // get/check eventid
+
+ if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"id")) || !*prop || !(eventid = atoll(prop)))
+ {
+ xmlFree(prop);
+ tell(0, "Missing event id, ignoring!");
+ continue;
+ }
+
+ xmlFree(prop);
+
+ // get/check provider id
+
+ if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"provid")) || !*prop || !atoi(prop))
+ {
+ xmlFree(prop);
+ tell(0, "Missing provider id, ignoring!");
+ continue;
+ }
+
+ extid = strdup(prop);
+ xmlFree(prop);
+
+ obj->mapDb->clear();
+ obj->mapDb->setValue("EXTERNALID", extid);
+ obj->mapDb->setValue("SOURCE", getSource());
+ free(extid);
+
+ for (int f = selectId->find(); f; f = selectId->fetch())
+ {
+ int insert;
+ const char* channelId = obj->mapDb->getStrValue("CHANNELID");
+
+ // create event ..
+
+ obj->eventsDb->clear();
+ obj->eventsDb->setBigintValue("EVENTID", eventid);
+ obj->eventsDb->setValue("CHANNELID", channelId);
+
+ insert = !obj->eventsDb->find();
+
+ obj->eventsDb->setValue("SOURCE", getSource());
+ obj->eventsDb->setValue("FILEREF", fileRef);
+
+ // auto parse and set other fields
+
+ obj->parseEvent(obj->eventsDb->getRow(), node);
+
+ // ...
+
+ time_t mergesp = obj->mapDb->getIntValue("MERGESP");
+ long starttime = obj->eventsDb->getIntValue("STARTTIME");
+ int merge = obj->mapDb->getIntValue("MERGE");
+
+ // store ..
+
+ if (insert)
+ {
+ // handle insert
+
+ obj->eventsDb->setValue("VERSION", 0xFF);
+ obj->eventsDb->setValue("TABLEID", 0L);
+ obj->eventsDb->setValue("USEID", 0L);
+
+ if (starttime <= mergesp)
+ obj->eventsDb->setCharValue("UPDFLG", cEventState::usInactive);
+ else
+ obj->eventsDb->setCharValue("UPDFLG", merge > 1 ? cEventState::usMergeSpare : cEventState::usActive);
+
+ obj->eventsDb->insert();
+ }
+ else
+ {
+ if (obj->eventsDb->hasValue("DELFLG", "Y"))
+ obj->eventsDb->setValue("DELFLG", "N");
+
+ if (obj->eventsDb->hasValue("UPDFLG", "D"))
+ {
+ if (starttime <= mergesp)
+ obj->eventsDb->setCharValue("UPDFLG", cEventState::usInactive);
+ else
+ obj->eventsDb->setCharValue("UPDFLG", merge > 1 ? cEventState::usMergeSpare : cEventState::usActive);
+ }
+
+ obj->eventsDb->update();
+ }
+
+ obj->eventsDb->reset();
+ count++;
+ }
+ }
+
+ selectId->freeResult();
+
+ xmlFreeDoc(transformedDoc);
+
+ tell(2, "XML File '%s' processed, updated %d events", fileRef, count);
+
+ return success;
+}
+
+//***************************************************************************
+// Get Picture
+//***************************************************************************
+
+int Epgdata::getPicture(const char* imagename, const char* fileRef, MemoryStruct* data)
+{
+ int fileSize = 0;
+ char* path = 0;
+ char entryName[200+TB];
+
+ data->clear();
+
+ // lookup file information
+
+ obj->fileDb->clear();
+ obj->fileDb->setValue("FILEREF", fileRef);
+ obj->fileDb->setValue("SOURCE", getSource());
+
+ if (stmtByFileRef->find())
+ asprintf(&path, "%s/epgdata/%s", EpgdConfig.cachePath,
+ obj->fileDb->getStrValue("Name"));
+
+ stmtByFileRef->freeResult();
+
+ if (!path)
+ {
+ tell(0, "Error: No entry with fileref '%s' to lookup image '%s' found",
+ fileRef, imagename);
+ return 0;
+ }
+
+ if (unzip(path, imagename, data->memory, fileSize, entryName) == success)
+ {
+ data->size = fileSize;
+ tell(2, "Unzip of image '%s' succeeded", imagename);
+ }
+
+ free(path);
+
+ return fileSize;
+}
+
+int Epgdata::cleanupAfter()
+{
+ const char* ext = ".zip";
+ struct dirent* dirent;
+ DIR* dir;
+ char* pdir;
+ int count = 0;
+ char* last = 0;
+
+ // cleanup *.zip in FS cache ...
+
+ // remove old versions for each day
+
+ obj->fileDb->clear();
+ obj->fileDb->setValue("SOURCE", getSource());
+
+ for (int f = stmtCleanDouble->find(); f; f = stmtCleanDouble->fetch())
+ {
+ const char* name = obj->fileDb->getStrValue("NAME");
+
+ if (last && strncmp(name, last, 8) == 0)
+ {
+ char* where;
+ tell(1, "Remove old epgdata file '%s' from table", name);
+ asprintf(&where, "name = '%s'", name);
+ obj->fileDb->deleteWhere("%s", where);
+ free(where);
+ }
+
+ free(last);
+ last = strdup(name);
+ }
+
+ free(last);
+ stmtCleanDouble->freeResult();
+
+ // mark wasted events (delflg, ...)
+
+ stmtMarkOldEvents->execute();
+
+ // cleanup filesystem, remove files which not referenced in table
+
+ asprintf(&pdir, "%s/%s", EpgdConfig.cachePath, getSource());
+
+ if (!(dir = opendir(pdir)))
+ {
+ tell(1, "Can't open directory '%s', '%s'", pdir, strerror(errno));
+ free(pdir);
+
+ return done;
+ }
+
+ tell(1, "Starting cleanup of epgdata zip's in '%s'", pdir);
+
+ free(pdir);
+
+ while ((dirent = readdir(dir)))
+ {
+ // check extension
+
+ if (strncmp(dirent->d_name + strlen(dirent->d_name) - strlen(ext), ext, strlen(ext)) != 0)
+ continue;
+
+ // lookup file
+
+ obj->fileDb->clear();
+ obj->fileDb->setValue("NAME", dirent->d_name);
+ obj->fileDb->setValue("SOURCE", getSource());
+
+ if (!obj->fileDb->find())
+ {
+ asprintf(&pdir, "%s/%s/%s", EpgdConfig.cachePath, getSource(), dirent->d_name);
+
+ if (!removeFile(pdir))
+ count++;
+
+ free(pdir);
+ }
+
+ obj->fileDb->reset();
+ }
+
+ closedir(dir);
+
+ tell(1, "Cleanup finished, removed (%d) epgdata files", count);
+
+ return success;
+}
+
+//***************************************************************************
+
+extern "C" void* EPGPluginCreator() { return new Epgdata(); }
diff --git a/PLUGINS/epgdata/epgdata.h b/PLUGINS/epgdata/epgdata.h
new file mode 100644
index 0000000..0bb0d88
--- /dev/null
+++ b/PLUGINS/epgdata/epgdata.h
@@ -0,0 +1,52 @@
+/*
+ * epgdata.h
+ *
+ * See the README file for copyright information
+ *
+ */
+
+#include "epgd.h"
+
+//***************************************************************************
+// Epgdata
+//***************************************************************************
+
+class Epgdata : public Plugin
+{
+ public:
+
+ Epgdata();
+ virtual ~Epgdata();
+
+ int init(cEpgd* aObject, int aUtf8);
+ int initDb();
+ int exitDb();
+ int atConfigItem(const char* Name, const char* Value);
+
+ const char* getSource() { return "epgdata"; }
+
+ int getPicture(const char* imagename, const char* fileRef, MemoryStruct* data);
+ int processDay(int day, int fullupdate, Statistic* statistic);
+ int cleanupAfter();
+ int ready();
+
+ protected:
+
+ int processFile(const char* data, int size, const char* fileRef);
+
+ cDbValue valueNameLike;
+ cDbValue valueName;
+ cDbValue valueFileRef;
+ cDbStatement* stmtByFileRef;
+ cDbStatement* stmtCleanDouble;
+ cDbStatement* selectId;
+ cDbStatement* selectByDate;
+ cDbStatement* stmtMarkOldEvents;
+ xsltStylesheetPtr pxsltStylesheet;
+
+ // config
+
+ char* baseurl;
+ int timeout;
+ char* pin;
+};
diff --git a/PLUGINS/epgdata/scripts/getepgdataids b/PLUGINS/epgdata/scripts/getepgdataids
new file mode 100755
index 0000000..898a647
--- /dev/null
+++ b/PLUGINS/epgdata/scripts/getepgdataids
@@ -0,0 +1,37 @@
+
+path="/tmp/epgdata/"
+file=$path/"info.zip"
+
+mkdir -p $path
+
+cd $path
+rm -f *
+
+wget "http://www.epgdata.com/index.php?action=sendInclude&iOEM=&pin=XYZ&dataType=xml" -q -O $file
+
+unzip $file > /dev/null 2>&1
+rm $file
+
+chanfile="channel_y.xml"
+
+cat $chanfile | while read line; do
+
+ if [[ ${line} =~ "<ch0>" ]]; then
+
+ chan=${line#*>}
+ chan=${chan%<*}
+
+ else
+
+ if [[ ${line} =~ "<ch4>" ]]; then
+
+ id=${line#*>}
+ id=${id%<*}
+
+ echo "epgdata:$id // $chan"
+
+ fi
+
+ fi
+
+done | sort
diff --git a/PLUGINS/epgdata/scripts/getincludes b/PLUGINS/epgdata/scripts/getincludes
new file mode 100755
index 0000000..120f1c1
--- /dev/null
+++ b/PLUGINS/epgdata/scripts/getincludes
@@ -0,0 +1,6 @@
+
+rm -f include.zip
+wget "http://www.epgdata.com/index.php?action=sendInclude&iOEM=&pin=&dataType=xml" -q -O include.zip
+unzip include.zip
+rm -f include.zip
+