📄 imapparser.hpp
字号:
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 = static_cast <unsigned char>(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: 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(); utility::progressListener* progress = target->progressListener(); 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->progressListener(); 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 utility::encoder::encoder* theEncoder = NULL; if (theEncoding->value()[0] == 'q' || theEncoding->value()[0] == 'Q') { // Quoted-printable theEncoder = new utility::encoder::qpEncoder(); theEncoder->getProperties()["rfc2047"] = true; } else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') { // Base64
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -