File indexing completed on 2024-11-24 04:44:12

0001 /*
0002 
0003     SPDX-FileCopyrightText: 2012 Christian Mollekopf <chrigi_1@fastmail.fm>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include "icalendar.h"
0009 #include "imip.h"
0010 #include "libkolab-version.h"
0011 #include "pimkolab_debug.h"
0012 
0013 #include <KMime/Message>
0014 
0015 #include "conversion/commonconversion.h"
0016 #include "conversion/kcalconversion.h"
0017 #include "mime/mimeutils.h"
0018 #include <KCalendarCore/Event>
0019 #include <KCalendarCore/ICalFormat>
0020 #include <KCalendarCore/MemoryCalendar>
0021 
0022 #include <KLocalizedString>
0023 
0024 #include <QTimeZone>
0025 
0026 #include <iostream>
0027 
0028 namespace Kolab
0029 {
0030 std::string toICal(const std::vector<Event> &events)
0031 {
0032     KCalendarCore::Calendar::Ptr calendar(new KCalendarCore::MemoryCalendar(Kolab::Conversion::getTimeSpec(true, std::string())));
0033     for (const Event &event : events) {
0034         KCalendarCore::Event::Ptr kcalEvent = Conversion::toKCalendarCore(event);
0035         kcalEvent->setCreated(QDateTime::currentDateTimeUtc()); // sets dtstamp
0036         calendar->addEvent(kcalEvent);
0037     }
0038     KCalendarCore::ICalFormat format;
0039     format.setApplication(QStringLiteral("libkolab"), QStringLiteral(LIBKOLAB_LIB_VERSION_STRING));
0040     //     qCDebug(PIMKOLAB_LOG) << format.createScheduleMessage(calendar->events().first(), KCalendarCore::iTIPRequest);
0041 
0042     return Conversion::toStdString(format.toString(calendar));
0043 }
0044 
0045 std::vector<Event> fromICalEvents(const std::string &input)
0046 {
0047     KCalendarCore::Calendar::Ptr calendar(new KCalendarCore::MemoryCalendar(Kolab::Conversion::getTimeSpec(true, std::string())));
0048     KCalendarCore::ICalFormat format;
0049     format.setApplication(QStringLiteral("libkolab"), QStringLiteral(LIBKOLAB_LIB_VERSION_STRING));
0050     format.fromString(calendar, Conversion::fromStdString(input));
0051     std::vector<Event> events;
0052     const auto eventsList = calendar->events();
0053     for (const KCalendarCore::Event::Ptr &event : eventsList) {
0054         events.push_back(Conversion::fromKCalendarCore(*event));
0055     }
0056     return events;
0057 }
0058 
0059 ITipHandler::ITipHandler()
0060     : mMethod(iTIPNoMethod)
0061 {
0062 }
0063 
0064 ITipHandler::ITipMethod mapFromKCalendarCore(KCalendarCore::iTIPMethod method)
0065 {
0066     Q_ASSERT((int)KCalendarCore::iTIPPublish == (int)ITipHandler::iTIPPublish);
0067     Q_ASSERT((int)KCalendarCore::iTIPNoMethod == (int)ITipHandler::iTIPNoMethod);
0068     return static_cast<ITipHandler::ITipMethod>(method);
0069 }
0070 
0071 KCalendarCore::iTIPMethod mapToKCalendarCore(ITipHandler::ITipMethod method)
0072 {
0073     Q_ASSERT((int)KCalendarCore::iTIPPublish == (int)ITipHandler::iTIPPublish);
0074     Q_ASSERT((int)KCalendarCore::iTIPNoMethod == (int)ITipHandler::iTIPNoMethod);
0075     return static_cast<KCalendarCore::iTIPMethod>(method);
0076 }
0077 
0078 std::string ITipHandler::toITip(const Event &event, ITipHandler::ITipMethod method) const
0079 {
0080     KCalendarCore::ICalFormat format;
0081     format.setApplication(QStringLiteral("libkolab"), QStringLiteral(LIBKOLAB_LIB_VERSION_STRING));
0082     KCalendarCore::iTIPMethod m = mapToKCalendarCore(method);
0083     if (m == KCalendarCore::iTIPNoMethod) {
0084         return {};
0085     }
0086     //     qCDebug(PIMKOLAB_LOG) << event.start().
0087     /* TODO
0088      * DTSTAMP is created
0089      * CREATED is current timestamp
0090      * LASTMODIFIED is lastModified
0091      *
0092      * Double check if that is correct.
0093      *
0094      * I think DTSTAMP should be the current timestamp, and CREATED should be the creation date.
0095      */
0096     KCalendarCore::Event::Ptr e = Conversion::toKCalendarCore(event);
0097     return Conversion::toStdString(format.createScheduleMessage(e, m));
0098 }
0099 
0100 std::vector<Event> ITipHandler::fromITip(const std::string &string)
0101 {
0102     KCalendarCore::Calendar::Ptr calendar(new KCalendarCore::MemoryCalendar(QTimeZone::utc()));
0103     KCalendarCore::ICalFormat format;
0104     KCalendarCore::ScheduleMessage::Ptr msg = format.parseScheduleMessage(calendar, Conversion::fromStdString(string));
0105     KCalendarCore::Event::Ptr event = msg->event().dynamicCast<KCalendarCore::Event>();
0106     std::vector<Event> events;
0107     events.push_back(Conversion::fromKCalendarCore(*event));
0108     mMethod = mapFromKCalendarCore(msg->method());
0109     return events;
0110 }
0111 
0112 ITipHandler::ITipMethod ITipHandler::method() const
0113 {
0114     return mMethod;
0115 }
0116 
0117 std::string ITipHandler::toIMip(const Event &event, ITipHandler::ITipMethod m, const std::string &from, bool bccMe) const
0118 {
0119     KCalendarCore::Event::Ptr e = Conversion::toKCalendarCore(event);
0120     //     e->recurrence()->addRDateTime(e->dtStart()); //FIXME The createScheduleMessage converts everything to utc without a recurrence.
0121     KCalendarCore::ICalFormat format;
0122     format.setApplication(QStringLiteral("libkolab"), QStringLiteral(LIBKOLAB_LIB_VERSION_STRING));
0123     KCalendarCore::iTIPMethod method = mapToKCalendarCore(m);
0124     const QString &messageText = format.createScheduleMessage(e, method);
0125     // This code is mostly from MailScheduler::performTransaction
0126     if (method == KCalendarCore::iTIPRequest || method == KCalendarCore::iTIPCancel || method == KCalendarCore::iTIPAdd
0127         || method == KCalendarCore::iTIPDeclineCounter) {
0128         return Conversion::toStdString(QString::fromUtf8(mailAttendees(e, bccMe, messageText)));
0129     } else {
0130         QString subject;
0131         if (e && method == KCalendarCore::iTIPCounter) {
0132             subject = i18n("Counter proposal: %1", e->summary());
0133         }
0134         return Conversion::toStdString(QString::fromUtf8(mailOrganizer(e, Conversion::fromStdString(from), bccMe, messageText, subject)));
0135     }
0136 }
0137 
0138 std::vector<Event> ITipHandler::fromIMip(const std::string &input)
0139 {
0140     KMime::Message::Ptr msg = KMime::Message::Ptr(new KMime::Message);
0141     msg->setContent(Conversion::fromStdString(input).toUtf8());
0142     msg->parse();
0143     msg->content(KMime::ContentIndex());
0144 
0145     KMime::Content *c = Kolab::Mime::findContentByType(msg, "text/calendar");
0146     if (!c) {
0147         qCWarning(PIMKOLAB_LOG) << "could not find text/calendar part";
0148         return {};
0149     }
0150     return fromITip(Conversion::toStdString(QString::fromUtf8(c->decodedContent())));
0151 }
0152 }