1 ///###////////////////////////////////////////////////////////////////////////
2 //
3 // Burton Computer Corporation
4 // http://www.burton-computer.com
5 // http://www.cooldevtools.com
6 // $Id: HeaderPrefixList.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 "HeaderPrefixList.h"
32
33 static const char *SKIPPED_HEADERS[] = {
34 "x-spam",
35 "x-razor",
36 "status",
37 "x-status",
38 "x-imap",
39 0
40 };
41
42 const string PREFIX_START("H");
43 const string PREFIX_END("_");
44
is_skipped_header(const string & line)45 static bool is_skipped_header(const string &line)
46 {
47 for (const char **s = SKIPPED_HEADERS; *s; ++s) {
48 if (starts_with(line, *s)) {
49 return true;
50 }
51 }
52 return false;
53 }
54
getPrefixBody(const string & prefix)55 string HeaderPrefixList::const_iterator::getPrefixBody(const string &prefix)
56 {
57 return prefix.substr(PREFIX_START.length(), prefix.length() - PREFIX_START.length() - PREFIX_END.length());
58 }
59
HeaderPrefixList()60 HeaderPrefixList::HeaderPrefixList()
61 : m_visitAllHeaders(false),
62 m_ignoreXHeaders(false),
63 m_forceBlankPrefixes(false)
64 {
65 }
66
~HeaderPrefixList()67 HeaderPrefixList::~HeaderPrefixList()
68 {
69 }
70
resetHeaderCounts()71 void HeaderPrefixList::resetHeaderCounts()
72 {
73 for (IteratorType i = m_values.begin(); i != m_values.end(); ++i) {
74 i->second.visit_count = 0;
75 }
76 }
77
shouldProcessHeader(const string & name,string & prefix)78 bool HeaderPrefixList::shouldProcessHeader(const string &name,
79 string &prefix)
80 {
81 IteratorType i = m_values.find(name);
82 if (i != m_values.end()) {
83 HeaderData &hd(i->second);
84 hd.visit_count += 1;
85 if (m_forceBlankPrefixes) {
86 prefix.erase();
87 } else if (hd.visit_count > 1) {
88 prefix = hd.other_prefix;
89 } else {
90 prefix = hd.first_prefix;
91 }
92 return true;
93 }
94
95 if (!m_visitAllHeaders) {
96 return false;
97 }
98
99 if (m_ignoreXHeaders && starts_with(name, "x-")) {
100 return false;
101 }
102
103 if (is_skipped_header(name)) {
104 return false;
105 }
106
107 if (m_forceBlankPrefixes) {
108 prefix.erase();
109 } else {
110 prefix = PREFIX_START + name + PREFIX_END;
111 }
112 addHeaderPrefix(name, name, name);
113 return true;
114 }
115
setBlankPrefixesMode()116 void HeaderPrefixList::setBlankPrefixesMode()
117 {
118 m_forceBlankPrefixes = true;
119 }
120
setDefaultHeadersMode()121 void HeaderPrefixList::setDefaultHeadersMode()
122 {
123 m_visitAllHeaders = false;
124 m_ignoreXHeaders = false;
125 m_forceBlankPrefixes = false;
126 m_values.clear();
127
128 addHeaderPrefix("reply-to", "reply-to", "reply-to");
129 addHeaderPrefix("sender", "sender", "sender");
130 addHeaderPrefix("originator", "originator", "originator");
131 addHeaderPrefix("subject", "subject", "subject");
132 addHeaderPrefix("from", "from", "from");
133 addHeaderPrefix("to", "to", "to");
134 addHeaderPrefix("cc", "cc", "cc");
135 addHeaderPrefix("message-id", "message-id", "message-id");
136 addHeaderPrefix("received", "recv", "recvx");
137 addHeaderPrefix("content-type", "", "");
138 }
139
setNonXHeadersMode()140 void HeaderPrefixList::setNonXHeadersMode()
141 {
142 m_visitAllHeaders = true;
143 m_ignoreXHeaders = true;
144 m_forceBlankPrefixes = false;
145 m_values.clear();
146 }
147
setAllHeadersMode()148 void HeaderPrefixList::setAllHeadersMode()
149 {
150 m_visitAllHeaders = true;
151 m_ignoreXHeaders = false;
152 m_forceBlankPrefixes = false;
153 m_values.clear();
154 }
155
setNoHeadersMode()156 void HeaderPrefixList::setNoHeadersMode()
157 {
158 m_visitAllHeaders = false;
159 m_ignoreXHeaders = false;
160 m_forceBlankPrefixes = false;
161 m_values.clear();
162 }
163
addSimpleHeaderPrefix(const string & name)164 void HeaderPrefixList::addSimpleHeaderPrefix(const string &name)
165 {
166 addHeaderPrefix(name, name, name);
167 }
168
addHeaderPrefix(const string & name,const string & first_prefix,const string & other_prefix)169 void HeaderPrefixList::addHeaderPrefix(const string &name,
170 const string &first_prefix,
171 const string &other_prefix)
172 {
173 HeaderData hd;
174 if (first_prefix.length() > 0) {
175 hd.first_prefix = PREFIX_START + to_lower(first_prefix) + PREFIX_END;
176 }
177 if (other_prefix.length() > 0) {
178 hd.other_prefix = PREFIX_START + to_lower(other_prefix) + PREFIX_END;
179 }
180 hd.visit_count = 0;
181 m_values.insert(make_pair(to_lower(name), hd));
182 }
183
removeHeaderPrefix(const string & name)184 void HeaderPrefixList::removeHeaderPrefix(const string &name)
185 {
186 string lower_name(to_lower(name));
187 MapType::iterator i = m_values.find(lower_name);
188 if (i != m_values.end()) {
189 m_values.erase(i);
190 }
191 }
192