Compatibility bugs in IMAP response parser.

This commit is contained in:
Vincent Richard 2005-12-18 21:20:43 +00:00
parent 14d30ac458
commit 54e4235b8d
2 changed files with 135 additions and 67 deletions

View File

@ -2,6 +2,10 @@
VERSION 0.8.1cvs
================
2005-12-18 Vincent Richard <vincent@vincent-richard.net>
* IMAPParser.hpp: compatibility bugs + enhanced debugging trace.
2005-12-04 Vincent Richard <vincent@vincent-richard.net>
* exception.{hpp|cpp}: fixed segfault in destructor when destroying

View File

@ -62,19 +62,70 @@ namespace imap {
#if DEBUG_RESPONSE
static string DEBUG_RESPONSE_level;
static std::vector <string> DEBUG_RESPONSE_components;
static int IMAPParserDebugResponse_level = 0;
static std::vector <string> IMAPParserDebugResponse_stack;
# 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;
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;