File indexing completed on 2024-11-24 04:44:13
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Sofia Balicka <balicka@kolabsys.com> 0003 * SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com> 0004 * 0005 * SPDX-License-Identifier: LGPL-3.0-or-later 0006 */ 0007 0008 #include "mimeobject.h" 0009 #include "conversion/commonconversion.h" 0010 #include "conversion/kabcconversion.h" 0011 #include "conversion/kcalconversion.h" 0012 #include "conversion/kolabconversion.h" 0013 #include "kolabformat/xmlobject.h" 0014 0015 #include "kolabformat/v2helpers.h" 0016 #include "libkolab-version.h" 0017 #include "mime/mimeutils.h" 0018 #include "pimkolab_debug.h" 0019 0020 #include <KRandom> 0021 #include <QString> 0022 #include <cstring> 0023 0024 Q_DECLARE_METATYPE(Kolab::Event) 0025 Q_DECLARE_METATYPE(Kolab::Todo) 0026 Q_DECLARE_METATYPE(Kolab::Journal) 0027 Q_DECLARE_METATYPE(Kolab::Contact) 0028 Q_DECLARE_METATYPE(Kolab::DistList) 0029 Q_DECLARE_METATYPE(Kolab::Note) 0030 Q_DECLARE_METATYPE(Kolab::Freebusy) 0031 Q_DECLARE_METATYPE(Kolab::Configuration) 0032 0033 static inline std::string eventKolabType() 0034 { 0035 return std::string(KOLAB_TYPE_EVENT); 0036 } 0037 0038 static inline std::string todoKolabType() 0039 { 0040 return std::string(KOLAB_TYPE_TASK); 0041 } 0042 0043 static inline std::string journalKolabType() 0044 { 0045 return std::string(KOLAB_TYPE_JOURNAL); 0046 } 0047 0048 static inline std::string contactKolabType() 0049 { 0050 return std::string(KOLAB_TYPE_CONTACT); 0051 } 0052 0053 static inline std::string distlistKolabType() 0054 { 0055 return std::string(KOLAB_TYPE_DISTLIST); 0056 } 0057 0058 static inline std::string distlistKolabTypeCompat() 0059 { 0060 return std::string(KOLAB_TYPE_DISTLIST_V2); 0061 } 0062 0063 static inline std::string noteKolabType() 0064 { 0065 return std::string(KOLAB_TYPE_NOTE); 0066 } 0067 0068 static inline std::string configurationKolabType() 0069 { 0070 return std::string(KOLAB_TYPE_CONFIGURATION); 0071 } 0072 0073 static inline std::string dictKolabType() 0074 { 0075 return std::string(KOLAB_TYPE_DICT); 0076 } 0077 0078 static inline std::string freebusyKolabType() 0079 { 0080 return std::string(KOLAB_TYPE_FREEBUSY); 0081 } 0082 0083 static inline std::string relationKolabType() 0084 { 0085 return std::string(KOLAB_TYPE_RELATION); 0086 } 0087 0088 static inline std::string xCalMimeType() 0089 { 0090 return std::string(MIME_TYPE_XCAL); 0091 } 0092 0093 static inline std::string xCardMimeType() 0094 { 0095 return std::string(MIME_TYPE_XCARD); 0096 } 0097 0098 static inline std::string kolabMimeType() 0099 { 0100 return std::string(MIME_TYPE_KOLAB); 0101 } 0102 0103 static std::string getProductId(const std::string &pId) 0104 { 0105 if (pId.empty()) { 0106 return LIBKOLAB_LIB_VERSION_STRING; 0107 } 0108 return pId + ' ' + LIBKOLAB_LIB_VERSION_STRING; 0109 } 0110 0111 namespace Kolab 0112 { 0113 static Kolab::ObjectType getObjectType(const std::string &type) 0114 { 0115 if (type == eventKolabType()) { 0116 return EventObject; 0117 } else if (type == todoKolabType()) { 0118 return TodoObject; 0119 } else if (type == journalKolabType()) { 0120 return JournalObject; 0121 } else if (type == contactKolabType()) { 0122 return ContactObject; 0123 } else if (type == distlistKolabType() || type == distlistKolabTypeCompat()) { 0124 return DistlistObject; 0125 } else if (type == noteKolabType()) { 0126 return NoteObject; 0127 } else if (type == freebusyKolabType()) { 0128 return FreebusyObject; 0129 } else if (strstr(type.c_str(), KOLAB_TYPE_DICT)) { // Previous versions appended the language to the type 0130 return DictionaryConfigurationObject; 0131 } else if (type == relationKolabType()) { 0132 return RelationConfigurationObject; 0133 } 0134 qCWarning(PIMKOLAB_LOG) << "Unknown object type: " << type; 0135 return Kolab::InvalidObject; 0136 } 0137 0138 static QByteArray getTypeString(Kolab::ObjectType type) 0139 { 0140 switch (type) { 0141 case EventObject: 0142 return KOLAB_TYPE_EVENT; 0143 case TodoObject: 0144 return KOLAB_TYPE_TASK; 0145 case JournalObject: 0146 return KOLAB_TYPE_JOURNAL; 0147 case FreebusyObject: 0148 return KOLAB_TYPE_FREEBUSY; 0149 case ContactObject: 0150 return KOLAB_TYPE_CONTACT; 0151 case DistlistObject: 0152 return KOLAB_TYPE_DISTLIST; 0153 case NoteObject: 0154 return KOLAB_TYPE_NOTE; 0155 case DictionaryConfigurationObject: 0156 return KOLAB_TYPE_CONFIGURATION; 0157 case RelationConfigurationObject: 0158 return KOLAB_TYPE_RELATION; 0159 default: 0160 qCCritical(PIMKOLAB_LOG) << "unknown type " << type; 0161 } 0162 return {}; 0163 } 0164 0165 static QByteArray getMimeType(Kolab::ObjectType type) 0166 { 0167 switch (type) { 0168 case EventObject: 0169 case TodoObject: 0170 case JournalObject: 0171 case FreebusyObject: 0172 return MIME_TYPE_XCAL; 0173 case ContactObject: 0174 case DistlistObject: 0175 return MIME_TYPE_XCARD; 0176 case NoteObject: 0177 case DictionaryConfigurationObject: 0178 case RelationConfigurationObject: 0179 return MIME_TYPE_KOLAB; 0180 default: 0181 qCCritical(PIMKOLAB_LOG) << "unknown type " << type; 0182 } 0183 return {}; 0184 } 0185 0186 static Kolab::ObjectType detectType(const KMime::Message::Ptr &msg) 0187 { 0188 const auto mimetypes{Mime::getContentMimeTypeList(msg)}; 0189 for (const QByteArray &type : mimetypes) { 0190 Kolab::ObjectType t = getObjectType(type.toStdString()); // works for v2 types 0191 if (t != InvalidObject) { 0192 return t; 0193 } 0194 } 0195 return InvalidObject; 0196 } 0197 0198 static void printMessageDebugInfo(const KMime::Message::Ptr &msg) 0199 { 0200 // TODO replace by Debug stream for Mimemessage 0201 qCDebug(PIMKOLAB_LOG) << "MessageId: " << msg->messageID()->asUnicodeString(); 0202 qCDebug(PIMKOLAB_LOG) << "Subject: " << msg->subject()->asUnicodeString(); 0203 // Debug() << msg->encodedContent(); 0204 } 0205 0206 //@cond PRIVATE 0207 class MIMEObjectPrivate 0208 { 0209 public: 0210 MIMEObjectPrivate() = default; 0211 0212 QVariant readKolabV2(const KMime::Message::Ptr &msg, Kolab::ObjectType objectType); 0213 QVariant readKolabV3(const KMime::Message::Ptr &msg, Kolab::ObjectType objectType); 0214 QVariant parseMimeMessage(const KMime::Message::Ptr &msg); 0215 QVariant parseMimeMessage(const std::string &s); 0216 0217 ObjectType mObjectType = InvalidObject; 0218 Version mVersion = KolabV3; 0219 ObjectType mOverrideObjectType = InvalidObject; 0220 Version mOverrideVersion = KolabV3; 0221 bool mDoOverrideVersion = false; 0222 QVariant mObject; 0223 }; 0224 //@endcond 0225 0226 static std::vector<Kolab::Attachment> getAttachments(const std::vector<Kolab::Attachment> &attachments, const KMime::Message::Ptr &msg) 0227 { 0228 std::vector<Kolab::Attachment> allAttachments; 0229 for (const Kolab::Attachment &attachment : attachments) { 0230 if (!attachment.uri().empty()) { 0231 const Kolab::Attachment extracted = Mime::getAttachment(attachment.uri(), msg); 0232 if (extracted.isValid()) { 0233 allAttachments.push_back(extracted); 0234 } 0235 } else { 0236 allAttachments.push_back(attachment); 0237 } 0238 } 0239 return allAttachments; 0240 } 0241 0242 static std::vector<Kolab::Attachment> getAttachments(const QStringList &attachmentNames, const KMime::Message::Ptr &msg) 0243 { 0244 std::vector<Kolab::Attachment> allAttachments; 0245 for (const QString &name : attachmentNames) { 0246 const Kolab::Attachment extracted = Mime::getAttachmentByName(name, msg); 0247 if (extracted.isValid()) { 0248 allAttachments.push_back(extracted); 0249 } 0250 } 0251 return allAttachments; 0252 } 0253 0254 QVariant MIMEObjectPrivate::readKolabV2(const KMime::Message::Ptr &msg, Kolab::ObjectType objectType) 0255 { 0256 if (objectType == DictionaryConfigurationObject) { 0257 KMime::Content *xmlContent = Mime::findContentByType(msg, "application/xml"); 0258 if (!xmlContent) { 0259 qCCritical(PIMKOLAB_LOG) << "no application/xml part found"; 0260 printMessageDebugInfo(msg); 0261 return InvalidObject; 0262 } 0263 const QByteArray &xmlData = xmlContent->decodedContent(); 0264 QString dictionaryLanguage; 0265 const QStringList entries = Kolab::readLegacyDictionaryConfiguration(xmlData, dictionaryLanguage); 0266 mObjectType = objectType; 0267 Kolab::Dictionary dictionary(Conversion::toStdString(dictionaryLanguage)); 0268 std::vector<std::string> convertedEntries; 0269 convertedEntries.reserve(entries.count()); 0270 for (const QString &value : entries) { 0271 convertedEntries.push_back(Conversion::toStdString(value)); 0272 } 0273 dictionary.setEntries(convertedEntries); 0274 return QVariant::fromValue(Kolab::Configuration(dictionary)); 0275 } 0276 KMime::Content *xmlContent = Mime::findContentByType(msg, getTypeString(objectType)); 0277 if (!xmlContent) { 0278 qCCritical(PIMKOLAB_LOG) << "no part with type" << getTypeString(objectType) << " found"; 0279 printMessageDebugInfo(msg); 0280 return {}; 0281 } 0282 const QByteArray &xmlData = xmlContent->decodedContent(); 0283 if (xmlData.isEmpty()) { 0284 qCCritical(PIMKOLAB_LOG) << "no content in message part with type" << getTypeString(objectType); 0285 printMessageDebugInfo(msg); 0286 return {}; 0287 } 0288 0289 QVariant variant; 0290 switch (objectType) { 0291 case EventObject: { 0292 QStringList attachments; 0293 auto kEvent = fromXML<KCalendarCore::Event::Ptr, KolabV2::Event>(xmlData, attachments); 0294 if (kEvent) { 0295 Kolab::Event event = Kolab::Conversion::fromKCalendarCore(*kEvent); 0296 event.setAttachments(getAttachments(attachments, msg)); 0297 variant = QVariant::fromValue(event); 0298 } 0299 break; 0300 } 0301 case TodoObject: { 0302 QStringList attachments; 0303 auto kTodo = fromXML<KCalendarCore::Todo::Ptr, KolabV2::Task>(xmlData, attachments); 0304 if (kTodo) { 0305 Kolab::Todo todo = Kolab::Conversion::fromKCalendarCore(*kTodo); 0306 todo.setAttachments(getAttachments(attachments, msg)); 0307 variant = QVariant::fromValue(todo); 0308 } 0309 break; 0310 } 0311 case JournalObject: { 0312 QStringList attachments; 0313 auto kJournal = fromXML<KCalendarCore::Journal::Ptr, KolabV2::Journal>(xmlData, attachments); 0314 if (kJournal) { 0315 Kolab::Journal journal = Kolab::Conversion::fromKCalendarCore(*kJournal); 0316 journal.setAttachments(getAttachments(attachments, msg)); 0317 variant = QVariant::fromValue(journal); 0318 } 0319 break; 0320 } 0321 case ContactObject: { 0322 KContacts::Addressee kContact = addresseeFromKolab(xmlData, msg); 0323 Kolab::Contact contact = Kolab::Conversion::fromKABC(kContact); 0324 variant = QVariant::fromValue(contact); 0325 break; 0326 } 0327 case DistlistObject: { 0328 KContacts::ContactGroup kContactGroup = contactGroupFromKolab(xmlData); 0329 Kolab::DistList distlist = Kolab::Conversion::fromKABC(kContactGroup); 0330 variant = QVariant::fromValue(distlist); 0331 break; 0332 } 0333 case NoteObject: { 0334 KMime::Message::Ptr kNote = noteFromKolab(xmlData, msg->date()->dateTime()); 0335 Kolab::Note note = Kolab::Conversion::fromNote(kNote); 0336 variant = QVariant::fromValue(note); 0337 break; 0338 } 0339 default: 0340 CRITICAL(QStringLiteral("no kolab object found ")); 0341 break; 0342 } 0343 if (ErrorHandler::errorOccured()) { 0344 printMessageDebugInfo(msg); 0345 return {}; 0346 } 0347 mObjectType = objectType; 0348 return variant; 0349 } 0350 0351 QVariant MIMEObjectPrivate::readKolabV3(const KMime::Message::Ptr &msg, Kolab::ObjectType objectType) 0352 { 0353 KMime::Content *const xmlContent = Mime::findContentByType(msg, getMimeType(objectType)); 0354 if (!xmlContent) { 0355 qCCritical(PIMKOLAB_LOG) << "no " << getMimeType(objectType) << " part found"; 0356 printMessageDebugInfo(msg); 0357 return InvalidObject; 0358 } 0359 const QByteArray &content = xmlContent->decodedContent(); 0360 const std::string xml = std::string(content.data(), content.size()); 0361 QVariant variant; 0362 switch (objectType) { 0363 case EventObject: { 0364 Kolab::Event event = Kolab::readEvent(xml, false); 0365 event.setAttachments(getAttachments(event.attachments(), msg)); 0366 variant = QVariant::fromValue<Kolab::Event>(event); 0367 break; 0368 } 0369 case TodoObject: { 0370 Kolab::Todo todo = Kolab::readTodo(xml, false); 0371 todo.setAttachments(getAttachments(todo.attachments(), msg)); 0372 variant = QVariant::fromValue<Kolab::Todo>(todo); 0373 break; 0374 } 0375 case JournalObject: { 0376 Kolab::Journal journal = Kolab::readJournal(xml, false); 0377 journal.setAttachments(getAttachments(journal.attachments(), msg)); 0378 variant = QVariant::fromValue<Kolab::Journal>(journal); 0379 break; 0380 } 0381 case ContactObject: 0382 variant = QVariant::fromValue<Kolab::Contact>(Kolab::readContact(xml, false)); 0383 break; 0384 case DistlistObject: 0385 variant = QVariant::fromValue<Kolab::DistList>(Kolab::readDistlist(xml, false)); 0386 break; 0387 case NoteObject: 0388 variant = QVariant::fromValue<Kolab::Note>(Kolab::readNote(xml, false)); 0389 break; 0390 case FreebusyObject: 0391 variant = QVariant::fromValue<Kolab::Freebusy>(Kolab::readFreebusy(xml, false)); 0392 break; 0393 case DictionaryConfigurationObject: 0394 case RelationConfigurationObject: 0395 variant = QVariant::fromValue<Kolab::Configuration>(Kolab::readConfiguration(xml, false)); 0396 break; 0397 default: 0398 qCCritical(PIMKOLAB_LOG) << "no kolab object found "; 0399 printMessageDebugInfo(msg); 0400 break; 0401 } 0402 0403 if (ErrorHandler::errorOccured()) { 0404 printMessageDebugInfo(msg); 0405 return {}; 0406 } 0407 mObjectType = objectType; 0408 return variant; 0409 } 0410 0411 QVariant MIMEObjectPrivate::parseMimeMessage(const KMime::Message::Ptr &msg) 0412 { 0413 ErrorHandler::clearErrors(); 0414 mObjectType = InvalidObject; 0415 if (msg->contents().isEmpty()) { 0416 qCCritical(PIMKOLAB_LOG) << "message has no contents (we likely failed to parse it correctly)"; 0417 printMessageDebugInfo(msg); 0418 return {}; 0419 } 0420 Kolab::ObjectType objectType = InvalidObject; 0421 if (mOverrideObjectType == InvalidObject) { 0422 if (KMime::Headers::Base *xKolabHeader = msg->headerByType(X_KOLAB_TYPE_HEADER)) { 0423 objectType = getObjectType(xKolabHeader->asUnicodeString().trimmed().toStdString()); 0424 } else { 0425 qCWarning(PIMKOLAB_LOG) << "could not find the X-Kolab-Type Header, trying autodetection"; 0426 // This works only for v2 messages atm. 0427 objectType = detectType(msg); 0428 } 0429 } else { 0430 objectType = mOverrideObjectType; 0431 } 0432 if (objectType == InvalidObject) { 0433 qCCritical(PIMKOLAB_LOG) << "unable to detect object type"; 0434 printMessageDebugInfo(msg); 0435 return {}; 0436 } 0437 0438 if (!mDoOverrideVersion) { 0439 KMime::Headers::Base *xKolabVersion = msg->headerByType(X_KOLAB_MIME_VERSION_HEADER); 0440 if (!xKolabVersion) { 0441 // For backwards compatibility to development versions, can be removed in future versions 0442 xKolabVersion = msg->headerByType(X_KOLAB_MIME_VERSION_HEADER_COMPAT); 0443 } 0444 if (!xKolabVersion || xKolabVersion->asUnicodeString() == KOLAB_VERSION_V2) { 0445 mVersion = KolabV2; 0446 } else { 0447 if (xKolabVersion->asUnicodeString() != KOLAB_VERSION_V3) { // TODO version compatibility check? 0448 qCWarning(PIMKOLAB_LOG) << "Kolab Version Header available but not on the same version as the implementation: " 0449 << xKolabVersion->asUnicodeString(); 0450 } 0451 mVersion = KolabV3; 0452 } 0453 } else { 0454 mVersion = mOverrideVersion; 0455 } 0456 0457 if (mVersion == KolabV2) { 0458 return readKolabV2(msg, objectType); 0459 } 0460 return readKolabV3(msg, objectType); 0461 } 0462 0463 QVariant MIMEObjectPrivate::parseMimeMessage(const std::string &s) 0464 { 0465 KMime::Message::Ptr msg(new KMime::Message); 0466 msg->setContent(QByteArray(s.c_str())); 0467 msg->parse(); 0468 return parseMimeMessage(msg); 0469 } 0470 0471 MIMEObject::MIMEObject() 0472 : d(new MIMEObjectPrivate) 0473 { 0474 } 0475 0476 MIMEObject::~MIMEObject() = default; 0477 0478 void MIMEObject::setObjectType(ObjectType type) 0479 { 0480 d->mOverrideObjectType = type; 0481 } 0482 0483 void MIMEObject::setVersion(Version version) 0484 { 0485 d->mOverrideVersion = version; 0486 d->mDoOverrideVersion = true; 0487 } 0488 0489 static std::string createCid() 0490 { 0491 return QStringLiteral("cid:%1@%2").arg(KRandom::randomString(16), QStringLiteral("kolab.resource.akonadi")).toStdString(); 0492 } 0493 0494 std::vector<Kolab::Attachment> convertToReferences(const std::vector<Kolab::Attachment> &attachments, std::vector<std::string> &attachmentCids) 0495 { 0496 std::vector<Kolab::Attachment> attachmentsWithReferences; 0497 for (const Kolab::Attachment &a : attachments) { 0498 Kolab::Attachment attachment; 0499 attachment.setLabel(a.label()); 0500 const std::string cid = a.uri().empty() ? createCid() : a.uri(); 0501 attachmentCids.push_back(cid); 0502 attachment.setUri(cid, a.mimetype()); // Serialize the attachment as attachment with uri, referencing the created mime-part 0503 attachmentsWithReferences.push_back(attachment); 0504 } 0505 return attachmentsWithReferences; 0506 } 0507 0508 template<class T> 0509 static T convertAttachmentsToReferences(const T &incidence, std::vector<std::string> &attachmentCids) 0510 { 0511 T removedAttachments = incidence; 0512 removedAttachments.setAttachments(convertToReferences(incidence.attachments(), attachmentCids)); 0513 return removedAttachments; 0514 } 0515 0516 static void addAttachments(KMime::Message::Ptr msg, const std::vector<Attachment> &attachments, std::vector<std::string> &attachmentCids) 0517 { 0518 int index = 0; 0519 for (const Attachment &attachment : attachments) { 0520 const std::string data = attachment.data(); 0521 const std::string cid = attachmentCids.empty() ? attachment.uri() : attachmentCids.at(index); 0522 msg->appendContent(Mime::createAttachmentPart(Mime::fromCid(QString::fromStdString(cid.c_str())).toLatin1(), 0523 QByteArray(attachment.mimetype().c_str()), 0524 QString::fromStdString(attachment.label()), 0525 QByteArray(data.c_str(), data.size()))); 0526 index++; 0527 } 0528 } 0529 0530 ObjectType MIMEObject::parseMessage(const std::string &msg) 0531 { 0532 d->mObject = d->parseMimeMessage(msg); 0533 return d->mObjectType; 0534 } 0535 0536 ObjectType MIMEObject::getType() const 0537 { 0538 return d->mObjectType; 0539 } 0540 0541 Version MIMEObject::getVersion() const 0542 { 0543 return d->mVersion; 0544 } 0545 0546 Kolab::Event MIMEObject::getEvent() const 0547 { 0548 return d->mObject.value<Kolab::Event>(); 0549 } 0550 0551 Kolab::Todo MIMEObject::getTodo() const 0552 { 0553 return d->mObject.value<Kolab::Todo>(); 0554 } 0555 0556 Kolab::Journal MIMEObject::getJournal() const 0557 { 0558 return d->mObject.value<Kolab::Journal>(); 0559 } 0560 0561 Kolab::Note MIMEObject::getNote() const 0562 { 0563 return d->mObject.value<Kolab::Note>(); 0564 } 0565 0566 Kolab::Contact MIMEObject::getContact() const 0567 { 0568 return d->mObject.value<Kolab::Contact>(); 0569 } 0570 0571 Kolab::DistList MIMEObject::getDistlist() const 0572 { 0573 return d->mObject.value<Kolab::DistList>(); 0574 } 0575 0576 Kolab::Freebusy MIMEObject::getFreebusy() const 0577 { 0578 return d->mObject.value<Kolab::Freebusy>(); 0579 } 0580 0581 Kolab::Configuration MIMEObject::getConfiguration() const 0582 { 0583 return d->mObject.value<Kolab::Configuration>(); 0584 } 0585 0586 std::string MIMEObject::writeEvent(const Event &event, Version version, const std::string &pId) 0587 { 0588 ErrorHandler::clearErrors(); 0589 const std::string productId = getProductId(pId); 0590 0591 KMime::Message::Ptr msg; 0592 Kolab::XMLObject xmlObject; 0593 std::vector<std::string> attachmentCids; 0594 if (version == KolabV3) { 0595 const std::string xml = xmlObject.writeEvent(convertAttachmentsToReferences(event, attachmentCids), version, productId); 0596 msg = Mime::createMessage(xCalMimeType(), eventKolabType(), xml, true, productId, event.organizer().email(), event.organizer().name(), event.uid()); 0597 } else if (version == KolabV2) { 0598 const std::string xml = xmlObject.writeEvent(event, version, productId); 0599 msg = Mime::createMessage(eventKolabType(), eventKolabType(), xml, false, productId, event.organizer().email(), event.organizer().name(), event.uid()); 0600 } 0601 addAttachments(msg, event.attachments(), attachmentCids); 0602 msg->assemble(); 0603 return msg->encodedContent().data(); 0604 } 0605 0606 Event MIMEObject::readEvent(const std::string &s) 0607 { 0608 return d->parseMimeMessage(s).value<Kolab::Event>(); 0609 } 0610 0611 std::string MIMEObject::writeTodo(const Todo &todo, Version version, const std::string &pId) 0612 { 0613 ErrorHandler::clearErrors(); 0614 const std::string productId = getProductId(pId); 0615 0616 KMime::Message::Ptr msg; 0617 Kolab::XMLObject xmlObject; 0618 std::vector<std::string> attachmentCids; 0619 if (version == KolabV3) { 0620 const std::string xml = xmlObject.writeTodo(convertAttachmentsToReferences(todo, attachmentCids), version, productId); 0621 msg = Mime::createMessage(xCalMimeType(), todoKolabType(), xml, true, productId, todo.organizer().email(), todo.organizer().name(), todo.uid()); 0622 } else if (version == KolabV2) { 0623 const std::string xml = xmlObject.writeTodo(todo, version, productId); 0624 msg = Mime::createMessage(todoKolabType(), todoKolabType(), xml, false, productId, todo.organizer().email(), todo.organizer().name(), todo.uid()); 0625 } 0626 addAttachments(msg, todo.attachments(), attachmentCids); 0627 msg->assemble(); 0628 return msg->encodedContent().data(); 0629 } 0630 0631 Todo MIMEObject::readTodo(const std::string &s) 0632 { 0633 return d->parseMimeMessage(s).value<Kolab::Todo>(); 0634 } 0635 0636 std::string MIMEObject::writeJournal(const Journal &journal, Version version, const std::string &pId) 0637 { 0638 ErrorHandler::clearErrors(); 0639 const std::string productId = getProductId(pId); 0640 0641 KMime::Message::Ptr msg; 0642 Kolab::XMLObject xmlObject; 0643 std::vector<std::string> attachmentCids; 0644 if (version == KolabV3) { 0645 const std::string xml = xmlObject.writeJournal(convertAttachmentsToReferences(journal, attachmentCids), version, productId); 0646 msg = Mime::createMessage(xCalMimeType(), journalKolabType(), xml, true, productId, std::string(), std::string(), journal.uid()); 0647 } else if (version == KolabV2) { 0648 const std::string xml = xmlObject.writeJournal(journal, version, productId); 0649 msg = Mime::createMessage(journalKolabType(), journalKolabType(), xml, false, productId, std::string(), std::string(), journal.uid()); 0650 } 0651 addAttachments(msg, journal.attachments(), attachmentCids); 0652 msg->assemble(); 0653 return msg->encodedContent().data(); 0654 } 0655 0656 Journal MIMEObject::readJournal(const std::string &s) 0657 { 0658 return d->parseMimeMessage(s).value<Kolab::Journal>(); 0659 } 0660 0661 std::string MIMEObject::writeNote(const Note ¬e, Version version, const std::string &pId) 0662 { 0663 ErrorHandler::clearErrors(); 0664 const std::string productId = getProductId(pId); 0665 0666 KMime::Message::Ptr msg; 0667 Kolab::XMLObject xmlObject; 0668 std::vector<std::string> attachmentCids; 0669 if (version == KolabV3) { 0670 const std::string xml = xmlObject.writeNote(convertAttachmentsToReferences(note, attachmentCids), version, productId); 0671 msg = Mime::createMessage(kolabMimeType(), noteKolabType(), xml, true, productId, std::string(), std::string(), note.uid()); 0672 } else if (version == KolabV2) { 0673 const std::string xml = xmlObject.writeNote(note, version, productId); 0674 msg = Mime::createMessage(noteKolabType(), noteKolabType(), xml, false, productId, std::string(), std::string(), note.uid()); 0675 } 0676 addAttachments(msg, note.attachments(), attachmentCids); 0677 msg->assemble(); 0678 return msg->encodedContent().data(); 0679 } 0680 0681 Note MIMEObject::readNote(const std::string &s) 0682 { 0683 return d->parseMimeMessage(s).value<Kolab::Note>(); 0684 } 0685 0686 std::string MIMEObject::writeContact(const Contact &contact, Version version, const std::string &pId) 0687 { 0688 ErrorHandler::clearErrors(); 0689 const std::string productId = getProductId(pId); 0690 0691 KMime::Message::Ptr msg; 0692 Kolab::XMLObject xmlObject; 0693 const std::string xml = xmlObject.writeContact(contact, version, productId); 0694 0695 Email preferredEmail = !contact.emailAddresses().empty() ? contact.emailAddresses().at(contact.emailAddressPreferredIndex()) : Email(); 0696 QPair<std::string, std::string> pair = Conversion::fromMailto(preferredEmail.address()); 0697 std::string name = pair.second; 0698 std::string email = pair.first; 0699 if (name.empty()) { 0700 name = contact.name(); 0701 } 0702 0703 if (version == KolabV3) { 0704 msg = Mime::createMessage(xCardMimeType(), contactKolabType(), xml, true, productId, email, name, contact.uid()); 0705 } else if (version == KolabV2) { 0706 msg = Mime::createMessage(contactKolabType(), contactKolabType(), xml, false, productId, email, name, contact.uid()); 0707 } 0708 msg->assemble(); 0709 return msg->encodedContent().data(); 0710 } 0711 0712 Contact MIMEObject::readContact(const std::string &s) 0713 { 0714 return d->parseMimeMessage(s).value<Kolab::Contact>(); 0715 } 0716 0717 std::string MIMEObject::writeDistlist(const DistList &distlist, Version version, const std::string &pId) 0718 { 0719 ErrorHandler::clearErrors(); 0720 const std::string productId = getProductId(pId); 0721 0722 KMime::Message::Ptr msg; 0723 Kolab::XMLObject xmlObject; 0724 const std::string xml = xmlObject.writeDistlist(distlist, version, productId); 0725 if (version == KolabV3) { 0726 msg = Mime::createMessage(xCardMimeType(), distlistKolabType(), xml, true, productId, std::string(), std::string(), distlist.uid()); 0727 } else if (version == KolabV2) { 0728 msg = Mime::createMessage(distlistKolabType(), distlistKolabType(), xml, false, productId, std::string(), std::string(), distlist.uid()); 0729 } 0730 msg->assemble(); 0731 return msg->encodedContent().data(); 0732 } 0733 0734 DistList MIMEObject::readDistlist(const std::string &s) 0735 { 0736 return d->parseMimeMessage(s).value<Kolab::DistList>(); 0737 } 0738 0739 std::string MIMEObject::writeConfiguration(const Configuration &configuration, Version version, const std::string &pId) 0740 { 0741 ErrorHandler::clearErrors(); 0742 const std::string productId = getProductId(pId); 0743 0744 KMime::Message::Ptr msg; 0745 Kolab::XMLObject xmlObject; 0746 const std::string xml = xmlObject.writeConfiguration(configuration, version, productId); 0747 std::string kolabType; 0748 switch (configuration.type()) { 0749 case Kolab::Configuration::TypeDictionary: 0750 kolabType = dictKolabType(); 0751 break; 0752 case Kolab::Configuration::TypeRelation: 0753 kolabType = relationKolabType(); 0754 break; 0755 case Kolab::Configuration::TypeSnippet: 0756 kolabType = configurationKolabType(); 0757 break; 0758 case Kolab::Configuration::TypeFileDriver: 0759 kolabType = configurationKolabType(); 0760 break; 0761 case Kolab::Configuration::TypeCategoryColor: 0762 kolabType = configurationKolabType(); 0763 break; 0764 default: 0765 break; 0766 } 0767 if (version == KolabV3) { 0768 msg = Mime::createMessage(kolabMimeType(), kolabType, xml, true, productId, std::string(), std::string(), configuration.uid()); 0769 } else if (version == KolabV2) { 0770 qCCritical(PIMKOLAB_LOG) << "Not available in KolabV2"; 0771 } 0772 msg->assemble(); 0773 return msg->encodedContent().data(); 0774 } 0775 0776 Configuration MIMEObject::readConfiguration(const std::string &s) 0777 { 0778 return d->parseMimeMessage(s).value<Kolab::Configuration>(); 0779 } 0780 0781 std::string MIMEObject::writeFreebusy(const Freebusy &freebusy, Version version, const std::string &pId) 0782 { 0783 ErrorHandler::clearErrors(); 0784 const std::string productId = getProductId(pId); 0785 0786 KMime::Message::Ptr msg; 0787 Kolab::XMLObject xmlObject; 0788 const std::string xml = xmlObject.writeFreebusy(freebusy, version, productId); 0789 if (version == KolabV3) { 0790 msg = Mime::createMessage(xCalMimeType(), freebusyKolabType(), xml, true, productId, std::string(), std::string(), freebusy.uid()); 0791 } else if (version == KolabV2) { 0792 qCCritical(PIMKOLAB_LOG) << "Not available in KolabV2"; 0793 } 0794 msg->assemble(); 0795 return msg->encodedContent().data(); 0796 } 0797 0798 Freebusy MIMEObject::readFreebusy(const std::string &s) 0799 { 0800 return d->parseMimeMessage(s).value<Kolab::Freebusy>(); 0801 } 0802 }