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

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

First release to xenial

File size: 7.0 KB
Line 
1#include <filezilla.h>
2#include "fzputtygen_interface.h"
3#include "Options.h"
4#include "filezillaapp.h"
5#include "inputdialog.h"
6
7CFZPuttyGenInterface::CFZPuttyGenInterface(wxWindow* parent)
8        : m_parent(parent)
9{
10}
11
12CFZPuttyGenInterface::~CFZPuttyGenInterface()
13{
14        if (m_pProcess)
15                EndProcess();
16}
17
18void CFZPuttyGenInterface::EndProcess()
19{
20        m_pProcess->CloseOutput();
21        m_pProcess->Detach();
22        m_pProcess = 0;
23}
24
25void CFZPuttyGenInterface::DeleteProcess()
26{
27        delete m_pProcess;
28        m_pProcess = 0;
29}
30
31bool CFZPuttyGenInterface::IsProcessCreated()
32{
33        return m_pProcess != 0;
34}
35
36bool CFZPuttyGenInterface::IsProcessStarted()
37{
38        return m_initialized;
39}
40
41int CFZPuttyGenInterface::NeedsConversion(wxString keyFile, bool silent)
42{
43        if (!Send(_T("file " + keyFile)))
44                return -1;
45
46        wxString reply;
47        ReplyCode code = GetReply(reply);
48        if (code == failure)
49                return -1;
50        if (code == error || (reply != _T("ok") && reply != _T("convertible"))) {
51                if (!silent) {
52                        wxString msg;
53                        if (reply == _T("incompatible")) {
54                                msg.Printf(_("The file '%s' contains an SSH1 key. The SSH1 protocol has been deprecated, FileZilla only supports SSH2 keys."), keyFile);
55                        }
56                        else {
57                                msg.Printf(_("The file '%s' could not be loaded or does not contain a private key."), keyFile);
58                        }
59                        wxMessageBoxEx(msg, _("Could not load key file"), wxICON_EXCLAMATION);
60                }
61                return -1;
62        }
63
64        return reply == _T("convertible") ? 1 : 0;
65}
66
67int CFZPuttyGenInterface::IsKeyFileEncrypted(wxString keyFile, bool silent)
68{
69        if (!Send(_T("encrypted")))
70                return -1;
71
72        wxString reply;
73        ReplyCode code = GetReply(reply);
74        if (code != success) {
75                wxASSERT(code != error);
76                return -1;
77        }
78
79        return reply == _T("1") ? 1 : 0;
80}
81
82bool CFZPuttyGenInterface::LoadKeyFile(wxString& keyFile, bool silent, wxString& comment, wxString& data)
83{
84        if (!LoadProcess(silent)) {
85                return false;
86        }
87
88        int needs_conversion = NeedsConversion(keyFile, silent);
89        if (needs_conversion < 0) {
90                return false;
91        }
92       
93        wxString reply;
94        ReplyCode code;
95        if (needs_conversion) {
96                if (silent) {
97                        return false;
98                }
99
100                int encrypted = IsKeyFileEncrypted(keyFile, silent);
101                if (encrypted < 0) {
102                        return false;
103                }
104
105                wxString msg = wxString::Format(_("The file '%s' is not in a format supported by FileZilla.\nWould you like to convert it into a supported format?"), keyFile);
106                int res = wxMessageBoxEx(msg, _("Convert key file"), wxICON_QUESTION | wxYES_NO);
107                if (res != wxYES)
108                        return false;
109
110                msg = wxString::Format(_("Enter the password for the file '%s'.\nThe converted file will be protected with the same password."), keyFile);
111                CInputDialog dlg;
112                if (!dlg.Create(m_parent, _("Password required"), msg))
113                        return false;
114
115                dlg.SetPasswordMode(true);
116
117                if (dlg.ShowModal() != wxID_OK)
118                        return false;
119                if (!Send(_T("password " + dlg.GetValue())))
120                        return false;
121                wxString reply;
122                code = GetReply(reply);
123                if (code != success) {
124                        msg = wxString::Format(_("Failed to load private key: %s"), reply);
125                        wxMessageBoxEx(msg, _("Could not load private key"), wxICON_EXCLAMATION);
126                        return false;
127                }
128
129                wxFileDialog fileDlg(m_parent, _("Select filename for converted key file"), wxString(), wxString(), _T("PuTTY private key files (*.ppk)|*.ppk"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
130                if (fileDlg.ShowModal() != wxID_OK)
131                        return false;
132
133                wxString newName = fileDlg.GetPath();
134                if (newName.empty())
135                        return false;
136
137                if (newName == keyFile) {
138                        // Not actually a requirement by fzputtygen, but be on the safe side. We don't want the user to lose his keys.
139                        wxMessageBoxEx(_("Source and target file may not be the same"), _("Could not convert private key"), wxICON_EXCLAMATION);
140                        return false;
141                }
142
143                Send(_T("write ") + newName);
144                code = GetReply(reply);
145                if (code == failure)
146                        return false;
147                if (code != success) {
148                        wxMessageBoxEx(wxString::Format(_("Could not write key file: %s"), reply), _("Could not convert private key"), wxICON_EXCLAMATION);
149                        return false;
150                }
151                keyFile = newName;
152        }
153       
154        if (!Send(_T("fingerprint")))
155                return false;
156        code = GetReply(data);
157        if (code != success)
158                return false;
159
160        Send(_T("comment"));
161        code = GetReply(comment);
162        if (code != success)
163                return false;
164
165        return true;
166}
167
168bool CFZPuttyGenInterface::LoadProcess(bool silent)
169{
170        if (m_initialized)
171                return m_pProcess != 0;
172
173        wxString executable = COptions::Get()->GetOption(OPTION_FZSFTP_EXECUTABLE);
174        int pos = executable.Find(wxFileName::GetPathSeparator(), true);
175        if (pos == -1) {
176                if (!silent) {
177                        wxMessageBoxEx(_("fzputtygen could not be started.\nPlease make sure this executable exists in the same directory as the main FileZilla executable."), _("Error starting program"), wxICON_EXCLAMATION);
178                }
179                return false;
180        }
181        else {
182                executable = executable.Left(pos + 1) + _T("fzputtygen");
183#ifdef __WXMSW__
184                executable += _T(".exe");
185#endif
186                if (!executable.empty() && executable[0] == '"')
187                        executable += '"';
188
189                if (executable.Find(' ') != -1 && executable[0] != '"') {
190                        executable = '"' + executable + '"';
191                }
192        }
193
194        m_pProcess = new wxProcess(m_parent);
195        m_pProcess->Redirect();
196
197        wxLogNull log;
198        if (!wxExecute(executable, wxEXEC_ASYNC, m_pProcess)) {
199                delete m_pProcess;
200                m_pProcess = 0;
201
202                if (!silent) {
203                        wxMessageBoxEx(_("fzputtygen could not be started.\nPlease make sure this executable exists in the same directory as the main FileZilla executable."), _("Error starting program"), wxICON_EXCLAMATION);
204                }
205                return false;
206        }
207
208        m_initialized = true;
209        return true;
210}
211
212bool CFZPuttyGenInterface::Send(const wxString& cmd)
213{
214        if (!m_pProcess)
215                return false;
216
217        const wxWX2MBbuf buf = (cmd + _T("\n")).mb_str();
218        const size_t len = strlen (buf);
219
220        wxOutputStream* stream = m_pProcess->GetOutputStream();
221        stream->Write((const char *) buf, len);
222
223        if (stream->GetLastError() != wxSTREAM_NO_ERROR || stream->LastWrite() != len) {
224                wxMessageBoxEx(_("Could not send command to fzputtygen."), _("Command failed"), wxICON_EXCLAMATION);
225                return false;
226        }
227
228        return true;
229}
230
231CFZPuttyGenInterface::ReplyCode CFZPuttyGenInterface::GetReply(wxString& reply)
232{
233        if (!m_pProcess)
234                return failure;
235        wxInputStream *pStream = m_pProcess->GetInputStream();
236        if (!pStream) {
237                wxMessageBoxEx(_("Could not get reply from fzputtygen."), _("Command failed"), wxICON_EXCLAMATION);
238                return failure;
239        }
240
241        char buffer[100];
242
243        wxString input;
244
245        for (;;) {
246                int pos = input.Find('\n');
247                if (pos == wxNOT_FOUND) {
248                        pStream->Read(buffer, 99);
249                        int read;
250                        if (pStream->Eof() || !(read = pStream->LastRead())) {
251                                wxMessageBoxEx(_("Could not get reply from fzputtygen."), _("Command failed"), wxICON_EXCLAMATION);
252                                return failure;
253                        }
254                        buffer[read] = 0;
255
256                        // Should only ever return ASCII strings so this is ok
257                        input += wxString(buffer, wxConvUTF8);
258
259                        pos = input.Find('\n');
260                        if (pos == wxNOT_FOUND)
261                                continue;
262                }
263
264                int pos2;
265                if (pos && input[pos - 1] == '\r')
266                        pos2 = pos - 1;
267                else
268                        pos2 = pos;
269                if (!pos2) {
270                        input = input.Mid(pos + 1);
271                        continue;
272                }
273                if (input.empty()) {
274                        continue;
275                }
276                wxChar c = input[0];
277
278                reply = input.Mid(1, pos2 - 1);
279                input = input.Mid(pos + 1);
280
281                if (c == '0' || c == '1')
282                        return success;
283                else if (c == '2')
284                        return error;
285                // Ignore others
286        }
287}
Note: See TracBrowser for help on using the repository browser.