1 /*
2 SPDX-FileCopyrightText: 2015-2017 Krzysztof Nowicki <krissn@op.pl>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7 #include "ewsxml.h"
8
9 #include <QDateTime>
10
11 #include "ewsfolder.h"
12 #include "ewsid.h"
13 #include "ewsitem.h"
14
15 static const QVector<QString> messageSensitivityNames = {
16 QStringLiteral("Normal"),
17 QStringLiteral("Personal"),
18 QStringLiteral("Private"),
19 QStringLiteral("Confidential"),
20 };
21
22 static const QVector<QString> messageImportanceNames = {QStringLiteral("Low"), QStringLiteral("Normal"), QStringLiteral("High")};
23
24 static const QVector<QString> calendarItemTypeNames = {
25 QStringLiteral("Single"),
26 QStringLiteral("Occurrence"),
27 QStringLiteral("Exception"),
28 QStringLiteral("RecurringMaster"),
29 };
30
31 static const QVector<QString> legacyFreeBusyStatusNames = {
32 QStringLiteral("Free"),
33 QStringLiteral("Tentative"),
34 QStringLiteral("Busy"),
35 QStringLiteral("OOF"),
36 QStringLiteral("NoData"),
37 };
38
39 static const QVector<QString> responseTypeNames = {
40 QStringLiteral("Unknown"),
41 QStringLiteral("Organizer"),
42 QStringLiteral("Tentative"),
43 QStringLiteral("Accept"),
44 QStringLiteral("Decline"),
45 QStringLiteral("NoResponseReceived"),
46 };
47
ewsXmlBoolReader(QXmlStreamReader & reader,QVariant & val)48 bool ewsXmlBoolReader(QXmlStreamReader &reader, QVariant &val)
49 {
50 const QString elmText = reader.readElementText();
51 if (reader.error() != QXmlStreamReader::NoError) {
52 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading %1 element").arg(reader.name().toString());
53 reader.skipCurrentElement();
54 return false;
55 }
56 if (elmText == QLatin1String("true")) {
57 val = true;
58 } else if (elmText == QLatin1String("false")) {
59 val = false;
60 } else {
61 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected invalid boolean value in %1 element:").arg(reader.name().toString()) << elmText;
62 return false;
63 }
64
65 return true;
66 }
67
ewsXmlBoolWriter(QXmlStreamWriter & writer,const QVariant & val)68 bool ewsXmlBoolWriter(QXmlStreamWriter &writer, const QVariant &val)
69 {
70 writer.writeCharacters(val.toBool() ? QStringLiteral("true") : QStringLiteral("false"));
71
72 return true;
73 }
74
ewsXmlBase64Reader(QXmlStreamReader & reader,QVariant & val)75 bool ewsXmlBase64Reader(QXmlStreamReader &reader, QVariant &val)
76 {
77 QString elmName = reader.name().toString();
78 val = QByteArray::fromBase64(reader.readElementText().toLatin1());
79 if (reader.error() != QXmlStreamReader::NoError) {
80 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
81 reader.skipCurrentElement();
82 return false;
83 }
84
85 return true;
86 }
87
ewsXmlBase64Writer(QXmlStreamWriter & writer,const QVariant & val)88 bool ewsXmlBase64Writer(QXmlStreamWriter &writer, const QVariant &val)
89 {
90 writer.writeCharacters(QString::fromLatin1(val.toByteArray().toBase64()));
91
92 return true;
93 }
94
ewsXmlIdReader(QXmlStreamReader & reader,QVariant & val)95 bool ewsXmlIdReader(QXmlStreamReader &reader, QVariant &val)
96 {
97 QString elmName = reader.name().toString();
98 EwsId id = EwsId(reader);
99 if (id.type() == EwsId::Unspecified) {
100 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
101 reader.skipCurrentElement();
102 return false;
103 }
104 val = QVariant::fromValue(id);
105 reader.skipCurrentElement();
106 return true;
107 }
108
ewsXmlIdWriter(QXmlStreamWriter & writer,const QVariant & val)109 bool ewsXmlIdWriter(QXmlStreamWriter &writer, const QVariant &val)
110 {
111 EwsId id = val.value<EwsId>();
112 if (id.type() == EwsId::Unspecified) {
113 return false;
114 }
115
116 id.writeAttributes(writer);
117
118 return true;
119 }
120
ewsXmlTextReader(QXmlStreamReader & reader,QVariant & val)121 bool ewsXmlTextReader(QXmlStreamReader &reader, QVariant &val)
122 {
123 QString elmName = reader.name().toString();
124 val = reader.readElementText();
125 if (reader.error() != QXmlStreamReader::NoError) {
126 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
127 reader.skipCurrentElement();
128 return false;
129 }
130 return true;
131 }
132
ewsXmlTextWriter(QXmlStreamWriter & writer,const QVariant & val)133 bool ewsXmlTextWriter(QXmlStreamWriter &writer, const QVariant &val)
134 {
135 writer.writeCharacters(val.toString());
136
137 return true;
138 }
139
ewsXmlUIntReader(QXmlStreamReader & reader,QVariant & val)140 bool ewsXmlUIntReader(QXmlStreamReader &reader, QVariant &val)
141 {
142 QString elmName = reader.name().toString();
143 bool ok;
144 val = reader.readElementText().toUInt(&ok);
145 if (reader.error() != QXmlStreamReader::NoError || !ok) {
146 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
147 return false;
148 }
149 return true;
150 }
151
ewsXmlUIntWriter(QXmlStreamWriter & writer,const QVariant & val)152 bool ewsXmlUIntWriter(QXmlStreamWriter &writer, const QVariant &val)
153 {
154 writer.writeCharacters(QString::number(val.toUInt()));
155
156 return true;
157 }
158
ewsXmlDateTimeReader(QXmlStreamReader & reader,QVariant & val)159 bool ewsXmlDateTimeReader(QXmlStreamReader &reader, QVariant &val)
160 {
161 QString elmName = reader.name().toString();
162 QDateTime dt = QDateTime::fromString(reader.readElementText(), Qt::ISODate);
163 if (reader.error() != QXmlStreamReader::NoError || !dt.isValid()) {
164 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
165 return false;
166 }
167 val = QVariant::fromValue<QDateTime>(dt);
168 return true;
169 }
170
ewsXmlItemReader(QXmlStreamReader & reader,QVariant & val)171 bool ewsXmlItemReader(QXmlStreamReader &reader, QVariant &val)
172 {
173 QString elmName = reader.name().toString();
174 EwsItem item = EwsItem(reader);
175 if (!item.isValid()) {
176 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
177 reader.skipCurrentElement();
178 return false;
179 }
180 val = QVariant::fromValue(item);
181 return true;
182 }
183
ewsXmlFolderReader(QXmlStreamReader & reader,QVariant & val)184 bool ewsXmlFolderReader(QXmlStreamReader &reader, QVariant &val)
185 {
186 const QString elmName = reader.name().toString();
187 EwsFolder folder = EwsFolder(reader);
188 if (!folder.isValid()) {
189 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
190 reader.skipCurrentElement();
191 return false;
192 }
193 val = QVariant::fromValue(folder);
194 return true;
195 }
196
ewsXmlEnumReader(QXmlStreamReader & reader,QVariant & val,const QVector<QString> & items)197 bool ewsXmlEnumReader(QXmlStreamReader &reader, QVariant &val, const QVector<QString> &items)
198 {
199 const QString elmName = reader.name().toString();
200 QString text = reader.readElementText();
201 if (reader.error() != QXmlStreamReader::NoError) {
202 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
203 reader.skipCurrentElement();
204 return false;
205 }
206 int i = 0;
207 QVector<QString>::const_iterator it;
208 for (it = items.cbegin(); it != items.cend(); ++it, i++) {
209 if (text == *it) {
210 val = i;
211 break;
212 }
213 }
214
215 if (it == items.cend()) {
216 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown value %2.").arg(elmName, text);
217 return false;
218 }
219 return true;
220 }
221
ewsXmlSensitivityReader(QXmlStreamReader & reader,QVariant & val)222 bool ewsXmlSensitivityReader(QXmlStreamReader &reader, QVariant &val)
223 {
224 return ewsXmlEnumReader(reader, val, messageSensitivityNames);
225 }
226
ewsXmlImportanceReader(QXmlStreamReader & reader,QVariant & val)227 bool ewsXmlImportanceReader(QXmlStreamReader &reader, QVariant &val)
228 {
229 return ewsXmlEnumReader(reader, val, messageImportanceNames);
230 }
231
ewsXmlCalendarItemTypeReader(QXmlStreamReader & reader,QVariant & val)232 bool ewsXmlCalendarItemTypeReader(QXmlStreamReader &reader, QVariant &val)
233 {
234 return ewsXmlEnumReader(reader, val, calendarItemTypeNames);
235 }
236
ewsXmlLegacyFreeBusyStatusReader(QXmlStreamReader & reader,QVariant & val)237 bool ewsXmlLegacyFreeBusyStatusReader(QXmlStreamReader &reader, QVariant &val)
238 {
239 return ewsXmlEnumReader(reader, val, legacyFreeBusyStatusNames);
240 }
241
ewsXmlResponseTypeReader(QXmlStreamReader & reader,QVariant & val)242 bool ewsXmlResponseTypeReader(QXmlStreamReader &reader, QVariant &val)
243 {
244 return ewsXmlEnumReader(reader, val, responseTypeNames);
245 }
246
readXmlElementValue(QXmlStreamReader & reader,bool & ok,const QString & parentElement)247 template<> QString readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
248 {
249 ok = true;
250 QStringRef elmName = reader.name();
251 QString val = reader.readElementText();
252 if (reader.error() != QXmlStreamReader::NoError) {
253 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
254 reader.skipCurrentElement();
255 val.clear();
256 ok = false;
257 }
258
259 return val;
260 }
261
readXmlElementValue(QXmlStreamReader & reader,bool & ok,const QString & parentElement)262 template<> int readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
263 {
264 QStringRef elmName = reader.name();
265 QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
266 int val = 0;
267 if (ok) {
268 val = valStr.toInt(&ok);
269 if (!ok) {
270 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
271 }
272 }
273
274 return val;
275 }
276
readXmlElementValue(QXmlStreamReader & reader,bool & ok,const QString & parentElement)277 template<> long readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
278 {
279 QStringRef elmName = reader.name();
280 QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
281 long val = 0;
282 if (ok) {
283 val = valStr.toLong(&ok);
284 if (!ok) {
285 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
286 }
287 }
288
289 return val;
290 }
291
readXmlElementValue(QXmlStreamReader & reader,bool & ok,const QString & parentElement)292 template<> QDateTime readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
293 {
294 QStringRef elmName = reader.name();
295 QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
296 QDateTime val;
297 if (ok) {
298 val = QDateTime::fromString(valStr, Qt::ISODate);
299 if (!val.isValid()) {
300 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
301 ok = false;
302 }
303 }
304
305 return val;
306 }
307
readXmlElementValue(QXmlStreamReader & reader,bool & ok,const QString & parentElement)308 template<> bool readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
309 {
310 QStringRef elmName = reader.name();
311 QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
312 bool val = false;
313 if (ok) {
314 if (valStr == QLatin1String("true")) {
315 val = true;
316 } else if (valStr == QLatin1String("false")) {
317 val = false;
318 } else {
319 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
320 ok = false;
321 }
322 }
323
324 return val;
325 }
326
readXmlElementValue(QXmlStreamReader & reader,bool & ok,const QString & parentElement)327 template<> QByteArray readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
328 {
329 QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
330 QByteArray val;
331 if (ok) {
332 /* QByteArray::fromBase64() does not perform any input validity checks
333 and skips invalid input characters */
334 val = QByteArray::fromBase64(valStr.toLatin1());
335 }
336
337 return val;
338 }
339