From 44388ac49531af9e2565f76ef99ff7afb757b3fb Mon Sep 17 00:00:00 2001 From: Erwin Hoffmann Date: Thu, 21 Sep 2023 17:36:16 +0200 Subject: all sources --- src/include/address.h | 29 +++ src/include/argparser.h | 69 ++++++ src/include/authenticate.h | 18 ++ src/include/base64.h | 18 ++ src/include/broker.h | 84 ++++++++ src/include/convert.h | 298 ++++++++++++++++++++++++++ src/include/depot.h | 154 +++++++++++++ src/include/globals.h | 25 +++ src/include/imapparser.h | 171 +++++++++++++++ src/include/imapserver.h | 37 ++++ src/include/iodevice.h | 382 +++++++++++++++++++++++++++++++++ src/include/iofactory.h | 53 +++++ src/include/mailbox.h | 136 ++++++++++++ src/include/maildir.h | 190 ++++++++++++++++ src/include/maildirmessage.h | 309 ++++++++++++++++++++++++++ src/include/message.h | 151 +++++++++++++ src/include/mime-inputsource.h | 141 ++++++++++++ src/include/mime-utils.h | 27 +++ src/include/mime.h | 121 +++++++++++ src/include/multilogdevice.h | 29 +++ src/include/operators.h | 476 +++++++++++++++++++++++++++++++++++++++++ src/include/pendingupdates.h | 107 +++++++++ src/include/recursivedescent.h | 64 ++++++ src/include/regmatch.h | 17 ++ src/include/session.h | 116 ++++++++++ src/include/status.h | 50 +++++ src/include/stdiodevice.h | 31 +++ src/include/syslogdevice.h | 41 ++++ src/include/tools.h | 23 ++ 29 files changed, 3367 insertions(+) create mode 100644 src/include/address.h create mode 100644 src/include/argparser.h create mode 100644 src/include/authenticate.h create mode 100644 src/include/base64.h create mode 100644 src/include/broker.h create mode 100644 src/include/convert.h create mode 100644 src/include/depot.h create mode 100644 src/include/globals.h create mode 100644 src/include/imapparser.h create mode 100644 src/include/imapserver.h create mode 100644 src/include/iodevice.h create mode 100644 src/include/iofactory.h create mode 100644 src/include/mailbox.h create mode 100644 src/include/maildir.h create mode 100644 src/include/maildirmessage.h create mode 100644 src/include/message.h create mode 100644 src/include/mime-inputsource.h create mode 100644 src/include/mime-utils.h create mode 100644 src/include/mime.h create mode 100644 src/include/multilogdevice.h create mode 100644 src/include/operators.h create mode 100644 src/include/pendingupdates.h create mode 100644 src/include/recursivedescent.h create mode 100644 src/include/regmatch.h create mode 100644 src/include/session.h create mode 100644 src/include/status.h create mode 100644 src/include/stdiodevice.h create mode 100644 src/include/syslogdevice.h create mode 100644 src/include/tools.h (limited to 'src/include') diff --git a/src/include/address.h b/src/include/address.h new file mode 100644 index 0000000..a8aded9 --- /dev/null +++ b/src/include/address.h @@ -0,0 +1,29 @@ +/** -------------------------------------------------------------------- + * @file address.h + * @brief Declaration of the Address class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef address_h_included +#define address_h_included +#include + +namespace Binc { + + //------------------------------------------------------------------------ + class Address { + public: + std::string name; + std::string local; + std::string host; + + //-- + std::string toParenList(void) const; + + //-- + Address(const std::string &name, const std::string &addr); + Address(const std::string &wholeaddr); + }; +} + +#endif diff --git a/src/include/argparser.h b/src/include/argparser.h new file mode 100644 index 0000000..6106974 --- /dev/null +++ b/src/include/argparser.h @@ -0,0 +1,69 @@ +/** -------------------------------------------------------------------- + * @file argparser.h + * @brief Declaration of the argument parser class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef ARGPARSER_H_INCLUDED +#define ARGPARSER_H_INCLUDED +#include +#include +#include + +namespace Binc { + class ArgOpts { + public: + std::string c; + bool b; + bool o; + std::string desc; + + inline ArgOpts(const std::string &chr, bool boolean, bool optional, + const std::string &descr) + { + c = chr; + b = boolean; + o = optional; + desc = descr; + } + }; + + class CommandLineArgs { + public: + CommandLineArgs(void); + + bool parse(int argc, char *argv[]); + std::string errorString(void) const; + + int argc(void) const; + + const std::string operator [](const std::string &arg) const; + + void addOptional(const std::string &arg, const std::string &desc, + bool boolean); + void addRequired(const std::string &arg, const std::string &desc, + bool boolean); + bool hasArg(const std::string &arg) const; + + std::string usageString(void) const; + + void setTail(const std::string &str); + + const std::vector &getUnqualifiedArgs() const; + + private: + void registerArg(const std::string &arg, const std::string &desc, + bool boolean, bool optional); + + std::string errString; + std::map reg; + std::map args; + std::map passedArgs; + std::vector unqualified; + std::string tail; + std::string head; + int ac; + }; +} + +#endif diff --git a/src/include/authenticate.h b/src/include/authenticate.h new file mode 100644 index 0000000..0ef6796 --- /dev/null +++ b/src/include/authenticate.h @@ -0,0 +1,18 @@ +/** -------------------------------------------------------------------- + * @file authenticate.h + * @brief Declaration of the common authentication mechanism. + * @author Andreas Aardal Hanssen, Erwin Hoffmann + * @date 2002-2005, 2023 + * ----------------------------------------------------------------- **/ +#ifndef authenticate_h_included +#define authenticate_h_included +#include + +#include "depot.h" + +namespace Binc { + int authenticate(Depot &, const std::string &username, + const std::string &password, const std::string &challenge); +} + +#endif diff --git a/src/include/base64.h b/src/include/base64.h new file mode 100644 index 0000000..25b0ff4 --- /dev/null +++ b/src/include/base64.h @@ -0,0 +1,18 @@ +/** -------------------------------------------------------------------- + * @file base64.h + * @brief Declaration of base64 Utilities + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef base64_h_included +#define base64_h_included +#include + +namespace Binc { + + std::string base64decode(const std::string &s_in); + std::string base64encode(const std::string &s_in); + +} + +#endif diff --git a/src/include/broker.h b/src/include/broker.h new file mode 100644 index 0000000..6d148ae --- /dev/null +++ b/src/include/broker.h @@ -0,0 +1,84 @@ +/** -------------------------------------------------------------------- + * @file broker.h + * @brief Declaration of the Broker class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef broker_h_included +#define broker_h_included +#include "depot.h" +#include "operators.h" + +#include +#include + +namespace Binc { + + class Request; + class Broker; + + //------------------------------------------------------------------ + class BrokerFactory { + private: + std::map brokers; + + //-- + BrokerFactory(void); + + mutable std::string lastError; + + public: + Broker *getBroker(int state); + void assign(const std::string &fname, Operator *o); + void addCapability(const std::string &c); + Operator *getOperator(int state, const std::string &name) const; + + inline const std::string &getLastError(void) const; + inline void setLastError(const std::string &error) const; + + //-- + static BrokerFactory &getInstance(void); + ~BrokerFactory(void); + }; + + //------------------------------------------------------------------ + inline const std::string &BrokerFactory::getLastError(void) const + { + return lastError; + } + + //------------------------------------------------------------------ + inline void BrokerFactory::setLastError(const std::string &error) const + { + lastError = error; + } + + //------------------------------------------------------------------ + class Broker { + private: + std::map operators; + std::map deletables; + + public: + Operator * get(const std::string &name) const; + void assign(const std::string &fname, Operator *o, bool deletable = false); + Operator::ParseResult parseStub(Request &cmd); + + //-- + inline Broker(Broker &); + inline Broker(const Broker &); + Broker(void); + ~Broker(void); + }; + + inline Broker::Broker(Broker &) + { + } + + inline Broker::Broker(const Broker &) + { + } + +} + +#endif diff --git a/src/include/convert.h b/src/include/convert.h new file mode 100644 index 0000000..cea2906 --- /dev/null +++ b/src/include/convert.h @@ -0,0 +1,298 @@ +/** -------------------------------------------------------------------- + * @file convert.h + * @brief Declaration of miscellaneous convertion functions. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ + +#ifndef convert_h_included +#define convert_h_included +#include +#include +#include +#include +#include + +#include +#include + +#include "address.h" +#include "depot.h" + +namespace Binc { + + //---------------------------------------------------------------------- + inline std::string toString(int i_in) + { + char intbuf[16]; + snprintf(intbuf, sizeof(intbuf), "%d", i_in); + return std::string(intbuf); + } + + //---------------------------------------------------------------------- + inline std::string toString(unsigned int i_in) + { + char intbuf[16]; + snprintf(intbuf, sizeof(intbuf), "%u", i_in); + return std::string(intbuf); + } + + //---------------------------------------------------------------------- + inline std::string toString(unsigned long i_in) + { + char longbuf[40]; + snprintf(longbuf, sizeof(longbuf), "%lu", i_in); + return std::string(longbuf); + } + + //---------------------------------------------------------------------- + inline std::string toString(const char *i_in) + { + return std::string(i_in); + } + + //---------------------------------------------------------------------- + inline int atoi(const std::string &s_in) + { + return ::atoi(s_in.c_str()); + } + + //---------------------------------------------------------------------- + inline std::string toHex(const std::string &s) + { + const char hexchars[] = "0123456789abcdef"; + std::string tmp; + for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { + unsigned char c = (unsigned char)*i; + tmp += hexchars[((c & 0xf0) >> 4)]; + tmp += hexchars[c & 0x0f]; + } + + return tmp; + } + + //---------------------------------------------------------------------- + inline std::string fromHex(const std::string &s) + { + // const + char hexchars[] = "0123456789abcdef"; + std::string tmp; + for (std::string::const_iterator i = s.begin(); + i != s.end() && i + 1 != s.end(); i += 2) { + int n; + unsigned char c = *i; + unsigned char d = *(i + 1); + + char *t; + if ((t = strchr(hexchars, c)) == 0) return "out of range"; + n = (t - hexchars) << 4; + + if ((t = strchr(hexchars, d)) == 0) return "out of range"; + n += (t - hexchars); + + if (n >= 0 && n <= 255) + tmp += (char) n; + else + return "out of range"; + } + + return tmp; + } + + //---------------------------------------------------------------------- + inline std::string toImapString(const std::string &s_in) + { + for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) { + unsigned char c = (unsigned char)*i; + if (c <= 31 || c >= 127 || c == '\"' || c == '\\') + return "{" + toString(s_in.length()) + "}\r\n" + s_in; + } + + return "\"" + s_in + "\""; + } + + //---------------------------------------------------------------------- + inline void uppercase(std::string &input) + { + for (std::string::iterator i = input.begin(); i != input.end(); ++i) + *i = toupper(*i); + } + + //---------------------------------------------------------------------- + inline void lowercase(std::string &input) + { + for (std::string::iterator i = input.begin(); i != input.end(); ++i) + *i = tolower(*i); + } + + //---------------------------------------------------------------------- + inline void chomp(std::string &s_in, const std::string &chars = " \t\r\n") + { + int n = s_in.length(); + while (n > 1 && chars.find(s_in[n - 1]) != std::string::npos) + s_in.resize(n-- - 1); + } + + //---------------------------------------------------------------------- + inline void trim(std::string &s_in, const std::string &chars = " \t\r\n") + { + while (s_in != "" && chars.find(s_in[0]) != std::string::npos) + s_in = s_in.substr(1); + chomp(s_in, chars); + } + + //---------------------------------------------------------------------- + inline const std::string unfold(const std::string &a, + bool removecomment = true) + { + std::string tmp; + bool incomment = false; + bool inquotes = false; + for (std::string::const_iterator i = a.begin(); i != a.end(); ++i) { + unsigned char c = (unsigned char)*i; + if (!inquotes && removecomment) { + if (c == '(') { + incomment = true; + tmp += " "; + } else if (c == ')') { + incomment = false; + } else if (c != 0x0a && c != 0x0d) { + tmp += *i; + } + } else if (c != 0x0a && c != 0x0d) { + tmp += *i; + } + + if (!incomment) { + if (*i == '\"') + inquotes = !inquotes; + } + } + + trim(tmp); + return tmp; + } + + //---------------------------------------------------------------------- + inline void split(const std::string &s_in, const std::string &delim, + std::vector &dest, bool skipempty = true) + { + std::string token; + for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) { + if (delim.find(*i) != std::string::npos) { + if (!skipempty || token != "") + dest.push_back(token); + token = ""; + } else + token += *i; + } + + if (token != "") + dest.push_back(token); + } + + //---------------------------------------------------------------------- + inline void splitAddr(const std::string &s_in, + std::vector &dest, bool skipempty = true) + { + static const std::string delim = ","; + std::string token; + bool inquote = false; + for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) { + if (inquote && *i == '\"') inquote = false; + else if (!inquote && *i == '\"') inquote = true; + + if (!inquote && delim.find(*i) != std::string::npos) { + if (!skipempty || token != "") dest.push_back(token); + token = ""; + } else + token += *i; + } + if (token != "") + dest.push_back(token); + } + + //---------------------------------------------------------------------- + inline std::string toCanonMailbox(const std::string &s_in) + { + if (s_in.find("..") != std::string::npos) return ""; + + if (s_in.length() >= 5) { + std::string a = s_in.substr(0, 5); + uppercase(a); + return a == "INBOX" ? + a + (s_in.length() > 5 ? s_in.substr(5) : "") : s_in; + } + + return s_in; + } + + //------------------------------------------------------------------------ + inline std::string toRegex(const std::string &s_in, char delimiter) + { + std::string regex = "^"; + for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) { + if (*i == '.' || *i == '[' || *i == ']' || *i == '{' || *i == '}' || + *i == '(' || *i == ')' || *i == '^' || *i == '$' || *i == '?' || + *i == '+' || *i == '\\') { + regex += "\\"; + regex += *i; + } else if (*i == '*') + regex += ".*?"; + else if (*i == '%') { + regex += "(\\"; + regex += delimiter; + regex += "){0,1}"; + regex += "[^\\"; + regex += delimiter; + regex += "]*?"; + } else + regex += *i; + } + + if (regex[regex.length() - 1] == '?') + regex[regex.length() - 1] = '$'; + else + regex += "$"; + + return regex; + } + + //------------------------------------------------------------------------ + class BincStream { + private: + std::string nstr; + + public: + //-- + BincStream &operator << (std::ostream&(*)(std::ostream&)); + BincStream &operator << (const std::string &t); + BincStream &operator << (unsigned long t); + BincStream &operator << (unsigned int t); + BincStream &operator << (int t); + BincStream &operator << (char t); + + //-- + std::string popString(unsigned int size); + + //-- + char popChar(void); + void unpopChar(char c); + void unpopStr(const std::string &s); + + //-- + const std::string &str(void) const; + + //-- + unsigned int getSize(void) const; + + //-- + void clear(void); + + //-- + BincStream(void); + ~BincStream(void); + }; +} + +#endif diff --git a/src/include/depot.h b/src/include/depot.h new file mode 100644 index 0000000..844a987 --- /dev/null +++ b/src/include/depot.h @@ -0,0 +1,154 @@ +/** -------------------------------------------------------------------- + * @filec depot.h + * @file Declaration of the Depot class (the mail storage) + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef depot_h_included +#define depot_h_included +#include +#include +#include + +#include + +namespace Binc { + + class Mailbox; + class Depot; + class Status; + + //------------------------------------------------------------------ + class DepotFactory { + private: + std::vector depots; + DepotFactory(void); + + public: + void assign(Depot *); + Depot *get(const std::string &name) const; + + static DepotFactory &getInstance(void); + ~DepotFactory(void); + }; + + //------------------------------------------------------------------ + class Depot { + public: + //-- + class iterator { + public: + std::string operator * (void) const; + void operator ++ (void); + bool operator != (iterator) const; + bool operator == (iterator) const; + + iterator(void); + iterator(const iterator ©); + iterator(DIR *, struct dirent *); + ~iterator(void); + + void deref(void); + + iterator &operator =(const iterator ©); + + friend class Depot; + + private: + DIR *dirp; + struct dirent *direntp; + int *ref; + }; + + private: + iterator enditerator; + std::vector backends; + Mailbox *defaultmailbox; + Mailbox *selectedmailbox; + std::vector subscribed; + std::string personalNamespace; + std::string othersNamespace; + std::string sharedNamespace; + + protected: + mutable std::string lastError; + std::string name; + char delimiter; + mutable std::map mailboxstatuses; + + public: + virtual iterator begin(const std::string &) const; + virtual const iterator &end(void) const; + + void setDelimiter(char); + const char getDelimiter(void) const; + + virtual void assign(Mailbox *); + + bool setDefaultType(const std::string &n); + Mailbox *getDefault(void) const; + virtual Mailbox *get(const std::string &path) const; + + virtual bool setSelected(Mailbox *); + virtual Mailbox *getSelected(void) const; + void resetSelected(void); + + bool getStatus(const std::string &s_in, Status &dest) const; + + const std::string &getName(void) const; + + virtual const std::string &getPersonalNamespace(void) const; + virtual const std::string &getOthersNamespace(void) const; + virtual const std::string &getSharedNamespace(void) const; + + virtual std::string mailboxToFilename(const std::string &m) const = 0; + virtual std::string filenameToMailbox(const std::string &m) const = 0; + + virtual bool createMailbox(const std::string &m) const; + virtual bool deleteMailbox(const std::string &m) const; + virtual bool renameMailbox(const std::string &m, const std::string &n) const; + + const std::string &getLastError(void) const; + void setLastError(const std::string &error) const; + + virtual std::vector getSubscriptions(void) const; + virtual void subscribeTo(const std::string mailbox); + virtual bool unsubscribeTo(const std::string mailbox); + virtual void loadSubscribes(void); + virtual bool saveSubscribes(void) const; + + //-- + Depot(void); + Depot(const std::string &name); + virtual ~Depot(void); + }; + + //------------------------------------------------------------------ + class MaildirPPDepot : public Depot { + public: + std::string mailboxToFilename(const std::string &m) const; + std::string filenameToMailbox(const std::string &m) const; + + const std::string &getPersonalNamespace(void) const; + + //-- + MaildirPPDepot(); + ~MaildirPPDepot(); + private: + std::string privateNamespace; + }; + + //------------------------------------------------------------------ + class IMAPdirDepot : public Depot { + public: + std::string mailboxToFilename(const std::string &m) const; + std::string filenameToMailbox(const std::string &m) const; + + //-- + IMAPdirDepot(); + ~IMAPdirDepot(); + }; + +} + +#endif diff --git a/src/include/globals.h b/src/include/globals.h new file mode 100644 index 0000000..dd63b5f --- /dev/null +++ b/src/include/globals.h @@ -0,0 +1,25 @@ +/** -------------------------------------------------------------------- + * @file globals.h + * @brief Global constants. + * @author Andreas Aardal Hanssen, Erwin Hoffmann + * @date 2002-2005, 2023 + * ----------------------------------------------------------------- **/ +#ifndef GLOBAL_H_INCLUDED +#define GLOBAL_H_INCLUDED + +#define BINC_VERSION "2.0.14" +#define IMAP_VERSION "IMAP4rev1" +#define BINC_CACHE "BINC-CACHE-1.0" +#define IMAP_PORT "143" +#define IMAPS_PORT "993" + +namespace Binc { + static const int IDLE_TIMEOUT = 30*60; + static const int AUTH_TIMEOUT = 60; + static const int AUTH_PENALTY = 5; + static const int TRANSFER_TIMEOUT = 20*60; + static const int TRANSFER_BUFFER_SIZE = 1024; + static const int INPUT_BUFFER_LIMIT = 8192; + +}; +#endif diff --git a/src/include/imapparser.h b/src/include/imapparser.h new file mode 100644 index 0000000..4f77985 --- /dev/null +++ b/src/include/imapparser.h @@ -0,0 +1,171 @@ +/** -------------------------------------------------------------------- + * @file imapparser.h + * @brief Declaration of the common items for parsing IMAP input + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef imapparser_h_included +#define imapparser_h_included + +/* stl includes */ +#include +#include +#include + +namespace Binc { + //------------------------------------------------------------------------ + class SequenceSet { + public: + void addRange(unsigned int a_in, unsigned int b_in); + bool isInSet(unsigned int n) const; + void addNumber(unsigned int a_in); + inline bool isLimited(void) const { return limited; } + + static SequenceSet &all(void); + + static SequenceSet &null(void); + + SequenceSet &operator = (const SequenceSet ©); + + SequenceSet(void); + SequenceSet(const SequenceSet ©); + ~SequenceSet(void); + + protected: + bool isNull(void) const; + + private: + bool limited; + bool nullSet; + + class Range { + public: + unsigned int from; + unsigned int to; + Range(unsigned int from, unsigned int to); + }; + + std::vector internal; + }; + + //------------------------------------------------------------------------ + class BincImapParserFetchAtt { + public: + std::string type; + std::string section; + std::string sectiontext; + std::vector headerlist; + unsigned int offsetstart; + unsigned int offsetlength; + bool hassection; + + BincImapParserFetchAtt(const std::string &typeName = ""); + + std::string toString(void); + }; + + //------------------------------------------------------------------------ + class BincImapParserSearchKey { + public: + std::string name; + std::string date; + std::string astring; + std::string bstring; + int type; + unsigned int number; + SequenceSet bset; + enum {KEY_AND, KEY_OR, KEY_NOT, KEY_OTHER, KEY_SET}; + + std::vector children; + + const SequenceSet& getSet(void) const; + + BincImapParserSearchKey(void); + }; + + //------------------------------------------------------------------------ + class BincImapParserData { + public: + virtual ~BincImapParserData(void) {} + }; + + //------------------------------------------------------------------------ + class Request { + private: + std::string tag; + std::string name; + std::string mode; + std::string date; + std::string userid; + std::string password; + std::string mailbox; + std::string newmailbox; + std::string authtype; + std::string listmailbox; + std::string charset; + std::string literal; + std::string contextInfo; + bool uidmode; + + public: + BincImapParserData * extra; + std::vector flags; + std::vector statuses; + + SequenceSet bset; + BincImapParserSearchKey searchkey; + std::vector fatt; + + void setUidMode(void); + bool getUidMode(void) const; + + void setTag(std::string &t_in); + const std::string &getTag(void) const; + + void setMode(const std::string &m_in); + const std::string &getMode(void) const; + + void setName(const std::string &s_in); + const std::string &getName(void) const; + + void setLiteral(const std::string &s_in); + const std::string &getLiteral(void) const; + + void setDate(const std::string &s_in); + const std::string &getDate(void) const; + + void setCharSet(const std::string &s_in); + const std::string &getCharSet(void) const; + + void setUserID(const std::string &s_in); + const std::string &getUserID(void) const; + + void setPassword(const std::string &s_in); + const std::string &getPassword(void) const; + + void setMailbox(const std::string &s_in); + const std::string &getMailbox(void) const; + + void setAuthType(const std::string &s_in); + const std::string &getAuthType(void) const; + + void setNewMailbox(const std::string &s_in); + const std::string &getNewMailbox(void) const; + + void setListMailbox(const std::string &s_in); + const std::string &getListMailbox(void) const; + + void setContextInfo(const std::string &s_in); + const std::string &getContextInfo(void) const; + + SequenceSet &getSet(void); + + std::vector &getFlags(void); + std::vector &getStatuses(void); + + Request(void); + ~Request(void); + }; +} + +#endif diff --git a/src/include/imapserver.h b/src/include/imapserver.h new file mode 100644 index 0000000..940234e --- /dev/null +++ b/src/include/imapserver.h @@ -0,0 +1,37 @@ +/** -------------------------------------------------------------------- + * @file imapserver.h + * @brief Declaration of the IMAPServer class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ + +namespace Binc { + + class IMAPServer { + public: + IMAPServer(int argc, char *argv[]); + ~IMAPServer(void); + + int initialize(void); + int runStub(void); + int run(void); + + enum ServerStatus { + OK, + RequestError, + RequestIgnore, // required for StartTLS, premature answer + RequestRejected, + ClientDisconnected, + Timeout + }; + + private: + void prepareForNextRequest(void); + + int argc; + char **argv; + bool stubMode; + + ServerStatus serverStatus; + }; +} diff --git a/src/include/iodevice.h b/src/include/iodevice.h new file mode 100644 index 0000000..070ac3f --- /dev/null +++ b/src/include/iodevice.h @@ -0,0 +1,382 @@ +/** -------------------------------------------------------------------- + * @file iodevice.h + * @brief Declaration of the IODevice class. + * @author Andreas Aardal Hanssen + * @date 2002, 2003 + * ----------------------------------------------------------------- **/ +#ifndef iodevice_h_included +#define iodevice_h_included + +#include "convert.h" // BincStream +//#include +#include +#include // ::write + +const char CMS_END_OF_LINE[4] = { 0x0d, '\n', 0x00, 0x00 }; + +namespace Binc { + /*! + \class IODevice + \brief The IODevice class provides a framework for reading and + writing to device. + + Implement new devices by inheriting this class and overloading all + virtual methods. + + service() returns the service that the specific device is used + for. Two values are "log" and "client". + + \sa IOFactory, MultilogDevice, SyslogDevice, StdIODevice, SSLDevice + */ + class IODevice { + public: + /*! + Standard options for an IODevice. + */ + enum Flags { + None = 0, + FlushesOnEndl = 1 << 0, + HasInputLimit = 1 << 1, + HasOutputLimit = 1 << 2, + IsEnabled = 1 << 3, + HasTimeout = 1 << 4 + }; + + /*! + Errors from when an operation returned false. + */ + enum Error { + Unknown, + Timeout + }; + + /*! + Constructs an invalid IODevice. + + Instances of IODevice perform no operations, and all boolean + functions always return false. This constructor is only useful + if called from a subclass that reimplements all virtual methods. + */ + IODevice(int f = 0); + + /*! + Destructs an IODevice; does nothing. + */ + virtual ~IODevice(void); + + /*! + Clears all data in the input and output buffers. + */ + void clear(void); + + /*! + Sets one or more flags. + \param f A bitwise OR of flags from the Flags enum. + */ + void setFlags(unsigned int f); + + /*! + Clears one or more flags. + \param f A bitwise OR of flags from the Flags enum. + */ + void clearFlags(unsigned int f); + + /*! + Sets the maximum allowed input buffer size. If this size is + non-zero and exceeded, reading from the device will fail. This + functionality is used to prevent clients from forcing this class + to consume so much memory that the program crashes. + + Setting the max input buffer size to 0 disables the input size + limit. + + \param max The maximum input buffer size in bytes. + */ + void setMaxInputBufferSize(unsigned int max); + + /*! + Sets the maximum allowed output buffer size. If this size is + non-zero and exceeded, flush() is called implicitly. + + Setting the max output buffer size to 0 disables the output size + limit. This is generally discouraged. + + As a contrast to setMaxInputBufferSize(), this function is used + to bundle up consequent write calls, allowing more efficient use + of the underlying device as larger blocks of data are written at + a time. + + \param max The maximum output buffer size in bytes. + */ + void setMaxOutputBufferSize(unsigned int max); + + /*! + Sets the device's internal timeout in seconds. This timeout is + used both when waiting for data to read and for waiting for the + ability to write. + + If this timeout is exceeded, the read or write function that + triggered the timeout will fail. + + Setting the timeout to 0 disables the timeout. + + \param t The timeout in seconds. + \sa getTimeout() + */ + void setTimeout(unsigned int t); + + /*! + Returns the timeout in seconds, or 0 if there is no timeout. + + \sa setTimeout() + */ + unsigned int getTimeout(void) const; + + enum LogLevel { + ErrorLevel, + InfoLevel, + WarningLevel, + DebugLevel + }; + + /*! + Sets the output level for the following write operations on this + device. + + The output level is a number which gives the following write + operations a priority. You can use setOutputLevelLimit() to + filter the write operations valid for different operating modes. + This enables you to have certain write operations ignored. + + For instance, if the output level is set to 0, then "Hello" is + written, and the output level is set to 1, followed by writing + "Daisy", the output level limit value will decive wether only + "Hello" is written, or if also "Daisy" is written. + + A low value of the level gives higher priority, and a high level + will give low priority. The default value is 0, and write + operations that are done with output level 0 are never ignored. + + \param level The output level + \sa getOutputLevel(), setOutputLevelLimit() + */ + void setOutputLevel(LogLevel level); + + /*! + Returns the current output level. + + \sa setOutputLevel() + */ + LogLevel getOutputLevel(void) const; + + /*! + Sets the current output level limit. Write operations with a + level higher than the output level limit are ignored. + + \param level The output level limit + \sa setOutputLevel() + */ + void setOutputLevelLimit(LogLevel level); + + /*! + Returns the current output level limit. + + \sa setOutputLevelLimit() + */ + LogLevel getOutputLevelLimit(void) const; + + /*! + Returns the number of bytes that have been read from this device + since it was created. + */ + unsigned int getReadCount(void) const; + + /*! + Returns the number of bytes that have been written to this + device since it was created. + */ + unsigned int getWriteCount(void) const; + + /*! + Calling this function enables the built-in protocol dumping feature in + the device. All input and output to this device will be dumped to a file + in /tmp. + */ + void enableProtocolDumping(void); + + /*! + Writes data to the device. Depending on the value of the max + output buffer size, the data may not be written immediately. + + \sa setMaxOutputBufferSize() + */ + template IODevice &operator << (const T &source); + + /*! + Writes data to the device. This function specializes on standard + ostream derivates, such as std::endl. + */ + IODevice &operator << (std::ostream &(*source)(std::ostream &)); + + /*! + Returns true if data can be read from the device; otherwise + returns false. + */ + virtual bool canRead(void) const; + + /*! + Reads data from the device, and stores this in a string. Returns + true on success; otherwise returns false. + + \param dest The incoming data is stored in this string. + \param max No more than this number of bytes is read from the + device. + */ + bool readStr(std::string *dest, unsigned int max = 0); + + /*! + Reads exactly one byte from the device and stores this in a + char. Returns true on success; otherwise returns false. + + \param dest The incoming byte is stored in this char. + */ + bool readChar(char *dest = 0); + + /*! + FIXME: add docs + */ + void unreadChar(char c); + + /*! + FIXME: add docs + */ + void unreadStr(const std::string &s); + + /*! + Reads characters from the device, until and including one + certain character is found. All read characters are discarded. + + This function can be used to skip to the beginning of a line, + with the terminating character being '\n'. + + \param The certain character. + */ + bool skipTo(char c); + + /*! + Flushes the output buffer. Writes all data in the output buffer + to the device. + */ + bool flush(void); + + /*! + Returns the type of error that most recently occurred. + */ + Error getLastError(void) const; + + /*! + Returns a human readable description of the error that most + recently occurred. If no known error has occurred, this method + returns "Unknown error". + */ + std::string getLastErrorString(void) const; + + /*! + Returns the type of service provided by this device. Two valid + return values are "client" and "log". + */ + virtual std::string service(void) const; + + protected: + /*! + Waits until data can be written to the device. If the timeout is + 0, this function waits indefinitely. Otherwise, it waits until + the timeout has expired. + + If this function returns true, data can be written to the + device; otherwise, getLastError() must be checked to determine + whether a timeout occurred or whether an error with the device + prevents further writing. + */ + virtual bool waitForWrite(void) const; + + /*! + Waits until data can be read from the device. + + \sa waitForWrite() + */ + virtual bool waitForRead(void) const; + + /*! + Types of results from a write. + */ + enum WriteResult { + WriteWait = 0, + WriteDone = 1 << 0, + WriteError = 1 << 1 + }; + + /*! + Writes as much data as possible to the device. If some but not + all data was written, returns WriteWait. If all data was + written, returns WriteDone. If an error occurred, returns + WriteError. + */ + virtual WriteResult write(void); + + /*! + Reads data from the device, and stores it in the input buffer. + Returns true on success; otherwise returns false. + + This method will fail if there is no more data available, if a + timeout occurred or if an error with the device prevents more + data from being read. + + The number of bytes read from the device is undefined. + */ + virtual bool fillInputBuffer(void); + + BincStream inputBuffer; + BincStream outputBuffer; + + protected: + unsigned int flags; + unsigned int maxInputBufferSize; + unsigned int maxOutputBufferSize; + + unsigned int timeout; + + unsigned int readCount; + unsigned int writeCount; + + LogLevel outputLevel; + LogLevel outputLevelLimit; + + mutable Error error; + mutable std::string errorString; + + int dumpfd; + }; + + //---------------------------------------------------------------------- + template IODevice &IODevice::operator << (const T &source) + { + if ((flags & IsEnabled) && outputLevel <= outputLevelLimit) { + outputBuffer << source; + + if (dumpfd) { + BincStream ss; + ss << source; + ::write(dumpfd, ss.str().c_str(), ss.getSize()); + } + + if (flags & HasInputLimit) + if (outputBuffer.getSize() > maxOutputBufferSize) + flush(); + } + + return *this; + } +} + +#endif diff --git a/src/include/iofactory.h b/src/include/iofactory.h new file mode 100644 index 0000000..6ebccaa --- /dev/null +++ b/src/include/iofactory.h @@ -0,0 +1,53 @@ +/** -------------------------------------------------------------------- + * @file iofactory.h + * @brief Declaration of the IOFactory class. + * @author Andreas Aardal Hanssen + * @date 2002, 2003 + * ----------------------------------------------------------------- **/ +#ifndef IOFACTORY_H_INCLUDED +#define IOFACTORY_H_INCLUDED +#include +#include + +#include "iodevice.h" + +namespace Binc { + class IOFactory { + public: + ~IOFactory(void); + + static void addDevice(IODevice *dev); + static IOFactory &getInstance(void); + static IODevice &getClient(void); + static IODevice &getLogger(void); + + private: + IOFactory(void); + + std::map devices; + }; +} + +#define bincClient \ + IOFactory::getClient() + +#if defined (DEBUG) +//#define bincError if (false) std::cout +#define bincError std::cerr +// #define bincWarning if (false) std::cout +#define bincWarning std::cerr +#define bincDebug std::cerr +//#define bincDebug if (false) std::cout +#else +#define bincError \ + IOFactory::getLogger().setOutputLevel(IODevice::ErrorLevel);IOFactory::getLogger() +#define bincWarning \ + IOFactory::getLogger().setOutputLevel(IODevice::WarningLevel);IOFactory::getLogger() +#define bincDebug \ + IOFactory::getLogger().setOutputLevel(IODevice::DebugLevel);IOFactory::getLogger() +#endif + +#define bincLog \ + IOFactory::getLogger().setOutputLevel(IODevice::InfoLevel);IOFactory::getLogger() + +#endif diff --git a/src/include/mailbox.h b/src/include/mailbox.h new file mode 100644 index 0000000..db98cc0 --- /dev/null +++ b/src/include/mailbox.h @@ -0,0 +1,136 @@ +/** -------------------------------------------------------------------- + * @file mailbox.h + * @brief Declaration of the Mailbox class (Mailbox is logical container) + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef mailbox_h_included +#define mailbox_h_included + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "imapparser.h" + +namespace Binc { + + class Message; + class Status; + class PendingUpdates; + class File; + + //------------------------------------------------------------------------ + class Mailbox { + public: + + //---------------------------------------------------------------------- + class BaseIterator { + public: + BaseIterator(int sqn = 0); + virtual ~BaseIterator(void); + + virtual Message &operator *(void) = 0; + virtual void operator ++(void) = 0; + virtual bool operator !=(const BaseIterator &d) const = 0; + virtual bool operator ==(const BaseIterator &d) const = 0; + + virtual void erase(void) = 0; + + unsigned int sqnr; + }; + + //---------------------------------------------------------------------- + class iterator { + public: + iterator(BaseIterator &i); + + Message &operator *(void); + void operator ++(void); + bool operator ==(const iterator &) const; + bool operator !=(const iterator &) const; + + unsigned int getSqnr() const; + + void erase(void); + + protected: + BaseIterator &realIterator; + }; + + enum Iterator { + INCLUDE_EXPUNGED = 1, + SKIP_EXPUNGED = 2 + }; + + enum Mode { + UID_MODE = 4, + SQNR_MODE = 8 + }; + + virtual iterator begin(const SequenceSet &bset, unsigned int mod = INCLUDE_EXPUNGED | SQNR_MODE) const = 0; + virtual iterator end(void) const = 0; + + //-- Generic for one mailbox type + virtual bool getStatus(const std::string &, Status &) const = 0; + virtual bool isMailbox(const std::string &) const = 0; + virtual bool isMarked(const std::string &) const = 0; + virtual unsigned int getStatusID(const std::string &) const = 0; + virtual void bumpUidValidity(const std::string &) const = 0; + + //-- Specific for one mailbox + void setReadOnly(bool readOnly); + bool isReadOnly(void) const; + + virtual const std::string getTypeName(void) const = 0; + const std::string getName(void) const; + void setName(const std::string &name); + + virtual unsigned int getMaxUid(void) const = 0; + virtual unsigned int getMaxSqnr(void) const = 0; + virtual unsigned int getUidNext(void) const = 0; + virtual unsigned int getUidValidity(void) const = 0; + + virtual bool getUpdates(bool scan, unsigned int type, + PendingUpdates &updates, bool forceScan) = 0; + + virtual void updateFlags(void) = 0; + virtual void expungeMailbox(void) = 0; + virtual bool selectMailbox(const std::string &name, const std::string &s_in) = 0; + virtual bool createMailbox(const std::string &s, mode_t mode, uid_t owner = 0, gid_t group = 0, bool root = false) = 0; + virtual bool deleteMailbox(const std::string &s) = 0; + virtual void closeMailbox(void) = 0; + + virtual Message *createMessage(const std::string &mbox, time_t idate = 0) = 0; + virtual bool commitNewMessages(const std::string &mbox) = 0; + virtual bool rollBackNewMessages(void) = 0; + virtual bool fastCopy(Message &source, Mailbox &desttype, const std::string &destname) = 0; + + const std::string &getLastError(void) const; + void setLastError(const std::string &error) const; + + //-- + Mailbox(void); + virtual ~Mailbox(void); + + friend class Mailbox::iterator; + + protected: + bool readOnly; + + private: + Mailbox(const Mailbox ©); + + mutable std::string lastError; + + std::string name; + }; +} + +#endif diff --git a/src/include/maildir.h b/src/include/maildir.h new file mode 100644 index 0000000..4a262b5 --- /dev/null +++ b/src/include/maildir.h @@ -0,0 +1,190 @@ +/** -------------------------------------------------------------------- + * @file maildir.h + * @brief Declaration of the Maildir class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef maildir_h_included +#define maildir_h_included +#include +#include +#include + +#include "mailbox.h" +#include "maildirmessage.h" + +namespace Binc { + static const std::string CACHEFILEVERSION = "1.0.5"; + static const std::string UIDVALFILEVERSION = "1.0.5"; + + //---------------------------------------------------------------------- + class Lock { + public: + Lock(const std::string &path); + ~Lock(); + + private: + std::string lock; + }; + + //------------------------------------------------------------------------ + class MaildirIndexItem { + public: + unsigned int uid; + std::string fileName; + }; + + //------------------------------------------------------------------------ + class MaildirIndex + { + private: + std::map idx; + + public: + void insert(const std::string &unique, unsigned int uid, + const std::string &fileName = ""); + void remove(const std::string &unique); + void clear(void); + void clearFileNames(void); + void clearUids(void); + unsigned int getSize(void) const; + MaildirIndexItem *find(const std::string &unique); + }; + + //------------------------------------------------------------------------ + class Maildir : public Mailbox { + public: + typedef std::map MessageMap; + + class iterator : public BaseIterator { + public: + iterator(void); + iterator(Maildir *home, MessageMap::iterator i, + const SequenceSet &bset, + unsigned int mod = INCLUDE_EXPUNGED | SQNR_MODE); + iterator(const iterator ©); + ~iterator(void); + + Message &operator *(void); + void operator ++(void); + bool operator ==(const BaseIterator &) const; + bool operator !=(const BaseIterator &) const; + + iterator &operator =(const iterator ©); + + void erase(void); + + friend class Maildir; + + protected: + void reposition(void); + MaildirMessage &curMessage(void); + + private: + Maildir *mailbox; + SequenceSet bset; + int mod; + + MessageMap::iterator i; + unsigned int uidmax; + unsigned int sqnrmax; + + iterator(iterator &external); + }; + + const std::string getTypeName(void) const; + + Mailbox::iterator begin(const SequenceSet &bset, unsigned int mod = INCLUDE_EXPUNGED | SQNR_MODE) const; + Mailbox::iterator end(void) const; + + unsigned int getMaxUid(void) const; + unsigned int getMaxSqnr(void) const; + unsigned int getUidValidity(void) const; + unsigned int getUidNext(void) const; + + bool getUpdates(bool doscan, unsigned int type, + PendingUpdates &updates, bool forceScan); + + const std::string &getPath(void) const; + void setPath(const std::string &path_in); + + void bumpUidValidity(const std::string &) const; + + unsigned int getStatusID(const std::string &) const; + bool getStatus(const std::string &, Status &) const; + void updateFlags(void); + + bool isMailbox(const std::string &) const; + bool isMarked(const std::string &) const; + bool selectMailbox(const std::string &name, const std::string &s_in); + void closeMailbox(void); + void expungeMailbox(void); + bool createMailbox(const std::string &s, mode_t mode, uid_t owner = 0, gid_t group = 0, bool root = false); + bool deleteMailbox(const std::string &s); + + Message *createMessage(const std::string &mbox, time_t idate = 0); + bool commitNewMessages(const std::string &mbox); + bool rollBackNewMessages(void); + + bool fastCopy(Message &source, Mailbox &desttype, const std::string &destname); + + //-- + Maildir(void); + ~Maildir(void); + + friend class Maildir::iterator; + friend class MaildirMessage; + + protected: + enum ReadCacheResult { + Ok, + NoCache, + Error + }; + + ReadCacheResult readCache(void); + bool writeCache(void); + bool scanFileNames(void) const; + + enum ScanResult { + Success = 0, + TemporaryError = 1, + PermanentError = 2 + }; + + ScanResult scan(bool forceScan = false); + + MaildirMessage *get(const std::string &id); + void add(MaildirMessage &m); + + private: + std::vector newMessages; + + unsigned int uidvalidity; + unsigned int uidnext; + bool selected; + std::string path; + + mutable iterator beginIterator; + mutable iterator endIterator; + + mutable bool firstscan; + mutable bool cacheRead; + mutable MaildirIndex index; + mutable MessageMap messages; + + mutable unsigned int oldrecent; + mutable unsigned int oldexists; + + mutable time_t old_bincimap_cache_st_mtime; + mutable time_t old_bincimap_cache_st_ctime; + mutable time_t old_cur_st_mtime; + mutable time_t old_cur_st_ctime; + mutable time_t old_new_st_mtime; + mutable time_t old_new_st_ctime; + + mutable bool mailboxchanged; + }; +} + +#endif diff --git a/src/include/maildirmessage.h b/src/include/maildirmessage.h new file mode 100644 index 0000000..9e9c717 --- /dev/null +++ b/src/include/maildirmessage.h @@ -0,0 +1,309 @@ +/** -------------------------------------------------------------------- + * @file maildirmessage.h + * @brief Declaration of the MaildirMessage class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef maildirmessage_h_included +#define maildirmessage_h_included +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "message.h" +#include "address.h" +#include "mime.h" + +namespace Binc { + + class Maildir; + + /*! + \class MaildirMessage + \brief The MaildirMessage class provides an interface for + IMAP messages. + + Mailbox independent operations and properties are available + through this interface. + + \sa Message + */ + class MaildirMessage : public Message { + public: + /*! + Sets the UID of a message. + \param uid The UID that will be set. + */ + void setUID(unsigned int uid); + + /*! + Returns the UID of a message. + */ + unsigned int getUID(void) const; + + /*! + Sets the size of the message. This size must be consistent with + the size reported when fetching the full message. + + \param size The size of the message in characters, after + any conversion to CRLF. + */ + void setSize(unsigned int size); + + /*! + Returns the size of the message, optionally determining the size + if it is not yet known. + + \param determine If render is true and the size is unknown, the + size will be calculated and stored implicitly. Otherwise if the + size is unknown, 0 is returned. + */ + unsigned int getSize(bool determine = false) const; + + /*! + Adds one or more flags to a message. + + \param flags This is a bitmask of flags from the Flags enum. + */ + void setStdFlag(unsigned char flags); + + /*! + Resets all flags on a message. + */ + void resetStdFlags(void); + + /*! + Returns the flags that are set on a message. + */ + unsigned char getStdFlags(void) const; + + /* + */ + void setCustomFlag(const std::string &flag); + void removeCustomFlag(const std::string &flag); + void resetCustomFlags(void); + std::vector getCustomFlags(void) const; + + /*! + Sets the internal flags. + + \param flags a bitmask of the Flags enum. + */ + void setInternalFlag(unsigned char flags); + + /*! + Removes the internal flags. + + \param flags a bitmask of the Flags enum. + */ + void clearInternalFlag(unsigned char flags); + + /*! + Returns the internal flags. + */ + unsigned char getInternalFlags(void) const; + + /*! + Sets a state in a message that indicates that no flags have been + changed. Used together with hasFlagsChanged() to check if the + flags in this message have been changed. + */ + void setFlagsUnchanged(void); + + /*! + Returns true if flags have been added or reset since the last + call to setFlagsUnchanged(), otherwise returns false. + */ + bool hasFlagsChanged(void) const; + + /*! + Sets the internal date of a message. This is usually the date in + which the message arrived in the mailbox. + + \param internaldate The internal date of the message in seconds + since the epoch. + */ + void setInternalDate(time_t internaldate); + + /*! + Returns the internal date of the message in seconds since the + epoch. + */ + time_t getInternalDate(void) const; + + /*! + Reads a chunk of up to 4096 bytes from a message. Call close() + before readChunk() to read the first chunk from a message. + + readChunk() is used for copying or appending a message to a + mailbox. + + \param chunk The characters are stored in this string. + */ + int readChunk(std::string &chunk); + + /*! + Appends a chunk of bytes to a message. appendChunk() is used for + copying or appending a message to a mailbox. + + \param chunk The content of this string is appended to the + message. + */ + bool appendChunk(const std::string &chunk); + + /*! + Resets a message and frees all allocated resources. + */ + void close(void); + + /*! + Marks the message as expunged. Equivalent to calling + setStdFlag() with F_EXPUNGED. + */ + void setExpunged(void); + + /*! + Removes the F_EXPUNGED flag from the message. + */ + void setUnExpunged(void); + + /*! + Returns true if the message is marked as expunged, otherwise + returns false. + */ + bool isExpunged(void) const; + + /*! + Returns the first occurrance of a MIME header in a message, + counting from the top of the message and downwards, or "" if no + such header is found. + \param header The name of the header to be fetched. + */ + const std::string &getHeader(const std::string &header); + + bool headerContains(const std::string &header, + const std::string &text); + + bool bodyContains(const std::string &text); + bool textContains(const std::string &text); + + bool printBodyStructure(bool extended = true) const; + + bool printEnvelope(void) const; + + bool printHeader(const std::string §ion, + std::vector headers, + bool includeHeaders = false, + unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool mime = false) const; + + unsigned int getHeaderSize(const std::string §ion, + std::vector headers, + bool includeHeaders = false, + unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool mime = false) const; + + bool printBody(const std::string §ion = "", + unsigned int startOffset = 0, + unsigned int length = UINTMAX) const; + unsigned int getBodySize(const std::string §ion, + unsigned int startOffset = 0, + unsigned int length = UINTMAX) const; + + bool printDoc(unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool onlyText = false) const; + + unsigned int getDocSize(unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool onlyText = false) const; + + void setUnique(const std::string &s_in); + const std::string &getUnique(void) const; + + //-- + MaildirMessage(Maildir &home); + ~MaildirMessage(void); + + friend class Maildir; + + bool operator < (const MaildirMessage &a) const; + + MaildirMessage(const MaildirMessage ©); + MaildirMessage &operator = (const MaildirMessage ©); + + enum Flags { + None = 0x00, + Expunged = 0x01, + FlagsChanged = 0x02, + JustArrived = 0x04, + WasWrittenTo = 0x08, + Committed = 0x10, + CustomFlagsChanged = 0x20 + }; + + protected: + bool parseFull(void) const; + bool parseHeaders(void) const; + + std::string getFixedFilename(void) const; + std::string getFileName(void) const; + + void setFile(int fd); + int getFile(void) const; + + void setSafeName(const std::string &name); + const std::string &getSafeName(void) const; + + private: + mutable int fd; + mutable MimeDocument *doc; + mutable unsigned char internalFlags; + mutable unsigned char stdflags; + mutable unsigned int uid; + mutable unsigned int size; + mutable std::string unique; + mutable std::string safeName; + time_t internaldate; + + Maildir &home; + static std::string storage; + std::vector *customFlags; + }; + + //------------------------------------------------------------------------ + class MaildirMessageCache + { + public: + ~MaildirMessageCache(); + + enum ParseStatus { + NotParsed, + HeaderParsed, + AllParsed + }; + + static MaildirMessageCache &getInstance(void); + + void removeStatus(const MaildirMessage *); + void addStatus(const MaildirMessage *, ParseStatus pstat); + ParseStatus getStatus(const MaildirMessage *) const; + void clear(void); + + private: + MaildirMessageCache(); + + mutable std::map statuses; + mutable std::deque parsed; + }; +} + +#endif diff --git a/src/include/message.h b/src/include/message.h new file mode 100644 index 0000000..76607e5 --- /dev/null +++ b/src/include/message.h @@ -0,0 +1,151 @@ +/** -------------------------------------------------------------------- + * @file message.h + * @brief Declaration of the Message class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef message_h_included +#define message_h_included +#include +#include +#include + +#ifndef UINTMAX +#define UINTMAX ((unsigned int)-1) +#endif + +namespace Binc { + + /*! + \class Message + \brief The Message class provides an interface for + IMAP messages. + + Mailbox independent operations and properties are available + through this interface. + + This class is an abstract, and has no implementation. + + \sa MaildirMessage + */ + class Message { + public: + + /*! + Standard IMAP message flags. + + */ + enum Flags { + F_NONE = 0x00, /*!< No flag is set */ + F_SEEN = 0x01, /*!< The message has been seen */ + F_ANSWERED = 0x02, /*!< The message has been answered */ + F_DELETED = 0x04, /*!< The message is marked as deleted */ + F_DRAFT = 0x08, /*!< The message is a draft */ + F_RECENT = 0x10, /*!< The message arrived recently */ + F_FLAGGED = 0x20, /*!< The message is flagged / important */ + F_EXPUNGED = 0x40, /*!< The message has been expunged */ + F_PASSED = 0x80 /*!< The message has been bounced */ + }; + + virtual void setUID(unsigned int) = 0; + virtual unsigned int getUID(void) const = 0; + + virtual void setSize(unsigned int) = 0; + virtual unsigned int getSize(bool render = false) const = 0; + + virtual void setStdFlag(unsigned char) = 0; + virtual void resetStdFlags(void) = 0; + virtual unsigned char getStdFlags(void) const = 0; + + virtual void setCustomFlag(const std::string &flag) = 0; + virtual void removeCustomFlag(const std::string &flag) = 0; + virtual void resetCustomFlags(void) = 0; + virtual std::vector getCustomFlags(void) const = 0; + + virtual void setFlagsUnchanged(void) = 0; + virtual bool hasFlagsChanged(void) const = 0; + + virtual void setInternalDate(time_t) = 0; + virtual time_t getInternalDate(void) const = 0; + + // virtual void rewind(void) = 0; + virtual int readChunk(std::string &) = 0; + virtual bool appendChunk(const std::string &) = 0; + virtual void close(void) = 0; + + virtual void setExpunged(void) = 0; + virtual void setUnExpunged(void) = 0; + virtual bool isExpunged(void) const = 0; + + virtual const std::string &getHeader(const std::string &header) = 0; + + virtual bool headerContains(const std::string &header, + const std::string &text) = 0; + + virtual bool bodyContains(const std::string &text) = 0; + virtual bool textContains(const std::string &text) = 0; + + virtual bool printBodyStructure(bool extended = true) const = 0; + + virtual bool printEnvelope(void) const = 0; + + virtual bool printHeader(const std::string §ion, + std::vector headers, + bool includeHeaders = false, + unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool mime = false) const = 0; + + virtual unsigned int getHeaderSize(const std::string §ion, + std::vector headers, + bool includeHeaders = false, + unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool mime = false) const = 0; + + virtual bool printBody(const std::string §ion, + unsigned int startOffset = 0, + unsigned int length = UINTMAX) const = 0; + + virtual unsigned int getBodySize(const std::string §ion, + unsigned int startOffset = 0, + unsigned int length = UINTMAX) const = 0; + + virtual bool printDoc(unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool onlyText = false) const = 0; + + virtual unsigned int getDocSize(unsigned int startOffset = 0, + unsigned int length = UINTMAX, + bool onlyText = false) const = 0; + + Message(void); + virtual ~Message(void); + + void setLastError(const std::string &) const; + const std::string &getLastError(void) const; + + private: + static std::string lastError; + }; + + inline Message::Message(void) + { + } + + inline Message::~Message(void) + { + } + + inline void Message::setLastError(const std::string &error) const + { + lastError = error; + } + + inline const std::string &Message::getLastError(void) const + { + return lastError; + } +} + +#endif diff --git a/src/include/mime-inputsource.h b/src/include/mime-inputsource.h new file mode 100644 index 0000000..e37d508 --- /dev/null +++ b/src/include/mime-inputsource.h @@ -0,0 +1,141 @@ +/** -------------------------------------------------------------------- + * @file mime-inputsource.h + * @brief The base class of the MIME input source + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef mime_inputsource_h_included +#define mime_inputsource_h_included + +#include +#include + +namespace Binc { + + class MimeInputSource { + public: + inline MimeInputSource(int fd, unsigned int start = 0); + virtual inline ~MimeInputSource(void); + + virtual inline bool fillInputBuffer(void); + virtual inline void reset(void); + + inline void seek(unsigned int offset); + inline bool getChar(char *c); + inline void ungetChar(void); + inline int getFileDescriptor(void) const; + + inline unsigned int getOffset(void) const; + + private: + int fd; + char data[16384]; + unsigned int offset; + unsigned int tail; + unsigned int head; + unsigned int start; + char lastChar; + }; + + inline MimeInputSource::MimeInputSource(int fd, unsigned int start) + { + this->fd = fd; + this->start = start; + offset = 0; + tail = 0; + head = 0; + lastChar = '\0'; + memset(data, '\0', sizeof(data)); + + seek(start); + } + + inline MimeInputSource::~MimeInputSource(void) + { + } + + inline bool MimeInputSource::fillInputBuffer(void) + { + char raw[4096]; + ssize_t nbytes = read(fd, raw, sizeof(raw)); + if (nbytes <= 0) { + // FIXME: If ferror(crlffile) we should log this. + return false; + } + + for (ssize_t i = 0; i < nbytes; ++i) { + const char c = raw[i]; + if (c == '\r') { + if (lastChar == '\r') { + data[tail++ & (0x4000-1)] = '\r'; + data[tail++ & (0x4000-1)] = '\n'; + } + } else if (c == '\n') { + data[tail++ & (0x4000-1)] = '\r'; + data[tail++ & (0x4000-1)] = '\n'; + } else { + if (lastChar == '\r') { + data[tail++ & (0x4000-1)] = '\r'; + data[tail++ & (0x4000-1)] = '\n'; + } + data[tail++ & (0x4000-1)] = c; + } + + lastChar = c; + } + + return true; + } + + inline void MimeInputSource::reset(void) + { + offset = head = tail = 0; + lastChar = '\0'; + + if (fd != -1) + lseek(fd, 0, SEEK_SET); + } + + inline void MimeInputSource::seek(unsigned int seekToOffset) + { + if (offset > seekToOffset) + reset(); + + char c; + int n = 0; + while (seekToOffset > offset) { + if (!getChar(&c)) break; + ++n; + } + } + + inline bool MimeInputSource::getChar(char *c) + { + if (head == tail && !fillInputBuffer()) + return false; + + *c = data[head++ & (0x4000-1)]; + ++offset; + return true; + } + + inline void MimeInputSource::ungetChar() + { + --head; + --offset; + } + + inline int MimeInputSource::getFileDescriptor(void) const + { + return fd; + } + + inline unsigned int MimeInputSource::getOffset(void) const + { + return offset; + } +} + +extern Binc::MimeInputSource *mimeSource; + +#endif diff --git a/src/include/mime-utils.h b/src/include/mime-utils.h new file mode 100644 index 0000000..732234a --- /dev/null +++ b/src/include/mime-utils.h @@ -0,0 +1,27 @@ +/** -------------------------------------------------------------------- + * @file mime.cc + * @brief Implementation of main mime parser components + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef mime_utils_h_included +#define mime_utils_h_included + +#include +#include +#include +#include + +using namespace ::std; + +inline bool compareStringToQueue(const char *s_in, char *bqueue, + int pos, int size) +{ + for (int i = 0; i < size; ++i) + if (s_in[i] != bqueue[(pos + i) % size]) + return false; + + return true; +} + +#endif diff --git a/src/include/mime.h b/src/include/mime.h new file mode 100644 index 0000000..2033442 --- /dev/null +++ b/src/include/mime.h @@ -0,0 +1,121 @@ +/** -------------------------------------------------------------------- + * @file mime.h + * @brief Declaration of main mime parser components + * @author Andreas Aardal Hanssen + * @date Andreas Aardal Hanssen + * ----------------------------------------------------------------- **/ +#ifndef mime_h_included +#define mime_h_included +#include +#include +#include +#include + +namespace Binc { + //---------------------------------------------------------------------- + class HeaderItem { + private: + mutable std::string key; + mutable std::string value; + + public: + inline const std::string &getKey(void) const { return key; } + inline const std::string &getValue(void) const { return value; } + + //-- + HeaderItem(void); + HeaderItem(const std::string &key, const std::string &value); + }; + + //---------------------------------------------------------------------- + class Header { + private: + mutable std::vector content; + + public: + bool getFirstHeader(const std::string &key, HeaderItem &dest) const; + bool getAllHeaders(const std::string &key, std::vector &dest) const; + void add(const std::string &name, const std::string &content); + void clear(void) const; + + //-- + Header(void); + ~Header(void); + }; + + //---------------------------------------------------------------------- + class IODevice; + class MimeDocument; + class MimePart { + protected: + public: + mutable bool multipart; + mutable bool messagerfc822; + mutable std::string subtype; + mutable std::string boundary; + + mutable unsigned int headerstartoffsetcrlf; + mutable unsigned int headerlength; + + mutable unsigned int bodystartoffsetcrlf; + mutable unsigned int bodylength; + mutable unsigned int nlines; + mutable unsigned int nbodylines; + mutable unsigned int size; + + public: + enum FetchType { + FetchBody, + FetchHeader, + FetchMime + }; + + mutable Header h; + + mutable std::vector members; + + inline const std::string &getSubType(void) const { return subtype; } + inline bool isMultipart(void) const { return multipart; } + inline bool isMessageRFC822(void) const { return messagerfc822; } + inline unsigned int getSize(void) const { return bodylength; } + inline unsigned int getNofLines(void) const { return nlines; } + inline unsigned int getNofBodyLines(void) const { return nbodylines; } + inline unsigned int getBodyLength(void) const { return bodylength; } + inline unsigned int getBodyStartOffset(void) const { return bodystartoffsetcrlf; } + + void printBody(int fd, Binc::IODevice &output, unsigned int startoffset, unsigned int length) const; + void printHeader(int fd, Binc::IODevice &output, std::vector headers, + bool includeheaders, unsigned int startoffset, unsigned int length, std::string &storage) const; + void printDoc(int fd, Binc::IODevice &output, unsigned int startoffset, unsigned int length) const; + virtual void clear(void) const; + + const MimePart *getPart(const std::string &findpart, std::string genpart, FetchType fetchType = FetchBody) const; + virtual int parseOnlyHeader(const std::string &toboundary) const; + virtual int parseFull(const std::string &toboundary, int &boundarysize) const; + + MimePart(void); + virtual ~MimePart(void); + }; + + //---------------------------------------------------------------------- + class MimeDocument : public MimePart { + private: + mutable bool headerIsParsed; + mutable bool allIsParsed; + + public: + void parseOnlyHeader(int fd) const; + void parseFull(int fd) const; + void clear(void) const; + + inline bool isHeaderParsed(void) { return headerIsParsed; } + inline bool isAllParsed(void) { return allIsParsed; } + + //-- + MimeDocument(void); + ~MimeDocument(void); + }; + +}; + +#endif diff --git a/src/include/multilogdevice.h b/src/include/multilogdevice.h new file mode 100644 index 0000000..a6f29f2 --- /dev/null +++ b/src/include/multilogdevice.h @@ -0,0 +1,29 @@ +/** -------------------------------------------------------------------- + * @file multilogdevice.h + * @brief Declaration of the MultilogDevice class. + * @author Andreas Aardal Hanssen + * @date Andreas Aardal Hanssen + * ----------------------------------------------------------------- **/ +#ifndef multilogdevice_h_included +#define multilogdevice_h_included + +#include "iodevice.h" + +namespace Binc { + class MultilogDevice : public IODevice { + public: + MultilogDevice(int flags); + ~MultilogDevice(); + + std::string service(void) const; + + protected: + bool waitForWrite(void) const; + bool waitForRead(void) const; + + WriteResult write(void); + bool fillInputBuffer(void); + }; +} + +#endif diff --git a/src/include/operators.h b/src/include/operators.h new file mode 100644 index 0000000..c030918 --- /dev/null +++ b/src/include/operators.h @@ -0,0 +1,476 @@ +/** -------------------------------------------------------------------- + * @file operators.h + * @brief Declaration of all operators. + * @author Andreas Aardal Hanssen, Erwin Hoffmann + * @date 2002-2005, 2023 + * ----------------------------------------------------------------- **/ +#ifndef operators_h_included +#define operators_h_included +#include +#include + +#include "imapparser.h" +#include "depot.h" +#include "message.h" + +namespace Binc { + + //-------------------------------------------------------------------- + class Operator { + public: + enum ProcessResult {OK, BAD, NO, NOTHING, ABORT}; + enum ParseResult {ACCEPT, REJECT, ERROR, TIMEOUT}; + + virtual ProcessResult process(Depot &, Request &) = 0; + virtual ParseResult parse(Request &) const = 0; + virtual int getState(void) const = 0; + virtual const std::string getName(void) const = 0; + + //-- + virtual ~Operator(void) {}; + }; + + //-------------------------------------------------------------------- + class AppendOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + const std::string getName(void) const; + int getState(void) const; + + AppendOperator(void); + ~AppendOperator(void); + }; + + //-------------------------------------------------------------------- + class AuthenticateOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + ProcessResult Login(std::string& username, std::string& password); + ProcessResult Plain(std::string& username, std::string& password); + ProcessResult Cram(std::string& username, std::string& password, + std::string& challenge); + + AuthenticateOperator(void); + ~AuthenticateOperator(void); + }; + + //-------------------------------------------------------------------- + class CapabilityOperator : public Operator { + std::vector capabilities; + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + void addCapability(const std::string &cap); + + CapabilityOperator(void); + ~CapabilityOperator(void); + }; + + //-------------------------------------------------------------------- + class CheckOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + CheckOperator(void); + ~CheckOperator(void); + }; + + //-------------------------------------------------------------------- + class CreateOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + CreateOperator(void); + ~CreateOperator(void); + }; + + //-------------------------------------------------------------------- + class CloseOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + CloseOperator(void); + ~CloseOperator(void); + }; + + //-------------------------------------------------------------------- + class CopyOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + CopyOperator(void); + ~CopyOperator(void); + }; + + //-------------------------------------------------------------------- + class DeleteOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + DeleteOperator(void); + ~DeleteOperator(void); + }; + + //-------------------------------------------------------------------- + class ExpungeOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + ExpungeOperator(void); + ~ExpungeOperator(void); + }; + + //-------------------------------------------------------------------- + class FetchOperator : public Operator { + protected: + ParseResult expectSectionText(BincImapParserFetchAtt &f_in) const; + ParseResult expectSection(BincImapParserFetchAtt &f_in) const; + ParseResult expectFetchAtt(BincImapParserFetchAtt &f_in) const; + ParseResult expectOffset(BincImapParserFetchAtt &f_in) const; + ParseResult expectHeaderList(BincImapParserFetchAtt &f_in) const; + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + FetchOperator(void); + ~FetchOperator(void); + }; + + //-------------------------------------------------------------------- + class IdOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + IdOperator(void); + ~IdOperator(void); + }; + + //-------------------------------------------------------------------- + class IdleOperator : public Operator { + protected: + ParseResult expectSectionText(BincImapParserFetchAtt &f_in) const; + ParseResult expectSection(BincImapParserFetchAtt &f_in) const; + ParseResult expectFetchAtt(BincImapParserFetchAtt &f_in) const; + ParseResult expectOffset(BincImapParserFetchAtt &f_in) const; + ParseResult expectHeaderList(BincImapParserFetchAtt &f_in) const; + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + IdleOperator(void); + ~IdleOperator(void); + }; + + //-------------------------------------------------------------------- + class ListOperator : public Operator { + protected: + enum MailboxFlags { + DIR_SELECT = 0x01, + DIR_MARKED = 0x02, + DIR_NOINFERIORS = 0x04, + DIR_LEAF = 0x08 + }; + + std::map cache; + time_t cacheTimeout; + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + ListOperator(void); + ~ListOperator(void); + }; + + //-------------------------------------------------------------------- + class LoginOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + LoginOperator(void); + ~LoginOperator(void); + }; + + //-------------------------------------------------------------------- + class LogoutOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + LogoutOperator(void); + ~LogoutOperator(void); + }; + + //-------------------------------------------------------------------- + class LsubOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + LsubOperator(void); + ~LsubOperator(void); + }; + + //-------------------------------------------------------------------- + class NamespaceOperator : public Operator { + public: + virtual ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + NamespaceOperator(void); + ~NamespaceOperator(void); + }; + + //-------------------------------------------------------------------- + class NoopOperator : public Operator { + public: + virtual ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + NoopOperator(void); + ~NoopOperator(void); + }; + + //-------------------------------------------------------------------- + class NoopPendingOperator : public NoopOperator { + public: + ProcessResult process(Depot &, Request &); + + NoopPendingOperator(void); + ~NoopPendingOperator(void); + }; + + //-------------------------------------------------------------------- + class RenameOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + RenameOperator(void); + ~RenameOperator(void); + }; + + //-------------------------------------------------------------------- + class SearchOperator : public Operator { + protected: + ParseResult expectSearchKey(BincImapParserSearchKey &s_in) const; + + //------------------------------------------------------------------ + class SearchNode { + + std::string date; + std::string astring; + std::string bstring; + unsigned int number; + + int type; + mutable int weight; + const SequenceSet *bset; + + std::vector children; + + public: + enum { + S_ALL, S_ANSWERED, S_BCC, S_BEFORE, S_BODY, S_CC, S_DELETED, + S_FLAGGED, S_FROM, S_KEYWORD, S_NEW, S_OLD, S_ON, S_RECENT, + S_SEEN, S_SINCE, S_SUBJECT, S_TEXT, S_TO, S_UNANSWERED, + S_UNDELETED, S_UNFLAGGED, S_UNKEYWORD, S_UNSEEN, S_DRAFT, + S_HEADER, S_LARGER, S_NOT, S_OR, S_SENTBEFORE, S_SENTON, + S_SENTSINCE, S_SMALLER, S_UID, S_UNDRAFT, S_SET, S_AND + }; + + static bool convertDate(const std::string &date, time_t &t, const std::string &delim = "-"); + static bool convertDateHeader(const std::string &d_in, time_t &t); + + void order(void); + + bool match(Mailbox *, Message *, + unsigned seqnr, unsigned int lastmessage, + unsigned int lastuid) const; + + int getType(void) const; + int getWeight(void) const; + void setWeight(int i); + + void init(const BincImapParserSearchKey &a); + + //- + static bool compareNodes(const SearchNode &a, + const SearchNode &b) + { + return a.getWeight() < b.getWeight(); + } + + SearchNode(void); + SearchNode(const BincImapParserSearchKey &a); + }; + + public: + + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + SearchOperator(void); + ~SearchOperator(void); + }; + + //-------------------------------------------------------------------- + class SelectOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + SelectOperator(void); + ~SelectOperator(void); + }; + + //-------------------------------------------------------------------- + class ExamineOperator : public SelectOperator { + public: + const std::string getName(void) const; + ExamineOperator(void); + ~ExamineOperator(void); + }; + + //-------------------------------------------------------------------- + class StarttlsOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + int goStartTLS(void) const; + + StarttlsOperator(void); + ~StarttlsOperator(void); + }; + + //-------------------------------------------------------------------- + class StatusOperator : public Operator { + + std::map statuses; + + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + StatusOperator(void); + ~StatusOperator(void); + }; + + //-------------------------------------------------------------------- + class StoreOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + StoreOperator(void); + ~StoreOperator(void); + }; + + //-------------------------------------------------------------------- + class SubscribeOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + SubscribeOperator(void); + ~SubscribeOperator(void); + }; + + //-------------------------------------------------------------------- + class UnsubscribeOperator : public Operator { + public: + ProcessResult process(Depot &, Request &); + virtual ParseResult parse(Request &) const; + + const std::string getName(void) const; + int getState(void) const; + + UnsubscribeOperator(void); + ~UnsubscribeOperator(void); + }; +} + +#endif diff --git a/src/include/pendingupdates.h b/src/include/pendingupdates.h new file mode 100644 index 0000000..ea192de --- /dev/null +++ b/src/include/pendingupdates.h @@ -0,0 +1,107 @@ +/** -------------------------------------------------------------------- + * @file pendingupdates.h + * @brief <---> + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#include +#include + +#ifndef pendingupdates_h_included +#define pendingupdates_h_included + +namespace Binc { + class Mailbox; + + //------------------------------------------------------------------------ + class PendingUpdates { + public: + enum { + EXPUNGE = 0x01, + FLAGS = 0x02, + EXISTS = 0x04, + RECENT = 0x08 + }; + + //---------------------------------------------------------------------- + class expunged_const_iterator { + private: + std::vector::iterator internal; + + public: + unsigned int operator * (void) const; + void operator ++ (void); + bool operator != (expunged_const_iterator) const; + bool operator == (expunged_const_iterator) const; + + //-- + expunged_const_iterator(void); + expunged_const_iterator(std::vector::iterator i); + }; + + //-- + expunged_const_iterator beginExpunged(void); + expunged_const_iterator endExpunged(void); + + //---------------------------------------------------------------------- + class flagupdates_const_iterator { + private: + std::map::iterator internal; + std::map *sqnrtouid; + std::map > *sqnrtocflags; + + public: + unsigned int first(void) const; + unsigned int second(void) const; + std::vector getCustomFlags(void) const; + unsigned int getUID(void) const; + + void operator ++ (void); + bool operator != (flagupdates_const_iterator) const; + + //-- + flagupdates_const_iterator(void); + flagupdates_const_iterator(std::map::iterator i, + std::map > *, + std::map *); + }; + + //-- + flagupdates_const_iterator beginFlagUpdates(void); + flagupdates_const_iterator endFlagUpdates(void); + + //-- + void addExpunged(unsigned int uid); + void addFlagUpdates(unsigned int sqnr, unsigned int uid, + unsigned int flags, + const std::vector &cflags); + void setExists(unsigned int n); + void setRecent(unsigned int n); + unsigned int getExists(void) const; + unsigned int getRecent(void) const; + bool newExists(void) const; + bool newRecent(void) const; + + //-- + PendingUpdates(void); + ~PendingUpdates(void); + + private: + std::vector expunges; + std::map flagupdates; + std::map sqnrtouid; + std::map > sqnrtocflags; + + unsigned int exists; + unsigned int recent; + bool newexists; + bool newrecent; + }; + + bool pendingUpdates(Mailbox *, int type, bool rescan, + bool showAll = false, + bool forceScan = false, + bool uidfetchflags = false); +} + +#endif diff --git a/src/include/recursivedescent.h b/src/include/recursivedescent.h new file mode 100644 index 0000000..ea8fe33 --- /dev/null +++ b/src/include/recursivedescent.h @@ -0,0 +1,64 @@ +/** -------------------------------------------------------------------- + * @file recursivedescent.h + * @brief Declaration of a recursive descent IMAP command parser. + * @author Andreas Aardal Hanssen + * @date Andreas Aardal Hanssen + * ----------------------------------------------------------------- **/ +#ifndef expectcommand_h_inluded +#define expectcommand_h_inluded +#include +#include + +#include "imapparser.h" +#include "operators.h" + +namespace Binc { + + extern std::stack inputBuffer; + extern int charnr; + + int readChar(void); + void unReadChar(int c_in); + void unReadChar(const std::string &s_in); + + Operator::ParseResult expectTag(std::string &s_in); + Operator::ParseResult expectTagChar(int &c_in); + Operator::ParseResult expectSPACE(void); + + Operator::ParseResult expectFlag(std::vector &v_in); + + Operator::ParseResult expectListMailbox(std::string &s_in); + Operator::ParseResult expectListWildcards(int &c_in); + + Operator::ParseResult expectDateTime(std::string &s_in); + Operator::ParseResult expectTime(std::string &s_in); + Operator::ParseResult expectZone(std::string &s_in); + + Operator::ParseResult expectMailbox(std::string &s_in); + Operator::ParseResult expectAstring(std::string &s_in); + Operator::ParseResult expectAtom(std::string &s_in); + Operator::ParseResult expectAtomChar(int &i_in); + Operator::ParseResult expectString(std::string &s_in); + + Operator::ParseResult expectDate(std::string &s_in); + + Operator::ParseResult expectNumber(unsigned int &i_in); + Operator::ParseResult expectDigit(unsigned int &i_in); + Operator::ParseResult expectDigitNZ(unsigned int &i_in); + + Operator::ParseResult expectLiteral(std::string &s_in); + Operator::ParseResult expectQuoted(std::string &s_in); + Operator::ParseResult expectQuotedChar(int &c_in); + + Operator::ParseResult expectSet(SequenceSet &s_in); + Operator::ParseResult expectSequenceNum(unsigned int &i_in); + Operator::ParseResult expectNZNumber(unsigned int &i_in); + + Operator::ParseResult expectCRLF(void); + Operator::ParseResult expectCR(void); + Operator::ParseResult expectLF(void); + + Operator::ParseResult expectThisString(const std::string &s_in); +} + +#endif diff --git a/src/include/regmatch.h b/src/include/regmatch.h new file mode 100644 index 0000000..1471e90 --- /dev/null +++ b/src/include/regmatch.h @@ -0,0 +1,17 @@ +/** -------------------------------------------------------------------- + * @file regex.h + * @brief Declaration of miscellaneous regexp functions. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef regex_h_included +#define regex_h_included + +#include + +namespace Binc { + + int regexMatch(const std::string &data_in, const std::string &p_in); +} + +#endif diff --git a/src/include/session.h b/src/include/session.h new file mode 100644 index 0000000..94825cd --- /dev/null +++ b/src/include/session.h @@ -0,0 +1,116 @@ +/** -------------------------------------------------------------------- + * @file session.h + * @brief <---> + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef session_h_included +#define session_h_included +#include +#include +#include +#include + +#include "argparser.h" + +namespace Binc { + + class Depot; + + //-------------------------------------------------------------------- + class Session { + public: + std::map attrs; + + char **unparsedArgs; + + struct { + bool help; + bool version; + bool ssl; + } command; + + bool mailboxchanges; + + enum State { + NONAUTHENTICATED = 0x01, + AUTHENTICATED = 0x02, + SELECTED = 0x04, + LOGOUT = 0x00 + }; + + CommandLineArgs args; + + int timeout() const; + + bool hasEnv(const std::string &key) const; + std::string getEnv(const std::string &key); + void setEnv(const std::string &key, const std::string &value); + + const int getState(void) const; + void setState(int n); + bool parseCommandLine(int argc, char * argv[]); + void assignCommandLineArgs(void); + int getWriteBytes(void) const; + int getReadBytes(void) const; + void addWriteBytes(int); + void addReadBytes(int); + int getBodies(void) const; + int getStatements(void) const; + void addBody(void); + void addStatement(void); + void setLogFacility(int facility); + int getLogFacility(void) const; + + const std::string &getLastError(void) const; + const std::string &getResponseCode(void) const; + const std::string &getIP(void) const; + const std::string &getUserID() const; + pid_t getPid(void); + const std::string &getHostname(void); + void setLastError(const std::string &error) const; + void setResponseCode(const std::string &error) const; + void clearResponseCode(void) const; + void setIP(const std::string &ip); + void setUserID(const std::string &s); + + inline Depot *getDepot(void) const; + + //-- + static Session &getInstance(void); + + bool initialize(int argc, char *argv[]); + + private: + //-- + int state; + std::string userid; + std::string ip; + char **argv; + int argc; + + int logfacility; + + int readbytes; + int writebytes; + int statements; + int bodies; + + Depot *depot; + + mutable std::string lastError; + mutable std::string responseCode; + + pid_t pid; + std::string hostname; + + Session(void); + }; + + inline Depot *Session::getDepot(void) const + { + return depot; + } +} + +#endif diff --git a/src/include/status.h b/src/include/status.h new file mode 100644 index 0000000..f7f9e1f --- /dev/null +++ b/src/include/status.h @@ -0,0 +1,50 @@ +/** -------------------------------------------------------------------- + * @file status.h + * @brief Declaration of the Status class. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#ifndef status_h_included +#define status_h_included + +namespace Binc { + + //------------------------------------------------------------------------ + class Status { + + //-- + int recent; + int messages; + int unseen; + int uidvalidity; + int uidnext; + + //-- + int statusid; + + public: + + //-- + inline void setMessages(int i) { messages = i; } + inline void setRecent(int i) { recent = i; } + inline void setStatusID(int i) { statusid = i; } + inline void setUnseen(int i) { unseen = i; } + inline void setUidValidity(int i) { uidvalidity = i; } + inline void setUidNext(int i) { uidnext = i; } + + //-- + inline int getMessages(void) const { return messages; } + inline int getRecent(void) const { return recent; } + inline int getStatusID(void) const { return statusid; } + inline int getUnseen(void) const { return unseen; } + inline int getUidValidity(void) const { return uidvalidity; } + inline int getUidNext(void) const { return uidnext; } + + + //-- + Status(void); + ~Status(void); + }; +} + +#endif diff --git a/src/include/stdiodevice.h b/src/include/stdiodevice.h new file mode 100644 index 0000000..026386c --- /dev/null +++ b/src/include/stdiodevice.h @@ -0,0 +1,31 @@ +/** -------------------------------------------------------------------- + * @file stdiodevice.h + * @brief Declaration of the StdIODevice class. + * @author Andreas Aardal Hanssen + * @date 2002, 2003 + * ----------------------------------------------------------------- **/ +#ifndef stdiodevice_h_included +#define stdiodevice_h_included + +#include "iodevice.h" + +namespace Binc { + class StdIODevice : public IODevice { + public: + StdIODevice(int flags); + ~StdIODevice(); + + std::string service(void) const; + + bool canRead(void) const; + + protected: + bool waitForWrite(void) const; + bool waitForRead(void) const; + + WriteResult write(void); + bool fillInputBuffer(void); + }; +} + +#endif diff --git a/src/include/syslogdevice.h b/src/include/syslogdevice.h new file mode 100644 index 0000000..2269fb2 --- /dev/null +++ b/src/include/syslogdevice.h @@ -0,0 +1,41 @@ +/** -------------------------------------------------------------------- + * @file Syslogdevice.h + * @brief Declaration of the SyslogDevice class. + * @author Andreas Aardal Hanssen + * @date 2002, 2003 + * ----------------------------------------------------------------- **/ +#ifndef syslogdevice_h_included +#define syslogdevice_h_included + +#include "iodevice.h" +#include + +namespace Binc { + class SyslogDevice : public IODevice { + public: + SyslogDevice(int flags, const char *ident = "bincimap", + int option = LOG_NDELAY | LOG_PID, + int facility = LOG_USER); + ~SyslogDevice(); + + void setPriority(int p); + + std::string service(void) const; + + protected: + bool waitForWrite(void) const; + bool waitForRead(void) const; + + WriteResult write(void); + bool fillInputBuffer(void); + + private: + static std::string ident; + + int option; + int facility; + int priority; + }; +} + +#endif diff --git a/src/include/tools.h b/src/include/tools.h new file mode 100644 index 0000000..67ed91e --- /dev/null +++ b/src/include/tools.h @@ -0,0 +1,23 @@ +/** -------------------------------------------------------------------- + * @file tools.h + * @brief Declaration of miscellaneous tools. + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ----------------------------------------------------------------- **/ +#include + +namespace Binc { + + class Tools { + private: + Tools(void); + + public: + void setenv(const std::string &key, const std::string &value) const; + std::string getenv(const std::string &key) const; + + //-- + static Tools &getInstance(void); + }; + +} -- cgit v1.2.3