2008年10月14日星期二

发现并修改Poco库中的一个小错误

今天使用Poco的Net中的Pop3收邮件时发现有时邮件主题找不到了,代码如下:
 
   session.retrieveMessage(infos.at(i).id,str);//
 
   std::istringstream inputstr(str.str());
   Poco::Net::MailMessage mailMessage;
   mailMessage.read(inputstr);
 
   std::string strSubject = mailMessage.getSubject();
   Poco::Timestamp mailTime = mailMessage.getDate();
   std::string strSender = mailMessage.getSender();
 
进一步跟踪,在如下数据时会造成主题丢失:
 
To: <xxx@126.com>
Cc:
Subject: You can win an iPhone from VMware when you update your VMware Profile
 
检查代码
 

void MessageHeader::read(std::istream& istr)
{
 static const int eof = std::char_traits<char>::eof();
 int ch = istr.get();
 while (ch != eof && ch != '\r' && ch != '\n')
 {
  std::string name;
  std::string value;
  while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = istr.get(); }
  if (ch == '\n') { ch = istr.get(); continue; } // ignore invalid header lines
  if (ch != ':') throw MessageException("Field name too long/no colon found");
  if (ch != eof) ch = istr.get(); // ':'
  while (std::isspace(ch)) ch = istr.get();
  while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); }
  if (ch == '\r') ch = istr.get();
  if (ch == '\n')
   ch = istr.get();
  else if (ch != eof)
   throw MessageException("Field value too long/no CRLF found");
  while (ch == ' ' || ch == '\t') // folding
  {
   while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); }
   if (ch == '\r') ch = istr.get();
   if (ch == '\n')
    ch = istr.get();
   else if (ch != eof)
    throw MessageException("Folded field value too long/no CRLF found");
  }
  add(name, value);
 }
 istr.putback(ch);
}
 
原来是红色代码(去掉空白字符)造成的,当分析到Cc时,由于将Cc后的\r\n当作空白字符去掉,使得Subject内容变成了Cc字段的数据,所以解析就不正确了
注释掉红色代码,重新编译,完事ok!

没有评论: