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