diff options
Diffstat (limited to 'src/messaging/IMAPParser.hpp')
| -rw-r--r-- | src/messaging/IMAPParser.hpp | 5077 |
1 files changed, 0 insertions, 5077 deletions
diff --git a/src/messaging/IMAPParser.hpp b/src/messaging/IMAPParser.hpp deleted file mode 100644 index bd4eeb56..00000000 --- a/src/messaging/IMAPParser.hpp +++ /dev/null @@ -1,5077 +0,0 @@ -// -// VMime library (http://vmime.sourceforge.net) -// Copyright (C) 2002-2004 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#ifndef VMIME_MESSAGING_IMAPPARSER_HPP_INCLUDED -#define VMIME_MESSAGING_IMAPPARSER_HPP_INCLUDED - - -#include "base.hpp" -#include "dateTime.hpp" -#include "charset.hpp" -#include "exception.hpp" - -#include "utility/smartPtr.hpp" -#include "utility/stringUtils.hpp" - -#include "encoderB64.hpp" -#include "encoderQP.hpp" - -#include "platformDependant.hpp" - -#include "messaging/progressionListener.hpp" -#include "messaging/timeoutHandler.hpp" -#include "messaging/socket.hpp" - -#include "messaging/IMAPTag.hpp" - -#include <vector> -#include <stdexcept> - - -//#define DEBUG_RESPONSE 1 - - -#if DEBUG_RESPONSE -# include <iostream> -#endif - - -namespace vmime { -namespace messaging { - - -#if DEBUG_RESPONSE - static string DEBUG_RESPONSE_level; - static std::vector <string> DEBUG_RESPONSE_components; - -# define DEBUG_ENTER_COMPONENT(x) \ - DEBUG_RESPONSE_components.push_back(x); \ - std::cout << DEBUG_RESPONSE_level \ - << "(" << DEBUG_RESPONSE_level.length() << ") " \ - << (x) << std::endl; -# define DEBUG_FOUND(x, y) \ - std::cout << "FOUND: " << x << ": " << y << std::endl; -#else -# define DEBUG_ENTER_COMPONENT(x) -# define DEBUG_FOUND(x, y) -#endif - - -class IMAPParser -{ -public: - - IMAPParser(IMAPTag* tag, socket* sok, timeoutHandler* _timeoutHandler) - : m_tag(tag), m_socket(sok), m_progress(NULL), - m_literalHandler(NULL), m_timeoutHandler(_timeoutHandler) - { - } - - - const IMAPTag* tag() const - { - return (m_tag); - } - - - const string lastLine() const - { - // Remove blanks and new lines at the end of the line. - string line(m_lastLine); - - string::const_iterator it = line.end(); - int count = 0; - - while (it != line.begin()) - { - const unsigned char c = *(it - 1); - - if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) - break; - - ++count; - --it; - } - - line.resize(line.length() - count); - - return (line); - } - - - - // - // literalHandler : literal content handler - // - - class component; - - class literalHandler - { - public: - - virtual ~literalHandler() { } - - - // Abstract target class - class target - { - protected: - - target(class progressionListener* progress) : m_progress(progress) {} - target(const target&) {} - - public: - - virtual ~target() { } - - - class progressionListener* progressionListener() { return (m_progress); } - - virtual void putData(const string& chunk) = 0; - - private: - - class progressionListener* m_progress; - }; - - - // Target: put in a string - class targetString : public target - { - public: - - targetString(class progressionListener* progress, vmime::string& str) - : target(progress), m_string(str) { } - - const vmime::string& string() const { return (m_string); } - vmime::string& string() { return (m_string); } - - - void putData(const vmime::string& chunk) - { - m_string += chunk; - } - - private: - - vmime::string& m_string; - }; - - - // Target: redirect to an output stream - class targetStream : public target - { - public: - - targetStream(class progressionListener* progress, utility::outputStream& stream) - : target(progress), m_stream(stream) { } - - const utility::outputStream& stream() const { return (m_stream); } - utility::outputStream& stream() { return (m_stream); } - - - void putData(const string& chunk) - { - m_stream.write(chunk.data(), chunk.length()); - } - - private: - - utility::outputStream& m_stream; - }; - - - // Called when the parser needs to know what to do with a literal - // . comp: the component in which we are at this moment - // . data: data specific to the component (may not be used) - // - // Returns : - // . == NULL to put the literal into the response - // . != NULL to redirect the literal to the specified target - - virtual target* targetFor(const component& comp, const int data) = 0; - }; - - - // - // Base class for a terminal or a non-terminal - // - - class component - { - public: - - component() { } - virtual ~component() { } - - virtual void go(IMAPParser& parser, string& line, string::size_type* currentPos) = 0; - - - const string makeResponseLine(const string& comp, const string& line, - const string::size_type pos) - { -#if DEBUG_RESPONSE - if (pos > line.length()) - std::cout << "WARNING: component::makeResponseLine(): pos > line.length()" << std::endl; -#endif - - string result(line.substr(0, pos)); - result += "[^]"; // indicates current parser position - result += line.substr(pos, line.length()); - if (!comp.empty()) result += " [" + comp + "]"; - - return (result); - } - }; - - - - // - // Parse one character - // - - template <char C> - class one_char : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT(string("one_char <") + C + ">: current='" + ((*currentPos < line.length() ? line[*currentPos] : '?')) + "'"); - - const string::size_type pos = *currentPos; - - if (pos < line.length() && line[pos] == C) - *currentPos = pos + 1; - else - throw exceptions::invalid_response("", makeResponseLine("", line, pos)); - } - }; - - - // - // SPACE ::= <ASCII SP, space, 0x20> - // - - class SPACE : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("SPACE"); - - string::size_type pos = *currentPos; - - while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) - ++pos; - - if (pos > *currentPos) - *currentPos = pos; - else - throw exceptions::invalid_response("", makeResponseLine("SPACE", line, pos)); - } - }; - - - // - // CR ::= <ASCII CR, carriage return, 0x0D> - // LF ::= <ASCII LF, line feed, 0x0A> - // CRLF ::= CR LF - // - - class CRLF : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("CRLF"); - - string::size_type pos = *currentPos; - - parser.check <SPACE>(line, &pos, true); - - if (pos + 1 < line.length() && - line[pos] == 0x0d && line[pos + 1] == 0x0a) - { - *currentPos = pos + 2; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("CRLF", line, pos)); - } - } - }; - - - // - // SPACE ::= <ASCII SP, space, 0x20> - // CTL ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f> - // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f> - // ATOM_CHAR ::= <any CHAR except atom_specials> - // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials - // list_wildcards ::= "%" / "*" - // quoted_specials ::= <"> / "\" - // - // tag ::= 1*<any ATOM_CHAR except "+"> (named "xtag") - // - - class xtag : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("tag"); - - string::size_type pos = *currentPos; - - bool end = false; - - string tagString; - tagString.reserve(10); - - while (!end && pos < line.length()) - { - const unsigned char c = line[pos]; - - switch (c) - { - case '+': - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': // list_wildcards - case '*': // list_wildcards - case '"': // quoted_specials - case '\\': // quoted_specials - - end = true; - break; - - default: - - if (c <= 0x1f || c >= 0x7f) - end = true; - else - { - tagString += c; - ++pos; - } - - break; - } - } - - if (tagString == (string) *(parser.tag())) - { - *currentPos = pos; - } - else - { - // Invalid tag - throw exceptions::invalid_response("", makeResponseLine("tag", line, pos)); - } - } - }; - - - // - // digit ::= "0" / digit_nz - // digit_nz ::= "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" - // - // number ::= 1*digit - // ;; Unsigned 32-bit integer - // ;; (0 <= n < 4,294,967,296) - // - - class number : public component - { - public: - - number(const bool nonZero = false) - : m_nonZero(nonZero), m_value(0) - { - } - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("number"); - - string::size_type pos = *currentPos; - - bool valid = true; - unsigned int val = 0; - - while (valid && pos < line.length()) - { - const char c = line[pos]; - - if (c >= '0' && c <= '9') - { - val = (val * 10) + (c - '0'); - ++pos; - } - else - { - valid = false; - } - } - - // Check for non-null length (and for non-zero number) - if (!(m_nonZero && val == 0) && pos != *currentPos) - { - m_value = val; - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("number", line, pos)); - } - } - - private: - - const bool m_nonZero; - unsigned int m_value; - - public: - - const unsigned int value() const { return (m_value); } - }; - - - // nz_number ::= digit_nz *digit - // ;; Non-zero unsigned 32-bit integer - // ;; (0 < n < 4,294,967,296) - // - - class nz_number : public number - { - public: - - nz_number() : number(true) - { - } - }; - - - // - // text ::= 1*TEXT_CHAR - // - // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f> - // TEXT_CHAR ::= <any CHAR except CR and LF> - // - - class text : public component - { - public: - - text(bool allow8bits = false, const char except = 0) - : m_allow8bits(allow8bits), m_except(except) - { - } - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("text"); - - string::size_type pos = *currentPos; - string::size_type len = 0; - - if (m_allow8bits) - { - const unsigned char except = m_except; - - for (bool end = false ; !end && pos < line.length() ; ) - { - const unsigned char c = line[pos]; - - if (c == 0x00 || c == 0x0d || c == 0x0a || c == except) - { - end = true; - } - else - { - ++pos; - ++len; - } - } - } - else - { - const unsigned char except = m_except; - - for (bool end = false ; !end && pos < line.length() ; ) - { - const unsigned char c = line[pos]; - - if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except) - { - end = true; - } - else - { - ++pos; - ++len; - } - } - } - - if (len != 0) - { - m_value.resize(len); - std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); - - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("text", line, pos)); - } - } - - private: - - string m_value; - const bool m_allow8bits; - const char m_except; - - public: - - const string& value() const { return (m_value); } - }; - - - class text8 : public text - { - public: - - text8() : text(true) - { - } - }; - - - template <char C> - class text_except : public text - { - public: - - text_except() : text(false, C) - { - } - }; - - - template <char C> - class text8_except : public text - { - public: - - text8_except() : text(true, C) - { - } - }; - - - // - // QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / "\" quoted_specials - // quoted_specials ::= <"> / "\" - // TEXT_CHAR ::= <any CHAR except CR and LF> - // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f> - // - - class QUOTED_CHAR : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("quoted_char"); - - string::size_type pos = *currentPos; - - const unsigned char c = (pos < line.length() ? line[pos] : 0); - - if (c >= 0x01 && c <= 0x7f && // 0x01 - 0x7f - c != '"' && c != '\\' && // quoted_specials - c != '\r' && c != '\n') // CR and LF - { - m_value = c; - *currentPos = pos + 1; - } - else if (c == '\\' && pos + 1 < line.length() && - (line[pos + 1] == '"' || line[pos + 1] == '\\')) - { - m_value = line[pos + 1]; - *currentPos = pos + 2; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("QUOTED_CHAR", line, pos)); - } - } - - private: - - char m_value; - - public: - - const char value() const { return (m_value); } - }; - - - // - // quoted ::= <"> *QUOTED_CHAR <"> - // QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / "\" quoted_specials - // quoted_specials ::= <"> / "\" - // TEXT_CHAR ::= <any CHAR except CR and LF> - // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f> - // - - class quoted_text : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("quoted_text"); - - string::size_type pos = *currentPos; - string::size_type len = 0; - bool valid = false; - - m_value.reserve(line.length() - pos); - - for (bool end = false, quoted = false ; !end && pos < line.length() ; ) - { - const unsigned char c = line[pos]; - - if (quoted) - { - if (c == '"' || c == '\\') - m_value += c; - else - { - m_value += '\\'; - m_value += c; - } - - quoted = false; - - ++pos; - ++len; - } - else - { - if (c == '\\') - { - quoted = true; - - ++pos; - ++len; - } - else if (c == '"') - { - valid = true; - end = true; - } - else if (c >= 0x01 && c <= 0x7f && // CHAR - c != 0x0a && c != 0x0d) // CR and LF - { - m_value += c; - - ++pos; - ++len; - } - else - { - valid = false; - end = true; - } - } - } - - if (valid) - { - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("quoted_text", line, pos)); - } - } - - private: - - string m_value; - - public: - - const string& value() const { return (m_value); } - }; - - - // - // nil ::= "NIL" - // - - class NIL : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("NIL"); - - string::size_type pos = *currentPos; - - parser.checkWithArg <special_atom>(line, &pos, "nil"); - - *currentPos = pos; - } - }; - - - // - // string ::= quoted / literal ----> named 'xstring' - // - // nil ::= "NIL" - // quoted ::= <"> *QUOTED_CHAR <"> - // QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / "\" quoted_specials - // quoted_specials ::= <"> / "\" - // TEXT_CHAR ::= <any CHAR except CR and LF> - // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f> - // literal ::= "{" number "}" CRLF *CHAR8 - // ;; Number represents the number of CHAR8 octets - // CHAR8 ::= <any 8-bit octet except NUL, 0x01 - 0xff> - // - - class xstring : public component - { - public: - - xstring(const bool canBeNIL = false, component* comp = NULL, const int data = 0) - : m_canBeNIL(canBeNIL), m_component(comp), m_data(data) - { - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("string"); - - string::size_type pos = *currentPos; - - if (m_canBeNIL && - parser.checkWithArg <special_atom>(line, &pos, "nil", true)) - { - // NIL - } - else - { - pos = *currentPos; - - // quoted ::= <"> *QUOTED_CHAR <"> - if (parser.check <one_char <'"'> >(line, &pos, true)) - { - utility::auto_ptr <quoted_text> text(parser.get <quoted_text>(line, &pos)); - parser.check <one_char <'"'> >(line, &pos); - - if (parser.m_literalHandler != NULL) - { - literalHandler::target* target = - parser.m_literalHandler->targetFor(*m_component, m_data); - - if (target != NULL) - { - m_value = "[literal-handler]"; - - const string::size_type length = text->value().length(); - progressionListener* progress = target->progressionListener(); - - if (progress) - { - progress->start(length); - } - - target->putData(text->value()); - - if (progress) - { - progress->progress(length, length); - progress->stop(length); - } - - delete (target); - } - else - { - m_value = text->value(); - } - } - else - { - m_value = text->value(); - } - - DEBUG_FOUND("string[quoted]", "<length=" << m_value.length() << ", value='" << m_value << "'>"); - } - // literal ::= "{" number "}" CRLF *CHAR8 - else - { - parser.check <one_char <'{'> >(line, &pos); - - number* num = parser.get <number>(line, &pos); - - const string::size_type length = num->value(); - delete (num); - - parser.check <one_char <'}'> >(line, &pos); - - parser.check <CRLF>(line, &pos); - - - if (parser.m_literalHandler != NULL) - { - literalHandler::target* target = - parser.m_literalHandler->targetFor(*m_component, m_data); - - if (target != NULL) - { - m_value = "[literal-handler]"; - - parser.m_progress = target->progressionListener(); - parser.readLiteral(*target, length); - parser.m_progress = NULL; - - delete (target); - } - else - { - literalHandler::targetString target(NULL, m_value); - parser.readLiteral(target, length); - } - } - else - { - literalHandler::targetString target(NULL, m_value); - parser.readLiteral(target, length); - } - - line += parser.readLine(); - - DEBUG_FOUND("string[literal]", "<length=" << length << ", value='" << m_value << "'>"); - } - } - - *currentPos = pos; - } - - private: - - bool m_canBeNIL; - string m_value; - - component* m_component; - const int m_data; - - public: - - const string& value() const { return (m_value); } - }; - - - // - // nstring ::= string / nil - // - - class nstring : public xstring - { - public: - - nstring(component* comp = NULL, const int data = 0) - : xstring(true, comp, data) - { - } - }; - - - // - // astring ::= atom / string - // - - class astring : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("astring"); - - string::size_type pos = *currentPos; - - xstring* str = NULL; - - if ((str = parser.get <xstring>(line, &pos, true))) - { - m_value = str->value(); - delete (str); - } - else - { - atom* at = parser.get <atom>(line, &pos); - m_value = at->value(); - delete (at); - } - - *currentPos = pos; - } - - private: - - string m_value; - - public: - - const string& value() const { return (m_value); } - }; - - - // - // atom ::= 1*ATOM_CHAR - // - // ATOM_CHAR ::= <any CHAR except atom_specials> - // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials - // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f> - // CTL ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f> - // list_wildcards ::= "%" / "*" - // quoted_specials ::= <"> / "\" - // SPACE ::= <ASCII SP, space, 0x20> - // - - class atom : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("atom"); - - string::size_type pos = *currentPos; - string::size_type len = 0; - - for (bool end = false ; !end && pos < line.length() ; ) - { - const unsigned char c = line[pos]; - - switch (c) - { - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': // list_wildcards - case '*': // list_wildcards - case '"': // quoted_specials - case '\\': // quoted_specials - - case '[': - case ']': // for "special_atom" - - end = true; - break; - - default: - - if (c <= 0x1f || c >= 0x7f) - end = true; - else - { - ++pos; - ++len; - } - } - } - - if (len != 0) - { - m_value.resize(len); - std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); - - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("atom", line, pos)); - } - } - - private: - - string m_value; - - public: - - const string& value() const { return (m_value); } - }; - - - // - // special atom (eg. "CAPABILITY", "FLAGS", "STATUS"...) - // - // " Except as noted otherwise, all alphabetic characters are case- - // insensitive. The use of upper or lower case characters to define - // token strings is for editorial clarity only. Implementations MUST - // accept these strings in a case-insensitive fashion. " - // - - class special_atom : public atom - { - public: - - special_atom(const char* str) - : m_string(str) // 'string' must be in lower-case - { - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT(string("special_atom(") + m_string + ")"); - - string::size_type pos = *currentPos; - - atom::go(parser, line, &pos); - - const char* cmp = value().c_str(); - const char* with = m_string; - - bool ok = true; - - while (ok && *cmp && *with) - { - ok = (std::tolower(*cmp, std::locale()) == *with); - - ++cmp; - ++with; - } - - if (!ok || *cmp || *with) - { - throw exceptions::invalid_response("", makeResponseLine(string("special_atom <") + m_string + ">", line, pos)); - } - else - { - *currentPos = pos; - } - } - - private: - - const char* m_string; - }; - - - // - // text_mime2 ::= "=?" <charset> "?" <encoding> "?" <encoded-text> "?=" - // ;; Syntax defined in [MIME-HDRS] - // - - class text_mime2 : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("text_mime2"); - - string::size_type pos = *currentPos; - - atom* theCharset = NULL, *theEncoding = NULL; - text* theText = NULL; - - try - { - parser.check <one_char <'='> >(line, &pos); - parser.check <one_char <'?'> >(line, &pos); - - theCharset = parser.get <atom>(line, &pos); - - parser.check <one_char <'?'> >(line, &pos); - - theEncoding = parser.get <atom>(line, &pos); - - parser.check <one_char <'?'> >(line, &pos); - - theText = parser.get <text8_except <'?'> >(line, &pos); - - parser.check <one_char <'?'> >(line, &pos); - parser.check <one_char <'='> >(line, &pos); - } - catch (std::exception& e) - { - delete (theCharset); - delete (theEncoding); - delete (theText); - - throw; - } - - m_charset = theCharset->value(); - delete (theCharset); - - // Decode text - encoder* theEncoder = NULL; - - if (theEncoding->value()[0] == 'q' || theEncoding->value()[0] == 'Q') - { - // Quoted-printable - theEncoder = new encoderQP; - theEncoder->getProperties()["rfc2047"] = true; - } - else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') - { - // Base64 - theEncoder = new encoderB64; - } - - if (theEncoder) - { - utility::inputStreamStringAdapter in(theText->value()); - utility::outputStreamStringAdapter out(m_value); - - theEncoder->decode(in, out); - delete (theEncoder); - } - // No decoder available - else - { - m_value = theText->value(); - } - - delete (theEncoding); - delete (theText); - - *currentPos = pos; - } - - private: - - vmime::charset m_charset; - string m_value; - - public: - - const vmime::charset& charset() const { return (m_charset); } - const string& value() const { return (m_value); } - }; - - - // - // flag ::= "\Answered" / "\Flagged" / "\Deleted" / - // "\Seen" / "\Draft" / flag_keyword / flag_extension - // - // flag_extension ::= "\" atom - // ;; Future expansion. Client implementations - // ;; MUST accept flag_extension flags. Server - // ;; implementations MUST NOT generate - // ;; flag_extension flags except as defined by - // ;; future standard or standards-track - // ;; revisions of this specification. - // - // flag_keyword ::= atom - // - - class flag : public component - { - public: - - flag() - : m_flag_keyword(NULL) - { - } - - ~flag() - { - delete (m_flag_keyword); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("flag_keyword"); - - string::size_type pos = *currentPos; - - if (parser.check <one_char <'\\'> >(line, &pos, true)) - { - if (parser.check <one_char <'*'> >(line, &pos, true)) - { - m_type = STAR; - } - else - { - atom* at = parser.get <atom>(line, &pos); - const string name = stringUtils::toLower(at->value()); - delete (at); - - if (name == "answered") - m_type = ANSWERED; - else if (name == "flagged") - m_type = FLAGGED; - else if (name == "deleted") - m_type = DELETED; - else if (name == "seen") - m_type = SEEN; - else if (name == "draft") - m_type = DRAFT; - else - { - m_type = UNKNOWN; - m_name = name; - } - } - } - else - { - m_flag_keyword = parser.get <atom>(line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - UNKNOWN, - ANSWERED, - FLAGGED, - DELETED, - SEEN, - DRAFT, - STAR // * = custom flags allowed - }; - - private: - - Type m_type; - string m_name; - - IMAPParser::atom* m_flag_keyword; - - public: - - const Type type() const { return (m_type); } - const string& name() const { return (m_name); } - - const IMAPParser::atom* flag_keyword() const { return (m_flag_keyword); } - }; - - - // - // flag_list ::= "(" #flag ")" - // - - class flag_list : public component - { - public: - - ~flag_list() - { - for (std::vector <flag*>::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("flag_list"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - { - m_flags.push_back(parser.get <flag>(line, &pos)); - parser.check <SPACE>(line, &pos, true); - } - - *currentPos = pos; - } - - private: - - std::vector <flag*> m_flags; - - public: - - const std::vector <flag*>& flags() const { return (m_flags); } - }; - - - // - // mailbox ::= "INBOX" / astring - // ;; INBOX is case-insensitive. All case variants of - // ;; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX - // ;; not as an astring. Refer to section 5.1 for - // ;; further semantic details of mailbox names. - // - - class mailbox : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox"); - - string::size_type pos = *currentPos; - - if (parser.checkWithArg <special_atom>(line, &pos, "inbox", true)) - { - m_type = INBOX; - m_name = "INBOX"; - } - else - { - m_type = OTHER; - - astring* astr = parser.get <astring>(line, &pos); - m_name = astr->value(); - delete (astr); - } - - *currentPos = pos; - } - - - enum Type - { - INBOX, - OTHER - }; - - private: - - Type m_type; - string m_name; - - public: - - const Type type() const { return (m_type); } - const string& name() const { return (m_name); } - }; - - - // - // mailbox_flag := "\Marked" / "\Noinferiors" / - // "\Noselect" / "\Unmarked" / flag_extension - // - - class mailbox_flag : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_flag"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'\\'> >(line, &pos); - - atom* at = parser.get <atom>(line, &pos); - const string name = stringUtils::toLower(at->value()); - delete (at); - - if (name == "marked") - m_type = MARKED; - else if (name == "noinferiors") - m_type = NOINFERIORS; - else if (name == "noselect") - m_type = NOSELECT; - else if (name == "unmarked") - m_type = UNMARKED; - else - { - m_type = UNKNOWN; - m_name = name; - } - - *currentPos = pos; - } - - - enum Type - { - UNKNOWN, - MARKED, - NOINFERIORS, - NOSELECT, - UNMARKED - }; - - private: - - Type m_type; - string m_name; - - public: - - const Type type() const { return (m_type); } - const string& name() const { return (m_name); } - }; - - - // - // mailbox_flag_list ::= "(" #(mailbox_flag) ")" - // - - class mailbox_flag_list : public component - { - public: - - ~mailbox_flag_list() - { - for (std::vector <mailbox_flag*>::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_flag_list"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - { - m_flags.push_back(parser.get <mailbox_flag>(line, &pos)); - parser.check <SPACE>(line, &pos, true); - } - - *currentPos = pos; - } - - private: - - std::vector <mailbox_flag*> m_flags; - - public: - - const std::vector <mailbox_flag*>& flags() const { return (m_flags); } - }; - - - // - // mailbox_list ::= mailbox_flag_list SPACE - // (<"> QUOTED_CHAR <"> / nil) SPACE mailbox - // - - class mailbox_list : public component - { - public: - - mailbox_list() - : m_mailbox_flag_list(NULL), - m_mailbox(NULL), m_quoted_char('\0') - { - } - - ~mailbox_list() - { - delete (m_mailbox_flag_list); - delete (m_mailbox); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_list"); - - string::size_type pos = *currentPos; - - m_mailbox_flag_list = parser.get <IMAPParser::mailbox_flag_list>(line, &pos); - - parser.check <SPACE>(line, &pos); - - if (!parser.check <NIL>(line, &pos, true)) - { - parser.check <one_char <'"'> >(line, &pos); - - QUOTED_CHAR* qc = parser.get <QUOTED_CHAR>(line, &pos); - m_quoted_char = qc->value(); - delete (qc); - - parser.check <one_char <'"'> >(line, &pos); - } - - parser.check <SPACE>(line, &pos); - - m_mailbox = parser.get <IMAPParser::mailbox>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::mailbox_flag_list* m_mailbox_flag_list; - IMAPParser::mailbox* m_mailbox; - char m_quoted_char; - - public: - - const IMAPParser::mailbox_flag_list* mailbox_flag_list() const { return (m_mailbox_flag_list); } - const IMAPParser::mailbox* mailbox() const { return (m_mailbox); } - const char quoted_char() const { return (m_quoted_char); } - }; - - - // - // resp_text_code ::= "ALERT" / "PARSE" / - // "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" / - // "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / - // "UIDVALIDITY" SPACE nz_number / - // "UNSEEN" SPACE nz_number / - // atom [SPACE 1*<any TEXT_CHAR except "]">] - - class resp_text_code : public component - { - public: - - resp_text_code() - : m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL), m_text(NULL) - { - } - - ~resp_text_code() - { - delete (m_nz_number); - delete (m_atom); - delete (m_flag_list); - delete (m_text); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_text_code"); - - string::size_type pos = *currentPos; - - // "ALERT" - if (parser.checkWithArg <special_atom>(line, &pos, "alert", true)) - { - m_type = ALERT; - } - // "PARSE" - else if (parser.checkWithArg <special_atom>(line, &pos, "parse", true)) - { - m_type = PARSE; - } - // "PERMANENTFLAGS" SPACE flag_list - else if (parser.checkWithArg <special_atom>(line, &pos, "permanentflags", true)) - { - m_type = PERMANENTFLAGS; - - parser.check <SPACE>(line, &pos); - - m_flag_list = parser.get <IMAPParser::flag_list>(line, &pos); - } - // "READ-ONLY" - else if (parser.checkWithArg <special_atom>(line, &pos, "read-only", true)) - { - m_type = READ_ONLY; - } - // "READ-WRITE" - else if (parser.checkWithArg <special_atom>(line, &pos, "read-write", true)) - { - m_type = READ_WRITE; - } - // "TRYCREATE" - else if (parser.checkWithArg <special_atom>(line, &pos, "trycreate", true)) - { - m_type = TRYCREATE; - } - // "UIDVALIDITY" SPACE nz_number - else if (parser.checkWithArg <special_atom>(line, &pos, "uidvalidity", true)) - { - m_type = UIDVALIDITY; - - parser.check <SPACE>(line, &pos); - m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos); - } - // "UNSEEN" SPACE nz_number - else if (parser.checkWithArg <special_atom>(line, &pos, "unseen", true)) - { - m_type = UNSEEN; - - parser.check <SPACE>(line, &pos); - m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos); - } - // atom [SPACE 1*<any TEXT_CHAR except "]">] - else - { - m_type = OTHER; - - m_atom = parser.get <IMAPParser::atom>(line, &pos); - - if (parser.check <SPACE>(line, &pos, true)) - m_text = parser.get <text_except <']'> >(line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - ALERT, - PARSE, - PERMANENTFLAGS, - READ_ONLY, - READ_WRITE, - TRYCREATE, - UIDVALIDITY, - UNSEEN, - OTHER - }; - - private: - - Type m_type; - - IMAPParser::nz_number* m_nz_number; - IMAPParser::atom* m_atom; - IMAPParser::flag_list* m_flag_list; - IMAPParser::text* m_text; - - public: - - const Type type() const { return (m_type); } - - const IMAPParser::nz_number* nz_number() const { return (m_nz_number); } - const IMAPParser::atom* atom() const { return (m_atom); } - const IMAPParser::flag_list* flag_list() const { return (m_flag_list); } - const IMAPParser::text* text() const { return (m_text); } - }; - - - // - // resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text) - // ;; text SHOULD NOT begin with "[" or "=" - - class resp_text : public component - { - public: - - resp_text() - : m_resp_text_code(NULL) - { - } - - ~resp_text() - { - delete (m_resp_text_code); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_text"); - - string::size_type pos = *currentPos; - - if (parser.check <one_char <'['> >(line, &pos, true)) - { - m_resp_text_code = parser.get <IMAPParser::resp_text_code>(line, &pos); - - parser.check <one_char <']'> >(line, &pos); - parser.check <SPACE>(line, &pos); - } - - text_mime2* text1 = parser.get <text_mime2>(line, &pos, true); - - if (text1 != NULL) - { - m_text = text1->value(); - delete (text1); - } - else - { - IMAPParser::text* text2 = - parser.get <IMAPParser::text>(line, &pos); - - m_text = text2->value(); - delete (text2); - } - - *currentPos = pos; - } - - private: - - IMAPParser::resp_text_code* m_resp_text_code; - string m_text; - - public: - - const IMAPParser::resp_text_code* resp_text_code() const { return (m_resp_text_code); } - const string& text() const { return (m_text); } - }; - - - // - // continue_req ::= "+" SPACE (resp_text / base64) - // - - class continue_req : public component - { - public: - - continue_req() - : m_resp_text(NULL) - { - } - - ~continue_req() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("continue_req"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'+'> >(line, &pos); - parser.check <SPACE>(line, &pos); - - m_resp_text = parser.get <IMAPParser::resp_text>(line, &pos); - - parser.check <CRLF>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_text* m_resp_text; - - public: - - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - }; - - - // - // auth_type ::= atom - // ;; Defined by [IMAP-AUTH] - // - - class auth_type : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("auth_type"); - - atom* at = parser.get <atom>(line, currentPos); - m_name = stringUtils::toLower(at->value()); - delete (at); - - if (m_name == "kerberos_v4") - m_type = KERBEROS_V4; - else if (m_name == "gssapi") - m_type = GSSAPI; - else if (m_name == "skey") - m_type = SKEY; - else - m_type = UNKNOWN; - } - - - enum Type - { - UNKNOWN, - - // RFC 1731 - IMAP4 Authentication Mechanisms - KERBEROS_V4, - GSSAPI, - SKEY - }; - - private: - - Type m_type; - string m_name; - - public: - - const Type type() const { return (m_type); } - const string name() const { return (m_name); } - }; - - - // - // status_att ::= "MESSAGES" / "RECENT" / "UIDNEXT" / - // "UIDVALIDITY" / "UNSEEN" - // - - class status_att : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("status_att"); - - string::size_type pos = *currentPos; - - if (parser.checkWithArg <special_atom>(line, &pos, "messages", true)) - { - m_type = MESSAGES; - } - else if (parser.checkWithArg <special_atom>(line, &pos, "recent", true)) - { - m_type = RECENT; - } - else if (parser.checkWithArg <special_atom>(line, &pos, "uidnext", true)) - { - m_type = UIDNEXT; - } - else if (parser.checkWithArg <special_atom>(line, &pos, "uidvalidity", true)) - { - m_type = UIDVALIDITY; - } - else - { - parser.checkWithArg <special_atom>(line, &pos, "unseen"); - m_type = UNSEEN; - } - - *currentPos = pos; - } - - - enum Type - { - MESSAGES, - RECENT, - UIDNEXT, - UIDVALIDITY, - UNSEEN - }; - - private: - - Type m_type; - - public: - - const Type type() const { return (m_type); } - }; - - - // - // capability ::= "AUTH=" auth_type / atom - // ;; New capabilities MUST begin with "X" or be - // ;; registered with IANA as standard or standards-track - // - - class capability : public component - { - public: - - capability() - : m_auth_type(NULL), m_atom(NULL) - { - } - - ~capability() - { - delete (m_auth_type); - delete (m_atom); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("capability"); - - string::size_type pos = *currentPos; - - class atom* at = parser.get <IMAPParser::atom>(line, &pos); - - string value = at->value(); - const char* str = value.c_str(); - - if ((str[0] == 'a' || str[0] == 'A') && - (str[1] == 'u' || str[1] == 'U') && - (str[2] == 't' || str[2] == 'T') && - (str[3] == 'h' || str[3] == 'H') && - (str[4] == '=')) - { - string::size_type pos = 5; - m_auth_type = parser.get <IMAPParser::auth_type>(value, &pos); - delete (at); - } - else - { - m_atom = at; - } - - *currentPos = pos; - } - - private: - - IMAPParser::auth_type* m_auth_type; - IMAPParser::atom* m_atom; - - public: - - const IMAPParser::auth_type* auth_type() const { return (m_auth_type); } - const IMAPParser::atom* atom() const { return (m_atom); } - }; - - - // - // capability_data ::= "CAPABILITY" SPACE [1#capability SPACE] "IMAP4rev1" - // [SPACE 1#capability] - // ;; IMAP4rev1 servers which offer RFC 1730 - // ;; compatibility MUST list "IMAP4" as the first - // ;; capability. - // - - class capability_data : public component - { - public: - - ~capability_data() - { - for (std::vector <capability*>::iterator it = m_capabilities.begin() ; - it != m_capabilities.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("capability_data"); - - string::size_type pos = *currentPos; - - parser.checkWithArg <special_atom>(line, &pos, "capability"); - parser.check <SPACE>(line, &pos); - - bool IMAP4rev1 = false; - - for (bool end = false ; !end && !IMAP4rev1 ; ) - { - if (parser.checkWithArg <special_atom>(line, &pos, "imap4rev1", true)) - { - IMAP4rev1 = true; - } - else - { - capability* cap = parser.get <capability>(line, &pos); - end = (cap == NULL); - - if (cap) - { - m_capabilities.push_back(cap); - } - } - - parser.check <SPACE>(line, &pos); - } - - - if (parser.check <SPACE>(line, &pos, true)) - { - for (capability* cap = NULL ; - (cap = parser.get <capability>(line, &pos)) != NULL ; ) - { - m_capabilities.push_back(cap); - - parser.check <SPACE>(line, &pos); - } - } - - *currentPos = pos; - } - - private: - - std::vector <capability*> m_capabilities; - - public: - - const std::vector <capability*>& capabilities() const { return (m_capabilities); } - }; - - - // - // date_day_fixed ::= (SPACE digit) / 2digit - // ;; Fixed-format version of date_day - // - // date_month ::= "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / - // "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" - // - // date_year ::= 4digit - // - // time ::= 2digit ":" 2digit ":" 2digit - // ;; Hours minutes seconds - // - // zone ::= ("+" / "-") 4digit - // ;; Signed four-digit value of hhmm representing - // ;; hours and minutes west of Greenwich (that is, - // ;; (the amount that the given time differs from - // ;; Universal Time). Subtracting the timezone - // ;; from the given time will give the UT form. - // ;; The Universal Time zone is "+0000". - // - // date_time ::= <"> date_day_fixed "-" date_month "-" date_year - // SPACE time SPACE zone <"> - // - - class date_time : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("date_time"); - - string::size_type pos = *currentPos; - - // <"> date_day_fixed "-" date_month "-" date_year - parser.check <one_char <'"'> >(line, &pos); - parser.check <SPACE>(line, &pos, true); - - utility::auto_ptr <number> nd(parser.get <number>(line, &pos)); - - parser.check <one_char <'-'> >(line, &pos); - - utility::auto_ptr <atom> amo(parser.get <atom>(line, &pos)); - - parser.check <one_char <'-'> >(line, &pos); - - utility::auto_ptr <number> ny(parser.get <number>(line, &pos)); - - parser.check <SPACE>(line, &pos, true); - - // 2digit ":" 2digit ":" 2digit - utility::auto_ptr <number> nh(parser.get <number>(line, &pos)); - - parser.check <one_char <':'> >(line, &pos); - - utility::auto_ptr <number> nmi(parser.get <number>(line, &pos)); - - parser.check <one_char <':'> >(line, &pos); - - utility::auto_ptr <number> ns(parser.get <number>(line, &pos)); - - parser.check <SPACE>(line, &pos, true); - - // ("+" / "-") 4digit - int sign = 1; - - if (!(parser.check <one_char <'+'> >(line, &pos, true))) - parser.check <one_char <'-'> >(line, &pos); - - utility::auto_ptr <number> nz(parser.get <number>(line, &pos)); - - parser.check <one_char <'"'> >(line, &pos); - - - m_datetime.setHour(std::min(std::max(nh->value(), 0u), 23u)); - m_datetime.setMinute(std::min(std::max(nmi->value(), 0u), 59u)); - m_datetime.setSecond(std::min(std::max(ns->value(), 0u), 59u)); - - const int zone = static_cast <int>(nz->value()); - const int zh = zone / 100; // hour offset - const int zm = zone % 100; // minute offset - - m_datetime.setZone(((zh * 60) + zm) * sign); - - m_datetime.setDay(std::min(std::max(nd->value(), 1u), 31u)); - m_datetime.setYear(ny->value()); - - const string month(stringUtils::toLower(amo->value())); - int mon = vmime::datetime::JANUARY; - - if (month.length() >= 3) - { - switch (month[0]) - { - case 'j': - { - switch (month[1]) - { - case 'a': mon = vmime::datetime::JANUARY; break; - case 'u': - { - switch (month[2]) - { - case 'n': mon = vmime::datetime::JUNE; break; - default: mon = vmime::datetime::JULY; break; - } - - break; - } - - } - - break; - } - case 'f': mon = vmime::datetime::FEBRUARY; break; - case 'm': - { - switch (month[2]) - { - case 'r': mon = vmime::datetime::MARCH; break; - default: mon = vmime::datetime::MAY; break; - } - - break; - } - case 'a': - { - switch (month[1]) - { - case 'p': mon = vmime::datetime::APRIL; break; - default: mon = vmime::datetime::AUGUST; break; - } - - break; - } - case 's': mon = vmime::datetime::SEPTEMBER; break; - case 'o': mon = vmime::datetime::OCTOBER; break; - case 'n': mon = vmime::datetime::NOVEMBER; break; - case 'd': mon = vmime::datetime::DECEMBER; break; - } - } - - m_datetime.setMonth(mon); - - *currentPos = pos; - } - - private: - - vmime::datetime m_datetime; - }; - - - // - // header_fld_name ::= astring - // - - typedef astring header_fld_name; - - - // - // header_list ::= "(" 1#header_fld_name ")" - // - - class header_list : public component - { - public: - - ~header_list() - { - for (std::vector <header_fld_name*>::iterator it = m_fld_names.begin() ; - it != m_fld_names.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("header_list"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - { - m_fld_names.push_back(parser.get <header_fld_name>(line, &pos)); - parser.check <SPACE>(line, &pos, true); - } - - *currentPos = pos; - } - - private: - - std::vector <header_fld_name*> m_fld_names; - - public: - - const std::vector <header_fld_name*>& fld_names() const { return (m_fld_names); } - }; - - - // - // body_extension ::= nstring / number / "(" 1#body_extension ")" - // ;; Future expansion. Client implementations - // ;; MUST accept body_extension fields. Server - // ;; implementations MUST NOT generate - // ;; body_extension fields except as defined by - // ;; future standard or standards-track - // ;; revisions of this specification. - // - - class body_extension : public component - { - public: - - body_extension() - : m_nstring(NULL), m_number(NULL) - { - } - - ~body_extension() - { - delete (m_nstring); - delete (m_number); - - for (std::vector <body_extension*>::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - string::size_type pos = *currentPos; - - if (parser.check <one_char <'('> >(line, &pos, true)) - { - m_body_extensions.push_back - (parser.get <body_extension>(line, &pos)); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - m_body_extensions.push_back(parser.get <body_extension>(line, &pos, true)); - } - else - { - if (!(m_nstring = parser.get <IMAPParser::nstring>(line, &pos, true))) - m_number = parser.get <IMAPParser::number>(line, &pos); - } - - *currentPos = pos; - } - - private: - - IMAPParser::nstring* m_nstring; - IMAPParser::number* m_number; - - std::vector <body_extension*> m_body_extensions; - - public: - - IMAPParser::nstring* nstring() const { return (m_nstring); } - IMAPParser::number* number() const { return (m_number); } - - const std::vector <body_extension*>& body_extensions() const { return (m_body_extensions); } - }; - - - // - // section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"] - // SPACE header_list / "TEXT" / "MIME" - // - - class section_text : public component - { - public: - - section_text() - : m_header_list(NULL) - { - } - - ~section_text() - { - delete (m_header_list); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("section_text"); - - string::size_type pos = *currentPos; - - // "HEADER.FIELDS" [".NOT"] SPACE header_list - const bool b1 = parser.checkWithArg <special_atom>(line, &pos, "header.fields.not", true); - const bool b2 = (b1 ? false : parser.checkWithArg <special_atom>(line, &pos, "header.fields", true)); - - if (b1 || b2) - { - m_type = b1 ? HEADER_FIELDS_NOT : HEADER_FIELDS; - - parser.check <SPACE>(line, &pos); - m_header_list = parser.get <IMAPParser::header_list>(line, &pos); - } - // "HEADER" - else if (parser.checkWithArg <special_atom>(line, &pos, "header", true)) - { - m_type = HEADER; - } - // "MIME" - else if (parser.checkWithArg <special_atom>(line, &pos, "mime", true)) - { - m_type = MIME; - } - // "TEXT" - else - { - m_type = TEXT; - - parser.checkWithArg <special_atom>(line, &pos, "text"); - } - - *currentPos = pos; - } - - - enum Type - { - HEADER, - HEADER_FIELDS, - HEADER_FIELDS_NOT, - MIME, - TEXT - }; - - private: - - Type m_type; - IMAPParser::header_list* m_header_list; - - public: - - const Type type() const { return (m_type); } - const IMAPParser::header_list* header_list() const { return (m_header_list); } - }; - - - // - // section ::= "[" [section_text / (nz_number *["." nz_number] - // ["." (section_text / "MIME")])] "]" - // - - class section : public component - { - public: - - section() - : m_section_text1(NULL), m_section_text2(NULL) - { - } - - ~section() - { - delete (m_section_text1); - delete (m_section_text2); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("section"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'['> >(line, &pos); - - if (!parser.check <one_char <']'> >(line, &pos, true)) - { - if (!(m_section_text1 = parser.get <section_text>(line, &pos, true))) - { - nz_number* num = parser.get <nz_number>(line, &pos); - m_nz_numbers.push_back(num->value()); - delete (num); - - while (parser.check <one_char <'.'> >(line, &pos, true)) - { - if ((num = parser.get <nz_number>(line, &pos, true))) - { - m_nz_numbers.push_back(num->value()); - delete (num); - } - else - { - m_section_text2 = parser.get <section_text>(line, &pos); - break; - } - } - } - - parser.check <one_char <']'> >(line, &pos); - } - - *currentPos = pos; - } - - private: - - section_text* m_section_text1; - section_text* m_section_text2; - std::vector <unsigned int> m_nz_numbers; - - public: - - const section_text* section_text1() const { return (m_section_text1); } - const section_text* section_text2() const { return (m_section_text2); } - const std::vector <unsigned int>& nz_numbers() const { return (m_nz_numbers); } - }; - - - // - // addr_adl ::= nstring - // ;; Holds route from [RFC-822] route-addr if - // ;; non-NIL - // - // addr_host ::= nstring - // ;; NIL indicates [RFC-822] group syntax. - // ;; Otherwise, holds [RFC-822] domain name - // - // addr_mailbox ::= nstring - // ;; NIL indicates end of [RFC-822] group; if - // ;; non-NIL and addr_host is NIL, holds - // ;; [RFC-822] group name. - // ;; Otherwise, holds [RFC-822] local-part - // - // addr_name ::= nstring - // ;; Holds phrase from [RFC-822] mailbox if - // ;; non-NIL - // - // address ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox - // SPACE addr_host ")" - // - - class address : public component - { - public: - - address() - : m_addr_name(NULL), m_addr_adl(NULL), - m_addr_mailbox(NULL), m_addr_host(NULL) - { - } - - ~address() - { - delete (m_addr_name); - delete (m_addr_adl); - delete (m_addr_mailbox); - delete (m_addr_host); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("address"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - m_addr_name = parser.get <nstring>(line, &pos); - parser.check <SPACE>(line, &pos); - m_addr_adl = parser.get <nstring>(line, &pos); - parser.check <SPACE>(line, &pos); - m_addr_mailbox = parser.get <nstring>(line, &pos); - parser.check <SPACE>(line, &pos); - m_addr_host = parser.get <nstring>(line, &pos); - parser.check <one_char <')'> >(line, &pos); - - *currentPos = pos; - } - - private: - - nstring* m_addr_name; - nstring* m_addr_adl; - nstring* m_addr_mailbox; - nstring* m_addr_host; - - public: - - nstring* addr_name() const { return (m_addr_name); } - nstring* addr_adl() const { return (m_addr_adl); } - nstring* addr_mailbox() const { return (m_addr_mailbox); } - nstring* addr_host() const { return (m_addr_host); } - }; - - - // - // address_list ::= "(" 1*address ")" / nil - // - - class address_list : public component - { - public: - - ~address_list() - { - for (std::vector <address*>::iterator it = m_addresses.begin() ; - it != m_addresses.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("address_list"); - - string::size_type pos = *currentPos; - - if (!parser.check <NIL>(line, &pos, true)) - { - parser.check <one_char <'('> >(line, &pos); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - { - m_addresses.push_back(parser.get <address>(line, &pos)); - parser.check <SPACE>(line, &pos, true); - } - } - - *currentPos = pos; - } - - private: - - std::vector <address*> m_addresses; - - public: - - const std::vector <address*>& addresses() const { return (m_addresses); } - }; - - - // - // env_bcc ::= "(" 1*address ")" / nil - // - - typedef address_list env_bcc; - - - // - // env_cc ::= "(" 1*address ")" / nil - // - - typedef address_list env_cc; - - - // - // env_date ::= nstring - // - - typedef nstring env_date; - - - // - // env_from ::= "(" 1*address ")" / nil - // - - typedef address_list env_from; - - - // - // env_in_reply_to ::= nstring - // - - typedef nstring env_in_reply_to; - - - // - // env_message_id ::= nstring - // - - typedef nstring env_message_id; - - - // - // env_reply_to ::= "(" 1*address ")" / nil - // - - typedef address_list env_reply_to; - - - // - // env_sender ::= "(" 1*address ")" / nil - // - - typedef address_list env_sender; - - - // - // env_subject ::= nstring - // - - typedef nstring env_subject; - - - // - // env_to ::= "(" 1*address ")" / nil - // - - typedef address_list env_to; - - - // - // envelope ::= "(" env_date SPACE env_subject SPACE env_from - // SPACE env_sender SPACE env_reply_to SPACE env_to - // SPACE env_cc SPACE env_bcc SPACE env_in_reply_to - // SPACE env_message_id ")" - // - - class envelope : public component - { - public: - - envelope() - : m_env_date(NULL), m_env_subject(NULL), - m_env_from(NULL), m_env_sender(NULL), m_env_reply_to(NULL), - m_env_to(NULL), m_env_cc(NULL), m_env_bcc(NULL), - m_env_in_reply_to(NULL), m_env_message_id(NULL) - { - } - - ~envelope() - { - delete (m_env_date); - delete (m_env_subject); - delete (m_env_from); - delete (m_env_sender); - delete (m_env_reply_to); - delete (m_env_to); - delete (m_env_cc); - delete (m_env_bcc); - delete (m_env_in_reply_to); - delete (m_env_message_id); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("envelope"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - - m_env_date = parser.get <IMAPParser::env_date>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_subject = parser.get <IMAPParser::env_subject>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_from = parser.get <IMAPParser::env_from>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_sender = parser.get <IMAPParser::env_sender>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_reply_to = parser.get <IMAPParser::env_reply_to>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_to = parser.get <IMAPParser::env_to>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_cc = parser.get <IMAPParser::env_cc>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_bcc = parser.get <IMAPParser::env_bcc>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_in_reply_to = parser.get <IMAPParser::env_in_reply_to>(line, &pos); - parser.check <SPACE>(line, &pos); - - m_env_message_id = parser.get <IMAPParser::env_message_id>(line, &pos); - - parser.check <one_char <')'> >(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::env_date* m_env_date; - IMAPParser::env_subject* m_env_subject; - IMAPParser::env_from* m_env_from; - IMAPParser::env_sender* m_env_sender; - IMAPParser::env_reply_to* m_env_reply_to; - IMAPParser::env_to* m_env_to; - IMAPParser::env_cc* m_env_cc; - IMAPParser::env_bcc* m_env_bcc; - IMAPParser::env_in_reply_to* m_env_in_reply_to; - IMAPParser::env_message_id* m_env_message_id; - - public: - - const IMAPParser::env_date* env_date() const { return (m_env_date); } - const IMAPParser::env_subject* env_subject() const { return (m_env_subject); } - const IMAPParser::env_from* env_from() const { return (m_env_from); } - const IMAPParser::env_sender* env_sender() const { return (m_env_sender); } - const IMAPParser::env_reply_to* env_reply_to() const { return (m_env_reply_to); } - const IMAPParser::env_to* env_to() const { return (m_env_to); } - const IMAPParser::env_cc* env_cc() const { return (m_env_cc); } - const IMAPParser::env_bcc* env_bcc() const { return (m_env_bcc); } - const IMAPParser::env_in_reply_to* env_in_reply_to() const { return (m_env_in_reply_to); } - const IMAPParser::env_message_id* env_message_id() const { return (m_env_message_id); } - }; - - - // - // body_fld_desc ::= nstring - // - - typedef nstring body_fld_desc; - - - // - // body_fld_id ::= nstring - // - - typedef nstring body_fld_id; - - - // - // body_fld_md5 ::= nstring - // - - typedef nstring body_fld_md5; - - - // - // body_fld_octets ::= number - // - - typedef number body_fld_octets; - - - // - // body_fld_lines ::= number - // - - typedef number body_fld_lines; - - - // - // body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ - // "QUOTED-PRINTABLE") <">) / string - // - - typedef xstring body_fld_enc; - - - // - // body_fld_param_item ::= string SPACE string - // - - class body_fld_param_item : public component - { - public: - - body_fld_param_item() - : m_string1(NULL), m_string2(NULL) - { - } - - ~body_fld_param_item() - { - delete (m_string1); - delete (m_string2); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_param_item"); - - string::size_type pos = *currentPos; - - m_string1 = parser.get <xstring>(line, &pos); - parser.check <SPACE>(line, &pos); - m_string2 = parser.get <xstring>(line, &pos); - - DEBUG_FOUND("body_fld_param_item", "<" << m_string1->value() << ", " << m_string2->value() << ">"); - - *currentPos = pos; - } - - private: - - xstring* m_string1; - xstring* m_string2; - - public: - - const xstring* string1() const { return (m_string1); } - const xstring* string2() const { return (m_string2); } - }; - - - // - // body_fld_param ::= "(" 1#(body_fld_param_item) ")" / nil - // - - class body_fld_param : public component - { - public: - - ~body_fld_param() - { - for (std::vector <body_fld_param_item*>::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_param"); - - string::size_type pos = *currentPos; - - if (!parser.check <NIL>(line, &pos, true)) - { - parser.check <one_char <'('> >(line, &pos); - - m_items.push_back(parser.get <body_fld_param_item>(line, &pos)); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - { - parser.check <SPACE>(line, &pos); - m_items.push_back(parser.get <body_fld_param_item>(line, &pos)); - } - } - - *currentPos = pos; - } - - private: - - std::vector <body_fld_param_item*> m_items; - - public: - - const std::vector <body_fld_param_item*>& items() const { return (m_items); } - }; - - - // - // body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil - // - - class body_fld_dsp : public component - { - public: - - body_fld_dsp() - : m_string(NULL), m_body_fld_param(NULL) - { - } - - ~body_fld_dsp() - { - delete (m_string); - delete (m_body_fld_param); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_dsp"); - - string::size_type pos = *currentPos; - - if (!parser.check <NIL>(line, &pos, true)) - { - parser.check <one_char <'('> >(line, &pos); - m_string = parser.get <xstring>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_param = parser.get <class body_fld_param>(line, &pos); - parser.check <one_char <')'> >(line, &pos); - } - - *currentPos = pos; - } - - private: - - class xstring* m_string; - class body_fld_param* m_body_fld_param; - - public: - - const class xstring* str() const { return (m_string); } - const class body_fld_param* body_fld_param() const { return (m_body_fld_param); } - }; - - - // - // body_fld_lang ::= nstring / "(" 1#string ")" - // - - class body_fld_lang : public component - { - public: - - ~body_fld_lang() - { - for (std::vector <xstring*>::iterator it = m_strings.begin() ; - it != m_strings.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_lang"); - - string::size_type pos = *currentPos; - - if (parser.check <one_char <'('> >(line, &pos, true)) - { - m_strings.push_back(parser.get <class xstring>(line, &pos)); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - m_strings.push_back(parser.get <class xstring>(line, &pos)); - } - else - { - m_strings.push_back(parser.get <class nstring>(line, &pos)); - } - - *currentPos = pos; - } - - private: - - std::vector <xstring*> m_strings; - - public: - - const std::vector <xstring*>& strings() const { return (m_strings); } - }; - - - // - // body_fields ::= body_fld_param SPACE body_fld_id SPACE - // body_fld_desc SPACE body_fld_enc SPACE - // body_fld_octets - // - - class body_fields : public component - { - public: - - body_fields() - : m_body_fld_param(NULL), m_body_fld_id(NULL), - m_body_fld_desc(NULL), m_body_fld_enc(NULL), m_body_fld_octets(NULL) - { - } - - ~body_fields() - { - delete (m_body_fld_param); - delete (m_body_fld_id); - delete (m_body_fld_desc); - delete (m_body_fld_enc); - delete (m_body_fld_octets); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fields"); - - string::size_type pos = *currentPos; - - m_body_fld_param = parser.get <IMAPParser::body_fld_param>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_id = parser.get <IMAPParser::body_fld_id>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_desc = parser.get <IMAPParser::body_fld_desc>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_enc = parser.get <IMAPParser::body_fld_enc>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_octets = parser.get <IMAPParser::body_fld_octets>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::body_fld_param* m_body_fld_param; - IMAPParser::body_fld_id* m_body_fld_id; - IMAPParser::body_fld_desc* m_body_fld_desc; - IMAPParser::body_fld_enc* m_body_fld_enc; - IMAPParser::body_fld_octets* m_body_fld_octets; - - public: - - const IMAPParser::body_fld_param* body_fld_param() const { return (m_body_fld_param); } - const IMAPParser::body_fld_id* body_fld_id() const { return (m_body_fld_id); } - const IMAPParser::body_fld_desc* body_fld_desc() const { return (m_body_fld_desc); } - const IMAPParser::body_fld_enc* body_fld_enc() const { return (m_body_fld_enc); } - const IMAPParser::body_fld_octets* body_fld_octets() const { return (m_body_fld_octets); } - }; - - - // - // media_subtype ::= string - // ;; Defined in [MIME-IMT] - // - - typedef xstring media_subtype; - - - // - // media_text ::= <"> "TEXT" <"> SPACE media_subtype - // ;; Defined in [MIME-IMT] - // - - class media_text : public component - { - public: - - media_text() - : m_media_subtype(NULL) - { - } - - ~media_text() - { - delete (m_media_subtype); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("media_text"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'"'> >(line, &pos); - parser.checkWithArg <special_atom>(line, &pos, "text"); - parser.check <one_char <'"'> >(line, &pos); - parser.check <SPACE>(line, &pos); - - m_media_subtype = parser.get <IMAPParser::media_subtype>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_subtype* m_media_subtype; - - public: - - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - }; - - - // - // media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <"> - // ;; Defined in [MIME-IMT] - // - - class media_message : public component - { - public: - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("media_message"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'"'> >(line, &pos); - parser.checkWithArg <special_atom>(line, &pos, "message"); - parser.check <one_char <'"'> >(line, &pos); - parser.check <SPACE>(line, &pos); - - //parser.check <one_char <'"'> >(line, &pos); - //parser.checkWithArg <special_atom>(line, &pos, "rfc822"); - //parser.check <one_char <'"'> >(line, &pos); - - m_media_subtype = parser.get <IMAPParser::media_subtype>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_subtype* m_media_subtype; - - public: - - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - }; - - - // - // media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" / - // "MESSAGE" / "VIDEO") <">) / string) - // SPACE media_subtype - // ;; Defined in [MIME-IMT] - - class media_basic : public component - { - public: - - media_basic() - : m_media_type(NULL), m_media_subtype(NULL) - { - } - - ~media_basic() - { - delete (m_media_type); - delete (m_media_subtype); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("media_basic"); - - string::size_type pos = *currentPos; - - m_media_type = parser.get <xstring>(line, &pos); - - parser.check <SPACE>(line, &pos); - - m_media_subtype = parser.get <IMAPParser::media_subtype>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::xstring* m_media_type; - IMAPParser::media_subtype* m_media_subtype; - - public: - - const IMAPParser::xstring* media_type() const { return (m_media_type); } - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - }; - - - // - // body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp - // [SPACE body_fld_lang - // [SPACE 1#body_extension]]] - // ;; MUST NOT be returned on non-extensible - // ;; "BODY" fetch - // - - class body_ext_1part : public component - { - public: - - body_ext_1part() - : m_body_fld_md5(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { - } - - ~body_ext_1part() - { - delete (m_body_fld_md5); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); - - for (std::vector <body_extension*>::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_ext_1part"); - - string::size_type pos = *currentPos; - - m_body_fld_md5 = parser.get <IMAPParser::body_fld_md5>(line, &pos); - - // [SPACE body_fld_dsp - if (parser.check <SPACE>(line, &pos, true)) - { - m_body_fld_dsp = parser.get <IMAPParser::body_fld_dsp>(line, &pos); - - // [SPACE body_fld_lang - if (parser.check <SPACE>(line, &pos, true)) - { - m_body_fld_lang = parser.get <IMAPParser::body_fld_lang>(line, &pos); - - // [SPACE 1#body_extension] - if (parser.check <SPACE>(line, &pos, true)) - { - m_body_extensions.push_back - (parser.get <body_extension>(line, &pos)); - - body_extension* ext = NULL; - - while ((ext = parser.get <body_extension>(line, &pos, true)) != NULL) - m_body_extensions.push_back(ext); - } - } - } - - *currentPos = pos; - } - - private: - - IMAPParser::body_fld_md5* m_body_fld_md5; - IMAPParser::body_fld_dsp* m_body_fld_dsp; - IMAPParser::body_fld_lang* m_body_fld_lang; - - std::vector <body_extension*> m_body_extensions; - - public: - - const IMAPParser::body_fld_md5* body_fld_md5() const { return (m_body_fld_md5); } - const IMAPParser::body_fld_dsp* body_fld_dsp() const { return (m_body_fld_dsp); } - const IMAPParser::body_fld_lang* body_fld_lang() const { return (m_body_fld_lang); } - - const std::vector <body_extension*> body_extensions() const { return (m_body_extensions); } - }; - - - // - // body_ext_mpart ::= body_fld_param - // [SPACE body_fld_dsp SPACE body_fld_lang - // [SPACE 1#body_extension]] - // ;; MUST NOT be returned on non-extensible - // ;; "BODY" fetch - - class body_ext_mpart : public component - { - public: - - body_ext_mpart() - : m_body_fld_param(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { - } - - ~body_ext_mpart() - { - delete (m_body_fld_param); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); - - for (std::vector <body_extension*>::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_ext_mpart"); - - string::size_type pos = *currentPos; - - m_body_fld_param = parser.get <IMAPParser::body_fld_param>(line, &pos); - - // [SPACE body_fld_dsp SPACE body_fld_lang [SPACE 1#body_extension]] - if (parser.check <SPACE>(line, &pos, true)) - { - m_body_fld_dsp = parser.get <IMAPParser::body_fld_dsp>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_lang = parser.get <IMAPParser::body_fld_lang>(line, &pos); - - // [SPACE 1#body_extension] - if (parser.check <SPACE>(line, &pos, true)) - { - m_body_extensions.push_back - (parser.get <body_extension>(line, &pos)); - - body_extension* ext = NULL; - - while ((ext = parser.get <body_extension>(line, &pos, true)) != NULL) - m_body_extensions.push_back(ext); - } - } - - *currentPos = pos; - } - - private: - - IMAPParser::body_fld_param* m_body_fld_param; - IMAPParser::body_fld_dsp* m_body_fld_dsp; - IMAPParser::body_fld_lang* m_body_fld_lang; - - std::vector <body_extension*> m_body_extensions; - - public: - - const IMAPParser::body_fld_param* body_fld_param() const { return (m_body_fld_param); } - const IMAPParser::body_fld_dsp* body_fld_dsp() const { return (m_body_fld_dsp); } - const IMAPParser::body_fld_lang* body_fld_lang() const { return (m_body_fld_lang); } - - const std::vector <body_extension*> body_extensions() const { return (m_body_extensions); } - }; - - - // - // body_type_basic ::= media_basic SPACE body_fields - // ;; MESSAGE subtype MUST NOT be "RFC822" - // - - class body_type_basic : public component - { - public: - - body_type_basic() - : m_media_basic(NULL), m_body_fields(NULL) - { - } - - ~body_type_basic() - { - delete (m_media_basic); - delete (m_body_fields); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_basic"); - - string::size_type pos = *currentPos; - - m_media_basic = parser.get <IMAPParser::media_basic>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fields = parser.get <IMAPParser::body_fields>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_basic* m_media_basic; - IMAPParser::body_fields* m_body_fields; - - public: - - const IMAPParser::media_basic* media_basic() const { return (m_media_basic); } - const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } - }; - - - // - // body_type_msg ::= media_message SPACE body_fields SPACE envelope - // SPACE body SPACE body_fld_lines - // - - class xbody; - typedef xbody body; - - class body_type_msg : public component - { - public: - - body_type_msg() - : m_media_message(NULL), m_body_fields(NULL), - m_envelope(NULL), m_body(NULL), m_body_fld_lines(NULL) - { - } - - ~body_type_msg() - { - delete (m_media_message); - delete (m_body_fields); - delete (m_envelope); - delete (m_body); - delete (m_body_fld_lines); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_msg"); - - string::size_type pos = *currentPos; - - m_media_message = parser.get <IMAPParser::media_message>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fields = parser.get <IMAPParser::body_fields>(line, &pos); - parser.check <SPACE>(line, &pos); - m_envelope = parser.get <IMAPParser::envelope>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body = parser.get <IMAPParser::xbody>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_lines = parser.get <IMAPParser::body_fld_lines>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_message* m_media_message; - IMAPParser::body_fields* m_body_fields; - IMAPParser::envelope* m_envelope; - IMAPParser::xbody* m_body; - IMAPParser::body_fld_lines* m_body_fld_lines; - - public: - - const IMAPParser::media_message* media_message() const { return (m_media_message); } - const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } - const IMAPParser::envelope* envelope() const { return (m_envelope); } - const IMAPParser::xbody* body() const { return (m_body); } - const IMAPParser::body_fld_lines* body_fld_lines() const { return (m_body_fld_lines); } - }; - - - // - // body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines - // - - class body_type_text : public component - { - public: - - body_type_text() - : m_media_text(NULL), - m_body_fields(NULL), m_body_fld_lines(NULL) - { - } - - ~body_type_text() - { - delete (m_media_text); - delete (m_body_fields); - delete (m_body_fld_lines); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_text"); - - string::size_type pos = *currentPos; - - m_media_text = parser.get <IMAPParser::media_text>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fields = parser.get <IMAPParser::body_fields>(line, &pos); - parser.check <SPACE>(line, &pos); - m_body_fld_lines = parser.get <IMAPParser::body_fld_lines>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_text* m_media_text; - IMAPParser::body_fields* m_body_fields; - IMAPParser::body_fld_lines* m_body_fld_lines; - - public: - - const IMAPParser::media_text* media_text() const { return (m_media_text); } - const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } - const IMAPParser::body_fld_lines* body_fld_lines() const { return (m_body_fld_lines); } - }; - - - // - // body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) - // [SPACE body_ext_1part] - // - - class body_type_1part : public component - { - public: - - body_type_1part() - : m_body_type_basic(NULL), m_body_type_msg(NULL), - m_body_type_text(NULL), m_body_ext_1part(NULL) - { - } - - ~body_type_1part() - { - delete (m_body_type_basic); - delete (m_body_type_msg); - delete (m_body_type_text); - - delete (m_body_ext_1part); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_1part"); - - string::size_type pos = *currentPos; - - if (!(m_body_type_text = parser.get <IMAPParser::body_type_text>(line, &pos, true))) - if (!(m_body_type_msg = parser.get <IMAPParser::body_type_msg>(line, &pos, true))) - m_body_type_basic = parser.get <IMAPParser::body_type_basic>(line, &pos); - - if (parser.check <SPACE>(line, &pos, true)) - m_body_ext_1part = parser.get <IMAPParser::body_ext_1part>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::body_type_basic* m_body_type_basic; - IMAPParser::body_type_msg* m_body_type_msg; - IMAPParser::body_type_text* m_body_type_text; - - IMAPParser::body_ext_1part* m_body_ext_1part; - - public: - - const IMAPParser::body_type_basic* body_type_basic() const { return (m_body_type_basic); } - const IMAPParser::body_type_msg* body_type_msg() const { return (m_body_type_msg); } - const IMAPParser::body_type_text* body_type_text() const { return (m_body_type_text); } - - const IMAPParser::body_ext_1part* body_ext_1part() const { return (m_body_ext_1part); } - }; - - - // - // body_type_mpart ::= 1*body SPACE media_subtype - // [SPACE body_ext_mpart] - // - - class body_type_mpart : public component - { - public: - - body_type_mpart() - : m_media_subtype(NULL), m_body_ext_mpart(NULL) - { - } - - ~body_type_mpart() - { - delete (m_media_subtype); - delete (m_body_ext_mpart); - - for (std::vector <xbody*>::iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_mpart"); - - string::size_type pos = *currentPos; - - m_list.push_back(parser.get <xbody>(line, &pos)); - - for (xbody* b ; (b = parser.get <xbody>(line, &pos, true)) ; ) - m_list.push_back(b); - - parser.check <SPACE>(line, &pos); - - m_media_subtype = parser.get <IMAPParser::media_subtype>(line, &pos); - - if (parser.check <SPACE>(line, &pos, true)) - m_body_ext_mpart = parser.get <IMAPParser::body_ext_mpart>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_subtype* m_media_subtype; - IMAPParser::body_ext_mpart* m_body_ext_mpart; - - std::vector <xbody*> m_list; - - public: - - const std::vector <IMAPParser::xbody*>& list() const { return (m_list); } - - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - const IMAPParser::body_ext_mpart* body_ext_mpart() const { return (m_body_ext_mpart); } - }; - - - // - // xbody ::= "(" body_type_1part / body_type_mpart ")" - // - - class xbody : public component - { - public: - - xbody() - : m_body_type_1part(NULL), m_body_type_mpart(NULL) - { - } - - ~xbody() - { - delete (m_body_type_1part); - delete (m_body_type_mpart); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("body"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - - if (!(m_body_type_1part = parser.get <IMAPParser::body_type_1part>(line, &pos, true))) - m_body_type_mpart = parser.get <IMAPParser::body_type_mpart>(line, &pos); - - parser.check <one_char <')'> >(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::body_type_1part* m_body_type_1part; - IMAPParser::body_type_mpart* m_body_type_mpart; - - public: - - const IMAPParser::body_type_1part* body_type_1part() const { return (m_body_type_1part); } - const IMAPParser::body_type_mpart* body_type_mpart() const { return (m_body_type_mpart); } - }; - - - // - // uniqueid ::= nz_number - // ;; Strictly ascending - // - // msg_att_item ::= "ENVELOPE" SPACE envelope / - // "FLAGS" SPACE "(" #(flag / "\Recent") ")" / - // "INTERNALDATE" SPACE date_time / - // "RFC822" [".HEADER" / ".TEXT"] SPACE nstring / - // "RFC822.SIZE" SPACE number / - // "BODY" ["STRUCTURE"] SPACE body / - // "BODY" section ["<" number ">"] SPACE nstring / - // "UID" SPACE uniqueid - // - - class msg_att_item : public component - { - public: - - msg_att_item() - : m_date_time(NULL), m_number(NULL), m_envelope(NULL), - m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL) - { - } - - ~msg_att_item() - { - delete (m_date_time); - delete (m_number); - delete (m_envelope); - delete (m_uniqueid); - delete (m_nstring); - delete (m_body); - delete (m_flag_list); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("msg_att_item"); - - string::size_type pos = *currentPos; - - // "ENVELOPE" SPACE envelope - if (parser.checkWithArg <special_atom>(line, &pos, "envelope", true)) - { - m_type = ENVELOPE; - - parser.check <SPACE>(line, &pos); - m_envelope = parser.get <IMAPParser::envelope>(line, &pos); - } - // "FLAGS" SPACE "(" #(flag / "\Recent") ")" - else if (parser.checkWithArg <special_atom>(line, &pos, "flags", true)) - { - m_type = FLAGS; - - parser.check <SPACE>(line, &pos); - - m_flag_list = parser.get <IMAPParser::flag_list>(line, &pos); - } - // "INTERNALDATE" SPACE date_time - else if (parser.checkWithArg <special_atom>(line, &pos, "internaldate", true)) - { - m_type = INTERNALDATE; - - parser.check <SPACE>(line, &pos); - m_date_time = parser.get <IMAPParser::date_time>(line, &pos); - } - // "RFC822" ".HEADER" SPACE nstring - else if (parser.checkWithArg <special_atom>(line, &pos, "rfc822.header", true)) - { - m_type = RFC822_HEADER; - - parser.check <SPACE>(line, &pos); - - m_nstring = parser.get <IMAPParser::nstring>(line, &pos); - } - // "RFC822" ".TEXT" SPACE nstring - else if (parser.checkWithArg <special_atom>(line, &pos, "rfc822.text", true)) - { - m_type = RFC822_TEXT; - - parser.check <SPACE>(line, &pos); - - m_nstring = parser.getWithArgs <IMAPParser::nstring> - (line, &pos, this, RFC822_TEXT); - } - // "RFC822.SIZE" SPACE number - else if (parser.checkWithArg <special_atom>(line, &pos, "rfc822.size", true)) - { - m_type = RFC822_SIZE; - - parser.check <SPACE>(line, &pos); - m_number = parser.get <IMAPParser::number>(line, &pos); - } - // "RFC822" SPACE nstring - else if (parser.checkWithArg <special_atom>(line, &pos, "rfc822", true)) - { - m_type = RFC822; - - parser.check <SPACE>(line, &pos); - - m_nstring = parser.get <IMAPParser::nstring>(line, &pos); - } - // "BODY" "STRUCTURE" SPACE body - else if (parser.checkWithArg <special_atom>(line, &pos, "bodystructure", true)) - { - m_type = BODY_STRUCTURE; - - parser.check <SPACE>(line, &pos); - - m_body = parser.get <IMAPParser::body>(line, &pos); - } - // "BODY" section ["<" number ">"] SPACE nstring - // "BODY" SPACE body - else if (parser.checkWithArg <special_atom>(line, &pos, "body", true)) - { - m_section = parser.get <IMAPParser::section>(line, &pos, true); - - // "BODY" section ["<" number ">"] SPACE nstring - if (m_section != NULL) - { - m_type = BODY_SECTION; - - if (parser.check <one_char <'<'> >(line, &pos, true)) - { - m_number = parser.get <IMAPParser::number>(line, &pos); - parser.check <one_char <'>'> >(line, &pos); - } - - parser.check <SPACE>(line, &pos); - - m_nstring = parser.getWithArgs <IMAPParser::nstring> - (line, &pos, this, BODY_SECTION); - } - // "BODY" SPACE body - else - { - m_type = BODY; - - parser.check <SPACE>(line, &pos); - - m_body = parser.get <IMAPParser::body>(line, &pos); - } - } - // "UID" SPACE uniqueid - else - { - m_type = UID; - - parser.checkWithArg <special_atom>(line, &pos, "uid"); - parser.check <SPACE>(line, &pos); - - m_uniqueid = parser.get <nz_number>(line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - ENVELOPE, - FLAGS, - INTERNALDATE, - RFC822, - RFC822_SIZE, - RFC822_HEADER, - RFC822_TEXT, - BODY, - BODY_SECTION, - BODY_STRUCTURE, - UID - }; - - private: - - Type m_type; - - IMAPParser::date_time* m_date_time; - IMAPParser::number* m_number; - IMAPParser::envelope* m_envelope; - IMAPParser::nz_number* m_uniqueid; - IMAPParser::nstring* m_nstring; - IMAPParser::xbody* m_body; - IMAPParser::flag_list* m_flag_list; - IMAPParser::section* m_section; - - public: - - const Type type() const { return (m_type); } - - const IMAPParser::date_time* date_time() const { return (m_date_time); } - const IMAPParser::number* number() const { return (m_number); } - const IMAPParser::envelope* envelope() const { return (m_envelope); } - const IMAPParser::nz_number* unique_id() const { return (m_uniqueid); } - const IMAPParser::nstring* nstring() const { return (m_nstring); } - const IMAPParser::xbody* body() const { return (m_body); } - const IMAPParser::flag_list* flag_list() const { return (m_flag_list); } - const IMAPParser::section* section() const { return (m_section); } - }; - - - // - // msg_att ::= "(" 1#(msg_att_item) ")" - // - - class msg_att : public component - { - public: - - ~msg_att() - { - for (std::vector <msg_att_item*>::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("msg_att"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'('> >(line, &pos); - - m_items.push_back(parser.get <msg_att_item>(line, &pos)); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - { - parser.check <SPACE>(line, &pos); - m_items.push_back(parser.get <msg_att_item>(line, &pos)); - } - - *currentPos = pos; - } - - private: - - std::vector <msg_att_item*> m_items; - - public: - - const std::vector <msg_att_item*>& items() const { return (m_items); } - }; - - - // - // message_data ::= nz_number SPACE ("EXPUNGE" / - // ("FETCH" SPACE msg_att)) - // - - class message_data : public component - { - public: - - message_data() - : m_number(0), m_msg_att(NULL) - { - } - - ~message_data() - { - delete (m_msg_att); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("message_data"); - - string::size_type pos = *currentPos; - - nz_number* num = parser.get <nz_number>(line, &pos); - m_number = num->value(); - delete (num); - - parser.check <SPACE>(line, &pos); - - if (parser.checkWithArg <special_atom>(line, &pos, "expunge", true)) - { - m_type = EXPUNGE; - } - else - { - parser.checkWithArg <special_atom>(line, &pos, "fetch"); - - parser.check <SPACE>(line, &pos); - - m_type = FETCH; - m_msg_att = parser.get <IMAPParser::msg_att>(line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - EXPUNGE, - FETCH - }; - - private: - - Type m_type; - unsigned int m_number; - IMAPParser::msg_att* m_msg_att; - - public: - - const Type type() const { return (m_type); } - const unsigned int number() const { return (m_number); } - const IMAPParser::msg_att* msg_att() const { return (m_msg_att); } - }; - - - // - // resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text - // ;; Status condition - // - - class resp_cond_state : public component - { - public: - - resp_cond_state() - : m_resp_text(NULL), m_status(BAD) - { - } - - ~resp_cond_state() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_cond_state"); - - string::size_type pos = *currentPos; - - if (parser.checkWithArg <special_atom>(line, &pos, "ok", true)) - { - m_status = OK; - } - else if (parser.checkWithArg <special_atom>(line, &pos, "no", true)) - { - m_status = NO; - } - else - { - parser.checkWithArg <special_atom>(line, &pos, "bad"); - m_status = BAD; - } - - parser.check <SPACE>(line, &pos); - - m_resp_text = parser.get <IMAPParser::resp_text>(line, &pos); - - *currentPos = pos; - } - - - enum Status - { - OK, - NO, - BAD - }; - - private: - - IMAPParser::resp_text* m_resp_text; - Status m_status; - - public: - - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - const Status status() const { return (m_status); } - }; - - - // - // resp_cond_bye ::= "BYE" SPACE resp_text - // - - class resp_cond_bye : public component - { - public: - - resp_cond_bye() - : m_resp_text(NULL) - { - } - - ~resp_cond_bye() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_cond_bye"); - - string::size_type pos = *currentPos; - - parser.checkWithArg <special_atom>(line, &pos, "bye"); - - parser.check <SPACE>(line, &pos); - - m_resp_text = parser.get <IMAPParser::resp_text>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_text* m_resp_text; - - public: - - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - }; - - - // - // resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text - // ;; Authentication condition - // - - class resp_cond_auth : public component - { - public: - - resp_cond_auth() - : m_resp_text(NULL) - { - } - - ~resp_cond_auth() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_cond_auth"); - - string::size_type pos = *currentPos; - - if (parser.checkWithArg <special_atom>(line, &pos, "ok", true)) - { - m_cond = OK; - } - else - { - parser.checkWithArg <special_atom>(line, &pos, "preauth"); - - m_cond = PREAUTH; - } - - parser.check <SPACE>(line, &pos); - - m_resp_text = parser.get <IMAPParser::resp_text>(line, &pos); - - *currentPos = pos; - } - - - enum Condition - { - OK, - PREAUTH - }; - - private: - - Condition m_cond; - IMAPParser::resp_text* m_resp_text; - - public: - - const Condition condition() const { return (m_cond); } - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - }; - - - // - // status_info ::= status_att SPACE number - // - - class status_info : public component - { - public: - - status_info() - : m_status_att(NULL), m_number(NULL) - { - } - - ~status_info() - { - delete (m_status_att); - delete (m_number); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("status_info"); - - string::size_type pos = *currentPos; - - m_status_att = parser.get <IMAPParser::status_att>(line, &pos); - parser.check <SPACE>(line, &pos); - m_number = parser.get <IMAPParser::number>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::status_att* m_status_att; - IMAPParser::number* m_number; - - public: - - const IMAPParser::status_att* status_att() const { return (m_status_att); } - const IMAPParser::number* number() const { return (m_number); } - }; - - - // - // mailbox_data ::= "FLAGS" SPACE mailbox_flag_list / - // "LIST" SPACE mailbox_list / - // "LSUB" SPACE mailbox_list / - // "MAILBOX" SPACE text / - // "SEARCH" [SPACE 1#nz_number] / - // "STATUS" SPACE mailbox SPACE - // "(" #<status_att number ")" / - // number SPACE "EXISTS" / - // number SPACE "RECENT" - // - - class mailbox_data : public component - { - public: - - mailbox_data() - : m_number(NULL), m_mailbox_flag_list(NULL), m_mailbox_list(NULL), - m_mailbox(NULL), m_text(NULL) - { - } - - ~mailbox_data() - { - delete (m_number); - delete (m_mailbox_flag_list); - delete (m_mailbox_list); - delete (m_mailbox); - delete (m_text); - - for (std::vector <nz_number*>::iterator it = m_search_nz_number_list.begin() ; - it != m_search_nz_number_list.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_data"); - - string::size_type pos = *currentPos; - - m_number = parser.get <IMAPParser::number>(line, &pos, true); - - if (m_number) - { - parser.check <SPACE>(line, &pos); - - if (parser.checkWithArg <special_atom>(line, &pos, "exists", true)) - { - m_type = EXISTS; - } - else - { - parser.checkWithArg <special_atom>(line, &pos, "recent"); - - m_type = RECENT; - } - } - else - { - // "FLAGS" SPACE mailbox_flag_list - if (parser.checkWithArg <special_atom>(line, &pos, "flags", true)) - { - parser.check <SPACE>(line, &pos); - - m_mailbox_flag_list = parser.get <IMAPParser::mailbox_flag_list>(line, &pos); - - m_type = FLAGS; - } - // "LIST" SPACE mailbox_list - else if (parser.checkWithArg <special_atom>(line, &pos, "list", true)) - { - parser.check <SPACE>(line, &pos); - - m_mailbox_list = parser.get <IMAPParser::mailbox_list>(line, &pos); - - m_type = LIST; - } - // "LSUB" SPACE mailbox_list - else if (parser.checkWithArg <special_atom>(line, &pos, "lsub", true)) - { - parser.check <SPACE>(line, &pos); - - m_mailbox_list = parser.get <IMAPParser::mailbox_list>(line, &pos); - - m_type = LSUB; - } - // "MAILBOX" SPACE text - else if (parser.checkWithArg <special_atom>(line, &pos, "mailbox", true)) - { - parser.check <SPACE>(line, &pos); - - m_text = parser.get <IMAPParser::text>(line, &pos); - - m_type = MAILBOX; - } - // "SEARCH" [SPACE 1#nz_number] - else if (parser.checkWithArg <special_atom>(line, &pos, "search", true)) - { - if (parser.check <SPACE>(line, &pos, true)) - { - m_search_nz_number_list.push_back - (parser.get <nz_number>(line, &pos)); - - while (parser.check <SPACE>(line, &pos, true)) - { - m_search_nz_number_list.push_back - (parser.get <nz_number>(line, &pos)); - } - } - - m_type = SEARCH; - } - // "STATUS" SPACE mailbox SPACE - // "(" #<status_att number)] ")" - // - // "(" [status_att SPACE number *(SPACE status_att SPACE number)] ")" - else - { - parser.checkWithArg <special_atom>(line, &pos, "status"); - parser.check <SPACE>(line, &pos); - - m_mailbox = parser.get <IMAPParser::mailbox>(line, &pos); - - parser.check <SPACE>(line, &pos); - parser.check <one_char <'('> >(line, &pos); - - m_status_info_list.push_back(parser.get <status_info>(line, &pos)); - - while (!parser.check <one_char <')'> >(line, &pos, true)) - m_status_info_list.push_back(parser.get <status_info>(line, &pos)); - - m_type = STATUS; - } - } - - *currentPos = pos; - } - - - enum Type - { - FLAGS, - LIST, - LSUB, - MAILBOX, - SEARCH, - STATUS, - EXISTS, - RECENT - }; - - private: - - Type m_type; - - IMAPParser::number* m_number; - IMAPParser::mailbox_flag_list* m_mailbox_flag_list; - IMAPParser::mailbox_list* m_mailbox_list; - IMAPParser::mailbox* m_mailbox; - IMAPParser::text* m_text; - std::vector <nz_number*> m_search_nz_number_list; - std::vector <status_info*> m_status_info_list; - - public: - - const Type type() const { return (m_type); } - - const IMAPParser::number* number() const { return (m_number); } - const IMAPParser::mailbox_flag_list* mailbox_flag_list() const { return (m_mailbox_flag_list); } - const IMAPParser::mailbox_list* mailbox_list() const { return (m_mailbox_list); } - const IMAPParser::mailbox* mailbox() const { return (m_mailbox); } - const IMAPParser::text* text() const { return (m_text); } - const std::vector <nz_number*>& search_nz_number_list() const { return (m_search_nz_number_list); } - const std::vector <status_info*>& status_info_list() const { return (m_status_info_list); } - }; - - - // - // response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye / - // mailbox_data / message_data / capability_data) CRLF - // - - class response_data : public component - { - public: - - response_data() - : m_resp_cond_state(NULL), m_resp_cond_bye(NULL), - m_mailbox_data(NULL), m_message_data(NULL), m_capability_data(NULL) - { - } - - ~response_data() - { - delete (m_resp_cond_state); - delete (m_resp_cond_bye); - delete (m_mailbox_data); - delete (m_message_data); - delete (m_capability_data); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("response_data"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'*'> >(line, &pos); - parser.check <SPACE>(line, &pos); - - if (!(m_resp_cond_state = parser.get <IMAPParser::resp_cond_state>(line, &pos, true))) - if (!(m_resp_cond_bye = parser.get <IMAPParser::resp_cond_bye>(line, &pos, true))) - if (!(m_mailbox_data = parser.get <IMAPParser::mailbox_data>(line, &pos, true))) - if (!(m_message_data = parser.get <IMAPParser::message_data>(line, &pos, true))) - m_capability_data = parser.get <IMAPParser::capability_data>(line, &pos); - - parser.check <CRLF>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_state* m_resp_cond_state; - IMAPParser::resp_cond_bye* m_resp_cond_bye; - IMAPParser::mailbox_data* m_mailbox_data; - IMAPParser::message_data* m_message_data; - IMAPParser::capability_data* m_capability_data; - - public: - - const IMAPParser::resp_cond_state* resp_cond_state() const { return (m_resp_cond_state); } - const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } - const IMAPParser::mailbox_data* mailbox_data() const { return (m_mailbox_data); } - const IMAPParser::message_data* message_data() const { return (m_message_data); } - const IMAPParser::capability_data* capability_data() const { return (m_capability_data); } - }; - - - class continue_req_or_response_data : public component - { - public: - - continue_req_or_response_data() - : m_continue_req(NULL), m_response_data(NULL) - { - } - - ~continue_req_or_response_data() - { - delete (m_continue_req); - delete (m_response_data); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("continue_req_or_response_data"); - - string::size_type pos = *currentPos; - - if (!(m_continue_req = parser.get <IMAPParser::continue_req>(line, &pos, true))) - m_response_data = parser.get <IMAPParser::response_data>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::continue_req* m_continue_req; - IMAPParser::response_data* m_response_data; - - public: - - const IMAPParser::continue_req* continue_req() const { return (m_continue_req); } - const IMAPParser::response_data* response_data() const { return (m_response_data); } - }; - - - // - // response_fatal ::= "*" SPACE resp_cond_bye CRLF - // ;; Server closes connection immediately - // - - class response_fatal : public component - { - public: - - response_fatal() - : m_resp_cond_bye(NULL) - { - } - - ~response_fatal() - { - delete (m_resp_cond_bye); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("response_fatal"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'*'> >(line, &pos); - parser.check <SPACE>(line, &pos); - - m_resp_cond_bye = parser.get <IMAPParser::resp_cond_bye>(line, &pos); - - parser.check <CRLF>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_bye* m_resp_cond_bye; - - public: - - const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } - }; - - - // - // response_tagged ::= tag SPACE resp_cond_state CRLF - // - - class response_tagged : public component - { - public: - - response_tagged() - : m_resp_cond_state(NULL) - { - } - - ~response_tagged() - { - delete (m_resp_cond_state); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("response_tagged"); - - string::size_type pos = *currentPos; - - parser.check <IMAPParser::xtag>(line, &pos); - parser.check <SPACE>(line, &pos); - m_resp_cond_state = parser.get <IMAPParser::resp_cond_state>(line, &pos); - parser.check <CRLF>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_state* m_resp_cond_state; - - public: - - const IMAPParser::resp_cond_state* resp_cond_state() const { return (m_resp_cond_state); } - }; - - - // - // response_done ::= response_tagged / response_fatal - // - - class response_done : public component - { - public: - - response_done() - : m_response_tagged(NULL), m_response_fatal(NULL) - { - } - - ~response_done() - { - delete (m_response_tagged); - delete (m_response_fatal); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("response_done"); - - string::size_type pos = *currentPos; - - if (!(m_response_tagged = parser.get <IMAPParser::response_tagged>(line, &pos, true))) - m_response_fatal = parser.get <IMAPParser::response_fatal>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::response_tagged* m_response_tagged; - IMAPParser::response_fatal* m_response_fatal; - - public: - - const IMAPParser::response_tagged* response_tagged() const { return (m_response_tagged); } - const IMAPParser::response_fatal* response_fatal() const { return (m_response_fatal); } - }; - - - // - // response ::= *(continue_req / response_data) response_done - // - - class response : public component - { - public: - - response() - : m_response_done(NULL) - { - } - - ~response() - { - for (std::vector <IMAPParser::continue_req_or_response_data*>::iterator - it = m_continue_req_or_response_data.begin() ; - it != m_continue_req_or_response_data.end() ; ++it) - { - delete (*it); - } - - delete (m_response_done); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("response"); - - string::size_type pos = *currentPos; - string curLine = line; - bool partial = false; // partial response - - IMAPParser::continue_req_or_response_data* resp = NULL; - - while ((resp = parser.get <IMAPParser::continue_req_or_response_data>(curLine, &pos, true)) != NULL) - { - m_continue_req_or_response_data.push_back(resp); - - // Partial response (continue_req) - if (resp->continue_req()) - { - partial = true; - break; - } - - // We have read a CRLF, read another line - curLine = parser.readLine(); - pos = 0; - } - - if (!partial) - m_response_done = parser.get <IMAPParser::response_done>(curLine, &pos); - - *currentPos = pos; - } - - - const bool isBad() const - { - if (!response_done()) // incomplete (partial) response - return (true); - - if (response_done()->response_fatal()) - return (true); - - if (response_done()->response_tagged()->resp_cond_state()-> - status() == IMAPParser::resp_cond_state::BAD) - { - return (true); - } - - return (false); - } - - private: - - std::vector <IMAPParser::continue_req_or_response_data*> m_continue_req_or_response_data; - IMAPParser::response_done* m_response_done; - - public: - - const std::vector <IMAPParser::continue_req_or_response_data*>& continue_req_or_response_data() const { return (m_continue_req_or_response_data); } - const IMAPParser::response_done* response_done() const { return (m_response_done); } - }; - - - // - // greeting ::= "*" SPACE (resp_cond_auth / resp_cond_bye) CRLF - // - - class greeting : public component - { - public: - - greeting() - : m_resp_cond_auth(NULL), m_resp_cond_bye(NULL) - { - } - - ~greeting() - { - delete (m_resp_cond_auth); - delete (m_resp_cond_bye); - } - - void go(IMAPParser& parser, string& line, string::size_type* currentPos) - { - DEBUG_ENTER_COMPONENT("greeting"); - - string::size_type pos = *currentPos; - - parser.check <one_char <'*'> >(line, &pos); - parser.check <SPACE>(line, &pos); - - if (!(m_resp_cond_auth = parser.get <IMAPParser::resp_cond_auth>(line, &pos, true))) - m_resp_cond_bye = parser.get <IMAPParser::resp_cond_bye>(line, &pos); - - parser.check <CRLF>(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_auth* m_resp_cond_auth; - IMAPParser::resp_cond_bye* m_resp_cond_bye; - - public: - - const IMAPParser::resp_cond_auth* resp_cond_auth() const { return (m_resp_cond_auth); } - const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } - }; - - - - // - // The main functions used to parse a response - // - - response* readResponse(literalHandler* lh = NULL) - { - string::size_type pos = 0; - string line = readLine(); - - m_literalHandler = lh; - response* resp = get <response>(line, &pos); - m_literalHandler = NULL; - - return (resp); - } - - - greeting* readGreeting() - { - string::size_type pos = 0; - string line = readLine(); - - return get <greeting>(line, &pos); - } - - - // - // Get a token and advance - // - - template <class TYPE> - TYPE* get(string& line, string::size_type* currentPos, - const bool noThrow = false) - { - component* resp = new TYPE; - return internalGet <TYPE>(resp, line, currentPos, noThrow); - } - - - template <class TYPE, class ARG1_TYPE, class ARG2_TYPE> - TYPE* getWithArgs(string& line, string::size_type* currentPos, - ARG1_TYPE arg1, ARG2_TYPE arg2, const bool noThrow = false) - { - component* resp = new TYPE(arg1, arg2); - return internalGet <TYPE>(resp, line, currentPos, noThrow); - } - - -private: - - template <class TYPE> - TYPE* internalGet(component* resp, string& line, string::size_type* currentPos, - const bool noThrow = false) - { -#if DEBUG_RESPONSE - DEBUG_RESPONSE_level += " "; -#endif - - try - { - resp->go(*this, line, currentPos); - -#if DEBUG_RESPONSE - std::cout << DEBUG_RESPONSE_level << "SUCCESS! (" << DEBUG_RESPONSE_components.back() << ")" << std::endl; - - DEBUG_RESPONSE_level.erase(DEBUG_RESPONSE_level.begin() + DEBUG_RESPONSE_level.length() - 1); - DEBUG_RESPONSE_components.pop_back(); -#endif - } - catch (...) - { -#if DEBUG_RESPONSE - std::cout << DEBUG_RESPONSE_level << "FAILED! (" << DEBUG_RESPONSE_components.back() << ")" << std::endl; - - DEBUG_RESPONSE_level.erase(DEBUG_RESPONSE_level.begin() + DEBUG_RESPONSE_level.length() - 1); - DEBUG_RESPONSE_components.pop_back(); -#endif - - delete (resp); - if (!noThrow) throw; - return (NULL); - } - - return static_cast <TYPE*>(resp); - } - - -public: - - // - // Check a token and advance - // - - template <class TYPE> - const bool check(string& line, string::size_type* currentPos, - const bool noThrow = false) - { - try - { - TYPE term; - term.go(*this, line, currentPos); - -#if DEBUG_RESPONSE - std::cout << DEBUG_RESPONSE_level << "SUCCESS! (" << DEBUG_RESPONSE_components.back() << ")" << std::endl; - DEBUG_RESPONSE_components.pop_back(); -#endif - } - catch (...) - { -#if DEBUG_RESPONSE - std::cout << DEBUG_RESPONSE_level << "FAILED! (" << DEBUG_RESPONSE_components.back() << ")" << std::endl; - DEBUG_RESPONSE_components.pop_back(); -#endif - - if (!noThrow) throw; - return false; - } - - return true; - } - - template <class TYPE, class ARG_TYPE> - const bool checkWithArg(string& line, string::size_type* currentPos, - const ARG_TYPE arg, const bool noThrow = false) - { - try - { - TYPE term(arg); - term.go(*this, line, currentPos); - -#if DEBUG_RESPONSE - std::cout << DEBUG_RESPONSE_level << "SUCCESS! (" << DEBUG_RESPONSE_components.back() << ")" << std::endl; - DEBUG_RESPONSE_components.pop_back(); -#endif - } - catch (...) - { -#if DEBUG_RESPONSE - std::cout << DEBUG_RESPONSE_level << "FAILED! (" << DEBUG_RESPONSE_components.back() << ")" << std::endl; - DEBUG_RESPONSE_components.pop_back(); -#endif - - if (!noThrow) throw; - return false; - } - - return true; - } - - -private: - - IMAPTag* m_tag; - socket* m_socket; - - progressionListener* m_progress; - - literalHandler* m_literalHandler; - - timeoutHandler* m_timeoutHandler; - - - string m_buffer; - int m_pos; - - string m_lastLine; - -public: - - // - // Read one line - // - - const string readLine() - { - string::size_type pos; - - while ((pos = m_buffer.find('\n')) == string::npos) - { - read(); - } - - string line; - line.resize(pos + 1); - std::copy(m_buffer.begin(), m_buffer.begin() + pos + 1, line.begin()); - - m_buffer.erase(m_buffer.begin(), m_buffer.begin() + pos + 1); - - m_lastLine = line; - -#if DEBUG_RESPONSE - std::cout << std::endl << "Read line:" << std::endl << line << std::endl; -#endif - - return (line); - } - - - // - // Read available data from socket stream - // - - void read() - { - string receiveBuffer; - - while (receiveBuffer.empty()) - { - // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - } - - // We have received data: reset the time-out counter - m_socket->receive(receiveBuffer); - - if (receiveBuffer.empty()) // buffer is empty - { - platformDependant::getHandler()->wait(); - continue; - } - - // We have received data ... - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - } - - m_buffer += receiveBuffer; - } - - - void readLiteral(literalHandler::target& buffer, string::size_type count) - { - string::size_type len = 0; - string receiveBuffer; - - if (m_progress) - m_progress->start(count); - - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - if (!m_buffer.empty()) - { - if (m_buffer.length() > count) - { - buffer.putData(string(m_buffer.begin(), m_buffer.begin() + count)); - m_buffer.erase(m_buffer.begin(), m_buffer.begin() + count); - len = count; - } - else - { - len += m_buffer.length(); - buffer.putData(m_buffer); - m_buffer.clear(); - } - } - - while (len < count) - { - // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - } - - // Receive data from the socket - m_socket->receive(receiveBuffer); - - if (receiveBuffer.empty()) // buffer is empty - { - platformDependant::getHandler()->wait(); - continue; - } - - // We have received data: reset the time-out counter - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - if (len + receiveBuffer.length() > count) - { - const string::size_type remaining = count - len; - - // Get the needed amount of data - buffer.putData(string(receiveBuffer.begin(), receiveBuffer.begin() + remaining)); - - // Put the remaining data into the internal response buffer - receiveBuffer.erase(receiveBuffer.begin(), receiveBuffer.begin() + remaining); - m_buffer += receiveBuffer; - - len = count; - } - else - { - buffer.putData(receiveBuffer); - len += receiveBuffer.length(); - } - - // Notify progression - if (m_progress) - m_progress->progress(len, count); - } - - if (m_progress) - m_progress->stop(count); - } -}; - - -} // messaging -} // vmime - - -#endif // VMIME_MESSAGING_IMAPPARSER_HPP_INCLUDED |
