diff options
author | Christian Wieninger <cwieninger (at) gmx (dot) de> | 2009-10-29 20:03:01 +0100 |
---|---|---|
committer | Christian Wieninger <cwieninger (at) gmx (dot) de> | 2009-10-29 20:03:01 +0100 |
commit | ac4560560513d838450e86c25611d950cefc44ee (patch) | |
tree | 647eb69cf384142a7313e8b957ec90708226a0a5 | |
parent | 06ca46d943e3d7bbf315fcfb8c4653523fae66de (diff) | |
download | vdr-plugin-epgsearch-ac4560560513d838450e86c25611d950cefc44ee.tar.gz vdr-plugin-epgsearch-ac4560560513d838450e86c25611d950cefc44ee.tar.bz2 |
extended internal variable syntax with 'connect'
-rw-r--r-- | HISTORY | 7 | ||||
-rw-r--r-- | HISTORY.DE | 7 | ||||
-rw-r--r-- | doc-src/en/epgsearch.4.txt | 10 | ||||
-rw-r--r-- | epgsearch.c | 2 | ||||
-rw-r--r-- | epgsearchtools.c | 85 | ||||
-rw-r--r-- | epgsearchtools.h | 3 | ||||
-rw-r--r-- | svdrpclient.h | 31 | ||||
-rw-r--r-- | uservars.c | 43 | ||||
-rw-r--r-- | uservars.h | 2 | ||||
-rw-r--r-- | varparser.c | 36 | ||||
-rw-r--r-- | varparser.h | 8 |
11 files changed, 197 insertions, 37 deletions
@@ -18,8 +18,8 @@ new: Switch timers now have the same option. - in addition to the announcements via OSD new events can now also be reported by mail. To do so, there's a new search timer action "Announce by mail". You also have to update - your mail template file epgsearchupdmail.templ (s. the updated sample in the conf directory - and/or read the MANUAL '13. Email notification'). + your mail template file epgsearchupdmail.templ (s. the updated html sample in the conf + directory and/or read the MANUAL '13. Email notification'). - The time in hours between the search timer mails can now be configured in the setup to avoid flooding your inbox. epgsearch buffers the contents of the pending mails in the new file pendingnotifications.conf. @@ -31,6 +31,9 @@ new: direct links e.g. in the search timer mails (see sample conf/epgsearchupdmail-html.templ). * %timer.liveid% returns the encoded timer ID as used in the frontend 'live' to add direct links e.g. in the search timer mails. +- new command 'connect' within internal variables: with this command you can connect to + a TCP service, pass data and assign the result to a variable. See the MANUAL for + details. - in memory to pat: french translation update, thanks to Patrice Staudt - italian translation update, thanks to Diego Pierotto - finnish translation update, thanks to Rolf Ahrenberg and Ville Skyttä @@ -17,8 +17,8 @@ neu: gewechselt werden. Umschalttimer haben die gleiche Option erhalten. - Zusätzlich zur Ankündigung per OSD können neue Sendungen nun auch per Mail bekannt- gegeben werden. Dazu gibt es eine neue Suchtimeraktion "Per Mail ankündigen". Man muss - ausserdem das Mail-Templatefile epgsearchupdmail.templ anpassen (s. Beispiel im conf- - Verzeichnis bzw. MANUAL '13. Email notification'). + ausserdem das Mail-Templatefile epgsearchupdmail.templ anpassen (s. aktualisiertes + HTML-Beispiel im conf-Verzeichnis bzw. MANUAL '13. Email notification'). - Die Zeit in Stunden zwischen den Suchtimer-Emails kann nun im Setup eingestellt werden um eine Überflutung des Posteingangs zu vermeiden. epgsearch puffert den Inhalt ausstehender Mails in der neuen Datei pendingnotifications.conf. @@ -31,6 +31,9 @@ neu: conf/epgsearchupdmail-html.templ) * %timer.liveid% liefert die kodierte Timer-ID wie sie im Frontend 'live' benutzt wird. Damit können nun z.B. in den Suchtimer-Mails direkte Links angegeben werden. +- neues Kommando 'connect' innerhalb interner Variablen: damit kann eine Verbindung zu einem + TCP-Dienst aufgebaut werden, Daten übergeben und das Ergebnis einer Variable zugewiesen + werden. S. MANUAL für Details. - Im Gedenken an pat: Update der französischen Übersetzung, Danke an Patrice Staudt - Update der italienischen Übersetzung, Danke an Diego Pierotto - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg und Ville Skyttä diff --git a/doc-src/en/epgsearch.4.txt b/doc-src/en/epgsearch.4.txt index 0d2588a..5938cc0 100644 --- a/doc-src/en/epgsearch.4.txt +++ b/doc-src/en/epgsearch.4.txt @@ -728,6 +728,16 @@ The script must return a string B<without> line break! If the script returns nothing, an empty string will be assigned to the Variable %Result%. +=head2 Calling a TCP service + +You can call a TCP service with the following syntax: + + %uservar%=connect(<addr>, <port>, [<data>]) + +This will connect to <addr> through the given port and pass the optional given +data. <addr> can be an IP address or the domain name of the TCP service. The result +returned by the service must be terminated with a line feed. + =head2 Possible variables for a list of already builtin variables refer to the section "Customizing the EPG menus" diff --git a/epgsearch.c b/epgsearch.c index b37a320..59b0494 100644 --- a/epgsearch.c +++ b/epgsearch.c @@ -67,7 +67,7 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include "confdloader.h" #include "pending_notifications.h" -static const char VERSION[] = "0.9.25.beta15"; +static const char VERSION[] = "0.9.25.beta16"; static const char DESCRIPTION[] = trNOOP("search the EPG for repeats and more"); // globals diff --git a/epgsearchtools.c b/epgsearchtools.c index 3f542e9..bca9bc2 100644 --- a/epgsearchtools.c +++ b/epgsearchtools.c @@ -26,6 +26,8 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include <fstream> #include <iostream> #include <ctype.h> +#include <netdb.h> +#include <arpa/inet.h> #include "uservars.h" #include "epgsearchtools.h" @@ -579,7 +581,7 @@ bool SendViaSVDRP(cString SVDRPcmd) else { cmdbuf = SVDRPcmd; - cSVDRPClient client(EPGSearchConfig.SVDRPPort); + cSVDRPClient client; if (!client.SendCmd(*cmdbuf)) { LogFile.eSysLog("command '%s' failed", *cmdbuf); @@ -1048,3 +1050,84 @@ std::string GetCodeset() return "ISO-8859-15"; #endif } + +/* Read a line from a socket */ +ssize_t Readline(int sockd, char *vptr, size_t maxlen) { + size_t n, rc; + char c, *buffer; + + buffer = vptr; + + for ( n = 1; n < maxlen; n++ ) { + + if ( (rc = read(sockd, &c, 1)) == 1 ) { + *buffer++ = c; + if ( c == '\n' ) + break; + } + else if ( rc == 0 ) { + if ( n == 1 ) + return 0; + else + break; + } + else { + if ( errno == EINTR ) + continue; + return -1; + } + } + + *buffer = 0; + return n; +} + +/* Write a line to a socket */ +ssize_t Writeline(int sockd, const char *vptr, size_t n) { + size_t nleft; + size_t nwritten; + const char *buffer; + + buffer = vptr; + nleft = n; + + while ( nleft > 0 ) { + if ( (nwritten = write(sockd, buffer, nleft)) <= 0 ) { + if ( errno == EINTR ) + nwritten = 0; + else + return -1; + } + nleft -= nwritten; + buffer += nwritten; + } + + return n; +} + +long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr) +{ + unsigned long ip; + + struct hostent * he; + + if(hostnameOrIp==NULL || addr==NULL) + return -1; + + ip=inet_addr(hostnameOrIp); + + if(ip!=INADDR_NONE) + { + addr->sin_addr.s_addr=ip; + return 0; + } + else + { + he=gethostbyname(hostnameOrIp); + if(he==NULL) + return -1; + else + memcpy(&(addr->sin_addr),he->h_addr_list[0],4); + return 0; + } +} diff --git a/epgsearchtools.h b/epgsearchtools.h index d55d5e3..d38103c 100644 --- a/epgsearchtools.h +++ b/epgsearchtools.h @@ -186,6 +186,9 @@ time_t GetDateTime(time_t day, int start); void SetAux(cTimer* timer, string aux); int msprintf(char **strp, const char *fmt, ...); std::string GetCodeset(); +ssize_t Readline(int sockd, char *vptr, size_t maxlen); +ssize_t Writeline(int sockd, const char *vptr, size_t n); +long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr); // --- cTimerObj -------------------------------------------------------- class cTimerObj : public cListObject { diff --git a/svdrpclient.h b/svdrpclient.h index aa021a1..8462fef 100644 --- a/svdrpclient.h +++ b/svdrpclient.h @@ -25,8 +25,6 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #define __SVDRPCLIENT_H #include <sys/socket.h> -#include <netdb.h> -#include <arpa/inet.h> #include "log.h" #define SVDRPCONNECT 220 @@ -39,7 +37,7 @@ class cSVDRPClient { public: bool bConnected; - cSVDRPClient(int Port) + cSVDRPClient() { bConnected = false; sock = socket(PF_INET, SOCK_STREAM, 0); @@ -64,33 +62,6 @@ public: LogFile.eSysLog("EPGSearch: could not connect to VDR!"); } - long getAddrFromString(char* hostnameOrIp, struct sockaddr_in* addr) - { - unsigned long ip; - - struct hostent * he; - - if(hostnameOrIp==NULL || addr==NULL) - return -1; - - ip=inet_addr(hostnameOrIp); - - if(ip!=INADDR_NONE) - { - addr->sin_addr.s_addr=ip; - return 0; - } - else - { - he=gethostbyname(hostnameOrIp); - if(he==NULL) - return -1; - else - memcpy(&(addr->sin_addr),he->h_addr_list[0],4); - return 0; - } - } - bool SendCmd(const char* cmd) { if (!bConnected) @@ -26,6 +26,8 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include "epgsearchcats.h" #include "epgsearchtools.h" #include "log.h" +#include <sys/socket.h> +#include <netdb.h> cUserVars UserVars; @@ -46,6 +48,8 @@ string cUserVar::Evaluate(const cEvent* e, bool escapeStrings) string result; if (IsShellCmd()) result = EvaluateShellCmd(e); + else if (IsConnectCmd()) + result = EvaluateConnectCmd(e); else if (IsCondExpr()) result = EvaluateCondExpr(e); else @@ -81,6 +85,45 @@ string cUserVar::EvaluateShellCmd(const cEvent* e) return result; } +#define MAX_LINE 1000 +string cUserVar::EvaluateConnectCmd(const cEvent* e) +{ + if (varparser.connectAddr == "") return ""; + + int conn_s; /* connection socket */ + struct sockaddr_in servaddr; /* socket address structure */ + char buffer[MAX_LINE]; /* character buffer */ + + if ( (conn_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) + { + LogFile.eSysLog("Error creating listening socket"); + return ""; + } + + memset(&servaddr, 0, sizeof(varparser.connectAddr.c_str())); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(varparser.connectPort); + + if (getAddrFromString(varparser.connectAddr.c_str(), &servaddr) != 0) + { + LogFile.eSysLog("Invalid remote address"); + return ""; + } + + if ( connect(conn_s, (struct sockaddr *) &servaddr, sizeof(servaddr) ) < 0 ) + { + LogFile.eSysLog("Error calling connect()"); + return ""; + } + + sprintf(buffer, "%s\n", varparser.cmdArgs.c_str()); + Writeline(conn_s, buffer, strlen(buffer)); + Readline(conn_s, buffer, MAX_LINE-1); + + close(conn_s); + return buffer; +} + string cUserVar::EvaluateCondExpr(const cEvent* e, bool escapeStrings) { string condresult = ""; @@ -51,6 +51,7 @@ class cUserVar : public cListObject { string EvaluateCondExpr(const cEvent* e, bool escapeStrings = false); string EvaluateCompExpr(const cEvent* e, bool escapeStrings = false); string EvaluateShellCmd(const cEvent* e); + string EvaluateConnectCmd(const cEvent* e); public: cUserVar(); cVarParser varparser; @@ -66,6 +67,7 @@ public: virtual string Name() { return varparser.varName; } virtual bool IsCondExpr() { return varparser.IsCondExpr(); } virtual bool IsShellCmd() { return varparser.IsShellCmd(); } + virtual bool IsConnectCmd() { return varparser.IsConnectCmd(); } bool DependsOnVar(const string& varName); bool DependsOnVar(cUserVar* var); bool AddDepVar(cUserVar* var); diff --git a/varparser.c b/varparser.c index 4f3963f..6e7c3d9 100644 --- a/varparser.c +++ b/varparser.c @@ -25,6 +25,7 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include <vdr/plugin.h> #include "log.h" #include "epgsearchtools.h" +#include <sstream> bool cVarParser::Parse(const string& input) { @@ -54,6 +55,10 @@ bool cVarParser::ParseExp(const string& input) int sysPos = input.find("system"); if (sysPos == 0) return ParseShellCmd(input); + // connect command? + int conPos = input.find("connect"); + if (conPos == 0) + return ParseConnectCmd(input); // conditional expression? int varPos = Strip(input).find("%"); if (varPos == 0) @@ -96,6 +101,32 @@ bool cVarParser::ParseShellCmd(const string& input) return true; } +bool cVarParser::ParseConnectCmd(const string& input) +{ + int startCon = input.find("("); + int endCon = input.find(")"); + if (startCon == -1 || endCon == -1) return false; + string connect(input.begin() + startCon + 1, input.begin() + endCon); + std::stringstream ss(connect); + std::string item; + if (std::getline(ss, item, ',')) + connectAddr = item; + if (std::getline(ss, item, ',')) + connectPort = atoi(item.c_str()); + if (std::getline(ss, item)) + cmdArgs = item; + + connectAddr = Strip(connectAddr); + cmdArgs = Strip(cmdArgs); + + if (connectAddr.size() == 0 || connectPort == -1) + { + LogFile.eSysLog("error parsing command: %s", input.c_str()); + return false; + } + return true; +} + bool cVarParser::ParseCondExp(const string& input) { int condEndPos = input.find("?"); @@ -178,3 +209,8 @@ bool cVarParser::IsShellCmd() { return (cmd != NULL); } + +bool cVarParser::IsConnectCmd() +{ + return (connectAddr != "" && connectPort != -1); +} diff --git a/varparser.h b/varparser.h index 397c57d..8f1cf75 100644 --- a/varparser.h +++ b/varparser.h @@ -47,17 +47,23 @@ class cVarParser string condvarTrue; string condvarFalse; string compExpr; + cCommand* cmd; string cmdArgs; - cVarParser() : cmd(NULL) {} + string connectAddr; + int connectPort; + + cVarParser() : cmd(NULL), connectPort(-1) {} bool Parse(const string& input); bool ParseExp(const string& input); bool IsCondExpr(); bool IsShellCmd(); + bool IsConnectCmd(); private: bool ParseAssign(const string& input); bool ParseShellCmd(const string& input); + bool ParseConnectCmd(const string& input); bool ParseCondExp(const string& input); bool ParseEquality(const string& input); bool ParseVar(const string& input); |