9 commits - CMakeLists.txt fbdaemon/authenticationjob.cpp fbdaemon/authenticationjob.h fbdaemon/CMakeLists.txt fbdaemon/fbaggregatorjob.cpp fbdaemon/fbaggregatorjob.h fbdaemon/fbcoordinator.cpp fbdaemon/fbcoordinator.h fbdaemon/fbgeneratorjob.cpp fbdaemon/fbgeneratorjob.h fbdaemon/generatefbjob.cpp fbdaemon/generatefbjob.h fbdaemon/getuserlistjob.cpp fbdaemon/getuserlistjob.h fbdaemon/kolabjob.cpp fbdaemon/kolabjob.h fbdaemon/main.cpp fbdaemon/settings.cpp fbdaemon/settings.h jobs/CMakeLists.txt jobs/fetchmessagesjob.cpp jobs/findkolabfoldersjob.cpp jobs/messagemodifyjob.cpp jobs/probekolabserverjob.cpp jobs/probekolabserverjob.h jobs/sequentialcompositejob.cpp jobs/setupkolabfoldersjob.cpp jobs/setupkolabfoldersjob.h testfiles/v2

Christian Mollekopf mollekopf at kolabsys.com
Wed Jul 18 18:05:00 CEST 2012


 CMakeLists.txt                  |    6 +
 fbdaemon/CMakeLists.txt         |    4 
 fbdaemon/authenticationjob.cpp  |   23 ++++-
 fbdaemon/authenticationjob.h    |    8 +
 fbdaemon/fbaggregatorjob.cpp    |  103 ++++++++++++++++++++++++
 fbdaemon/fbaggregatorjob.h      |   45 ++++++++++
 fbdaemon/fbcoordinator.cpp      |   32 +++++++
 fbdaemon/fbcoordinator.h        |   14 +++
 fbdaemon/fbgeneratorjob.cpp     |  134 ++++++++++++++------------------
 fbdaemon/fbgeneratorjob.h       |   16 +--
 fbdaemon/generatefbjob.cpp      |   31 ++++---
 fbdaemon/generatefbjob.h        |    5 -
 fbdaemon/getuserlistjob.cpp     |  166 ++++++++++++++++++++++++++++++++++++++++
 fbdaemon/getuserlistjob.h       |   50 ++++++++++++
 fbdaemon/kolabjob.cpp           |   91 +++++++++++++++++++++
 fbdaemon/kolabjob.h             |   51 ++++++++++++
 fbdaemon/main.cpp               |   15 +++
 fbdaemon/settings.cpp           |   18 ++++
 fbdaemon/settings.h             |    9 +-
 jobs/CMakeLists.txt             |    1 
 jobs/fetchmessagesjob.cpp       |   11 +-
 jobs/findkolabfoldersjob.cpp    |    5 -
 jobs/messagemodifyjob.cpp       |    3 
 jobs/probekolabserverjob.cpp    |   40 +++++++++
 jobs/probekolabserverjob.h      |    5 +
 jobs/sequentialcompositejob.cpp |    3 
 jobs/setupkolabfoldersjob.cpp   |  129 +++++++++++++++++++++++++++++++
 jobs/setupkolabfoldersjob.h     |   57 +++++++++++++
 testfiles/v2/event/allday.ics   |   16 +++
 29 files changed, 978 insertions(+), 113 deletions(-)

New commits:
commit 00ff3950b77a77363ef6b53d9047f9d02753015d
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Wed Jul 18 18:04:53 2012 +0200

    Setup f/b folder if not existing already.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c45e79d..aa2667b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -47,6 +47,7 @@ QT4_WRAP_CPP(JOB_MOC
     ${CMAKE_CURRENT_SOURCE_DIR}/jobs/sequentialcompositejob.h
     ${CMAKE_CURRENT_SOURCE_DIR}/jobs/messagemodifyjob.h
     ${CMAKE_CURRENT_SOURCE_DIR}/jobs/fetchmessagesjob.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/jobs/setupkolabfoldersjob.h
 )
 set( JOBS_SRCS ${JOBS_SRCS} ${JOB_MOC} )
 
diff --git a/fbdaemon/fbgeneratorjob.cpp b/fbdaemon/fbgeneratorjob.cpp
index 42fc9be..2e7f774 100644
--- a/fbdaemon/fbgeneratorjob.cpp
+++ b/fbdaemon/fbgeneratorjob.cpp
@@ -42,9 +42,14 @@ FBGeneratorJob::FBGeneratorJob(const QString& hostName, qint16 port, const QStri
 
 }
 
+QStringList FBGeneratorJob::requiredFolders()
+{
+    return QStringList() << KOLAB_FOLDER_TYPE_FREEBUSY;
+}
+
+
 void FBGeneratorJob::startWork(ProbeKolabServerJob* capabilitiesJob)
 {
-    //TODO freebusy default folder
     if (capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_FREEBUSY).isEmpty()) {
         kWarning() << "no freebusy folder found";
         setError(KJob::UserDefinedError);
@@ -52,8 +57,12 @@ void FBGeneratorJob::startWork(ProbeKolabServerJob* capabilitiesJob)
         return;
     }
     mFreebusyFolder = capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_FREEBUSY).first();
-    //TODO create freebusy folder if not existing? (setupkolabfolders job?)
     mEventFolders = capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_EVENT);
+    if (mEventFolders.isEmpty()) {
+        kWarning() << "no event folders available";
+        emitResult();
+        return;
+    }
 
     FetchMessagesJob *fetchJob = new FetchMessagesJob(mFreebusyFolder, mSession, this);
     connect( fetchJob, SIGNAL(result(KJob*)), this, SLOT(onFetchFBDone(KJob*)) );
diff --git a/fbdaemon/fbgeneratorjob.h b/fbdaemon/fbgeneratorjob.h
index 8e1224d..5848b45 100644
--- a/fbdaemon/fbgeneratorjob.h
+++ b/fbdaemon/fbgeneratorjob.h
@@ -32,6 +32,8 @@ private Q_SLOTS:
     void onFetchFBDone(KJob *job);
     void onGenerateFBDone(KJob*);
     void onModDone(KJob*);
+protected:
+    virtual QStringList requiredFolders();
 private:
     virtual void startWork(ProbeKolabServerJob* job);
 
diff --git a/fbdaemon/kolabjob.cpp b/fbdaemon/kolabjob.cpp
index acc76b3..cba3b67 100644
--- a/fbdaemon/kolabjob.cpp
+++ b/fbdaemon/kolabjob.cpp
@@ -57,6 +57,11 @@ void KolabJob::start()
     job->start();
 }
 
+QStringList KolabJob::requiredFolders()
+{
+    return QStringList();
+}
+
 void KolabJob::onAuthDone(KJob *job)
 {
     if ( job->error() ) {
@@ -67,6 +72,7 @@ void KolabJob::onAuthDone(KJob *job)
     }
     kDebug() << "login successful";
     ProbeKolabServerJob *probeJob = new ProbeKolabServerJob(mSession, this);
+    probeJob->createDefaultsIfMissing(requiredFolders());
     QObject::connect(probeJob, SIGNAL(result(KJob*)), this, SLOT(onProbeDone(KJob*)));
     probeJob->start();
 }
diff --git a/fbdaemon/kolabjob.h b/fbdaemon/kolabjob.h
index f1d54ac..9819faa 100644
--- a/fbdaemon/kolabjob.h
+++ b/fbdaemon/kolabjob.h
@@ -18,6 +18,7 @@
 #ifndef KOLABJOB_H
 #define KOLABJOB_H
 #include <kimap/session.h>
+#include <QStringList>
 
 #define X_ORIGIN_HEADER "X-Freebusy-Origin"
 
@@ -35,6 +36,7 @@ private Q_SLOTS:
     void onProbeDone(KJob* job);
 
 protected:
+    virtual QStringList requiredFolders();
     virtual void startWork(ProbeKolabServerJob *job) = 0;
     QString mHostName;
     qint16 mPort;
diff --git a/jobs/CMakeLists.txt b/jobs/CMakeLists.txt
index 5cfce9a..3d849cb 100644
--- a/jobs/CMakeLists.txt
+++ b/jobs/CMakeLists.txt
@@ -4,5 +4,6 @@ set (JOBS_SRCS
     ${CMAKE_CURRENT_SOURCE_DIR}/sequentialcompositejob.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/messagemodifyjob.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/fetchmessagesjob.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/setupkolabfoldersjob.cpp
     PARENT_SCOPE)
 
diff --git a/jobs/probekolabserverjob.cpp b/jobs/probekolabserverjob.cpp
index b3a8495..5c2599d 100644
--- a/jobs/probekolabserverjob.cpp
+++ b/jobs/probekolabserverjob.cpp
@@ -17,6 +17,7 @@
 
 #include "probekolabserverjob.h"
 #include "findkolabfoldersjob.h"
+#include "setupkolabfoldersjob.h"
 #include <kimap/capabilitiesjob.h>
 #include <kimap/namespacejob.h>
 #include <kdebug.h>
@@ -40,6 +41,11 @@ void ProbeKolabServerJob::start()
     capabilities->start();    
 }
 
+void ProbeKolabServerJob::createDefaultsIfMissing(const QStringList &folders)
+{
+    mFoldersToCreate = folders;
+}
+
 void ProbeKolabServerJob::onCapabilitiesTestDone(KJob* job)
 {
     if ( job->error() ) {
@@ -93,9 +99,40 @@ void ProbeKolabServerJob::findKolabFoldersDone(KJob *job)
     FindKolabFoldersJob *findJob = static_cast<FindKolabFoldersJob*>(job);
     kDebug() << findJob->getKolabFolders();
     mKolabFolders = findJob->getKolabFolders();
+
+    //TODO and now create the missing defaults
+    QString rootFolder;
+    QStringList toCreate;
+    foreach (const QString &folderType, mFoldersToCreate) {
+        if (!mKolabFolders.contains(folderType)) {
+            toCreate << folderType;
+        }
+    }
+    if (toCreate.isEmpty()) {
+        emitResult();
+        return;
+    }
+    SetupKolabFoldersJob *setupJob = new SetupKolabFoldersJob(mCapabilities, rootFolder, mSession, this);
+    setupJob->setKolabFolders(toCreate);
+    connect(setupJob, SIGNAL(result(KJob*)), this, SLOT(onSetupDone(KJob*)));
+    setupJob->start();
+}
+
+void ProbeKolabServerJob::onSetupDone(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+    }
+    SetupKolabFoldersJob *setupJob = static_cast<SetupKolabFoldersJob*>(job);
+    const QMap<QString, QString> createdFolders = setupJob->createdFolders();
+    foreach (const QString &folderType, createdFolders.keys()) {
+        mKolabFolders.insert(folderType, createdFolders.value(folderType));
+    }
     emitResult();
 }
 
+
 QMultiHash<QString, QString> ProbeKolabServerJob::kolabFolders() const
 {
     return mKolabFolders;
diff --git a/jobs/probekolabserverjob.h b/jobs/probekolabserverjob.h
index e63a33a..c359792 100644
--- a/jobs/probekolabserverjob.h
+++ b/jobs/probekolabserverjob.h
@@ -34,6 +34,8 @@ public:
     virtual ~ProbeKolabServerJob();
     virtual void start();
 
+    void createDefaultsIfMissing(const QStringList &);
+
     QList<KIMAP::MailBoxDescriptor> personalNamespace() const;
     QList<KIMAP::MailBoxDescriptor> excludedNamespaces() const;
     QStringList capabilities() const;
@@ -49,6 +51,9 @@ private:
     QList<KIMAP::MailBoxDescriptor> mPersonalNamespace;
     QList<KIMAP::MailBoxDescriptor> mExcludedNamespace;
     QMultiHash<QString, QString> mKolabFolders;
+    QStringList mFoldersToCreate;
+public slots:
+    void onSetupDone(KJob*);
 };
 
 #endif // PROBEKOLABSERVERJOB_H
diff --git a/jobs/setupkolabfoldersjob.cpp b/jobs/setupkolabfoldersjob.cpp
new file mode 100644
index 0000000..0c26034
--- /dev/null
+++ b/jobs/setupkolabfoldersjob.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "setupkolabfoldersjob.h"
+#include <kimap/session.h>
+#include <kimap/createjob.h>
+#include <kimap/selectjob.h>
+#include <kimap/setmetadatajob.h>
+#include <QStringList>
+#include <kdebug.h>
+
+#include <kolab/kolabdefinitions.h>
+#include <kolab/formathelpers.h>
+
+SetupKolabFoldersJob::SetupKolabFoldersJob(const QStringList &serverCapabilities, QString rootFolder, KIMAP::Session* session, QObject* parent)
+:   KJob(parent),
+    m_session(session),
+    m_rootFolder(rootFolder),
+    m_serverCapabilities(serverCapabilities)
+{
+
+}
+
+void SetupKolabFoldersJob::setKolabFolders(const QStringList &mailboxes)
+{
+    m_folderTypes.clear();
+    foreach (const QString &folder, mailboxes) {
+        if (!m_folderTypes.contains(folder)) {
+            m_folderTypes.append(folder);
+        }
+    }
+}
+
+void SetupKolabFoldersJob::start()
+{
+    if (!m_rootFolder.isEmpty()) {
+        KIMAP::SelectJob *selectJob = new KIMAP::SelectJob(m_session);
+        selectJob->setMailBox(m_rootFolder);
+        connect(selectJob, SIGNAL(result(KJob*)), this, SLOT(onSelectDone(KJob*)));
+        selectJob->start();
+    } else {
+        createMailbox();
+    }
+}
+
+void SetupKolabFoldersJob::onSelectDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    createMailbox();
+}
+
+void SetupKolabFoldersJob::createMailbox()
+{
+    if (m_folderTypes.isEmpty()) {
+        emitResult();
+        return;
+    }
+    m_currentFolderType = m_folderTypes.takeFirst();
+    KIMAP::CreateJob *createJob = new KIMAP::CreateJob(m_session);
+    createJob->setMailBox(QString::fromStdString(Kolab::nameForFolderType(Kolab::FreebusyType)));
+    connect(createJob, SIGNAL(result(KJob*)), this, SLOT(onCreateDone(KJob*)));
+    createJob->start();
+}
+
+void SetupKolabFoldersJob::onCreateDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString() << job->error();
+        setError(KJob::UserDefinedError);
+        createMailbox();
+        //TODO also check metadata in case this fails because the folder is already existing but doesn't contain the annotation
+        return;
+    }
+    KIMAP::CreateJob *createJob = static_cast<KIMAP::CreateJob*>(job);
+    kDebug() << "Created folder " << m_rootFolder << createJob->mailBox();
+    m_createdFolders.insert(m_currentFolderType, createJob->mailBox());
+    
+    KIMAP::SetMetaDataJob *setMetadataJob = new KIMAP::SetMetaDataJob(m_session);
+    setMetadataJob->setMailBox(createJob->mailBox());
+    const QByteArray folderType = QByteArray(KOLAB_FOLDER_TYPE_FREEBUSY);
+    if ( m_serverCapabilities.contains( "METADATA" ) ) {
+        setMetadataJob->setServerCapability( KIMAP::MetaDataJobBase::Metadata );
+        setMetadataJob->setEntry( KOLAB_FOLDER_TYPE_ANNOTATION );
+        setMetadataJob->addMetaData( KOLAB_FOLDER_TYPE_ANNOTATION, QString::fromStdString(Kolab::folderAnnotation(Kolab::FreebusyType, true)).toLatin1() );
+        
+//         setMetadataJob->addMetaData(QByteArray("/shared" KOLAB_FOLDER_TYPE_ANNOTATION), folderType);
+    } else {
+        setMetadataJob->setServerCapability( KIMAP::MetaDataJobBase::Annotatemore );
+        setMetadataJob->setEntry( KOLAB_FOLDER_TYPE_ANNOTATION );
+        setMetadataJob->addMetaData( "value.shared", KOLAB_FOLDER_TYPE_FREEBUSY );
+    }
+    connect(setMetadataJob, SIGNAL(result(KJob*)), this, SLOT(onMetadataSetDone(KJob*)));
+    setMetadataJob->start();
+}
+
+void SetupKolabFoldersJob::onMetadataSetDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+    }
+    createMailbox();
+}
+
+QMap< QString, QString > SetupKolabFoldersJob::createdFolders() const
+{
+    return m_createdFolders;
+}
+
+
diff --git a/jobs/setupkolabfoldersjob.h b/jobs/setupkolabfoldersjob.h
new file mode 100644
index 0000000..6115c02
--- /dev/null
+++ b/jobs/setupkolabfoldersjob.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SETUPKOLABFOLDERSJOB_H
+#define SETUPKOLABFOLDERSJOB_H
+#include <kjob.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+namespace KIMAP {
+class Session;
+}
+
+
+class SetupKolabFoldersJob : public KJob
+{
+    Q_OBJECT
+public:
+    explicit SetupKolabFoldersJob(const QStringList &serverCapabilities, QString rootFolder, KIMAP::Session *session, QObject* parent = 0);
+    virtual void start();
+
+    /**
+     * Folders to create as KOLAB_FOLDER_TYPE_* from kolabdefinitions.h
+     */
+    void setKolabFolders(const QStringList &);
+    
+    QMap<QString, QString> createdFolders() const;
+private slots:
+    void onSelectDone(KJob*);
+    void onCreateDone(KJob*);
+    void onMetadataSetDone(KJob*);
+private:
+    void createMailbox();
+    KIMAP::Session *m_session;
+    QStringList m_folderTypes;
+    QString m_currentFolderType;
+    QString m_rootFolder;
+    QStringList m_serverCapabilities;
+    QMap<QString, QString> m_createdFolders;
+
+};
+
+#endif // SETUPKOLABFOLDERSJOB_H


commit 74588207f1fc1b62649bfbb3b9d2059bd028296b
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Wed Jul 18 00:35:30 2012 +0200

    Make sure we fetch all messages

diff --git a/jobs/fetchmessagesjob.cpp b/jobs/fetchmessagesjob.cpp
index 87818e4..570ec5f 100644
--- a/jobs/fetchmessagesjob.cpp
+++ b/jobs/fetchmessagesjob.cpp
@@ -85,9 +85,13 @@ void FetchMessagesJob::onHeadersReceived( const QString &mailBox,
                                            const QMap<qint64, KIMAP::MessagePtr> &messages )
 {
 //     kDebug() << mailBox;
-    mMessages = messages;
-    mFlags = flags;
-    mUids = uids;
+    foreach (qint64 key, uids.keys()) {
+        Q_ASSERT(mMessages.contains(key));
+        mMessages.insert(key, messages.value(key));
+        Q_ASSERT(mFlags.contains(key));
+        mFlags.insert(key, flags.value(key));
+        mUids.insert(key, uids.value(key));
+    }
 }
 
 void FetchMessagesJob::onHeadersFetchDone( KJob *job )


commit 6d14e560c3f96018f7b3739a91b449891fd4d5df
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Tue Jul 17 19:15:33 2012 +0200

    Try guessing the organizer from the events, otherwise overwrite it later on.

diff --git a/fbdaemon/fbaggregatorjob.cpp b/fbdaemon/fbaggregatorjob.cpp
index 6753e95..c8cbefc 100644
--- a/fbdaemon/fbaggregatorjob.cpp
+++ b/fbdaemon/fbaggregatorjob.cpp
@@ -83,7 +83,7 @@ void FBAggregatorJob::onFetchFBDone(KJob *job)
 
     Kolab::Freebusy aggregatedFb = Kolab::FreebusyUtils::aggregateFreeBusy(fbList, organizerEmail, organizerName, true);
 
-    kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(aggregatedFb));
+//     kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(aggregatedFb));
     if (QDir::setCurrent(Settings::instance().getAggregatedICalOutputDirectory())) {
         QFile file(QString::fromLatin1("%1.sfb").arg(mUserName)/*.arg(KDateTime::currentUtcDateTime().toString(KDateTime::ISODate))*/);
         if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) {
diff --git a/fbdaemon/fbgeneratorjob.cpp b/fbdaemon/fbgeneratorjob.cpp
index 674a75e..42fc9be 100644
--- a/fbdaemon/fbgeneratorjob.cpp
+++ b/fbdaemon/fbgeneratorjob.cpp
@@ -98,10 +98,9 @@ void FBGeneratorJob::onFetchFBDone(KJob *job)
 
     KDateTime start = KDateTime::currentUtcDateTime();
     KDateTime end = start.addDays(Settings::instance().getTimeframe());
-    KCalCore::Person::Ptr organizer = KCalCore::Person::Ptr(new KCalCore::Person(mUserName, "email")); //TODO email
 
 //     kDebug() << mEventFolder;
-    GenerateFBJob *fbJob = new GenerateFBJob(mEventFolders, start, end, organizer, mSession, this);
+    GenerateFBJob *fbJob = new GenerateFBJob(mEventFolders, start, end, mSession, this);
     QObject::connect(fbJob, SIGNAL(result(KJob*)), this, SLOT(onGenerateFBDone(KJob*)));
     fbJob->start();
 }
@@ -117,9 +116,19 @@ void FBGeneratorJob::onGenerateFBDone(KJob *job)
     Q_ASSERT(fbJob);
     kDebug() << "generated fb";
 
-    KMime::Message::Ptr message = Kolab::KolabObjectWriter::writeFreebusy(fbJob->getFreebusy());
+    Kolab::Freebusy fb = fbJob->getFreebusy();
+    if (!fb.organizer().isValid()) {
+//         fb.setOrganizer(/*mUserName, mUserName+QLatin1Char('@')+mHostName.remove("imap.")*/);
+        kWarning() << "no valid organizer";
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+
+    KMime::Message::Ptr message = Kolab::KolabObjectWriter::writeFreebusy(fb);
     if (Kolab::ErrorHandler::instance().error() > Kolab::ErrorHandler::Debug) {
         kWarning() << Kolab::ErrorHandler::instance().errorMessage();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -127,7 +136,7 @@ void FBGeneratorJob::onGenerateFBDone(KJob *job)
     message->appendHeader( new KMime::Headers::Generic( X_ORIGIN_HEADER, message.get(), Settings::instance().getServerUri().toUtf8(), "utf-8" ) );
     message->assemble();
     
-    kDebug() << message->encodedContent();
+//     kDebug() << message->encodedContent();
     SequentialCompositeJob *seqJob = new SequentialCompositeJob(this);
     seqJob->addSubjob(new MessageModifyJob(message, mFreebusyFolder, mOldFlags, mOldImapUid, mSession, this));
     seqJob->addSubjob(new KIMAP::ExpungeJob(mSession));
diff --git a/fbdaemon/generatefbjob.cpp b/fbdaemon/generatefbjob.cpp
index e65988d..86197fe 100644
--- a/fbdaemon/generatefbjob.cpp
+++ b/fbdaemon/generatefbjob.cpp
@@ -26,13 +26,12 @@
 #include <errorhandler.h>
 #include <kcalconversion.h>
 
-GenerateFBJob::GenerateFBJob(const QStringList &kolabEventFolders, const KDateTime &start, const KDateTime &end, KCalCore::Person::Ptr organizer, KIMAP::Session *session, QObject* parent)
+GenerateFBJob::GenerateFBJob(const QStringList &kolabEventFolders, const KDateTime &start, const KDateTime &end, KIMAP::Session *session, QObject* parent)
 :   KJob(parent),
     mSession(session),
     mKolabEventFolders(kolabEventFolders),
     mStart(start),
-    mEnd(end),
-    mOrganizer(organizer)
+    mEnd(end)
 {
 
 }
@@ -47,10 +46,12 @@ void GenerateFBJob::start()
     fetchJob->start();
 }
 
-static void mergeEventsToFB(Kolab::Freebusy &freebusy, const QList<KMime::Message::Ptr> &messages, const KDateTime &start, const KDateTime &end, const KCalCore::Person::Ptr &organizer)
+static void mergeEventsToFB(Kolab::Freebusy &freebusy, const QList<KMime::Message::Ptr> &messages, const KDateTime &start, const KDateTime &end)
 {
     QList<KCalCore::Event::Ptr> events;
+    Kolab::ContactReference org;
     Q_FOREACH ( const KMime::Message::Ptr &message, messages ) {
+        kDebug() << message->encodedContent();
         Kolab::KolabObjectReader reader(message);
         if (Kolab::ErrorHandler::instance().error() > Kolab::ErrorHandler::Debug) {
             kWarning() << Kolab::ErrorHandler::instance().errorMessage();
@@ -61,11 +62,17 @@ static void mergeEventsToFB(Kolab::Freebusy &freebusy, const QList<KMime::Messag
             continue;
         }
         KCalCore::Event::Ptr event = reader.getEvent();
+        if (!freebusy.isValid() && !org.isValid()) {
+            org = Kolab::ContactReference(Kolab::ContactReference::EmailReference, event->organizer()->email().toStdString(), event->organizer()->name().toStdString());
+        }
         events.append(event);
     }
-    const Kolab::Freebusy &fb = Kolab::FreebusyUtils::generateFreeBusy(events, start, end, organizer);
+    const Kolab::Freebusy &fb = Kolab::FreebusyUtils::generateFreeBusy(events, start, end, KCalCore::Person::Ptr());
     if (!freebusy.isValid()) {
         freebusy = fb;
+        if (!freebusy.organizer().isValid()) {
+            freebusy.setOrganizer(org);
+        }
     } else {
         //TODO replace by kcalcore merging
         std::vector <Kolab::FreebusyPeriod > periods = freebusy.periods();
@@ -95,9 +102,9 @@ void GenerateFBJob::onFetchDone(KJob *job)
         return;
     }
     
-    mergeEventsToFB(mFreebusy, fetch->getMessages(), mStart, mEnd, mOrganizer);
+    mergeEventsToFB(mFreebusy, fetch->getMessages(), mStart, mEnd);
 
-    kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(mFreebusy));
+//     kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(mFreebusy));
 
     checkJobDone();
 }
diff --git a/fbdaemon/generatefbjob.h b/fbdaemon/generatefbjob.h
index 4eeefe0..b6ec795 100644
--- a/fbdaemon/generatefbjob.h
+++ b/fbdaemon/generatefbjob.h
@@ -31,7 +31,7 @@ class GenerateFBJob: public KJob
 {
     Q_OBJECT
 public:
-    explicit GenerateFBJob(const QStringList &kolabEventFolders, const KDateTime &start, const KDateTime &end, KCalCore::Person::Ptr organizer, KIMAP::Session *, QObject* parent = 0);
+    explicit GenerateFBJob(const QStringList &kolabEventFolders, const KDateTime &start, const KDateTime &end, KIMAP::Session *, QObject* parent = 0);
     virtual void start();
     Kolab::Freebusy getFreebusy() const;
 private Q_SLOTS:
@@ -43,7 +43,6 @@ private:
     KIMAP::Session *mSession;
     KDateTime mStart;
     KDateTime mEnd;
-    KCalCore::Person::Ptr mOrganizer;
 };
 
 #endif // GENERATEFBJOB_H


commit b64680d95d902f2e32d2a1cdd1ee9d5e91bc49f7
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Tue Jul 17 19:14:34 2012 +0200

    Mass generation preparations

diff --git a/fbdaemon/fbcoordinator.cpp b/fbdaemon/fbcoordinator.cpp
index d71cb15..9d72d10 100644
--- a/fbdaemon/fbcoordinator.cpp
+++ b/fbdaemon/fbcoordinator.cpp
@@ -21,6 +21,7 @@
 #include "settings.h"
 #include "getuserlistjob.h"
 #include "fbaggregatorjob.h"
+#include <jobs/sequentialcompositejob.h>
 #include <kdebug.h>
 
 FBCoordinator::FBCoordinator(QObject* parent)
@@ -32,9 +33,26 @@ FBCoordinator::FBCoordinator(QObject* parent)
 void FBCoordinator::generateForAllUsers()
 {
     GetUserListJob *getUsersJob = new GetUserListJob(Settings::instance().getServerUri(), Settings::instance().getServerPort(), this);
-    connect(getUsersJob, SIGNAL(result(KJob*)), this, SLOT(onGeneratorDone(KJob*)));
+    connect(getUsersJob, SIGNAL(result(KJob*)), this, SLOT(onGotUserList(KJob*)));
     getUsersJob->start();
 }
+void FBCoordinator::onGotUserList(KJob *job)
+{
+    const QString server = Settings::instance().getServerUri();
+    const qint16 port =  Settings::instance().getServerPort();
+    GetUserListJob *getUsersJob = static_cast<GetUserListJob*>(job);
+    SequentialCompositeJob *generateJobs = new SequentialCompositeJob(this);
+    SequentialCompositeJob *aggregateJobs = new SequentialCompositeJob(this);
+    foreach(const QString &user, getUsersJob->getUserList()) {
+        generateJobs->addSubjob(new FBGeneratorJob(server, port, user, generateJobs));
+        aggregateJobs->addSubjob(new FBAggregatorJob(server, port, user, aggregateJobs));
+    }
+    SequentialCompositeJob *allJobs = new SequentialCompositeJob(this);
+    allJobs->addSubjob(generateJobs);
+    allJobs->addSubjob(aggregateJobs);
+    connect(allJobs, SIGNAL(result(KJob*)), this, SLOT(onGeneratorDone(KJob*)));
+    allJobs->start();
+}
 
 
 void FBCoordinator::generateForUser(const QString& user)
diff --git a/fbdaemon/fbcoordinator.h b/fbdaemon/fbcoordinator.h
index c47d61d..d1531ef 100644
--- a/fbdaemon/fbcoordinator.h
+++ b/fbdaemon/fbcoordinator.h
@@ -49,6 +49,8 @@ signals:
     void quit();
 private slots:
     void onGeneratorDone(KJob*);
+public slots:
+    void onGotUserList(KJob*);
 };
 
 #endif // FBCOORDINATOR_H
diff --git a/fbdaemon/getuserlistjob.cpp b/fbdaemon/getuserlistjob.cpp
index bed0943..6a01f8d 100644
--- a/fbdaemon/getuserlistjob.cpp
+++ b/fbdaemon/getuserlistjob.cpp
@@ -153,6 +153,10 @@ void GetUserListJob::onListDone(KJob *job)
     emitResult();
 }
 
+QStringList GetUserListJob::getUserList() const
+{
+    return mNames;
+}
 
 
 
diff --git a/fbdaemon/getuserlistjob.h b/fbdaemon/getuserlistjob.h
index 7e5f6a9..fd7e339 100644
--- a/fbdaemon/getuserlistjob.h
+++ b/fbdaemon/getuserlistjob.h
@@ -28,6 +28,7 @@ class GetUserListJob: public KJob
 public:
     explicit GetUserListJob(const QString &hostName, qint16 port, QObject* parent = 0);
     virtual void start();
+    QStringList getUserList() const;
 private Q_SLOTS:
     void onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState);
     void onAuthDone(KJob*);


commit 628b1ed490919369becfa249178c44f5a16ed03e
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Tue Jul 17 17:23:38 2012 +0200

    Write aggregated .sfb to a file.

diff --git a/fbdaemon/fbaggregatorjob.cpp b/fbdaemon/fbaggregatorjob.cpp
index 2128e5f..6753e95 100644
--- a/fbdaemon/fbaggregatorjob.cpp
+++ b/fbdaemon/fbaggregatorjob.cpp
@@ -21,6 +21,8 @@
 #include <jobs/fetchmessagesjob.h>
 #include </home/chrigi/work/kolab/xmlformat/libkolab/freebusy/freebusy.h>
 #include <kdebug.h>
+#include <QFile>
+#include <QDir>
 #include <kolab/kolabobject.h>
 #include <kolabdefinitions.h>
 #include <freebusy.h>
@@ -62,18 +64,40 @@ void FBAggregatorJob::onFetchFBDone(KJob *job)
     Q_ASSERT(fetchJob);
 
     std::vector<Kolab::Freebusy> fbList;
+    std::string organizerName;
+    std::string organizerEmail;
     foreach (const KMime::Message::Ptr &msg, fetchJob->getMessages()) {
         kDebug() << "aggregating fb object: " << msg->subject()->asUnicodeString();
+//         kDebug() << msg->encodedContent();
         Kolab::KolabObjectReader reader(msg);
         if (reader.getType() != Kolab::FreebusyObject) {
             kWarning() << "wrong object type in freebusy folder";
             continue;
         }
         fbList.push_back(reader.getFreebusy());
+        if (organizerEmail.empty()) {
+            organizerEmail = reader.getFreebusy().organizer().email();
+            organizerName = reader.getFreebusy().organizer().name();
+        }
     }
-    Kolab::Freebusy aggregatedFb =Kolab::FreebusyUtils::aggregateFreeBusy(fbList, true);
+
+    Kolab::Freebusy aggregatedFb = Kolab::FreebusyUtils::aggregateFreeBusy(fbList, organizerEmail, organizerName, true);
 
     kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(aggregatedFb));
+    if (QDir::setCurrent(Settings::instance().getAggregatedICalOutputDirectory())) {
+        QFile file(QString::fromLatin1("%1.sfb").arg(mUserName)/*.arg(KDateTime::currentUtcDateTime().toString(KDateTime::ISODate))*/);
+        if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) {
+            kWarning() << "failed to open file";
+            emitResult();
+            return;
+        }
+        QTextStream out(&file);
+        out << QString::fromStdString(Kolab::FreebusyUtils::toIFB(aggregatedFb));
+        kDebug() << "wrote " << QDir::current().absoluteFilePath (file.fileName());
+    } else {
+        kWarning() << "failed to change to aggregated ical output directory: " << Settings::instance().getAggregatedICalOutputDirectory();
+    }
+    
     emitResult();
 }
 
diff --git a/fbdaemon/settings.cpp b/fbdaemon/settings.cpp
index e5d2bc3..8c41fdd 100644
--- a/fbdaemon/settings.cpp
+++ b/fbdaemon/settings.cpp
@@ -82,3 +82,8 @@ int Settings::getThreshold() const
     return 0;
 }
 
+QString Settings::getAggregatedICalOutputDirectory() const
+{
+    return QString("/tmp");
+}
+
diff --git a/fbdaemon/settings.h b/fbdaemon/settings.h
index 04a9b52..6b1cb3b 100644
--- a/fbdaemon/settings.h
+++ b/fbdaemon/settings.h
@@ -41,6 +41,8 @@ public:
     int getTimeframe() const;
     //Number of days after which the f/b is considered out of date
     int getThreshold() const;
+
+    QString getAggregatedICalOutputDirectory() const;
     
 private:
     QVariant getValue(const QString &, const QString &) const;


commit 257263303ddea2632caa7feb58f0cee9c90f9724
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Tue Jul 17 17:22:55 2012 +0200

    Get only the annotation we're interested in

diff --git a/jobs/findkolabfoldersjob.cpp b/jobs/findkolabfoldersjob.cpp
index ce0ca12..9e4081a 100644
--- a/jobs/findkolabfoldersjob.cpp
+++ b/jobs/findkolabfoldersjob.cpp
@@ -82,10 +82,10 @@ void FindKolabFoldersJob::onMailBoxesReceived( const QList< KIMAP::MailBoxDescri
         meta->setMailBox( descriptor.name );
         if ( m_serverCapabilities.contains( "METADATA" ) ) {
             meta->setServerCapability( KIMAP::MetaDataJobBase::Metadata );
-            meta->addEntry( "*" );
+            meta->addEntry( KOLAB_FOLDER_TYPE_ANNOTATION );
         } else {
             meta->setServerCapability( KIMAP::MetaDataJobBase::Annotatemore );
-            meta->addEntry( "*", "value.shared" );
+            meta->addEntry( KOLAB_FOLDER_TYPE_ANNOTATION, "value.shared" );
         }
         connect( meta, SIGNAL(result(KJob*)), SLOT(onGetMetaDataDone(KJob*)) );
         m_metadataRetrieveJobs++;


commit 8cb38686928fe4c087a236aaed9881f0a38cbc80
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Mon Jul 16 18:20:14 2012 +0200

    Some refactoring, getuserlistjob, fbaggregatorjob

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ec85877..c45e79d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,6 +81,9 @@ QT4_WRAP_CPP(FB_MOC
     fbdaemon/fbcoordinator.h
     fbdaemon/fbgeneratorjob.h
     fbdaemon/generatefbjob.h
+    fbdaemon/getuserlistjob.h
+    fbdaemon/kolabjob.h
+    fbdaemon/fbaggregatorjob.h
 )
 set( FBDAEMON_SRCS ${FBDAEMON_SRCS} ${FB_MOC} ${JOBS_SRCS} )
 
diff --git a/fbdaemon/CMakeLists.txt b/fbdaemon/CMakeLists.txt
index 2458c13..2fc2be6 100644
--- a/fbdaemon/CMakeLists.txt
+++ b/fbdaemon/CMakeLists.txt
@@ -5,6 +5,10 @@ set (FBDAEMON_SRCS
     ${CMAKE_CURRENT_SOURCE_DIR}/fbgeneratorjob.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/generatefbjob.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/settings.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/getuserlistjob.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/kolabjob.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/fbaggregatorjob.cpp
+    
     PARENT_SCOPE)
 
 
diff --git a/fbdaemon/authenticationjob.cpp b/fbdaemon/authenticationjob.cpp
index 8dfb72e..77e5921 100644
--- a/fbdaemon/authenticationjob.cpp
+++ b/fbdaemon/authenticationjob.cpp
@@ -24,17 +24,31 @@
 AuthenticationJob::AuthenticationJob(const QString &userName, KIMAP::Session *session, QObject* parent)
 :   KJob(parent),
     mUserName(userName),
-    mSession(session)
+    mSession(session),
+    mDoProxyAuth(true)
 {
 
 }
 
+AuthenticationJob::AuthenticationJob(KIMAP::Session *session, QObject* parent)
+:   KJob(parent),
+    mSession(session),
+    mDoProxyAuth(false)
+{
+
+}
+
+
 void AuthenticationJob::start()
 {
     kDebug() << "logging in as " << mUserName << Settings::instance().getAuthorizationUser() << Settings::instance().getPassword();
     KIMAP::LoginJob *loginJob = new KIMAP::LoginJob( mSession );
-    loginJob->setUserName( mUserName );
-    loginJob->setAuthorizationName(Settings::instance().getAuthorizationUser());
+    if (mDoProxyAuth) {
+        loginJob->setUserName( mUserName );
+        loginJob->setAuthorizationName(Settings::instance().getAuthorizationUser());
+    } else {
+        loginJob->setUserName( Settings::instance().getAuthorizationUser() );
+    }
     loginJob->setPassword(Settings::instance().getPassword());
     
     loginJob->setEncryptionMode( KIMAP::LoginJob::AnySslVersion );
diff --git a/fbdaemon/authenticationjob.h b/fbdaemon/authenticationjob.h
index 5d75ac0..16cd207 100644
--- a/fbdaemon/authenticationjob.h
+++ b/fbdaemon/authenticationjob.h
@@ -30,7 +30,14 @@ class AuthenticationJob: public KJob
 {
     Q_OBJECT
 public:
+    /**
+     * Proxyauthentication with @param userName
+     */
     explicit AuthenticationJob(const QString &userName, KIMAP::Session *, QObject* parent = 0);
+    /**
+     * Login as admin
+     */
+    explicit AuthenticationJob(KIMAP::Session *, QObject* parent = 0);
     virtual void start();
     
 private slots:
@@ -38,6 +45,7 @@ private slots:
 private:
     KIMAP::Session *mSession;
     QString mUserName;
+    bool mDoProxyAuth;
 };
 
 #endif // AUTHENTICATIONJOB_H
diff --git a/fbdaemon/fbaggregatorjob.cpp b/fbdaemon/fbaggregatorjob.cpp
new file mode 100644
index 0000000..2128e5f
--- /dev/null
+++ b/fbdaemon/fbaggregatorjob.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "fbaggregatorjob.h"
+#include "settings.h"
+#include "jobs/probekolabserverjob.h"
+#include <jobs/fetchmessagesjob.h>
+#include </home/chrigi/work/kolab/xmlformat/libkolab/freebusy/freebusy.h>
+#include <kdebug.h>
+#include <kolab/kolabobject.h>
+#include <kolabdefinitions.h>
+#include <freebusy.h>
+
+FBAggregatorJob::FBAggregatorJob(const QString& hostName, qint16 port, const QString& username, QObject* parent)
+: KolabJob(hostName, port, username, parent)
+{
+
+}
+
+void FBAggregatorJob::startWork(ProbeKolabServerJob* capabilitiesJob)
+{
+    //TODO freebusy default folder
+    if (capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_FREEBUSY).isEmpty()) {
+        kWarning() << "no freebusy folder found";
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    mFreebusyFolder = capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_FREEBUSY).first();
+    //TODO create freebusy folder if not existing? (setupkolabfolders job?)
+//     mEventFolders = capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_EVENT);
+
+    FetchMessagesJob *fetchJob = new FetchMessagesJob(mFreebusyFolder, mSession, this);
+    connect( fetchJob, SIGNAL(result(KJob*)), this, SLOT(onFetchFBDone(KJob*)) );
+    fetchJob->start();
+}
+
+
+void FBAggregatorJob::onFetchFBDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    FetchMessagesJob *fetchJob = qobject_cast<FetchMessagesJob*>( job );
+    Q_ASSERT(fetchJob);
+
+    std::vector<Kolab::Freebusy> fbList;
+    foreach (const KMime::Message::Ptr &msg, fetchJob->getMessages()) {
+        kDebug() << "aggregating fb object: " << msg->subject()->asUnicodeString();
+        Kolab::KolabObjectReader reader(msg);
+        if (reader.getType() != Kolab::FreebusyObject) {
+            kWarning() << "wrong object type in freebusy folder";
+            continue;
+        }
+        fbList.push_back(reader.getFreebusy());
+    }
+    Kolab::Freebusy aggregatedFb =Kolab::FreebusyUtils::aggregateFreeBusy(fbList, true);
+
+    kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(aggregatedFb));
+    emitResult();
+}
+
diff --git a/fbdaemon/fbaggregatorjob.h b/fbdaemon/fbaggregatorjob.h
new file mode 100644
index 0000000..9f930e8
--- /dev/null
+++ b/fbdaemon/fbaggregatorjob.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FBAGGREGATORJOB_H
+#define FBAGGREGATORJOB_H
+#include <kjob.h>
+#include <kolabfreebusy.h>
+#include "kolabjob.h"
+
+namespace KIMAP {
+class Session;
+}
+
+class FBAggregatorJob: public KolabJob
+{
+    Q_OBJECT
+public:
+    explicit FBAggregatorJob(const QString &hostName, qint16 port, const QString &username, QObject* parent = 0);
+private Q_SLOTS:
+    void onFetchFBDone(KJob *job);
+//     void onGenerateFBDone(KJob*);
+//     void onModDone(KJob*);
+private:
+    virtual void startWork(ProbeKolabServerJob* job);
+
+    QString mFreebusyFolder;
+
+    Kolab::Freebusy mSimpleFreebusy;
+};
+
+#endif // FBAGGREGATORJOB_H
diff --git a/fbdaemon/fbcoordinator.cpp b/fbdaemon/fbcoordinator.cpp
index 3a85d53..d71cb15 100644
--- a/fbdaemon/fbcoordinator.cpp
+++ b/fbdaemon/fbcoordinator.cpp
@@ -19,6 +19,8 @@
 #include "fbcoordinator.h"
 #include "fbgeneratorjob.h"
 #include "settings.h"
+#include "getuserlistjob.h"
+#include "fbaggregatorjob.h"
 #include <kdebug.h>
 
 FBCoordinator::FBCoordinator(QObject* parent)
@@ -27,6 +29,14 @@ FBCoordinator::FBCoordinator(QObject* parent)
     //TODO get user from job (trigger)
 }
 
+void FBCoordinator::generateForAllUsers()
+{
+    GetUserListJob *getUsersJob = new GetUserListJob(Settings::instance().getServerUri(), Settings::instance().getServerPort(), this);
+    connect(getUsersJob, SIGNAL(result(KJob*)), this, SLOT(onGeneratorDone(KJob*)));
+    getUsersJob->start();
+}
+
+
 void FBCoordinator::generateForUser(const QString& user)
 {
     FBGeneratorJob *generator = new FBGeneratorJob(Settings::instance().getServerUri(), Settings::instance().getServerPort(), user, this);
@@ -36,7 +46,9 @@ void FBCoordinator::generateForUser(const QString& user)
 
 void FBCoordinator::aggregateForUser(const QString& user)
 {
-
+    FBAggregatorJob *generator = new FBAggregatorJob(Settings::instance().getServerUri(), Settings::instance().getServerPort(), user, this);
+    connect(generator, SIGNAL(result(KJob*)), this, SLOT(onGeneratorDone(KJob*)));
+    generator->start();
 }
 
 
diff --git a/fbdaemon/fbcoordinator.h b/fbdaemon/fbcoordinator.h
index f2c4298..c47d61d 100644
--- a/fbdaemon/fbcoordinator.h
+++ b/fbdaemon/fbcoordinator.h
@@ -30,7 +30,19 @@ class FBCoordinator: public QObject
 public:
     explicit FBCoordinator(QObject* parent = 0);
 
+    /**
+     * Gets a list of all available users and triggers a generate job
+     */
+    void generateForAllUsers();
+    
+    /**
+     * Generates a partial f/b list for the @param user
+     */
     void generateForUser(const QString &user);
+    
+    /**
+     * Aggregates the partial f/b lists of the @param user
+     */
     void aggregateForUser(const QString &user);
     
 signals:
diff --git a/fbdaemon/fbgeneratorjob.cpp b/fbdaemon/fbgeneratorjob.cpp
index 653852b..674a75e 100644
--- a/fbdaemon/fbgeneratorjob.cpp
+++ b/fbdaemon/fbgeneratorjob.cpp
@@ -35,80 +35,15 @@
 #include <kimap/expungejob.h>
 
 
-#define X_ORIGIN_HEADER "X-Freebusy-Origin"
-
-class UiProxy: public KIMAP::SessionUiProxy {
-  public:
-    bool ignoreSslError(const KSslErrorUiData& errorData) {
-        kWarning() << "Error during ssl";
-        return true;
-    }
-};
-
 FBGeneratorJob::FBGeneratorJob(const QString& hostName, qint16 port, const QString& username, QObject* parent)
-:   KJob(parent),
-    mHostName(hostName),
-    mPort(port),
-    mUserName(username),
-    mSession(new KIMAP::Session( hostName, port, this )),
+:   KolabJob(hostName, port, username, parent),
     mOldImapUid(-1)
 {
-    mSession->setUiProxy( KIMAP::SessionUiProxy::Ptr(new UiProxy()) );
-    QObject::connect( mSession, SIGNAL(stateChanged(KIMAP::Session::State,KIMAP::Session::State)),
-                      this, SLOT(onSessionStateChanged(KIMAP::Session::State,KIMAP::Session::State)) );
-}
-
-void FBGeneratorJob::onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState)
-{
-    kDebug() << newState;
-    if (newState == KIMAP::Session::Disconnected && oldState != KIMAP::Session::Disconnected) {
-        kWarning() << "lost connenction";
-    }
-}
 
-void FBGeneratorJob::start()
-{
-    kDebug() << "generating f/b for " << mUserName << " on " << mHostName;
-    AuthenticationJob *job = new AuthenticationJob(mUserName, mSession, this);
-    QObject::connect( job, SIGNAL(result(KJob*)),
-                      this, SLOT(onAuthDone(KJob*)) );
-    job->start();
 }
 
-//TODO get what we need from IMAP
-//Find folder (Test server job (capabilities, namespace, find kolab folders))
-//download events
-//parse events
-//generate fb
-//append fb
-//optional: download external f/b from config file
-//done
-void FBGeneratorJob::onAuthDone(KJob *job)
+void FBGeneratorJob::startWork(ProbeKolabServerJob* capabilitiesJob)
 {
-    if ( job->error() ) {
-        kWarning() << job->errorString();
-        setError(KJob::UserDefinedError);
-        emitResult();
-        return;
-    }
-    kDebug() << "login successful";
-    ProbeKolabServerJob *probeJob = new ProbeKolabServerJob(mSession, this);
-    QObject::connect(probeJob, SIGNAL(result(KJob*)), this, SLOT(onProbeDone(KJob*)));
-    probeJob->start();
-}
-
-void FBGeneratorJob::onProbeDone(KJob* job)
-{
-    if ( job->error() ) {
-        kWarning() << job->errorString();
-        setError(KJob::UserDefinedError);
-        emitResult();
-        return;
-    }
-    ProbeKolabServerJob *capabilitiesJob = qobject_cast<ProbeKolabServerJob*>( job );
-    Q_ASSERT(capabilitiesJob);
-
-
     //TODO freebusy default folder
     if (capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_FREEBUSY).isEmpty()) {
         kWarning() << "no freebusy folder found";
@@ -125,6 +60,7 @@ void FBGeneratorJob::onProbeDone(KJob* job)
     fetchJob->start();
 }
 
+
 void FBGeneratorJob::onFetchFBDone(KJob *job)
 {
     if ( job->error() ) {
diff --git a/fbdaemon/fbgeneratorjob.h b/fbdaemon/fbgeneratorjob.h
index 33ee2e8..8e1224d 100644
--- a/fbdaemon/fbgeneratorjob.h
+++ b/fbdaemon/fbgeneratorjob.h
@@ -21,33 +21,25 @@
 #include <kjob.h>
 #include <kimap/session.h>
 #include <kimap/fetchjob.h>
+#include "kolabjob.h"
 
-class FBGeneratorJob: public KJob
+class FBGeneratorJob: public KolabJob
 {
     Q_OBJECT
 public:
     explicit FBGeneratorJob(const QString &hostName, qint16 port, const QString &username, QObject* parent = 0);
-    virtual void start();
 private Q_SLOTS:
-    void onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState);
-    void onAuthDone(KJob*);
-    void onProbeDone(KJob* job);
     void onFetchFBDone(KJob *job);
     void onGenerateFBDone(KJob*);
     void onModDone(KJob*);
 private:
-    QString mHostName;
-    qint16 mPort;
-    QString mUserName;
+    virtual void startWork(ProbeKolabServerJob* job);
 
     QString mFreebusyFolder;
     QStringList mEventFolders;
 
     qint64 mOldImapUid;
     KIMAP::MessageFlags mOldFlags;
-
-    KIMAP::Session *mSession;
-
 };
 
 #endif // FBGENERATORJOB_H
diff --git a/fbdaemon/generatefbjob.cpp b/fbdaemon/generatefbjob.cpp
index d464348..e65988d 100644
--- a/fbdaemon/generatefbjob.cpp
+++ b/fbdaemon/generatefbjob.cpp
@@ -47,7 +47,7 @@ void GenerateFBJob::start()
     fetchJob->start();
 }
 
-void mergeEventsToFB(Kolab::Freebusy &freebusy, const QList<KMime::Message::Ptr> &messages, const KDateTime &start, const KDateTime &end, const KCalCore::Person::Ptr &organizer)
+static void mergeEventsToFB(Kolab::Freebusy &freebusy, const QList<KMime::Message::Ptr> &messages, const KDateTime &start, const KDateTime &end, const KCalCore::Person::Ptr &organizer)
 {
     QList<KCalCore::Event::Ptr> events;
     Q_FOREACH ( const KMime::Message::Ptr &message, messages ) {
diff --git a/fbdaemon/getuserlistjob.cpp b/fbdaemon/getuserlistjob.cpp
new file mode 100644
index 0000000..bed0943
--- /dev/null
+++ b/fbdaemon/getuserlistjob.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "getuserlistjob.h"
+#include "authenticationjob.h"
+#include <kdebug.h>
+#include <kimap/listjob.h>
+#include <kimap/selectjob.h>
+#include <kimap/namespacejob.h>
+
+class UiProxy: public KIMAP::SessionUiProxy {
+  public:
+    bool ignoreSslError(const KSslErrorUiData& errorData) {
+        kWarning() << "Error during ssl";
+        return true;
+    }
+};
+
+GetUserListJob::GetUserListJob(const QString& hostName, qint16 port, QObject* parent)
+:   KJob(parent),
+    mHostName(hostName),
+    mPort(port),
+    mSession(new KIMAP::Session( hostName, port, this ))
+{
+    mSession->setUiProxy( KIMAP::SessionUiProxy::Ptr(new UiProxy()) );
+    QObject::connect( mSession, SIGNAL(stateChanged(KIMAP::Session::State,KIMAP::Session::State)),
+                      this, SLOT(onSessionStateChanged(KIMAP::Session::State,KIMAP::Session::State)) );
+}
+
+void GetUserListJob::onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState)
+{
+    kDebug() << newState;
+    if (newState == KIMAP::Session::Disconnected && oldState != KIMAP::Session::Disconnected) {
+        kWarning() << "lost connenction";
+    }
+}
+
+void GetUserListJob::start()
+{
+    AuthenticationJob *job = new AuthenticationJob(mSession, this);
+    QObject::connect( job, SIGNAL(result(KJob*)),
+                      this, SLOT(onAuthDone(KJob*)) );
+    job->start();
+}
+
+void GetUserListJob::onAuthDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    kDebug() << "login successful";
+
+//     KIMAP::SelectJob *selectJob = new KIMAP::SelectJob(mSession);
+//     selectJob->setMailBox(QLatin1String("user"));
+//     selectJob->setOpenReadOnly(true);
+//     QObject::connect(selectJob, SIGNAL(result(KJob*)), this, SLOT(onSelectDone(KJob*)));
+//     selectJob->start();
+
+//     KIMAP::NamespaceJob *nsJob = new KIMAP::NamespaceJob( mSession );
+//     QObject::connect( nsJob, SIGNAL(result(KJob*)), SLOT(onNamespacesTestDone(KJob*)));
+//     nsJob->start();
+
+    KIMAP::ListJob *listJob = new KIMAP::ListJob(mSession);
+    listJob->setOption(KIMAP::ListJob::IncludeUnsubscribed);
+//     KIMAP::MailBoxDescriptor desc;
+//     desc.name = QLatin1String("user/");
+//     desc.separator = QLatin1Char('/');
+//     QList<KIMAP::MailBoxDescriptor> namespaces;
+//     namespaces.append(desc);
+//     listJob->setQueriedNamespaces(namespaces);
+    QObject::connect( listJob, SIGNAL(mailBoxesReceived(QList<KIMAP::MailBoxDescriptor>,QList<QList<QByteArray> >)),
+                      this, SLOT(mailBoxesReceived(QList<KIMAP::MailBoxDescriptor>,QList<QList<QByteArray> >)));
+    QObject::connect( listJob, SIGNAL(result(KJob*)),
+                      this, SLOT(onListDone(KJob*)) );
+    listJob->start();
+
+}
+
+void GetUserListJob::onNamespacesTestDone(KJob *job)
+{
+    KIMAP::NamespaceJob *nsJob = qobject_cast<KIMAP::NamespaceJob*>( job );
+    Q_ASSERT(nsJob);
+    foreach (const KIMAP::MailBoxDescriptor &desc, nsJob->personalNamespaces()) {
+        kDebug() << "personal " << desc.name;
+    }
+    foreach (const KIMAP::MailBoxDescriptor &desc, nsJob->userNamespaces()) {
+        kDebug() << "user " << desc.name << desc.separator;
+    }
+    foreach (const KIMAP::MailBoxDescriptor &desc, nsJob->sharedNamespaces()) {
+        kDebug() << "shared " << desc.name;
+    }
+}
+
+
+void GetUserListJob::onSelectDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    
+
+}
+
+
+void GetUserListJob::mailBoxesReceived(const QList<KIMAP::MailBoxDescriptor> &descriptors, const QList< QList< QByteArray > > &flags)
+{
+    // For now we simply extract the name from: user/christian.mollekopf at klab.cc
+    foreach (const KIMAP::MailBoxDescriptor &descriptor, descriptors) {
+        //FIXME this contains to many assumptions about the server, maybe we can use the namespace result instead?
+//         int firstSep = descriptor.name.indexOf(QLatin1Char('/'));
+        int secondSep = descriptor.name.indexOf(QLatin1Char('/'), 6);
+        int index = descriptor.name.indexOf(QLatin1Char('@'), 6);
+//         kDebug() << secondSep << index << descriptor.name;
+        if (descriptor.name.startsWith(QLatin1String("user/")) && (index >= 0) && (secondSep < 0)) {
+            const QString name = descriptor.name.mid(5);
+            kDebug() << name << descriptor.name;
+            if (!mNames.contains(name)) {
+                mNames.append(name);
+            }
+        }
+    }
+}
+
+void GetUserListJob::onListDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    kDebug() << "list successful";
+    emitResult();
+}
+
+
+
+
+
+
+
+
diff --git a/fbdaemon/getuserlistjob.h b/fbdaemon/getuserlistjob.h
new file mode 100644
index 0000000..7e5f6a9
--- /dev/null
+++ b/fbdaemon/getuserlistjob.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GETUSERLISTJOB_H
+#define GETUSERLISTJOB_H
+#include <kjob.h>
+#include <qstringlist.h>
+#include <kimap/session.h>
+#include <kimap/listjob.h>
+
+class GetUserListJob: public KJob
+{
+    Q_OBJECT
+public:
+    explicit GetUserListJob(const QString &hostName, qint16 port, QObject* parent = 0);
+    virtual void start();
+private Q_SLOTS:
+    void onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState);
+    void onAuthDone(KJob*);
+
+private:
+    QString mHostName;
+    qint16 mPort;
+
+    KIMAP::Session *mSession;
+    QStringList mNames;
+
+public slots:
+    void onListDone(KJob*);
+    void mailBoxesReceived(const QList<KIMAP::MailBoxDescriptor> &, const QList<QList<QByteArray> > &);
+    void onSelectDone(KJob*);
+    void onNamespacesTestDone(KJob*);
+};
+
+#endif // GETUSERLISTJOB_H
diff --git a/fbdaemon/kolabjob.cpp b/fbdaemon/kolabjob.cpp
new file mode 100644
index 0000000..acc76b3
--- /dev/null
+++ b/fbdaemon/kolabjob.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "kolabjob.h"
+#include "authenticationjob.h"
+#include <jobs/probekolabserverjob.h>
+#include <kdebug.h>
+
+class UiProxy: public KIMAP::SessionUiProxy {
+  public:
+    bool ignoreSslError(const KSslErrorUiData& errorData) {
+        kWarning() << "Error during ssl";
+        return true;
+    }
+};
+
+KolabJob::KolabJob(const QString& hostName, qint16 port, const QString& username, QObject* parent)
+:   KJob(parent),
+    mHostName(hostName),
+    mPort(port),
+    mUserName(username),
+    mSession(new KIMAP::Session( hostName, port, this ))
+{
+    mSession->setUiProxy( KIMAP::SessionUiProxy::Ptr(new UiProxy()) );
+    QObject::connect( mSession, SIGNAL(stateChanged(KIMAP::Session::State,KIMAP::Session::State)),
+                      this, SLOT(onSessionStateChanged(KIMAP::Session::State,KIMAP::Session::State)) );
+}
+
+void KolabJob::onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState)
+{
+    kDebug() << newState;
+    if (newState == KIMAP::Session::Disconnected && oldState != KIMAP::Session::Disconnected) {
+        kWarning() << "lost connenction";
+    }
+}
+
+void KolabJob::start()
+{
+    kDebug() << "generating f/b for " << mUserName << " on " << mHostName;
+    AuthenticationJob *job = new AuthenticationJob(mUserName, mSession, this);
+    QObject::connect( job, SIGNAL(result(KJob*)),
+                      this, SLOT(onAuthDone(KJob*)) );
+    job->start();
+}
+
+void KolabJob::onAuthDone(KJob *job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    kDebug() << "login successful";
+    ProbeKolabServerJob *probeJob = new ProbeKolabServerJob(mSession, this);
+    QObject::connect(probeJob, SIGNAL(result(KJob*)), this, SLOT(onProbeDone(KJob*)));
+    probeJob->start();
+}
+
+void KolabJob::onProbeDone(KJob* job)
+{
+    if ( job->error() ) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    ProbeKolabServerJob *capabilitiesJob = qobject_cast<ProbeKolabServerJob*>( job );
+    Q_ASSERT(capabilitiesJob);
+    startWork(capabilitiesJob);
+}
diff --git a/fbdaemon/kolabjob.h b/fbdaemon/kolabjob.h
new file mode 100644
index 0000000..f1d54ac
--- /dev/null
+++ b/fbdaemon/kolabjob.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KOLABJOB_H
+#define KOLABJOB_H
+#include <kimap/session.h>
+
+#define X_ORIGIN_HEADER "X-Freebusy-Origin"
+
+class ProbeKolabServerJob;
+class KolabJob: public KJob
+{
+    Q_OBJECT
+public:
+    explicit KolabJob(const QString &hostName, qint16 port, const QString &username, QObject* parent = 0);
+    virtual void start();
+    
+private Q_SLOTS:
+    void onSessionStateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState);
+    void onAuthDone(KJob*);
+    void onProbeDone(KJob* job);
+
+protected:
+    virtual void startWork(ProbeKolabServerJob *job) = 0;
+    QString mHostName;
+    qint16 mPort;
+    QString mUserName;
+
+    QString mFreebusyFolder;
+
+    KIMAP::Session *mSession;
+
+};
+
+#endif // KOLABJOB_H
diff --git a/fbdaemon/main.cpp b/fbdaemon/main.cpp
index 9960cd7..6796668 100644
--- a/fbdaemon/main.cpp
+++ b/fbdaemon/main.cpp
@@ -54,11 +54,16 @@ int main(int argc, char *argv[])
     QObject::connect(&coordinator, SIGNAL(quit()), &app, SLOT(quit()));
     bool nothingTodo = true;
     if (args->isSet("generate")) {
-        coordinator.generateForUser(args->arg(0));
+        if (args->arg(0) == QLatin1String("all")) {
+            coordinator.generateForAllUsers();
+        } else {
+            coordinator.generateForUser(args->arg(0));
+        }
         nothingTodo = false;
     }
     if (args->isSet("aggregate")) {
-
+        coordinator.aggregateForUser(args->arg(0));
+        nothingTodo = false;
     }
     if (args->isSet("daemon")) {
 
diff --git a/testfiles/v2/event/allday.ics b/testfiles/v2/event/allday.ics
new file mode 100644
index 0000000..da7f460
--- /dev/null
+++ b/testfiles/v2/event/allday.ics
@@ -0,0 +1,16 @@
+BEGIN:VCALENDAR
+PRODID:-//K Desktop Environment//NONSGML libkcal 3.2//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20090901T131514Z
+CREATED:20090901T131514Z
+UID:KOrganizer-1256760206.500
+LAST-MODIFIED:20090901T131514Z
+SUMMARY:All Day Event
+DTSTART;VALUE=DATE:20090902
+DTEND;VALUE=DATE:20090903
+TRANSP:OPAQUE
+END:VEVENT
+
+END:VCALENDAR
+


commit 190108bd38902489a0d3a98c44b08404b302a338
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Fri Jun 29 01:03:33 2012 +0200

    De-hardcode timeframe

diff --git a/fbdaemon/fbgeneratorjob.cpp b/fbdaemon/fbgeneratorjob.cpp
index db0638d..653852b 100644
--- a/fbdaemon/fbgeneratorjob.cpp
+++ b/fbdaemon/fbgeneratorjob.cpp
@@ -160,8 +160,12 @@ void FBGeneratorJob::onFetchFBDone(KJob *job)
     //TODO check timeframe of existing f/b object, maybe we don't need to regenerate
     //TODO also check events if anything changed
 
+    KDateTime start = KDateTime::currentUtcDateTime();
+    KDateTime end = start.addDays(Settings::instance().getTimeframe());
+    KCalCore::Person::Ptr organizer = KCalCore::Person::Ptr(new KCalCore::Person(mUserName, "email")); //TODO email
+
 //     kDebug() << mEventFolder;
-    GenerateFBJob *fbJob = new GenerateFBJob(mEventFolders, mSession, this);
+    GenerateFBJob *fbJob = new GenerateFBJob(mEventFolders, start, end, organizer, mSession, this);
     QObject::connect(fbJob, SIGNAL(result(KJob*)), this, SLOT(onGenerateFBDone(KJob*)));
     fbJob->start();
 }
diff --git a/fbdaemon/generatefbjob.cpp b/fbdaemon/generatefbjob.cpp
index b5e2885..d464348 100644
--- a/fbdaemon/generatefbjob.cpp
+++ b/fbdaemon/generatefbjob.cpp
@@ -26,10 +26,13 @@
 #include <errorhandler.h>
 #include <kcalconversion.h>
 
-GenerateFBJob::GenerateFBJob(QStringList kolabEventFolders, KIMAP::Session *session, QObject* parent)
+GenerateFBJob::GenerateFBJob(const QStringList &kolabEventFolders, const KDateTime &start, const KDateTime &end, KCalCore::Person::Ptr organizer, KIMAP::Session *session, QObject* parent)
 :   KJob(parent),
     mSession(session),
-    mKolabEventFolders(kolabEventFolders)
+    mKolabEventFolders(kolabEventFolders),
+    mStart(start),
+    mEnd(end),
+    mOrganizer(organizer)
 {
 
 }
@@ -37,7 +40,8 @@ GenerateFBJob::GenerateFBJob(QStringList kolabEventFolders, KIMAP::Session *sess
 void GenerateFBJob::start()
 {
     const QString mailbox = mKolabEventFolders.takeFirst();
-    kDebug() << "Processing Mailboxes....... " << mailbox;
+    kDebug() << "Generate f/b from mailbox: " << mailbox;
+    kDebug() << "from: " << mStart << " to: " << mEnd;
     FetchMessagesJob *fetchJob = new FetchMessagesJob(mailbox, mSession, this);
     connect( fetchJob, SIGNAL(result(KJob*)), this, SLOT(onFetchDone(KJob*)) );
     fetchJob->start();
@@ -91,12 +95,7 @@ void GenerateFBJob::onFetchDone(KJob *job)
         return;
     }
     
-    //FIXME get from config?
-    KDateTime start(QDate(2010, 1, 10), KDateTime::UTC);
-    KDateTime end(QDate(2013, 1, 10), KDateTime::UTC);
-    KCalCore::Person::Ptr organizer = KCalCore::Person::Ptr(new KCalCore::Person("name", "email"));
-
-    mergeEventsToFB(mFreebusy, fetch->getMessages(), start, end, organizer);
+    mergeEventsToFB(mFreebusy, fetch->getMessages(), mStart, mEnd, mOrganizer);
 
     kDebug() << QString::fromStdString(Kolab::FreebusyUtils::toIFB(mFreebusy));
 
diff --git a/fbdaemon/generatefbjob.h b/fbdaemon/generatefbjob.h
index 1124f57..4eeefe0 100644
--- a/fbdaemon/generatefbjob.h
+++ b/fbdaemon/generatefbjob.h
@@ -22,6 +22,7 @@
 #include <kimap/session.h>
 #include <kimap/fetchjob.h>
 #include <kmime/kmime_message.h>
+#include <kcalcore/person.h>
 
 /**
  * Get events and generate a fb object
@@ -30,7 +31,7 @@ class GenerateFBJob: public KJob
 {
     Q_OBJECT
 public:
-    explicit GenerateFBJob(QStringList kolabEventFolders, KIMAP::Session *, QObject* parent = 0);
+    explicit GenerateFBJob(const QStringList &kolabEventFolders, const KDateTime &start, const KDateTime &end, KCalCore::Person::Ptr organizer, KIMAP::Session *, QObject* parent = 0);
     virtual void start();
     Kolab::Freebusy getFreebusy() const;
 private Q_SLOTS:
@@ -40,6 +41,9 @@ private:
     QStringList mKolabEventFolders;
     Kolab::Freebusy mFreebusy;
     KIMAP::Session *mSession;
+    KDateTime mStart;
+    KDateTime mEnd;
+    KCalCore::Person::Ptr mOrganizer;
 };
 
 #endif // GENERATEFBJOB_H
diff --git a/fbdaemon/settings.cpp b/fbdaemon/settings.cpp
index 8a6bab0..e5d2bc3 100644
--- a/fbdaemon/settings.cpp
+++ b/fbdaemon/settings.cpp
@@ -71,3 +71,14 @@ QString Settings::getPassword() const
 {
     return getValue("admin_password", "VerySecret-admin").toString();
 }
+
+int Settings::getTimeframe() const
+{
+    return 90;
+}
+
+int Settings::getThreshold() const
+{
+    return 0;
+}
+
diff --git a/fbdaemon/settings.h b/fbdaemon/settings.h
index ba74ab6..04a9b52 100644
--- a/fbdaemon/settings.h
+++ b/fbdaemon/settings.h
@@ -36,6 +36,11 @@ public:
 
     QString getAuthorizationUser() const;
     QString getPassword() const;
+
+    //Number of days in f/b
+    int getTimeframe() const;
+    //Number of days after which the f/b is considered out of date
+    int getThreshold() const;
     
 private:
     QVariant getValue(const QString &, const QString &) const;


commit 7db3d930a080863b5d5f8963fe99896d8b1eff79
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Fri Jun 29 00:28:32 2012 +0200

    set job errors, identify old f/b object

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b4c7c94..ec85877 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,7 +16,7 @@ if (USE_LIBCALENDARING)
     message("${Libcalendaring_INCLUDE_DIRS} ${Libcalendaring_LIBRARIES}")
 else()
     find_package(KDE4 4.8 REQUIRED)
-    find_package(KdepimLibs 4.8 REQUIRED)
+    find_package(KdepimLibs 4.9.50 REQUIRED)
     set( KDE_INCLUDES ${KDEPIMLIBS_INCLUDE_DIRS} ${KDE4_INCLUDE_DIR})
     set( KDE_LIBRARIES
         ${KDE4_KDECORE_LIBRARY}
diff --git a/fbdaemon/authenticationjob.cpp b/fbdaemon/authenticationjob.cpp
index 9b74ebb..8dfb72e 100644
--- a/fbdaemon/authenticationjob.cpp
+++ b/fbdaemon/authenticationjob.cpp
@@ -31,10 +31,10 @@ AuthenticationJob::AuthenticationJob(const QString &userName, KIMAP::Session *se
 
 void AuthenticationJob::start()
 {
-    kDebug() << "logging in as " << mUserName;
+    kDebug() << "logging in as " << mUserName << Settings::instance().getAuthorizationUser() << Settings::instance().getPassword();
     KIMAP::LoginJob *loginJob = new KIMAP::LoginJob( mSession );
     loginJob->setUserName( mUserName );
-    loginJob->setAuthorizationName(Settings::instance().getAuthenticationUser()); //TODO needs a kdepimlibs patch
+    loginJob->setAuthorizationName(Settings::instance().getAuthorizationUser());
     loginJob->setPassword(Settings::instance().getPassword());
     
     loginJob->setEncryptionMode( KIMAP::LoginJob::AnySslVersion );
@@ -49,6 +49,7 @@ void AuthenticationJob::onLoginDone(KJob* job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
diff --git a/fbdaemon/fbgeneratorjob.cpp b/fbdaemon/fbgeneratorjob.cpp
index 6704b5c..db0638d 100644
--- a/fbdaemon/fbgeneratorjob.cpp
+++ b/fbdaemon/fbgeneratorjob.cpp
@@ -21,15 +21,21 @@
 #include "fbgeneratorjob.h"
 #include "authenticationjob.h"
 #include "generatefbjob.h"
+#include "settings.h"
 #include "jobs/probekolabserverjob.h"
 #include <jobs/messagemodifyjob.h>
 #include <jobs/fetchmessagesjob.h>
+#include <jobs/sequentialcompositejob.h>
 
 #include <kolabdefinitions.h>
 #include <kolabobject.h>
 #include <errorhandler.h>
 #include <kdebug.h>
 #include <kimap/logoutjob.h>
+#include <kimap/expungejob.h>
+
+
+#define X_ORIGIN_HEADER "X-Freebusy-Origin"
 
 class UiProxy: public KIMAP::SessionUiProxy {
   public:
@@ -62,7 +68,7 @@ void FBGeneratorJob::onSessionStateChanged(KIMAP::Session::State newState, KIMAP
 
 void FBGeneratorJob::start()
 {
-    kDebug() << "generating f/b for " << mUserName;
+    kDebug() << "generating f/b for " << mUserName << " on " << mHostName;
     AuthenticationJob *job = new AuthenticationJob(mUserName, mSession, this);
     QObject::connect( job, SIGNAL(result(KJob*)),
                       this, SLOT(onAuthDone(KJob*)) );
@@ -81,10 +87,11 @@ void FBGeneratorJob::onAuthDone(KJob *job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
-
+    kDebug() << "login successful";
     ProbeKolabServerJob *probeJob = new ProbeKolabServerJob(mSession, this);
     QObject::connect(probeJob, SIGNAL(result(KJob*)), this, SLOT(onProbeDone(KJob*)));
     probeJob->start();
@@ -94,6 +101,7 @@ void FBGeneratorJob::onProbeDone(KJob* job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -104,6 +112,7 @@ void FBGeneratorJob::onProbeDone(KJob* job)
     //TODO freebusy default folder
     if (capabilitiesJob->kolabFolders().values(KOLAB_FOLDER_TYPE_FREEBUSY).isEmpty()) {
         kWarning() << "no freebusy folder found";
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -120,18 +129,36 @@ void FBGeneratorJob::onFetchFBDone(KJob *job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
     FetchMessagesJob *fetchJob = qobject_cast<FetchMessagesJob*>( job );
     Q_ASSERT(fetchJob);
 
+    kDebug() << fetchJob->getMessages().size();
+    foreach (const KMime::Message::Ptr &msg, fetchJob->getMessages()) {
+        kDebug() << "existing fb object " << msg->subject()->asUnicodeString();
+    }
+
+    /*
+     * The f/b object to update is identified based on a Mime-Header
+     *
+     * For the local server we're going to use the Settings::getServerUri()
+     */
+    const QString localUri = Settings::instance().getServerUri().toUtf8();
     foreach (const KMime::Message::Ptr &msg, fetchJob->getMessages()) {
-        //TODO identify correct fb object
-        mOldImapUid = fetchJob->getImapUid(msg);
-        mOldFlags = fetchJob->getFlags(msg);
-        break; //FIXME currently we just have only one f/b object
+        KMime::Headers::Base *xOriginHeader = msg->getHeaderByType(X_ORIGIN_HEADER);
+        if (xOriginHeader) kDebug() << "existing fb object " << xOriginHeader->asUnicodeString() << localUri;
+        if (xOriginHeader && (xOriginHeader->asUnicodeString() == localUri)) {
+            
+            mOldImapUid = fetchJob->getImapUid(msg);
+            mOldFlags = fetchJob->getFlags(msg);
+            break;
+        }
     }
+    //TODO check timeframe of existing f/b object, maybe we don't need to regenerate
+    //TODO also check events if anything changed
 
 //     kDebug() << mEventFolder;
     GenerateFBJob *fbJob = new GenerateFBJob(mEventFolders, mSession, this);
@@ -156,11 +183,17 @@ void FBGeneratorJob::onGenerateFBDone(KJob *job)
         emitResult();
         return;
     }
-    kDebug() << message->encodedContent();
 
-    MessageModifyJob *modJob = new MessageModifyJob(message, mFreebusyFolder, mOldFlags, mOldImapUid, mSession, this);
-    QObject::connect(modJob, SIGNAL(result(KJob*)), this, SLOT(onModDone(KJob*)));
-    modJob->start();
+    message->appendHeader( new KMime::Headers::Generic( X_ORIGIN_HEADER, message.get(), Settings::instance().getServerUri().toUtf8(), "utf-8" ) );
+    message->assemble();
+    
+    kDebug() << message->encodedContent();
+    SequentialCompositeJob *seqJob = new SequentialCompositeJob(this);
+    seqJob->addSubjob(new MessageModifyJob(message, mFreebusyFolder, mOldFlags, mOldImapUid, mSession, this));
+    seqJob->addSubjob(new KIMAP::ExpungeJob(mSession));
+    seqJob->addSubjob(new KIMAP::LogoutJob(mSession));
+    QObject::connect(seqJob, SIGNAL(result(KJob*)), this, SLOT(onModDone(KJob*)));
+    seqJob->start();
 }
 
 void FBGeneratorJob::onModDone(KJob *job)
@@ -169,9 +202,6 @@ void FBGeneratorJob::onModDone(KJob *job)
     if ( job->error() ) {
         kWarning() << job->errorString();
     }
-    //TODO expunge
-    //Logout after we're done
-    new KIMAP::LogoutJob(mSession);
 
     emitResult();
 }
diff --git a/fbdaemon/generatefbjob.cpp b/fbdaemon/generatefbjob.cpp
index c70cc1e..b5e2885 100644
--- a/fbdaemon/generatefbjob.cpp
+++ b/fbdaemon/generatefbjob.cpp
@@ -76,6 +76,7 @@ void GenerateFBJob::onFetchDone(KJob *job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
diff --git a/fbdaemon/main.cpp b/fbdaemon/main.cpp
index c112b2f..9960cd7 100644
--- a/fbdaemon/main.cpp
+++ b/fbdaemon/main.cpp
@@ -52,15 +52,21 @@ int main(int argc, char *argv[])
 
     FBCoordinator coordinator(&app);
     QObject::connect(&coordinator, SIGNAL(quit()), &app, SLOT(quit()));
+    bool nothingTodo = true;
     if (args->isSet("generate")) {
         coordinator.generateForUser(args->arg(0));
+        nothingTodo = false;
     }
     if (args->isSet("aggregate")) {
-        
+
     }
     if (args->isSet("daemon")) {
 
     }
+    if (nothingTodo) {
+        return 0;
+    }
+
     app.exec();
     return 0;
 }
\ No newline at end of file
diff --git a/fbdaemon/settings.cpp b/fbdaemon/settings.cpp
index 8f48873..8a6bab0 100644
--- a/fbdaemon/settings.cpp
+++ b/fbdaemon/settings.cpp
@@ -62,7 +62,7 @@ qint16 Settings::getServerPort() const
     return getValue("port", "993").value<qint16>();
 }
 
-QString Settings::getAuthenticationUser() const
+QString Settings::getAuthorizationUser() const
 {
     return getValue("admin_login", "cyrus-admin").toString();
 }
diff --git a/fbdaemon/settings.h b/fbdaemon/settings.h
index 3fd315c..ba74ab6 100644
--- a/fbdaemon/settings.h
+++ b/fbdaemon/settings.h
@@ -34,7 +34,7 @@ public:
     QString getServerUri() const;
     qint16 getServerPort() const;
 
-    QString getAuthenticationUser() const;
+    QString getAuthorizationUser() const;
     QString getPassword() const;
     
 private:
diff --git a/jobs/fetchmessagesjob.cpp b/jobs/fetchmessagesjob.cpp
index 4831c0c..87818e4 100644
--- a/jobs/fetchmessagesjob.cpp
+++ b/jobs/fetchmessagesjob.cpp
@@ -46,6 +46,7 @@ void FetchMessagesJob::onSelectDone(KJob *job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
diff --git a/jobs/findkolabfoldersjob.cpp b/jobs/findkolabfoldersjob.cpp
index 613228c..ce0ca12 100644
--- a/jobs/findkolabfoldersjob.cpp
+++ b/jobs/findkolabfoldersjob.cpp
@@ -109,6 +109,7 @@ void FindKolabFoldersJob::onGetMetaDataDone( KJob *job )
     m_metadataRetrieveJobs--;
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         if (m_mailBoxReceiveDone && (m_metadataRetrieveJobs <= 0)) {
             emitResult();
         }
diff --git a/jobs/messagemodifyjob.cpp b/jobs/messagemodifyjob.cpp
index 53c08dd..2c549ff 100644
--- a/jobs/messagemodifyjob.cpp
+++ b/jobs/messagemodifyjob.cpp
@@ -59,6 +59,7 @@ void MessageModifyJob::onAppendMessageDone( KJob *job )
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -85,6 +86,7 @@ void MessageModifyJob::onPreDeleteSelectDone( KJob *job )
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -115,6 +117,7 @@ void MessageModifyJob::onDeleteDone( KJob *job )
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
diff --git a/jobs/probekolabserverjob.cpp b/jobs/probekolabserverjob.cpp
index adeb603..b3a8495 100644
--- a/jobs/probekolabserverjob.cpp
+++ b/jobs/probekolabserverjob.cpp
@@ -44,6 +44,7 @@ void ProbeKolabServerJob::onCapabilitiesTestDone(KJob* job)
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -67,6 +68,7 @@ void ProbeKolabServerJob::onNamespacesTestDone( KJob *job )
 {
     if ( job->error() ) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
@@ -84,6 +86,7 @@ void ProbeKolabServerJob::findKolabFoldersDone(KJob *job)
 {
     if (job->error()) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
         emitResult();
         return;
     }
diff --git a/jobs/sequentialcompositejob.cpp b/jobs/sequentialcompositejob.cpp
index 96aeac7..854829e 100644
--- a/jobs/sequentialcompositejob.cpp
+++ b/jobs/sequentialcompositejob.cpp
@@ -19,7 +19,7 @@
 
 
 #include "sequentialcompositejob.h"
-#include <KDE/KDebug>
+#include <kdebug.h>
 
 SequentialCompositeJob::SequentialCompositeJob(QObject* parent)
 : KCompositeJob(parent)
@@ -37,6 +37,7 @@ void SequentialCompositeJob::slotResult(KJob* job)
 {
     if (job->error()) {
         kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
     }
     m_jobs.removeAll(job);
     KCompositeJob::slotResult(job);





More information about the commits mailing list