1 ///###////////////////////////////////////////////////////////////////////////
2 //
3 // Burton Computer Corporation
4 // http://www.burton-computer.com
5 // http://www.cooldevtools.com
6 // $Id: MailMessageReader.cc 272 2007-01-06 19:37:27Z brian $
7 //
8 // Copyright (C) 2007 Burton Computer Corporation
9 // ALL RIGHTS RESERVED
10 //
11 // This program is open source software; you can redistribute it
12 // and/or modify it under the terms of the Q Public License (QPL)
13 // version 1.0. Use of this software in whole or in part, including
14 // linking it (modified or unmodified) into other programs is
15 // subject to the terms of the QPL.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 // Q Public License for more details.
21 //
22 // You should have received a copy of the Q Public License
23 // along with this program; see the file LICENSE.txt.  If not, visit
24 // the Burton Computer Corporation or CoolDevTools web site
25 // QPL pages at:
26 //
27 //    http://www.burton-computer.com/qpl.html
28 //    http://www.cooldevtools.com/qpl.html
29 //
30 
31 #include <cstdlib>
32 #include "RegularExpression.h"
33 #include "MailMessage.h"
34 #include "MailMessageList.h"
35 #include "LineReader.h"
36 #include "MultiLineString.h"
37 #include "MailMessageReader.h"
38 
39 // Defines how many chars to deduct from content-length so that we can
40 // find a blank line before the message delimiter line that follows
41 // the message.
42 static const int CONTENT_LENGTH_PADDING = 10;
43 
MailMessageReader(bool use_content_length)44 MailMessageReader::MailMessageReader(bool use_content_length)
45   : m_useContentLength(use_content_length)
46 {
47 }
48 
~MailMessageReader()49 MailMessageReader::~MailMessageReader()
50 {
51 }
52 
findContentLength(MultiLineString * text,int & content_length)53 bool MailMessageReader::findContentLength(MultiLineString *text,
54                                           int &content_length)
55 {
56   RegularExpression regex("^content-length: *([0-9]+)", 2, true);
57   for (int i = 0; i < text->lineCount(); ++i) {
58     if (regex.match(text->line(i))) {
59       string buffer;
60       content_length = max(0, atoi(regex.getMatch(1, buffer).c_str()) - CONTENT_LENGTH_PADDING);
61       return true;
62     }
63   }
64   return false;
65 }
66 
readMessage()67 OWNED MailMessage *MailMessageReader::readMessage()
68 {
69   Ref<MultiLineString> text(new MultiLineString());
70   if (m_useContentLength) {
71     readMessageWithContentLength(text.ptr());
72   } else {
73     readMessageWithBoundary(text.ptr(), false);
74   }
75   return (text->lineCount() > 0) ? new MailMessage(text) : 0;
76 }
77 
readMessageWithBoundary(MultiLineString * text,bool append_to_last_line)78 void MailMessageReader::readMessageWithBoundary(MultiLineString *text,
79                                                 bool append_to_last_line)
80 {
81   while (reader()->hasLine()) {
82     if (isNewMessageBoundary(reader()->currentLine())) {
83       break;
84     }
85     if (is_debug) {
86       cerr << "LINE: '" << reader()->currentLine() << "'" << endl;
87     }
88     if (append_to_last_line) {
89       text->appendToLastLine(reader()->currentLine());
90       append_to_last_line = false;
91     } else {
92       text->addLine(reader()->currentLine());
93     }
94     reader()->forward();
95   }
96 }
97 
readMessageWithContentLength(MultiLineString * text)98 void MailMessageReader::readMessageWithContentLength(MultiLineString *text)
99 {
100   while (reader()->hasLine()) {
101     if (is_debug) {
102       cerr << "HDR: '" << reader()->currentLine() << "'" << endl;
103     }
104     text->addLine(reader()->currentLine());
105     if (reader()->currentLine().length() == 0) {
106       break;
107     }
108     reader()->forward();
109   }
110 
111   bool should_append = false;
112   int content_length = 0;
113   if (findContentLength(text, content_length)) {
114     should_append = content_length > 0;
115     while (reader()->forward(content_length)) {
116       if (is_debug) {
117         cerr << "CL: " << content_length << ": " << reader()->currentLine() << endl;
118       }
119       text->addLine(reader()->currentLine());
120     }
121     reader()->forward();
122   }
123 
124   readMessageWithBoundary(text, should_append);
125 }
126 
isNewMessageBoundary(const string & line)127 bool MailMessageReader::isNewMessageBoundary(const string &line)
128 {
129   return false;
130 }
131