1 ///###////////////////////////////////////////////////////////////////////////
2 //
3 // Burton Computer Corporation
4 // http://www.burton-computer.com
5 // http://www.cooldevtools.com
6 // $Id: BodyParser.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 "MessageHeader.h"
32 #include "MessageHeaderList.h"
33 #include "MultiLineString.h"
34 #include "MultiLineSubString.h"
35 #include "MailMessage.h"
36 #include "MailMessageList.h"
37 #include "BodyParser.h"
38 
parseBody(const MessageHeaderList * headers,const CRef<AbstractMultiLineString> & body_text)39 Ref<MailMessageList> BodyParser::parseBody(const MessageHeaderList *headers,
40                                               const CRef<AbstractMultiLineString> &body_text)
41 {
42   m_headers = headers;
43   m_bodyText = body_text;
44   m_bodyParts = make_ref(new MailMessageList());
45   parse();
46   m_bodyText.clear();
47   return m_bodyParts;
48 }
49 
skipToBlank(const CRef<AbstractMultiLineString> & lines,int & offset)50 int BodyParser::skipToBlank(const CRef<AbstractMultiLineString> &lines,
51                             int &offset)
52 {
53   while (offset < lines->lineCount()) {
54     if (lines->line(offset).length() == 0) {
55       return offset;
56     }
57     ++offset;
58   }
59   return lines->lineCount();
60 }
61 
skipToNonBlank(const CRef<AbstractMultiLineString> & lines,int & offset)62 int BodyParser::skipToNonBlank(const CRef<AbstractMultiLineString> &lines,
63                                int &offset)
64 {
65   while (offset < lines->lineCount()) {
66     if (lines->line(offset).length() > 0) {
67       return offset;
68     }
69     ++offset;
70   }
71   return lines->lineCount();
72 }
73 
addPart(const CRef<AbstractMultiLineString> & lines)74 void BodyParser::addPart(const CRef<AbstractMultiLineString> &lines)
75 {
76   int offset = 0;
77   int header_start = skipToNonBlank(lines, offset);
78   int header_end = skipToBlank(lines, offset);
79   int body_start = skipToNonBlank(lines, offset);
80   int body_end = lines->lineCount();
81 
82   CRef<AbstractMultiLineString> head(new MultiLineSubString(lines, header_start, header_end));
83   CRef<AbstractMultiLineString> body(new MultiLineSubString(lines, body_start, body_end));
84   Ptr<MailMessage> message(new MailMessage(head, body, lines));
85   m_bodyParts->addMessage(message.release());
86 }
87 
addPartsForBoundary(const CRef<AbstractMultiLineString> & lines,const string & boundary)88 void BodyParser::addPartsForBoundary(const CRef<AbstractMultiLineString> &lines,
89                                      const string &boundary)
90 {
91   string part_boundary = "--" + boundary;
92   string end_boundary = part_boundary + "--";
93 
94   int offset = 0;
95   offset = skipToNonBlank(lines, offset);
96 
97   int prev_offset = -1;
98   while (offset < lines->lineCount()) {
99     const string &line(lines->line(offset));
100     if (line == part_boundary || line == end_boundary) {
101       if (prev_offset >= 0 && offset > prev_offset) {
102         Ref<AbstractMultiLineString> part(new MultiLineSubString(lines, prev_offset, offset));
103         addPart(part);
104       }
105       if (line == end_boundary) {
106         // ignore anything after end boundary
107         return;
108       }
109       prev_offset = offset + 1;
110     }
111     ++offset;
112   }
113 
114   // a safety net in case the loser mail client didn't include the end boundary
115   if (prev_offset >= 0 && offset > prev_offset) {
116     Ref<AbstractMultiLineString> part(new MultiLineSubString(lines, prev_offset, offset));
117     addPart(part);
118   }
119 }
120 
parse()121 void BodyParser::parse()
122 {
123   string boundary;
124   m_headers->getBoundaryString(boundary);
125   if (boundary.length() > 0) {
126     addPartsForBoundary(m_bodyText, boundary);
127   } else {
128     addPart(m_bodyText);
129   }
130 }
131