1 #include "filezilla.h"
2 #include "storj_key_interface.h"
3 #include "Options.h"
4 #include "filezillaapp.h"
5 #include "inputdialog.h"
6 
7 #include <libfilezilla/process.hpp>
8 
CStorjKeyInterface(wxWindow * parent)9 CStorjKeyInterface::CStorjKeyInterface(wxWindow* parent)
10 	: m_parent(parent)
11 {
12 }
13 
~CStorjKeyInterface()14 CStorjKeyInterface::~CStorjKeyInterface()
15 {
16 }
17 
18 namespace {
quote(std::wstring_view const & arg)19 std::wstring quote(std::wstring_view const& arg)
20 {
21 	return L"\"" + fz::replaced_substrings(arg, L"\"", L"\"\"") + L"\"";
22 }
23 }
ValidateGrant(std::wstring const & grant,bool silent)24 std::tuple<bool, std::wstring> CStorjKeyInterface::ValidateGrant(std::wstring const& grant, bool silent)
25 {
26 	if (grant.empty()) {
27 		return {false, std::wstring()};
28 	}
29 	LoadProcess(silent);
30 
31 	if (!Send(L"validate grant " + quote(grant))) {
32 		return {false, std::wstring()};
33 	}
34 
35 	std::wstring reply;
36 	ReplyCode code = GetReply(reply);
37 	return {code == success, reply};
38 }
39 
LoadProcess(bool silent)40 bool CStorjKeyInterface::LoadProcess(bool silent)
41 {
42 	if (m_initialized) {
43 		return m_process != 0;
44 	}
45 	m_initialized = true;
46 
47 	std::wstring executable = COptions::Get()->get_string(OPTION_FZSTORJ_EXECUTABLE);
48 	size_t pos = executable.rfind(wxFileName::GetPathSeparator());
49 	if (pos == std::wstring::npos) {
50 		if (!silent) {
51 			wxMessageBoxEx(_("fzstorj could not be started.\nPlease make sure this executable exists in the same directory as the main FileZilla executable."), _("Error starting program"), wxICON_EXCLAMATION);
52 		}
53 		return false;
54 	}
55 
56 	executable = executable.substr(0, pos + 1) + L"fzstorj";
57 #ifdef FZ_WINDOWS
58 	executable += L".exe";
59 #endif
60 
61 	m_process = std::make_unique<fz::process>();
62 	if (!m_process->spawn(fz::to_native(executable))) {
63 		m_process.reset();
64 
65 		if (!silent) {
66 			wxMessageBoxEx(_("fzstorj could not be started.\nPlease make sure this executable exists in the same directory as the main FileZilla executable."), _("Error starting program"), wxICON_EXCLAMATION);
67 		}
68 		return false;
69 	}
70 
71 	return true;
72 }
73 
Send(std::wstring const & cmd)74 bool CStorjKeyInterface::Send(std::wstring const& cmd)
75 {
76 	if (!m_process) {
77 		return false;
78 	}
79 
80 	std::string utf8 = fz::to_utf8(cmd) + "\n";
81 	if (!m_process->write(utf8)) {
82 		m_process.reset();
83 
84 		wxMessageBoxEx(_("Could not send command to fzstorj."), _("Command failed"), wxICON_EXCLAMATION);
85 		return false;
86 	}
87 
88 	return true;
89 }
90 
GetReply(std::wstring & reply)91 CStorjKeyInterface::ReplyCode CStorjKeyInterface::GetReply(std::wstring & reply)
92 {
93 	if (!m_process) {
94 		return error;
95 	}
96 
97 	char buffer[100];
98 
99 	std::string input;
100 
101 	for (;;) {
102 		size_t pos = input.find_first_of("\r\n");
103 		if (pos == std::string::npos) {
104 			int read = m_process->read(buffer, 100);
105 			if (read <= 0) {
106 				wxMessageBoxEx(_("Could not get reply from fzstorj."), _("Command failed"), wxICON_EXCLAMATION);
107 				m_process.reset();
108 				return error;
109 			}
110 
111 			input.append(buffer, read);
112 			continue;
113 		}
114 
115 		// Strip everything behind first linebreak.
116 		if (!pos) {
117 			input = input.substr(1);
118 			continue;
119 		}
120 
121 		char c = input[0];
122 
123 		reply = fz::to_wstring_from_utf8(input.substr(1, pos - 1));
124 		input = input.substr(pos + 1);
125 
126 		if (c == '1') {
127 			return success;
128 		}
129 		else if (c == '2') {
130 			return error;
131 		}
132 		// Ignore others
133 	}
134 }
135 
ProcessFailed() const136 bool CStorjKeyInterface::ProcessFailed() const
137 {
138 	return m_initialized && !m_process;
139 }
140