1 ///###////////////////////////////////////////////////////////////////////////
2 //
3 // Burton Computer Corporation
4 // http://www.burton-computer.com
5 // http://www.cooldevtools.com
6 // $Id: MessageHeaderList.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 "RegularExpression.h"
32 #include "MultiLineSubString.h"
33 #include "MultiLineJoinedString.h"
34 #include "MessageHeader.h"
35 #include "MessageHeaderList.h"
36 
37 static const string CONTENT_TYPE("content-type");
38 
header(const string & name) const39 CRef<AbstractMultiLineString> MessageHeaderList::header(const string &name) const
40 {
41     MultiLineStringList values;
42     for (int i = 0; i < m_headers.size(); ++i) {
43         if (m_headers[i]->hasName(name)) {
44             values.push_back(m_headers[i]->lines());
45         }
46     }
47 
48     if (values.size() == 0) {
49         return CRef<AbstractMultiLineString>();
50     }
51 
52     if (values.size() == 1) {
53         return values[0];
54     }
55 
56     return CRef<AbstractMultiLineString>(new MultiLineJoinedString(values));
57 }
58 
getContentTypeString(string & buffer) const59 const string &MessageHeaderList::getContentTypeString(string &buffer) const
60 {
61     getHeaderString(CONTENT_TYPE, EMPTY_STRING, buffer);
62     buffer = to_lower(buffer);
63     return buffer;
64 }
65 
getBoundaryString(string & buffer) const66 const string &MessageHeaderList::getBoundaryString(string &buffer) const
67 {
68     string header;
69     getHeaderString(CONTENT_TYPE, EMPTY_STRING, header);
70     return findParam(header, "boundary", EMPTY_STRING, buffer);
71 }
72 
getCharsetString(string & buffer) const73 const string &MessageHeaderList::getCharsetString(string &buffer) const
74 {
75     string header;
76     getHeaderString(CONTENT_TYPE, EMPTY_STRING, header);
77     findParam(header, "charset", EMPTY_STRING, buffer);
78     buffer = to_lower(buffer);
79     return buffer;
80 }
81 
getHeaderString(const string & header_name,const string & default_value,string & buffer) const82 const string &MessageHeaderList::getHeaderString(const string &header_name,
83                                                  const string &default_value,
84                                                  string &buffer) const
85 {
86     CRef<AbstractMultiLineString> header_strings(header(header_name));
87     if (header_strings.isNull()) {
88         buffer = default_value;
89     } else {
90         header_strings->join(buffer);
91     }
92     return buffer;
93 }
94 
hasBoundaryString() const95 bool MessageHeaderList::hasBoundaryString() const
96 {
97     string boundary_string;
98     getBoundaryString(boundary_string);
99     return boundary_string.length() > 0;
100 }
101 
isTextType() const102 bool MessageHeaderList::isTextType() const
103 {
104     string content_type;
105     getContentTypeString(content_type);
106     return content_type.length() == 0 || starts_with(content_type, "text");
107 }
108 
hasType(const string & type_name) const109 bool MessageHeaderList::hasType(const string &type_name) const
110 {
111     string content_type;
112     getContentTypeString(content_type);
113     return starts_with(content_type, type_name);
114 }
115 
isMessageType() const116 bool MessageHeaderList::isMessageType() const
117 {
118   return hasType("message/rfc822");
119 }
120 
findParam(const string & header,const string & param,const string & defaultValue,string & buffer) const121 const string &MessageHeaderList::findParam(const string &header,
122                                            const string &param,
123                                            const string &defaultValue,
124                                            string &buffer) const
125 {
126     RegularExpression param_regex(string("[^a-z]") + param + "[ \t]*=[ \t]*\"([^\"]+)\"", 2, true);
127     if (param_regex.match(header)) {
128         return param_regex.getMatch(1, buffer);
129     }
130 
131     param_regex.setExpression(string("[^a-z]") + param + "[ \t]*=[ \t]*([^ \t;\"]+)", 2, true);
132     if (param_regex.match(header)) {
133         return param_regex.getMatch(1, buffer);
134     }
135 
136     buffer = defaultValue;
137     return buffer;
138 }
139 
140