2 commits - calendaring/event.cpp calendaring/event.h CMakeLists.txt icalendar/CMakeLists.txt icalendar/icalendar.cpp icalendar/icalendar.h icalendar/imip.cpp icalendar/imip.h tests/calendaringtest.cpp tests/calendaringtest.h tests/icalendartest.cpp tests/icalendartest.h
Christian Mollekopf
mollekopf at kolabsys.com
Fri Jun 1 02:25:15 CEST 2012
CMakeLists.txt | 16 ++-
calendaring/event.cpp | 51 +++++++++
calendaring/event.h | 22 ++++
icalendar/CMakeLists.txt | 4
icalendar/icalendar.cpp | 101 +++++++++++++++----
icalendar/icalendar.h | 22 +++-
icalendar/imip.cpp | 239 ++++++++++++++++++++++++++++++++++++++++++++++
icalendar/imip.h | 34 ++++++
tests/calendaringtest.cpp | 43 ++++++++
tests/calendaringtest.h | 4
tests/icalendartest.cpp | 44 ++++++++
tests/icalendartest.h | 3
12 files changed, 557 insertions(+), 26 deletions(-)
New commits:
commit 3189cdfcfa9f94db7f0396a49abdf19d0898b5d4
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Fri Jun 1 02:24:59 2012 +0200
MIME / iMip handling for event.
diff --git a/calendaring/event.cpp b/calendaring/event.cpp
index 6efd1ec..b09ceeb 100644
--- a/calendaring/event.cpp
+++ b/calendaring/event.cpp
@@ -18,6 +18,8 @@
#include "event.h"
#include <icalendar/icalendar.h>
+#include <kolabformat/kolabobject.h>
+#include <conversion/kcalconversion.h>
#include <iostream>
#include <kolabformat.h>
@@ -53,6 +55,28 @@ std::string Event::write() const
return Kolab::writeEvent(*this);
}
+bool Event::fromMime(const std::string &input)
+{
+ KMime::Message::Ptr msg = KMime::Message::Ptr(new KMime::Message);
+ msg->setContent( QString::fromStdString(input).toLatin1() );
+ msg->parse();
+ msg->content(KMime::ContentIndex());
+ KolabObjectReader reader(msg);
+ if (reader.getType() != EventObject) {
+ std::cout << "not an event ";
+ return false;
+ }
+ const Kolab::Event &e = Kolab::Conversion::fromKCalCore(*reader.getEvent());
+ Kolab::Event::operator=(e);
+ return true;
+}
+
+std::string Event::toMime() const
+{
+ return QString(KolabObjectWriter::writeEvent(Kolab::Conversion::toKCalCore(*this))->encodedContent()).toStdString();
+}
+
+
bool Event::fromICal(const std::string &input)
{
std::vector<Kolab::Event> list = fromICalEvents(input);
@@ -71,6 +95,33 @@ std::string Event::toICal() const
return Kolab::toICal(list);
}
+bool Event::fromIMip(const std::string &input)
+{
+ std::vector<Kolab::Event> list = mITipHandler.fromIMip(input);
+ if (list.size() != 1) {
+ std::cout << "invalid number of events: " << list.size();
+ return false;
+ }
+ Kolab::Event::operator=(list.at(0));
+ return true;
+}
+
+std::string Event::toIMip(ITipMethod method) const
+{
+ std::vector<Kolab::Event> list;
+ list.push_back(*this);
+ return mITipHandler.toIMip(*this, static_cast<ITipHandler::ITipMethod>(method), "from");
+}
+
+Calendaring::Event::ITipMethod Event::getSchedulingMethod() const
+{
+ Q_ASSERT(iTIPPublish == ITipHandler::iTIPPublish);
+ Q_ASSERT(iTIPNoMethod == ITipHandler::iTIPNoMethod);
+ return static_cast<ITipMethod>(mITipHandler.method());
+}
+
+
+
bool contains(const Kolab::ContactReference &delegatorRef, const std::vector <Kolab::ContactReference > &list)
{
foreach (const Kolab::ContactReference &ref, list) {
diff --git a/calendaring/event.h b/calendaring/event.h
index afb8e1a..5775b84 100644
--- a/calendaring/event.h
+++ b/calendaring/event.h
@@ -22,6 +22,7 @@
#ifndef SWIG
#include "kolab_export.h"
+#include <icalendar/icalendar.h>
#else
/* No export/import SWIG interface files */
#define KOLAB_EXPORT
@@ -39,9 +40,29 @@ public:
bool read(const std::string &);
std::string write() const;
+ bool fromMime(const std::string &);
+ std::string toMime() const;
+
+ enum ITipMethod {
+ iTIPPublish, /**< Event, to-do, journal or freebusy posting */
+ iTIPRequest, /**< Event, to-do or freebusy scheduling request */
+ iTIPReply, /**< Event, to-do or freebusy reply to request */
+ iTIPAdd, /**< Event, to-do or journal additional property request */
+ iTIPCancel, /**< Event, to-do or journal cancellation notice */
+ iTIPRefresh, /**< Event or to-do description update request */
+ iTIPCounter, /**< Event or to-do submit counter proposal */
+ iTIPDeclineCounter,/**< Event or to-do decline a counter proposal */
+ iTIPNoMethod /**< No method */
+ };
+
bool fromICal(const std::string &);
std::string toICal() const;
+ bool fromIMip(const std::string &);
+ std::string toIMip(ITipMethod method) const;
+
+ ITipMethod getSchedulingMethod() const;
+
/**
* Updates the delegators and delegatees of the event.
@@ -59,6 +80,7 @@ public:
Kolab::Attendee getAttendee(const std::string &);
private:
Kolab::Attendee *getAttendee(const ContactReference &);
+ Kolab::ITipHandler mITipHandler;
};
};
diff --git a/icalendar/icalendar.cpp b/icalendar/icalendar.cpp
index b3936b2..aca1c58 100644
--- a/icalendar/icalendar.cpp
+++ b/icalendar/icalendar.cpp
@@ -74,7 +74,7 @@ KCalCore::iTIPMethod mapToKCalCore(ITipHandler::ITipMethod method)
}
-std::string ITipHandler::toITip(const Event &event, ITipHandler::ITipMethod method)
+std::string ITipHandler::toITip(const Event &event, ITipHandler::ITipMethod method) const
{
KCalCore::ICalFormat format;
KCalCore::iTIPMethod m = mapToKCalCore(method);
@@ -115,7 +115,7 @@ ITipHandler::ITipMethod ITipHandler::method() const
}
-std::string ITipHandler::toIMip(const Event &event , ITipHandler::ITipMethod m, std::string from, bool bccMe)
+std::string ITipHandler::toIMip(const Event &event , ITipHandler::ITipMethod m, std::string from, bool bccMe) const
{
KCalCore::Event::Ptr e = Conversion::toKCalCore(event);
diff --git a/icalendar/icalendar.h b/icalendar/icalendar.h
index 018ddea..11db800 100644
--- a/icalendar/icalendar.h
+++ b/icalendar/icalendar.h
@@ -56,13 +56,13 @@ namespace Kolab {
iTIPNoMethod /**< No method */
};
- std::string toIMip(const Kolab::Event &, ITipMethod, std::string from, bool bbcMe = false);
+ std::string toIMip(const Kolab::Event &, ITipMethod, std::string from, bool bbcMe = false) const;
std::vector<Kolab::Event> fromIMip(const std::string &);
/**
* Create iTip message from single event
*/
- std::string toITip(const Kolab::Event &, ITipMethod);
+ std::string toITip(const Kolab::Event &, ITipMethod) const;
/**
* Parse iTip message with a single event
diff --git a/tests/calendaringtest.cpp b/tests/calendaringtest.cpp
index 6d94178..3671ecb 100644
--- a/tests/calendaringtest.cpp
+++ b/tests/calendaringtest.cpp
@@ -43,6 +43,7 @@ void compareEvents(const std::vector<Kolab::Event> &list1, const std::vector<Kol
const Kolab::Event &e1 = list1.at(i);
const Kolab::Event &e2 = list2.at(i);
// qDebug() << i;
+// QCOMPARE(e1.uid(), e2.uid());
QCOMPARE(e1.start(), e2.start());
QCOMPARE(e1.end(), e2.end());
}
@@ -334,6 +335,48 @@ void CalendaringTest::delegationTest()
//TODO write an actual test
}
+void CalendaringTest::testICal()
+{
+ Kolab::Calendaring::Event event;
+ event.setStart(Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
+ const std::string &result = event.toICal();
+ //TODO write an actual test
+ event.setStart(Kolab::cDateTime(1,1,1));
+ event.fromICal(result);
+ QCOMPARE(event.start(), Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
+}
+
+void CalendaringTest::testMime()
+{
+ Kolab::Calendaring::Event event;
+ event.setStart(Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
+ std::cout << event.toMime();
+ const std::string &result = event.toMime();
+ event.setStart(Kolab::cDateTime(1,1,1));
+ event.fromMime(result);
+ QCOMPARE(event.start(), Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
+}
+
+void CalendaringTest::testIMip()
+{
+ Kolab::Calendaring::Event event;
+ Kolab::Attendee att1(Kolab::ContactReference("email1", "name1", "uid1"));
+
+ std::vector <Kolab::Attendee > attendees;
+ attendees.push_back(att1);
+ event.setAttendees(attendees);
+ event.setOrganizer(Kolab::ContactReference("organizer at test.org", "organizer", "uid3"));
+ event.setSummary("summary");
+ event.setStart(Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
+ const std::string &result = event.toIMip(Kolab::Calendaring::Event::iTIPRequest);
+ event.setStart(Kolab::cDateTime(1,1,1));
+ event.fromIMip(result);
+ QCOMPARE(event.start(), Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
+ QCOMPARE(event.getSchedulingMethod(), Kolab::Calendaring::Event::iTIPRequest);
+ //TODO returns UTC instead of local timezone
+}
+
+
QTEST_MAIN( CalendaringTest )
diff --git a/tests/calendaringtest.h b/tests/calendaringtest.h
index 02c39bc..295dd90 100644
--- a/tests/calendaringtest.h
+++ b/tests/calendaringtest.h
@@ -39,6 +39,10 @@ private slots:
void testCalendar();
void delegationTest();
+
+ void testMime();
+ void testICal();
+ void testIMip();
};
#endif // CALENDARINGTEST_H
diff --git a/tests/icalendartest.cpp b/tests/icalendartest.cpp
index af0c000..d3273a7 100644
--- a/tests/icalendartest.cpp
+++ b/tests/icalendartest.cpp
@@ -68,7 +68,7 @@ void ICalendarTest::testToIMip()
Kolab::ITipHandler handler;
Kolab::Event ev1;
ev1.setStart(Kolab::cDateTime(2011,10,10,12,1,1,true));
- ev1.setEnd(Kolab::cDateTime(2011,10,11,12,1,1,true));
+ ev1.setEnd(Kolab::cDateTime("Europe/Zurich",2012,5,5,3,4,4));
ev1.setLastModified(Kolab::cDateTime(2011,10,11,12,1,2,true));
ev1.setCreated(Kolab::cDateTime(2011,10,11,12,1,3,true));
@@ -88,6 +88,8 @@ void ICalendarTest::testToIMip()
qDebug() << QString::fromStdString(Kolab::toICal(eventResult));
QCOMPARE((int)eventResult.size(), 1);
+ QCOMPARE(ev1.start(), eventResult.front().start());
+ QCOMPARE(ev1.end(), eventResult.front().end());
}
commit f5183b4e23b97add769fdaf647b43500e1059024
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Fri Jun 1 01:44:40 2012 +0200
First crude iMip implementation.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 567ba5d..b8ef17e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,7 +68,21 @@ add_subdirectory(calendaring)
add_subdirectory(icalendar)
set(KOLAB_SRCS kolabformat/kolabobject.cpp kolabformat/errorhandler.cpp mime/mimeutils.cpp ${CONVERSION_SRCS} ${kolabformatv2_SRCS} ${CALENDARING_SRCS} ${ICALENDAR_SRCS})
-set(KOLAB_LINK_LIBRARIES ${Libkolabxml_LIBRARIES} ${KDEPIMLIBS_KCALCORE_LIBS} ${KDEPIMLIBS_KABC_LIBS} ${KDEPIMLIBS_KMIME_LIBS} ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_AKONADI_NOTES_LIBS} ${QT_QTCORE_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBRARY} ${KDE4_KIO_LIBRARY})
+set(KOLAB_LINK_LIBRARIES
+ ${Libkolabxml_LIBRARIES}
+ ${KDEPIMLIBS_KCALCORE_LIBS}
+ ${KDEPIMLIBS_KABC_LIBS}
+ ${KDEPIMLIBS_KMIME_LIBS}
+ ${KDEPIMLIBS_AKONADI_LIBS}
+ ${KDEPIMLIBS_AKONADI_NOTES_LIBS}
+ ${KDEPIMLIBS_KCALUTILS_LIBS}
+ ${KDEPIMLIBS_KPIMUTILS_LIBS}
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTXML_LIBRARY}
+ ${QT_QTGUI_LIBRARY}
+ ${KDE4_KDECORE_LIBRARY}
+ ${KDE4_KIO_LIBRARY}
+)
if(BUILD_TESTS)
#for tests only
kde4_add_library(kolab_static STATIC ${KOLAB_SRCS})
diff --git a/icalendar/CMakeLists.txt b/icalendar/CMakeLists.txt
index b82684f..7e0efd6 100644
--- a/icalendar/CMakeLists.txt
+++ b/icalendar/CMakeLists.txt
@@ -1,6 +1,8 @@
set (ICALENDAR_SRCS
- ${CMAKE_CURRENT_SOURCE_DIR}/icalendar.cpp PARENT_SCOPE)
+ ${CMAKE_CURRENT_SOURCE_DIR}/icalendar.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/imip.cpp
+ PARENT_SCOPE)
if(PYTHON_BINDINGS)
message("building python bindings")
diff --git a/icalendar/icalendar.cpp b/icalendar/icalendar.cpp
index 5e0f15a..b3936b2 100644
--- a/icalendar/icalendar.cpp
+++ b/icalendar/icalendar.cpp
@@ -19,13 +19,16 @@
#include "icalendar.h"
+#include "imip.h"
#include <conversion/kcalconversion.h>
#include <conversion/commonconversion.h>
+#include <mime/mimeutils.h>
#include <KCalCore/Event>
#include <kcalcore/memorycalendar.h>
#include <kcalcore/icalformat.h>
-
-#include <QDebug>
+#include <kmime/kmime_message.h>
+#include <klocalizedstring.h>
+#include <kdebug.h>
namespace Kolab {
@@ -56,21 +59,45 @@ std::vector< Event > fromICalEvents(const std::string &input)
return events;
}
+ITipHandler::ITipMethod mapFromKCalCore(KCalCore::iTIPMethod method)
+{
+ Q_ASSERT(KCalCore::iTIPPublish == ITipHandler::iTIPPublish);
+ Q_ASSERT(KCalCore::iTIPNoMethod == ITipHandler::iTIPNoMethod);
+ return static_cast<ITipHandler::ITipMethod>(method);
+}
+
+KCalCore::iTIPMethod mapToKCalCore(ITipHandler::ITipMethod method)
+{
+ Q_ASSERT(KCalCore::iTIPPublish == ITipHandler::iTIPPublish);
+ Q_ASSERT(KCalCore::iTIPNoMethod == ITipHandler::iTIPNoMethod);
+ return static_cast<KCalCore::iTIPMethod>(method);
+}
+
std::string ITipHandler::toITip(const Event &event, ITipHandler::ITipMethod method)
{
KCalCore::ICalFormat format;
- KCalCore::iTIPMethod m;
- switch (method) {
- case ITipHandler::iTIPRequest:
- m = KCalCore::iTIPRequest;
- break;
- default:
- qWarning() << "unsupported itip method";
+ KCalCore::iTIPMethod m = mapToKCalCore(method);
+ if (m == KCalCore::iTIPNoMethod) {
+ return std::string();
}
- return format.createScheduleMessage(Conversion::toKCalCore(event), m).toStdString();
+// kDebug() << event.start().
+/* TODO
+ * DTSTAMP is created
+ * CREATED is current timestamp
+ * LASTMODIFIED is lastModified
+ *
+ * Double check if that is correct.
+ *
+ * I think DTSTAMP should be the current timestamp, and CREATED should be the creation date.
+ */
+ KCalCore::Event::Ptr e = Conversion::toKCalCore(event);
+ return format.createScheduleMessage(e, m).toStdString();
}
+
+
+
std::vector< Event > ITipHandler::fromITip(const std::string &string)
{
KCalCore::Calendar::Ptr calendar(new KCalCore::MemoryCalendar(Kolab::Conversion::getTimeSpec(true, std::string())));
@@ -78,14 +105,7 @@ std::vector< Event > ITipHandler::fromITip(const std::string &string)
KCalCore::ScheduleMessage::Ptr msg= format.parseScheduleMessage(calendar, QString::fromStdString(string));
std::vector< Event > events;
events.push_back(Conversion::fromKCalCore(*(msg->event().dynamicCast<KCalCore::Event>())));
- switch (msg->method()) {
- case KCalCore::iTIPRequest:
- mMethod = ITipHandler::iTIPRequest;
- break;
- default:
- mMethod = ITipHandler::iTipUnknown;
- qWarning() << "unsupported itip method";
- }
+ mMethod = mapFromKCalCore(msg->method());
return events;
}
@@ -95,4 +115,47 @@ ITipHandler::ITipMethod ITipHandler::method() const
}
+std::string ITipHandler::toIMip(const Event &event , ITipHandler::ITipMethod m, std::string from, bool bccMe)
+{
+ KCalCore::Event::Ptr e = Conversion::toKCalCore(event);
+
+ KCalCore::ICalFormat format;
+
+ KCalCore::iTIPMethod method = mapToKCalCore(m);
+ const QString &messageText = format.createScheduleMessage( e, method );
+ //This code is mostly from MailScheduler::performTransaction
+ bool status;
+ if ( method == KCalCore::iTIPRequest ||
+ method == KCalCore::iTIPCancel ||
+ method == KCalCore::iTIPAdd ||
+ method == KCalCore::iTIPDeclineCounter ) {
+ return QString(mailAttendees(e, bccMe, messageText)).toStdString();
+ } else {
+ QString subject;
+ if ( e && method == KCalCore::iTIPCounter ) {
+ subject = i18n( "Counter proposal: %1", e->summary() );
+ }
+ return QString(mailOrganizer( e, QString::fromStdString(from), bccMe, messageText, subject)).toStdString();
+ }
+ return std::string();
+}
+
+std::vector< Event > ITipHandler::fromIMip(const std::string &input)
+{
+ KMime::Message::Ptr msg = KMime::Message::Ptr(new KMime::Message);
+ msg->setContent( QString::fromStdString(input).toLatin1() );
+ msg->parse();
+ msg->content(KMime::ContentIndex());
+
+ KMime::Content *c = Kolab::Mime::findContentByType(msg, "text/calendar");
+ if (!c) {
+ qWarning() << "could not find text/calendar part";
+ return std::vector< Event >();
+ }
+ return fromITip(QString(c->decodedContent()).toStdString());
+}
+
+
+
+
}
diff --git a/icalendar/icalendar.h b/icalendar/icalendar.h
index 395d673..018ddea 100644
--- a/icalendar/icalendar.h
+++ b/icalendar/icalendar.h
@@ -45,16 +45,27 @@ namespace Kolab {
class KOLAB_EXPORT ITipHandler {
public:
enum ITipMethod {
- iTipUnknown,
- iTIPRequest
+ iTIPPublish, /**< Event, to-do, journal or freebusy posting */
+ iTIPRequest, /**< Event, to-do or freebusy scheduling request */
+ iTIPReply, /**< Event, to-do or freebusy reply to request */
+ iTIPAdd, /**< Event, to-do or journal additional property request */
+ iTIPCancel, /**< Event, to-do or journal cancellation notice */
+ iTIPRefresh, /**< Event or to-do description update request */
+ iTIPCounter, /**< Event or to-do submit counter proposal */
+ iTIPDeclineCounter,/**< Event or to-do decline a counter proposal */
+ iTIPNoMethod /**< No method */
};
+
+ std::string toIMip(const Kolab::Event &, ITipMethod, std::string from, bool bbcMe = false);
+ std::vector<Kolab::Event> fromIMip(const std::string &);
+
/**
- * Create iTip message from single event (only request supported so far)
+ * Create iTip message from single event
*/
std::string toITip(const Kolab::Event &, ITipMethod);
/**
- * Parse iTip message with a single event (only request supported so far)
+ * Parse iTip message with a single event
*/
std::vector<Kolab::Event> fromITip(const std::string &);
ITipMethod method() const;
@@ -62,6 +73,7 @@ namespace Kolab {
ITipMethod mMethod;
};
+
}
#endif // ICALENDAR_H
diff --git a/icalendar/imip.cpp b/icalendar/imip.cpp
new file mode 100644
index 0000000..a49aafa
--- /dev/null
+++ b/icalendar/imip.cpp
@@ -0,0 +1,239 @@
+/*
+ <one line to give the library's name and an idea of what it does.>
+ Copyright (C) 2012 Christian Mollekopf <chrigi_1 at fastmail.fm>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "imip.h"
+
+#include <kcalutils/incidenceformatter.h>
+#include <KPIMUtils/Email>
+#include <kmime/kmime_message.h>
+#include <QDebug>
+#include <klocalizedstring.h>
+#include <ksystemtimezone.h>
+#include <kdebug.h>
+
+/*
+ * The code in here is copy paste work from kdepim/calendarsupport.
+ *
+ * We need to refactor the code there and move the relevant parts to kdepimlibs to make it reusable.
+ *
+ *
+ */
+
+//From MailClient::send
+KMime::Message::Ptr createMessage( const QString &from, const QString &_to,
+ const QString &cc, const QString &subject,
+ const QString &body, bool hidden, bool bccMe,
+ const QString &attachment/*, const QString &mailTransport */)
+{
+ Q_UNUSED( hidden );
+
+ const bool outlookConformInvitation = false;
+ QString userAgent = "libkolab";
+
+ // We must have a recipients list for most MUAs. Thus, if the 'to' list
+ // is empty simply use the 'from' address as the recipient.
+ QString to = _to;
+ if ( to.isEmpty() ) {
+ to = from;
+ }
+ kDebug() << "\nFrom:" << from
+ << "\nTo:" << to
+ << "\nCC:" << cc
+ << "\nSubject:" << subject << "\nBody: \n" << body
+ << "\nAttachment:\n" << attachment
+ /*<< "\nmailTransport: " << mailTransport*/;
+
+ // Now build the message we like to send. The message KMime::Message::Ptr instance
+ // will be the root message that has 2 additional message. The body itself and
+ // the attached cal.ics calendar file.
+ KMime::Message::Ptr message = KMime::Message::Ptr( new KMime::Message );
+ message->contentTransferEncoding()->clear(); // 7Bit, decoded.
+
+ // Set the headers
+ message->userAgent()->fromUnicodeString(userAgent, "utf-8" );
+ message->from()->fromUnicodeString( from, "utf-8" );
+ message->to()->fromUnicodeString( to, "utf-8" );
+ message->cc()->fromUnicodeString( cc, "utf-8" );
+ if( bccMe ) {
+ message->bcc()->fromUnicodeString( from, "utf-8" ); //from==me, right?
+ }
+ message->date()->setDateTime( KDateTime::currentLocalDateTime() );
+ message->subject()->fromUnicodeString( subject, "utf-8" );
+
+ if ( outlookConformInvitation ) {
+ message->contentType()->setMimeType( "text/calendar" );
+ message->contentType()->setCharset( "utf-8" );
+ message->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
+ message->contentType()->setParameter( QLatin1String( "method" ), QLatin1String( "request" ) );
+
+ if ( !attachment.isEmpty() ) {
+ KMime::Headers::ContentDisposition *disposition =
+ new KMime::Headers::ContentDisposition( message.get() );
+ disposition->setDisposition( KMime::Headers::CDinline );
+ message->setHeader( disposition );
+ message->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
+ message->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
+ }
+ } else {
+ // We need to set following 4 lines by hand else KMime::Content::addContent
+ // will create a new Content instance for us to attach the main message
+ // what we don't need cause we already have the main message instance where
+ // 2 additional messages are attached.
+ KMime::Headers::ContentType *ct = message->contentType();
+ ct->setMimeType( "multipart/mixed" );
+ ct->setBoundary( KMime::multiPartBoundary() );
+ ct->setCategory( KMime::Headers::CCcontainer );
+
+ // Set the first multipart, the body message.
+ KMime::Content *bodyMessage = new KMime::Content;
+ KMime::Headers::ContentDisposition *bodyDisposition =
+ new KMime::Headers::ContentDisposition( bodyMessage );
+ bodyDisposition->setDisposition( KMime::Headers::CDinline );
+ bodyMessage->contentType()->setMimeType( "text/plain" );
+ bodyMessage->contentType()->setCharset( "utf-8" );
+ bodyMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
+ bodyMessage->setBody( KMime::CRLFtoLF( body.toUtf8() ) );
+ message->addContent( bodyMessage );
+
+ // Set the sedcond multipart, the attachment.
+ if ( !attachment.isEmpty() ) {
+ KMime::Content *attachMessage = new KMime::Content;
+ KMime::Headers::ContentDisposition *attachDisposition =
+ new KMime::Headers::ContentDisposition( attachMessage );
+ attachDisposition->setDisposition( KMime::Headers::CDattachment );
+ attachMessage->contentType()->setMimeType( "text/calendar" );
+ attachMessage->contentType()->setCharset( "utf-8" );
+ attachMessage->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
+ attachMessage->contentType()->setParameter( QLatin1String( "method" ),
+ QLatin1String( "request" ) );
+ attachMessage->setHeader( attachDisposition );
+ attachMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
+ attachMessage->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
+ message->addContent( attachMessage );
+ }
+ }
+
+ // Job done, attach the both multiparts and assemble the message.
+ message->assemble();
+ return message;
+}
+
+//From MailClient::mailAttendees
+QByteArray mailAttendees( const KCalCore::IncidenceBase::Ptr &incidence,
+// const KPIMIdentities::Identity &identity,
+ bool bccMe, const QString &attachment
+ /*const QString &mailTransport */)
+{
+ KCalCore::Attendee::List attendees = incidence->attendees();
+ if ( attendees.isEmpty() ) {
+ kWarning() << "There are no attendees to e-mail";
+ return false;
+ }
+
+ const QString from = incidence->organizer()->fullName();
+ const QString organizerEmail = incidence->organizer()->email();
+
+ QStringList toList;
+ QStringList ccList;
+ const int numberOfAttendees( attendees.count() );
+ for ( int i=0; i<numberOfAttendees; ++i ) {
+ KCalCore::Attendee::Ptr a = attendees.at(i);
+
+ const QString email = a->email();
+ if ( email.isEmpty() ) {
+ continue;
+ }
+
+ // In case we (as one of our identities) are the organizer we are sending
+ // this mail. We could also have added ourselves as an attendee, in which
+ // case we don't want to send ourselves a notification mail.
+ if ( organizerEmail == email ) {
+ continue;
+ }
+
+ // Build a nice address for this attendee including the CN.
+ QString tname, temail;
+ const QString username = KPIMUtils::quoteNameIfNecessary( a->name() );
+ // ignore the return value from extractEmailAddressAndName() because
+ // it will always be false since tusername does not contain "@domain".
+ KPIMUtils::extractEmailAddressAndName( username, temail/*byref*/, tname/*byref*/ );
+ tname += QLatin1String( " <" ) + email + QLatin1Char( '>' );
+
+ // Optional Participants and Non-Participants are copied on the email
+ if ( a->role() == KCalCore::Attendee::OptParticipant ||
+ a->role() == KCalCore::Attendee::NonParticipant ) {
+ ccList << tname;
+ } else {
+ toList << tname;
+ }
+ }
+ if( toList.isEmpty() && ccList.isEmpty() ) {
+ // Not really to be called a groupware meeting, eh
+ kWarning() << "There are really no attendees to e-mail";
+ return false;
+ }
+ QString to;
+ if ( !toList.isEmpty() ) {
+ to = toList.join( QLatin1String( ", " ) );
+ }
+ QString cc;
+ if ( !ccList.isEmpty() ) {
+ cc = ccList.join( QLatin1String( ", " ) );
+ }
+
+ QString subject;
+ if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) {
+ KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>();
+ subject = inc->summary();
+ } else {
+ subject = i18n( "Free Busy Object" );
+ }
+
+ const QString body =
+ KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() );
+
+ return createMessage(/* identity, */from, to, cc, subject, body, false,
+ bccMe, attachment/*, mailTransport */)->encodedContent();
+}
+
+QByteArray mailOrganizer( const KCalCore::IncidenceBase::Ptr &incidence,
+// const KPIMIdentities::Identity &identity,
+ const QString &from, bool bccMe,
+ const QString &attachment,
+ const QString &sub/*, const QString &mailTransport*/ )
+{
+ const QString to = incidence->organizer()->fullName();
+ QString subject = sub;
+
+ if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) {
+ KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>();
+ if ( subject.isEmpty() ) {
+ subject = inc->summary();
+ }
+ } else {
+ subject = i18n( "Free Busy Message" );
+ }
+
+ QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() );
+
+ return createMessage( /*identity, */from, to, QString(), subject, body, false,
+ bccMe, attachment/*, mailTransport */)->encodedContent();
+}
+
diff --git a/icalendar/imip.h b/icalendar/imip.h
new file mode 100644
index 0000000..2ee747e
--- /dev/null
+++ b/icalendar/imip.h
@@ -0,0 +1,34 @@
+/*
+ <one line to give the library's name and an idea of what it does.>
+ Copyright (C) 2012 Christian Mollekopf <chrigi_1 at fastmail.fm>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef IMIP_H
+#define IMIP_H
+#include <QByteArray>
+#include <kcalcore/incidencebase.h>
+
+QByteArray mailAttendees( const KCalCore::IncidenceBase::Ptr &incidence,
+ bool bccMe, const QString &attachment );
+
+QByteArray mailOrganizer( const KCalCore::IncidenceBase::Ptr &incidence,
+ const QString &from, bool bccMe,
+ const QString &attachment,
+ const QString &sub );
+
+#endif // IMIP_H
diff --git a/tests/icalendartest.cpp b/tests/icalendartest.cpp
index 8be697b..af0c000 100644
--- a/tests/icalendartest.cpp
+++ b/tests/icalendartest.cpp
@@ -50,6 +50,48 @@ void ICalendarTest::testToICal()
qDebug() << QString::fromStdString(Kolab::toICal(events));
}
+void ICalendarTest::testToITip()
+{
+ Kolab::ITipHandler handler;
+ Kolab::Event ev1;
+ ev1.setStart(Kolab::cDateTime(2011,10,10,12,1,1,true));
+ ev1.setEnd(Kolab::cDateTime(2011,10,11,12,1,1,true));
+ ev1.setLastModified(Kolab::cDateTime(2011,10,11,12,1,2,true));
+ ev1.setCreated(Kolab::cDateTime(2011,10,11,12,1,3,true));
+
+ qDebug() << QString::fromStdString(handler.toITip(ev1, Kolab::ITipHandler::iTIPRequest));
+
+}
+
+void ICalendarTest::testToIMip()
+{
+ Kolab::ITipHandler handler;
+ Kolab::Event ev1;
+ ev1.setStart(Kolab::cDateTime(2011,10,10,12,1,1,true));
+ ev1.setEnd(Kolab::cDateTime(2011,10,11,12,1,1,true));
+ ev1.setLastModified(Kolab::cDateTime(2011,10,11,12,1,2,true));
+ ev1.setCreated(Kolab::cDateTime(2011,10,11,12,1,3,true));
+
+ std::vector <Kolab::Attendee > attendees;
+ attendees.push_back(Kolab::Attendee(Kolab::ContactReference("email1 at test.org", "name1", "uid1")));
+ attendees.push_back(Kolab::Attendee (Kolab::ContactReference("email2 at test.org", "name2", "uid2")));
+ ev1.setAttendees(attendees);
+
+ ev1.setOrganizer(Kolab::ContactReference("organizer at test.org", "organizer", "uid3"));
+
+ const std::string mimeResult = handler.toIMip(ev1, Kolab::ITipHandler::iTIPRequest, "test at test.com");
+ qDebug() << QString::fromStdString(mimeResult);
+ qDebug() << QString::fromStdString(handler.toIMip(ev1, Kolab::ITipHandler::iTIPReply, "test at test.com"));
+
+ const std::vector<Kolab::Event> &eventResult = handler.fromIMip(mimeResult);
+
+ qDebug() << QString::fromStdString(Kolab::toICal(eventResult));
+
+ QCOMPARE((int)eventResult.size(), 1);
+}
+
+
+
QTEST_MAIN( ICalendarTest )
#include "icalendartest.moc"
diff --git a/tests/icalendartest.h b/tests/icalendartest.h
index b3e4166..d6f5acd 100644
--- a/tests/icalendartest.h
+++ b/tests/icalendartest.h
@@ -30,6 +30,9 @@ private slots:
// void testEventConflict_data();
void testToICal();
void testFromICalEvent();
+
+ void testToITip();
+ void testToIMip();
};
#endif // ICALENDARTEST_H
More information about the commits
mailing list