Bug Summary

File:templatefile.c
Location:line 68, column 18
Description:Potential memory leak

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 <set>
25#include "templatefile.h"
26#include "epgsearchcfg.h"
27#include "epgsearchtools.h"
28
29std::set<cMenuTemplate*> cTemplFile::menuTemplates;
30char** cTemplFile::SearchTemplates = NULL__null;
31
32bool cMenuTemplate::PrepareTemplate(const char* templateLine)
33{
34 if (!templateLine || strlen(templateLine) == 0) return true;
16
Taking false branch
35
36 char *pstrSearchToken, *pptr;
37 char *pstrSearch=strdup(templateLine);
38 pstrSearchToken=strtok_r(pstrSearch, "|", &pptr);
39 cString stripped;
40 int iToken = 0;
41 while(pstrSearchToken)
17
Loop condition is true. Entering loop body
42 {
43 char* tmp = strchr(pstrSearchToken,':');
44 if (tmp)
18
Assuming 'tmp' is non-null
19
Taking true branch
45 {
46 int tabWidth = atoi(tmp+1);
47 if (tabWidth == 0)
20
Assuming 'tabWidth' is not equal to 0
21
Taking false branch
48 {
49 LogFile.eSysLog("warning - tab width in \"%s\" is 0, set to min value 1!", Name());
50 tabWidth = 1;
51 }
52 menuTabs[iToken++] = tabWidth;
53 }
54 else
55 {
56 free(pstrSearch);
57 LogFile.eSysLog("error parsing entry \"%s\", falling back to default entries.", Name());
58 return false;
59 }
60 *tmp = 0;
61 if (isempty(stripped))
22
Taking true branch
62 stripped = strdup(pstrSearchToken);
23
Memory is allocated
63 else
64 {
65 cString tmp = stripped;
66 stripped = cString::sprintf("%s|%s", *tmp, pstrSearchToken);
67 }
68 pstrSearchToken=strtok_r(NULL__null, "|", &pptr);
24
Potential memory leak
69 }
70 free(pstrSearch);
71
72 // no limit for the last column
73 if (iToken>0) menuTabs[iToken-1] = 0;
74
75 if (!isempty(stripped))
76 {
77 menuTemplate = strdup(stripped);
78 // the status variables are handled in menu_whatson.c itself
79 // to speedup the var-parser we 'hide' them here in renaming them
80 menuTemplate = strreplacei(menuTemplate, "%status%", "$status$");
81 menuTemplate = strreplacei(menuTemplate, "%t_status%", "$t_status$");
82 menuTemplate = strreplacei(menuTemplate, "%v_status%", "$v_status$");
83 menuTemplate = strreplacei(menuTemplate, "%r_status%", "$r_status$");
84 }
85 return true;
86}
87
88cTemplLine::cTemplLine(void)
89{
90 name = value = NULL__null;
91}
92
93cTemplLine::cTemplLine(const char *Name, const char *Value)
94{
95 name = strdup(Name);
96 value = strdup(Value);
97}
98
99cTemplLine::~cTemplLine()
100{
101 free(name);
102 free(value);
103}
104
105bool cTemplLine::Parse(char *s)
106{
107 if (!s) return false;
108 if (s[0] == '#')
109 return true;
110 char *p = strchr(s, '=');
111 if (p)
112 {
113 *p = 0;
114 char *Name = compactspace(s);
115 char *Value = compactspace(p + 1);
116 if (*Name)
117 {
118 name = strdup(Name);
119 value = strdup(Value);
120 return true;
121 }
122 }
123 return false;
124}
125
126cTemplFile::cTemplFile()
127{
128 Reset();
129}
130
131void cTemplFile::Reset()
132{
133 std::set<cMenuTemplate*>::iterator it;
134 for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it)
135 delete (*it);
136 menuTemplates.clear();
137}
138
139cMenuTemplate* cTemplFile::GetTemplateByName(const char* Name)
140{
141 std::set<cMenuTemplate*>::iterator it;
142 for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it)
143 if (!strcasecmp(Name, (*it)->Name())) return (*it);
144 return NULL__null;
145}
146
147bool cTemplFile::Load(const char *FileName)
148{
149 // auto-enable WarEagle-Icons if VDRSymbols font is used
150 if (strstr(Setup.FontOsd, "VDRSymbols") == Setup.FontOsd)
151 EPGSearchConfig.WarEagle = 1;
152
153 if (cConfig<cTemplLine>::Load(FileName, true))
154 {
155 bool result = true;
156 for (cTemplLine *l = First(); l; l = Next(l))
157 {
158 bool error = false;
159 if (!Parse(l->Name(), l->Value()))
160 error = true;
161 if (error)
162 {
163 result = false;
164 }
165 }
166 return result;
167 }
168 return false;
169}
170
171bool cTemplFile::Parse(const char *Name, const char *Value)
172{
173 if (Name && Name[0] == '#') return true;
174 if (!strcasecmp(Name, "WarEagleIcons"))
175 {
176 EPGSearchConfig.WarEagle = atoi(Value);
177 return true;
178 }
179
180 if (!strcasecmp(Name, "MenuWhatsOnNow") ||
181 !strcasecmp(Name, "MenuWhatsOnNext") ||
182 !strcasecmp(Name, "MenuWhatsOnElse") ||
183 !strcasecmp(Name, "MenuSchedule") ||
184 !strncasecmp(Name, "MenuSearchResults", strlen("MenuSearchResults")) ||
185 !strcasecmp(Name, "MenuFavorites"))
186 {
187 cMenuTemplate* menuTemplate = new cMenuTemplate(Name);
188 if (menuTemplate->PrepareTemplate(Value))
189 {
190 LogFile.Log(3, "loaded menu template: %s", Name);
191 cMenuTemplate* TemplOld = GetTemplateByName(Name);
192 if (TemplOld)
193 {
194 LogFile.Log(1, "menu template '%s' gets overwritten", Name);
195 menuTemplates.erase(TemplOld);
196 delete TemplOld;
197 }
198 menuTemplates.insert(menuTemplate);
199 return true;
200 }
201 }
202 else
203 {
204 LogFile.eSysLog("ERROR: unknown parameter: %s = %s", Name, Value);
205 return false;
206 }
207 return true;
208}
209
210void cTemplFile::PrepareDefaultTemplates()
211{
212 char channelnr[20] = "";
213 sprintf(channelnr, "%%chnr%%:%d|", CHNUMWIDTH(numdigits(Channels.MaxNumber()) + 2));
214
215 bool text2skin = !(strcmp(Setup.OSDSkin, "soppalusikka") == 0 ||
216 strcmp(Setup.OSDSkin, "classic") == 0 ||
217 strcmp(Setup.OSDSkin, "sttng") == 0);
218
219 char menutemplate[MAXTEMPLLEN2000] = "";
220 // What's on now
221 cMenuTemplate* WhatsOnNow = GetTemplateByName("MenuWhatsOnNow");
222 if (!WhatsOnNow)
1
Taking true branch
223 {
224 WhatsOnNow = new cMenuTemplate("MenuWhatsOnNow");
225 menuTemplates.insert(WhatsOnNow);
226 }
227 if (WhatsOnNow && WhatsOnNow->MenuTemplate() == 0)
2
Taking false branch
228 {
229 sprintf(menutemplate, "%s%%chsh%%:12|%%time%%:6|%s%s$status$:3|%%title%% ~ %%subtitle%%:30",
230 EPGSearchConfig.showChannelNr?channelnr:"",
231 EPGSearchConfig.showProgress==0?"":(EPGSearchConfig.showProgress==1?"%progrT2S%:4|":"%progr%:5|"),
232 text2skin?" ":"");
233 WhatsOnNow->PrepareTemplate(menutemplate);
234 }
235
236 // What's on next and else
237 sprintf(menutemplate, "%s%%chsh%%:12|%%time%%:7|$status$:4|%%title%% ~ %%subtitle%%:30",
238 EPGSearchConfig.showChannelNr?channelnr:"");
3
'?' condition is false
239 cMenuTemplate* WhatsOnNext = GetTemplateByName("MenuWhatsOnNext");
240 if (!WhatsOnNext)
4
Taking true branch
241 {
242 WhatsOnNext = new cMenuTemplate("MenuWhatsOnNext");
243 menuTemplates.insert(WhatsOnNext);
244 }
245 if (WhatsOnNext && WhatsOnNext->MenuTemplate() == 0)
5
Taking false branch
246 WhatsOnNext->PrepareTemplate(menutemplate);
247 cMenuTemplate* WhatsOnElse = GetTemplateByName("MenuWhatsOnElse");
248 if (!WhatsOnElse)
6
Taking true branch
249 {
250 WhatsOnElse = new cMenuTemplate("MenuWhatsOnElse");
251 menuTemplates.insert(WhatsOnElse);
252 }
253 if (WhatsOnElse && WhatsOnElse->MenuTemplate() == 0)
7
Taking false branch
254 WhatsOnElse->PrepareTemplate(menutemplate);
255
256 // Schedule
257 cMenuTemplate* Schedule = GetTemplateByName("MenuSchedule");
258 if (!Schedule)
8
Taking true branch
259 {
260 Schedule = new cMenuTemplate("MenuSchedule");
261 menuTemplates.insert(Schedule);
262 }
263 if (Schedule && Schedule->MenuTemplate() == 0)
9
Taking false branch
264 {
265 strcpy(menutemplate, "%time_w% %time_d%:7|%time%:6|$status$:4|%title% ~ %subtitle%:30");
266 Schedule->PrepareTemplate(menutemplate);
267 }
268
269 // Search results
270 cMenuTemplate* SearchResults = GetTemplateByName("MenuSearchResults");
271 if (!SearchResults)
10
Taking true branch
272 {
273 SearchResults = new cMenuTemplate("MenuSearchResults");
274 menuTemplates.insert(SearchResults);
275 }
276 if (SearchResults && SearchResults->MenuTemplate() == 0)
277 {
278 sprintf(menutemplate, "%s%%chsh%%:12|%%datesh%%:6|%%time%%:6|$status$:3|%%title%% ~ %%subtitle%%:30",
279 EPGSearchConfig.showChannelNr?channelnr:"");
280 SearchResults->PrepareTemplate(menutemplate);
281 }
282
283 // Favorites
284 cMenuTemplate* Favorites = GetTemplateByName("MenuFavorites");
285 if (!Favorites)
11
Assuming 'Favorites' is null
12
Taking true branch
286 {
287 Favorites = new cMenuTemplate("MenuFavorites");
288 menuTemplates.insert(Favorites);
289 }
290 if (Favorites && Favorites->MenuTemplate() == 0)
13
Taking true branch
291 {
292 sprintf(menutemplate, "%s%%chsh%%:12|%%time%%:6|%%timespan%%:7|$status$:3|%%title%% ~ %%subtitle%%:30",
293 EPGSearchConfig.showChannelNr?channelnr:"");
14
'?' condition is false
294 Favorites->PrepareTemplate(menutemplate);
15
Calling 'cMenuTemplate::PrepareTemplate'
295 }
296
297 // create an array of all search template names
298 if (SearchTemplates)
299 delete [] SearchTemplates;
300 SearchTemplates = new char*[CountSearchResultsTemplates()];
301 std::set<cMenuTemplate*>::iterator it;
302 int Count = 0;
303 for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it)
304 if (!strncasecmp("MenuSearchResults", (*it)->Name(), strlen("MenuSearchResults")))
305 {
306 char* templateName = strdup((*it)->Name() + strlen("MenuSearchResults"));
307 if (*templateName == 0) templateName = strdup(tr("Standard")I18nTranslate("Standard", "vdr-" "epgsearch"));
308 SearchTemplates[Count++] = templateName;
309 }
310}
311
312int cTemplFile::CountSearchResultsTemplates()
313{
314 int Count = 0;
315 std::set<cMenuTemplate*>::iterator it;
316 for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it)
317 if (!strncasecmp("MenuSearchResults", (*it)->Name(), strlen("MenuSearchResults"))) Count++;
318 return Count;
319}
320
321cMenuTemplate* cTemplFile::GetSearchTemplateByPos(int iPos)
322{
323 int Count = 0;
324 std::set<cMenuTemplate*>::iterator it;
325 for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it)
326 if (!strncasecmp("MenuSearchResults", (*it)->Name(), strlen("MenuSearchResults")))
327 if(Count++ == iPos)
328 return (*it);
329 return NULL__null;
330}