diff --git a/client/ews/ewsattendee.cpp b/client/ews/ewsattendee.cpp index 1d34d20..7be7212 100644 --- a/client/ews/ewsattendee.cpp +++ b/client/ews/ewsattendee.cpp @@ -1,127 +1,128 @@ /* SPDX-FileCopyrightText: 2015-2016 Krzysztof Nowicki SPDX-License-Identifier: LGPL-2.0-or-later */ #include "ewsattendee.h" #include #include #include "ewsclient_debug.h" #include "ewsmailbox.h" class EwsAttendeePrivate : public QSharedData { public: EwsAttendeePrivate(); virtual ~EwsAttendeePrivate(); bool mValid; EwsMailbox mMailbox; EwsEventResponseType mResponse; QDateTime mResponseTime; }; -static const QString responseTypeNames[] = {QStringLiteral("Unknown"), - QStringLiteral("Organizer"), - QStringLiteral("Tentative"), - QStringLiteral("Accept"), - QStringLiteral("Decline"), - QStringLiteral("NoResponseReceived")}; -constexpr unsigned responseTypeNameCount = sizeof(responseTypeNames) / sizeof(responseTypeNames[0]); +static constexpr auto responseTypeNames = std::to_array({ + QLatin1StringView("Unknown"), + QLatin1StringView("Organizer"), + QLatin1StringView("Tentative"), + QLatin1StringView("Accept"), + QLatin1StringView("Decline"), + QLatin1StringView("NoResponseReceived"), +}); EwsAttendeePrivate::EwsAttendeePrivate() : mValid(false) , mResponse(EwsEventResponseNotReceived) { } EwsAttendee::EwsAttendee() : d(new EwsAttendeePrivate()) { } EwsAttendee::EwsAttendee(QXmlStreamReader &reader) : d(new EwsAttendeePrivate()) { while (reader.readNextStartElement()) { if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in mailbox element:") << reader.namespaceUri(); return; } const QStringView readerName = reader.name(); if (readerName == QLatin1String("Mailbox")) { d->mMailbox = EwsMailbox(reader); if (!d->mMailbox.isValid()) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid attendee %1 element.").arg(readerName.toString()); return; } } else if (readerName == QLatin1String("ResponseType")) { bool ok; - d->mResponse = decodeEnumString(reader.readElementText(), responseTypeNames, responseTypeNameCount, &ok); + d->mResponse = decodeEnumString(reader.readElementText(), responseTypeNames, &ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid attendee %1 element.").arg(readerName.toString()); return; } } else if (readerName == QLatin1String("LastResponseTime")) { // Unsupported - ignore // qCWarningNC(EWSCLIENT_LOG) << QStringLiteral("Unsupported mailbox element %1").arg(reader.name().toString()); reader.skipCurrentElement(); } } d->mValid = true; } EwsAttendeePrivate::~EwsAttendeePrivate() { } EwsAttendee::EwsAttendee(const EwsAttendee &other) : d(other.d) { } EwsAttendee::EwsAttendee(EwsAttendee &&other) : d(std::move(other.d)) { } EwsAttendee::~EwsAttendee() { } EwsAttendee &EwsAttendee::operator=(const EwsAttendee &other) { d = other.d; return *this; } EwsAttendee &EwsAttendee::operator=(EwsAttendee &&other) { d = std::move(other.d); return *this; } bool EwsAttendee::isValid() const { return d->mValid; } const EwsMailbox &EwsAttendee::mailbox() const { return d->mMailbox; } EwsEventResponseType EwsAttendee::response() const { return d->mResponse; } QDateTime EwsAttendee::responseTime() const { return d->mResponseTime; } diff --git a/client/ews/ewspropertyfield.cpp b/client/ews/ewspropertyfield.cpp index 910f87e..e8e532e 100644 --- a/client/ews/ewspropertyfield.cpp +++ b/client/ews/ewspropertyfield.cpp @@ -1,622 +1,622 @@ /* SPDX-FileCopyrightText: 2015-2017 Krzysztof Nowicki SPDX-License-Identifier: LGPL-2.0-or-later */ #include "ewspropertyfield.h" #include #include "ewsclient_debug.h" -static const QString distinguishedPropSetIdNames[] = { - QStringLiteral("Meeting"), - QStringLiteral("Appointment"), - QStringLiteral("Common"), - QStringLiteral("PublicStrings"), - QStringLiteral("Address"), - QStringLiteral("InternetHeaders"), - QStringLiteral("CalendarAssistant"), - QStringLiteral("UnifiedMessaging"), -}; - -static const QString propertyTypeNames[] = { - QStringLiteral("ApplicationTime"), - QStringLiteral("ApplicationTimeArray"), - QStringLiteral("Binary"), - QStringLiteral("BinaryArray"), - QStringLiteral("Boolean"), - QStringLiteral("CLSID"), - QStringLiteral("CLSIDArray"), - QStringLiteral("Currency"), - QStringLiteral("CurrencyArray"), - QStringLiteral("Double"), - QStringLiteral("DoubleArray"), - QStringLiteral("Error"), - QStringLiteral("Float"), - QStringLiteral("FloatArray"), - QStringLiteral("Integer"), - QStringLiteral("IntegerArray"), - QStringLiteral("Long"), - QStringLiteral("LongArray"), - QStringLiteral("Null"), - QStringLiteral("Object"), - QStringLiteral("ObjectArray"), - QStringLiteral("Short"), - QStringLiteral("ShortArray"), - QStringLiteral("SystemTime"), - QStringLiteral("SystemTimeArray"), - QStringLiteral("String"), - QStringLiteral("StringArray"), -}; +static constexpr auto distinguishedPropSetIdNames = std::to_array({ + QLatin1StringView("Meeting"), + QLatin1StringView("Appointment"), + QLatin1StringView("Common"), + QLatin1StringView("PublicStrings"), + QLatin1StringView("Address"), + QLatin1StringView("InternetHeaders"), + QLatin1StringView("CalendarAssistant"), + QLatin1StringView("UnifiedMessaging"), +}); + +static constexpr auto propertyTypeNames = std::to_array({ + QLatin1StringView("ApplicationTime"), + QLatin1StringView("ApplicationTimeArray"), + QLatin1StringView("Binary"), + QLatin1StringView("BinaryArray"), + QLatin1StringView("Boolean"), + QLatin1StringView("CLSID"), + QLatin1StringView("CLSIDArray"), + QLatin1StringView("Currency"), + QLatin1StringView("CurrencyArray"), + QLatin1StringView("Double"), + QLatin1StringView("DoubleArray"), + QLatin1StringView("Error"), + QLatin1StringView("Float"), + QLatin1StringView("FloatArray"), + QLatin1StringView("Integer"), + QLatin1StringView("IntegerArray"), + QLatin1StringView("Long"), + QLatin1StringView("LongArray"), + QLatin1StringView("Null"), + QLatin1StringView("Object"), + QLatin1StringView("ObjectArray"), + QLatin1StringView("Short"), + QLatin1StringView("ShortArray"), + QLatin1StringView("SystemTime"), + QLatin1StringView("SystemTimeArray"), + QLatin1StringView("String"), + QLatin1StringView("StringArray"), +}); class EwsPropertyFieldPrivate : public QSharedData { public: EwsPropertyFieldPrivate() : mPropType(EwsPropertyField::UnknownField) , mIndex(0) , mPsIdType(DistinguishedPropSet) , mPsDid(EwsPropSetMeeting) , mIdType(PropName) , mId(0) , mHasTag(false) , mTag(0) , mType(EwsPropTypeNull) , mHash(0) { } enum PropSetIdType { DistinguishedPropSet, RealPropSet, }; enum PropIdType { PropName, PropId, }; EwsPropertyField::Type mPropType; QString mUri; unsigned mIndex; PropSetIdType mPsIdType; EwsDistinguishedPropSetId mPsDid; QString mPsId; PropIdType mIdType; unsigned mId; QString mName; bool mHasTag; unsigned mTag; EwsPropertyType mType; uint mHash; // Precalculated hash for the qHash() function. void recalcHash(); }; void EwsPropertyFieldPrivate::recalcHash() { mHash = 0; switch (mPropType) { case EwsPropertyField::Field: mHash = 0x00000000 | (qHash(mUri) & 0x3FFFFFFF); break; case EwsPropertyField::IndexedField: mHash = 0x80000000 | ((qHash(mUri) ^ mIndex) & 0x3FFFFFFF); break; case EwsPropertyField::ExtendedField: if (mHasTag) { mHash = 0x40000000 | mTag; } else { if (mPsIdType == DistinguishedPropSet) { mHash |= mPsDid << 16; } else { mHash |= (qHash(mPsId) & 0x1FFF) << 16; } if (mIdType == PropId) { mHash |= mId & 0xFFFF; } else { mHash |= (qHash(mName) & 0xFFFF); } mHash |= 0xC0000000; } break; default: break; } } EwsPropertyField::EwsPropertyField() : d(new EwsPropertyFieldPrivate()) { } EwsPropertyField::EwsPropertyField(const QString &uri) : d(new EwsPropertyFieldPrivate()) { d->mPropType = Field; d->mUri = uri; d->recalcHash(); } EwsPropertyField::EwsPropertyField(const QString &uri, unsigned index) : d(new EwsPropertyFieldPrivate()) { d->mPropType = IndexedField; d->mUri = uri; d->mIndex = index; d->recalcHash(); } EwsPropertyField::EwsPropertyField(EwsDistinguishedPropSetId psid, unsigned id, EwsPropertyType type) : d(new EwsPropertyFieldPrivate()) { d->mPropType = ExtendedField; d->mPsIdType = EwsPropertyFieldPrivate::DistinguishedPropSet; d->mPsDid = psid; d->mIdType = EwsPropertyFieldPrivate::PropId; d->mId = id; d->mType = type; d->recalcHash(); } EwsPropertyField::EwsPropertyField(EwsDistinguishedPropSetId psid, const QString &name, EwsPropertyType type) : d(new EwsPropertyFieldPrivate()) { d->mPropType = ExtendedField; d->mPsIdType = EwsPropertyFieldPrivate::DistinguishedPropSet; d->mPsDid = psid; d->mIdType = EwsPropertyFieldPrivate::PropName; d->mName = name; d->mType = type; d->recalcHash(); } EwsPropertyField::EwsPropertyField(const QString &psid, unsigned id, EwsPropertyType type) : d(new EwsPropertyFieldPrivate()) { d->mPropType = ExtendedField; d->mPsIdType = EwsPropertyFieldPrivate::RealPropSet; d->mPsId = psid; d->mIdType = EwsPropertyFieldPrivate::PropId; d->mId = id; d->mType = type; d->recalcHash(); } EwsPropertyField::EwsPropertyField(const QString &psid, const QString &name, EwsPropertyType type) : d(new EwsPropertyFieldPrivate()) { d->mPropType = ExtendedField; d->mPsIdType = EwsPropertyFieldPrivate::RealPropSet; d->mPsId = psid; d->mIdType = EwsPropertyFieldPrivate::PropName; d->mName = name; d->mType = type; d->recalcHash(); } EwsPropertyField::EwsPropertyField(unsigned tag, EwsPropertyType type) : d(new EwsPropertyFieldPrivate()) { d->mPropType = ExtendedField; d->mHasTag = true; d->mTag = tag; d->mType = type; d->recalcHash(); } EwsPropertyField::EwsPropertyField(const EwsPropertyField &other) : d(other.d) { } EwsPropertyField::EwsPropertyField(EwsPropertyField &&other) : d(other.d) { } EwsPropertyField &EwsPropertyField::operator=(EwsPropertyField &&other) { d = other.d; return *this; } EwsPropertyField::~EwsPropertyField() { } EwsPropertyField &EwsPropertyField::operator=(const EwsPropertyField &other) { d = other.d; return *this; } bool EwsPropertyField::operator==(const EwsPropertyField &other) const { if (d == other.d) { return true; } const EwsPropertyFieldPrivate *od = other.d; if (d->mPropType != od->mPropType) { return false; } switch (d->mPropType) { case UnknownField: return true; case Field: return d->mUri == od->mUri; case IndexedField: return (d->mUri == od->mUri) && (d->mIndex == od->mIndex); case ExtendedField: if (d->mType != od->mType) { return false; } if (d->mHasTag != od->mHasTag) { return false; } else if (d->mHasTag) { return d->mTag == od->mTag; } if (d->mPsIdType != od->mPsIdType) { return false; } else if ((d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) && (d->mPsDid != od->mPsDid)) { return false; } else if ((d->mPsIdType == EwsPropertyFieldPrivate::RealPropSet) && (d->mPsId != od->mPsId)) { return false; } if (d->mIdType != od->mIdType) { return false; } else if ((d->mIdType == EwsPropertyFieldPrivate::PropId) && (d->mId != od->mId)) { return false; } else if ((d->mIdType == EwsPropertyFieldPrivate::PropName) && (d->mName != od->mName)) { return false; } return true; default: return false; } // Shouldn't get here. return false; } void EwsPropertyField::write(QXmlStreamWriter &writer) const { switch (d->mPropType) { case Field: writer.writeStartElement(ewsTypeNsUri, QStringLiteral("FieldURI")); writer.writeAttribute(QStringLiteral("FieldURI"), d->mUri); writer.writeEndElement(); break; case IndexedField: { writer.writeStartElement(ewsTypeNsUri, QStringLiteral("IndexedFieldURI")); writer.writeAttribute(QStringLiteral("FieldURI"), d->mUri); QStringList tokens = d->mUri.split(QLatin1Char(':')); writer.writeAttribute(QStringLiteral("FieldIndex"), tokens[1] + QString::number(d->mIndex)); writer.writeEndElement(); break; } case ExtendedField: writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ExtendedFieldURI")); if (d->mHasTag) { writer.writeAttribute(QStringLiteral("PropertyTag"), QStringLiteral("0x") + QString::number(d->mTag, 16)); } else { if (d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) { writer.writeAttribute(QStringLiteral("DistinguishedPropertySetId"), distinguishedPropSetIdNames[d->mPsDid]); } else { writer.writeAttribute(QStringLiteral("PropertySetId"), d->mPsId); } if (d->mIdType == EwsPropertyFieldPrivate::PropId) { writer.writeAttribute(QStringLiteral("PropertyId"), QString::number(d->mId)); } else { writer.writeAttribute(QStringLiteral("PropertyName"), d->mName); } } writer.writeAttribute(QStringLiteral("PropertyType"), propertyTypeNames[d->mType]); writer.writeEndElement(); break; case UnknownField: break; } } bool EwsPropertyField::read(QXmlStreamReader &reader) { if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - invalid namespace."); return false; } QXmlStreamAttributes attrs = reader.attributes(); bool ok; // First check the property type if (reader.name() == QLatin1String("FieldURI")) { if (!attrs.hasAttribute(QStringLiteral("FieldURI"))) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldURI")); return false; } d->mPropType = Field; d->mUri = attrs.value(QStringLiteral("FieldURI")).toString(); } else if (reader.name() == QLatin1String("IndexedFieldURI")) { if (!attrs.hasAttribute(QStringLiteral("FieldURI"))) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldURI")); return false; } if (!attrs.hasAttribute(QStringLiteral("FieldIndex"))) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldIndex")); return false; } QString uri = attrs.value(QStringLiteral("FieldURI")).toString(); QStringList tokens = uri.split(QLatin1Char(':')); QString indexStr = attrs.value(QStringLiteral("FieldIndex")).toString(); if (!indexStr.startsWith(tokens[1])) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - malformed %1 attribute.").arg(QStringLiteral("FieldIndex")); return false; } unsigned index = QStringView(indexStr).mid(tokens[1].size()).toUInt(&ok, 0); if (!ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("FieldIndex")); return false; } d->mPropType = IndexedField; d->mUri = uri; d->mIndex = index; } else if (reader.name() == QLatin1String("ExtendedFieldURI")) { if (!attrs.hasAttribute(QStringLiteral("PropertyType"))) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("PropertyType")); return false; } auto propTypeText = attrs.value(QStringLiteral("PropertyType")); unsigned i; EwsPropertyType propType; for (i = 0; i < sizeof(propertyTypeNames) / sizeof(propertyTypeNames[0]); ++i) { if (propTypeText == propertyTypeNames[i]) { propType = static_cast(i); break; } } if (i == sizeof(propertyTypeNames) / sizeof(propertyTypeNames[0])) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyType")); return false; } if (attrs.hasAttribute(QStringLiteral("PropertyTag"))) { unsigned tag = attrs.value(QStringLiteral("PropertyTag")).toUInt(&ok, 0); if (!ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyTag")); return false; } d->mHasTag = true; d->mTag = tag; } else { EwsPropertyFieldPrivate::PropSetIdType psIdType = EwsPropertyFieldPrivate::DistinguishedPropSet; EwsDistinguishedPropSetId psDid = EwsPropSetMeeting; QString psId; EwsPropertyFieldPrivate::PropIdType idType = EwsPropertyFieldPrivate::PropName; unsigned id = 0; QString name; if (attrs.hasAttribute(QStringLiteral("PropertyId"))) { id = attrs.value(QStringLiteral("PropertyId")).toUInt(&ok, 0); if (!ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyId")); return false; } idType = EwsPropertyFieldPrivate::PropId; } else if (attrs.hasAttribute(QStringLiteral("PropertyName"))) { name = attrs.value(QStringLiteral("PropertyName")).toString(); idType = EwsPropertyFieldPrivate::PropName; } else { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing one of %1 or %2 attributes.") .arg(QStringLiteral("PropertyId").arg(QStringLiteral("PropertyName"))); return false; } if (attrs.hasAttribute(QStringLiteral("DistinguishedPropertySetId"))) { auto didText = attrs.value(QStringLiteral("DistinguishedPropertySetId")); unsigned i; for (i = 0; i < sizeof(distinguishedPropSetIdNames) / sizeof(distinguishedPropSetIdNames[0]); ++i) { if (didText == distinguishedPropSetIdNames[i]) { psDid = static_cast(i); break; } } if (i == sizeof(distinguishedPropSetIdNames) / sizeof(distinguishedPropSetIdNames[0])) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("DistinguishedPropertySetId")); return false; } psIdType = EwsPropertyFieldPrivate::DistinguishedPropSet; } else if (attrs.hasAttribute(QStringLiteral("PropertySetId"))) { psId = attrs.value(QStringLiteral("PropertySetId")).toString(); psIdType = EwsPropertyFieldPrivate::RealPropSet; } else { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing one of %1 or %2 attributes.") .arg(QStringLiteral("DistinguishedPropertySetId").arg(QStringLiteral("PropertySetId"))); return false; } d->mPsIdType = psIdType; d->mPsDid = psDid; d->mPsId = psId; d->mIdType = idType; d->mId = id; d->mName = name; } d->mType = propType; d->mPropType = ExtendedField; } d->recalcHash(); return true; } uint qHash(const EwsPropertyField &prop, uint seed) { return prop.d->mHasTag ^ seed; } QDebug operator<<(QDebug debug, const EwsPropertyField &prop) { QDebugStateSaver saver(debug); QDebug d = debug.nospace().noquote(); d << QStringLiteral("EwsPropertyField("); switch (prop.d->mPropType) { case EwsPropertyField::Field: d << QStringLiteral("FieldUri: ") << prop.d->mUri; break; case EwsPropertyField::IndexedField: d << QStringLiteral("IndexedFieldUri: ") << prop.d->mUri << '@' << prop.d->mIndex; break; case EwsPropertyField::ExtendedField: d << QStringLiteral("ExtendedFieldUri: "); if (prop.d->mHasTag) { d << QStringLiteral("tag: 0x") << QString::number(prop.d->mTag, 16); } else { if (prop.d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) { d << QStringLiteral("psdid: ") << distinguishedPropSetIdNames[prop.d->mPsDid]; } else { d << QStringLiteral("psid: ") << prop.d->mPsId; } d << QStringLiteral(", "); if (prop.d->mIdType == EwsPropertyFieldPrivate::PropId) { d << QStringLiteral("id: 0x") << QString::number(prop.d->mId, 16); } else { d << QStringLiteral("name: ") << prop.d->mName; } } d << QStringLiteral(", type: ") << propertyTypeNames[prop.d->mType]; break; case EwsPropertyField::UnknownField: d << QStringLiteral("Unknown"); break; } d << ')'; return debug; } bool EwsPropertyField::writeWithValue(QXmlStreamWriter &writer, const QVariant &value) const { switch (d->mPropType) { case Field: { QStringList tokens = d->mUri.split(QLatin1Char(':')); if (tokens.size() != 2) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Invalid field URI: %1").arg(d->mUri); return false; } writer.writeStartElement(ewsTypeNsUri, tokens[1]); writeValue(writer, value); writer.writeEndElement(); break; } case IndexedField: { QStringList tokens = d->mUri.split(QLatin1Char(':')); if (tokens.size() != 2) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Invalid field URI: %1").arg(d->mUri); return false; } writer.writeStartElement(ewsTypeNsUri, tokens[1] + QStringLiteral("es")); writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Entry")); writer.writeAttribute(QStringLiteral("Key"), tokens[1] + QString::number(d->mIndex)); writeValue(writer, value); writer.writeEndElement(); writer.writeEndElement(); break; } case ExtendedField: writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ExtendedProperty")); write(writer); writeExtendedValue(writer, value); writer.writeEndElement(); break; default: return false; } return true; } void EwsPropertyField::writeValue(QXmlStreamWriter &writer, const QVariant &value) const { switch (value.userType()) { case QMetaType::QStringList: { const QStringList list = value.toStringList(); for (const QString &str : list) { writer.writeTextElement(ewsTypeNsUri, QStringLiteral("String"), str); } break; } case QMetaType::QString: writer.writeCharacters(value.toString()); break; default: qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown variant type to write: %1").arg(QString::fromLatin1(value.typeName())); } } void EwsPropertyField::writeExtendedValue(QXmlStreamWriter &writer, const QVariant &value) const { switch (value.userType()) { case QMetaType::QStringList: { const QStringList list = value.toStringList(); writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Values")); for (const QString &str : list) { writer.writeTextElement(ewsTypeNsUri, QStringLiteral("Value"), str); } writer.writeEndElement(); break; } case QMetaType::QString: writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Value")); writer.writeCharacters(value.toString()); writer.writeEndElement(); break; default: qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown variant type to write: %1").arg(QString::fromLatin1(value.typeName())); } } EwsPropertyField::Type EwsPropertyField::type() const { return d->mPropType; } QString EwsPropertyField::uri() const { if (d->mPropType == Field || d->mPropType == IndexedField) { return d->mUri; } else { return QString(); } } diff --git a/client/ews/ewsrecurrence.cpp b/client/ews/ewsrecurrence.cpp index 1ff7f74..f3e4236 100644 --- a/client/ews/ewsrecurrence.cpp +++ b/client/ews/ewsrecurrence.cpp @@ -1,532 +1,529 @@ /* SPDX-FileCopyrightText: 2015-2017 Krzysztof Nowicki SPDX-License-Identifier: LGPL-2.0-or-later */ #include "ewsrecurrence.h" #include #include #include #include "ewsclient_debug.h" #include "ewstypes.h" using namespace KCalendarCore; -static const QString dayOfWeekNames[] = { - QStringLiteral("Monday"), - QStringLiteral("Tuesday"), - QStringLiteral("Wednesday"), - QStringLiteral("Thursday"), - QStringLiteral("Friday"), - QStringLiteral("Saturday"), - QStringLiteral("Sunday"), - QStringLiteral("Day"), - QStringLiteral("Weekday"), - QStringLiteral("WeekendDay"), -}; -constexpr unsigned dayOfWeekNameCount = sizeof(dayOfWeekNames) / sizeof(dayOfWeekNames[0]); - -static const QString dayOfWeekIndexNames[] = { - QStringLiteral("First"), - QStringLiteral("Second"), - QStringLiteral("Third"), - QStringLiteral("Fourth"), - QStringLiteral("Last"), -}; -constexpr unsigned dayOfWeekIndexNameCount = sizeof(dayOfWeekIndexNames) / sizeof(dayOfWeekIndexNames[0]); - -static const QString monthNames[] = { - QStringLiteral("January"), - QStringLiteral("February"), - QStringLiteral("March"), - QStringLiteral("April"), - QStringLiteral("May"), - QStringLiteral("June"), - QStringLiteral("July"), - QStringLiteral("August"), - QStringLiteral("September"), - QStringLiteral("October"), - QStringLiteral("November"), - QStringLiteral("December"), -}; -constexpr unsigned monthNameCount = sizeof(monthNames) / sizeof(monthNames[0]); +static constexpr auto dayOfWeekNames = std::to_array({ + QLatin1StringView("Monday"), + QLatin1StringView("Tuesday"), + QLatin1StringView("Wednesday"), + QLatin1StringView("Thursday"), + QLatin1StringView("Friday"), + QLatin1StringView("Saturday"), + QLatin1StringView("Sunday"), + QLatin1StringView("Day"), + QLatin1StringView("Weekday"), + QLatin1StringView("WeekendDay"), +}); + +static constexpr auto dayOfWeekIndexNames = std::to_array({ + QLatin1StringView("First"), + QLatin1StringView("Second"), + QLatin1StringView("Third"), + QLatin1StringView("Fourth"), + QLatin1StringView("Last"), +}); + +static constexpr auto monthNames = std::to_array({ + QLatin1StringView("January"), + QLatin1StringView("February"), + QLatin1StringView("March"), + QLatin1StringView("April"), + QLatin1StringView("May"), + QLatin1StringView("June"), + QLatin1StringView("July"), + QLatin1StringView("August"), + QLatin1StringView("September"), + QLatin1StringView("October"), + QLatin1StringView("November"), + QLatin1StringView("December"), +}); EwsRecurrence::EwsRecurrence() : Recurrence() { } EwsRecurrence::EwsRecurrence(QXmlStreamReader &reader) { while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return; } if (elmName == QLatin1String("RelativeYearlyRecurrence")) { if (!readRelativeYearlyRecurrence(reader)) { return; } } else if (elmName == QLatin1String("AbsoluteYearlyRecurrence")) { if (!readAbsoluteYearlyRecurrence(reader)) { return; } } else if (elmName == QLatin1String("RelativeMonthlyRecurrence")) { if (!readRelativeMonthlyRecurrence(reader)) { return; } } else if (elmName == QLatin1String("AbsoluteMonthlyRecurrence")) { if (!readAbsoluteMonthlyRecurrence(reader)) { return; } } else if (elmName == QLatin1String("WeeklyRecurrence")) { if (!readWeeklyRecurrence(reader)) { return; } } else if (elmName == QLatin1String("DailyRecurrence")) { if (!readWeeklyRecurrence(reader)) { return; } } else if (elmName == QLatin1String("NoEndRecurrence")) { // Ignore - this is the default reader.skipCurrentElement(); } else if (elmName == QLatin1String("EndDateRecurrence")) { if (!readEndDateRecurrence(reader)) { return; } } else if (elmName == QLatin1String("NumberedRecurrence")) { if (!readNumberedRecurrence(reader)) { return; } } else { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown element: %2.").arg(QStringLiteral("Recurrence"), elmName); return; } } } EwsRecurrence::EwsRecurrence(const EwsRecurrence &other) : Recurrence(other) { } bool EwsRecurrence::readRelativeYearlyRecurrence(QXmlStreamReader &reader) { QBitArray dow(7); short dowWeekIndex = 0; short month = 0; bool hasDow = false; bool hasDowWeekIndex = false; bool hasMonth = false; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("DaysOfWeek")) { if (!readDow(reader, dow)) { return false; } hasDow = true; } else if (elmName == QLatin1String("DayOfWeekIndex")) { bool ok; QString text = reader.readElementText(); - dowWeekIndex = decodeEnumString(text, dayOfWeekIndexNames, dayOfWeekIndexNameCount, &ok); + dowWeekIndex = decodeEnumString(text, dayOfWeekIndexNames, &ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("DayOfWeekIndex").arg(text)); return false; } if (dowWeekIndex == 4) { // "Last" dowWeekIndex = -1; } hasDowWeekIndex = true; } else if (elmName == QLatin1String("Month")) { bool ok; QString text = reader.readElementText(); - month = decodeEnumString(text, monthNames, monthNameCount, &ok); + month = decodeEnumString(text, monthNames, &ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("Month"), text); return false; } hasMonth = true; } else { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown element: %2.").arg(QStringLiteral("RelativeYearlyRecurrence"), elmName); return false; } } if (!hasMonth || !hasDow || !hasDowWeekIndex) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - expected all of Month, DaysOfWeek and DayOfWeekIndex elements."); return false; } addYearlyMonth(month); addYearlyPos(dowWeekIndex, dow); return true; } bool EwsRecurrence::readAbsoluteYearlyRecurrence(QXmlStreamReader &reader) { short dom = 0; short month = 0; bool hasDom = false; bool hasMonth = false; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("DayOfMonth")) { bool ok; QString text = reader.readElementText(); dom = text.toShort(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("DayOfMonth").arg(text)); return false; } hasDom = true; } else if (elmName == QLatin1String("Month")) { bool ok; QString text = reader.readElementText(); - month = decodeEnumString(text, monthNames, monthNameCount, &ok); + month = decodeEnumString(text, monthNames, &ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("Month").arg(text)); return false; } hasMonth = true; } else { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read recurrence element - unknown element: %1.").arg(elmName); return false; } } if (!hasDom || !hasMonth) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read recurrence element - need both month and dom values."); return false; } // "If for a particular month this value is larger than the number of days in the month, // the last day of the month is assumed for this property." QDate date(2000, month, 1); if (dom > date.daysInMonth()) { dom = -1; } addYearlyMonth(month); addYearlyDay(dom); return true; } bool EwsRecurrence::readRelativeMonthlyRecurrence(QXmlStreamReader &reader) { QBitArray dow(7); short dowWeekIndex = 0; int interval = 0; bool hasDow = false; bool hasDowWeekIndex = false; bool hasInterval = false; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("Interval")) { bool ok; QString text = reader.readElementText(); interval = text.toInt(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("Interval").arg(text)); return false; } hasInterval = true; } else if (elmName == QLatin1String("DaysOfWeek")) { if (!readDow(reader, dow)) { return false; } hasDow = true; } else if (elmName == QLatin1String("DayOfWeekIndex")) { bool ok; QString text = reader.readElementText(); - dowWeekIndex = decodeEnumString(text, dayOfWeekIndexNames, dayOfWeekIndexNameCount, &ok); + dowWeekIndex = decodeEnumString(text, dayOfWeekIndexNames, &ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("DayOfWeekIndex").arg(text)); return false; } if (dowWeekIndex == 4) { // "Last" dowWeekIndex = -1; } hasDowWeekIndex = true; } else { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - unknown element: %1.").arg(elmName); return false; } } if (!hasInterval || !hasDow || !hasDowWeekIndex) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - expected all of Interval, DaysOfWeek and DayOfWeekIndex elements."); return false; } addMonthlyPos(dowWeekIndex, dow); setFrequency(interval); return true; } bool EwsRecurrence::readAbsoluteMonthlyRecurrence(QXmlStreamReader &reader) { short dom = 0; int interval = 0; bool hasInterval = false; bool hasDom = false; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("Interval")) { bool ok; QString text = reader.readElementText(); interval = text.toInt(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("Interval").arg(text)); return false; } hasInterval = true; } else if (elmName == QLatin1String("DayOfMonth")) { bool ok; QString text = reader.readElementText(); dom = text.toShort(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("DayOfMonth").arg(text)); return false; } hasDom = true; } else { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - unknown element: %1.").arg(elmName); return false; } } if (!hasInterval || !hasDom) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - expected both Interval and DayOfMonth."); return false; } addMonthlyDate(dom); setFrequency(interval); return true; } bool EwsRecurrence::readWeeklyRecurrence(QXmlStreamReader &reader) { int interval = 1; QBitArray dow(7); int weekStart = 0; bool hasInterval = false; bool hasDow = false; bool hasWeekStart = false; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("Interval")) { bool ok; QString text = reader.readElementText(); interval = text.toInt(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("Interval").arg(text)); return false; } hasInterval = true; } else if (elmName == QLatin1String("DaysOfWeek")) { if (!readDow(reader, dow)) { return false; } hasDow = true; } else if (elmName == QLatin1String("FirstDayOfWeek")) { bool ok; QString text = reader.readElementText(); - weekStart = decodeEnumString(text, dayOfWeekNames, dayOfWeekNameCount, &ok) + 1; + weekStart = decodeEnumString(text, dayOfWeekNames, &ok) + 1; if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("FirstDayOfWeek").arg(text)); return false; } hasWeekStart = true; } else { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown element: %2.").arg(QStringLiteral("WeeklyRecurrence"), elmName); return false; } } if (!hasInterval || !hasDow || !hasWeekStart) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - expected all of Interval, DaysOfWeek and FirstDatOfWeek elements."); return false; } setWeekly(interval, dow, weekStart); return true; } bool EwsRecurrence::readDailyRecurrence(QXmlStreamReader &reader) { int interval = 1; bool hasInterval = false; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("Interval")) { bool ok; QString text = reader.readElementText(); interval = text.toInt(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("Interval").arg(text)); return false; } hasInterval = true; } else { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read recurrence element - unknown element: %1.").arg(elmName); return false; } } if (!hasInterval) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read Recurrence element - expected an Interval element."); return false; } setDaily(interval); return true; } bool EwsRecurrence::readEndDateRecurrence(QXmlStreamReader &reader) { QDate dateEnd; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("EndDate")) { QString text = reader.readElementText(); dateEnd = QDate::fromString(text, Qt::ISODate); if (reader.error() != QXmlStreamReader::NoError || !dateEnd.isValid()) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("EndDate").arg(text)); return false; } } else if (elmName == QLatin1String("StartDate")) { // Don't care reader.skipCurrentElement(); } else { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown element: %2.").arg(QStringLiteral("EndDateRecurrence"), elmName); return false; } } setEndDate(dateEnd); return true; } bool EwsRecurrence::readNumberedRecurrence(QXmlStreamReader &reader) { int numOccurrences = 0; while (reader.readNextStartElement()) { QString elmName = reader.name().toString(); if (reader.namespaceUri() != ewsTypeNsUri) { qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in %1 element:").arg(elmName) << reader.namespaceUri(); return false; } if (elmName == QLatin1String("NumberOfOccurrences")) { bool ok; QString text = reader.readElementText(); numOccurrences = text.toInt(&ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("NumberOfOccurrences").arg(text)); return false; } } else if (elmName == QLatin1String("StartDate")) { // Don't care reader.skipCurrentElement(); } else { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read recurrence element - unknown element: %1.").arg(elmName); return false; } } setDuration(numOccurrences); return true; } bool EwsRecurrence::readDow(QXmlStreamReader &reader, QBitArray &dow) { bool ok; QString text = reader.readElementText(); const QStringList days = text.split(QLatin1Char(' ')); for (const QString &day : days) { - auto dowIndex = decodeEnumString(day, dayOfWeekNames, dayOfWeekNameCount, &ok); + auto dowIndex = decodeEnumString(day, dayOfWeekNames, &ok); if (reader.error() != QXmlStreamReader::NoError || !ok) { qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read EWS request - invalid %1 element (value: %2).").arg(QStringLiteral("DaysOfWeek").arg(day)); return false; } if (dowIndex == 7) { // "Day" dow.fill(true, 0, 7); } else if (dowIndex == 8) { // "Weekday" dow.fill(true, 0, 5); } else if (dowIndex == 9) { // "WeekendDay" dow.fill(true, 5, 7); } else { dow.setBit(dowIndex); } } return true; } diff --git a/client/ews/ewstypes.h b/client/ews/ewstypes.h index 0f7bfe3..e3bd4fd 100644 --- a/client/ews/ewstypes.h +++ b/client/ews/ewstypes.h @@ -1,489 +1,489 @@ /* SPDX-FileCopyrightText: 2015-2019 Krzysztof Nowicki SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once class QString; #include extern const QString soapEnvNsUri; extern const QString ewsMsgNsUri; extern const QString ewsTypeNsUri; typedef enum { EwsFolderTypeMail = 0, EwsFolderTypeCalendar, EwsFolderTypeContacts, EwsFolderTypeSearch, EwsFolderTypeTasks, EwsFolderTypeUnknown, } EwsFolderType; typedef enum { EwsResponseSuccess = 0, EwsResponseWarning, EwsResponseError, EwsResponseParseError, // Internal - never returned by an Exchange server EwsResponseUnknown // Internal - never returned by an Exchange server } EwsResponseClass; typedef enum { EwsDIdCalendar = 0, EwsDIdContacts, EwsDIdDeletedItems, EwsDIdDrafts, EwsDIdInbox, EwsDIdJournal, EwsDIdNotes, EwsDIdOutbox, EwsDIdSentItems, EwsDIdTasks, EwsDIdMsgFolderRoot, EwsDIdRoot, EwsDIdJunkEmail, EwsDIdSearchFolders, EwsDIdVoiceMail, EwsDIdRecoverableItemsRoot, EwsDIdRecoverableItemsDeletions, EwsDIdRecoverableItemsVersions, EwsDIdRecoverableItemsPurges, EwsDIdArchiveRoot, EwsDIdArchiveMsgFolderRoot, EwsDIdArchiveDeletedItems, EwsDIdArchiveRecoverableItemsRoot, EwsDIdArchiveRecoverableItemsDeletions, EwsDIdArchiveRecoverableItemsVersions, EwsDIdArchiveRecoverableItemsPurges } EwsDistinguishedId; typedef enum { EwsShapeIdOnly = 0, EwsShapeDefault, EwsShapeAllProperties } EwsBaseShape; typedef enum { EwsPropSetMeeting = 0, EwsPropSetAppointment, EwsPropSetCommon, EwsPropSetPublicStrings, EwsPropSetAddress, EwsPropSetInternetHeaders, EwsPropSetCalendarAssistant, EwsPropSetUnifiedMessaging } EwsDistinguishedPropSetId; typedef enum { EwsPropTypeApplicationTime = 0, EwsPropTypeApplicationTimeArray, EwsPropTypeBinary, EwsPropTypeBinaryArray, EwsPropTypeBoolean, EwsPropTypeCLSID, EwsPropTypeCLSIDArray, EwsPropTypeCurrency, EwsPropTypeCurrencyArray, EwsPropTypeDouble, EwsPropTypeDoubleArray, EwsPropTypeError, EwsPropTypeFloat, EwsPropTypeFloatArray, EwsPropTypeInteger, EwsPropTypeTntegerArray, EwsPropTypeLong, EwsPropTypeLongArray, EwsPropTypeNull, EwsPropTypeObject, EwsPropTypeObjectArray, EwsPropTypeShort, EwsPropTypeShortArray, EwsPropTypeSystemTime, EwsPropTypeSystemTimeArray, EwsPropTypeString, EwsPropTypeStringArray } EwsPropertyType; typedef enum { EwsTraversalShallow = 0, EwsTraversalDeep, EwsTraversalSoftDeleted, EwsTraversalAssociated } EwsTraversalType; typedef enum { EwsItemTypeItem = 0, EwsItemTypeMessage, EwsItemTypeCalendarItem, EwsItemTypeContact, EwsItemTypeDistributionList, EwsItemTypeMeetingMessage, EwsItemTypeMeetingRequest, EwsItemTypeMeetingResponse, EwsItemTypeMeetingCancellation, EwsItemTypeTask, EwsItemTypeAbchPerson, EwsItemTypePostItem, EwsItemTypeUnknown } EwsItemType; typedef enum { EwsItemSensitivityNormal, EwsItemSensitivityPersonal, EwsItemSensitivityPrivate, EwsItemSensitivityConfidential } EwsItemSensitivity; /** * @brief List of fields in EWS Item and its descendants * * The list is based on the XSD schema and contains duplicates, which were commented out. */ typedef enum { EwsItemFieldInvalid = -1, // Folder EwsFolderFieldFolderId, EwsFolderFieldParentFolderId, EwsFolderFieldFolderClass, EwsFolderFieldDisplayName, EwsFolderFieldTotalCount, EwsFolderFieldChildFolderCount, EwsFolderFieldManagedFolderInformation, EwsFolderFieldEffectiveRights, // Calendar folder EwsFolderFieldPermissionSet, // Contacts folder // EwsFolderFieldPermissionSet, DUPLICATE // Mail folder EwsFolderFieldUnreadCount, // EwsFolderFieldPermissionSet, DUPLICATE // Search folder // EwsFolderFieldUnreadCount, DUPLICATE EwsFolderFieldSearchParameters, // Tasks folder // EwsFolderFieldUnreadCount, DUPLICATE // Item EwsItemFieldMimeContent, EwsItemFieldItemId, EwsItemFieldParentFolderId, EwsItemFieldItemClass, EwsItemFieldSubject, EwsItemFieldSensitivity, EwsItemFieldBody, EwsItemFieldAttachments, EwsItemFieldDateTimeReceived, EwsItemFieldSize, EwsItemFieldCategories, EwsItemFieldImportance, EwsItemFieldInReplyTo, EwsItemFieldIsSubmitted, EwsItemFieldIsDraft, EwsItemFieldIsFromMe, EwsItemFieldIsResend, EwsItemFieldIsUnmodified, EwsItemFieldInternetMessageHeaders, EwsItemFieldDateTimeSent, EwsItemFieldDateTimeCreated, EwsItemFieldResponseObjects, EwsItemFieldReminderDueBy, EwsItemFieldReminderIsSet, EwsItemFieldReminderMinutesBeforeStart, EwsItemFieldDisplayCc, EwsItemFieldDisplayTo, EwsItemFieldHasAttachments, EwsItemFieldCulture, EwsItemFieldEffectiveRights, EwsItemFieldLastModifiedName, EwsItemFieldLastModifiedTime, EwsItemFieldIsAssociated, EwsItemFieldWebClientReadFormQueryString, EwsItemFieldWebClientEditFormQueryString, EwsItemFieldConversationId, EwsItemFieldUniqueBody, EwsItemFieldFlag, EwsItemFieldStoreEntryId, EwsItemFieldInstanceKey, EwsItemFieldNormalizedBody, EwsItemFieldEntityExtractionResult, EwsItemFieldPolicyTag, EwsItemFieldArchiveTag, EwsItemFieldRetentionDate, EwsItemFieldPreview, EwsItemFieldRightsManagementLicenseData, EwsItemFieldPredictedActionReasons, EwsItemFieldIsClutter, EwsItemFieldBlockStatus, EwsItemFieldHasBlockedImages, EwsItemFieldTextBody, EwsItemFieldIconIndex, EwsItemFieldSearchKey, EwsItemFieldSortKey, EwsItemFieldHashtags, EwsItemFieldMentions, EwsItemFieldMentionedMe, EwsItemFieldMentionsPreview, EwsItemFieldMentionsEx, EwsItemFieldAppliedHashtags, EwsItemFieldAppliedHashtagsPreview, EwsItemFieldLikes, EwsItemFieldLikesPreview, EwsItemFieldPendingSocialActivityTagIds, EwsItemFieldAtAllMention, EwsItemFieldCanDelete, EwsItemFieldInferenceClassification, // Message EwsItemFieldSender, EwsItemFieldToRecipients, EwsItemFieldCcRecipients, EwsItemFieldBccRecipients, EwsItemFieldIsReadReceiptRequested, EwsItemFieldIsDeliveryReceiptRequested, EwsItemFieldConversationIndex, EwsItemFieldConversationTopic, EwsItemFieldFrom, EwsItemFieldInternetMessageId, EwsItemFieldIsRead, EwsItemFieldIsResponseRequested, EwsItemFieldReferences, EwsItemFieldReplyTo, EwsItemFieldReceivedBy, EwsItemFieldReceivedRepresenting, // Task EwsItemFieldActualWork, EwsItemFieldAssignedTime, EwsItemFieldBillingInformation, EwsItemFieldChangeCount, EwsItemFieldCompanies, EwsItemFieldCompleteDate, EwsItemFieldContacts, EwsItemFieldDelegationState, EwsItemFieldDelegator, EwsItemFieldDueDate, EwsItemFieldIsAssignmentEditable, EwsItemFieldIsComplete, EwsItemFieldIsRecurring, EwsItemFieldIsTeamTask, EwsItemFieldMileage, EwsItemFieldOwner, EwsItemFieldPercentComplete, EwsItemFieldRecurrence, EwsItemFieldStartDate, EwsItemFieldStatus, EwsItemFieldStatusDescription, EwsItemFieldTotalWork, // Calendar EwsItemFieldUID, EwsItemFieldRecurrenceId, EwsItemFieldDateTimeStamp, EwsItemFieldStart, EwsItemFieldEnd, EwsItemFieldOriginalStart, EwsItemFieldIsAllDayEvent, EwsItemFieldLegacyFreeBusyStatus, EwsItemFieldLocation, EwsItemFieldWhen, EwsItemFieldIsMeeting, EwsItemFieldIsCancelled, // EwsItemFieldIsRecurring, DUPLICATE EwsItemFieldMeetingRequestWasSent, // EwsItemFieldIsResponseRequested, DUPLICATE EwsItemFieldCalendarItemType, EwsItemFieldMyResponseType, EwsItemFieldOrganizer, EwsItemFieldRequiredAttendees, EwsItemFieldOptionalAttendees, EwsItemFieldResources, EwsItemFieldConflictingMeetingCount, EwsItemFieldAdjacentMeetingCount, EwsItemFieldConflictingMeetings, EwsItemFieldAdjacentMeetings, EwsItemFieldDuration, EwsItemFieldTimeZone, EwsItemFieldStartTimeZone, EwsItemFieldEndTimeZone, EwsItemFieldAppointmentReplyTime, EwsItemFieldAppointmentSequenceNumber, EwsItemFieldAppointmentState, // EwsItemFieldRecurrence, DUPLICATE EwsItemFieldFirstOccurrence, EwsItemFieldLastOccurrence, EwsItemFieldModifiedOccurrences, EwsItemFieldDeletedOccurrences, EwsItemFieldMeetingTimeZone, EwsItemFieldConferenceType, EwsItemFieldAllowNewTimeProposal, EwsItemFieldIsOnlineMeeting, EwsItemFieldMeetingWorkspaceUrl, EwsItemFieldNetShowUrl, EwsItemFieldEnhancedLocation, EwsItemFieldStartWallClock, EwsItemFieldEndWallClock, EwsItemFieldStartTimeZoneId, EwsItemFieldEndTimeZoneId, EwsItemFieldIntendedFreeBusyStatus, EwsItemFieldJoinOnlineMeetingUrl, EwsItemFieldOnlineMeetingSettings, EwsItemFieldIsOrganizer, EwsItemFieldCalendarActivityData, EwsItemFieldDoNotForwardMeeting, // MeetingMessage EwsItemFieldAssociatedCalendarItemId, EwsItemFieldIsDelegated, EwsItemFieldIsOutOfDate, EwsItemFieldHasBeenProcessed, EwsItemFieldResponseType, // EwsItemFieldUID, DUPLICATE // EwsItemFieldRecurrenceId, DUPLICATE // EwsItemFieldDateTimeStamp, DUPLICATE // MeetingRequestMessage EwsItemFieldMeetingRequestType, // EwsItemFieldIntendedFreeBusyStatus, DUPLICATE // EwsItemFieldStart, DUPLICATE // EwsItemFieldEnd, DUPLICATE // EwsItemFieldOriginalStart, DUPLICATE // EwsItemFieldIsAllDayEvent, DUPLICATE // EwsItemFieldLegacyFreeBusyStatus, DUPLICATE // EwsItemFieldLocation, DUPLICATE // EwsItemFieldWhen, DUPLICATE // EwsItemFieldIsMeeting, DUPLICATE // EwsItemFieldIsCancelled, DUPLICATE // EwsItemFieldIsRecurring, DUPLICATE // EwsItemFieldMeetingRequestWasSent, DUPLICATE // EwsItemFieldCalendarItemType, DUPLICATE // EwsItemFieldMyResponseType, DUPLICATE // EwsItemFieldOrganizer, DUPLICATE // EwsItemFieldRequiredAttendees, DUPLICATE // EwsItemFieldOptionalAttendees, DUPLICATE // EwsItemFieldResources, DUPLICATE // EwsItemFieldConflictingMeetingCount, DUPLICATE // EwsItemFieldAdjacentMeetingCount, DUPLICATE // EwsItemFieldConflictingMeetings, DUPLICATE // EwsItemFieldAdjacentMeetings, DUPLICATE // EwsItemFieldDuration, DUPLICATE // EwsItemFieldTimeZone, DUPLICATE // EwsItemFieldAppointmentReplyTime, DUPLICATE // EwsItemFieldAppointmentSequenceNumber,DUPLICATE // EwsItemFieldAppointmentState, DUPLICATE // EwsItemFieldRecurrence, DUPLICATE // EwsItemFieldFirstOccurrence, DUPLICATE // EwsItemFieldLastOccurrence, DUPLICATE // EwsItemFieldModifiedOccurrences, DUPLICATE // EwsItemFieldDeletedOccurrences, DUPLICATE // EwsItemFieldMeetingTimeZone, DUPLICATE // EwsItemFieldConferenceType, DUPLICATE // EwsItemFieldAllowNewTimeProposal, DUPLICATE // EwsItemFieldIsOnlineMeeting, DUPLICATE // EwsItemFieldMeetingWorkspaceUrl, DUPLICATE // EwsItemFieldNetShowUrl, DUPLICATE // Contact EwsItemFieldFileAs, EwsItemFieldFileAsMapping, EwsItemFieldDisplayName, EwsItemFieldGivenName, EwsItemFieldInitials, EwsItemFieldMiddleName, EwsItemFieldNickname, EwsItemFieldCompleteName, EwsItemFieldCompanyName, EwsItemFieldEmailAddresses, EwsItemFieldPhysicalAddresses, EwsItemFieldPhoneNumbers, EwsItemFieldAssistantName, EwsItemFieldBirthday, EwsItemFieldBusinessHomePage, EwsItemFieldChildren, // EwsItemFieldCompanies, DUPLICATE EwsItemFieldContactSource, EwsItemFieldDepartment, EwsItemFieldGeneration, EwsItemFieldImAddresses, EwsItemFieldJobTitle, EwsItemFieldManager, // EwsItemFieldMileage, DUPLICATE EwsItemFieldOfficeLocation, EwsItemFieldPostalAddressIndex, EwsItemFieldProfession, EwsItemFieldSpouseName, EwsItemFieldSurname, EwsItemFieldWeddingAnniversary, // DistributionList // EwsItemFieldDisplayName, DUPLICATE // EwsItemFieldFileAs, DUPLICATE // EwsItemFieldContactSource, DUPLICATE // Additional fields not in EWS specification EwsItemFieldBodyIsHtml, EwsItemFieldExtendedProperties, EwsItemFieldExchangePersonIdGuid, } EwsItemFields; typedef enum { EwsItemImportanceLow, EwsItemImportanceNormal, EwsItemImportanceHigh } EwsItemImportance; typedef enum { EwsBasePointBeginning, EwsBasePointEnd } EwsIndexedViewBasePoint; typedef enum { EwsCalendarItemSingle = 0, EwsCalendarItemOccurrence, EwsCalendarItemException, EwsCalendarItemRecurringMaster } EwsCalendarItemType; typedef enum { EwsEventResponseUnknown = 0, EwsEventResponseOrganizer, EwsEventResponseTentative, EwsEventResponseAccept, EwsEventResponseDecline, EwsEventResponseNotReceived } EwsEventResponseType; typedef enum { EwsLfbStatusFree = 0, EwsLfbStatusTentative, EwsLfbStatusBusy, EwsLfbOutOfOffice, EwsLfbNoData } EwsLegacyFreeBusyStatus; typedef enum { EwsDispSaveOnly = 0, EwsDispSendOnly, EwsDispSendAndSaveCopy, } EwsMessageDisposition; typedef enum { EwsResolNeverOverwrite = 0, EwsResolAutoResolve, EwsResolAlwaysOverwrite, } EwsConflictResolution; typedef enum { EwsMeetingDispSendToNone = 0, EwsMeetingDispSendOnlyToAll, EwsMeetingDispSendOnlyToChanged, EwsMeetingDispSendToAllAndSaveCopy, EwsMeetingDispSendToChangedAndSaveCopy, EwsMeetingDispUnspecified } EwsMeetingDisposition; typedef enum { EwsCopiedEvent = 0, EwsCreatedEvent, EwsDeletedEvent, EwsModifiedEvent, EwsMovedEvent, EwsNewMailEvent, EwsFreeBusyChangedEvent, EwsStatusEvent, EwsUnknownEvent } EwsEventType; typedef enum { EwsResponseCodeNoError = 0, EwsResponseCodeErrorServerBusy, EwsResponseCodeUnauthorized, EwsResponseCodeUnknown, } EwsResponseCode; -template -T decodeEnumString(const QString &str, const QString *table, unsigned count, bool *ok) +template +T decodeEnumString(const QString &str, const std::array &table, bool *ok) { - unsigned i; - T enumVal = T(); - for (i = 0; i < count; i++) { - if (str == table[i]) { - enumVal = static_cast(i); - break; + unsigned i = 0; + for (const auto &value : table) { + if (str == value) { + *ok = true; + return static_cast(i); } + i++; } - *ok = (i < count); - return enumVal; + *ok = false; + return T(); } inline bool isEwsMessageItemType(EwsItemType type) { return (type == EwsItemTypeItem) || (type == EwsItemTypePostItem); } extern const QList ewsItemTypeNames; EwsResponseCode decodeEwsResponseCode(const QString &code); bool isEwsResponseCodeTemporaryError(EwsResponseCode code);