File indexing completed on 2024-12-22 04:57:04

0001 /*
0002     SPDX-FileCopyrightText: 2015-2017 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ewsxml.h"
0008 
0009 #include <QDateTime>
0010 
0011 #include "ewsfolder.h"
0012 #include "ewsid.h"
0013 #include "ewsitem.h"
0014 
0015 static const QList<QString> messageSensitivityNames = {
0016     QStringLiteral("Normal"),
0017     QStringLiteral("Personal"),
0018     QStringLiteral("Private"),
0019     QStringLiteral("Confidential"),
0020 };
0021 
0022 static const QList<QString> messageImportanceNames = {QStringLiteral("Low"), QStringLiteral("Normal"), QStringLiteral("High")};
0023 
0024 static const QList<QString> calendarItemTypeNames = {
0025     QStringLiteral("Single"),
0026     QStringLiteral("Occurrence"),
0027     QStringLiteral("Exception"),
0028     QStringLiteral("RecurringMaster"),
0029 };
0030 
0031 static const QList<QString> legacyFreeBusyStatusNames = {
0032     QStringLiteral("Free"),
0033     QStringLiteral("Tentative"),
0034     QStringLiteral("Busy"),
0035     QStringLiteral("OOF"),
0036     QStringLiteral("NoData"),
0037 };
0038 
0039 static const QList<QString> responseTypeNames = {
0040     QStringLiteral("Unknown"),
0041     QStringLiteral("Organizer"),
0042     QStringLiteral("Tentative"),
0043     QStringLiteral("Accept"),
0044     QStringLiteral("Decline"),
0045     QStringLiteral("NoResponseReceived"),
0046 };
0047 
0048 bool ewsXmlBoolReader(QXmlStreamReader &reader, QVariant &val)
0049 {
0050     const QString elmText = reader.readElementText();
0051     if (reader.error() != QXmlStreamReader::NoError) {
0052         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading %1 element").arg(reader.name().toString());
0053         reader.skipCurrentElement();
0054         return false;
0055     }
0056     if (elmText == QLatin1StringView("true")) {
0057         val = true;
0058     } else if (elmText == QLatin1StringView("false")) {
0059         val = false;
0060     } else {
0061         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected invalid boolean value in %1 element:").arg(reader.name().toString()) << elmText;
0062         return false;
0063     }
0064 
0065     return true;
0066 }
0067 
0068 bool ewsXmlBoolWriter(QXmlStreamWriter &writer, const QVariant &val)
0069 {
0070     writer.writeCharacters(val.toBool() ? QStringLiteral("true") : QStringLiteral("false"));
0071 
0072     return true;
0073 }
0074 
0075 bool ewsXmlBase64Reader(QXmlStreamReader &reader, QVariant &val)
0076 {
0077     QString elmName = reader.name().toString();
0078     val = QByteArray::fromBase64(reader.readElementText().toLatin1());
0079     if (reader.error() != QXmlStreamReader::NoError) {
0080         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0081         reader.skipCurrentElement();
0082         return false;
0083     }
0084 
0085     return true;
0086 }
0087 
0088 bool ewsXmlBase64Writer(QXmlStreamWriter &writer, const QVariant &val)
0089 {
0090     writer.writeCharacters(QString::fromLatin1(val.toByteArray().toBase64()));
0091 
0092     return true;
0093 }
0094 
0095 bool ewsXmlIdReader(QXmlStreamReader &reader, QVariant &val)
0096 {
0097     QString elmName = reader.name().toString();
0098     EwsId id = EwsId(reader);
0099     if (id.type() == EwsId::Unspecified) {
0100         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0101         reader.skipCurrentElement();
0102         return false;
0103     }
0104     val = QVariant::fromValue(id);
0105     reader.skipCurrentElement();
0106     return true;
0107 }
0108 
0109 bool ewsXmlIdWriter(QXmlStreamWriter &writer, const QVariant &val)
0110 {
0111     EwsId id = val.value<EwsId>();
0112     if (id.type() == EwsId::Unspecified) {
0113         return false;
0114     }
0115 
0116     id.writeAttributes(writer);
0117 
0118     return true;
0119 }
0120 
0121 bool ewsXmlTextReader(QXmlStreamReader &reader, QVariant &val)
0122 {
0123     QString elmName = reader.name().toString();
0124     val = reader.readElementText();
0125     if (reader.error() != QXmlStreamReader::NoError) {
0126         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0127         reader.skipCurrentElement();
0128         return false;
0129     }
0130     return true;
0131 }
0132 
0133 bool ewsXmlTextWriter(QXmlStreamWriter &writer, const QVariant &val)
0134 {
0135     writer.writeCharacters(val.toString());
0136 
0137     return true;
0138 }
0139 
0140 bool ewsXmlUIntReader(QXmlStreamReader &reader, QVariant &val)
0141 {
0142     QString elmName = reader.name().toString();
0143     bool ok;
0144     val = reader.readElementText().toUInt(&ok);
0145     if (reader.error() != QXmlStreamReader::NoError || !ok) {
0146         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0147         return false;
0148     }
0149     return true;
0150 }
0151 
0152 bool ewsXmlUIntWriter(QXmlStreamWriter &writer, const QVariant &val)
0153 {
0154     writer.writeCharacters(QString::number(val.toUInt()));
0155 
0156     return true;
0157 }
0158 
0159 bool ewsXmlDateTimeReader(QXmlStreamReader &reader, QVariant &val)
0160 {
0161     QString elmName = reader.name().toString();
0162     QDateTime dt = QDateTime::fromString(reader.readElementText(), Qt::ISODate);
0163     if (reader.error() != QXmlStreamReader::NoError || !dt.isValid()) {
0164         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0165         return false;
0166     }
0167     val = QVariant::fromValue<QDateTime>(dt);
0168     return true;
0169 }
0170 
0171 bool ewsXmlItemReader(QXmlStreamReader &reader, QVariant &val)
0172 {
0173     QString elmName = reader.name().toString();
0174     EwsItem item = EwsItem(reader);
0175     if (!item.isValid()) {
0176         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0177         reader.skipCurrentElement();
0178         return false;
0179     }
0180     val = QVariant::fromValue(item);
0181     return true;
0182 }
0183 
0184 bool ewsXmlFolderReader(QXmlStreamReader &reader, QVariant &val)
0185 {
0186     const QString elmName = reader.name().toString();
0187     EwsFolder folder = EwsFolder(reader);
0188     if (!folder.isValid()) {
0189         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0190         reader.skipCurrentElement();
0191         return false;
0192     }
0193     val = QVariant::fromValue(folder);
0194     return true;
0195 }
0196 
0197 bool ewsXmlEnumReader(QXmlStreamReader &reader, QVariant &val, const QList<QString> &items)
0198 {
0199     const QString elmName = reader.name().toString();
0200     QString text = reader.readElementText();
0201     if (reader.error() != QXmlStreamReader::NoError) {
0202         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid content.").arg(elmName);
0203         reader.skipCurrentElement();
0204         return false;
0205     }
0206     int i = 0;
0207     QList<QString>::const_iterator it;
0208     for (it = items.cbegin(); it != items.cend(); ++it, i++) {
0209         if (text == *it) {
0210             val = i;
0211             break;
0212         }
0213     }
0214 
0215     if (it == items.cend()) {
0216         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown value %2.").arg(elmName, text);
0217         return false;
0218     }
0219     return true;
0220 }
0221 
0222 bool ewsXmlSensitivityReader(QXmlStreamReader &reader, QVariant &val)
0223 {
0224     return ewsXmlEnumReader(reader, val, messageSensitivityNames);
0225 }
0226 
0227 bool ewsXmlImportanceReader(QXmlStreamReader &reader, QVariant &val)
0228 {
0229     return ewsXmlEnumReader(reader, val, messageImportanceNames);
0230 }
0231 
0232 bool ewsXmlCalendarItemTypeReader(QXmlStreamReader &reader, QVariant &val)
0233 {
0234     return ewsXmlEnumReader(reader, val, calendarItemTypeNames);
0235 }
0236 
0237 bool ewsXmlLegacyFreeBusyStatusReader(QXmlStreamReader &reader, QVariant &val)
0238 {
0239     return ewsXmlEnumReader(reader, val, legacyFreeBusyStatusNames);
0240 }
0241 
0242 bool ewsXmlResponseTypeReader(QXmlStreamReader &reader, QVariant &val)
0243 {
0244     return ewsXmlEnumReader(reader, val, responseTypeNames);
0245 }
0246 
0247 template<>
0248 QString readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
0249 {
0250     ok = true;
0251     const QStringView elmName = reader.name();
0252     QString val = reader.readElementText();
0253     if (reader.error() != QXmlStreamReader::NoError) {
0254         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
0255         reader.skipCurrentElement();
0256         val.clear();
0257         ok = false;
0258     }
0259 
0260     return val;
0261 }
0262 
0263 template<>
0264 int readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
0265 {
0266     const QStringView elmName = reader.name();
0267     QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
0268     int val = 0;
0269     if (ok) {
0270         val = valStr.toInt(&ok);
0271         if (!ok) {
0272             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
0273         }
0274     }
0275 
0276     return val;
0277 }
0278 
0279 template<>
0280 long readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
0281 {
0282     const QStringView elmName = reader.name();
0283     QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
0284     long val = 0;
0285     if (ok) {
0286         val = valStr.toLong(&ok);
0287         if (!ok) {
0288             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
0289         }
0290     }
0291 
0292     return val;
0293 }
0294 
0295 template<>
0296 QDateTime readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
0297 {
0298     const QStringView elmName = reader.name();
0299     QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
0300     QDateTime val;
0301     if (ok) {
0302         val = QDateTime::fromString(valStr, Qt::ISODate);
0303         if (!val.isValid()) {
0304             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
0305             ok = false;
0306         }
0307     }
0308 
0309     return val;
0310 }
0311 
0312 template<>
0313 bool readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
0314 {
0315     const QStringView elmName = reader.name();
0316     QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
0317     bool val = false;
0318     if (ok) {
0319         if (valStr == QLatin1StringView("true")) {
0320             val = true;
0321         } else if (valStr == QLatin1StringView("false")) {
0322             val = false;
0323         } else {
0324             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElement, elmName.toString());
0325             ok = false;
0326         }
0327     }
0328 
0329     return val;
0330 }
0331 
0332 template<>
0333 QByteArray readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement)
0334 {
0335     QString valStr = readXmlElementValue<QString>(reader, ok, parentElement);
0336     QByteArray val;
0337     if (ok) {
0338         /* QByteArray::fromBase64() does not perform any input validity checks
0339            and skips invalid input characters */
0340         val = QByteArray::fromBase64(valStr.toLatin1());
0341     }
0342 
0343     return val;
0344 }