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 "ewspropertyfield.h"
8
9 #include <QString>
10
11 #include "ewsclient_debug.h"
12
13 static const QString distinguishedPropSetIdNames[] = {
14 QStringLiteral("Meeting"),
15 QStringLiteral("Appointment"),
16 QStringLiteral("Common"),
17 QStringLiteral("PublicStrings"),
18 QStringLiteral("Address"),
19 QStringLiteral("InternetHeaders"),
20 QStringLiteral("CalendarAssistant"),
21 QStringLiteral("UnifiedMessaging"),
22 };
23
24 static const QString propertyTypeNames[] = {
25 QStringLiteral("ApplicationTime"),
26 QStringLiteral("ApplicationTimeArray"),
27 QStringLiteral("Binary"),
28 QStringLiteral("BinaryArray"),
29 QStringLiteral("Boolean"),
30 QStringLiteral("CLSID"),
31 QStringLiteral("CLSIDArray"),
32 QStringLiteral("Currency"),
33 QStringLiteral("CurrencyArray"),
34 QStringLiteral("Double"),
35 QStringLiteral("DoubleArray"),
36 QStringLiteral("Error"),
37 QStringLiteral("Float"),
38 QStringLiteral("FloatArray"),
39 QStringLiteral("Integer"),
40 QStringLiteral("IntegerArray"),
41 QStringLiteral("Long"),
42 QStringLiteral("LongArray"),
43 QStringLiteral("Null"),
44 QStringLiteral("Object"),
45 QStringLiteral("ObjectArray"),
46 QStringLiteral("Short"),
47 QStringLiteral("ShortArray"),
48 QStringLiteral("SystemTime"),
49 QStringLiteral("SystemTimeArray"),
50 QStringLiteral("String"),
51 QStringLiteral("StringArray"),
52 };
53
54 class EwsPropertyFieldPrivate : public QSharedData
55 {
56 public:
EwsPropertyFieldPrivate()57 EwsPropertyFieldPrivate()
58 : mPropType(EwsPropertyField::UnknownField)
59 , mIndex(0)
60 , mPsIdType(DistinguishedPropSet)
61 , mPsDid(EwsPropSetMeeting)
62 , mIdType(PropName)
63 , mId(0)
64 , mHasTag(false)
65 , mTag(0)
66 , mType(EwsPropTypeNull)
67 , mHash(0)
68 {
69 }
70
71 enum PropSetIdType {
72 DistinguishedPropSet,
73 RealPropSet,
74 };
75
76 enum PropIdType {
77 PropName,
78 PropId,
79 };
80
81 EwsPropertyField::Type mPropType;
82
83 QString mUri;
84 unsigned mIndex;
85
86 PropSetIdType mPsIdType;
87 EwsDistinguishedPropSetId mPsDid;
88 QString mPsId;
89
90 PropIdType mIdType;
91 unsigned mId;
92 QString mName;
93
94 bool mHasTag;
95 unsigned mTag;
96
97 EwsPropertyType mType;
98
99 uint mHash; // Precalculated hash for the qHash() function.
100
101 void recalcHash();
102 };
103
recalcHash()104 void EwsPropertyFieldPrivate::recalcHash()
105 {
106 mHash = 0;
107 switch (mPropType) {
108 case EwsPropertyField::Field:
109 mHash = 0x00000000 | (qHash(mUri) & 0x3FFFFFFF);
110 break;
111 case EwsPropertyField::IndexedField:
112 mHash = 0x80000000 | ((qHash(mUri) ^ mIndex) & 0x3FFFFFFF);
113 break;
114 case EwsPropertyField::ExtendedField:
115 if (mHasTag) {
116 mHash = 0x40000000 | mTag;
117 } else {
118 if (mPsIdType == DistinguishedPropSet) {
119 mHash |= mPsDid << 16;
120 } else {
121 mHash |= (qHash(mPsId) & 0x1FFF) << 16;
122 }
123
124 if (mIdType == PropId) {
125 mHash |= mId & 0xFFFF;
126 } else {
127 mHash |= (qHash(mName) & 0xFFFF);
128 }
129 mHash |= 0xC0000000;
130 }
131 break;
132 default:
133 break;
134 }
135 }
136
EwsPropertyField()137 EwsPropertyField::EwsPropertyField()
138 : d(new EwsPropertyFieldPrivate())
139 {
140 }
141
EwsPropertyField(const QString & uri)142 EwsPropertyField::EwsPropertyField(const QString &uri)
143 : d(new EwsPropertyFieldPrivate())
144 {
145 d->mPropType = Field;
146 d->mUri = uri;
147 d->recalcHash();
148 }
149
EwsPropertyField(const QString & uri,unsigned index)150 EwsPropertyField::EwsPropertyField(const QString &uri, unsigned index)
151 : d(new EwsPropertyFieldPrivate())
152 {
153 d->mPropType = IndexedField;
154 d->mUri = uri;
155 d->mIndex = index;
156 d->recalcHash();
157 }
158
EwsPropertyField(EwsDistinguishedPropSetId psid,unsigned id,EwsPropertyType type)159 EwsPropertyField::EwsPropertyField(EwsDistinguishedPropSetId psid, unsigned id, EwsPropertyType type)
160 : d(new EwsPropertyFieldPrivate())
161 {
162 d->mPropType = ExtendedField;
163
164 d->mPsIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
165 d->mPsDid = psid;
166
167 d->mIdType = EwsPropertyFieldPrivate::PropId;
168 d->mId = id;
169
170 d->mType = type;
171 d->recalcHash();
172 }
173
EwsPropertyField(EwsDistinguishedPropSetId psid,const QString & name,EwsPropertyType type)174 EwsPropertyField::EwsPropertyField(EwsDistinguishedPropSetId psid, const QString &name, EwsPropertyType type)
175 : d(new EwsPropertyFieldPrivate())
176 {
177 d->mPropType = ExtendedField;
178
179 d->mPsIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
180 d->mPsDid = psid;
181
182 d->mIdType = EwsPropertyFieldPrivate::PropName;
183 d->mName = name;
184
185 d->mType = type;
186 d->recalcHash();
187 }
188
EwsPropertyField(const QString & psid,unsigned id,EwsPropertyType type)189 EwsPropertyField::EwsPropertyField(const QString &psid, unsigned id, EwsPropertyType type)
190 : d(new EwsPropertyFieldPrivate())
191 {
192 d->mPropType = ExtendedField;
193
194 d->mPsIdType = EwsPropertyFieldPrivate::RealPropSet;
195 d->mPsId = psid;
196
197 d->mIdType = EwsPropertyFieldPrivate::PropId;
198 d->mId = id;
199
200 d->mType = type;
201 d->recalcHash();
202 }
203
EwsPropertyField(const QString & psid,const QString & name,EwsPropertyType type)204 EwsPropertyField::EwsPropertyField(const QString &psid, const QString &name, EwsPropertyType type)
205 : d(new EwsPropertyFieldPrivate())
206 {
207 d->mPropType = ExtendedField;
208
209 d->mPsIdType = EwsPropertyFieldPrivate::RealPropSet;
210 d->mPsId = psid;
211
212 d->mIdType = EwsPropertyFieldPrivate::PropName;
213 d->mName = name;
214
215 d->mType = type;
216 d->recalcHash();
217 }
218
EwsPropertyField(unsigned tag,EwsPropertyType type)219 EwsPropertyField::EwsPropertyField(unsigned tag, EwsPropertyType type)
220 : d(new EwsPropertyFieldPrivate())
221 {
222 d->mPropType = ExtendedField;
223
224 d->mHasTag = true;
225 d->mTag = tag;
226
227 d->mType = type;
228 d->recalcHash();
229 }
230
EwsPropertyField(const EwsPropertyField & other)231 EwsPropertyField::EwsPropertyField(const EwsPropertyField &other)
232 : d(other.d)
233 {
234 }
235
EwsPropertyField(EwsPropertyField && other)236 EwsPropertyField::EwsPropertyField(EwsPropertyField &&other)
237 : d(other.d)
238 {
239 }
240
operator =(EwsPropertyField && other)241 EwsPropertyField &EwsPropertyField::operator=(EwsPropertyField &&other)
242 {
243 d = other.d;
244 return *this;
245 }
246
~EwsPropertyField()247 EwsPropertyField::~EwsPropertyField()
248 {
249 }
250
operator =(const EwsPropertyField & other)251 EwsPropertyField &EwsPropertyField::operator=(const EwsPropertyField &other)
252 {
253 d = other.d;
254 return *this;
255 }
256
operator ==(const EwsPropertyField & other) const257 bool EwsPropertyField::operator==(const EwsPropertyField &other) const
258 {
259 if (d == other.d) {
260 return true;
261 }
262
263 const EwsPropertyFieldPrivate *od = other.d;
264
265 if (d->mPropType != od->mPropType) {
266 return false;
267 }
268
269 switch (d->mPropType) {
270 case UnknownField:
271 return true;
272 case Field:
273 return d->mUri == od->mUri;
274 case IndexedField:
275 return (d->mUri == od->mUri) && (d->mIndex == od->mIndex);
276 case ExtendedField:
277 if (d->mType != od->mType) {
278 return false;
279 }
280
281 if (d->mHasTag != od->mHasTag) {
282 return false;
283 } else if (d->mHasTag) {
284 return d->mTag == od->mTag;
285 }
286
287 if (d->mPsIdType != od->mPsIdType) {
288 return false;
289 } else if ((d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) && (d->mPsDid != od->mPsDid)) {
290 return false;
291 } else if ((d->mPsIdType == EwsPropertyFieldPrivate::RealPropSet) && (d->mPsId != od->mPsId)) {
292 return false;
293 }
294
295 if (d->mIdType != od->mIdType) {
296 return false;
297 } else if ((d->mIdType == EwsPropertyFieldPrivate::PropId) && (d->mId != od->mId)) {
298 return false;
299 } else if ((d->mIdType == EwsPropertyFieldPrivate::PropName) && (d->mName != od->mName)) {
300 return false;
301 }
302 return true;
303 default:
304 return false;
305 }
306
307 // Shouldn't get here.
308 return false;
309 }
310
write(QXmlStreamWriter & writer) const311 void EwsPropertyField::write(QXmlStreamWriter &writer) const
312 {
313 switch (d->mPropType) {
314 case Field:
315 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("FieldURI"));
316 writer.writeAttribute(QStringLiteral("FieldURI"), d->mUri);
317 writer.writeEndElement();
318 break;
319 case IndexedField: {
320 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("IndexedFieldURI"));
321 writer.writeAttribute(QStringLiteral("FieldURI"), d->mUri);
322 QStringList tokens = d->mUri.split(QLatin1Char(':'));
323 writer.writeAttribute(QStringLiteral("FieldIndex"), tokens[1] + QString::number(d->mIndex));
324 writer.writeEndElement();
325 break;
326 }
327 case ExtendedField:
328 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ExtendedFieldURI"));
329 if (d->mHasTag) {
330 writer.writeAttribute(QStringLiteral("PropertyTag"), QStringLiteral("0x") + QString::number(d->mTag, 16));
331 } else {
332 if (d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) {
333 writer.writeAttribute(QStringLiteral("DistinguishedPropertySetId"), distinguishedPropSetIdNames[d->mPsDid]);
334 } else {
335 writer.writeAttribute(QStringLiteral("PropertySetId"), d->mPsId);
336 }
337
338 if (d->mIdType == EwsPropertyFieldPrivate::PropId) {
339 writer.writeAttribute(QStringLiteral("PropertyId"), QString::number(d->mId));
340 } else {
341 writer.writeAttribute(QStringLiteral("PropertyName"), d->mName);
342 }
343 }
344 writer.writeAttribute(QStringLiteral("PropertyType"), propertyTypeNames[d->mType]);
345 writer.writeEndElement();
346 break;
347 case UnknownField:
348 break;
349 }
350 }
351
read(QXmlStreamReader & reader)352 bool EwsPropertyField::read(QXmlStreamReader &reader)
353 {
354 if (reader.namespaceUri() != ewsTypeNsUri) {
355 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - invalid namespace.");
356 return false;
357 }
358
359 QXmlStreamAttributes attrs = reader.attributes();
360 bool ok;
361
362 // First check the property type
363 if (reader.name() == QLatin1String("FieldURI")) {
364 if (!attrs.hasAttribute(QStringLiteral("FieldURI"))) {
365 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldURI"));
366 return false;
367 }
368 d->mPropType = Field;
369 d->mUri = attrs.value(QStringLiteral("FieldURI")).toString();
370 } else if (reader.name() == QLatin1String("IndexedFieldURI")) {
371 if (!attrs.hasAttribute(QStringLiteral("FieldURI"))) {
372 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldURI"));
373 return false;
374 }
375 if (!attrs.hasAttribute(QStringLiteral("FieldIndex"))) {
376 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("FieldIndex"));
377 return false;
378 }
379 QString uri = attrs.value(QStringLiteral("FieldURI")).toString();
380 QStringList tokens = uri.split(QLatin1Char(':'));
381 QString indexStr = attrs.value(QStringLiteral("FieldIndex")).toString();
382 if (!indexStr.startsWith(tokens[1])) {
383 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - malformed %1 attribute.").arg(QStringLiteral("FieldIndex"));
384 return false;
385 }
386 unsigned index = indexStr.midRef(tokens[1].size()).toUInt(&ok, 0);
387 if (!ok) {
388 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("FieldIndex"));
389 return false;
390 }
391 d->mPropType = IndexedField;
392 d->mUri = uri;
393 d->mIndex = index;
394 } else if (reader.name() == QLatin1String("ExtendedFieldURI")) {
395 if (!attrs.hasAttribute(QStringLiteral("PropertyType"))) {
396 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing %1 attribute.").arg(QStringLiteral("PropertyType"));
397 return false;
398 }
399 QStringRef propTypeText = attrs.value(QStringLiteral("PropertyType"));
400 unsigned i;
401 EwsPropertyType propType;
402 for (i = 0; i < sizeof(propertyTypeNames) / sizeof(propertyTypeNames[0]); ++i) {
403 if (propTypeText == propertyTypeNames[i]) {
404 propType = static_cast<EwsPropertyType>(i);
405 break;
406 }
407 }
408 if (i == sizeof(propertyTypeNames) / sizeof(propertyTypeNames[0])) {
409 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyType"));
410 return false;
411 }
412
413 if (attrs.hasAttribute(QStringLiteral("PropertyTag"))) {
414 unsigned tag = attrs.value(QStringLiteral("PropertyTag")).toUInt(&ok, 0);
415 if (!ok) {
416 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyTag"));
417 return false;
418 }
419 d->mHasTag = true;
420 d->mTag = tag;
421 } else {
422 EwsPropertyFieldPrivate::PropSetIdType psIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
423 EwsDistinguishedPropSetId psDid = EwsPropSetMeeting;
424 QString psId;
425
426 EwsPropertyFieldPrivate::PropIdType idType = EwsPropertyFieldPrivate::PropName;
427 unsigned id = 0;
428 QString name;
429 if (attrs.hasAttribute(QStringLiteral("PropertyId"))) {
430 id = attrs.value(QStringLiteral("PropertyId")).toUInt(&ok, 0);
431 if (!ok) {
432 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("PropertyId"));
433 return false;
434 }
435 idType = EwsPropertyFieldPrivate::PropId;
436 } else if (attrs.hasAttribute(QStringLiteral("PropertyName"))) {
437 name = attrs.value(QStringLiteral("PropertyName")).toString();
438 idType = EwsPropertyFieldPrivate::PropName;
439 } else {
440 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing one of %1 or %2 attributes.")
441 .arg(QStringLiteral("PropertyId").arg(QStringLiteral("PropertyName")));
442 return false;
443 }
444
445 if (attrs.hasAttribute(QStringLiteral("DistinguishedPropertySetId"))) {
446 QStringRef didText = attrs.value(QStringLiteral("DistinguishedPropertySetId"));
447 unsigned i;
448 for (i = 0; i < sizeof(distinguishedPropSetIdNames) / sizeof(distinguishedPropSetIdNames[0]); ++i) {
449 if (didText == distinguishedPropSetIdNames[i]) {
450 psDid = static_cast<EwsDistinguishedPropSetId>(i);
451 break;
452 }
453 }
454 if (i == sizeof(distinguishedPropSetIdNames) / sizeof(distinguishedPropSetIdNames[0])) {
455 qCWarningNC(EWSCLI_LOG)
456 << QStringLiteral("Error reading property field - error reading %1 attribute.").arg(QStringLiteral("DistinguishedPropertySetId"));
457 return false;
458 }
459 psIdType = EwsPropertyFieldPrivate::DistinguishedPropSet;
460 } else if (attrs.hasAttribute(QStringLiteral("PropertySetId"))) {
461 psId = attrs.value(QStringLiteral("PropertySetId")).toString();
462 psIdType = EwsPropertyFieldPrivate::RealPropSet;
463 } else {
464 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Error reading property field - missing one of %1 or %2 attributes.")
465 .arg(QStringLiteral("DistinguishedPropertySetId").arg(QStringLiteral("PropertySetId")));
466 return false;
467 }
468 d->mPsIdType = psIdType;
469 d->mPsDid = psDid;
470 d->mPsId = psId;
471 d->mIdType = idType;
472 d->mId = id;
473 d->mName = name;
474 }
475
476 d->mType = propType;
477 d->mPropType = ExtendedField;
478 }
479 d->recalcHash();
480 return true;
481 }
482
qHash(const EwsPropertyField & prop,uint seed)483 uint qHash(const EwsPropertyField &prop, uint seed)
484 {
485 return prop.d->mHasTag ^ seed;
486 }
487
operator <<(QDebug debug,const EwsPropertyField & prop)488 QDebug operator<<(QDebug debug, const EwsPropertyField &prop)
489 {
490 QDebugStateSaver saver(debug);
491 QDebug d = debug.nospace().noquote();
492 d << QStringLiteral("EwsPropertyField(");
493
494 switch (prop.d->mPropType) {
495 case EwsPropertyField::Field:
496 d << QStringLiteral("FieldUri: ") << prop.d->mUri;
497 break;
498 case EwsPropertyField::IndexedField:
499 d << QStringLiteral("IndexedFieldUri: ") << prop.d->mUri << '@' << prop.d->mIndex;
500 break;
501 case EwsPropertyField::ExtendedField:
502 d << QStringLiteral("ExtendedFieldUri: ");
503 if (prop.d->mHasTag) {
504 d << QStringLiteral("tag: 0x") << QString::number(prop.d->mTag, 16);
505 } else {
506 if (prop.d->mPsIdType == EwsPropertyFieldPrivate::DistinguishedPropSet) {
507 d << QStringLiteral("psdid: ") << distinguishedPropSetIdNames[prop.d->mPsDid];
508 } else {
509 d << QStringLiteral("psid: ") << prop.d->mPsId;
510 }
511 d << QStringLiteral(", ");
512
513 if (prop.d->mIdType == EwsPropertyFieldPrivate::PropId) {
514 d << QStringLiteral("id: 0x") << QString::number(prop.d->mId, 16);
515 } else {
516 d << QStringLiteral("name: ") << prop.d->mName;
517 }
518 }
519 d << QStringLiteral(", type: ") << propertyTypeNames[prop.d->mType];
520 break;
521 case EwsPropertyField::UnknownField:
522 d << QStringLiteral("Unknown");
523 break;
524 }
525 d << ')';
526 return debug;
527 }
528
writeWithValue(QXmlStreamWriter & writer,const QVariant & value) const529 bool EwsPropertyField::writeWithValue(QXmlStreamWriter &writer, const QVariant &value) const
530 {
531 switch (d->mPropType) {
532 case Field: {
533 QStringList tokens = d->mUri.split(QLatin1Char(':'));
534 if (tokens.size() != 2) {
535 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Invalid field URI: %1").arg(d->mUri);
536 return false;
537 }
538 writer.writeStartElement(ewsTypeNsUri, tokens[1]);
539 writeValue(writer, value);
540 writer.writeEndElement();
541 break;
542 }
543 case IndexedField: {
544 QStringList tokens = d->mUri.split(QLatin1Char(':'));
545 if (tokens.size() != 2) {
546 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Invalid field URI: %1").arg(d->mUri);
547 return false;
548 }
549 writer.writeStartElement(ewsTypeNsUri, tokens[1] + QStringLiteral("es"));
550 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Entry"));
551 writer.writeAttribute(QStringLiteral("Key"), tokens[1] + QString::number(d->mIndex));
552 writeValue(writer, value);
553 writer.writeEndElement();
554 writer.writeEndElement();
555 break;
556 }
557 case ExtendedField:
558 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ExtendedProperty"));
559 write(writer);
560 writeExtendedValue(writer, value);
561 writer.writeEndElement();
562 break;
563 default:
564 return false;
565 }
566
567 return true;
568 }
569
writeValue(QXmlStreamWriter & writer,const QVariant & value) const570 void EwsPropertyField::writeValue(QXmlStreamWriter &writer, const QVariant &value) const
571 {
572 switch (value.type()) {
573 case QVariant::StringList: {
574 const QStringList list = value.toStringList();
575 for (const QString &str : list) {
576 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("String"), str);
577 }
578 break;
579 }
580 case QVariant::String:
581 writer.writeCharacters(value.toString());
582 break;
583 default:
584 qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown variant type to write: %1").arg(QString::fromLatin1(value.typeName()));
585 }
586 }
587
writeExtendedValue(QXmlStreamWriter & writer,const QVariant & value) const588 void EwsPropertyField::writeExtendedValue(QXmlStreamWriter &writer, const QVariant &value) const
589 {
590 switch (value.type()) {
591 case QVariant::StringList: {
592 const QStringList list = value.toStringList();
593 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Values"));
594 for (const QString &str : list) {
595 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("Value"), str);
596 }
597 writer.writeEndElement();
598 break;
599 }
600 case QVariant::String:
601 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Value"));
602 writer.writeCharacters(value.toString());
603 writer.writeEndElement();
604 break;
605 default:
606 qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown variant type to write: %1").arg(QString::fromLatin1(value.typeName()));
607 }
608 }
609
type() const610 EwsPropertyField::Type EwsPropertyField::type() const
611 {
612 return d->mPropType;
613 }
614
uri() const615 QString EwsPropertyField::uri() const
616 {
617 if (d->mPropType == Field || d->mPropType == IndexedField) {
618 return d->mUri;
619 } else {
620 return QString();
621 }
622 }
623