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

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

Update new version: 3.15.02

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()
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        ReplyCode code;
94        if (needs_conversion) {
95                if (silent) {
96                        return false;
97                }
98
99                int encrypted = IsKeyFileEncrypted();
100                if (encrypted < 0) {
101                        return false;
102                }
103
104                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);
105                int res = wxMessageBoxEx(msg, _("Convert key file"), wxICON_QUESTION | wxYES_NO);
106                if (res != wxYES)
107                        return false;
108
109                msg = wxString::Format(_("Enter the password for the file '%s'.\nThe converted file will be protected with the same password."), keyFile);
110                CInputDialog dlg;
111                if (!dlg.Create(m_parent, _("Password required"), msg))
112                        return false;
113
114                dlg.SetPasswordMode(true);
115
116                if (dlg.ShowModal() != wxID_OK)
117                        return false;
118                if (!Send(_T("password " + dlg.GetValue())))
119                        return false;
120                wxString reply;
121                code = GetReply(reply);
122                if (code != success) {
123                        msg = wxString::Format(_("Failed to load private key: %s"), reply);
124                        wxMessageBoxEx(msg, _("Could not load private key"), wxICON_EXCLAMATION);
125                        return false;
126                }
127
128                wxFileDialog fileDlg(m_parent, _("Select filename for converted key file"), wxString(), wxString(), _T("PuTTY private key files (*.ppk)|*.ppk"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
129                if (fileDlg.ShowModal() != wxID_OK)
130                        return false;
131
132                wxString newName = fileDlg.GetPath();
133                if (newName.empty())
134                        return false;
135
136                if (newName == keyFile) {
137                        // Not actually a requirement by fzputtygen, but be on the safe side. We don't want the user to lose his keys.
138                        wxMessageBoxEx(_("Source and target file may not be the same"), _("Could not convert private key"), wxICON_EXCLAMATION);
139                        return false;
140                }
141
142                Send(_T("write ") + newName);
143                code = GetReply(reply);
144                if (code == failure)
145                        return false;
146                if (code != success) {
147                        wxMessageBoxEx(wxString::Format(_("Could not write key file: %s"), reply), _("Could not convert private key"), wxICON_EXCLAMATION);
148                        return false;
149                }
150                keyFile = newName;
151        }
152       
153        if (!Send(_T("fingerprint")))
154                return false;
155        code = GetReply(data);
156        if (code != success)
157                return false;
158
159        Send(_T("comment"));
160        code = GetReply(comment);
161        if (code != success)
162                return false;
163
164        return true;
165}
166
167bool CFZPuttyGenInterface::LoadProcess(bool silent)
168{
169        if (m_initialized)
170                return m_pProcess != 0;
171
172        wxString executable = COptions::Get()->GetOption(OPTION_FZSFTP_EXECUTABLE);
173        int pos = executable.Find(wxFileName::GetPathSeparator(), true);
174        if (pos == -1) {
175                if (!silent) {
176                        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);
177                }
178                return false;
179        }
180        else {
181                executable = executable.Left(pos + 1) + _T("fzputtygen");
182#ifdef __WXMSW__
183                executable += _T(".exe");
184#endif
185                if (!executable.empty() && executable[0] == '"')
186                        executable += '"';
187
188                if (executable.Find(' ') != -1 && executable[0] != '"') {
189                        executable = '"' + executable + '"';
190                }
191        }
192
193        m_pProcess = new wxProcess(m_parent);
194        m_pProcess->Redirect();
195
196        wxLogNull log;
197        if (!wxExecute(executable, wxEXEC_ASYNC, m_pProcess)) {
198                delete m_pProcess;
199                m_pProcess = 0;
200
201                if (!silent) {
202                        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);
203                }
204                return false;
205        }
206
207        m_initialized = true;
208        return true;
209}
210
211bool CFZPuttyGenInterface::Send(const wxString& cmd)
212{
213        if (!m_pProcess)
214                return false;
215
216        const wxWX2MBbuf buf = (cmd + _T("\n")).mb_str(wxConvUTF8);
217        const size_t len = strlen (buf);
218
219        wxOutputStream* stream = m_pProcess->GetOutputStream();
220        stream->Write((const char *) buf, len);
221
222        if (stream->GetLastError() != wxSTREAM_NO_ERROR || stream->LastWrite() != len) {
223                wxMessageBoxEx(_("Could not send command to fzputtygen."), _("Command failed"), wxICON_EXCLAMATION);
224                return false;
225        }
226
227        return true;
228}
229
230CFZPuttyGenInterface::ReplyCode CFZPuttyGenInterface::GetReply(wxString& reply)
231{
232        if (!m_pProcess)
233                return failure;
234        wxInputStream *pStream = m_pProcess->GetInputStream();
235        if (!pStream) {
236                wxMessageBoxEx(_("Could not get reply from fzputtygen."), _("Command failed"), wxICON_EXCLAMATION);
237                return failure;
238        }
239
240        char buffer[100];
241
242        wxString input;
243
244        for (;;) {
245                int pos = input.Find('\n');
246                if (pos == wxNOT_FOUND) {
247                        pStream->Read(buffer, 99);
248                        int read;
249                        if (pStream->Eof() || !(read = pStream->LastRead())) {
250                                wxMessageBoxEx(_("Could not get reply from fzputtygen."), _("Command failed"), wxICON_EXCLAMATION);
251                                return failure;
252                        }
253                        buffer[read] = 0;
254
255                        // Should only ever return ASCII strings so this is ok
256                        input += wxString(buffer, wxConvUTF8);
257
258                        pos = input.Find('\n');
259                        if (pos == wxNOT_FOUND)
260                                continue;
261                }
262
263                int pos2;
264                if (pos && input[pos - 1] == '\r')
265                        pos2 = pos - 1;
266                else
267                        pos2 = pos;
268                if (!pos2) {
269                        input = input.Mid(pos + 1);
270                        continue;
271                }
272                if (input.empty()) {
273                        continue;
274                }
275                wxChar c = input[0];
276
277                reply = input.Mid(1, pos2 - 1);
278                input = input.Mid(pos + 1);
279
280                if (c == '0' || c == '1')
281                        return success;
282                else if (c == '2')
283                        return error;
284                // Ignore others
285        }
286}
Note: See TracBrowser for help on using the repository browser.