source: filezilla/trunk/fuentes/src/interface/sitemanager.cpp @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

File size: 19.6 KB
Line 
1        #include <filezilla.h>
2#include "sitemanager.h"
3
4#include "filezillaapp.h"
5#include "ipcmutex.h"
6#include "Options.h"
7#include "xmlfunctions.h"
8
9std::map<int, std::unique_ptr<CSiteManagerItemData_Site>> CSiteManager::m_idMap;
10
11bool CSiteManager::Load(CSiteManagerXmlHandler& handler)
12{
13        CXmlFile file(wxGetApp().GetSettingsFile(_T("sitemanager")));
14        auto document = file.Load();
15        if (!document) {
16                wxMessageBoxEx(file.GetError(), _("Error loading xml file"), wxICON_ERROR);
17                return false;
18        }
19
20        auto element = document.child("Servers");
21        if (!element) {
22                return false;
23        }
24
25        return Load(element, handler);
26}
27
28bool CSiteManager::Load(pugi::xml_node element, CSiteManagerXmlHandler& handler)
29{
30        wxASSERT(element);
31
32        for (auto child = element.first_child(); child; child = child.next_sibling()) {
33                if (!strcmp(child.name(), "Folder")) {
34                        wxString name = GetTextElement_Trimmed(child);
35                        if (name.empty())
36                                continue;
37
38                        const bool expand = GetTextAttribute(child, "expanded") != _T("0");
39                        if (!handler.AddFolder(name, expand))
40                                return false;
41                        Load(child, handler);
42                        if (!handler.LevelUp())
43                                return false;
44                }
45                else if (!strcmp(child.name(), "Server")) {
46                        std::unique_ptr<CSiteManagerItemData_Site> data = ReadServerElement(child);
47
48                        if (data) {
49                                handler.AddSite(std::move(data));
50
51                                // Bookmarks
52                                for (auto bookmark = child.child("Bookmark"); bookmark; bookmark = bookmark.next_sibling("Bookmark")) {
53                                        wxString name = GetTextElement_Trimmed(bookmark, "Name");
54                                        if (name.empty())
55                                                continue;
56
57                                        auto bookmarkData = std::make_unique<CSiteManagerItemData>(CSiteManagerItemData::BOOKMARK);
58
59                                        bookmarkData->m_localDir = GetTextElement(bookmark, "LocalDir");
60                                        bookmarkData->m_remoteDir.SetSafePath(GetTextElement(bookmark, "RemoteDir"));
61                                        if (bookmarkData->m_localDir.empty() && bookmarkData->m_remoteDir.empty()) {
62                                                continue;
63                                        }
64
65                                        if (!bookmarkData->m_localDir.empty() && !bookmarkData->m_remoteDir.empty())
66                                                bookmarkData->m_sync = GetTextElementBool(bookmark, "SyncBrowsing", false);
67
68                                        bookmarkData->m_comparison = GetTextElementBool(bookmark, "DirectoryComparison", false);
69
70                                        handler.AddBookmark(name, std::move(bookmarkData));
71                                }
72
73                                if (!handler.LevelUp())
74                                        return false;
75                        }
76                }
77        }
78
79        return true;
80}
81
82std::unique_ptr<CSiteManagerItemData_Site> CSiteManager::ReadServerElement(pugi::xml_node element)
83{
84        CServer server;
85        if (!::GetServer(element, server))
86                return 0;
87        if (server.GetName().empty())
88                return 0;
89
90        auto data = std::make_unique<CSiteManagerItemData_Site>(server);
91        data->m_comments = GetTextElement(element, "Comments");
92        data->m_localDir = GetTextElement(element, "LocalDir");
93        data->m_remoteDir.SetSafePath(GetTextElement(element, "RemoteDir"));
94
95        if (!data->m_localDir.empty() && !data->m_remoteDir.empty())
96                data->m_sync = GetTextElementBool(element, "SyncBrowsing", false);
97
98        data->m_comparison = GetTextElementBool(element, "DirectoryComparison", false);
99
100        return data;
101}
102
103class CSiteManagerXmlHandler_Menu : public CSiteManagerXmlHandler
104{
105public:
106        CSiteManagerXmlHandler_Menu(wxMenu* pMenu, std::map<int, std::unique_ptr<CSiteManagerItemData_Site>> *idMap, bool predefined)
107                : m_pMenu(pMenu), m_idMap(idMap)
108        {
109                m_added_site = false;
110
111                if (predefined)
112                        path = _T("1");
113                else
114                        path = _T("0");
115        }
116
117        unsigned int GetInsertIndex(wxMenu* pMenu, const wxString& name)
118        {
119                unsigned int i;
120                for (i = 0; i < pMenu->GetMenuItemCount(); ++i)
121                {
122                        const wxMenuItem* const pItem = pMenu->FindItemByPosition(i);
123                        if (!pItem)
124                                continue;
125
126                        // Use same sorting as site tree in site manager
127#ifdef __WXMSW__
128                        if (pItem->GetItemLabelText().CmpNoCase(name) > 0)
129                                break;
130#else
131                        if (pItem->GetItemLabelText() > name)
132                                break;
133#endif
134                }
135
136                return i;
137        }
138
139        virtual bool AddFolder(const wxString& name, bool)
140        {
141                m_parents.push_back(m_pMenu);
142                m_childNames.push_back(name);
143                m_paths.push_back(path);
144                path += _T("/") + CSiteManager::EscapeSegment(name);
145
146                m_pMenu = new wxMenu;
147
148                return true;
149        }
150
151        virtual bool AddSite(std::unique_ptr<CSiteManagerItemData_Site> data)
152        {
153                wxString newName(data->m_server.GetName());
154                int i = GetInsertIndex(m_pMenu, newName);
155                newName.Replace(_T("&"), _T("&&"));
156                wxMenuItem* pItem = m_pMenu->Insert(i, wxID_ANY, newName);
157
158                data->m_path = path + _T("/") + CSiteManager::EscapeSegment(data->m_server.GetName());
159
160                (*m_idMap)[pItem->GetId()] = std::move(data);
161
162                m_added_site = true;
163
164                return true;
165        }
166
167        virtual bool AddBookmark(const wxString& name, std::unique_ptr<CSiteManagerItemData> data)
168        {
169                return true;
170        }
171
172        // Go up a level
173        virtual bool LevelUp()
174        {
175                if (m_added_site)
176                {
177                        m_added_site = false;
178                        return true;
179                }
180
181                if (m_parents.empty() || m_childNames.empty())
182                        return false;
183
184                wxMenu* pChild = m_pMenu;
185                m_pMenu = m_parents.back();
186                if (pChild->GetMenuItemCount())
187                {
188                        wxString name = m_childNames.back();
189                        int i = GetInsertIndex(m_pMenu, name);
190                        name.Replace(_T("&"), _T("&&"));
191
192                        wxMenuItem* pItem = new wxMenuItem(m_pMenu, wxID_ANY, name, _T(""), wxITEM_NORMAL, pChild);
193                        m_pMenu->Insert(i, pItem);
194                }
195                else
196                        delete pChild;
197                m_childNames.pop_back();
198                m_parents.pop_back();
199
200                path = m_paths.back();
201                m_paths.pop_back();
202
203                return true;
204        }
205
206protected:
207        wxMenu* m_pMenu;
208
209        std::map<int, std::unique_ptr<CSiteManagerItemData_Site>> *m_idMap;
210
211        std::list<wxMenu*> m_parents;
212        std::list<wxString> m_childNames;
213
214        bool m_added_site;
215
216        wxString path;
217        std::list<wxString> m_paths;
218};
219
220
221class CSiteManagerXmlHandler_Stats : public CSiteManagerXmlHandler
222{
223public:
224        virtual bool AddFolder(const wxString& name, bool)
225        {
226                ++directories_;
227                return true;
228        }
229
230        virtual bool AddSite(std::unique_ptr<CSiteManagerItemData_Site> data)
231        {
232                ++sites_;
233                return true;
234        }
235
236        virtual bool AddBookmark(const wxString& name, std::unique_ptr<CSiteManagerItemData> data)
237        {
238                ++bookmarks_;
239                return true;
240        }
241
242        unsigned int sites_{};
243        unsigned int directories_{};
244        unsigned int bookmarks_{};
245};
246
247std::unique_ptr<wxMenu> CSiteManager::GetSitesMenu()
248{
249        ClearIdMap();
250
251        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
252        // to the same file or one is reading while the other one writes.
253        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
254
255        auto predefinedSites = GetSitesMenu_Predefined(m_idMap);
256
257        auto pMenu = std::make_unique<wxMenu>();
258        CSiteManagerXmlHandler_Menu handler(pMenu.get(), &m_idMap, false);
259
260        bool res = Load(handler);
261        if (!res || !pMenu->GetMenuItemCount()) {
262                pMenu.reset();
263        }
264
265        if (pMenu) {
266                if (!predefinedSites)
267                        return pMenu;
268
269                auto pRootMenu = std::make_unique<wxMenu>();
270                pRootMenu->AppendSubMenu(predefinedSites.release(), _("Predefined Sites"));
271                pRootMenu->AppendSubMenu(pMenu.release(), _("My Sites"));
272
273                return pRootMenu;
274        }
275
276        if (predefinedSites)
277                return predefinedSites;
278
279        pMenu = std::make_unique<wxMenu>();
280        wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
281        pItem->Enable(false);
282        return pMenu;
283}
284
285void CSiteManager::ClearIdMap()
286{
287        m_idMap.clear();
288}
289
290bool CSiteManager::LoadPredefined(CSiteManagerXmlHandler& handler)
291{
292        CLocalPath const defaultsDir = wxGetApp().GetDefaultsDir();
293        if (defaultsDir.empty())
294                return false;
295
296        wxString const name(defaultsDir.GetPath() + _T("fzdefaults.xml"));
297        CXmlFile file(name);
298
299        auto document = file.Load();
300        if (!document)
301                return false;
302
303        auto element = document.child("Servers");
304        if (!element)
305                return false;
306
307        if (!Load(element, handler)) {
308                return false;
309        }
310
311        return true;
312}
313
314std::unique_ptr<wxMenu> CSiteManager::GetSitesMenu_Predefined(std::map<int, std::unique_ptr<CSiteManagerItemData_Site>> &idMap)
315{
316        auto pMenu = std::make_unique<wxMenu>();
317        CSiteManagerXmlHandler_Menu handler(pMenu.get(), &idMap, true);
318
319        if (!LoadPredefined(handler)) {
320                return 0;
321        }
322
323        if (!pMenu->GetMenuItemCount()) {
324                return 0;
325        }
326
327        return pMenu;
328}
329
330std::unique_ptr<CSiteManagerItemData_Site> CSiteManager::GetSiteById(int id)
331{
332        auto iter = m_idMap.find(id);
333
334        std::unique_ptr<CSiteManagerItemData_Site> pData;
335        if (iter != m_idMap.end()) {
336                pData = std::move(iter->second);
337        }
338        ClearIdMap();
339
340        return pData;
341}
342
343bool CSiteManager::UnescapeSitePath(wxString path, std::list<wxString>& result)
344{
345        result.clear();
346
347        wxString name;
348        wxChar const* p = path.c_str();
349
350        // Undo escapement
351        bool lastBackslash = false;
352        while (*p)
353        {
354                const wxChar& c = *p;
355                if (c == '\\')
356                {
357                        if (lastBackslash)
358                        {
359                                name += _T("\\");
360                                lastBackslash = false;
361                        }
362                        else
363                                lastBackslash = true;
364                }
365                else if (c == '/')
366                {
367                        if (lastBackslash)
368                        {
369                                name += _T("/");
370                                lastBackslash = 0;
371                        }
372                        else
373                        {
374                                if (!name.empty())
375                                        result.push_back(name);
376                                name.clear();
377                        }
378                }
379                else
380                        name += *p;
381                ++p;
382        }
383        if (lastBackslash)
384                return false;
385        if (!name.empty())
386                result.push_back(name);
387
388        return !result.empty();
389}
390
391wxString CSiteManager::EscapeSegment(wxString segment)
392{
393        segment.Replace(_T("\\"), _T("\\\\"));
394        segment.Replace(_T("/"), _T("\\/"));
395        return segment;
396}
397
398wxString CSiteManager::BuildPath(wxChar root, std::list<wxString> const& segments)
399{
400        wxString ret = root;
401        for (std::list<wxString>::const_iterator it = segments.begin(); it != segments.end(); ++it)
402                ret += _T("/") + EscapeSegment(*it);
403
404        return ret;
405}
406
407std::unique_ptr<CSiteManagerItemData_Site> CSiteManager::GetSiteByPath(wxString sitePath)
408{
409        wxChar c = sitePath.empty() ? 0 : sitePath[0];
410        if (c != '0' && c != '1') {
411                wxMessageBoxEx(_("Site path has to begin with 0 or 1."), _("Invalid site path"));
412                return 0;
413        }
414
415        sitePath = sitePath.Mid(1);
416
417        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
418        // to the same file or one is reading while the other one writes.
419        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
420
421        CXmlFile file;
422        if (c == '0') {
423                file.SetFileName(wxGetApp().GetSettingsFile(_T("sitemanager")));
424        }
425        else {
426                CLocalPath const defaultsDir = wxGetApp().GetDefaultsDir();
427                if (defaultsDir.empty()) {
428                        wxMessageBoxEx(_("Site does not exist."), _("Invalid site path"));
429                        return 0;
430                }
431                file.SetFileName(defaultsDir.GetPath() + _T("fzdefaults.xml"));
432        }
433
434        auto document = file.Load();
435        if (!document) {
436                wxMessageBoxEx(file.GetError(), _("Error loading xml file"), wxICON_ERROR);
437                return 0;
438        }
439
440        auto element = document.child("Servers");
441        if (!element) {
442                wxMessageBoxEx(_("Site does not exist."), _("Invalid site path"));
443                return 0;
444        }
445
446        std::list<wxString> segments;
447        if (!UnescapeSitePath(sitePath, segments) || segments.empty()) {
448                wxMessageBoxEx(_("Site path is malformed."), _("Invalid site path"));
449                return 0;
450        }
451
452        auto child = GetElementByPath(element, segments);
453        if (!child) {
454                wxMessageBoxEx(_("Site does not exist."), _("Invalid site path"));
455                return 0;
456        }
457
458        pugi::xml_node bookmark;
459        if (!strcmp(child.name(), "Bookmark")) {
460                bookmark = child;
461                child = child.parent();
462                segments.pop_back();
463        }
464
465        std::unique_ptr<CSiteManagerItemData_Site> data = ReadServerElement(child);
466
467        if (!data) {
468                wxMessageBoxEx(_("Could not read server item."), _("Invalid site path"));
469                return 0;
470        }
471
472        if (bookmark) {
473                data->m_localDir = GetTextElement(bookmark, "LocalDir");
474                data->m_remoteDir.SetSafePath(GetTextElement(bookmark, "RemoteDir"));
475                if (!data->m_localDir.empty() && !data->m_remoteDir.empty()) {
476                        data->m_sync = GetTextElementBool(bookmark, "SyncBrowsing", false);
477                }
478                else
479                        data->m_sync = false;
480                data->m_comparison = GetTextElementBool(bookmark, "DirectoryComparison", false);
481        }
482
483        data->m_path = BuildPath( c, segments );
484
485        return data;
486}
487
488bool CSiteManager::GetBookmarks(wxString sitePath, std::list<wxString> &bookmarks)
489{
490        if (sitePath.empty())
491                return false;
492        wxChar c = sitePath[0];
493        if (c != '0' && c != '1')
494                return false;
495
496        sitePath = sitePath.Mid(1);
497
498        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
499        // to the same file or one is reading while the other one writes.
500        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
501
502        CXmlFile file;
503        if (c == '0') {
504                file.SetFileName(wxGetApp().GetSettingsFile(_T("sitemanager")));
505        }
506        else {
507                CLocalPath const defaultsDir = wxGetApp().GetDefaultsDir();
508                if (defaultsDir.empty()) {
509                        wxMessageBoxEx(_("Site does not exist."), _("Invalid site path"));
510                        return 0;
511                }
512                file.SetFileName(defaultsDir.GetPath() + _T("fzdefaults.xml"));
513        }
514
515        auto document = file.Load();
516        if (!document) {
517                wxMessageBoxEx(file.GetError(), _("Error loading xml file"), wxICON_ERROR);
518                return false;
519        }
520
521        auto element = document.child("Servers");
522        if (!element)
523                return false;
524
525        std::list<wxString> segments;
526        if (!UnescapeSitePath(sitePath, segments)) {
527                wxMessageBoxEx(_("Site path is malformed."), _("Invalid site path"));
528                return 0;
529        }
530
531        auto child = GetElementByPath(element, segments);
532
533        if (child && !strcmp(child.name(), "Bookmark"))
534                child = child.parent();
535
536        if (!child || strcmp(child.name(), "Server"))
537                return 0;
538
539        // Bookmarks
540        for (auto bookmark = child.child("Bookmark"); bookmark; bookmark = bookmark.next_sibling("Bookmark")) {
541                wxString name = GetTextElement_Trimmed(bookmark, "Name");
542                if (name.empty())
543                        continue;
544
545                wxString localPath = GetTextElement(bookmark, "LocalDir");
546                CServerPath remotePath;
547                remotePath.SetSafePath(GetTextElement(bookmark, "RemoteDir"));
548                if (localPath.empty() && remotePath.empty())
549                        continue;
550
551                bookmarks.push_back(name);
552        }
553
554        return true;
555}
556
557wxString CSiteManager::AddServer(CServer server)
558{
559        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
560        // to the same file or one is reading while the other one writes.
561        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
562
563        CXmlFile file(wxGetApp().GetSettingsFile(_T("sitemanager")));
564        auto document = file.Load();
565        if (!document) {
566                wxString msg = file.GetError() + _T("\n") + _("The server could not be added.");
567                wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR);
568
569                return wxString();
570        }
571
572        auto element = document.child("Servers");
573        if (!element)
574                return wxString();
575
576        std::list<wxString> names;
577        for (auto child = element.child("Server"); child; child = child.next_sibling("Server")) {
578                wxString name = GetTextElement(child, "Name");
579                if (name.empty())
580                        continue;
581
582                names.push_back(name);
583        }
584
585        wxString name = _("New site");
586        int i = 1;
587
588        for (;;) {
589                std::list<wxString>::const_iterator iter;
590                for (iter = names.begin(); iter != names.end(); ++iter) {
591                        if (*iter == name)
592                                break;
593                }
594                if (iter == names.end())
595                        break;
596
597                name = _("New site") + wxString::Format(_T(" %d"), ++i);
598        }
599
600        server.SetName(name);
601
602        auto xServer = element.append_child("Server");
603        SetServer(xServer, server);
604        AddTextElement(xServer, name);
605
606        if (!file.Save(false)) {
607                if (COptions::Get()->GetOptionVal(OPTION_DEFAULT_KIOSKMODE) == 2)
608                        return wxString();
609
610                wxString msg = wxString::Format(_("Could not write \"%s\", any changes to the Site Manager could not be saved: %s"), file.GetFileName(), file.GetError());
611                wxMessageBoxEx(msg, _("Error writing xml file"), wxICON_ERROR);
612                return wxString();
613        }
614
615        return _T("0/") + EscapeSegment(name);
616}
617
618pugi::xml_node CSiteManager::GetElementByPath(pugi::xml_node node, std::list<wxString> const& segments)
619{
620        for (std::list<wxString>::const_iterator it = segments.begin(); it != segments.end(); ++it) {
621                const wxString & segment = *it;
622
623                pugi::xml_node child;
624                for (child = node.first_child(); child; child = child.next_sibling()) {
625                        if (strcmp(child.name(), "Server") && strcmp(child.name(), "Folder") && strcmp(child.name(), "Bookmark"))
626                                continue;
627
628                        wxString name = GetTextElement_Trimmed(child, "Name");
629                        if (name.empty())
630                                name = GetTextElement_Trimmed(child);
631                        if (name.empty())
632                                continue;
633
634                        if (name == segment)
635                                break;
636                }
637                if (!child)
638                        return pugi::xml_node();
639
640                node = child;
641                continue;
642        }
643
644        return node;
645}
646
647bool CSiteManager::AddBookmark(wxString sitePath, const wxString& name, const wxString &local_dir, const CServerPath &remote_dir, bool sync, bool comparison)
648{
649        if (local_dir.empty() && remote_dir.empty())
650                return false;
651
652        wxChar c = sitePath.empty() ? 0 : sitePath[0];
653        if (c != '0')
654                return false;
655
656        sitePath = sitePath.Mid(1);
657
658        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
659        // to the same file or one is reading while the other one writes.
660        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
661
662        CXmlFile file(wxGetApp().GetSettingsFile(_T("sitemanager")));
663        auto document = file.Load();
664        if (!document) {
665                wxString msg = file.GetError() + _T("\n") + _("The bookmark could not be added.");
666                wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR);
667
668                return false;
669        }
670
671        auto element = document.child("Servers");
672        if (!element)
673                return false;
674
675        std::list<wxString> segments;
676        if (!UnescapeSitePath(sitePath, segments)) {
677                wxMessageBoxEx(_("Site path is malformed."), _("Invalid site path"));
678                return 0;
679        }
680
681        auto child = GetElementByPath(element, segments);
682        if (!child || strcmp(child.name(), "Server")) {
683                wxMessageBoxEx(_("Site does not exist."), _("Invalid site path"));
684                return 0;
685        }
686
687        // Bookmarks
688        pugi::xml_node insertBefore, bookmark;
689        for (bookmark = child.child("Bookmark"); bookmark; bookmark = bookmark.next_sibling("Bookmark")) {
690                wxString old_name = GetTextElement_Trimmed(bookmark, "Name");
691                if (old_name.empty())
692                        continue;
693
694                if (name == old_name) {
695                        wxMessageBoxEx(_("Name of bookmark already exists."), _("New bookmark"), wxICON_EXCLAMATION);
696                        return false;
697                }
698                if (name < old_name && !insertBefore)
699                        insertBefore = bookmark;
700        }
701
702        if (insertBefore)
703                bookmark = child.insert_child_before("Bookmark", insertBefore);
704        else
705                bookmark = child.append_child("Bookmark");
706        AddTextElement(bookmark, "Name", name);
707        if (!local_dir.empty())
708                AddTextElement(bookmark, "LocalDir", local_dir);
709        if (!remote_dir.empty())
710                AddTextElement(bookmark, "RemoteDir", remote_dir.GetSafePath());
711        if (sync)
712                AddTextElementRaw(bookmark, "SyncBrowsing", "1");
713        if (comparison)
714                AddTextElementRaw(bookmark, "DirectoryComparison", "1");
715
716        if (!file.Save(false)) {
717                if (COptions::Get()->GetOptionVal(OPTION_DEFAULT_KIOSKMODE) == 2)
718                        return true;
719
720                wxString msg = wxString::Format(_("Could not write \"%s\", the selected sites could not be exported: %s"), file.GetFileName(), file.GetError());
721                wxMessageBoxEx(msg, _("Error writing xml file"), wxICON_ERROR);
722        }
723
724        return true;
725}
726
727bool CSiteManager::ClearBookmarks(wxString sitePath)
728{
729        wxChar const c = sitePath.empty() ? 0 : sitePath[0];
730        if (c != '0')
731                return false;
732
733        sitePath = sitePath.Mid(1);
734
735        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
736        // to the same file or one is reading while the other one writes.
737        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
738
739        CXmlFile file(wxGetApp().GetSettingsFile(_T("sitemanager")));
740        auto document = file.Load();
741        if (!document) {
742                wxString msg = file.GetError() + _T("\n") + _("The bookmarks could not be cleared.");
743                wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR);
744
745                return false;
746        }
747
748        auto element = document.child("Servers");
749        if (!element)
750                return false;
751
752        std::list<wxString> segments;
753        if (!UnescapeSitePath(sitePath, segments)) {
754                wxMessageBoxEx(_("Site path is malformed."), _("Invalid site path"));
755                return 0;
756        }
757
758        auto child = GetElementByPath(element, segments);
759        if (!child || strcmp(child.name(), "Server")) {
760                wxMessageBoxEx(_("Site does not exist."), _("Invalid site path"));
761                return 0;
762        }
763
764        auto bookmark = child.child("Bookmark");
765        while (bookmark) {
766                child.remove_child(bookmark);
767                bookmark = child.child("Bookmark");
768        }
769
770        if (!file.Save(false)) {
771                if (COptions::Get()->GetOptionVal(OPTION_DEFAULT_KIOSKMODE) == 2)
772                        return true;
773
774                wxString msg = wxString::Format(_("Could not write \"%s\", the selected sites could not be exported: %s"), file.GetFileName(), file.GetError());
775                wxMessageBoxEx(msg, _("Error writing xml file"), wxICON_ERROR);
776        }
777
778        return true;
779}
780
781bool CSiteManager::HasSites()
782{
783        CSiteManagerXmlHandler_Stats handler;
784        Load(handler);
785
786        return handler.sites_ > 0;
787}
Note: See TracBrowser for help on using the repository browser.