1 //
2 // VMime library (http://www.vmime.org)
3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 3 of
8 // the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // Linking this library statically or dynamically with other modules is making
20 // a combined work based on this library. Thus, the terms and conditions of
21 // the GNU General Public License cover the whole combination.
22 //
23
24 #include "vmime/propertySet.hpp"
25 #include "vmime/parserHelpers.hpp"
26
27
28 namespace vmime
29 {
30
31
propertySet()32 propertySet::propertySet()
33 {
34 }
35
36
propertySet(const string & props)37 propertySet::propertySet(const string& props)
38 {
39 parse(props);
40 }
41
42
propertySet(const propertySet & set)43 propertySet::propertySet(const propertySet& set)
44 : object()
45 {
46 for (std::list <shared_ptr <property> >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it)
47 m_props.push_back(make_shared <property>(**it));
48 }
49
50
~propertySet()51 propertySet::~propertySet()
52 {
53 removeAllProperties();
54 }
55
56
operator =(const propertySet & set)57 propertySet& propertySet::operator=(const propertySet& set)
58 {
59 removeAllProperties();
60
61 for (std::list <shared_ptr <property> >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it)
62 m_props.push_back(make_shared <property>(**it));
63
64 return (*this);
65 }
66
67
setFromString(const string & props)68 void propertySet::setFromString(const string& props)
69 {
70 parse(props);
71 }
72
73
removeAllProperties()74 void propertySet::removeAllProperties()
75 {
76 m_props.clear();
77 }
78
79
removeProperty(const string & name)80 void propertySet::removeProperty(const string& name)
81 {
82 std::list <shared_ptr <property> >::iterator it = std::find_if
83 (m_props.begin(), m_props.end(), propFinder(name));
84
85 if (it != m_props.end())
86 m_props.erase(it);
87 }
88
89
parse(const string & props)90 void propertySet::parse(const string& props)
91 {
92 const string::const_iterator end = props.end();
93 string::const_iterator pos = props.begin();
94
95 for ( ; pos != end ; )
96 {
97 // Skip white-spaces
98 for ( ; pos != end && parserHelpers::isSpace(*pos) ; ++pos) {}
99
100 if (pos != end)
101 {
102 if (*pos == ';')
103 {
104 ++pos;
105 continue;
106 }
107
108 // Extract the property name
109 const string::const_iterator optStart = pos;
110
111 for ( ; pos != end && *pos != '=' ; ++pos) {}
112
113 string::const_iterator optEnd = pos;
114
115 for ( ; optEnd != optStart && parserHelpers::isSpace(*(optEnd - 1)) ; --optEnd) {}
116
117 const string option(optStart, optEnd);
118 string value = "1";
119
120 if (pos != end)
121 {
122 ++pos; // skip '='
123
124 // Extract the value
125 for ( ; pos != end && parserHelpers::isSpace(*pos) ; ++pos) {}
126
127 if (pos != end)
128 {
129 // A quoted-string
130 if (*pos == '"' || *pos == '\'')
131 {
132 value.reserve(50);
133
134 const char quoteChar = *pos;
135 bool theEnd = false;
136 bool escape = false;
137
138 for ( ; (pos != end) && !theEnd ; ++pos)
139 {
140 if (escape)
141 {
142 value += *pos;
143 escape = false;
144 }
145 else
146 {
147 if (*pos == '\\')
148 escape = true;
149 else if (*pos == quoteChar)
150 theEnd = true;
151 else
152 value += *pos;
153 }
154 }
155
156 if (pos != end)
157 ++pos;
158 }
159 // Simple value
160 else
161 {
162 const string::const_iterator valStart = pos;
163
164 for ( ; pos != end && !parserHelpers::isSpace(*pos) ; ++pos) {}
165
166 value = string(valStart, pos);
167 }
168
169 // Advance to the next ';'
170 for ( ; pos != end && (*pos != ';') ; ++pos) {}
171
172 if (pos != end)
173 ++pos; // skip ';'
174 }
175 }
176
177 m_props.push_back(make_shared <property>(option, value));
178 }
179 }
180 }
181
182
find(const string & name) const183 shared_ptr <propertySet::property> propertySet::find(const string& name) const
184 {
185 std::list <shared_ptr <property> >::const_iterator it = std::find_if
186 (m_props.begin(), m_props.end(), propFinder(name));
187
188 return (it != m_props.end() ? *it : null);
189 }
190
191
findOrCreate(const string & name)192 shared_ptr <propertySet::property> propertySet::findOrCreate(const string& name)
193 {
194 std::list <shared_ptr <property> >::const_iterator it = std::find_if
195 (m_props.begin(), m_props.end(), propFinder(name));
196
197 if (it != m_props.end())
198 {
199 return (*it);
200 }
201 else
202 {
203 shared_ptr <property> prop = make_shared <property>(name, "");
204 m_props.push_back(prop);
205 return (prop);
206 }
207 }
208
209
operator [](const string & name)210 propertySet::propertyProxy propertySet::operator[](const string& name)
211 {
212 return (propertyProxy(name, this));
213 }
214
215
operator [](const string & name) const216 const propertySet::constPropertyProxy propertySet::operator[](const string& name) const
217 {
218 return (constPropertyProxy(name, this));
219 }
220
221
hasProperty(const string & name) const222 bool propertySet::hasProperty(const string& name) const
223 {
224 return (find(name) != NULL);
225 }
226
227
getPropertyList() const228 const std::vector <shared_ptr <const propertySet::property> > propertySet::getPropertyList() const
229 {
230 std::vector <shared_ptr <const property> > res;
231
232 for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it)
233 res.push_back(*it);
234
235 return (res);
236 }
237
238
getPropertyList()239 const std::vector <shared_ptr <propertySet::property> > propertySet::getPropertyList()
240 {
241 std::vector <shared_ptr <property> > res;
242
243 for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it)
244 res.push_back(*it);
245
246 return (res);
247 }
248
249
250 //
251 // propertySet::property
252 //
253
property(const string & name,const string & value)254 propertySet::property::property(const string& name, const string& value)
255 : m_name(name), m_value(value)
256 {
257 }
258
259
property(const string & name)260 propertySet::property::property(const string& name)
261 : m_name(name)
262 {
263 }
264
265
property(const property & prop)266 propertySet::property::property(const property& prop)
267 : object(), m_name(prop.m_name), m_value(prop.m_value)
268 {
269 }
270
271
getName() const272 const string& propertySet::property::getName() const
273 {
274 return (m_name);
275 }
276
277
278 #ifndef _MSC_VER
279
280
getValue() const281 const string& propertySet::property::getValue() const
282 {
283 return (m_value);
284 }
285
286
setValue(const string & value)287 void propertySet::property::setValue(const string& value)
288 {
289 m_value = value;
290 }
291
292
293 #endif // !_MSC_VER
294
295
296 #ifndef VMIME_INLINE_TEMPLATE_SPECIALIZATION
297
298 template <>
setValue(const string & value)299 void propertySet::property::setValue(const string& value)
300 {
301 m_value = value;
302 }
303
304
305 template <>
setValue(const bool & value)306 void propertySet::property::setValue(const bool& value)
307 {
308 m_value = value ? "true" : "false";
309 }
310
311
312 template <>
getValue() const313 string propertySet::property::getValue() const
314 {
315 return (m_value);
316 }
317
318
319 template <>
getValue() const320 bool propertySet::property::getValue() const
321 {
322 if (utility::stringUtils::toLower(m_value) == "true")
323 return true;
324 else
325 {
326 int val = 0;
327
328 std::istringstream iss(m_value);
329 iss.imbue(std::locale::classic()); // no formatting
330
331 iss >> val;
332
333 return (!iss.fail() && val != 0);
334 }
335 }
336
337
338
339
340 template <>
valueFromString(const string & value)341 string propertySet::valueFromString(const string& value)
342 {
343 return value;
344 }
345
346
347 template <>
valueToString(const string & value)348 string propertySet::valueToString(const string& value)
349 {
350 return value;
351 }
352
353
354 template <>
valueFromString(const string & value)355 bool propertySet::valueFromString(const string& value)
356 {
357 if (utility::stringUtils::toLower(value) == "true")
358 return true;
359 else
360 {
361 int val = 0;
362
363 std::istringstream iss(value);
364 iss.imbue(std::locale::classic()); // no formatting
365
366 iss >> val;
367
368 return (!iss.fail() && val != 0);
369 }
370 }
371
372
373 template <>
valueToString(const bool & value)374 string propertySet::valueToString(const bool& value)
375 {
376 return (value ? "true" : "false");
377 }
378
379 #endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION
380
381
382 } // vmime
383