File indexing completed on 2024-11-24 04:44:14
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Christian Mollekopf <mollekopf@kolabsys.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #include "v2helpers.h" 0008 0009 #include "pimkolab_debug.h" 0010 0011 #include <QBuffer> 0012 0013 namespace Kolab 0014 { 0015 void getAttachments(KCalendarCore::Incidence::Ptr incidence, const QStringList &attachments, const KMime::Message::Ptr &mimeData) 0016 { 0017 if (!incidence) { 0018 qCCritical(PIMKOLAB_LOG) << "Invalid incidence"; 0019 return; 0020 } 0021 for (const QString &name : attachments) { 0022 QByteArray type; 0023 KMime::Content *content = Mime::findContentByName(mimeData, name, type); 0024 if (!content) { // guard against malformed events with non-existent attachments 0025 qCWarning(PIMKOLAB_LOG) << "could not find attachment: " << name.toUtf8() << type; 0026 continue; 0027 } 0028 const QByteArray c = content->decodedContent().toBase64(); 0029 KCalendarCore::Attachment attachment(c, QString::fromLatin1(type)); 0030 attachment.setLabel(name); 0031 incidence->addAttachment(attachment); 0032 qCDebug(PIMKOLAB_LOG) << "ATTACHMENT NAME" << name << type; 0033 } 0034 } 0035 0036 static QImage getPicture(const QString &pictureAttachmentName, const KMime::Message::Ptr &data, QByteArray &type) 0037 { 0038 if (!data) { 0039 qCCritical(PIMKOLAB_LOG) << "empty message"; 0040 return {}; 0041 } 0042 KMime::Content *imgContent = Mime::findContentByName(data, pictureAttachmentName /*"kolab-picture.png"*/, type); 0043 if (!imgContent) { 0044 qCWarning(PIMKOLAB_LOG) << "could not find picture: " << pictureAttachmentName; 0045 return {}; 0046 } 0047 QByteArray imgData = imgContent->decodedContent(); 0048 QBuffer buffer(&imgData); 0049 buffer.open(QIODevice::ReadOnly); 0050 QImage image; 0051 bool success = false; 0052 if (type == "image/jpeg") { 0053 success = image.load(&buffer, "JPEG"); 0054 // FIXME I tried getting the code to interpret the picture as PNG, but the VCard implementation writes it as JPEG anyways... 0055 // if (success) { 0056 // QByteArray pic; 0057 // QBuffer b(&pic); 0058 // b.open(QIODevice::ReadWrite); 0059 // Q_ASSERT(image.save(&b, "PNG")); 0060 // b.close(); 0061 // Debug() << pic.toBase64(); 0062 // QBuffer b2(&pic); 0063 // b2.open(QIODevice::ReadOnly); 0064 // success = image.load(&b2, "PNG"); 0065 // b2.close(); 0066 // Q_ASSERT(success); 0067 // } 0068 } else { 0069 type = "image/png"; 0070 success = image.load(&buffer, "PNG"); 0071 } 0072 buffer.close(); 0073 if (!success) { 0074 qCWarning(PIMKOLAB_LOG) << "failed to load picture"; 0075 } 0076 return image; 0077 } 0078 0079 KContacts::Addressee addresseeFromKolab(const QByteArray &xmlData, const KMime::Message::Ptr &data) 0080 { 0081 if (!data) { 0082 qCCritical(PIMKOLAB_LOG) << "empty message"; 0083 return {}; 0084 } 0085 KContacts::Addressee addressee; 0086 // qCDebug(PIMKOLAB_LOG) << "xmlData " << xmlData; 0087 KolabV2::Contact contact(QString::fromUtf8(xmlData)); 0088 QByteArray type; 0089 const QString &pictureAttachmentName = contact.pictureAttachmentName(); 0090 if (!pictureAttachmentName.isEmpty()) { 0091 const QImage &img = getPicture(pictureAttachmentName, data, type); 0092 contact.setPicture(img, QString::fromLatin1(type)); 0093 } 0094 0095 const QString &logoAttachmentName = contact.logoAttachmentName(); 0096 if (!logoAttachmentName.isEmpty()) { 0097 contact.setLogo(getPicture(logoAttachmentName, data, type), QString::fromLatin1(type)); 0098 } 0099 0100 const QString &soundAttachmentName = contact.soundAttachmentName(); 0101 if (!soundAttachmentName.isEmpty()) { 0102 KMime::Content *content = Mime::findContentByName(data, soundAttachmentName /*"sound"*/, type); 0103 if (content) { 0104 const QByteArray &sData = content->decodedContent(); 0105 contact.setSound(sData); 0106 } else { 0107 qCWarning(PIMKOLAB_LOG) << "could not find sound: " << soundAttachmentName; 0108 } 0109 } 0110 contact.saveTo(&addressee); 0111 return addressee; 0112 } 0113 0114 KContacts::Addressee addresseeFromKolab(const QByteArray &xmlData, QString &pictureAttachmentName, QString &logoAttachmentName, QString &soundAttachmentName) 0115 { 0116 KContacts::Addressee addressee; 0117 KolabV2::Contact contact(QString::fromUtf8(xmlData)); 0118 pictureAttachmentName = contact.pictureAttachmentName(); 0119 logoAttachmentName = contact.logoAttachmentName(); 0120 soundAttachmentName = contact.soundAttachmentName(); 0121 contact.saveTo(&addressee); 0122 return addressee; 0123 } 0124 0125 static QByteArray createPicture(const QImage &img, const QString & /*format*/, QByteArray &type) 0126 { 0127 QByteArray pic; 0128 QBuffer buffer(&pic); 0129 buffer.open(QIODevice::WriteOnly); 0130 type = "image/png"; 0131 // FIXME it's not possible to save jpegs lossless, so we always use png. otherwise we would compress the image on every write. 0132 // if (format == "image/jpeg") { 0133 // type = "image/jpeg"; 0134 // img.save(&buffer, "JPEG"); 0135 // } else { 0136 img.save(&buffer, "PNG"); 0137 // } 0138 buffer.close(); 0139 return pic; 0140 } 0141 0142 KMime::Message::Ptr contactToKolabFormat(const KolabV2::Contact &contact, const QString &productId) 0143 { 0144 KMime::Message::Ptr message = Mime::createMessage(QByteArray(KOLAB_TYPE_CONTACT), false, productId.toLatin1()); 0145 if (!message) { 0146 qCCritical(PIMKOLAB_LOG) << "empty message"; 0147 return {}; 0148 } 0149 message->subject()->fromUnicodeString(contact.uid(), "utf-8"); 0150 message->from()->fromUnicodeString(contact.fullEmail(), "utf-8"); 0151 0152 KMime::Content *content = Mime::createMainPart(KOLAB_TYPE_CONTACT, contact.saveXML().toUtf8()); 0153 message->appendContent(content); 0154 0155 if (!contact.picture().isNull()) { 0156 QByteArray type; 0157 const QByteArray &pic = createPicture(contact.picture(), contact.pictureFormat(), type); 0158 content = Mime::createAttachmentPart(QByteArray(), type, /*"kolab-picture.png"*/ contact.pictureAttachmentName(), pic); 0159 message->appendContent(content); 0160 } 0161 0162 if (!contact.logo().isNull()) { 0163 QByteArray type; 0164 const QByteArray &pic = createPicture(contact.logo(), contact.logoFormat(), type); 0165 content = Mime::createAttachmentPart(QByteArray(), type, /*"kolab-logo.png"*/ contact.logoAttachmentName(), pic); 0166 message->appendContent(content); 0167 } 0168 0169 if (!contact.sound().isEmpty()) { 0170 content = Mime::createAttachmentPart(QByteArray(), "audio/unknown", /*"sound"*/ contact.soundAttachmentName(), contact.sound()); 0171 message->appendContent(content); 0172 } 0173 0174 message->assemble(); 0175 return message; 0176 } 0177 0178 KContacts::ContactGroup contactGroupFromKolab(const QByteArray &xmlData) 0179 { 0180 KContacts::ContactGroup contactGroup; 0181 // qCDebug(PIMKOLAB_LOG) << "xmlData " << xmlData; 0182 KolabV2::DistributionList distList(QString::fromUtf8(xmlData)); 0183 distList.saveTo(&contactGroup); 0184 return contactGroup; 0185 } 0186 0187 KMime::Message::Ptr distListToKolabFormat(const KolabV2::DistributionList &distList, const QString &productId) 0188 { 0189 KMime::Message::Ptr message = Mime::createMessage(KOLAB_TYPE_DISTLIST_V2, false, productId.toLatin1()); 0190 if (!message) { 0191 qCCritical(PIMKOLAB_LOG) << "empty message"; 0192 return {}; 0193 } 0194 message->subject()->fromUnicodeString(distList.uid(), "utf-8"); 0195 message->from()->fromUnicodeString(distList.uid(), "utf-8"); 0196 0197 KMime::Content *content = Mime::createMainPart(KOLAB_TYPE_DISTLIST_V2, distList.saveXML().toUtf8()); 0198 message->appendContent(content); 0199 0200 message->assemble(); 0201 return message; 0202 } 0203 0204 KMime::Message::Ptr noteFromKolab(const QByteArray &xmlData, const QDateTime &creationDate) 0205 { 0206 KolabV2::Note j; 0207 if (!j.load(QString::fromUtf8(xmlData))) { 0208 qCWarning(PIMKOLAB_LOG) << "failed to read note"; 0209 return {}; 0210 } 0211 0212 Akonadi::NoteUtils::NoteMessageWrapper note; 0213 note.setTitle(j.summary()); 0214 note.setText(j.body()); 0215 note.setFrom(QStringLiteral("kolab@kde4")); 0216 note.setCreationDate(creationDate); 0217 return note.message(); 0218 } 0219 0220 KMime::Message::Ptr noteToKolab(const KMime::Message::Ptr &msg, const QString &productId) 0221 { 0222 if (!msg) { 0223 qCCritical(PIMKOLAB_LOG) << "empty message"; 0224 return {}; 0225 } 0226 Akonadi::NoteUtils::NoteMessageWrapper note(msg); 0227 return Mime::createMessage(note.title(), QStringLiteral(KOLAB_TYPE_NOTE), QStringLiteral(KOLAB_TYPE_NOTE), noteToKolabXML(msg), false, productId); 0228 } 0229 0230 QByteArray noteToKolabXML(const KMime::Message::Ptr &msg) 0231 { 0232 if (!msg) { 0233 qCCritical(PIMKOLAB_LOG) << "empty message"; 0234 return {}; 0235 } 0236 Akonadi::NoteUtils::NoteMessageWrapper note(msg); 0237 KolabV2::Note j; 0238 j.setSummary(note.title()); 0239 j.setBody(note.text()); 0240 return j.saveXML().toUtf8(); 0241 } 0242 0243 QStringList readLegacyDictionaryConfiguration(const QByteArray &xmlData, QString &language) 0244 { 0245 QStringList dictionary; 0246 const QDomDocument xmlDoc = KolabV2::KolabBase::loadDocument(QString::fromUtf8(xmlData)); // TODO extract function from V2 format 0247 if (xmlDoc.isNull()) { 0248 qCCritical(PIMKOLAB_LOG) << "Failed to read the xml document"; 0249 return {}; 0250 } 0251 0252 QDomElement top = xmlDoc.documentElement(); 0253 0254 if (top.tagName() != QLatin1StringView("configuration")) { 0255 qCWarning(PIMKOLAB_LOG) << QStringLiteral("XML error: Top tag was %1 instead of the expected configuration").arg(top.tagName()); 0256 return {}; 0257 } 0258 0259 for (QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling()) { 0260 if (n.isComment() || !n.isElement()) { 0261 continue; 0262 } 0263 const QDomElement e = n.toElement(); 0264 const QString tagName = e.tagName(); 0265 if (tagName == QLatin1StringView("language")) { 0266 language = e.text(); 0267 } else if (tagName == QLatin1Char('e')) { 0268 dictionary.append(e.text()); 0269 } 0270 } 0271 return dictionary; 0272 } 0273 }