File indexing completed on 2024-12-22 04:57:00
0001 /* 0002 SPDX-FileCopyrightText: 2017 Krzysztof Nowicki <krissn@op.pl> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ewsattachment.h" 0008 0009 #include <QBitArray> 0010 0011 #include "ewsclient_debug.h" 0012 #include "ewsxml.h" 0013 0014 class EwsAttachmentPrivate : public QSharedData 0015 { 0016 public: 0017 EwsAttachmentPrivate(); 0018 ~EwsAttachmentPrivate(); 0019 0020 enum Field { 0021 Id = 0, 0022 Name, 0023 ContentType, 0024 ContentId, 0025 ContentLocation, 0026 Size, 0027 LastModifiedTime, 0028 IsInline, 0029 IsContactPhoto, 0030 Content, 0031 Item, 0032 NumFields, 0033 }; 0034 0035 EwsAttachment::Type mType; 0036 QString mId; 0037 QString mName; 0038 QString mContentType; 0039 QString mContentId; 0040 QString mContentLocation; 0041 long mSize = 0; 0042 QDateTime mLastModifiedTime; 0043 bool mIsInline = false; 0044 bool mIsContactPhoto = false; 0045 QByteArray mContent; 0046 EwsItem mItem; 0047 bool mValid = false; 0048 QBitArray mValidFields; 0049 }; 0050 0051 EwsAttachmentPrivate::EwsAttachmentPrivate() 0052 : mType(EwsAttachment::UnknownAttachment) 0053 , mValidFields(NumFields) 0054 { 0055 } 0056 0057 EwsAttachmentPrivate::~EwsAttachmentPrivate() 0058 { 0059 } 0060 0061 EwsAttachment::EwsAttachment() 0062 : d(new EwsAttachmentPrivate()) 0063 { 0064 } 0065 0066 EwsAttachment::~EwsAttachment() 0067 { 0068 } 0069 0070 EwsAttachment::EwsAttachment(QXmlStreamReader &reader) 0071 : d(new EwsAttachmentPrivate()) 0072 { 0073 bool ok = true; 0074 0075 if (reader.namespaceUri() != ewsTypeNsUri) { 0076 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in Attachment element:") << reader.namespaceUri(); 0077 reader.skipCurrentElement(); 0078 return; 0079 } 0080 const QStringView readerName = reader.name(); 0081 if (readerName == QLatin1StringView("ItemAttachment")) { 0082 d->mType = ItemAttachment; 0083 } else if (readerName == QLatin1StringView("FileAttachment")) { 0084 d->mType = FileAttachment; 0085 } else if (readerName == QLatin1StringView("ReferenceAttachment")) { 0086 d->mType = ReferenceAttachment; 0087 } else { 0088 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unknown attachment type %1").arg(readerName.toString()); 0089 ok = false; 0090 } 0091 0092 // Skip this attachment type as it's not clearly documented. 0093 if (d->mType == ReferenceAttachment) { 0094 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Attachment type ReferenceAttachment not fully supported"); 0095 reader.skipCurrentElement(); 0096 d->mValid = true; 0097 return; 0098 } 0099 0100 while (ok && reader.readNextStartElement()) { 0101 if (reader.namespaceUri() != ewsTypeNsUri) { 0102 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Unexpected namespace in Attachment element:") << reader.namespaceUri(); 0103 reader.skipCurrentElement(); 0104 ok = false; 0105 break; 0106 } 0107 0108 const QString elmName = reader.name().toString(); 0109 if (elmName == QLatin1StringView("AttachmentId")) { 0110 QXmlStreamAttributes attrs = reader.attributes(); 0111 if (!attrs.hasAttribute(QStringLiteral("Id"))) { 0112 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - missing Id in AttachmentId element.").arg(QStringLiteral("Attachment")); 0113 reader.skipCurrentElement(); 0114 ok = false; 0115 } else { 0116 d->mId = attrs.value(QStringLiteral("Id")).toString(); 0117 d->mValidFields.setBit(EwsAttachmentPrivate::Id); 0118 } 0119 reader.skipCurrentElement(); 0120 } else if (elmName == QLatin1StringView("Name")) { 0121 d->mName = readXmlElementValue<QString>(reader, ok, QStringLiteral("Attachment")); 0122 d->mValidFields.setBit(EwsAttachmentPrivate::Name, ok); 0123 } else if (elmName == QLatin1StringView("ContentType")) { 0124 d->mContentType = readXmlElementValue<QString>(reader, ok, QStringLiteral("Attachment")); 0125 d->mValidFields.setBit(EwsAttachmentPrivate::ContentType, ok); 0126 } else if (elmName == QLatin1StringView("ContentId")) { 0127 d->mContentId = readXmlElementValue<QString>(reader, ok, QStringLiteral("Attachment")); 0128 d->mValidFields.setBit(EwsAttachmentPrivate::ContentId, ok); 0129 } else if (elmName == QLatin1StringView("ContentLocation")) { 0130 d->mContentLocation = readXmlElementValue<QString>(reader, ok, QStringLiteral("Attachment")); 0131 d->mValidFields.setBit(EwsAttachmentPrivate::ContentLocation, ok); 0132 } else if (elmName == QLatin1StringView("AttachmentOriginalUrl")) { 0133 // Ignore 0134 reader.skipCurrentElement(); 0135 } else if (elmName == QLatin1StringView("Size")) { 0136 d->mSize = readXmlElementValue<long>(reader, ok, QStringLiteral("Attachment")); 0137 d->mValidFields.setBit(EwsAttachmentPrivate::Size, ok); 0138 } else if (elmName == QLatin1StringView("LastModifiedTime")) { 0139 d->mLastModifiedTime = readXmlElementValue<QDateTime>(reader, ok, QStringLiteral("Attachment")); 0140 d->mValidFields.setBit(EwsAttachmentPrivate::LastModifiedTime, ok); 0141 } else if (elmName == QLatin1StringView("IsInline")) { 0142 d->mIsInline = readXmlElementValue<bool>(reader, ok, QStringLiteral("Attachment")); 0143 d->mValidFields.setBit(EwsAttachmentPrivate::IsInline, ok); 0144 } else if (d->mType == FileAttachment && elmName == QLatin1StringView("IsContactPhoto")) { 0145 d->mIsContactPhoto = readXmlElementValue<bool>(reader, ok, QStringLiteral("Attachment")); 0146 d->mValidFields.setBit(EwsAttachmentPrivate::IsContactPhoto, ok); 0147 } else if (d->mType == FileAttachment && elmName == QLatin1StringView("Content")) { 0148 d->mContent = readXmlElementValue<QByteArray>(reader, ok, QStringLiteral("Attachment")); 0149 d->mValidFields.setBit(EwsAttachmentPrivate::Content, ok); 0150 } else if (d->mType == ItemAttachment 0151 && (elmName == QLatin1StringView("Item") || elmName == QLatin1StringView("Message") || elmName == QLatin1StringView("CalendarItem") 0152 || elmName == QLatin1StringView("Contact") || elmName == QLatin1StringView("MeetingMessage") 0153 || elmName == QLatin1StringView("MeetingRequest") || elmName == QLatin1StringView("MeetingResponse") 0154 || elmName == QLatin1StringView("MeetingCancellation") || elmName == QLatin1StringView("Task"))) { 0155 d->mItem = EwsItem(reader); 0156 if (!d->mItem.isValid()) { 0157 qCWarningNC(EWSCLI_LOG) 0158 << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(QStringLiteral("Attachment"), QStringLiteral("Item")); 0159 reader.skipCurrentElement(); 0160 ok = false; 0161 } else { 0162 d->mValidFields.setBit(EwsAttachmentPrivate::Item); 0163 } 0164 } else { 0165 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - unknown %2 element.").arg(QStringLiteral("Attachment"), elmName); 0166 reader.skipCurrentElement(); 0167 ok = false; 0168 } 0169 } 0170 0171 if (!ok) { 0172 reader.skipCurrentElement(); 0173 } 0174 d->mValid = ok; 0175 } 0176 0177 EwsAttachment::EwsAttachment(const EwsAttachment &other) 0178 : d(other.d) 0179 { 0180 } 0181 0182 EwsAttachment::EwsAttachment(EwsAttachment &&other) 0183 : d(std::move(other.d)) 0184 { 0185 } 0186 0187 EwsAttachment &EwsAttachment::operator=(EwsAttachment &&other) 0188 { 0189 d = std::move(other.d); 0190 return *this; 0191 } 0192 0193 EwsAttachment &EwsAttachment::operator=(const EwsAttachment &other) 0194 { 0195 d = other.d; 0196 return *this; 0197 } 0198 0199 void EwsAttachment::write(QXmlStreamWriter &writer) const 0200 { 0201 QString elmName; 0202 switch (d->mType) { 0203 case ItemAttachment: 0204 elmName = QStringLiteral("ItemAttachment"); 0205 break; 0206 case FileAttachment: 0207 elmName = QStringLiteral("FileAttachment"); 0208 break; 0209 case ReferenceAttachment: 0210 elmName = QStringLiteral("ReferenceAttachment"); 0211 break; 0212 default: 0213 qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to write Attachment element - invalid attachment type."); 0214 return; 0215 } 0216 writer.writeStartElement(ewsTypeNsUri, elmName); 0217 0218 if (d->mType == ReferenceAttachment) { 0219 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Attachment type ReferenceAttachment not fully supported"); 0220 writer.writeEndElement(); 0221 return; 0222 } 0223 0224 if (d->mValidFields[EwsAttachmentPrivate::Id]) { 0225 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("AttachmentId")); 0226 writer.writeAttribute(QStringLiteral("Id"), d->mId); 0227 writer.writeEndElement(); 0228 } 0229 if (d->mValidFields[EwsAttachmentPrivate::Name]) { 0230 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("Name"), d->mName); 0231 } 0232 if (d->mValidFields[EwsAttachmentPrivate::ContentType]) { 0233 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("ContentType"), d->mContentType); 0234 } 0235 if (d->mValidFields[EwsAttachmentPrivate::ContentId]) { 0236 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("ContentId"), d->mContentId); 0237 } 0238 if (d->mValidFields[EwsAttachmentPrivate::ContentLocation]) { 0239 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("ContentLocation"), d->mContentLocation); 0240 } 0241 if (d->mValidFields[EwsAttachmentPrivate::Size]) { 0242 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("Size"), QString::number(d->mSize)); 0243 } 0244 if (d->mValidFields[EwsAttachmentPrivate::LastModifiedTime]) { 0245 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("LastModifiedTime"), d->mLastModifiedTime.toString(Qt::ISODate)); 0246 } 0247 if (d->mValidFields[EwsAttachmentPrivate::IsInline]) { 0248 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("IsInline"), d->mIsInline ? QStringLiteral("true") : QStringLiteral("false")); 0249 } 0250 if (d->mType == FileAttachment) { 0251 if (d->mValidFields[EwsAttachmentPrivate::IsContactPhoto]) { 0252 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("IsContactPhoto"), d->mIsContactPhoto ? QStringLiteral("true") : QStringLiteral("false")); 0253 } 0254 if (d->mValidFields[EwsAttachmentPrivate::Content]) { 0255 writer.writeTextElement(ewsTypeNsUri, QStringLiteral("Content"), QString::fromLatin1(d->mContent.toBase64())); 0256 } 0257 } else if (d->mType == ItemAttachment) { 0258 if (d->mValidFields[EwsAttachmentPrivate::Item]) { 0259 d->mItem.write(writer); 0260 } 0261 } 0262 0263 writer.writeEndElement(); 0264 } 0265 0266 bool EwsAttachment::isValid() const 0267 { 0268 return d->mValid; 0269 } 0270 0271 EwsAttachment::Type EwsAttachment::type() const 0272 { 0273 return d->mType; 0274 } 0275 0276 void EwsAttachment::setType(Type type) 0277 { 0278 d->mType = type; 0279 } 0280 0281 QString EwsAttachment::id() const 0282 { 0283 return d->mId; 0284 } 0285 0286 void EwsAttachment::setId(const QString &id) 0287 { 0288 d->mId = id; 0289 d->mValidFields.setBit(EwsAttachmentPrivate::Id); 0290 } 0291 0292 void EwsAttachment::resetId() 0293 { 0294 d->mValidFields.clearBit(EwsAttachmentPrivate::Id); 0295 } 0296 0297 bool EwsAttachment::hasId() const 0298 { 0299 return d->mValidFields[EwsAttachmentPrivate::Id]; 0300 } 0301 0302 QString EwsAttachment::name() const 0303 { 0304 return d->mName; 0305 } 0306 0307 void EwsAttachment::setName(const QString &name) 0308 { 0309 d->mName = name; 0310 d->mValidFields.setBit(EwsAttachmentPrivate::Name); 0311 } 0312 0313 void EwsAttachment::resetName() 0314 { 0315 d->mValidFields.clearBit(EwsAttachmentPrivate::Name); 0316 } 0317 0318 bool EwsAttachment::hasName() const 0319 { 0320 return d->mValidFields[EwsAttachmentPrivate::Name]; 0321 } 0322 0323 QString EwsAttachment::contentType() const 0324 { 0325 return d->mContentType; 0326 } 0327 0328 void EwsAttachment::setContentType(const QString &contentType) 0329 { 0330 d->mContentType = contentType; 0331 d->mValidFields.setBit(EwsAttachmentPrivate::ContentType); 0332 } 0333 0334 void EwsAttachment::resetContentType() 0335 { 0336 d->mValidFields.clearBit(EwsAttachmentPrivate::ContentType); 0337 } 0338 0339 bool EwsAttachment::hasContentType() const 0340 { 0341 return d->mValidFields[EwsAttachmentPrivate::ContentType]; 0342 } 0343 0344 QString EwsAttachment::contentId() const 0345 { 0346 return d->mContentId; 0347 } 0348 0349 void EwsAttachment::setContentId(const QString &contentId) 0350 { 0351 d->mContentId = contentId; 0352 d->mValidFields.setBit(EwsAttachmentPrivate::ContentId); 0353 } 0354 0355 void EwsAttachment::resetContentId() 0356 { 0357 d->mValidFields.clearBit(EwsAttachmentPrivate::ContentId); 0358 } 0359 0360 bool EwsAttachment::hasContentId() const 0361 { 0362 return d->mValidFields[EwsAttachmentPrivate::ContentId]; 0363 } 0364 0365 QString EwsAttachment::contentLocation() const 0366 { 0367 return d->mContentLocation; 0368 } 0369 0370 void EwsAttachment::setContentLocation(const QString &contentLocation) 0371 { 0372 d->mContentLocation = contentLocation; 0373 d->mValidFields.setBit(EwsAttachmentPrivate::ContentLocation); 0374 } 0375 0376 void EwsAttachment::resetContentLocation() 0377 { 0378 d->mValidFields.clearBit(EwsAttachmentPrivate::ContentLocation); 0379 } 0380 0381 bool EwsAttachment::hasContentLocation() const 0382 { 0383 return d->mValidFields[EwsAttachmentPrivate::ContentLocation]; 0384 } 0385 0386 long EwsAttachment::size() const 0387 { 0388 return d->mSize; 0389 } 0390 0391 void EwsAttachment::setSize(long size) 0392 { 0393 d->mSize = size; 0394 d->mValidFields.setBit(EwsAttachmentPrivate::Size); 0395 } 0396 0397 void EwsAttachment::resetSize() 0398 { 0399 d->mValidFields.clearBit(EwsAttachmentPrivate::Size); 0400 } 0401 0402 bool EwsAttachment::hasSize() const 0403 { 0404 return d->mValidFields[EwsAttachmentPrivate::Size]; 0405 } 0406 0407 QDateTime EwsAttachment::lastModifiedTime() const 0408 { 0409 return d->mLastModifiedTime; 0410 } 0411 0412 void EwsAttachment::setLastModifiedTime(const QDateTime &time) 0413 { 0414 d->mLastModifiedTime = time; 0415 d->mValidFields.setBit(EwsAttachmentPrivate::LastModifiedTime); 0416 } 0417 0418 void EwsAttachment::resetLastModifiedTime() 0419 { 0420 d->mValidFields.clearBit(EwsAttachmentPrivate::LastModifiedTime); 0421 } 0422 0423 bool EwsAttachment::hasLastModifiedTime() const 0424 { 0425 return d->mValidFields[EwsAttachmentPrivate::LastModifiedTime]; 0426 } 0427 0428 bool EwsAttachment::isInline() const 0429 { 0430 return d->mIsInline; 0431 } 0432 0433 void EwsAttachment::setIsInline(bool isInline) 0434 { 0435 d->mIsInline = isInline; 0436 d->mValidFields.setBit(EwsAttachmentPrivate::IsInline); 0437 } 0438 0439 void EwsAttachment::resetIsInline() 0440 { 0441 d->mValidFields.clearBit(EwsAttachmentPrivate::IsInline); 0442 } 0443 0444 bool EwsAttachment::hasIsInline() const 0445 { 0446 return d->mValidFields[EwsAttachmentPrivate::IsInline]; 0447 } 0448 0449 bool EwsAttachment::isContactPhoto() const 0450 { 0451 return d->mIsContactPhoto; 0452 } 0453 0454 void EwsAttachment::setIsContactPhoto(bool isContactPhoto) 0455 { 0456 d->mIsContactPhoto = isContactPhoto; 0457 d->mValidFields.setBit(EwsAttachmentPrivate::IsContactPhoto); 0458 } 0459 0460 void EwsAttachment::resetIsContactPhoto() 0461 { 0462 d->mValidFields.clearBit(EwsAttachmentPrivate::IsContactPhoto); 0463 } 0464 0465 bool EwsAttachment::hasIsContactPhoto() const 0466 { 0467 return d->mValidFields[EwsAttachmentPrivate::IsContactPhoto]; 0468 } 0469 0470 QByteArray EwsAttachment::content() const 0471 { 0472 return d->mContent; 0473 } 0474 0475 void EwsAttachment::setContent(const QByteArray &content) 0476 { 0477 d->mContent = content; 0478 d->mValidFields.setBit(EwsAttachmentPrivate::Content); 0479 } 0480 0481 void EwsAttachment::resetContent() 0482 { 0483 d->mValidFields.clearBit(EwsAttachmentPrivate::Content); 0484 } 0485 0486 bool EwsAttachment::hasContent() const 0487 { 0488 return d->mValidFields[EwsAttachmentPrivate::Content]; 0489 } 0490 0491 const EwsItem &EwsAttachment::item() const 0492 { 0493 return d->mItem; 0494 } 0495 0496 void EwsAttachment::setItem(const EwsItem &item) 0497 { 0498 d->mItem = item; 0499 d->mValidFields.setBit(EwsAttachmentPrivate::Item); 0500 } 0501 0502 void EwsAttachment::resetItem() 0503 { 0504 d->mValidFields.clearBit(EwsAttachmentPrivate::Item); 0505 } 0506 0507 bool EwsAttachment::hasItem() const 0508 { 0509 return d->mValidFields[EwsAttachmentPrivate::Item]; 0510 }