Bug Summary

File:menu_search.c
Location:line 99, column 1
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 <vector>
25#include <string>
26#include <iomanip>
27#include <sstream>
28
29#include "menu_search.h"
30#include "epgsearchtools.h"
31#include "epgsearchcfg.h"
32#include "recdone.h"
33#include "menu_searchedit.h"
34#include "menu_searchactions.h"
35#include "timerdone.h"
36
37using namespace std;
38
39// --- cMenuSearchExtItem ----------------------------------------------------------
40class cMenuSearchExtItem : public cOsdItem {
41 private:
42public:
43 cSearchExt* searchExt;
44 cMenuSearchExtItem(cSearchExt* SearchExt);
45 int Compare(const cListObject &ListObject) const;
46 void Set(void);
47 };
48
49cMenuSearchExtItem::cMenuSearchExtItem(cSearchExt* SearchExt)
50{
51 searchExt = SearchExt;
52 Set();
1
Calling 'cMenuSearchExtItem::Set'
53}
54
55void cMenuSearchExtItem::Set(void)
56{
57 ostringstream line;
58
59 if (searchExt->useAsSearchTimer)
2
Taking false branch
60 {
61 if (searchExt->IsActiveAt(time(NULL__null)))
62 line << ">";
63 else
64 line << "!";
65 }
66
67 line << "\t";
68 if (searchExt->search && strlen(searchExt->search) > 0)
3
Taking false branch
69 line << setiosflags(ios::left) << string(searchExt->search);
70 else
71 line << setiosflags(ios::left) << "*";
72
73 line << "\t";
74 if (searchExt->useChannel == 1)
4
Taking false branch
75 {
76 if (searchExt->channelMin != searchExt->channelMax)
77 line << setiosflags(ios::left) << searchExt->channelMin->Number() << " - " << searchExt->channelMax->Number();
78 else
79 line << setiosflags(ios::left) << setw(11) << (searchExt->useChannel?CHANNELNAME(searchExt->channelMin)(searchExt->channelMin ? searchExt->channelMin->ShortName
(true) : "")
:"");
80 }
81 else if (searchExt->useChannel == 2)
5
Taking false branch
82 line << setiosflags(ios::left) << setw(11) << searchExt->channelGroup;
83 else
84 line << " ";
85
86 line << "\t";
87 if (searchExt->useTime)
6
Taking false branch
88 {
89 ostringstream timeline;
90 timeline << setfill('0') << setw(2) << searchExt->startTime / 100 << ":" << setw(2) << searchExt->startTime % 100;
91 timeline << "\t";
92 timeline << setfill('0') << setw(2) << searchExt->stopTime / 100 << ":" << setw(2) << searchExt->stopTime % 100;
93 line << timeline.str();
94 }
95 else
96 line << "--:--\t--:--";
97
98 SetText(strdup(line.str().c_str()), false);
7
Memory is allocated
99}
8
Potential memory leak
100
101int cMenuSearchExtItem::Compare(const cListObject &ListObject) const
102{
103 cMenuSearchExtItem *p = (cMenuSearchExtItem *)&ListObject;
104 return strcasecmp(searchExt->search, p->searchExt->search);
105}
106
107// --- cMenuEPGSearchExt ----------------------------------------------------------
108cMenuEPGSearchExt::cMenuEPGSearchExt()
109:cOsdMenu("", 2, 20, 11, 6, 5)
110{
111#if VDRVERSNUM20005 >= 10728
112 SetMenuCategory(mcPlugin);
113#endif
114 cMutexLock SearchExtsLock(&SearchExts);
115 cSearchExt *SearchExt = SearchExts.First();
116 while (SearchExt) {
117 Add(new cMenuSearchExtItem(SearchExt));
118 SearchExt = SearchExts.Next(SearchExt);
119 }
120
121 UpdateTitle();
122 SetHelp(trVDR("Button$Edit")I18nTranslate("Button$Edit"), trVDR("Button$New")I18nTranslate("Button$New"), trVDR("Button$Delete")I18nTranslate("Button$Delete"), tr("Button$Actions")I18nTranslate("Button$Actions", "vdr-" "epgsearch"));
123 Sort();
124}
125
126void cMenuEPGSearchExt::UpdateTitle()
127{
128 int total=0, active=0;
129 cMutexLock SearchExtsLock(&SearchExts);
130 cSearchExt *SearchExt = SearchExts.First();
131 while (SearchExt) {
132 if (SearchExt->useAsSearchTimer) active++;
133 SearchExt = SearchExts.Next(SearchExt);
134 total++;
135 }
136
137 cString buffer = cString::sprintf("%s (%d/%d %s)", tr("Search entries")I18nTranslate("Search entries", "vdr-" "epgsearch"), active, total, tr("active")I18nTranslate("active", "vdr-" "epgsearch"));
138 SetTitle(buffer);
139 Display();
140}
141
142cSearchExt *cMenuEPGSearchExt::CurrentSearchExt(void)
143{
144 cMenuSearchExtItem *item = (cMenuSearchExtItem *)Get(Current());
145 if (item && SearchExts.Exists(item->searchExt))
146 return item->searchExt;
147 return NULL__null;
148}
149
150
151eOSState cMenuEPGSearchExt::New(void)
152{
153 if (HasSubMenu())
154 return osContinue;
155 return AddSubMenu(new cMenuEditSearchExt(new cSearchExt, true));
156}
157
158eOSState cMenuEPGSearchExt::Delete(void)
159{
160 cSearchExt *curSearchExt = CurrentSearchExt();
161 if (curSearchExt) {
162 if (Interface->Confirm(tr("Edit$Delete search?")I18nTranslate("Edit$Delete search?", "vdr-" "epgsearch"))) {
163 int DelID = curSearchExt->ID;
164 if (Interface->Confirm(tr("Delete all timers created from this search?")I18nTranslate("Delete all timers created from this search?", "vdr-"
"epgsearch")
))
165 curSearchExt->DeleteAllTimers();
166 LogFile.Log(1,"search timer %s (%d) deleted", curSearchExt->search, curSearchExt->ID);
167 cMutexLock SearchExtsLock(&SearchExts);
168 SearchExts.Del(curSearchExt);
169 SearchExts.Save();
170 RecsDone.RemoveSearchID(DelID);
171 TimersDone.RemoveEntriesOfSearch(DelID);
172 cOsdMenu::Del(Current());
173 Display();
174 UpdateTitle();
175 }
176 }
177 return osContinue;
178}
179
180eOSState cMenuEPGSearchExt::Actions(eKeys Key)
181{
182 if (HasSubMenu() || Count() == 0)
183 return osContinue;
184 cSearchExt* search = CurrentSearchExt();
185
186 cMenuSearchActions *menu;
187 eOSState state = AddSubMenu(menu = new cMenuSearchActions(search, true));
188 if (Key != kNone)
189 state = menu->ProcessKey(Key);
190 return state;
191}
192
193
194eOSState cMenuEPGSearchExt::ProcessKey(eKeys Key)
195{
196 int SearchNumber = HasSubMenu() ? Count() : -1;
197 eOSState state = cOsdMenu::ProcessKey(Key);
198 if (state == osUnknown) {
199 switch (Key) {
200 case k0:
201 if (HasSubMenu())
202 return osContinue;
203 if (CurrentSearchExt())
204 state = AddSubMenu(new cMenuSearchActions(CurrentSearchExt()));
205 else
206 state = osContinue;
207 break;
208 case k1...k9:
209 return Actions(Key);
210 case kOk:
211 state = Actions(k1);
212 case kBlue:
213 if (HasSubMenu())
214 return osContinue;
215 state = AddSubMenu(new cMenuSearchActions(CurrentSearchExt()));
216 break;
217 case kRed:
218 if (HasSubMenu())
219 return osContinue;
220 if (CurrentSearchExt())
221 state = AddSubMenu(new cMenuEditSearchExt(CurrentSearchExt()));
222 else
223 state = osContinue;
224 break;
225 case kGreen: state = New(); break;
226 case kYellow: state = Delete(); break;
227 default: break;
228 }
229 }
230 if (SearchNumber >= 0 && !HasSubMenu())
231 {
232 cMutexLock SearchExtsLock(&SearchExts);
233 cSearchExt* search = SearchExts.Get(SearchNumber);
234 if (search) // a newly created search was confirmed with Ok
235 Add(new cMenuSearchExtItem(search));
236 else
237 search = CurrentSearchExt();
238 // always update all entries, since channel group names may have changed and affect other searches
239 Sort();
240 for(int i=0; i<Count(); i++)
241 {
242 cMenuSearchExtItem *item = (cMenuSearchExtItem *)Get(i);
243 if (item)
244 {
245 item->Set();
246 if (item->searchExt == search)
247 SetCurrent(item);
248 }
249 }
250 Display();
251 UpdateTitle();
252 }
253
254 return state;
255}