Compatibility bugs in IMAP response parser.
This commit is contained in:
parent
14d30ac458
commit
54e4235b8d
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user