Bug Summary

File:uservars.c
Location:line 226, column 7
Description:Value stored to 'varPos' is never read

Annotated Source Code

1/* -*- c++ -*-
2Copyright (C) 2004-2013 Christian Wieninger
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18
19The author can be reached at cwieninger@gmx.de
20
21The project's page is at http://winni.vdr-developer.org/epgsearch
22*/
23
24#include <algorithm>
25#ifdef __FreeBSD__
26#include <netinet/in.h>
27#endif
28#include "uservars.h"
29#include "epgsearchcats.h"
30#include "epgsearchtools.h"
31#include "log.h"
32#include <sys/socket.h>
33#include <netdb.h>
34
35cUserVars UserVars;
36
37string cPlugconfdirVar::dir = "";
38string cExtEPGVar::nameSpace = "epg";
39string cTimerVar::nameSpace = "timer";
40string cSearchVar::nameSpace = "search";
41
42// cUserVar
43
44cUserVar::cUserVar()
45{
46 oldEvent = NULL__null;
47 oldescapeStrings = false;
48}
49
50string cUserVar::Evaluate(const cEvent* e, bool escapeStrings)
51{
52 if (oldEvent && oldEvent == e && oldescapeStrings == escapeStrings)
53 return oldResult;
54 usedVars.clear();
55 string result;
56 if (IsShellCmd())
57 result = EvaluateShellCmd(e);
58 else if (IsConnectCmd())
59 result = EvaluateConnectCmd(e);
60 else if (IsLengthCmd())
61 result = EvaluateLengthCmd(e);
62 else if (IsCondExpr())
63 result = EvaluateCondExpr(e);
64 else
65 result = EvaluateCompExpr(e);
66 oldResult = result;
67 oldEvent = e;
68 oldescapeStrings = escapeStrings;
69
70 // avoid double dir separators
71 int pos = 0;
72 while((pos = result.find("~~")) >= 0)
73 result.replace(pos, 2, "~");
74
75 return result;
76}
77
78string cUserVar::EvaluateShellCmd(const cEvent* e)
79{
80 if (!varparser.cmd) return "";
81 string cmdArgs;
82 if (varparser.cmdArgs != "")
83 {
84 string args = varparser.cmdArgs;
85 varparser.compExpr = args; //handle the args as composed expr
86 cmdArgs = EvaluateCompExpr(e, true);
87 }
88 const char* res = varparser.cmd->Execute(cmdArgs.c_str());
89 string result = res?res:"";
90 int crPos = 0; // remove any CR
91 while((crPos = result.find("\n")) >= 0)
92 result.replace(crPos, 1, "");
93
94 return result;
95}
96
97#define MAX_LINE1000 1000
98string cUserVar::EvaluateConnectCmd(const cEvent* e)
99{
100 if (varparser.connectAddr == "") return "";
101
102 int conn_s; /* connection socket */
103 struct sockaddr_in servaddr; /* socket address structure */
104 char buffer[MAX_LINE1000]; /* character buffer */
105
106 if ( (conn_s = socket(AF_INET2, SOCK_STREAMSOCK_STREAM, 0)) < 0 )
107 {
108 LogFile.eSysLog("Error creating listening socket");
109 return "";
110 }
111
112 memset(&servaddr, 0, sizeof(varparser.connectAddr.c_str()));
113 servaddr.sin_family = AF_INET2;
114 servaddr.sin_port = htons(varparser.connectPort)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (varparser.connectPort); if (__builtin_constant_p (__x)
) __v = ((unsigned short int) ((((__x) >> 8) & 0xff
) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
;
115
116 if (getAddrFromString(varparser.connectAddr.c_str(), &servaddr) != 0)
117 {
118 LogFile.eSysLog("Invalid remote address");
119 return "";
120 }
121
122 if ( connect(conn_s, (struct sockaddr *) &servaddr, sizeof(servaddr) ) < 0 )
123 {
124 LogFile.eSysLog("Error calling connect()");
125 return "";
126 }
127
128 varparser.compExpr = varparser.cmdArgs;
129 string resexp = EvaluateCompExpr(e, true);
130 sprintf(buffer, "%s\n", resexp.c_str());
131 Writeline(conn_s, buffer, strlen(buffer));
132 Readline(conn_s, buffer, MAX_LINE1000-1);
133
134 close(conn_s);
135 return buffer;
136}
137
138string cUserVar::EvaluateLengthCmd(const cEvent* e)
139{
140 return NumToString(EvaluateCompExpr(e, false).size());
141}
142
143string cUserVar::EvaluateCondExpr(const cEvent* e, bool escapeStrings)
144{
145 string condresult = "";
146 cVarExpr leftExp(varparser.condEqLeft);
147 string resLeft = leftExp.Evaluate(e);
148 cVarExpr rightExp(varparser.condEqRight);
149 string resRight = rightExp.Evaluate(e);
150 if (varparser.condOp == condEq && resLeft == resRight) condresult = "1"; // assign any value
151 if (varparser.condOp == condNeq && resLeft != resRight) condresult = "1"; // assign any value
152
153 cUserVar* condVarTrue = UserVars.GetFromName(varparser.condvarTrue);
154 cUserVar* condVarFalse = UserVars.GetFromName(varparser.condvarFalse);
155 if (!condVarTrue || !condVarFalse) return "";
156
157 if (!AddDepVar(condVarTrue)) return "";
158 if (!AddDepVar(condVarFalse)) return "";
159
160 if (condresult != "")
161 {
162 LogFile.Log(3, "using case 'true'");
163 return condVarTrue->Evaluate(e, escapeStrings);
164 }
165 else
166 {
167 LogFile.Log(3, "using case 'false'");
168 return condVarFalse->Evaluate(e, escapeStrings);
169 }
170}
171
172string cUserVar::EvaluateCompExpr(const cEvent* e, bool escapeStrings)
173{
174 string expr = varparser.compExpr;
175 if (expr.find('%') == string::npos) return expr;
176
177 // handle internal vars like title and subtitle
178 expr = EvaluateInternalVars(expr, e, escapeStrings);
179
180 // replace ext. EPG variables
181 expr = EvaluateExtEPGVars(expr, e, escapeStrings);
182
183 // replace other user vars
184 expr = EvaluateUserVars(expr, e, escapeStrings);
185
186 return expr;
187}
188
189string cUserVar::EvaluateInternalVars(const string& Expr, const cEvent* e, bool escapeStrings)
190{
191 string expr = Expr;
192 if (expr.find('%') == string::npos) return expr;
193
194 std::map<string, cInternalVar*>::iterator it;
195 for (it = UserVars.internalVars.begin(); it != UserVars.internalVars.end(); ++it)
196 {
197 string varName = (it->second)->Name();
198 int varPos = 0;
199 while((varPos = FindIgnoreCase(expr, varName)) >= 0)
200 {
201 usedVars.insert(it->second);
202 expr.replace(varPos, varName.size(), (it->second)->Evaluate(e, escapeStrings));
203 }
204 }
205 return expr;
206}
207
208string cUserVar::EvaluateExtEPGVars(const string& Expr, const cEvent* e, bool escapeStrings)
209{
210 string expr = Expr;
211 if (expr.find('%') == string::npos) return expr;
212
213 std::map<string, cExtEPGVar*>::iterator evar;
214 for (evar = UserVars.extEPGVars.begin(); evar != UserVars.extEPGVars.end(); ++evar)
215 {
216 // replace ext. EPG variables with leading namespace
217 string varName = evar->second->Name(true);
218 int varPos = 0;
219 while((varPos = FindIgnoreCase(expr, varName)) >= 0)
220 {
221 expr.replace(varPos, varName.size(), evar->second->Evaluate(e, escapeStrings));
222 usedVars.insert(evar->second);
223 }
224 // replace ext. EPG variables without leading namespace
225 varName = evar->second->Name();
226 varPos = 0;
Value stored to 'varPos' is never read
227 while((varPos = FindIgnoreCase(expr, varName)) >= 0)
228 {
229 expr.replace(varPos, varName.size(), evar->second->Evaluate(e, escapeStrings));
230 usedVars.insert(evar->second);
231 }
232 }
233 return expr;
234}
235
236string cUserVar::EvaluateUserVars(const string& Expr, const cEvent* e, bool escapeStrings)
237{
238 string expr = Expr;
239 if (expr.find('%') == string::npos) return expr;
240
241 std::set<cUserVar*>::iterator it;
242 for (it = UserVars.userVars.begin(); it != UserVars.userVars.end(); ++it)
243 {
244 string varName = (*it)->Name();
245 int varPos = 0;
246 while((varPos = FindIgnoreCase(expr, varName)) >= 0)
247 {
248 if (!AddDepVar(*it)) return "";
249 expr.replace(varPos, varName.size(), (*it)->Evaluate(e, escapeStrings));
250 }
251 }
252 return expr;
253}
254
255string cUserVar::EvaluateInternalTimerVars(const string& Expr, const cTimer* t)
256{
257 string expr = Expr;
258 if (expr.find('%') == string::npos) return expr;
259
260 std::map<string, cTimerVar*>::iterator tvar;
261 for (tvar = UserVars.internalTimerVars.begin(); tvar != UserVars.internalTimerVars.end(); ++tvar)
262 {
263 string varName = tvar->second->Name();
264 int varPos = 0;
265
266 while((varPos = FindIgnoreCase(expr, varName)) >= 0)
267 {
268 expr.replace(varPos, varName.size(), tvar->second->Evaluate(t));
269 }
270 }
271 return expr;
272}
273
274string cUserVar::EvaluateInternalSearchVars(const string& Expr, const cSearchExt* s)
275{
276 string expr = Expr;
277 if (expr.find('%') == string::npos) return expr;
278
279 std::map<string, cSearchVar*>::iterator svar;
280 for (svar = UserVars.internalSearchVars.begin(); svar != UserVars.internalSearchVars.end(); ++svar)
281 {
282 string varName = svar->second->Name();
283 int varPos = 0;
284 while((varPos = FindIgnoreCase(expr, varName)) >= 0)
285 {
286 expr.replace(varPos, varName.size(), svar->second->Evaluate(s));
287 }
288 }
289 return expr;
290}
291
292bool cUserVar::DependsOnVar(const string& varName)
293{
294 string VarName = Strip(varName);
295 cUserVar* var = UserVars.GetFromName(VarName);
296 if (!var) return false;
297 return DependsOnVar(var);
298}
299
300bool cUserVar::DependsOnVar(cUserVar* var)
301{
302 if (!var) return false;
303 if (usedVars.find(var) != usedVars.end()) return true;
304 std::set<cUserVar*>::iterator it;
305 for (it = usedVars.begin(); it != usedVars.end(); ++it)
306 if ((*it)->DependsOnVar(var))
307 return true;
308 return false;
309}
310
311bool cUserVar::AddDepVar(cUserVar* var)
312{
313 if (var == this || var->DependsOnVar(this))
314 {
315 LogFile.eSysLog("ERROR - found cylic reference to var '%s' in var '%s'", var->Name().c_str(), Name().c_str());
316 return false;
317 }
318 usedVars.insert(var);
319 return true;
320}
321
322void cUserVar::ResetCache()
323{
324 oldEvent = NULL__null;
325 oldResult = "";
326}
327
328// cUserVarLine
329bool cUserVarLine::Parse(char *s)
330{
331 if (!s) return false;
332 if (s[0] == '#')
333 return true;
334 char *p = strchr(s, '=');
335 if (p)
336 {
337 cUserVar* userVar = new cUserVar;
338 if (userVar->varparser.Parse(s))
339 {
340 cUserVar* oldVar = UserVars.GetFromName(userVar->Name(), false);
341 if (oldVar) // allow redefintion of existing vars
342 {
343 LogFile.Log(1, "variable '%s' gets overwritten", oldVar->Name().c_str());
344 UserVars.userVars.erase(oldVar);
345 delete oldVar;
346 }
347 UserVars.userVars.insert(userVar);
348 return true;
349 }
350 }
351 return false;
352}
353
354// cUserVars
355cUserVar* cUserVars::GetFromName(const string& varName, bool log)
356{
357 string VarName = Strip(varName);
358 std::transform(VarName.begin(), VarName.end(), VarName.begin(), tolower);
359
360 std::map<string, cInternalVar*>::iterator ivar = internalVars.find(VarName);
361 if (ivar != internalVars.end())
362 return ivar->second;
363
364 std::set<cUserVar*>::iterator uvar;
365 for (uvar = userVars.begin(); uvar != userVars.end(); ++uvar)
366 if (EqualsNoCase((*uvar)->Name(), VarName))
367 return (*uvar);
368
369 std::map<string, cExtEPGVar*>::iterator evar = extEPGVars.find(VarName);
370 if (evar != extEPGVars.end())
371 return evar->second;
372
373 if (log)
374 LogFile.eSysLog("var '%s' not defined!", VarName.c_str());
375 return NULL__null;
376}
377
378// cVarExpr
379string cVarExpr::Evaluate(const cEvent* e)
380{
381 // create a dummy user var
382 cUserVar var;
383 if (!var.varparser.ParseExp(expr))
384 return "";
385
386 LogFile.Log(3, "start evaluating expression '%s'", expr.c_str());
387 string result = var.Evaluate(e);
388 LogFile.Log(3, "stop evaluating expression '%s' - result: '%s'", expr.c_str(), result.c_str());
389 usedVars = var.usedVars;
390 return result;
391}
392
393string cVarExpr::Evaluate(const cTimer* t)
394{
395 // create a dummy user var
396 cUserVar var;
397 if (!var.varparser.ParseExp(expr))
398 return "";
399
400 usedVars = var.usedVars;
401 return var.EvaluateInternalTimerVars(expr, t);
402}
403
404string cVarExpr::Evaluate(const cSearchExt* s)
405{
406 // create a dummy user var
407 cUserVar var;
408 if (!var.varparser.ParseExp(expr))
409 return "";
410
411 usedVars = var.usedVars;
412 return var.EvaluateInternalSearchVars(expr, s);
413}
414
415bool cVarExpr::DependsOnVar(const string& varName, const cEvent* e)
416{
417 string VarName = Strip(varName);
418 if (FindIgnoreCase(expr, VarName) >= 0)
419 return true;
420 // create a dummy user var
421 cUserVar var;
422 var.varparser.varName = expr;
423 if (!var.varparser.ParseExp(expr))
424 return false;
425 var.Evaluate(e);
426 return var.DependsOnVar(VarName);
427}