#ifndef __IMAPServer_h__ # define __IMAPServer_h__ # include "TCPServer.h" # include "TLSInfo.h" # include "Exception.h" # include "IMAPSession.h" # include "MailFileSystem.h" # include "__IMAP_APPEND.h" # include "__IMAP_AUTHENTICATE.h" # include "__IMAP_CAPABILITY.h" # include "__IMAP_CHECK.h" # include "__IMAP_CLOSE.h" # include "__IMAP_COPY.h" # include "__IMAP_CREATE.h" # include "__IMAP_DELETE.h" # include "__IMAP_EXAMINE.h" # include "__IMAP_EXPUNGE.h" # include "__IMAP_FETCH.h" # include "__IMAP_LIST.h" # include "__IMAP_LOGIN.h" # include "__IMAP_LOGOUT.h" # include "__IMAP_LSUB.h" # include "__IMAP_NOOP.h" # include "__IMAP_RENAME.h" # include "__IMAP_SEARCH.h" # include "__IMAP_SELECT.h" # include "__IMAP_STARTTLS.h" # include "__IMAP_STATUS.h" # include "__IMAP_STORE.h" # include "__IMAP_SUBSCRIBE.h" # include "__IMAP_UID.h" # include "__IMAP_UNSUBSCRIBE.h" namespace mail { class IMAPServer : public core::TCPServer { public: IMAPServer(core::EPoll &epoll, std::string hostName, MailFileSystem &mailFileSystem, core::IPAddress ipAddress, core::TLSInfo *tlsInfo) : TCPServer(epoll, ipAddress, tlsInfo, " ", 10, "IMAP Server"), mailFileSystem(mailFileSystem), hostName(hostName) { commands.add(_imap_append, "APPEND"); // Was registered as "AUTHENTCATE" (missing the I) - no // correctly-spelled client request could ever match it. commands.add(_imap_authenticate, "AUTHENTICATE"); // RFC 3501 6.1.1/6.1.2/6.1.3: CAPABILITY, NOOP, and LOGOUT MUST // be supported in every connection state - none of the three // were registered at all before. commands.add(_imap_capability, "CAPABILITY"); commands.add(_imap_check, "CHECK"); commands.add(_imap_close, "CLOSE"); commands.add(_imap_copy, "COPY"); commands.add(_imap_create, "CREATE"); commands.add(_imap_delete, "DELETE"); // Was registered as "EXAAMINE" (double A) - same problem. commands.add(_imap_examine, "EXAMINE"); commands.add(_imap_expunge, "EXPUNGE"); commands.add(_imap_fetch, "FETCH"); commands.add(_imap_list, "LIST"); commands.add(_imap_login, "LOGIN"); commands.add(_imap_logout, "LOGOUT"); commands.add(_imap_lsub, "LSUB"); commands.add(_imap_noop, "NOOP"); commands.add(_imap_rename, "RENAME"); commands.add(_imap_search, "SEARCH"); commands.add(_imap_select, "SELECT"); commands.add(_imap_starttls, "STARTTLS"); commands.add(_imap_status, "STATUS"); commands.add(_imap_store, "STORE"); commands.add(_imap_subscribe, "SUBSCRIBE"); commands.add(_imap_uid, "UID"); commands.add(_imap_unsubscribe, "UNSUBSCRIBE"); } MailFileSystem &mailFileSystem; std::string hostName; // Without this override, TCPServer's default getSocketAccept() // returns a plain TCPSession for every accepted connection, not // an IMAPSession - IMAPSession::onConnected() (the greeting // banner) then never fires, and IMAPCommand's session casts // ((IMAPSession &)session) reinterpret a TCPSession's memory as // an IMAPSession, undefined behavior the moment any handler // touches a member IMAPSession actually has and TCPSession // doesn't. IMAPSession *getSocketAccept(core::EPoll &ePoll) override { return new IMAPSession(ePoll, *this); } private: __IMAP_APPEND _imap_append; __IMAP_AUTHENTICATE _imap_authenticate; __IMAP_CAPABILITY _imap_capability; __IMAP_CHECK _imap_check; __IMAP_CLOSE _imap_close; __IMAP_COPY _imap_copy; __IMAP_CREATE _imap_create; __IMAP_DELETE _imap_delete; __IMAP_EXAMINE _imap_examine; __IMAP_EXPUNGE _imap_expunge; __IMAP_FETCH _imap_fetch; __IMAP_LIST _imap_list; __IMAP_LOGIN _imap_login; __IMAP_LOGOUT _imap_logout; __IMAP_LSUB _imap_lsub; __IMAP_NOOP _imap_noop; __IMAP_RENAME _imap_rename; __IMAP_SEARCH _imap_search; __IMAP_SELECT _imap_select; __IMAP_STARTTLS _imap_starttls; __IMAP_STATUS _imap_status; __IMAP_STORE _imap_store; __IMAP_SUBSCRIBE _imap_subscribe; __IMAP_UID _imap_uid; __IMAP_UNSUBSCRIBE _imap_unsubscribe; }; } #endif