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

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

First release to xenial

File size: 10.0 KB
Line 
1#include <filezilla.h>
2#include "filezillaapp.h"
3#include "import.h"
4#include "xmlfunctions.h"
5#include "ipcmutex.h"
6#include "Options.h"
7#include "queue.h"
8
9CImportDialog::CImportDialog(wxWindow* parent, CQueueView* pQueueView)
10        : m_parent(parent), m_pQueueView(pQueueView)
11{
12}
13
14void CImportDialog::Run()
15{
16        wxFileDialog dlg(m_parent, _("Select file to import settings from"), wxString(),
17                                        _T("FileZilla.xml"), _T("XML files (*.xml)|*.xml"),
18                                        wxFD_OPEN | wxFD_FILE_MUST_EXIST);
19        dlg.CenterOnParent();
20
21        if (dlg.ShowModal() != wxID_OK)
22                return;
23
24        wxFileName fn(dlg.GetPath());
25        wxString const path = fn.GetPath();
26        wxString const settingsDir(COptions::Get()->GetOption(OPTION_DEFAULT_SETTINGSDIR));
27        if (path == settingsDir) {
28                wxMessageBoxEx(_("You cannot import settings from FileZilla's own settings directory."), _("Error importing"), wxICON_ERROR, m_parent);
29                return;
30        }
31
32        CXmlFile fz3(dlg.GetPath());
33        auto fz3Root = fz3.Load();
34        if (fz3Root) {
35                bool settings = fz3Root.child("Settings") != 0;
36                bool queue = fz3Root.child("Queue") != 0;
37                bool sites = fz3Root.child("Servers") != 0;
38
39                if (settings || queue || sites) {
40                        if (!Load(m_parent, _T("ID_IMPORT"))) {
41                                wxBell();
42                                return;
43                        }
44                        if (!queue)
45                                XRCCTRL(*this, "ID_QUEUE", wxCheckBox)->Hide();
46                        if (!sites)
47                                XRCCTRL(*this, "ID_SITEMANAGER", wxCheckBox)->Hide();
48                        if (!settings)
49                                XRCCTRL(*this, "ID_SETTINGS", wxCheckBox)->Hide();
50                        GetSizer()->Fit(this);
51
52                        if (ShowModal() != wxID_OK) {
53                                return;
54                        }
55
56                        if (fz3.IsFromFutureVersion()) {
57                                wxString msg = wxString::Format(_("The file '%s' has been created by a more recent version of FileZilla.\nLoading files created by newer versions can result in loss of data.\nDo you want to continue?"), fz3.GetFileName());
58                                if (wxMessageBoxEx(msg, _("Detected newer version of FileZilla"), wxICON_QUESTION | wxYES_NO) != wxYES) {
59                                        return;
60                                }
61                        }
62
63                        if (queue && XRCCTRL(*this, "ID_QUEUE", wxCheckBox)->IsChecked()) {
64                                m_pQueueView->ImportQueue(fz3Root.child("Queue"), true);
65                        }
66
67                        if (sites && XRCCTRL(*this, "ID_SITEMANAGER", wxCheckBox)->IsChecked()) {
68                                ImportSites(fz3Root.child("Servers"));
69                        }
70
71                        if (settings && XRCCTRL(*this, "ID_SETTINGS", wxCheckBox)->IsChecked()) {
72                                COptions::Get()->Import(fz3Root.child("Settings"));
73                                wxMessageBoxEx(_("The settings have been imported. You have to restart FileZilla for all settings to have effect."), _("Import successful"), wxOK, this);
74                        }
75
76                        wxMessageBoxEx(_("The selected categories have been imported."), _("Import successful"), wxOK, this);
77                        return;
78                }
79        }
80
81        CXmlFile fz2(dlg.GetPath(), _T("FileZilla"));
82        auto fz2Root = fz2.Load();
83        if (fz2Root) {
84                auto sites_fz2 = fz2Root.child("Sites");
85                if (sites_fz2) {
86                        int res = wxMessageBoxEx(_("The file you have selected contains site manager data from a previous version of FileZilla.\nDue to differences in the storage format, only host, port, username and password will be imported.\nContinue with the import?"),
87                                _("Import data from older version"), wxICON_QUESTION | wxYES_NO);
88
89                        if (res == wxYES)
90                                ImportLegacySites(sites_fz2);
91                        return;
92                }
93        }
94
95        wxMessageBoxEx(_("File does not contain any importable data."), _("Error importing"), wxICON_ERROR, m_parent);
96}
97
98bool CImportDialog::ImportLegacySites(pugi::xml_node sites)
99{
100        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
101
102        CXmlFile file(wxGetApp().GetSettingsFile(_T("sitemanager")));
103        auto element = file.Load();
104        if (!element) {
105                wxString msg = wxString::Format(_("Could not load \"%s\", please make sure the file is valid and can be accessed.\nAny changes made in the Site Manager will not be saved."), file.GetFileName());
106                wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR);
107
108                return false;
109        }
110
111        auto currentSites = element.child("Servers");
112        if (!currentSites)
113                currentSites = element.append_child("Servers");
114
115        if (!ImportLegacySites(sites, currentSites))
116                return false;
117
118        return file.Save(true);
119}
120
121wxString CImportDialog::DecodeLegacyPassword(wxString pass)
122{
123        if( pass.size() % 3 ) {
124                return wxString();
125        }
126
127        wxString output;
128        const char* key = "FILEZILLA1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
129
130        int pos = (pass.Length() / 3) % strlen(key);
131        for (unsigned int i = 0; i < pass.Length(); i += 3) {
132                if (pass[i] < '0' || pass[i] > '9' ||
133                        pass[i + 1] < '0' || pass[i + 1] > '9' ||
134                        pass[i + 2] < '0' || pass[i + 2] > '9')
135                        return wxString();
136                int number = (pass[i] - '0') * 100 +
137                                                (pass[i + 1] - '0') * 10 +
138                                                (pass[i + 2] - '0');
139                wxChar c = number ^ key[(i / 3 + pos) % strlen(key)];
140                output += c;
141        }
142
143        return output;
144}
145
146bool CImportDialog::ImportLegacySites(pugi::xml_node sitesToImport, pugi::xml_node existingSites)
147{
148        for (auto importFolder = sitesToImport.child("Folder"); importFolder; importFolder = importFolder.next_sibling("Folder")) {
149                wxString name = GetTextAttribute(importFolder, "Name");
150                if (name.empty())
151                        continue;
152
153                wxString newName = name;
154                int i = 2;
155                pugi::xml_node folder;
156                while (!(folder = GetFolderWithName(existingSites, newName))) {
157                        newName = wxString::Format(_T("%s %d"), name, i++);
158                }
159
160                ImportLegacySites(importFolder, folder);
161        }
162
163        for (auto importSite = sitesToImport.child("Site"); importSite; importSite = importSite.next_sibling("Site")) {
164                wxString name = GetTextAttribute(importSite, "Name");
165                if (name.empty())
166                        continue;
167
168                wxString host = GetTextAttribute(importSite, "Host");
169                if (host.empty())
170                        continue;
171
172                int port = GetAttributeInt(importSite, "Port");
173                if (port < 1 || port > 65535)
174                        continue;
175
176                int serverType = GetAttributeInt(importSite, "ServerType");
177                if (serverType < 0 || serverType > 4)
178                        continue;
179
180                int protocol;
181                switch (serverType)
182                {
183                default:
184                case 0:
185                        protocol = 0;
186                        break;
187                case 1:
188                        protocol = 3;
189                        break;
190                case 2:
191                case 4:
192                        protocol = 4;
193                        break;
194                case 3:
195                        protocol = 1;
196                        break;
197                }
198
199                bool dontSavePass = GetAttributeInt(importSite, "DontSavePass") == 1;
200
201                int logontype = GetAttributeInt(importSite, "Logontype");
202                if (logontype < 0 || logontype > 2)
203                        continue;
204                if (logontype == 2)
205                        logontype = 4;
206                if (logontype == 1 && dontSavePass)
207                        logontype = 2;
208
209                wxString user = GetTextAttribute(importSite, "User");
210                wxString pass = DecodeLegacyPassword(GetTextAttribute(importSite, "Pass"));
211                wxString account = GetTextAttribute(importSite, "Account");
212                if (logontype && user.empty())
213                        continue;
214
215                // Find free name
216                wxString newName = name;
217                int i = 2;
218                while (HasEntryWithName(existingSites, newName)) {
219                        newName = wxString::Format(_T("%s %d"), name, i++);
220                }
221
222                auto server = existingSites.append_child("Server");
223                AddTextElement(server, newName);
224
225                AddTextElement(server, "Host", host);
226                AddTextElement(server, "Port", port);
227                AddTextElement(server, "Protocol", protocol);
228                AddTextElement(server, "Logontype", logontype);
229                AddTextElement(server, "User", user);
230                AddTextElement(server, "Pass", pass);
231                AddTextElement(server, "Account", account);
232        }
233
234        return true;
235}
236
237bool CImportDialog::HasEntryWithName(pugi::xml_node element, const wxString& name)
238{
239        pugi::xml_node child;
240        for (child = element.child("Server"); child; child = child.next_sibling("Server")) {
241                wxString childName = GetTextElement(child);
242                childName.Trim(true);
243                childName.Trim(false);
244                if (!name.CmpNoCase(childName))
245                        return true;
246        }
247        for (child = element.child("Folder"); child; child = child.next_sibling("Folder")) {
248                wxString childName = GetTextElement(child);
249                childName.Trim(true);
250                childName.Trim(false);
251                if (!name.CmpNoCase(childName))
252                        return true;
253        }
254
255        return false;
256}
257
258pugi::xml_node CImportDialog::GetFolderWithName(pugi::xml_node element, const wxString& name)
259{
260        pugi::xml_node child;
261        for (child = element.child("Server"); child; child = child.next_sibling("Server")) {
262                wxString childName = GetTextElement(child);
263                childName.Trim(true);
264                childName.Trim(false);
265                if (!name.CmpNoCase(childName)) {
266                        // We do not allow servers and directories to share the same name
267                        return pugi::xml_node();
268                }
269        }
270
271        for (child = element.child("Folder"); child; child = child.next_sibling("Folder")) {
272                wxString childName = GetTextElement(child);
273                childName.Trim(true);
274                childName.Trim(false);
275                if (!name.CmpNoCase(childName))
276                        return child;
277        }
278
279        child = element.append_child("Folder");
280        AddTextElement(child, name);
281
282        return child;
283}
284
285bool CImportDialog::ImportSites(pugi::xml_node sites)
286{
287        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
288
289        CXmlFile file(wxGetApp().GetSettingsFile(_T("sitemanager")));
290        auto element = file.Load();
291        if (!element) {
292                wxString msg = wxString::Format(_("Could not load \"%s\", please make sure the file is valid and can be accessed.\nAny changes made in the Site Manager will not be saved."), file.GetFileName());
293                wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR);
294
295                return false;
296        }
297
298        auto currentSites = element.child("Servers");
299        if (!currentSites)
300                currentSites = element.append_child("Servers");
301
302        if (!ImportSites(sites, currentSites))
303                return false;
304
305        return file.Save(true);
306}
307
308bool CImportDialog::ImportSites(pugi::xml_node sitesToImport, pugi::xml_node existingSites)
309{
310        for (auto importFolder = sitesToImport.child("Folder"); importFolder; importFolder = importFolder.next_sibling("Folder")) {
311                wxString name = GetTextElement_Trimmed(importFolder, "Name");
312                if (name.empty())
313                        name = GetTextElement_Trimmed(importFolder);
314                if (name.empty())
315                        continue;
316
317                wxString newName = name;
318                int i = 2;
319                pugi::xml_node folder;
320                while (!(folder = GetFolderWithName(existingSites, newName))) {
321                        newName = wxString::Format(_T("%s %d"), name, i++);
322                }
323
324                ImportSites(importFolder, folder);
325        }
326
327        for (auto importSite = sitesToImport.child("Server"); importSite; importSite = importSite.next_sibling("Server")) {
328                wxString name = GetTextElement_Trimmed(importSite, "Name");
329                if (name.empty())
330                        name = GetTextElement_Trimmed(importSite);
331                if (name.empty())
332                        continue;
333
334                // Find free name
335                wxString newName = name;
336                int i = 2;
337                while (HasEntryWithName(existingSites, newName)) {
338                        newName = wxString::Format(_T("%s %d"), name, i++);
339                }
340
341                auto server = existingSites.append_copy(importSite);
342                AddTextElement(server, "Name", newName, true);
343                AddTextElement(server, newName);
344        }
345
346        return true;
347}
Note: See TracBrowser for help on using the repository browser.