aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2005-12-18 21:20:43 +0000
committerVincent Richard <[email protected]>2005-12-18 21:20:43 +0000
commit54e4235b8dff6134f9ac1a415957fbcb43fc835d (patch)
tree61e9fbacdb7ae9d1bceb01b2805a2a75d2c1bb5d
parentEnhanced detection of GnuTLS (SCons). (diff)
downloadvmime-54e4235b8dff6134f9ac1a415957fbcb43fc835d.tar.gz
vmime-54e4235b8dff6134f9ac1a415957fbcb43fc835d.zip
Compatibility bugs in IMAP response parser.
-rw-r--r--ChangeLog4
-rw-r--r--vmime/net/imap/IMAPParser.hpp200
2 files changed, 136 insertions, 68 deletions
diff --git a/ChangeLog b/ChangeLog
index b5fcddd7..0a6ad965 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,10 @@
VERSION 0.8.1cvs
================
+2005-12-18 Vincent Richard <[email protected]>
+
+ * IMAPParser.hpp: compatibility bugs + enhanced debugging trace.
+
2005-12-04 Vincent Richard <[email protected]>
* exception.{hpp|cpp}: fixed segfault in destructor when destroying
diff --git a/vmime/net/imap/IMAPParser.hpp b/vmime/net/imap/IMAPParser.hpp
index f8a15f33..3b7def05 100644
--- a/vmime/net/imap/IMAPParser.hpp
+++ b/vmime/net/imap/IMAPParser.hpp
@@ -62,19 +62,70 @@ namespace imap {
#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;
+ static int IMAPParserDebugResponse_level = 0;
+ static std::vector <string> IMAPParserDebugResponse_stack;
+
+ class IMAPParserDebugResponse
+ {
+ public:
+
+ IMAPParserDebugResponse(const string& name, string& line, const string::size_type currentPos)
+ : m_name(name), m_line(line), m_pos(currentPos)
+ {
+ ++IMAPParserDebugResponse_level;
+ IMAPParserDebugResponse_stack.push_back(name);
+
+ for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i)
+ std::cout << " ";
+
+ std::cout << "ENTER(" << m_name << "), pos=" << m_pos;
+ std::cout << std::endl;
+
+ for (std::vector <string>::iterator it = IMAPParserDebugResponse_stack.begin() ;
+ it != IMAPParserDebugResponse_stack.end() ; ++it)
+ {
+ std::cout << "> " << *it << " ";
+ }
+
+ std::cout << std::endl;
+ std::cout << string(m_line.begin() + (m_pos < 30 ? 0U : m_pos - 30),
+ m_line.begin() + std::min(m_line.length(), m_pos + 30)) << std::endl;
+
+ for (string::size_type i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i)
+ std::cout << " ";
+
+ std::cout << "^" << std::endl;
+ }
+
+ ~IMAPParserDebugResponse()
+ {
+ for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i)
+ std::cout << " ";
+
+ std::cout << "LEAVE(" << m_name << "), result=";
+ std::cout << (std::uncaught_exception() ? "FALSE" : "TRUE") << ", pos=" << m_pos;
+ std::cout << std::endl;
+
+ --IMAPParserDebugResponse_level;
+ IMAPParserDebugResponse_stack.pop_back();
+ }
+
+ private:
+
+ const string& m_name;
+ string& m_line;
+ string::size_type m_pos;
+ };
+
+
+ #define DEBUG_ENTER_COMPONENT(x) \
+ IMAPParserDebugResponse dbg(x, line, *currentPos)
+
+ #define DEBUG_FOUND(x, y) \
+ std::cout << "FOUND: " << x << ": " << y << std::endl;
#else
-# define DEBUG_ENTER_COMPONENT(x)
-# define DEBUG_FOUND(x, y)
+ #define DEBUG_ENTER_COMPONENT(x)
+ #define DEBUG_FOUND(x, y)
#endif
@@ -252,6 +303,16 @@ public:
};
+#define COMPONENT_ALIAS(parent, name) \
+ class name : public parent \
+ { \
+ void go(IMAPParser& parser, string& line, string::size_type* currentPos) \
+ { \
+ DEBUG_ENTER_COMPONENT(#name); \
+ parent::go(parser, line, currentPos); \
+ } \
+ }
+
//
// Parse one character
@@ -1730,7 +1791,7 @@ public:
m_resp_text_code = parser.get <IMAPParser::resp_text_code>(line, &pos);
parser.check <one_char <']'> >(line, &pos);
- parser.check <SPACE>(line, &pos);
+ parser.check <SPACE>(line, &pos, true);
}
text_mime2* text1 = parser.get <text_mime2>(line, &pos, true);
@@ -2282,7 +2343,10 @@ public:
(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));
+ {
+ m_body_extensions.push_back(parser.get <body_extension>(line, &pos));
+ parser.check <SPACE>(line, &pos, true);
+ }
}
else
{
@@ -2586,70 +2650,70 @@ public:
// env_bcc ::= "(" 1*address ")" / nil
//
- typedef address_list env_bcc;
+ COMPONENT_ALIAS(address_list, env_bcc);
//
// env_cc ::= "(" 1*address ")" / nil
//
- typedef address_list env_cc;
+ COMPONENT_ALIAS(address_list, env_cc);
//
// env_date ::= nstring
//
- typedef nstring env_date;
+ COMPONENT_ALIAS(nstring, env_date);
//
// env_from ::= "(" 1*address ")" / nil
//
- typedef address_list env_from;
+ COMPONENT_ALIAS(address_list, env_from);
//
// env_in_reply_to ::= nstring
//
- typedef nstring env_in_reply_to;
+ COMPONENT_ALIAS(nstring, env_in_reply_to);
//
// env_message_id ::= nstring
//
- typedef nstring env_message_id;
+ COMPONENT_ALIAS(nstring, env_message_id);
//
// env_reply_to ::= "(" 1*address ")" / nil
//
- typedef address_list env_reply_to;
+ COMPONENT_ALIAS(address_list, env_reply_to);
//
// env_sender ::= "(" 1*address ")" / nil
//
- typedef address_list env_sender;
+ COMPONENT_ALIAS(address_list, env_sender);
//
// env_subject ::= nstring
//
- typedef nstring env_subject;
+ COMPONENT_ALIAS(nstring, env_subject);
//
// env_to ::= "(" 1*address ")" / nil
//
- typedef address_list env_to;
+ COMPONENT_ALIAS(address_list, env_to);
//
@@ -2867,10 +2931,8 @@ public:
string::size_type pos = *currentPos;
- if (!parser.check <NIL>(line, &pos, true))
+ if (parser.check <one_char <'('> >(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))
@@ -2879,6 +2941,10 @@ public:
m_items.push_back(parser.get <body_fld_param_item>(line, &pos));
}
}
+ else
+ {
+ parser.check <NIL>(line, &pos);
+ }
*currentPos = pos;
}
@@ -2918,14 +2984,17 @@ public:
string::size_type pos = *currentPos;
- if (!parser.check <NIL>(line, &pos, true))
+ if (parser.check <one_char <'('> >(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);
}
+ else
+ {
+ parser.check <NIL>(line, &pos);
+ }
*currentPos = pos;
}
@@ -2970,7 +3039,10 @@ public:
m_strings.push_back(parser.get <class xstring>(line, &pos));
while (!parser.check <one_char <')'> >(line, &pos, true))
+ {
+ parser.check <SPACE>(line, &pos);
m_strings.push_back(parser.get <class xstring>(line, &pos));
+ }
}
else
{
@@ -3246,10 +3318,15 @@ public:
m_body_extensions.push_back
(parser.get <body_extension>(line, &pos));
+ parser.check <SPACE>(line, &pos, true);
+
body_extension* ext = NULL;
while ((ext = parser.get <body_extension>(line, &pos, true)) != NULL)
+ {
m_body_extensions.push_back(ext);
+ parser.check <SPACE>(line, &pos, true);
+ }
}
}
}
@@ -3325,10 +3402,15 @@ public:
m_body_extensions.push_back
(parser.get <body_extension>(line, &pos));
+ parser.check <SPACE>(line, &pos, true);
+
body_extension* ext = NULL;
while ((ext = parser.get <body_extension>(line, &pos, true)) != NULL)
+ {
m_body_extensions.push_back(ext);
+ parser.check <SPACE>(line, &pos, true);
+ }
}
}
@@ -3435,10 +3517,13 @@ public:
parser.check <SPACE>(line, &pos);
m_body_fields = parser.get <IMAPParser::body_fields>(line, &pos);
parser.check <SPACE>(line, &pos);
+
+ // BUGFIX: made SPACE optional. This is not standard, but some servers
+ // seem to return responses like that...
m_envelope = parser.get <IMAPParser::envelope>(line, &pos);
- parser.check <SPACE>(line, &pos);
+ parser.check <SPACE>(line, &pos, true);
m_body = parser.get <IMAPParser::xbody>(line, &pos);
- parser.check <SPACE>(line, &pos);
+ parser.check <SPACE>(line, &pos, true);
m_body_fld_lines = parser.get <IMAPParser::body_fld_lines>(line, &pos);
*currentPos = pos;
@@ -3547,7 +3632,12 @@ public:
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);
+ {
+ m_body_ext_1part = parser.get <IMAPParser::body_ext_1part>(line, &pos, true);
+
+ if (!m_body_ext_1part)
+ --pos;
+ }
*currentPos = pos;
}
@@ -3660,8 +3750,8 @@ public:
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);
+ if (!(m_body_type_mpart = parser.get <IMAPParser::body_type_mpart>(line, &pos, true)))
+ m_body_type_1part = parser.get <IMAPParser::body_type_1part>(line, &pos);
parser.check <one_char <')'> >(line, &pos);
@@ -4815,29 +4905,15 @@ private:
TYPE* internalGet(component* resp, string& line, string::size_type* currentPos,
const bool noThrow = false)
{
-#if DEBUG_RESPONSE
- DEBUG_RESPONSE_level += " ";
-#endif
+ const string::size_type oldPos = *currentPos;
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
+ *currentPos = oldPos;
delete (resp);
if (!noThrow) throw;
@@ -4858,22 +4934,16 @@ public:
const bool check(string& line, string::size_type* currentPos,
const bool noThrow = false)
{
+ const string::size_type oldPos = *currentPos;
+
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
+ *currentPos = oldPos;
if (!noThrow) throw;
return false;
@@ -4886,22 +4956,16 @@ public:
const bool checkWithArg(string& line, string::size_type* currentPos,
const ARG_TYPE arg, const bool noThrow = false)
{
+ const string::size_type oldPos = *currentPos;
+
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
+ *currentPos = oldPos;
if (!noThrow) throw;
return false;