Bug Summary

File:epgsearchtools.c
Location:line 234, column 18
Description:Null pointer passed as an argument to a 'nonnull' parameter

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#include <string>
26#include <fstream>
27#include <iostream>
28#include <ctype.h>
29#include <netdb.h>
30#include <arpa/inet.h>
31#ifdef __FreeBSD__
32#include <netinet/in.h>
33#endif
34#include "uservars.h"
35#include "epgsearchtools.h"
36#include "epgsearchext.h"
37#include "epgsearchcats.h"
38#include "epgsearchcfg.h"
39#include "svdrpclient.h"
40#include "distance.h"
41#include "md5.h"
42#include "afuzzy.h"
43#include "timerstatus.h"
44#include <langinfo.h>
45
46#ifdef HAVE_PCREPOSIX
47#include <pcreposix.h>
48#elif defined(HAVE_LIBTRE)
49#include <tre/regex.h>
50#else
51#include <regex.h>
52#endif
53
54const char AllowedChars[] = trNOOP("$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_")("$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_"
)
;
55extern bool isUTF8;
56
57int CompareEventTime(const void *p1, const void *p2)
58{
59 time_t time1 = (*(cSearchResult **)p1)->event->StartTime();
60 time_t time2 = (*(cSearchResult **)p2)->event->StartTime();
61 if (time1 == time2)
62 return (int)(ChannelNrFromEvent((*(cSearchResult **)p1)->event) -
63 ChannelNrFromEvent((*(cSearchResult **)p2)->event));
64 else
65 return (int)(time1 - time2);
66}
67
68int CompareEventChannel(const void *p1, const void *p2)
69{
70 int ch1 = ChannelNrFromEvent((*(cSearchResult **)p1)->event);
71 int ch2 = ChannelNrFromEvent((*(cSearchResult **)p2)->event);
72 if (ch1 == ch2)
73 return (int)((*(cSearchResult **)p1)->event->StartTime() -
74 (*(cSearchResult **)p2)->event->StartTime());
75 else
76 return ch1 - ch2;
77}
78
79int CompareSearchExtPrioDescTerm(const void *p1, const void *p2)
80{
81 int prio1 = (*(cSearchExt **)p1)->Priority;
82 int prio2 = (*(cSearchExt **)p2)->Priority;
83 if (prio2 != prio1)
84 return prio2 - prio1;
85 else
86 return strcmp((*(cSearchExt **)p1)->search, (*(cSearchExt **)p2)->search);
87}
88
89cString IndentMenuItem(const char* szString, int indentions)
90{
91 char* szIndented = NULL__null;
92 msprintf(&szIndented, "%*s", strlen(szString)+indentions*2, szString);
93 cString szIndentedStr(szIndented, true /*take pointer*/);
94 return szIndentedStr;
95}
96
97bool MatchesSearchMode(const char* szTest, const char* searchText, int mode, const char* delim, int tolerance)
98{
99 if (szTest && *szTest)
100 {
101 if (mode == 0) // substring
102 return (strstr(szTest, searchText) != NULL__null);
103 else if (mode == 1 || mode == 2) // AND or OR
104 {
105 bool bTesting = false;
106 char *pstrSearchToken, *pptr;
107 bool bFirst=true;
108 char *pstrSearch=strdup(searchText);
109 pstrSearchToken=strtok_r(pstrSearch, delim, &pptr);
110 while(pstrSearchToken)
111 {
112 if(szTest && strstr(szTest, skipspace(pstrSearchToken)))
113 {
114 if(mode==1)
115 { // means AND
116 if(bFirst)
117 {
118 bTesting=true;
119 bFirst=false;
120 }
121 else
122 bTesting&=true;
123 }
124 else
125 bTesting|=true;
126 }
127 else
128 {// not found!!
129 if(mode==1)
130 { // means AND
131 bTesting=false;
132 bFirst=false;
133 }
134 }
135 pstrSearchToken=strtok_r(NULL__null, delim, &pptr);
136 }
137 free(pstrSearch);
138 return bTesting;
139 }
140 else if (mode == 3) // match exactly
141 {
142 if (strcmp(szTest, searchText) == 0)
143 return true;
144 else
145 return false;
146 }
147 else if (mode == 4) // regexp
148 {
149 regex_t re;
150
151 if ( 0 == regcomp(&re, searchText, REG_EXTENDED1 | REG_NOSUB(((1 << 1) << 1) << 1)) )
152 {
153 int status = regexec( &re, szTest, 0, NULL__null, 0);
154 regfree(&re);
155 return (status == 0);
156 }
157 return false;
158 }
159 else if (mode == 5) // fuzzy
160 {
161 AFUZZY af = { NULL__null, NULL__null, NULL__null, NULL__null, NULL__null, NULL__null, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 };
162 string query = searchText?searchText:"";
163 if (query.size() > 32) query = query.substr(0, 32);
164 afuzzy_init(query.c_str(), tolerance, 0, &af);
165 /* Checking substring */
166 int res = afuzzy_checkSUB(szTest, &af);
167 afuzzy_free(&af);
168 return (res > 0);
169 }
170 else if (mode >= 10 && mode <= 15)
171 {
172 int testvalue = atoi(szTest);
173 int value = atoi(searchText);
174 if (value == 0) return true;
175
176 if (mode == 10) // less
177 return testvalue < value;
178 else if (mode == 11) // less or equal
179 return testvalue <= value;
180 else if (mode == 12) // greater
181 return testvalue > value;
182 else if (mode == 13) // greater or equal
183 return testvalue >= value;
184 else if (mode == 14) // equal
185 return testvalue == value;
186 else if (mode == 15) // not equal
187 return testvalue != value;
188 }
189 }
190 return false;
191}
192
193void ToLower(char* szText)
194{
195 if (!szText)
196 return;
197
198 if (!isUTF8)
199 {
200 for (int loop = 0; szText[loop] !=0; loop++)
201 szText[loop] = tolower(szText[loop]);
202 return;
203 }
204 else
205 {
206 int length = strlen(szText)+1;
207 uint* valueUtf8 = new uint[length];
208 int lengthUtf8 = Utf8ToArray(szText, valueUtf8, length);
209 for(int i=0; i<lengthUtf8; i++)
210 valueUtf8[i] = Utf8to(lower, valueUtf8[i])(cCharSetConv::SystemCharacterTable() ? tolower(valueUtf8[i])
: towlower(valueUtf8[i]))
;
211 Utf8FromArray(valueUtf8, szText, length);
212 delete [] valueUtf8;
213 }
214}
215
216char* GetExtEPGValue(const cEvent* e, cSearchExtCat* SearchExtCat)
217{
218 if (!e || !SearchExtCat)
219 return NULL__null;
220 return GetExtEPGValue(e->Description(), SearchExtCat->name, SearchExtCat->format);
221}
222
223char* GetExtEPGValue(const char* description, const char* catname, const char *format)
224{
225 if (isempty(description))
32
Taking false branch
226 return NULL__null;
227 char* tmp1 = NULL__null;
228 char* tmp2 = NULL__null;
229
230 // search the category, must be the first line or at the beginning of a line
231 if (msprintf(&tmp1, "\n%s: ", catname)==-1 ||
33
Taking false branch
232 msprintf(&tmp2, "%s: ", catname)==-1)
233 return NULL__null;
234 char* descr = strdup(description);
34
Null pointer passed as an argument to a 'nonnull' parameter
235 char* cat = NULL__null;
236 int valueOffset = 0;
237 if ((cat = strstr(descr, tmp1)) != NULL__null)
238 {
239 cat++; // skip linefeed
240 valueOffset = strlen(tmp1);
241 }
242 else if (strstr(descr, tmp2) == descr) // in first line
243 {
244 cat = descr;
245 valueOffset = strlen(tmp2)+1;
246 }
247 else
248 {
249 free(descr);
250 free(tmp1);
251 free(tmp2);
252 return NULL__null;
253 }
254
255 // search the value to appear before the next line feed or end
256 char* end = strchr(cat, '\n');
257 int endpos = strlen(cat);
258 if (end)
259 endpos = end - cat;
260 cat[endpos] = 0;
261
262 char* value = NULL__null;
263 msprintf(&value, "%s", cat + valueOffset - 1);
264 if (format)
265 {
266 int ivalue;
267 if (sscanf(value,"%8i",&ivalue)==1)
268 {
269 free(value);
270 value = NULL__null;
271 msprintf(&value, format, ivalue);
272 }
273 }
274 free(descr);
275 free(tmp1);
276 free(tmp2);
277
278 return value;
279}
280
281char* GetAuxValue(const char* aux, const char* name)
282{
283 if (isempty(aux))
284 return NULL__null;
285
286 char* descr = strdup(aux);
287 char* beginaux = strstr(descr, "<epgsearch>");
288 char* endaux = strstr(descr, "</epgsearch>");
289 if (!beginaux || !endaux) {
290 free(descr);
291 return NULL__null;
292 }
293
294 beginaux += 11; // strlen("<epgsearch>");
295 endaux[0] = 0;
296 memmove(descr, beginaux, endaux - beginaux + 1);
297
298 if (strcmp(name, "epgsearch") == 0)
299 return descr; // full aux
300
301 int namelen = strlen(name);
302 char catname[100] = "";
303 catname[0] = '<';
304 memcpy(catname + 1, name, namelen);
305 catname[1 + namelen] = '>';
306 catname[2 + namelen] = 0;
307
308 char* cat = strcasestr(descr, catname);
309 if (!cat) {
310 free(descr);
311 return NULL__null;
312 }
313
314 cat += namelen + 2;
315 char* end = strstr(cat, "</");
316 if (!end) {
317 free(descr);
318 return NULL__null;
319 }
320 end[0] = 0;
321
322 int catlen = end - cat + 1;
323 char* value = (char *) malloc(catlen);
324 memcpy(value, cat, catlen);
325
326 free(descr);
327 return value;
328}
329
330char* GetAuxValue(const cRecording *recording, const char* name)
331{
332 if (!recording || !recording->Info()) return NULL__null;
333 return GetAuxValue(recording->Info()->Aux(), name);
334}
335
336char* GetAuxValue(const cTimer *timer, const char* name)
337{
338 if (!timer || !timer->Aux()) return NULL__null;
339 return GetAuxValue(timer->Aux(), name);
340}
341
342string UpdateAuxValue(string aux, string section, long num)
343{
344 return UpdateAuxValue(aux, section, NumToString(num));
345}
346
347string UpdateAuxValue(string aux, string section, string value)
348{
349 string secStart = "<" + section + ">";
350 string secEnd = "</" + section + ">";
351 int valueStartPos = aux.find(secStart);
352 int valueEndPos = aux.find(secEnd);
353 if (valueStartPos >= 0 && valueEndPos >= 0)
354 aux.replace(valueStartPos + secStart.size(), valueEndPos - valueStartPos - secStart.size(), value);
355 else
356 aux += secStart + value + secEnd;
357 return aux;
358}
359
360// replace s1 with s2 in s ignoring the case of s1
361char *strreplacei(char *s, const char *s1, const char *s2)
362{
363 char *p = strcasestr(s, s1);
364 if (p) {
365 int of = p - s;
366 int l = strlen(s);
367 int l1 = strlen(s1);
368 int l2 = 0;
369 if (s2)
370 l2 = strlen(s2);
371 if (l2 > l1)
372 s = (char *)realloc(s, l + l2 - l1 + 1);
373 if (l2 != l1)
374 memmove(s + of + l2, s + of + l1, l - of - l1 + 1);
375 memcpy(s + of, s2, l2);
376 }
377 return s;
378}
379
380std::string strreplace(
381 std::string& result,
382 const std::string& replaceWhat,
383 const std::string& replaceWithWhat)
384{
385 while(1)
386 {
387 const int pos = result.find(replaceWhat);
388 if (pos==-1) break;
389 result.replace(pos,replaceWhat.size(),replaceWithWhat);
390 }
391 return result;
392}
393
394
395void sleepMSec(long ms)
396{
397 cCondWait::SleepMs(ms);
398}
399
400void sleepSec(long s)
401{
402 sleepMSec(s * 1000);
403}
404
405bool SendViaSVDRP(cString SVDRPcmd)
406{
407 bool bSuccess = true;
408 cString cmdbuf;
409 if (EPGSearchConfig.useExternalSVDRP)
410 {
411 cmdbuf = cString::sprintf("%s -p %d \"%s\"",
412 cSVDRPClient::SVDRPSendCmd,
413 EPGSearchConfig.SVDRPPort,
414 *SVDRPcmd);
415
416 FILE *p = popen(cmdbuf, "r");
417 if (p)
418 pclose(p);
419 else
420 {
421 LogFile.eSysLog("can't open pipe for command '%s'", *cmdbuf);
422 bSuccess = false;
423 }
424 }
425 else
426 {
427 cmdbuf = SVDRPcmd;
428 cSVDRPClient client;
429 if (!client.SendCmd(*cmdbuf))
430 {
431 LogFile.eSysLog("command '%s' failed", *cmdbuf);
432 bSuccess = false;
433 }
434 }
435
436 return bSuccess;
437}
438
439int SendMsg(cString Message, bool confirm, int seconds, eMessageType messageType)
440{
441 int Keys = Skins.QueueMessage(messageType, Message, seconds, confirm?seconds+2:0);
442 return Keys;
443}
444
445
446bool InEditMode(const char* ItemText, const char* ItemName, const char* ItemValue)
447{
448 bool bEditMode = true;
449 // ugly solution to detect, if in edit mode
450 char* value = strdup(ItemText);
451 strreplace(value, ItemName, "");
452 strreplace(value, ":\t", "");
453 // for bigpatch
454 strreplace(value, "\t", "");
455 if (strlen(value) == strlen(ItemValue))
456 bEditMode = false;
457 free(value);
458 return bEditMode;
459}
460
461// checks if the timer was triggered from a search timer and return a pointer to the search
462cSearchExt* TriggeredFromSearchTimer(const cTimer* timer)
463{
464 char* searchID = GetAuxValue(timer, "s-id");
465 if (!searchID)
466 return NULL__null;
467
468 cSearchExt* search = SearchExts.GetSearchFromID(atoi(searchID));
469 free(searchID);
470 return search;
471}
472
473int TriggeredFromSearchTimerID(const cTimer* timer)
474{
475 cSearchExt* trigger = TriggeredFromSearchTimer(timer);
476 if (trigger)
477 return trigger->ID;
478 else
479 return -1;
480}
481
482double FuzzyMatch(const char* s1, const char* s2, int maxLength)
483{
484 Distance D;
485 int dist = D.LD (s1, s2, maxLength);
486 double fMaxLength = max(strlen(s1), strlen(s2));
487 return (fMaxLength - dist)/fMaxLength;
488}
489
490bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit)
491{
492 if (eDescr == NULL__null && rDescr == NULL__null) return true;
493 if (eDescr == NULL__null && rDescr != NULL__null) return false;
494 if (eDescr != NULL__null && rDescr == NULL__null) return false;
495 int l_eDescr = strlen(eDescr);
496 int l_rDescr = strlen(rDescr);
497 if (l_eDescr == l_rDescr && strcmp(eDescr, rDescr) == 0) return true;
498
499 // partial match:
500 // first check the length, should only be different at match limit
501 int minLength = min(l_eDescr, l_rDescr);
502 int maxLength = max(l_eDescr, l_rDescr);
503 if (100*double(minLength)/double(maxLength) < matchLimit)
504 return false;
505
506 // last try with Levenshtein Distance, only compare the first 1000 chars
507 double fMatch = FuzzyMatch(eDescr, rDescr, 1000);
508 double tmp_matchlimit = matchLimit/100.0;
509 if(maxLength - minLength < 5 && matchLimit < 95)
510 {
511 tmp_matchlimit = 0.95;
512 LogFile.Log(2,"difference between both descriptions is < 5 setting matchlimit to: %.2f %%", tmp_matchlimit*100);
513 }
514 if (fMatch > tmp_matchlimit)
515 {
516 LogFile.Log(2,"match is: %.2f %%", fMatch*100);
517 return true;
518 }
519 return false;
520}
521
522const cEvent* GetEvent(cTimer* timer)
523{
524 const cEvent* event = NULL__null;
525 const cChannel *channel = timer->Channel();
526 time_t Time = timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2;
527 for (int seconds = 0; seconds <= 3; seconds++)
528 {
529 {
530 cSchedulesLock SchedulesLock;
531 const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
532 if (Schedules) {
533 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
534 if (Schedule) {
535 event = Schedule->GetEventAround(Time);
536 if (event) return event;
537 }
538 }
539 }
540 if (seconds == 0)
541 LogFile.Log(2,"waiting for EPG info...");
542 sleepSec(1);
543 }
544 LogFile.Log(1,"no EPG info available");
545 return NULL__null;
546}
547
548// this extracts the real description from a given epg entry cutting all that looks like a category line
549// we assume that a category has a name not longer than MAXCATNAMELENGTH and a value not longer than
550// MAXCATVALUELENGTH (so in most cases e.g. the 'cast' category will stay part of the description). name and
551// value are separated with ': '
552#define MAXCATNAMELENGTH40 40
553#define MAXCATVALUELENGTH60 60
554
555char* GetRawDescription(const char* descr)
556{
557 if (!descr || !*descr) return NULL__null;
558
559 char* rawDescr = (char*) calloc(strlen(descr)+1, sizeof(char));
560
561 const char* tmp = descr;
562 while(tmp)
563 {
564 // extract a single line
565 const char* lf = strchr(tmp, '\n');
566 char* line = NULL__null;
567 if (lf)
568 line = strndup(tmp, lf-tmp);
569 else
570 line = strdup(tmp);
571 // if (lf) *lf = 0;
572 // check for category
573 char* delim = strstr(line, ": ");
574 if (!delim ||
575 (delim && (delim - line > MAXCATNAMELENGTH40 || strlen(line) - (delim - line) + 2 > MAXCATVALUELENGTH60)))
576 if (*line)
577 strcat(rawDescr, line);
578
579 if (lf) tmp += strlen(line)+1; else tmp = NULL__null;
580 free(line);
581 }
582 return rawDescr;
583}
584
585void PrepareTimerFile(const cEvent* event, cTimer* timer)
586{
587 if (!event) return;
588 if (EPGSearchConfig.addSubtitleToTimer == addSubtitleNever && strlen(EPGSearchConfig.defrecdir) == 0) // nothing to do
589 return;
590 if (!isempty(event->ShortText())) // add subtitle if present
591 {
592 bool addSubtitle = (EPGSearchConfig.addSubtitleToTimer != addSubtitleNever);
593 if (EPGSearchConfig.addSubtitleToTimer == addSubtitleSmart)
594 if (event->Duration() > 80*60)
595 addSubtitle = false;
596
597 if (addSubtitle)
598 {
599 char tmp[MaxFileName255] = "";
600 snprintf(tmp, MaxFileName255, "%s~%s", event->Title(), event->ShortText());
601 timer->SetFile(tmp);
602 }
603 }
604 if (strlen(EPGSearchConfig.defrecdir) > 0)
605 {
606 char directory[MaxFileName255] = "";
607 strn0cpy(directory, EPGSearchConfig.defrecdir,sizeof(directory));
608 cVarExpr varExprDir(directory);
609 if (!varExprDir.DependsOnVar("%title%", event))
610 {
611 strcat(directory, "~");
612 strcat(directory, timer->File());
613 }
614 // parse the epxression and evaluate it
615 cVarExpr varExpr(directory);
616 strcpy(directory, varExpr.Evaluate(event).c_str());
617 if (strchr(directory, '%') == NULL__null) // only set directory to new value if all categories could have been replaced
618 timer->SetFile(directory);
619 }
620}
621
622bool EventsMatch(const cEvent* event1, const cEvent* event2, bool compareTitle, int compareSubtitle, bool compareSummary, int compareDate, unsigned long catvaluesAvoidRepeat, int matchLimit)
623{
624 if (!event1 || !event2) return false;
1
Assuming 'event1' is non-null
2
Assuming 'event2' is non-null
3
Taking false branch
625 if (event1 == event2) return true;
4
Assuming 'event1' is not equal to 'event2'
5
Taking false branch
626
627 // only compare the alphanumeric portions
628 string Title1 = "";
629 string Title2 = "";
630 if (compareTitle)
6
Assuming 'compareTitle' is 0
7
Taking false branch
631 {
632 string s1 = event1->Title()?event1->Title():"";
633 string s2 = event2->Title()?event2->Title():"";
634 Title1 = GetAlNum(s1);
635 Title2 = GetAlNum(s2);
636 std::transform(Title1.begin(), Title1.end(), Title1.begin(), tolower);
637 std::transform(Title2.begin(), Title2.end(), Title2.begin(), tolower);
638 }
639 string Subtitle1 = "";
640 string Subtitle2 = "";
641 if (compareSubtitle)
8
Assuming 'compareSubtitle' is 0
9
Taking false branch
642 {
643 string s1 = event1->ShortText()?event1->ShortText():"";
644 string s2 = event2->ShortText()?event2->ShortText():"";
645 Subtitle1 = GetAlNum(s1);
646 Subtitle2 = GetAlNum(s2);
647 std::transform(Subtitle1.begin(), Subtitle1.end(), Subtitle1.begin(), tolower);
648 std::transform(Subtitle2.begin(), Subtitle2.end(), Subtitle2.begin(), tolower);
649 }
650 string compareExpression = "";
651 if (compareDate == 1) compareExpression = "%date%";
10
Assuming 'compareDate' is not equal to 1
11
Taking false branch
652 if (compareDate == 2) compareExpression = "%year%-%week%";
12
Assuming 'compareDate' is not equal to 2
13
Taking false branch
653 if (compareDate == 3) compareExpression = "%year%-%month%";
14
Assuming 'compareDate' is not equal to 3
15
Taking false branch
654
655 bool match = false;
656 if ((!compareTitle || Title1 == Title2) &&
657 (!compareSubtitle || (Subtitle1 == Subtitle2 && Subtitle1!="")))
658 {
659 const char* Descr1 = event1->Description();
16
Calling 'cEvent::Description'
17
Returning from 'cEvent::Description'
18
'Descr1' initialized here
660 const char* Descr2 = event2->Description();
661 if (compareSummary)
19
Assuming 'compareSummary' is 0
20
Taking false branch
662 {
663 char* rawDescr1 = GetRawDescription(Descr1);
664 char* rawDescr2 = GetRawDescription(Descr2);
665 match = DescriptionMatches(rawDescr1, rawDescr2, matchLimit);
666 free(rawDescr1);
667 free(rawDescr2);
668 if (!match) return false;
669 }
670 if (compareExpression.size() > 0)
21
Taking false branch
671 {
672 cVarExpr varExpr(compareExpression);
673 string resEvent1 = varExpr.Evaluate(event1);
674 string resEvent2 = varExpr.Evaluate(event2);
675 if (resEvent1 != resEvent2)
676 return false;
677 }
678 if (catvaluesAvoidRepeat != 0) // check categories
22
Assuming 'catvaluesAvoidRepeat' is not equal to 0
23
Taking true branch
679 {
680 bool bCatMatch = ((Descr1 && Descr2) || (!Descr1 && !Descr2));
24
Assuming pointer value is null
25
Assuming 'Descr2' is null
681 cSearchExtCat *SearchExtCat = SearchExtCats.First();
682 int index = 0;
683 while (catvaluesAvoidRepeat > 0 && SearchExtCat && bCatMatch)
26
Loop condition is true. Entering loop body
28
Loop condition is true. Entering loop body
684 {
685 if (catvaluesAvoidRepeat & (1<<index))
27
Taking false branch
29
Taking true branch
686 {
687 char* CatValue1 = GetExtEPGValue(Descr1, SearchExtCat->name, SearchExtCat->format);
30
Passing null pointer value via 1st parameter 'description'
31
Calling 'GetExtEPGValue'
688 char* CatValue2 = GetExtEPGValue(Descr2, SearchExtCat->name, SearchExtCat->format);
689 if ((!CatValue1 && CatValue2) ||
690 (!CatValue2 && CatValue1) ||
691 (CatValue1 && CatValue2 && strcmp(CatValue1, CatValue2) != 0))
692 bCatMatch = false;
693 free(CatValue1);
694 free(CatValue2);
695 }
696 SearchExtCat = SearchExtCats.Next(SearchExtCat);
697 index++;
698 }
699 if (bCatMatch)
700 match = true;
701 }
702 else
703 match = true;
704 }
705 return match;
706}
707
708int ChannelNrFromEvent(const cEvent* pEvent)
709{
710 if (!pEvent)
711 return -1;
712 cChannel* channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true);
713 if (!channel)
714 return -1;
715 else
716 return channel->Number();
717}
718
719void DelTimer(int index)
720{
721 cString cmdbuf = cString::sprintf("DELT %d", index);
722 LogFile.Log(2, "delete timer %d", index);
723 SendViaSVDRP(cmdbuf);
724 gl_timerStatusMonitor->SetConflictCheckAdvised();
725}
726
727char* FixSeparators(char* buffer, char sep)
728{
729 int l = strlen(buffer);
730 char *dest = buffer;
731 for (int i = 0; i < l; i ++) {
732 char c = buffer[i];
733 int j = i;
734 if (c == sep) {
735 for (j = i + 1; (j < l) & (buffer[j] == ' '); j++)
736 ;
737
738 if ((j <= l) | (i + 1 < j)) {
739 switch (buffer[j]) {
740 case '\t':
741 i = j;
742 c = '\t';
743 break;
744 case 0:
745 i = j;
746 c = 0;
747 break;
748 default:
749 break;
750 }
751 }
752 }
753 if (c == '\t') {
754 for (; (j < l) & (buffer[j] == ' '); j++)
755 ;
756 if (j < l && buffer[j] == sep) {
757 buffer[j] = '\t';
758 i = j - 1;
759 continue;
760 }
761 }
762 *dest++ = c;
763 }
764 *dest = 0;
765 return buffer;
766}
767
768cString DateTime(time_t t)
769{
770 char buffer[32];
771 if (t == 0)
772 time(&t);
773 struct tm tm_r;
774 tm *tm = localtime_r(&t, &tm_r);
775 snprintf(buffer, sizeof(buffer), "%02d.%02d. %02d:%02d", tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
776 return buffer;
777}
778
779string NumToString(long num)
780{
781 ostringstream os;
782 os << num;
783 return os.str();
784}
785
786int FindIgnoreCase(const string& expr, const string& query)
787{
788 const char *p = expr.c_str();
789 const char *r = strcasestr(p, query.c_str());
790
791 if (!r)
792 return -1;
793 return r - p;
794}
795
796bool EqualsNoCase(const string& a, const string& b)
797{
798 return strcasecmp(a.c_str(), b.c_str()) == 0;
799}
800
801string Strip(const string& input)
802{
803 string str = input;
804 string::size_type pos = str.find_last_not_of(' ');
805 if(pos != string::npos) {
806 str.erase(pos + 1);
807 pos = str.find_first_not_of(' ');
808 if(pos != string::npos) str.erase(0, pos);
809 }
810 else str.erase(str.begin(), str.end());
811 return str;
812}
813
814string GetAlNum(const string& s)
815{
816 string res;
817 for(unsigned int i=0; i<s.size(); i++)
818 if (isalnum(s[i]))
819 res += s[i];
820 return res;
821}
822
823string ReplaceAll(const string& input, const string& what, const string& with)
824{
825 string result = input;
826 int pos = 0;
827
828 while((pos = FindIgnoreCase(result, what)) >= 0)
829 result.replace(pos, what.size(), with);
830 return result;
831}
832
833string EscapeString(const string& S)
834{
835 string tmp = S;
836 int apostrophPos = 0;
837 int apostrophTempPos = 0;
838 while((apostrophPos = tmp.find("'", apostrophTempPos)) >= apostrophTempPos) {
839 tmp.replace(apostrophPos, 1, "'\"'\"'");
840 apostrophTempPos = apostrophPos + 5;
841 }
842 return tmp;
843}
844
845string QuoteApostroph(const string& S)
846{
847 string tmp = S;
848 int apostrophPos = 0;
849 int apostrophTempPos = 0;
850 while((apostrophPos = tmp.find("\"", apostrophTempPos)) >= apostrophTempPos) {
851 tmp.replace(apostrophPos, 1, "\\\"");
852 apostrophTempPos = apostrophPos + 2;
853 }
854 return tmp;
855}
856
857string MD5(const string& input)
858{
859 char* szInput = strdup(input.c_str());
860 if (!szInput) return "";
861 char* szRes = MD5String(szInput);
862 string res = szRes;
863 free(szRes);
864 return res;
865}
866
867void SetAux(cTimer* timer, string aux)
868{
869 if (!timer) return;
870 string timerText = *timer->ToText();
871 string::size_type auxPos = string::npos;
872 for(int i=0; i<=7; i++) // get aux value
873 auxPos = timerText.find(":", auxPos == string::npos?0:auxPos+1);
874 if (auxPos == string::npos) return;
875 timerText.replace(auxPos+1, timerText.size()-auxPos+1, aux);
876 timer->Parse(timerText.c_str());
877}
878
879int msprintf(char **strp, const char *fmt, ...)
880{
881 va_list ap;
882 va_start (ap, fmt)__builtin_va_start(ap, fmt);
883 int res=vasprintf (strp, fmt, ap);
884 va_end (ap)__builtin_va_end(ap);
885 return res;
886}
887
888std::string GetCodeset()
889{
890 // Taken from VDR's vdr.c
891 char *CodeSet = NULL__null;
892 if (setlocale(LC_CTYPE0, ""))
893 CodeSet = nl_langinfo(CODESETCODESET);
894 else {
895 char *LangEnv = getenv("LANG"); // last resort in case locale stuff isn't installed
896 if (LangEnv) {
897 CodeSet = strchr(LangEnv, '.');
898 if (CodeSet)
899 CodeSet++; // skip the dot
900 }
901 }
902 if (CodeSet)
903 return std::string(CodeSet);
904 else
905 return "ISO-8859-15";
906}
907
908/* Read a line from a socket */
909ssize_t Readline(int sockd, char *vptr, size_t maxlen) {
910 size_t n, rc;
911 char c, *buffer;
912
913 buffer = vptr;
914
915 for ( n = 1; n < maxlen; n++ ) {
916
917 if ( (rc = read(sockd, &c, 1)) == 1 ) {
918 if ( c == '\n' )
919 break;
920 *buffer++ = c;
921 }
922 else if ( rc == 0 ) {
923 if ( n == 1 )
924 return 0;
925 else
926 break;
927 }
928 else {
929 if ( errno(*__errno_location ()) == EINTR4 )
930 continue;
931 return -1;
932 }
933 }
934
935 *buffer = 0;
936 return n;
937}
938
939/* Write a line to a socket */
940ssize_t Writeline(int sockd, const char *vptr, ssize_t n) {
941 ssize_t nleft;
942 ssize_t nwritten;
943 const char *buffer;
944
945 buffer = vptr;
946 nleft = n;
947
948 while ( nleft > 0 ) {
949 if ( (nwritten = write(sockd, buffer, nleft)) <= 0 ) {
950 if ( errno(*__errno_location ()) == EINTR4 )
951 nwritten = 0;
952 else
953 return -1;
954 }
955 nleft -= nwritten;
956 buffer += nwritten;
957 }
958
959 return n;
960}
961
962long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr)
963{
964 unsigned long ip;
965
966 struct hostent * he;
967
968 if(hostnameOrIp==NULL__null || addr==NULL__null)
969 return -1;
970
971 ip=inet_addr(hostnameOrIp);
972
973 if(ip!=INADDR_NONE((in_addr_t) 0xffffffff))
974 {
975 addr->sin_addr.s_addr=ip;
976 return 0;
977 }
978 else
979 {
980 he=gethostbyname(hostnameOrIp);
981 if(he==NULL__null)
982 return -1;
983 else
984 memcpy(&(addr->sin_addr),he->h_addr_list[0],4);
985 return 0;
986 }
987}
988
989#if VDRVERSNUM20005 >= 10712
990char *cCommand::result = NULL__null;
991
992cCommand::cCommand(void)
993{
994 title = command = NULL__null;
995 confirm = false;
996}
997
998cCommand::~cCommand()
999{
1000 free(title);
1001 free(command);
1002}
1003
1004bool cCommand::Parse(const char *s)
1005{
1006 const char *p = strchr(s, ':');
1007 if (p) {
1008 int l = p - s;
1009 if (l > 0) {
1010 title = MALLOC(char, l + 1)(char *)malloc(sizeof(char) * (l + 1));
1011 stripspace(strn0cpy(title, s, l + 1));
1012 if (!isempty(title)) {
1013 int l = strlen(title);
1014 if (l > 1 && title[l - 1] == '?') {
1015 confirm = true;
1016 title[l - 1] = 0;
1017 }
1018 command = stripspace(strdup(skipspace(p + 1)));
1019 return !isempty(command);
1020 }
1021 }
1022 }
1023 return false;
1024}
1025
1026const char *cCommand::Execute(const char *Parameters)
1027{
1028 free(result);
1029 result = NULL__null;
1030 cString cmdbuf;
1031 if (Parameters)
1032 cmdbuf = cString::sprintf("%s %s", command, Parameters);
1033 const char *cmd = *cmdbuf ? *cmdbuf : command;
1034 dsyslog("executing command '%s'", cmd)void( (SysLogLevel > 2) ? syslog_with_tid(3, "executing command '%s'"
, cmd) : void() )
;
1035 cPipe p;
1036 if (p.Open(cmd, "r")) {
1037 int l = 0;
1038 int c;
1039 while ((c = fgetc(p)) != EOF(-1)) {
1040 if (l % 20 == 0)
1041 result = (char *)realloc(result, l + 21);
1042 result[l++] = char(c);
1043 }
1044 if (result)
1045 result[l] = 0;
1046 p.Close();
1047 }
1048 else
1049 esyslog("ERROR: can't open pipe for command '%s'", cmd)void( (SysLogLevel > 0) ? syslog_with_tid(3, "ERROR: can't open pipe for command '%s'"
, cmd) : void() )
;
1050 return result;
1051}
1052#endif