1 #ifndef FILEZILLA_ENGINE_NOTIFICATION_HEADER
2 #define FILEZILLA_ENGINE_NOTIFICATION_HEADER
3 
4 // Notification overview
5 // ---------------------
6 
7 // To inform the application about what's happening, the engine sends
8 // some notifications to the application through the notification callback
9 // passed to the engine on construction.
10 // Whenever the callback is called, CFileZillaEngine::GetNextNotification
11 // has to be called until it returns 0 to re-arm the callback,
12 // or you will lose important notifications or your memory will fill with
13 // pending notifications.
14 //
15 // Note: It may be called from a worker thread.
16 
17 // A special class of notifications are the asynchronous requests. These
18 // requests have to be answered. Once processed, call
19 // CFileZillaEngine::SetAsyncRequestReply to continue the current operation.
20 
21 #include "commands.h"
22 #include "local_path.h"
23 #include "logging.h"
24 #include "server.h"
25 
26 #include <libfilezilla/time.hpp>
27 #include <libfilezilla/tls_info.hpp>
28 
29 enum NotificationId
30 {
31 	nId_logmsg,				// notification about new messages for the message log
32 	nId_operation,			// operation reply codes
33 	nId_transferstatus,		// transfer information: bytes transferred, transfer speed and such
34 	nId_listing,			// directory listings
35 	nId_asyncrequest,		// asynchronous request
36 	nId_sftp_encryption,	// information about key exchange, encryption algorithms and so on for SFTP
37 	nId_local_dir_created,	// local directory has been created
38 	nId_serverchange,		// With some protocols, actual server identity isn't known until after logon
39 	nId_ftp_tls_resumption
40 };
41 
42 // Async request IDs
43 enum RequestId
44 {
45 	reqId_fileexists,          // Target file already exists, awaiting further instructions
46 	reqId_interactiveLogin,    // gives a challenge prompt for a password
47 	reqId_hostkey,             // used only by SSH/SFTP to indicate new host key
48 	reqId_hostkeyChanged,      // used only by SSH/SFTP to indicate changed host key
49 	reqId_certificate,         // sent after a successful TLS handshake to allow certificate
50 	                           // validation.
51 	reqId_insecure_connection, // If using opportunistic FTP over TLS, or a completely
52 	                           // unprotected protocol ask user whether he really wants
53 	                           // to use a plaintext connection.
54 	reqId_tls_no_resumption
55 };
56 
57 class FZC_PUBLIC_SYMBOL CNotification
58 {
59 public:
60 	virtual ~CNotification() = default;
61 	virtual NotificationId GetID() const = 0;
62 
63 protected:
64 	CNotification() = default;
65 	CNotification(CNotification const&) = default;
66 	CNotification& operator=(CNotification const&) = default;
67 };
68 
69 template<NotificationId id>
70 class FZC_PUBLIC_SYMBOL CNotificationHelper : public CNotification
71 {
72 public:
GetID()73 	virtual NotificationId GetID() const final { return id; }
74 
75 protected:
76 	CNotificationHelper<id>() = default;
77 	CNotificationHelper<id>(CNotificationHelper<id> const&) = default;
78 	CNotificationHelper<id>& operator=(CNotificationHelper<id> const&) = default;
79 };
80 
81 class FZC_PUBLIC_SYMBOL CLogmsgNotification final : public CNotificationHelper<nId_logmsg>
82 {
83 public:
CLogmsgNotification(logmsg::type t)84 	explicit CLogmsgNotification(logmsg::type t)
85 		: msgType(t)
86 	{}
87 
88 	template<typename String>
CLogmsgNotification(logmsg::type t,String && m,fz::datetime const & time)89 	CLogmsgNotification(logmsg::type t, String && m, fz::datetime const& time)
90 		: msg(std::forward<String>(m))
91 		, time_(time)
92 		, msgType(t)
93 	{
94 	}
95 
96 	std::wstring msg;
97 	fz::datetime time_;
98 	logmsg::type msgType{logmsg::status}; // Type of message, see logging.h for details
99 };
100 
101 // If CFileZillaEngine does return with FZ_REPLY_WOULDBLOCK, you will receive
102 // a nId_operation notification once the operation ends.
103 class FZC_PUBLIC_SYMBOL COperationNotification final : public CNotificationHelper<nId_operation>
104 {
105 public:
106 	COperationNotification() = default;
COperationNotification(int replyCode,Command commandId)107 	COperationNotification(int replyCode, Command commandId)
108 		: replyCode_(replyCode)
109 		, commandId_(commandId)
110 	{}
111 
112 	int replyCode_{};
113 	Command commandId_{Command::none};
114 };
115 
116 // You get this type of notification everytime a directory listing has been
117 // requested explicitely or when a directory listing was retrieved implicitely
118 // during another operation, e.g. file transfers.
119 //
120 // Primary notifications are those resulting from a CListCommand, other ones
121 // can happen spontanously through other actions.
122 class CDirectoryListing;
123 class FZC_PUBLIC_SYMBOL CDirectoryListingNotification final : public CNotificationHelper<nId_listing>
124 {
125 public:
126 	explicit CDirectoryListingNotification(CServerPath const& path, bool const primary, bool const failed = false);
Primary()127 	bool Primary() const { return primary_; }
Failed()128 	bool Failed() const { return m_failed; }
GetPath()129 	const CServerPath GetPath() const { return m_path; }
130 
131 protected:
132 	bool const primary_{};
133 	bool m_failed{};
134 	CServerPath m_path;
135 };
136 
137 class FZC_PUBLIC_SYMBOL CAsyncRequestNotification : public CNotificationHelper<nId_asyncrequest>
138 {
139 public:
140 	virtual RequestId GetRequestID() const = 0;
141 	unsigned int requestNumber{}; // Do never change this
142 
143 protected:
144 	CAsyncRequestNotification() = default;
145 	CAsyncRequestNotification(CAsyncRequestNotification const&) = default;
146 	CAsyncRequestNotification& operator=(CAsyncRequestNotification const&) = default;
147 };
148 
149 class FZC_PUBLIC_SYMBOL CFileExistsNotification final : public CAsyncRequestNotification
150 {
151 public:
152 	virtual RequestId GetRequestID() const;
153 
154 	bool download{};
155 
156 	std::wstring localFile;
157 	int64_t localSize{-1};
158 	fz::datetime localTime;
159 
160 	std::wstring remoteFile;
161 	CServerPath remotePath;
162 	int64_t remoteSize{-1};
163 	fz::datetime remoteTime;
164 
165 	bool ascii{};
166 
167 	bool canResume{};
168 
169 	// overwriteAction will be set by the request handler
170 	enum OverwriteAction : signed char
171 	{
172 		unknown = -1,
173 		ask,
174 		overwrite,
175 		overwriteNewer,	// Overwrite if source file is newer than target file
176 		overwriteSize,	// Overwrite if source file is is different in size than target file
177 		overwriteSizeOrNewer,	// Overwrite if source file is different in size or newer than target file
178 		resume, // Overwrites if cannot be resumed
179 		rename,
180 		skip,
181 
182 		ACTION_COUNT
183 	};
184 
185 	// Set overwriteAction to the desired action
186 	OverwriteAction overwriteAction{unknown};
187 
188 	// On uploads: Set to new filename if overwriteAction is rename. Might trigger further
189 	// file exists notifications if new target file exists as well.
190 	std::wstring newName;
191 
192 	// On downloads: New writer if overwriteAction is rename
193 	writer_factory_holder new_writer_factory_;
194 };
195 
196 class FZC_PUBLIC_SYMBOL CInteractiveLoginNotification final : public CAsyncRequestNotification
197 {
198 public:
199 	enum type {
200 		interactive,
201 		keyfile
202 	};
203 
204 	CInteractiveLoginNotification(type t, std::wstring const& challenge, bool repeated);
205 	virtual RequestId GetRequestID() const;
206 
207 	// Set to true if you have set a password
208 	bool passwordSet{};
209 
210 	CServer server;
211 	ServerHandle handle_;
212 	Credentials credentials;
213 
GetChallenge()214 	std::wstring const& GetChallenge() const { return m_challenge; }
215 
GetType()216 	type GetType() const { return m_type; }
217 
IsRepeated()218 	bool IsRepeated() const { return m_repeated; }
219 
220 protected:
221 	// Password prompt string as given by the server
222 	std::wstring const m_challenge;
223 
224 	type const m_type;
225 
226 	bool const m_repeated;
227 };
228 
229 class FZC_PUBLIC_SYMBOL CTransferStatus final
230 {
231 public:
CTransferStatus()232 	CTransferStatus() {}
CTransferStatus(int64_t total,int64_t start,bool l)233 	CTransferStatus(int64_t total, int64_t start, bool l)
234 		: totalSize(total)
235 		, startOffset(start)
236 		, currentOffset(start)
237 		, list(l)
238 	{}
239 
240 	fz::datetime started;
241 	int64_t totalSize{-1};		// Total size of the file to transfer, -1 if unknown
242 	int64_t startOffset{-1};
243 	int64_t currentOffset{-1};
244 
clear()245 	void clear() { startOffset = -1; }
empty()246 	bool empty() const { return startOffset < 0; }
247 
248 	explicit operator bool() const { return !empty(); }
249 
250 	// True on download notifications iff currentOffset != startOffset.
251 	// True on FTP upload notifications iff currentOffset != startOffset
252 	// AND after the first accepted data after the first EWOULDBLOCK.
253 	// SFTP uploads: Set to true if currentOffset >= startOffset + 65536.
254 	bool madeProgress{};
255 
256 	bool list{};
257 };
258 
259 class FZC_PUBLIC_SYMBOL CTransferStatusNotification final : public CNotificationHelper<nId_transferstatus>
260 {
261 public:
CTransferStatusNotification()262 	CTransferStatusNotification() {}
263 	CTransferStatusNotification(CTransferStatus const& status);
264 
265 	CTransferStatus const& GetStatus() const;
266 
267 protected:
268 	CTransferStatus const status_;
269 };
270 
271 class FZC_PUBLIC_SYMBOL CSftpEncryptionDetails
272 {
273 public:
274 	virtual ~CSftpEncryptionDetails() = default;
275 
276 	std::wstring hostKeyAlgorithm;
277 	std::wstring hostKeyFingerprint;
278 	std::wstring kexAlgorithm;
279 	std::wstring kexHash;
280 	std::wstring kexCurve;
281 	std::wstring cipherClientToServer;
282 	std::wstring cipherServerToClient;
283 	std::wstring macClientToServer;
284 	std::wstring macServerToClient;
285 };
286 
287 // Notification about new or changed hostkeys, only used by SSH/SFTP transfers.
288 // GetRequestID() returns either reqId_hostkey or reqId_hostkeyChanged
289 class FZC_PUBLIC_SYMBOL CHostKeyNotification final : public CAsyncRequestNotification, public CSftpEncryptionDetails
290 {
291 public:
292 	CHostKeyNotification(std::wstring const& host, int port, CSftpEncryptionDetails const& details, bool changed = false);
293 
294 	virtual RequestId GetRequestID() const;
295 
296 	std::wstring GetHost() const;
297 	int GetPort() const;
298 
299 	// Set to true if you trust the server
300 	bool m_trust{};
301 
302 	// If m_truest is true, set this to true to always trust this server
303 	// in future.
304 	bool m_alwaysTrust{};
305 
306 protected:
307 
308 	const std::wstring m_host;
309 	const int m_port;
310 	const bool m_changed;
311 };
312 
313 class FZC_PUBLIC_SYMBOL CCertificateNotification final : public CAsyncRequestNotification
314 {
315 public:
316 	CCertificateNotification(fz::tls_session_info && info);
GetRequestID()317 	virtual RequestId GetRequestID() const { return reqId_certificate; }
318 
319 	fz::tls_session_info info_;
320 
321 	bool trusted_{};
322 };
323 
324 class FZC_PUBLIC_SYMBOL CSftpEncryptionNotification final : public CNotificationHelper<nId_sftp_encryption>, public CSftpEncryptionDetails
325 {
326 };
327 
328 class FZC_PUBLIC_SYMBOL CLocalDirCreatedNotification final : public CNotificationHelper<nId_local_dir_created>
329 {
330 public:
331 	CLocalPath dir;
332 };
333 
334 class FZC_PUBLIC_SYMBOL CInsecureConnectionNotification final : public CAsyncRequestNotification
335 {
336 public:
337 	CInsecureConnectionNotification(CServer const& server);
GetRequestID()338 	virtual RequestId GetRequestID() const { return reqId_insecure_connection; }
339 
340 	CServer const server_;
341 	bool allow_{};
342 };
343 
344 class FZC_PUBLIC_SYMBOL ServerChangeNotification final : public CNotificationHelper<nId_serverchange>
345 {
346 public:
347 	ServerChangeNotification() = default;
348 
ServerChangeNotification(CServer const & server)349 	explicit ServerChangeNotification(CServer const& server)
350 	    : newServer_(server)
351 	{}
352 
353 	CServer newServer_;
354 };
355 
356 class FZC_PUBLIC_SYMBOL FtpTlsResumptionNotification final : public CNotificationHelper<nId_ftp_tls_resumption>
357 {
358 public:
359 	FtpTlsResumptionNotification() = default;
360 
FtpTlsResumptionNotification(CServer const & server)361 	explicit FtpTlsResumptionNotification(CServer const& server)
362 	    : server_(server)
363 	{}
364 
365 	CServer const server_;
366 };
367 
368 class FZC_PUBLIC_SYMBOL FtpTlsNoResumptionNotification final : public CAsyncRequestNotification
369 {
370 public:
FtpTlsNoResumptionNotification(CServer const & server)371 	FtpTlsNoResumptionNotification(CServer const& server)
372 	    : server_(server)
373 	{}
374 
GetRequestID()375 	virtual RequestId GetRequestID() const { return reqId_tls_no_resumption; }
376 
377 	CServer const server_;
378 	bool allow_{};
379 };
380 
381 #endif
382