/* Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "varparser.h" #include #include "log.h" #include "epgsearchtools.h" #include bool cVarParser::Parse(const string& input) { return ParseAssign(input); } bool cVarParser::ParseAssign(const string& input) { int assignPos = input.find("="); if (assignPos >= 0) { string var(input.begin(), input.begin() + assignPos); if (ParseVar(var)) { varName = Strip(var); string assign(input.begin() + assignPos + 1, input.end()); return ParseExp(assign); } } LogFile.eSysLog("error parsing '%s'", input.c_str()); return false; } bool cVarParser::ParseExp(const string& input) { // system call? int sysPos = input.find("system"); if (sysPos == 0) return ParseShellCmd(input); // connect command? int conPos = input.find("connect"); if (conPos == 0) return ParseConnectCmd(input); // length command? int lenPos = input.find("length"); if (lenPos == 0) return ParseLengthCmd(input); // conditional expression? int varPos = Strip(input).find("%"); if (varPos == 0) { int queryPos = input.find("?"); if (queryPos >= 0) { int colonPos = input.find(":"); if (colonPos > queryPos) return ParseCondExp(input); } } // composed expression compExpr = input; return true; } bool cVarParser::ParseShellCmd(const string& input) { int cmdPos = input.find("("); int cmdArgsBegin = input.find(","); int cmdArgsEnd = input.rfind(")"); if (cmdPos == -1 || cmdArgsEnd == -1) return false; string shellcmd(input.begin() + cmdPos + 1, input.begin() + (cmdArgsBegin >= 0?cmdArgsBegin:cmdArgsEnd)); shellcmd = Strip(shellcmd); cmdArgs = ""; if (cmdArgsBegin >= 0) cmdArgs = string(input.begin() + cmdArgsBegin + 1, input.begin() + cmdArgsEnd); string cmdVDR = "varcmd: " + shellcmd; cmd = new cCommand; if (!cmd->Parse(cmdVDR.c_str())) { LogFile.eSysLog("error parsing command: %s", input.c_str()); delete cmd; cmd = NULL; return false; } type = cVarParser::shellcmd; 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; } type = cVarParser::connectcmd; return true; } bool cVarParser::ParseLengthCmd(const string& input) { int startLen = input.find("("); int endLen = input.find(")"); if (startLen == -1 || endLen == -1) return false; string arg(input.begin() + startLen + 1, input.begin() + endLen); compExpr = arg; type = cVarParser::lengthcmd; return true; } bool cVarParser::ParseCondExp(const string& input) { int condEndPos = input.find("?"); string cond(input.begin(), input.begin() + condEndPos); int condNeqPos = cond.find("!="); int condEqPos = cond.find("=="); if (condEqPos == -1 && condNeqPos == -1) { cond += "!="; condNeqPos = cond.find("!="); } if (condEqPos >= 0 || condNeqPos >= 0) { if (!ParseEquality(cond)) { LogFile.eSysLog("error parsing '%s'", input.c_str()); return false; } condOp = (condEqPos >= 0)?condEq:condNeq; } else { LogFile.eSysLog("error parsing '%s'", input.c_str()); return false; } string truefalse(input.begin() + condEndPos + 1, input.end()); int elsePos = truefalse.find(":"); if (elsePos >= 0) { string truePart(truefalse.begin(), truefalse.begin() + elsePos); string falsePart(truefalse.begin() + elsePos + 1, truefalse.end()); if (ParseVar(truePart) && ParseVar(falsePart)) { condvarTrue = Strip(truePart); condvarFalse = Strip(falsePart); type = cVarParser::condition; return true; } } LogFile.eSysLog("error parsing '%s'", input.c_str()); condEqLeft = condEqRight = ""; return false; } bool cVarParser::ParseEquality(const string& input) { int condEqPos = input.find("=="); int condNeqPos = input.find("!="); int condOpPos = -1; if (condEqPos >= 0) condOpPos = condEqPos; if (condNeqPos >= 0) condOpPos = condNeqPos; if (condOpPos == -1) return false; string left(input.begin(), input.begin() + condOpPos); string right(input.begin() + condOpPos + 2, input.end()); if (ParseExp(left) && ParseExp(right)) { condEqLeft = Strip(left); condEqRight = Strip(right); return true; } return false; } bool cVarParser::ParseVar(const string& input) { string str = Strip(input); if (str.size() > 2 && str[0] == '%' && str[str.size()-1] == '%') return true; return false; } bool cVarParser::IsCondExpr() { return type == cVarParser::condition; } bool cVarParser::IsShellCmd() { return type == cVarParser::shellcmd; } bool cVarParser::IsConnectCmd() { return type == cVarParser::connectcmd; } bool cVarParser::IsLengthCmd() { return type == cVarParser::lengthcmd; }