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