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

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 "ewspropertyfield.h"
0008 
0009 #include <QString>
0010 
0011 #include "ewsclient_debug.h"
0012 
0013 static const QString distinguishedPropSetIdNames[] = {
0014     QStringLiteral("Meeting"),
0015     QStringLiteral("Appointment"),
0016     QStringLiteral("Common"),
0017     QStringLiteral("PublicStrings"),
0018     QStringLiteral("Address"),
0019     QStringLiteral("InternetHeaders"),
0020     QStringLiteral("CalendarAssistant"),
0021     QStringLiteral("UnifiedMessaging"),
0022 };
0023 
0024 static const QString propertyTypeNames[] = {
0025     QStringLiteral("ApplicationTime"),
0026     QStringLiteral("ApplicationTimeArray"),
0027     QStringLiteral("Binary"),
0028     QStringLiteral("BinaryArray"),
0029     QStringLiteral("Boolean"),
0030     QStringLiteral("CLSID"),
0031     QStringLiteral("CLSIDArray"),
0032     QStringLiteral("Currency"),
0033     QStringLiteral("CurrencyArray"),
0034     QStringLiteral("Double"),
0035     QStringLiteral("DoubleArray"),
0036     QStringLiteral("Error"),
0037     QStringLiteral("Float"),
0038     QStringLiteral("FloatArray"),
0039     QStringLiteral("Integer"),
0040     QStringLiteral("IntegerArray"),
0041     QStringLiteral("Long"),
0042     QStringLiteral("LongArray"),
0043     QStringLiteral("Null"),
0044     QStringLiteral("Object"),
0045     QStringLiteral("ObjectArray"),
0046     QStringLiteral("Short"),
0047     QStringLiteral("ShortArray"),
0048     QStringLiteral("SystemTime"),
0049     QStringLiteral("SystemTimeArray"),
0050     QStringLiteral("String"),
0051     QStringLiteral("StringArray"),
0052 };
0053 
0054 class EwsPropertyFieldPrivate : public QSharedData
0055 {
0056 public:
0057     EwsPropertyFieldPrivate()
0058         : mPropType(EwsPropertyField::UnknownField)
0059         , mIndex(0)
0060         , mPsIdType(DistinguishedPropSet)
0061         , mPsDid(EwsPropSetMeeting)
0062         , mIdType(PropName)
0063         , mId(0)
0064         , mHasTag(false)
0065         , mTag(0)
0066         , mType(EwsPropTypeNull)
0067         , mHash(0)
0068     {
0069     }
0070 
0071     enum PropSetIdType {
0072         DistinguishedPropSet,
0073         RealPropSet,
0074     };
0075 
0076     enum PropIdType {
0077         PropName,
0078         PropId,
0079     };
0080 
0081     EwsPropertyField::Type mPropType;
0082 
0083     QString mUri;
0084     unsigned mIndex;
0085 
0086     PropSetIdType mPsIdType;
0087     EwsDistinguishedPropSetId mPsDid;
0088     QString mPsId;
0089 
0090     PropIdType mIdType;
0091     unsigned mId;
0092     QString mName;
0093 
0094     bool mHasTag;
0095     unsigned mTag;
0096 
0097     EwsPropertyType mType;
0098 
0099     uint mHash; // Precalculated hash for the qHash() function.
0100 
0101     void recalcHash();
0102 };
0103 
0104 void EwsPropertyFieldPrivate::recalcHash()
0105 {
0106     mHash = 0;
0107     switch (mPropType) {
0108     case EwsPropertyField::Field:
0109         mHash = 0x00000000 | (qHash(mUri) & 0x3FFFFFFF);
0110         break;
0111     case EwsPropertyField::IndexedField:
0112         mHash = 0x80000000 | ((qHash(mUri) ^ mIndex) & 0x3FFFFFFF);
0113         break;
0114     case EwsPropertyField::ExtendedField:
0115         if (mHasTag) {
0116             mHash = 0x40000000 | mTag;
0117         } else {
0118             if (mPsIdType == DistinguishedPropSet) {
0119                 mHash |= mPsDid << 16;
0120             } else {
0121                 mHash |= (qHash(mPsId) & 0x1FFF) << 16;
0122             }
0123 
0124             if (mIdType == PropId) {
0125                 mHash |= mId & 0xFFFF;
0126             } else {
0127                 mHash |= (qHash(mName) & 0xFFFF);
0128             }
0129             mHash |= 0xC0000000;
0130         }
0131         break;
0132     default:
0133         break;
0134     }
0135 }
0136 
0137 EwsPropertyField::EwsPropertyField()
0138     : d(new EwsPropertyFieldPrivate())
0139 {
0140 }
0141 
0142 EwsPropertyField::EwsPropertyField(const QString &uri)
0143     : d(new EwsPropertyFieldPrivate())
0144 {
0145     d->mPropType = Field;
0146     d->mUri = uri;
0147     d->recalcHash();
0148 }
0149 
0150 EwsPropertyField::EwsPropertyField(const QString &uri, unsigned index)
0151     : d(new EwsPropertyFieldPrivate())
0152 {
0153     d->mPropType = IndexedField;
0154     d->mUri = uri;
0155     d->mIndex = index;
0156     d->recalcHash();
0157 }
0158 
0159 EwsPropertyField::EwsPropertyField(EwsDistinguishedPropSetId psid, unsigned id, EwsPropertyType type)
0160     : d(new EwsPropertyFieldPrivate())
0161 {
0162     d->mPropType = ExtendedField;
0163 
0164     d->mPsIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
0165     d->mPsDid = psid;
0166 
0167     d->mIdType = EwsPropertyFieldPrivate::PropId;
0168     d->mId = id;
0169 
0170     d->mType = type;
0171     d->recalcHash();
0172 }
0173 
0174 EwsPropertyField::EwsPropertyField(EwsDistinguishedPropSetId psid, const QString &name, EwsPropertyType type)
0175     : d(new EwsPropertyFieldPrivate())
0176 {
0177     d->mPropType = ExtendedField;
0178 
0179     d->mPsIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
0180     d->mPsDid = psid;
0181 
0182     d->mIdType = EwsPropertyFieldPrivate::PropName;
0183     d->mName = name;
0184 
0185     d->mType = type;
0186     d->recalcHash();
0187 }
0188 
0189 EwsPropertyField::EwsPropertyField(const QString &psid, unsigned id, EwsPropertyType type)
0190     : d(new EwsPropertyFieldPrivate())
0191 {
0192     d->mPropType = ExtendedField;
0193 
0194     d->mPsIdType = EwsPropertyFieldPrivate::RealPropSet;
0195     d->mPsId = psid;
0196 
0197     d->mIdType = EwsPropertyFieldPrivate::PropId;
0198     d->mId = id;
0199 
0200     d->mType = type;
0201     d->recalcHash();
0202 }
0203 
0204 EwsPropertyField::EwsPropertyField(const QString &psid, const QString &name, EwsPropertyType type)
0205     : d(new EwsPropertyFieldPrivate())
0206 {
0207     d->mPropType = ExtendedField;
0208 
0209     d->mPsIdType = EwsPropertyFieldPrivate::RealPropSet;
0210     d->mPsId = psid;
0211 
0212     d->mIdType = EwsPropertyFieldPrivate::PropName;
0213     d->mName = name;
0214 
0215     d->mType = type;
0216     d->recalcHash();
0217 }
0218 
0219 EwsPropertyField::EwsPropertyField(unsigned tag, EwsPropertyType type)
0220     : d(new EwsPropertyFieldPrivate())
0221 {
0222     d->mPropType = ExtendedField;
0223 
0224     d->mHasTag = true;
0225     d->mTag = tag;
0226 
0227     d->mType = type;
0228     d->recalcHash();
0229 }
0230 
0231 EwsPropertyField::EwsPropertyField(const EwsPropertyField &other)
0232     : d(other.d)
0233 {
0234 }
0235 
0236 EwsPropertyField::EwsPropertyField(EwsPropertyField &&other)
0237     : d(other.d)
0238 {
0239 }
0240 
0241 EwsPropertyField &EwsPropertyField::operator=(EwsPropertyField &&other)
0242 {
0243     d = other.d;
0244     return *this;
0245 }
0246 
0247 EwsPropertyField::~EwsPropertyField()
0248 {
0249 }
0250 
0251 EwsPropertyField &EwsPropertyField::operator=(const EwsPropertyField &other)
0252 {
0253     d = other.d;
0254     return *this;
0255 }
0256 
0257 bool EwsPropertyField::operator==(const EwsPropertyField &other) const
0258 {
0259     if (d == other.d) {
0260         return true;
0261     }
0262 
0263     const EwsPropertyFieldPrivate *od = other.d;
0264 
0265     if (d->mPropType != od->mPropType) {
0266         return false;
0267     }
0268 
0269     switch (d->mPropType) {
0270     case UnknownField:
0271         return true;
0272     case Field:
0273         return d->mUri == od->mUri;
0274     case IndexedField:
0275         return (d->mUri == od->mUri) && (d->mIndex == od->mIndex);
0276     case ExtendedField:
0277         if (d->mType != od->mType) {
0278             return false;
0279         }
0280 
0281         if (d->mHasTag != od->mHasTag) {
0282             return false;
0283         } else if (d->mHasTag) {
0284             return d->mTag == od->mTag;
0285         }
0286 
0287         if (d->mPsIdType != od->mPsIdType) {
0288             return false;
0289         } else if ((d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) && (d->mPsDid != od->mPsDid)) {
0290             return false;
0291         } else if ((d->mPsIdType == EwsPropertyFieldPrivate::RealPropSet) && (d->mPsId != od->mPsId)) {
0292             return false;
0293         }
0294 
0295         if (d->mIdType != od->mIdType) {
0296             return false;
0297         } else if ((d->mIdType == EwsPropertyFieldPrivate::PropId) && (d->mId != od->mId)) {
0298             return false;
0299         } else if ((d->mIdType == EwsPropertyFieldPrivate::PropName) && (d->mName != od->mName)) {
0300             return false;
0301         }
0302         return true;
0303     default:
0304         return false;
0305     }
0306 
0307     // Shouldn't get here.
0308     return false;
0309 }
0310 
0311 void EwsPropertyField::write(QXmlStreamWriter &writer) const
0312 {
0313     switch (d->mPropType) {
0314     case Field:
0315         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("FieldURI"));
0316         writer.writeAttribute(QStringLiteral("FieldURI"), d->mUri);
0317         writer.writeEndElement();
0318         break;
0319     case IndexedField: {
0320         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("IndexedFieldURI"));
0321         writer.writeAttribute(QStringLiteral("FieldURI"), d->mUri);
0322         QStringList tokens = d->mUri.split(QLatin1Char(':'));
0323         writer.writeAttribute(QStringLiteral("FieldIndex"), tokens[1] + QString::number(d->mIndex));
0324         writer.writeEndElement();
0325         break;
0326     }
0327     case ExtendedField:
0328         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ExtendedFieldURI"));
0329         if (d->mHasTag) {
0330             writer.writeAttribute(QStringLiteral("PropertyTag"), QStringLiteral("0x") + QString::number(d->mTag, 16));
0331         } else {
0332             if (d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) {
0333                 writer.writeAttribute(QStringLiteral("DistinguishedPropertySetId"), distinguishedPropSetIdNames[d->mPsDid]);
0334             } else {
0335                 writer.writeAttribute(QStringLiteral("PropertySetId"), d->mPsId);
0336             }
0337 
0338             if (d->mIdType == EwsPropertyFieldPrivate::PropId) {
0339                 writer.writeAttribute(QStringLiteral("PropertyId"), QString::number(d->mId));
0340             } else {
0341                 writer.writeAttribute(QStringLiteral("PropertyName"), d->mName);
0342             }
0343         }
0344         writer.writeAttribute(QStringLiteral("PropertyType"), propertyTypeNames[d->mType]);
0345         writer.writeEndElement();
0346         break;
0347     case UnknownField:
0348         break;
0349     }
0350 }
0351 
0352 bool EwsPropertyField::read(QXmlStreamReader &reader)
0353 {
0354     if (reader.namespaceUri() != ewsTypeNsUri) {
0355         qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - invalid namespace.");
0356         return false;
0357     }
0358 
0359     QXmlStreamAttributes attrs = reader.attributes();
0360     bool ok;
0361 
0362     // First check the property type
0363     if (reader.name() == QLatin1StringView("FieldURI")) {
0364         if (!attrs.hasAttribute(QStringLiteral("FieldURI"))) {
0365             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldURI"));
0366             return false;
0367         }
0368         d->mPropType = Field;
0369         d->mUri = attrs.value(QStringLiteral("FieldURI")).toString();
0370     } else if (reader.name() == QLatin1StringView("IndexedFieldURI")) {
0371         if (!attrs.hasAttribute(QStringLiteral("FieldURI"))) {
0372             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldURI"));
0373             return false;
0374         }
0375         if (!attrs.hasAttribute(QStringLiteral("FieldIndex"))) {
0376             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldIndex"));
0377             return false;
0378         }
0379         QString uri = attrs.value(QStringLiteral("FieldURI")).toString();
0380         QStringList tokens = uri.split(QLatin1Char(':'));
0381         QString indexStr = attrs.value(QStringLiteral("FieldIndex")).toString();
0382         if (!indexStr.startsWith(tokens[1])) {
0383             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - malformed %1 attribute.").arg(QStringLiteral("FieldIndex"));
0384             return false;
0385         }
0386         unsigned index = QStringView(indexStr).mid(tokens[1].size()).toUInt(&ok, 0);
0387         if (!ok) {
0388             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("FieldIndex"));
0389             return false;
0390         }
0391         d->mPropType = IndexedField;
0392         d->mUri = uri;
0393         d->mIndex = index;
0394     } else if (reader.name() == QLatin1StringView("ExtendedFieldURI")) {
0395         if (!attrs.hasAttribute(QStringLiteral("PropertyType"))) {
0396             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("PropertyType"));
0397             return false;
0398         }
0399         auto propTypeText = attrs.value(QStringLiteral("PropertyType"));
0400         unsigned i;
0401         EwsPropertyType propType;
0402         for (i = 0; i < sizeof(propertyTypeNames) / sizeof(propertyTypeNames[0]); ++i) {
0403             if (propTypeText == propertyTypeNames[i]) {
0404                 propType = static_cast<EwsPropertyType>(i);
0405                 break;
0406             }
0407         }
0408         if (i == sizeof(propertyTypeNames) / sizeof(propertyTypeNames[0])) {
0409             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyType"));
0410             return false;
0411         }
0412 
0413         if (attrs.hasAttribute(QStringLiteral("PropertyTag"))) {
0414             unsigned tag = attrs.value(QStringLiteral("PropertyTag")).toUInt(&ok, 0);
0415             if (!ok) {
0416                 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyTag"));
0417                 return false;
0418             }
0419             d->mHasTag = true;
0420             d->mTag = tag;
0421         } else {
0422             EwsPropertyFieldPrivate::PropSetIdType psIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
0423             EwsDistinguishedPropSetId psDid = EwsPropSetMeeting;
0424             QString psId;
0425 
0426             EwsPropertyFieldPrivate::PropIdType idType = EwsPropertyFieldPrivate::PropName;
0427             unsigned id = 0;
0428             QString name;
0429             if (attrs.hasAttribute(QStringLiteral("PropertyId"))) {
0430                 id = attrs.value(QStringLiteral("PropertyId")).toUInt(&ok, 0);
0431                 if (!ok) {
0432                     qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyId"));
0433                     return false;
0434                 }
0435                 idType = EwsPropertyFieldPrivate::PropId;
0436             } else if (attrs.hasAttribute(QStringLiteral("PropertyName"))) {
0437                 name = attrs.value(QStringLiteral("PropertyName")).toString();
0438                 idType = EwsPropertyFieldPrivate::PropName;
0439             } else {
0440                 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing one of %1 or %2 attributes.")
0441                                                .arg(QStringLiteral("PropertyId").arg(QStringLiteral("PropertyName")));
0442                 return false;
0443             }
0444 
0445             if (attrs.hasAttribute(QStringLiteral("DistinguishedPropertySetId"))) {
0446                 auto didText = attrs.value(QStringLiteral("DistinguishedPropertySetId"));
0447                 unsigned i;
0448                 for (i = 0; i < sizeof(distinguishedPropSetIdNames) / sizeof(distinguishedPropSetIdNames[0]); ++i) {
0449                     if (didText == distinguishedPropSetIdNames[i]) {
0450                         psDid = static_cast<EwsDistinguishedPropSetId>(i);
0451                         break;
0452                     }
0453                 }
0454                 if (i == sizeof(distinguishedPropSetIdNames) / sizeof(distinguishedPropSetIdNames[0])) {
0455                     qCWarningNC(EWSCLI_LOG)
0456                         << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("DistinguishedPropertySetId"));
0457                     return false;
0458                 }
0459                 psIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
0460             } else if (attrs.hasAttribute(QStringLiteral("PropertySetId"))) {
0461                 psId = attrs.value(QStringLiteral("PropertySetId")).toString();
0462                 psIdType = EwsPropertyFieldPrivate::RealPropSet;
0463             } else {
0464                 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing one of %1 or %2 attributes.")
0465                                                .arg(QStringLiteral("DistinguishedPropertySetId").arg(QStringLiteral("PropertySetId")));
0466                 return false;
0467             }
0468             d->mPsIdType = psIdType;
0469             d->mPsDid = psDid;
0470             d->mPsId = psId;
0471             d->mIdType = idType;
0472             d->mId = id;
0473             d->mName = name;
0474         }
0475 
0476         d->mType = propType;
0477         d->mPropType = ExtendedField;
0478     }
0479     d->recalcHash();
0480     return true;
0481 }
0482 
0483 uint qHash(const EwsPropertyField &prop, uint seed)
0484 {
0485     return prop.d->mHasTag ^ seed;
0486 }
0487 
0488 QDebug operator<<(QDebug debug, const EwsPropertyField &prop)
0489 {
0490     QDebugStateSaver saver(debug);
0491     QDebug d = debug.nospace().noquote();
0492     d << QStringLiteral("EwsPropertyField(");
0493 
0494     switch (prop.d->mPropType) {
0495     case EwsPropertyField::Field:
0496         d << QStringLiteral("FieldUri: ") << prop.d->mUri;
0497         break;
0498     case EwsPropertyField::IndexedField:
0499         d << QStringLiteral("IndexedFieldUri: ") << prop.d->mUri << '@' << prop.d->mIndex;
0500         break;
0501     case EwsPropertyField::ExtendedField:
0502         d << QStringLiteral("ExtendedFieldUri: ");
0503         if (prop.d->mHasTag) {
0504             d << QStringLiteral("tag: 0x") << QString::number(prop.d->mTag, 16);
0505         } else {
0506             if (prop.d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) {
0507                 d << QStringLiteral("psdid: ") << distinguishedPropSetIdNames[prop.d->mPsDid];
0508             } else {
0509                 d << QStringLiteral("psid: ") << prop.d->mPsId;
0510             }
0511             d << QStringLiteral(", ");
0512 
0513             if (prop.d->mIdType == EwsPropertyFieldPrivate::PropId) {
0514                 d << QStringLiteral("id: 0x") << QString::number(prop.d->mId, 16);
0515             } else {
0516                 d << QStringLiteral("name: ") << prop.d->mName;
0517             }
0518         }
0519         d << QStringLiteral(", type: ") << propertyTypeNames[prop.d->mType];
0520         break;
0521     case EwsPropertyField::UnknownField:
0522         d << QStringLiteral("Unknown");
0523         break;
0524     }
0525     d << ')';
0526     return debug;
0527 }
0528 
0529 bool EwsPropertyField::writeWithValue(QXmlStreamWriter &writer, const QVariant &value) const
0530 {
0531     switch (d->mPropType) {
0532     case Field: {
0533         QStringList tokens = d->mUri.split(QLatin1Char(':'));
0534         if (tokens.size() != 2) {
0535             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Invalid field URI: %1").arg(d->mUri);
0536             return false;
0537         }
0538         writer.writeStartElement(ewsTypeNsUri, tokens[1]);
0539         writeValue(writer, value);
0540         writer.writeEndElement();
0541         break;
0542     }
0543     case IndexedField: {
0544         QStringList tokens = d->mUri.split(QLatin1Char(':'));
0545         if (tokens.size() != 2) {
0546             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Invalid field URI: %1").arg(d->mUri);
0547             return false;
0548         }
0549         writer.writeStartElement(ewsTypeNsUri, tokens[1] + QStringLiteral("es"));
0550         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Entry"));
0551         writer.writeAttribute(QStringLiteral("Key"), tokens[1] + QString::number(d->mIndex));
0552         writeValue(writer, value);
0553         writer.writeEndElement();
0554         writer.writeEndElement();
0555         break;
0556     }
0557     case ExtendedField:
0558         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ExtendedProperty"));
0559         write(writer);
0560         writeExtendedValue(writer, value);
0561         writer.writeEndElement();
0562         break;
0563     default:
0564         return false;
0565     }
0566 
0567     return true;
0568 }
0569 
0570 void EwsPropertyField::writeValue(QXmlStreamWriter &writer, const QVariant &value) const
0571 {
0572     switch (value.userType()) {
0573     case QMetaType::QStringList: {
0574         const QStringList list = value.toStringList();
0575         for (const QString &str : list) {
0576             writer.writeTextElement(ewsTypeNsUri, QStringLiteral("String"), str);
0577         }
0578         break;
0579     }
0580     case QMetaType::QString:
0581         writer.writeCharacters(value.toString());
0582         break;
0583     default:
0584         qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown variant type to write: %1").arg(QString::fromLatin1(value.typeName()));
0585     }
0586 }
0587 
0588 void EwsPropertyField::writeExtendedValue(QXmlStreamWriter &writer, const QVariant &value) const
0589 {
0590     switch (value.userType()) {
0591     case QMetaType::QStringList: {
0592         const QStringList list = value.toStringList();
0593         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Values"));
0594         for (const QString &str : list) {
0595             writer.writeTextElement(ewsTypeNsUri, QStringLiteral("Value"), str);
0596         }
0597         writer.writeEndElement();
0598         break;
0599     }
0600     case QMetaType::QString:
0601         writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Value"));
0602         writer.writeCharacters(value.toString());
0603         writer.writeEndElement();
0604         break;
0605     default:
0606         qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown variant type to write: %1").arg(QString::fromLatin1(value.typeName()));
0607     }
0608 }
0609 
0610 EwsPropertyField::Type EwsPropertyField::type() const
0611 {
0612     return d->mPropType;
0613 }
0614 
0615 QString EwsPropertyField::uri() const
0616 {
0617     if (d->mPropType == Field || d->mPropType == IndexedField) {
0618         return d->mUri;
0619     } else {
0620         return QString();
0621     }
0622 }