summaryrefslogtreecommitdiffstats
path: root/kresources/egroupware
diff options
context:
space:
mode:
Diffstat (limited to 'kresources/egroupware')
-rw-r--r--kresources/egroupware/Makefile.am73
-rw-r--r--kresources/egroupware/access.h31
-rw-r--r--kresources/egroupware/debugdialog.cpp126
-rw-r--r--kresources/egroupware/debugdialog.h78
-rw-r--r--kresources/egroupware/kabc_egroupwareprefs.kcfgc11
-rw-r--r--kresources/egroupware/kabc_resourcexmlrpc.cpp771
-rw-r--r--kresources/egroupware/kabc_resourcexmlrpc.h114
-rw-r--r--kresources/egroupware/kabc_resourcexmlrpcconfig.cpp97
-rw-r--r--kresources/egroupware/kabc_resourcexmlrpcconfig.h52
-rw-r--r--kresources/egroupware/kabc_resourcexmlrpcplugin.cpp40
-rw-r--r--kresources/egroupware/kabc_xmlrpc.desktop51
-rw-r--r--kresources/egroupware/kcal_egroupwareprefs.kcfgc11
-rw-r--r--kresources/egroupware/kcal_resourcexmlrpc.cpp1203
-rw-r--r--kresources/egroupware/kcal_resourcexmlrpc.h236
-rw-r--r--kresources/egroupware/kcal_resourcexmlrpcconfig.cpp98
-rw-r--r--kresources/egroupware/kcal_resourcexmlrpcconfig.h53
-rw-r--r--kresources/egroupware/kcal_resourcexmlrpcplugin.cpp40
-rw-r--r--kresources/egroupware/kcal_xmlrpc.desktop51
-rw-r--r--kresources/egroupware/knotes_egroupwareprefs.kcfgc11
-rw-r--r--kresources/egroupware/knotes_resourcexmlrpc.cpp333
-rw-r--r--kresources/egroupware/knotes_resourcexmlrpc.h103
-rw-r--r--kresources/egroupware/knotes_resourcexmlrpcconfig.cpp98
-rw-r--r--kresources/egroupware/knotes_resourcexmlrpcconfig.h53
-rw-r--r--kresources/egroupware/knotes_resourcexmlrpcplugin.cpp40
-rw-r--r--kresources/egroupware/knotes_xmlrpc.desktop51
-rw-r--r--kresources/egroupware/kresources_kabc_egroupware.kcfg24
-rw-r--r--kresources/egroupware/kresources_kcal_egroupware.kcfg24
-rw-r--r--kresources/egroupware/kresources_knotes_egroupware.kcfg24
-rw-r--r--kresources/egroupware/synchronizer.cpp50
-rw-r--r--kresources/egroupware/synchronizer.h72
-rw-r--r--kresources/egroupware/todostatemapper.cpp167
-rw-r--r--kresources/egroupware/todostatemapper.h75
-rw-r--r--kresources/egroupware/xmlrpciface.cpp464
-rw-r--r--kresources/egroupware/xmlrpciface.h165
34 files changed, 4890 insertions, 0 deletions
diff --git a/kresources/egroupware/Makefile.am b/kresources/egroupware/Makefile.am
new file mode 100644
index 000000000..8325ed01c
--- /dev/null
+++ b/kresources/egroupware/Makefile.am
@@ -0,0 +1,73 @@
+INCLUDES = -I$(top_srcdir)/libical/src/libical \
+ -I$(top_srcdir)/libical/src/libicalss \
+ -I$(top_builddir)/libical/src/libical \
+ -I$(top_builddir)/libical/src/libicalss \
+ -I$(srcdir)/versit -I$(top_srcdir)/ \
+ -I$(top_srcdir)/knotes \
+ -I$(top_builddir)/kaddressbook \
+ -I$(top_builddir)/kaddressbook/common \
+ -I$(top_srcdir)/kaddressbook/common \
+ -I$(top_builddir)/kresources/egroupware \
+ $(all_includes)
+
+noinst_HEADERS = kabc_resourcexmlrpcconfig.h kcal_resourcexmlrpcconfig.h \
+ knotes_resourcexmlrpcconfig.h
+
+noinst_LTLIBRARIES = libegwcommon.la
+libegwcommon_la_SOURCES = xmlrpciface.cpp synchronizer.cpp debugdialog.cpp
+
+lib_LTLIBRARIES = libkabc_xmlrpc.la libkcal_xmlrpc.la libknotes_xmlrpc.la
+libkabc_xmlrpc_la_SOURCES = kabc_resourcexmlrpc.cpp kabc_resourcexmlrpcconfig.cpp \
+ kabc_egroupwareprefs.kcfgc
+libkabc_xmlrpc_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) -version-info 1:0:0 -no-undefined
+libkabc_xmlrpc_la_LIBADD = $(LIB_KIO) -lkabc $(top_builddir)/libkdepim/libkdepim.la \
+ $(top_builddir)/kaddressbook/common/libkabcommon.la \
+ libegwcommon.la
+
+libkcal_xmlrpc_la_SOURCES = kcal_resourcexmlrpc.cpp kcal_resourcexmlrpcconfig.cpp \
+ todostatemapper.cpp kcal_egroupwareprefs.kcfgc
+libkcal_xmlrpc_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) -version-info 1:0:0 -no-undefined
+libkcal_xmlrpc_la_LIBADD = $(top_builddir)/libkcal/libkcal.la \
+ $(top_builddir)/libkdepim/libkdepim.la \
+ libegwcommon.la
+
+libknotes_xmlrpc_la_SOURCES = knotes_resourcexmlrpc.cpp knotes_resourcexmlrpcconfig.cpp \
+ knotes_egroupwareprefs.kcfgc
+libknotes_xmlrpc_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) -version-info 1:0:0 -no-undefined
+libknotes_xmlrpc_la_LIBADD = $(top_builddir)/libkcal/libkcal.la -lkdeprint \
+ $(top_builddir)/knotes/libknotesresources.la \
+ $(top_builddir)/libkdepim/libkdepim.la \
+ libegwcommon.la
+
+kabcincludedir = $(includedir)/kabc
+kabcinclude_HEADERS = kabc_resourcexmlrpc.h kcal_resourcexmlrpc.h
+
+kde_module_LTLIBRARIES = kabc_xmlrpc.la kcal_xmlrpc.la knotes_xmlrpc.la
+
+kabc_xmlrpc_la_SOURCES = kabc_resourcexmlrpcplugin.cpp
+kabc_xmlrpc_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kabc_xmlrpc_la_LIBADD = libkabc_xmlrpc.la
+
+kcal_xmlrpc_la_SOURCES = kcal_resourcexmlrpcplugin.cpp
+kcal_xmlrpc_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kcal_xmlrpc_la_LIBADD = libkcal_xmlrpc.la
+
+knotes_xmlrpc_la_SOURCES = knotes_resourcexmlrpcplugin.cpp
+knotes_xmlrpc_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+knotes_xmlrpc_la_LIBADD = libknotes_xmlrpc.la
+
+kabc_servicedir = $(kde_servicesdir)/kresources/kabc
+kabc_service_DATA = kabc_xmlrpc.desktop
+
+kcal_servicedir = $(kde_servicesdir)/kresources/kcal
+kcal_service_DATA = kcal_xmlrpc.desktop
+
+knotes_servicedir = $(kde_servicesdir)/kresources/knotes
+knotes_service_DATA = knotes_xmlrpc.desktop
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kres_xmlrpc.pot
+
+kabc_resourcexmlrpc.lo: ../../kaddressbook/common/kabprefs_base.h
diff --git a/kresources/egroupware/access.h b/kresources/egroupware/access.h
new file mode 100644
index 000000000..8ed6a6afe
--- /dev/null
+++ b/kresources/egroupware/access.h
@@ -0,0 +1,31 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ACCESS_H
+#define ACCESS_H
+
+#define EGW_ACCESS_READ 1
+#define EGW_ACCESS_ADD 2
+#define EGW_ACCESS_EDIT 4
+#define EGW_ACCESS_DELETE 8
+#define EGW_ACCESS_PRIVATE 9
+#define EGW_ACCESS_ALL 15
+
+#endif
diff --git a/kresources/egroupware/debugdialog.cpp b/kresources/egroupware/debugdialog.cpp
new file mode 100644
index 000000000..117db3243
--- /dev/null
+++ b/kresources/egroupware/debugdialog.cpp
@@ -0,0 +1,126 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qfile.h>
+#include <qfiledialog.h>
+#include <qlayout.h>
+
+#include <ktextbrowser.h>
+#include <kstaticdeleter.h>
+
+#include <stdlib.h>
+#include <klocale.h>
+#include "debugdialog.h"
+
+DebugDialog* DebugDialog::mSelf = 0;
+static KStaticDeleter<DebugDialog> debugDialogDeleter;
+
+DebugDialog::DebugDialog()
+ : KDialogBase( Plain, WStyle_DialogBorder | WStyle_StaysOnTop, 0,
+ "Debug Dialog", false, i18n("Debug Dialog"),
+ User1 | User2 | Ok, Ok, true )
+{
+ QWidget *page = plainPage();
+ QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
+
+ mView = new KTextBrowser( page );
+ layout->addWidget( mView );
+
+ setButtonText( User1, "Save As..." );
+ setButtonText( User2, "Clear" );
+
+ clear();
+}
+
+void DebugDialog::init()
+{
+ if ( !mSelf ) {
+ if ( getenv( "EGROUPWARE_DEBUG" ) != 0 ) {
+ debugDialogDeleter.setObject( mSelf, new DebugDialog );
+ }
+ }
+
+ if ( mSelf ) {
+ mSelf->show();
+ mSelf->raise();
+ }
+}
+
+DebugDialog::~DebugDialog()
+{
+ mSelf = 0;
+}
+
+void DebugDialog::addMessage( const QString &msg, Type type )
+{
+ if ( mSelf )
+ mSelf->addText( msg, type );
+}
+
+void DebugDialog::clear()
+{
+ mView->clear();
+ mMessages.clear();
+}
+
+void DebugDialog::save()
+{
+ QString fileName = QFileDialog::getSaveFileName();
+ if ( fileName.isEmpty() )
+ return;
+
+ QFile file( fileName );
+ if ( !file.open( IO_WriteOnly ) ) {
+ qWarning( "Couldn't open file %s", file.name().latin1() );
+ return;
+ }
+
+ file.writeBlock( mMessages.join( "\n\n" ).utf8() );
+ file.close();
+}
+
+void DebugDialog::slotUser1()
+{
+ save();
+}
+
+void DebugDialog::slotUser2()
+{
+ clear();
+}
+
+void DebugDialog::addText( const QString &text, Type type )
+{
+ QString htmlCode( text );
+ htmlCode.replace( "<", "&lt;" );
+ htmlCode.replace( ">", "&gt;" );
+ htmlCode.replace( "\n", "<br>" );
+
+ mMessages.append( text );
+ if ( type == Input )
+ mHTMLMessages.append( "<font color=\"green\">" + htmlCode + "</font>" );
+ else
+ mHTMLMessages.append( "<font color=\"blue\">" + htmlCode + "</font>" );
+
+ mView->clear();
+ mView->setText( mHTMLMessages.join( "<br>" ) );
+}
+
+#include "debugdialog.moc"
diff --git a/kresources/egroupware/debugdialog.h b/kresources/egroupware/debugdialog.h
new file mode 100644
index 000000000..c5f91377f
--- /dev/null
+++ b/kresources/egroupware/debugdialog.h
@@ -0,0 +1,78 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DEBUGDIALOG_H
+#define DEBUGDIALOG_H
+
+#include <kdialogbase.h>
+
+class KTextBrowser;
+
+/**
+ A dialog that parses chunks of XML documents and
+ displays them in a treeview.
+ */
+class DebugDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ The type of the message.
+ */
+ enum Type { Input, Output };
+
+ /**
+ Starts the debug dialog depending on the presence
+ of the environment variable EGROUPWARE_DEBUG.
+ */
+ static void init();
+
+ /**
+ Destructor.
+ */
+ ~DebugDialog();
+
+ /**
+ Adds a message, which will be shown by the dialog.
+ */
+ static void addMessage( const QString &msg, Type type );
+
+ private slots:
+ void clear();
+ void save();
+
+ protected slots:
+ virtual void slotUser1();
+ virtual void slotUser2();
+
+ private:
+ DebugDialog();
+ static DebugDialog *mSelf;
+
+ void addText( const QString&, Type );
+
+ QStringList mMessages;
+ QStringList mHTMLMessages;
+
+ KTextBrowser *mView;
+};
+
+#endif
diff --git a/kresources/egroupware/kabc_egroupwareprefs.kcfgc b/kresources/egroupware/kabc_egroupwareprefs.kcfgc
new file mode 100644
index 000000000..0009334ac
--- /dev/null
+++ b/kresources/egroupware/kabc_egroupwareprefs.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=kresources_kabc_egroupware.kcfg
+ClassName=EGroupwarePrefs
+NameSpace=KABC
+Singleton=false
+Mutators=true
+Inherits=KResourcePrefs
+IncludeFiles=libkdepim/kresourceprefs.h
+GlobalEnums=true
+#ItemAccessors=true
+#SetUserTexts=true
diff --git a/kresources/egroupware/kabc_resourcexmlrpc.cpp b/kresources/egroupware/kabc_resourcexmlrpc.cpp
new file mode 100644
index 000000000..eba630cc3
--- /dev/null
+++ b/kresources/egroupware/kabc_resourcexmlrpc.cpp
@@ -0,0 +1,771 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qapplication.h>
+
+#include <kabc/addressee.h>
+#include <kabprefs.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmdcodec.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+#include <libkcal/freebusyurlstore.h>
+#include <libkdepim/kpimprefs.h>
+
+#include "kabc_egroupwareprefs.h"
+#include "kabc_resourcexmlrpc.h"
+#include "kabc_resourcexmlrpcconfig.h"
+
+#include "access.h"
+#include "synchronizer.h"
+#include "xmlrpciface.h"
+
+using namespace KABC;
+
+static const QString SearchContactsCommand = "addressbook.boaddressbook.search";
+static const QString AddContactCommand = "addressbook.boaddressbook.write";
+static const QString DeleteContactCommand = "addressbook.boaddressbook.delete";
+static const QString LoadCategoriesCommand = "addressbook.boaddressbook.categories";
+static const QString LoadCustomFieldsCommand = "addressbook.boaddressbook.customfields";
+
+static void setRights( KABC::Addressee &addr, int rights )
+{
+ addr.insertCustom( "EGWRESOURCE", "RIGHTS", QString::number( rights ) );
+}
+
+static int rights( const KABC::Addressee &addr )
+{
+ return addr.custom( "EGWRESOURCE", "RIGHTS" ).toInt();
+}
+
+ResourceXMLRPC::ResourceXMLRPC( const KConfig *config )
+ : ResourceCached( config ), mServer( 0 )
+{
+ init();
+
+ mPrefs->addGroupPrefix( identifier() );
+
+ if ( config )
+ mPrefs->readConfig();
+
+ initEGroupware();
+}
+
+ResourceXMLRPC::ResourceXMLRPC( const QString &url, const QString &domain,
+ const QString &user, const QString &password )
+ : ResourceCached( 0 ), mServer( 0 )
+{
+ init();
+
+ mPrefs->addGroupPrefix( identifier() );
+
+ mPrefs->setUrl( url );
+ mPrefs->setDomain( domain );
+ mPrefs->setUser( user );
+ mPrefs->setPassword( password );
+
+ initEGroupware();
+}
+
+void ResourceXMLRPC::init()
+{
+ setType( "xmlrpc" );
+
+ mSynchronizer = new Synchronizer;
+
+ mPrefs = new EGroupwarePrefs;
+}
+
+void ResourceXMLRPC::initEGroupware()
+{
+ KURL url( mPrefs->url() );
+
+ mAddrTypes.insert( "dom", Address::Dom );
+ mAddrTypes.insert( "intl", Address::Intl );
+ mAddrTypes.insert( "parcel", Address::Parcel );
+ mAddrTypes.insert( "postal", Address::Postal );
+}
+
+ResourceXMLRPC::~ResourceXMLRPC()
+{
+ saveCache();
+
+ delete mServer;
+ mServer = 0;
+
+ delete mPrefs;
+ mPrefs = 0;
+
+ delete mSynchronizer;
+ mSynchronizer = 0;
+}
+
+void ResourceXMLRPC::writeConfig( KConfig *config )
+{
+ Resource::writeConfig( config );
+
+ mPrefs->writeConfig();
+}
+
+Ticket *ResourceXMLRPC::requestSaveTicket()
+{
+ if ( !addressBook() ) {
+ kdDebug(5700) << "no addressbook" << endl;
+ return 0;
+ }
+
+ return createTicket( this );
+}
+
+void ResourceXMLRPC::releaseSaveTicket( Ticket *ticket )
+{
+ delete ticket;
+}
+
+bool ResourceXMLRPC::doOpen()
+{
+ if ( mServer )
+ delete mServer;
+
+ mServer = new KXMLRPC::Server( KURL(), this );
+ mServer->setUrl( KURL( mPrefs->url() ) );
+ mServer->setUserAgent( "KDE-AddressBook" );
+
+ QMap<QString, QVariant> args;
+ args.insert( "domain", mPrefs->domain() );
+ args.insert( "username", mPrefs->user() );
+ args.insert( "password", mPrefs->password() );
+
+ mServer->call( "system.login", QVariant( args ),
+ this, SLOT( loginFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mSynchronizer->start();
+
+ return true;
+}
+
+void ResourceXMLRPC::doClose()
+{
+ QMap<QString, QVariant> args;
+ args.insert( "sessionid", mSessionID );
+ args.insert( "kp3", mKp3 );
+
+ mServer->call( "system.logout", QVariant( args ),
+ this, SLOT( logoutFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mSynchronizer->start();
+}
+
+bool ResourceXMLRPC::load()
+{
+ mAddrMap.clear();
+
+ return true;
+}
+
+bool ResourceXMLRPC::asyncLoad()
+{
+ if ( !mServer )
+ return false;
+
+ mAddrMap.clear();
+
+ loadCache();
+
+ QMap<QString, QVariant> args;
+ args.insert( "start", "0" );
+ args.insert( "query", "" );
+ args.insert( "filter", "" );
+ args.insert( "sort", "" );
+ args.insert( "order", "" );
+ args.insert( "include_users", "calendar" );
+
+ mServer->call( SearchContactsCommand, args,
+ this, SLOT( listContactsFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mServer->call( LoadCategoriesCommand, QVariant( false, 0 ),
+ this, SLOT( loadCategoriesFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mServer->call( LoadCustomFieldsCommand, QVariant( QValueList<QVariant>() ),
+ this, SLOT( loadCustomFieldsFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ return true;
+}
+
+
+bool ResourceXMLRPC::save( Ticket *ticket )
+{
+ return asyncSave( ticket );
+}
+
+bool ResourceXMLRPC::asyncSave( Ticket* )
+{
+ KABC::Addressee::List::ConstIterator it;
+
+ const KABC::Addressee::List addedList = addedAddressees();
+ for ( it = addedList.begin(); it != addedList.end(); ++it ) {
+ addContact( *it );
+ }
+
+ const KABC::Addressee::List changedList = changedAddressees();
+ for ( it = changedList.begin(); it != changedList.end(); ++it ) {
+ updateContact( *it );
+ }
+
+ const KABC::Addressee::List deletedList = deletedAddressees();
+ for ( it = deletedList.begin(); it != deletedList.end(); ++it ) {
+ deleteContact( *it );
+ }
+
+ return true;
+}
+
+void ResourceXMLRPC::addContact( const Addressee& addr )
+{
+ QMap<QString, QVariant> args;
+ writeContact( addr, args );
+
+ mServer->call( AddContactCommand, args,
+ this, SLOT( addContactFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( addContactFault( int, const QString&, const QVariant& ) ),
+ QVariant( addr.uid() ) );
+}
+
+void ResourceXMLRPC::updateContact( const Addressee& addr )
+{
+ if ( !(rights( addr ) & EGW_ACCESS_DELETE) && (rights( addr ) != -1) ) {
+ clearChange( addr.uid() );
+ return;
+ }
+
+ QMap<QString, QVariant> args;
+ writeContact( addr, args );
+
+ args.insert( "id", idMapper().remoteId( addr.uid() ) );
+ mServer->call( AddContactCommand, args,
+ this, SLOT( updateContactFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( updateContactFault( int, const QString&, const QVariant& ) ),
+ QVariant( addr.uid() ) );
+}
+
+void ResourceXMLRPC::deleteContact( const Addressee& addr )
+{
+ if ( !(rights( addr ) & EGW_ACCESS_DELETE) && rights( addr ) != -1 ) {
+ clearChange( addr.uid() );
+ idMapper().removeRemoteId( idMapper().remoteId( addr.uid() ) );
+ return;
+ }
+
+ mServer->call( DeleteContactCommand, idMapper().remoteId( addr.uid() ),
+ this, SLOT( deleteContactFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( deleteContactFault( int, const QString&, const QVariant& ) ),
+ QVariant( addr.uid() ) );
+}
+
+void ResourceXMLRPC::loginFinished( const QValueList<QVariant> &variant,
+ const QVariant& )
+{
+ QMap<QString, QVariant> map = variant[0].toMap();
+
+ KURL url( mPrefs->url() );
+ if ( map[ "GOAWAY" ].toString() == "XOXO" ) { // failed
+ mSessionID = mKp3 = "";
+ addressBook()->error( i18n( "Login failed, please check your username and password." ) );
+ } else {
+ mSessionID = map[ "sessionid" ].toString();
+ mKp3 = map[ "kp3" ].toString();
+ }
+
+ url.setUser( mSessionID );
+ url.setPass( mKp3 );
+ mServer->setUrl( url );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::logoutFinished( const QValueList<QVariant> &variant,
+ const QVariant& )
+{
+ QMap<QString, QVariant> map = variant[0].toMap();
+
+ if ( map[ "GOODBYE" ].toString() != "XOXO" )
+ addressBook()->error( i18n( "Logout failed, please check your username and password." ) );
+
+ KURL url( mPrefs->url() );
+ mSessionID = mKp3 = "";
+ url.setUser( mSessionID );
+ url.setPass( mKp3 );
+ mServer->setUrl( url );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::listContactsFinished( const QValueList<QVariant> &mapList,
+ const QVariant& )
+{
+ const QValueList<QVariant> contactList = mapList[ 0 ].toList();
+ QValueList<QVariant>::ConstIterator contactIt;
+
+ KABC::Addressee::List serverContacts;
+ for ( contactIt = contactList.begin(); contactIt != contactList.end(); ++contactIt ) {
+ const QMap<QString, QVariant> map = (*contactIt).toMap();
+
+ Addressee addr;
+ QString uid;
+
+ readContact( map, addr, uid );
+
+ if ( !addr.isEmpty() ) {
+ addr.setResource( this );
+ addr.setChanged( false );
+
+ QString local = idMapper().localId( uid );
+ if ( local.isEmpty() ) { // new entry
+ idMapper().setRemoteId( addr.uid(), uid );
+ } else {
+ addr.setUid( local );
+ }
+
+ mAddrMap.insert( addr.uid(), addr );
+ serverContacts.append( addr );
+ }
+ }
+
+ cleanUpCache( serverContacts );
+ saveCache();
+
+ emit loadingFinished( this );
+}
+
+void ResourceXMLRPC::addContactFinished( const QValueList<QVariant> &list,
+ const QVariant &id )
+{
+ clearChange( id.toString() );
+ idMapper().setRemoteId( id.toString(), list[ 0 ].toString() );
+
+ saveCache();
+}
+
+void ResourceXMLRPC::updateContactFinished( const QValueList<QVariant>&,
+ const QVariant &id )
+{
+ clearChange( id.toString() );
+
+ saveCache();
+}
+
+void ResourceXMLRPC::deleteContactFinished( const QValueList<QVariant>&,
+ const QVariant &id )
+{
+ clearChange( id.toString() );
+ idMapper().removeRemoteId( idMapper().remoteId( id.toString() ) );
+
+ saveCache();
+}
+
+void ResourceXMLRPC::fault( int error, const QString &errorMsg,
+ const QVariant& )
+{
+ QString msg = i18n( "<qt>Server sent error %1: <b>%2</b></qt>" ).arg( error ).arg( errorMsg );
+ if ( addressBook() )
+ addressBook()->error( msg );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::addContactFault( int, const QString &errorMsg,
+ const QVariant &id )
+{
+ KABC::Addressee addr = mAddrMap[ id.toString() ];
+
+ mAddrMap.remove( addr.uid() );
+
+ QString msg = i18n( "Unable to add contact %1 to server. (%2)" );
+ addressBook()->error( msg.arg( addr.formattedName(), errorMsg ) );
+}
+
+void ResourceXMLRPC::updateContactFault( int, const QString &errorMsg,
+ const QVariant &id )
+{
+ KABC::Addressee addr = mAddrMap[ id.toString() ];
+
+ QString msg = i18n( "Unable to update contact %1 on server. (%2)" );
+ addressBook()->error( msg.arg( addr.formattedName(), errorMsg ) );
+}
+
+void ResourceXMLRPC::deleteContactFault( int, const QString &errorMsg,
+ const QVariant &id )
+{
+ KABC::Addressee addr;
+
+ const KABC::Addressee::List deletedList = deletedAddressees();
+ KABC::Addressee::List::ConstIterator it;
+ for ( it = deletedList.begin(); it != deletedList.end(); ++it ) {
+ if ( (*it).uid() == id.toString() ) {
+ addr = *it;
+ break;
+ }
+ }
+
+ mAddrMap.insert( addr.uid(), addr );
+
+ QString msg = i18n( "Unable to delete contact %1 from server. (%2)" );
+ addressBook()->error( msg.arg( addr.formattedName(), errorMsg ) );
+}
+
+QString ResourceXMLRPC::addrTypesToTypeStr( int typeMask )
+{
+ QStringList types;
+ QMap<QString, int>::ConstIterator it;
+ for ( it = mAddrTypes.begin(); it != mAddrTypes.end(); ++it )
+ if ( it.data() & typeMask )
+ types.append( it.key() );
+
+ return types.join( ";" );
+}
+
+void ResourceXMLRPC::writeContact( const Addressee &addr, QMap<QString, QVariant> &args )
+{
+ args.insert( "access", ( addr.secrecy().type() == Secrecy::Private ? "private" : "public" ) );
+ args.insert( "fn", addr.formattedName() );
+ args.insert( "n_given", addr.givenName() );
+ args.insert( "n_family", addr.familyName() );
+ args.insert( "n_middle", addr.additionalName() );
+ args.insert( "n_prefix", addr.prefix() );
+ args.insert( "n_suffix", addr.suffix() );
+// args.insert( "sound", "sound" );
+ args.insert( "bday", addr.birthday() );
+ args.insert( "note", addr.note() );
+ int hours = addr.timeZone().offset() / 60;
+ args.insert( "tz", hours );
+// args.insert( "geo", "geo" );
+ args.insert( "url", addr.url().url() );
+// args.insert( "pubkey", "pubkey" );
+ args.insert( "org_name", addr.organization() );
+// args.insert( "org_unit", "org_unit" );
+ args.insert( "title", addr.title() );
+
+ // CATEGORIES
+ QStringList::ConstIterator catIt;
+ const QStringList categories = addr.categories();
+
+ QMap<QString, QVariant> catMap;
+ int counter = 0;
+ for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
+ QMap<QString, int>::ConstIterator it = mCategoryMap.find( *catIt );
+ if ( it == mCategoryMap.end() ) // new category
+ catMap.insert( QString::number( counter-- ), *catIt );
+ else
+ catMap.insert( QString::number( it.data() ), *catIt );
+ }
+ args.insert( "cat_id", catMap );
+
+ Address workAddr = addr.address( Address::Work );
+ if ( !workAddr.isEmpty() ) {
+ args.insert( "adr_one_street", workAddr.street() );
+ args.insert( "adr_one_locality", workAddr.locality() );
+ args.insert( "adr_one_region", workAddr.region() );
+ args.insert( "adr_one_postalcode", workAddr.postalCode() );
+ args.insert( "adr_one_countryname", workAddr.country() );
+
+ args.insert( "adr_one_type", addrTypesToTypeStr( workAddr.type() ) );
+ args.insert( "label", workAddr.label() );
+ }
+
+ Address homeAddr = addr.address( Address::Home );
+ if ( !homeAddr.isEmpty() ) {
+ args.insert( "adr_two_street", homeAddr.street() );
+ args.insert( "adr_two_locality", homeAddr.locality() );
+ args.insert( "adr_two_region", homeAddr.region() );
+ args.insert( "adr_two_postalcode", homeAddr.postalCode() );
+ args.insert( "adr_two_countryname", homeAddr.country() );
+ args.insert( "adr_two_type", addrTypesToTypeStr( homeAddr.type() ) );
+ }
+
+ PhoneNumber phone = addr.phoneNumber( PhoneNumber::Work );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_work", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Home );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_home", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Voice );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_voice", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Fax );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_fax", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Msg );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_msg", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Cell );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_cell", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Pager );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_pager", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Bbs );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_bbs", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Modem );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_modem", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Car );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_car", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Isdn );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_isdn", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Video );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_video", phone.number() );
+
+ phone = addr.phoneNumber( PhoneNumber::Pref );
+ if ( !phone.number().isEmpty() )
+ args.insert( "tel_prefer", phone.number() );
+
+ if ( !addr.preferredEmail().isEmpty() ) {
+ args.insert( "email", addr.preferredEmail() );
+ args.insert( "email_type", "INTERNET" );
+ }
+
+ if ( addr.emails().count() > 1 ) {
+ args.insert( "email_home", addr.emails()[ 1 ] );
+ args.insert( "email_home_type", "INTERNET" );
+ }
+
+
+ const QStringList customFields = addr.customs();
+ QStringList::ConstIterator it;
+ for ( it = customFields.begin(); it != customFields.end(); ++it ) {
+ int colon = (*it).find( ":" );
+ QString identifier = (*it).left( colon );
+ int dash = identifier.find( "-" );
+ QString app = identifier.left( dash );
+ QString name = identifier.mid( dash + 1 );
+ QString value = (*it).mid( colon + 1 );
+ if ( value.isEmpty() )
+ continue;
+
+ if ( app == "XMLRPCResource" )
+ args.insert( name, value );
+ }
+
+ QString url = KCal::FreeBusyUrlStore::self()->readUrl( addr.preferredEmail() );
+ if ( !url.isEmpty() )
+ args.insert( "freebusy_url", url );
+}
+
+void ResourceXMLRPC::readContact( const QMap<QString, QVariant> &args, Addressee &addr, QString &uid )
+{
+ Address addrOne, addrTwo;
+
+ QMap<QString, QVariant>::ConstIterator it;
+ for ( it = args.begin(); it != args.end(); ++it ) {
+ if ( it.key() == "id" ) {
+ uid = it.data().toString();
+ } else if ( it.key() == "access" ) {
+ Secrecy secrecy;
+ if ( it.data().toString() == "private" )
+ secrecy.setType( Secrecy::Private );
+ else
+ secrecy.setType( Secrecy::Public );
+
+ addr.setSecrecy( secrecy );
+ } else if ( it.key() == "fn" ) {
+ addr.setFormattedName( it.data().toString() );
+ } else if ( it.key() == "n_given" ) {
+ addr.setGivenName( it.data().toString() );
+ } else if ( it.key() == "n_family" ) {
+ addr.setFamilyName( it.data().toString() );
+ } else if ( it.key() == "n_middle" ) {
+ addr.setAdditionalName( it.data().toString() );
+ } else if ( it.key() == "n_prefix" ) {
+ addr.setPrefix( it.data().toString() );
+ } else if ( it.key() == "n_suffix" ) {
+ addr.setSuffix( it.data().toString() );
+ } else if ( it.key() == "sound" ) {
+ } else if ( it.key() == "bday" ) {
+ addr.setBirthday( it.data().toDateTime() );
+ } else if ( it.key() == "note" ) {
+ addr.setNote( it.data().toString() );
+ } else if ( it.key() == "tz" ) {
+ int hour = it.data().toInt();
+ TimeZone timeZone( hour * 60 );
+ addr.setTimeZone( timeZone );
+ } else if ( it.key() == "geo" ) {
+ } else if ( it.key() == "url" ) {
+ addr.setUrl( KURL( it.data().toString() ) );
+ } else if ( it.key() == "pubkey" ) {
+ } else if ( it.key() == "org_name" ) {
+ addr.setOrganization( it.data().toString() );
+ } else if ( it.key() == "org_unit" ) {
+ } else if ( it.key() == "title" ) {
+ addr.setTitle( it.data().toString() );
+ } else if ( it.key() == "adr_one_street" ) {
+ addrOne.setStreet( it.data().toString() );
+ } else if ( it.key() == "adr_one_locality" ) {
+ addrOne.setLocality( it.data().toString() );
+ } else if ( it.key() == "adr_one_region" ) {
+ addrOne.setRegion( it.data().toString() );
+ } else if ( it.key() == "adr_one_postalcode" ) {
+ addrOne.setPostalCode( it.data().toString() );
+ } else if ( it.key() == "adr_one_countryname" ) {
+ addrOne.setCountry( it.data().toString() );
+ } else if ( it.key() == "adr_one_type" ) {
+ QStringList types = QStringList::split( ';', it.data().toString() );
+
+ int type = Address::Work;
+ for ( uint i = 0; i < types.count(); ++i )
+ type += mAddrTypes[ types[ i ] ];
+
+ addrOne.setType( type );
+ } else if ( it.key() == "label" ) {
+ addrOne.setLabel( it.data().toString() );
+ } else if ( it.key() == "adr_two_street" ) {
+ addrTwo.setStreet( it.data().toString() );
+ } else if ( it.key() == "adr_two_locality" ) {
+ addrTwo.setLocality( it.data().toString() );
+ } else if ( it.key() == "adr_two_region" ) {
+ addrTwo.setRegion( it.data().toString() );
+ } else if ( it.key() == "adr_two_postalcode" ) {
+ addrTwo.setPostalCode( it.data().toString() );
+ } else if ( it.key() == "adr_two_countryname" ) {
+ addrTwo.setCountry( it.data().toString() );
+ } else if ( it.key() == "adr_two_type" ) {
+ QStringList types = QStringList::split( ';', it.data().toString() );
+
+ int type = Address::Home;
+ for ( uint i = 0; i < types.count(); ++i )
+ type += mAddrTypes[ types[ i ] ];
+
+ addrTwo.setType( type );
+ } else if ( it.key() == "tel_work" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Work ) );
+ } else if ( it.key() == "tel_home" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Home ) );
+ } else if ( it.key() == "tel_voice" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Voice ) );
+ } else if ( it.key() == "tel_fax" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Fax ) );
+ } else if ( it.key() == "tel_msg" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Msg ) );
+ } else if ( it.key() == "tel_cell" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Cell ) );
+ } else if ( it.key() == "tel_pager" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Pager ) );
+ } else if ( it.key() == "tel_bbs" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Bbs ) );
+ } else if ( it.key() == "tel_modem" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Modem ) );
+ } else if ( it.key() == "tel_car" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Car ) );
+ } else if ( it.key() == "tel_isdn" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Isdn ) );
+ } else if ( it.key() == "tel_video" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Video ) );
+ } else if ( it.key() == "tel_prefer" ) {
+ addr.insertPhoneNumber( PhoneNumber( it.data().toString(), PhoneNumber::Pref ) );
+ } else if ( it.key() == "email" ) {
+ addr.insertEmail( it.data().toString(), true );
+ } else if ( it.key() == "email_type" ) {
+ } else if ( it.key() == "email_home" ) {
+ addr.insertEmail( it.data().toString(), false );
+ } else if ( it.key() == "email_home_type" ) {
+ } else if ( it.key() == "cat_id" ) {
+ const QMap<QString, QVariant> categories = it.data().toMap();
+ QMap<QString, QVariant>::ConstIterator it;
+
+ for ( it = categories.begin(); it != categories.end(); ++it )
+ addr.insertCategory( it.data().toString() );
+ } else if ( it.key() == "rights" ) {
+ setRights( addr, it.data().toInt() );
+ }
+ }
+
+ QMap<QString, QString>::ConstIterator cfIt;
+ for ( cfIt = mCustomFieldsMap.begin(); cfIt != mCustomFieldsMap.end(); ++cfIt ) {
+ if ( args[ cfIt.key() ].toString().isEmpty() )
+ continue;
+
+ if ( cfIt.key() == "freebusy_url" ) {
+ KCal::FreeBusyUrlStore::self()->writeUrl( addr.preferredEmail(),
+ args[ cfIt.key() ].toString() );
+ KCal::FreeBusyUrlStore::self()->sync();
+ } else
+ addr.insertCustom( "XMLRPCResource", cfIt.key(), cfIt.data() );
+ }
+
+ if ( !addrOne.isEmpty() )
+ addr.insertAddress( addrOne );
+ if ( !addrTwo.isEmpty() )
+ addr.insertAddress( addrTwo );
+}
+
+void ResourceXMLRPC::loadCategoriesFinished( const QValueList<QVariant> &mapList,
+ const QVariant& )
+{
+ mCategoryMap.clear();
+
+ const QMap<QString, QVariant> map = mapList[ 0 ].toMap();
+ QMap<QString, QVariant>::ConstIterator it;
+
+ KABPrefs *prefs = KABPrefs::instance();
+ for ( it = map.begin(); it != map.end(); ++it ) {
+ mCategoryMap.insert( it.data().toString(), it.key().toInt() );
+
+ QStringList categories = prefs->customCategories();
+ if ( categories.find( it.data().toString() ) == categories.end() )
+ categories.append( it.data().toString() );
+
+ prefs->mCustomCategories = categories;
+ }
+}
+
+void ResourceXMLRPC::loadCustomFieldsFinished( const QValueList<QVariant> &mapList,
+ const QVariant& )
+{
+ mCustomFieldsMap.clear();
+
+ const QMap<QString, QVariant> map = mapList[ 0 ].toMap();
+ QMap<QString, QVariant>::ConstIterator it;
+
+ for ( it = map.begin(); it != map.end(); ++it )
+ mCustomFieldsMap.insert( it.key(), it.data().toString() );
+}
+
+#include "kabc_resourcexmlrpc.moc"
diff --git a/kresources/egroupware/kabc_resourcexmlrpc.h b/kresources/egroupware/kabc_resourcexmlrpc.h
new file mode 100644
index 000000000..57bbd903a
--- /dev/null
+++ b/kresources/egroupware/kabc_resourcexmlrpc.h
@@ -0,0 +1,114 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KABC_RESOURCEXMLRPC_H
+#define KABC_RESOURCEXMLRPC_H
+
+#include <qmap.h>
+#include <kdepimmacros.h>
+
+#include "libkdepim/kabcresourcecached.h"
+
+class KConfig;
+class Synchronizer;
+
+namespace KXMLRPC {
+class Server;
+}
+
+namespace KABC {
+
+class EGroupwarePrefs;
+
+class KDE_EXPORT ResourceXMLRPC : public ResourceCached
+{
+ Q_OBJECT
+
+ public:
+ ResourceXMLRPC( const KConfig* );
+ ResourceXMLRPC( const QString &url, const QString &domain,
+ const QString &user, const QString &password );
+ ~ResourceXMLRPC();
+
+ virtual void writeConfig( KConfig* );
+
+ EGroupwarePrefs *prefs() const { return mPrefs; }
+
+ virtual bool doOpen();
+ virtual void doClose();
+
+ virtual Ticket *requestSaveTicket();
+ virtual void releaseSaveTicket( Ticket* );
+
+ virtual bool load();
+ virtual bool asyncLoad();
+ virtual bool save( Ticket * );
+ virtual bool asyncSave( Ticket * );
+
+ protected:
+ void init();
+
+ protected slots:
+ void loginFinished( const QValueList<QVariant>&, const QVariant& );
+ void logoutFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void listContactsFinished( const QValueList<QVariant>&, const QVariant& );
+ void addContactFinished( const QValueList<QVariant>&, const QVariant& );
+ void updateContactFinished( const QValueList<QVariant>&, const QVariant& );
+ void deleteContactFinished( const QValueList<QVariant>&, const QVariant& );
+ void loadCategoriesFinished( const QValueList<QVariant>&, const QVariant& );
+ void loadCustomFieldsFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void fault( int, const QString&, const QVariant& );
+ void addContactFault( int, const QString&, const QVariant& );
+ void updateContactFault( int, const QString&, const QVariant& );
+ void deleteContactFault( int, const QString&, const QVariant& );
+
+ void addContact( const KABC::Addressee& );
+ void updateContact( const KABC::Addressee& );
+ void deleteContact( const KABC::Addressee& );
+
+ private:
+ void initEGroupware();
+
+ QString addrTypesToTypeStr( int );
+
+ void writeContact( const Addressee&, QMap<QString, QVariant>& );
+ void readContact( const QMap<QString, QVariant>&, Addressee &addr, QString& );
+
+ EGroupwarePrefs *mPrefs;
+
+ QString mSessionID;
+ QString mKp3;
+
+ QMap<QString, int> mCategoryMap;
+ QMap<QString, int> mAddrTypes;
+ QMap<QString, QString> mCustomFieldsMap;
+
+ KXMLRPC::Server *mServer;
+ Synchronizer *mSynchronizer;
+
+ class ResourceXMLRPCPrivate;
+ ResourceXMLRPCPrivate *d;
+};
+
+}
+
+#endif
diff --git a/kresources/egroupware/kabc_resourcexmlrpcconfig.cpp b/kresources/egroupware/kabc_resourcexmlrpcconfig.cpp
new file mode 100644
index 000000000..cd2075c71
--- /dev/null
+++ b/kresources/egroupware/kabc_resourcexmlrpcconfig.cpp
@@ -0,0 +1,97 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2002 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+
+#include "kabc_egroupwareprefs.h"
+#include "kabc_resourcexmlrpc.h"
+#include "kabc_resourcexmlrpcconfig.h"
+
+using namespace KABC;
+
+ResourceXMLRPCConfig::ResourceXMLRPCConfig( QWidget* parent, const char* name )
+ : KRES::ConfigWidget( parent, name )
+{
+ QGridLayout *mainLayout = new QGridLayout( this, 4, 2, 0, KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "URL:" ), this );
+ mURL = new KURLRequester( this );
+
+ mainLayout->addWidget( label, 0, 0 );
+ mainLayout->addWidget( mURL, 0, 1 );
+
+ label = new QLabel( i18n( "Domain:" ), this );
+ mDomain = new KLineEdit( this );
+
+ mainLayout->addWidget( label, 1, 0 );
+ mainLayout->addWidget( mDomain, 1, 1 );
+
+ label = new QLabel( i18n( "User:" ), this );
+ mUser = new KLineEdit( this );
+
+ mainLayout->addWidget( label, 2, 0 );
+ mainLayout->addWidget( mUser, 2, 1 );
+
+ label = new QLabel( i18n( "Password:" ), this );
+ mPassword = new KLineEdit( this );
+ mPassword->setEchoMode( QLineEdit::Password );
+
+ mainLayout->addWidget( label, 3, 0 );
+ mainLayout->addWidget( mPassword, 3, 1 );
+}
+
+void ResourceXMLRPCConfig::loadSettings( KRES::Resource *res )
+{
+ ResourceXMLRPC *resource = dynamic_cast<ResourceXMLRPC*>( res );
+
+ if ( !resource ) {
+ kdDebug(5700) << "ResourceXMLRPCConfig::loadSettings(): cast failed" << endl;
+ return;
+ }
+
+ mURL->setURL( resource->prefs()->url() );
+ mDomain->setText( resource->prefs()->domain() );
+ mUser->setText( resource->prefs()->user() );
+ mPassword->setText( resource->prefs()->password() );
+}
+
+void ResourceXMLRPCConfig::saveSettings( KRES::Resource *res )
+{
+ ResourceXMLRPC *resource = dynamic_cast<ResourceXMLRPC*>( res );
+
+ if ( !resource ) {
+ kdDebug(5700) << "ResourceXMLRPCConfig::saveSettings(): cast failed" << endl;
+ return;
+ }
+
+ resource->prefs()->setUrl( mURL->url() );
+ resource->prefs()->setDomain( mDomain->text() );
+ resource->prefs()->setUser( mUser->text() );
+ resource->prefs()->setPassword( mPassword->text() );
+}
+
+#include "kabc_resourcexmlrpcconfig.moc"
diff --git a/kresources/egroupware/kabc_resourcexmlrpcconfig.h b/kresources/egroupware/kabc_resourcexmlrpcconfig.h
new file mode 100644
index 000000000..6e0ddfdb8
--- /dev/null
+++ b/kresources/egroupware/kabc_resourcexmlrpcconfig.h
@@ -0,0 +1,52 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2002 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RESOURCEXMLRPCCONFIG_H
+#define RESOURCEXMLRPCCONFIG_H
+
+#include <kresources/configwidget.h>
+#include <kdepimmacros.h>
+
+class KLineEdit;
+class KURLRequester;
+
+namespace KABC {
+
+class KDE_EXPORT ResourceXMLRPCConfig : public KRES::ConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ ResourceXMLRPCConfig( QWidget* parent = 0, const char* name = 0 );
+
+ public slots:
+ void loadSettings( KRES::Resource* );
+ void saveSettings( KRES::Resource* );
+
+ private:
+ KURLRequester *mURL;
+ KLineEdit *mDomain;
+ KLineEdit *mUser;
+ KLineEdit *mPassword;
+};
+
+}
+
+#endif
diff --git a/kresources/egroupware/kabc_resourcexmlrpcplugin.cpp b/kresources/egroupware/kabc_resourcexmlrpcplugin.cpp
new file mode 100644
index 000000000..9fd5611e6
--- /dev/null
+++ b/kresources/egroupware/kabc_resourcexmlrpcplugin.cpp
@@ -0,0 +1,40 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kabc_resourcexmlrpc.h"
+#include "kabc_resourcexmlrpcconfig.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+
+using namespace KABC;
+
+typedef KRES::PluginFactory< ResourceXMLRPC, ResourceXMLRPCConfig > XMLRPCFactory;
+
+// FIXME: Use K_EXPORT_COMPONENT_FACTORY( kabc_xmlrpc, XMLRPCFactory ); here
+// Problem: How to insert the catalogue!
+extern "C"
+{
+ void *init_kabc_xmlrpc()
+ {
+ KGlobal::locale()->insertCatalogue( "kres_xmlrpc" );
+ return new XMLRPCFactory;
+ }
+}
diff --git a/kresources/egroupware/kabc_xmlrpc.desktop b/kresources/egroupware/kabc_xmlrpc.desktop
new file mode 100644
index 000000000..c7386a593
--- /dev/null
+++ b/kresources/egroupware/kabc_xmlrpc.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=eGroupware Server (via XML-RPC)
+Name[af]=eGroupware Bediener (via XML-RPC)
+Name[bg]=Сървър eGroupware (чрез XML-RPC)
+Name[br]=Servijer eGroupware (gant XML-RPC)
+Name[ca]=Servidor eGroupware (via XML-RPC)
+Name[cs]=eGroupware Server (přes XML-RPC)
+Name[da]=eGroupware server (via XML-RPC)
+Name[el]=Εξυπηρετητής eGroupware (μέσω XML-RPC)
+Name[es]=Servidor de eGroupware (por medio de XML-RPC)
+Name[et]=eGroupware server (XML-RPC vahendusel)
+Name[eu]=eGroupware zerbitzaria (XML-RPC bidez)
+Name[fa]=کارساز eGroupware (از طریق XML-RPC)
+Name[fi]=eGroupware-palvelin (XML-RPC kautta)
+Name[fr]=Serveur eGroupware (via XML-RPC)
+Name[fy]=eGroupware-tsjinner (fia XML-RPC)
+Name[ga]=Freastalaí eGroupware (via XML-RPC)
+Name[gl]=Servidor eGroupware (mediante XML-RPC)
+Name[hu]=eGroupware-kiszolgáló (XML-RPC-n keresztül)
+Name[is]=eGroupware þjónn (gegnum XML-RPC)
+Name[it]=Server eGroupware (via XML-RPC)
+Name[ja]=eGroupware サーバ (XML-RPC 経由)
+Name[ka]=სერბერი eGroupware (XML-RPC-ის საშუალებით)
+Name[kk]=eGroupware сервері (XML-RPC арқылы)
+Name[km]=ម៉ាស៊ីន​បម្រើ eGroupware (តាម​រយៈ XML-RPC)
+Name[lt]=eGroupware serveris (per XML-RPC)
+Name[ms]=Pelayan eGroupware (melalui XML-RPC)
+Name[nb]=eGroupware-tjener (via XML-RPPC)
+Name[nds]=eGroupware-Server (över XML-RPC)
+Name[ne]=(XML-RPC मार्फत) eGroupware सर्भर
+Name[nl]=eGroupware-server (via XML-RPC)
+Name[nn]=eGroupware-tenar (via XML-RPC)
+Name[pl]=Serwer eGroupware (poprzez XML-RPC)
+Name[pt]=Servidor eGroupware (via XML-RPC)
+Name[pt_BR]=Servidor eGroupware (via XML-RPC)
+Name[ru]=Сервер eGroupware (через XML-RPC)
+Name[sk]=eGroupware Server (cez XML-RPC)
+Name[sl]=Strežnik eGroupware (preko XML-RPC)
+Name[sr]=eGroupware сервер (преко XML-RPC)
+Name[sr@Latn]=eGroupware server (preko XML-RPC)
+Name[sv]=eGroupware-server (via XML-RPC)
+Name[ta]=eGroupware சேவகன் (via XML-RPC)
+Name[tr]=eGroupware Sunucusu (XML-RPC ile)
+Name[uk]=Сервер eGroupware (через XML-RPC)
+Name[zh_CN]=eGroupware 服务器(通过 XML-RPC)
+Name[zh_TW]=eGroupware 伺服器(透過 XML-RPC)
+X-KDE-Library=kabc_xmlrpc
+Type=Service
+ServiceTypes=KResources/Plugin
+X-KDE-ResourceFamily=contact
+X-KDE-ResourceType=xmlrpc
diff --git a/kresources/egroupware/kcal_egroupwareprefs.kcfgc b/kresources/egroupware/kcal_egroupwareprefs.kcfgc
new file mode 100644
index 000000000..6a278752b
--- /dev/null
+++ b/kresources/egroupware/kcal_egroupwareprefs.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=kresources_kcal_egroupware.kcfg
+ClassName=EGroupwarePrefs
+NameSpace=KCal
+Singleton=false
+Mutators=true
+Inherits=KResourcePrefs
+IncludeFiles=libkdepim/kresourceprefs.h
+GlobalEnums=true
+#ItemAccessors=true
+#SetUserTexts=true
diff --git a/kresources/egroupware/kcal_resourcexmlrpc.cpp b/kresources/egroupware/kcal_resourcexmlrpc.cpp
new file mode 100644
index 000000000..af4f019c1
--- /dev/null
+++ b/kresources/egroupware/kcal_resourcexmlrpc.cpp
@@ -0,0 +1,1203 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+#include <typeinfo>
+
+#include <qapplication.h>
+#include <qdatetime.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+
+#include <kabc/locknull.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kresources/configwidget.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+#include <kurl.h>
+#include <libkdepim/kpimprefs.h>
+
+#include "libkcal/vcaldrag.h"
+#include "libkcal/vcalformat.h"
+#include "libkcal/icalformat.h"
+#include "libkcal/exceptions.h"
+#include "libkcal/incidence.h"
+#include "libkcal/event.h"
+#include "libkcal/todo.h"
+#include "libkcal/journal.h"
+#include "libkcal/filestorage.h"
+#include "libkcal/alarm.h"
+
+#include "kcal_egroupwareprefs.h"
+#include "kcal_resourcexmlrpcconfig.h"
+#include "kcal_resourcexmlrpc.h"
+
+#include "access.h"
+#include "synchronizer.h"
+#include "xmlrpciface.h"
+
+#define CAL_PRIO_LOW 1
+#define CAL_PRIO_NORMAL 2
+#define CAL_PRIO_HIGH 3
+
+#define CAL_RECUR_NONE 0
+#define CAL_RECUR_DAILY 1
+#define CAL_RECUR_WEEKLY 2
+#define CAL_RECUR_MONTHLY_MDAY 3
+#define CAL_RECUR_MONTHLY_WDAY 4
+#define CAL_RECUR_YEARLY 5
+#define CAL_SUNDAY 1
+#define CAL_MONDAY 2
+#define CAL_TUESDAY 4
+#define CAL_WEDNESDAY 8
+#define CAL_THURSDAY 16
+#define CAL_FRIDAY 32
+#define CAL_SATURDAY 64
+#define CAL_WEEKDAYS 62
+#define CAL_WEEKEND 65
+#define CAL_ALLDAYS 127
+
+using namespace KCal;
+
+typedef KRES::PluginFactory<ResourceXMLRPC, ResourceXMLRPCConfig> XMLRPCFactory;
+K_EXPORT_COMPONENT_FACTORY( kcal_xmlrpc, XMLRPCFactory )
+
+
+static const QString SearchEventsCommand = "calendar.bocalendar.search";
+static const QString AddEventCommand = "calendar.bocalendar.write";
+static const QString DeleteEventCommand = "calendar.bocalendar.delete";
+static const QString LoadEventCategoriesCommand = "calendar.bocalendar.categories";
+
+static const QString SearchTodosCommand = "infolog.boinfolog.search";
+static const QString AddTodoCommand = "infolog.boinfolog.write";
+static const QString DeleteTodoCommand = "infolog.boinfolog.delete";
+static const QString LoadTodoCategoriesCommand = "infolog.boinfolog.categories";
+
+static void setRights( Incidence *incidence, int rights )
+{
+ incidence->setCustomProperty( "EGWRESOURCE", "RIGHTS", QString::number( rights ) );
+}
+
+static int rights( Incidence *incidence )
+{
+ return incidence->customProperty( "EGWRESOURCE", "RIGHTS" ).toInt();
+}
+
+ResourceXMLRPC::ResourceXMLRPC( const KConfig* config )
+ : ResourceCached( config ), mServer( 0 ), mLock( 0 )
+{
+ init();
+
+ mPrefs->addGroupPrefix( identifier() );
+
+ if ( config )
+ readConfig( config );
+
+ initEGroupware();
+}
+
+ResourceXMLRPC::ResourceXMLRPC( )
+ : ResourceCached( 0 ), mServer( 0 ), mLock( 0 )
+{
+ init();
+
+ mPrefs->addGroupPrefix( identifier() );
+
+ initEGroupware();
+}
+
+ResourceXMLRPC::~ResourceXMLRPC()
+{
+ disableChangeNotification();
+
+ delete mServer;
+ mServer = 0;
+
+ delete mLock;
+ mLock = 0;
+
+ delete mPrefs;
+ mPrefs = 0;
+
+ delete mSynchronizer;
+ mSynchronizer = 0;
+}
+
+void ResourceXMLRPC::init()
+{
+ setType( "xmlrpc" );
+
+ mTodoStateMapper.setPath( "kcal/todostatemap/" );
+
+ mPrefs = new EGroupwarePrefs;
+ mLoaded = 0;
+
+ mLock = new KABC::LockNull( true );
+ mSynchronizer = new Synchronizer();
+}
+
+void ResourceXMLRPC::initEGroupware()
+{
+ KURL url( mPrefs->url() );
+}
+
+void ResourceXMLRPC::readConfig( const KConfig* config )
+{
+ mPrefs->readConfig();
+
+ ResourceCached::readConfig( config );
+}
+
+void ResourceXMLRPC::writeConfig( KConfig* config )
+{
+ ResourceCalendar::writeConfig( config );
+
+ mPrefs->writeConfig();
+
+ ResourceCached::writeConfig( config );
+}
+
+bool ResourceXMLRPC::doOpen()
+{
+ kdDebug(5800) << "ResourceXMLRPC::doOpen()" << endl;
+
+ if ( mServer )
+ delete mServer;
+
+ mServer = new KXMLRPC::Server( KURL(), this );
+ mServer->setUrl( KURL( mPrefs->url() ) );
+ mServer->setUserAgent( "KDE-Calendar" );
+
+ QMap<QString, QVariant> args;
+ args.insert( "domain", mPrefs->domain() );
+ args.insert( "username", mPrefs->user() );
+ args.insert( "password", mPrefs->password() );
+
+ mServer->call( "system.login", QVariant( args ),
+ this, SLOT( loginFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mSynchronizer->start();
+
+ return true;
+}
+
+void ResourceXMLRPC::doClose()
+{
+ kdDebug(5800) << "ResourceXMLRPC::doClose()" << endl;
+
+ QMap<QString, QVariant> args;
+ args.insert( "sessionid", mSessionID );
+ args.insert( "kp3", mKp3 );
+
+ mServer->call( "system.logout", QVariant( args ),
+ this, SLOT( logoutFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mSynchronizer->start();
+}
+
+bool ResourceXMLRPC::doLoad()
+{
+ kdDebug() << "ResourceXMLRPC::load()" << endl;
+
+ mCalendar.close();
+
+ disableChangeNotification();
+ loadCache();
+ enableChangeNotification();
+
+ emit resourceChanged( this );
+
+ clearChanges();
+
+ loadCache();
+ mTodoStateMapper.setIdentifier( type() + "_" + identifier() );
+ mTodoStateMapper.load();
+
+ QMap<QString, QVariant> args, columns;
+ args.insert( "start", QDateTime( QDate::currentDate().addDays( -12 ) ) );
+ args.insert( "end", QDateTime( QDate::currentDate().addDays( 2000 ) ) );
+
+ mServer->call( SearchEventsCommand, args,
+ this, SLOT( listEventsFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+ args.clear();
+
+ columns.insert( "type", "task" );
+ args.insert( "filter", "none" );
+ args.insert( "col_filter", columns );
+ args.insert( "order", "id_parent" );
+
+ mServer->call( SearchTodosCommand, args,
+ this, SLOT( listTodosFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mServer->call( LoadEventCategoriesCommand, QVariant( QMap<QString, QVariant>() ),
+ this, SLOT( loadEventCategoriesFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mServer->call( LoadTodoCategoriesCommand, QVariant( false, 0 ),
+ this, SLOT( loadTodoCategoriesFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+ return true;
+}
+
+bool ResourceXMLRPC::doSave()
+{
+ if ( readOnly() || !hasChanges() ) {
+ emit resourceSaved( this );
+ return true;
+ }
+
+ saveCache();
+
+ const Event::List events = mCalendar.rawEvents();
+ Event::List::ConstIterator evIt;
+
+ uint counter = 0;
+ for ( evIt = events.begin(); evIt != events.end(); ++evIt ) {
+ if ( !(*evIt)->isReadOnly() ) {
+ QMap<QString, QVariant> args;
+ writeEvent( (*evIt), args );
+
+ args.insert( "id", idMapper().remoteId( (*evIt)->uid() ).toInt() );
+ mServer->call( AddEventCommand, QVariant( args ),
+ this, SLOT( updateEventFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+ counter++;
+ }
+ }
+
+ const Todo::List todos = mCalendar.rawTodos();
+ Todo::List::ConstIterator todoIt;
+
+ for ( todoIt = todos.begin(); todoIt != todos.end(); ++todoIt ) {
+ if ( !(*todoIt)->isReadOnly() ) {
+ QMap<QString, QVariant> args;
+ writeTodo( (*todoIt), args );
+
+ args.insert( "id", idMapper().remoteId( (*todoIt)->uid() ).toInt() );
+ mServer->call( AddTodoCommand, QVariant( args ),
+ this, SLOT( updateTodoFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+ counter++;
+ }
+ }
+
+ if ( counter != 0 )
+ mSynchronizer->start();
+
+ mTodoStateMapper.save();
+
+ return true;
+}
+
+bool ResourceXMLRPC::isSaving()
+{
+ return false;
+}
+
+KABC::Lock *ResourceXMLRPC::lock()
+{
+ return mLock;
+}
+
+
+bool ResourceXMLRPC::addEvent( Event* ev )
+{
+ QMap<QString, QVariant> args;
+
+ disableChangeNotification();
+
+ setRights( ev, EGW_ACCESS_ALL );
+ Event *oldEvent = mCalendar.event( ev->uid() );
+ if ( oldEvent ) { // already exists
+ if ( !oldEvent->isReadOnly() ) {
+ writeEvent( ev, args );
+ args.insert( "id", idMapper().remoteId( ev->uid() ).toInt() );
+ mServer->call( AddEventCommand, QVariant( args ),
+ this, SLOT( updateEventFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mCalendar.deleteIncidence( oldEvent );
+ mCalendar.addIncidence( ev );
+ saveCache();
+ }
+ } else { // new event
+ writeEvent( ev, args );
+ mServer->call( AddEventCommand, QVariant( args ),
+ this, SLOT( addEventFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ),
+ QVariant( ev->uid() ) );
+
+ mCalendar.addEvent( ev );
+ saveCache();
+ }
+
+ enableChangeNotification();
+
+ return true;
+}
+
+bool ResourceXMLRPC::deleteEvent( Event* ev )
+{
+ if ( !(rights( ev ) & EGW_ACCESS_DELETE) && rights( ev ) != -1 )
+ return false;
+
+ mServer->call( DeleteEventCommand, idMapper().remoteId( ev->uid() ).toInt(),
+ this, SLOT( deleteEventFinished( const QValueList<QVariant>&,
+ const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ),
+ QVariant( ev->uid() ) );
+ return true;
+}
+
+
+Event *ResourceXMLRPC::event( const QString& uid )
+{
+ return mCalendar.event( uid );
+}
+
+Event::List ResourceXMLRPC::rawEventsForDate( const QDate& qd,
+ EventSortField sortField,
+ SortDirection sortDirection )
+{
+ return mCalendar.rawEventsForDate( qd, sortField, sortDirection );
+}
+
+
+Event::List ResourceXMLRPC::rawEvents( const QDate& start, const QDate& end,
+ bool inclusive )
+{
+ return mCalendar.rawEvents( start, end, inclusive );
+}
+
+Event::List ResourceXMLRPC::rawEventsForDate( const QDateTime& qdt )
+{
+ return mCalendar.rawEventsForDate( qdt.date() );
+}
+
+Event::List ResourceXMLRPC::rawEvents()
+{
+ return mCalendar.rawEvents();
+}
+
+
+bool ResourceXMLRPC::addTodo( Todo *todo )
+{
+ QMap<QString, QVariant> args;
+
+ disableChangeNotification();
+
+ setRights( todo, EGW_ACCESS_ALL );
+ Todo *oldTodo = mCalendar.todo( todo->uid() );
+ if ( oldTodo ) { // already exists
+ if ( !oldTodo->isReadOnly() ) {
+ writeTodo( todo, args );
+ args.insert( "id", idMapper().remoteId( todo->uid() ).toInt() );
+ mServer->call( AddTodoCommand, QVariant( args ),
+ this, SLOT( updateTodoFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mCalendar.deleteIncidence( oldTodo );
+ mCalendar.addIncidence( todo );
+ saveCache();
+ }
+ } else { // new todo
+ writeTodo( todo, args );
+ mServer->call( AddTodoCommand, QVariant( args ),
+ this, SLOT( addTodoFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ),
+ QVariant( todo->uid() ) );
+
+ mCalendar.addTodo( todo );
+ saveCache();
+ }
+
+ enableChangeNotification();
+
+ return true;
+}
+
+bool ResourceXMLRPC::deleteTodo( Todo *todo )
+{
+ if ( !(rights( todo ) & EGW_ACCESS_DELETE) && rights( todo ) != -1 )
+ return false;
+
+ mServer->call( DeleteTodoCommand, idMapper().remoteId( todo->uid() ).toInt(),
+ this, SLOT( deleteTodoFinished( const QValueList<QVariant>&,
+ const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ),
+ QVariant( todo->uid() ) );
+ return true;
+}
+
+Todo::List ResourceXMLRPC::rawTodos()
+{
+ return mCalendar.rawTodos();
+}
+
+Todo *ResourceXMLRPC::todo( const QString& uid )
+{
+ return mCalendar.todo( uid );
+}
+
+Todo::List ResourceXMLRPC::rawTodosForDate( const QDate& date )
+{
+ return mCalendar.rawTodosForDate( date );
+}
+
+bool ResourceXMLRPC::addJournal( Journal* journal )
+{
+ return mCalendar.addJournal( journal );
+}
+
+bool ResourceXMLRPC::deleteJournal( Journal* journal )
+{
+ return mCalendar.deleteJournal( journal );
+}
+
+Journal::List ResourceXMLRPC::journals( const QDate& date )
+{
+ return mCalendar.journals( date );
+}
+
+Journal *ResourceXMLRPC::journal( const QString& uid )
+{
+ return mCalendar.journal( uid );
+}
+
+
+Alarm::List ResourceXMLRPC::alarmsTo( const QDateTime& to )
+{
+ return mCalendar.alarmsTo( to );
+}
+
+Alarm::List ResourceXMLRPC::alarms( const QDateTime& from, const QDateTime& to )
+{
+ return mCalendar.alarms( from, to );
+}
+
+void ResourceXMLRPC::dump() const
+{
+ ResourceCalendar::dump();
+}
+
+void ResourceXMLRPC::reload()
+{
+ load();
+}
+
+
+void ResourceXMLRPC::loginFinished( const QValueList<QVariant>& variant,
+ const QVariant& )
+{
+ QMap<QString, QVariant> map = variant[ 0 ].toMap();
+
+ KURL url = KURL( mPrefs->url() );
+ if ( map[ "GOAWAY" ].toString() == "XOXO" ) { // failed
+ mSessionID = mKp3 = "";
+ } else {
+ mSessionID = map[ "sessionid" ].toString();
+ mKp3 = map[ "kp3" ].toString();
+ }
+
+ url.setUser( mSessionID );
+ url.setPass( mKp3 );
+ mServer->setUrl( url );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::logoutFinished( const QValueList<QVariant>& variant,
+ const QVariant& )
+{
+ QMap<QString, QVariant> map = variant[ 0 ].toMap();
+
+ if ( map[ "GOODBYE" ].toString() != "XOXO" )
+ kdError() << "logout failed" << endl;
+
+ KURL url = KURL( mPrefs->url() );
+ mSessionID = mKp3 = "";
+ url.setUser( mSessionID );
+ url.setPass( mKp3 );
+ mServer->setUrl( url );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::listEventsFinished( const QValueList<QVariant>& list,
+ const QVariant& )
+{
+ const QValueList<QVariant> eventList = list[ 0 ].toList();
+ QValueList<QVariant>::ConstIterator eventIt;
+
+ disableChangeNotification();
+
+ Event::List retrievedEvents;
+
+ bool changed = false;
+ for ( eventIt = eventList.begin(); eventIt != eventList.end(); ++eventIt ) {
+ QMap<QString, QVariant> map = (*eventIt).toMap();
+
+ Event *event = new Event;
+ event->setFloats( false );
+
+ QString uid;
+ readEvent( map, event, uid );
+
+ // do we already have this event?
+ Event *oldEvent = 0;
+ QString localUid = idMapper().localId( uid );
+ if ( !localUid.isEmpty() )
+ oldEvent = mCalendar.event( localUid );
+
+ if ( oldEvent ) {
+ event->setUid( oldEvent->uid() );
+ event->setCreated( oldEvent->created() );
+
+ if ( !(*oldEvent == *event) ) {
+ mCalendar.deleteEvent( oldEvent );
+ mCalendar.addEvent( event );
+ retrievedEvents.append( event );
+ changed = true;
+ } else
+ delete event;
+ } else {
+ if ( !localUid.isEmpty() )
+ event->setUid( localUid );
+ idMapper().setRemoteId( event->uid(), uid );
+ mCalendar.addEvent( event );
+ retrievedEvents.append( event );
+ changed = true;
+ }
+ }
+
+ enableChangeNotification();
+
+ clearChanges();
+
+
+ if ( changed ) {
+ cleanUpEventCache( retrievedEvents );
+ saveCache();
+ emit resourceChanged( this );
+ }
+
+ checkLoadingFinished();
+}
+
+void ResourceXMLRPC::deleteEventFinished( const QValueList<QVariant>&,
+ const QVariant& id )
+{
+ idMapper().removeRemoteId( idMapper().remoteId( id.toString() ) );
+
+ Event *ev = mCalendar.event( id.toString() );
+
+ disableChangeNotification();
+ mCalendar.deleteEvent( ev );
+ saveCache();
+ enableChangeNotification();
+
+ emit resourceChanged( this );
+}
+
+void ResourceXMLRPC::updateEventFinished( const QValueList<QVariant>&,
+ const QVariant& )
+{
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::addEventFinished( const QValueList<QVariant>& list,
+ const QVariant& id )
+{
+ idMapper().setRemoteId( id.toString(), list[ 0 ].toString() );
+
+ emit resourceChanged( this );
+}
+
+void ResourceXMLRPC::loadEventCategoriesFinished( const QValueList<QVariant> &mapList, const QVariant& )
+{
+ mEventCategoryMap.clear();
+
+ const QMap<QString, QVariant> map = mapList[ 0 ].toMap();
+ QMap<QString, QVariant>::ConstIterator it;
+
+ KPimPrefs prefs( "korganizerrc" );
+ for ( it = map.begin(); it != map.end(); ++it ) {
+ mEventCategoryMap.insert( it.data().toString(), it.key().toInt() );
+
+ if ( prefs.mCustomCategories.find( it.data().toString() ) == prefs.mCustomCategories.end() )
+ prefs.mCustomCategories.append( it.data().toString() );
+ }
+
+ prefs.usrWriteConfig();
+ prefs.config()->sync();
+
+ checkLoadingFinished();
+}
+
+void ResourceXMLRPC::listTodosFinished( const QValueList<QVariant>& list,
+ const QVariant& )
+{
+ const QValueList<QVariant> todoList = list[ 0 ].toList();
+ QValueList<QVariant>::ConstIterator todoIt;
+
+ disableChangeNotification();
+
+ Todo::List retrievedTodos;
+
+ bool changed = false;
+ for ( todoIt = todoList.begin(); todoIt != todoList.end(); ++todoIt ) {
+ QMap<QString, QVariant> map = (*todoIt).toMap();
+
+ Todo *todo = new Todo;
+
+ QString uid;
+ readTodo( map, todo, uid );
+
+ // do we already have this todo?
+ Todo *oldTodo = 0;
+ QString localUid = idMapper().localId( uid );
+ if ( !localUid.isEmpty() )
+ oldTodo = mCalendar.todo( localUid );
+
+ if ( oldTodo ) {
+ todo->setUid( oldTodo->uid() );
+ todo->setCreated( oldTodo->created() );
+
+ if ( !(*oldTodo == *todo) ) {
+ mCalendar.deleteTodo( oldTodo );
+ mCalendar.addTodo( todo );
+ retrievedTodos.append( todo );
+ changed = true;
+ } else
+ delete todo;
+ } else {
+ idMapper().setRemoteId( todo->uid(), uid );
+ mCalendar.addTodo( todo );
+ retrievedTodos.append( todo );
+ changed = true;
+ }
+ }
+
+ enableChangeNotification();
+
+ if ( changed ) {
+ cleanUpTodoCache( retrievedTodos );
+ saveCache();
+ emit resourceChanged( this );
+ }
+
+ checkLoadingFinished();
+}
+
+void ResourceXMLRPC::deleteTodoFinished( const QValueList<QVariant>&,
+ const QVariant& id )
+{
+ idMapper().removeRemoteId( idMapper().remoteId( id.toString() ) );
+ mTodoStateMapper.remove( idMapper().remoteId( id.toString() ) );
+
+ Todo *todo = mCalendar.todo( id.toString() );
+ disableChangeNotification();
+ mCalendar.deleteTodo( todo );
+ saveCache();
+ enableChangeNotification();
+
+ emit resourceChanged( this );
+}
+
+void ResourceXMLRPC::addTodoFinished( const QValueList<QVariant>& list,
+ const QVariant& id )
+{
+ idMapper().setRemoteId( id.toString(), list[ 0 ].toString() );
+
+ emit resourceChanged( this );
+}
+
+void ResourceXMLRPC::updateTodoFinished( const QValueList<QVariant>&,
+ const QVariant& )
+{
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::loadTodoCategoriesFinished( const QValueList<QVariant> &mapList, const QVariant& )
+{
+ mTodoCategoryMap.clear();
+
+ const QMap<QString, QVariant> map = mapList[ 0 ].toMap();
+ QMap<QString, QVariant>::ConstIterator it;
+
+ KPimPrefs prefs( "korganizerrc" );
+ for ( it = map.begin(); it != map.end(); ++it ) {
+ mTodoCategoryMap.insert( it.data().toString(), it.key().toInt() );
+
+ if ( prefs.mCustomCategories.find( it.data().toString() ) == prefs.mCustomCategories.end() )
+ prefs.mCustomCategories.append( it.data().toString() );
+ }
+
+ prefs.usrWriteConfig();
+ prefs.config()->sync();
+
+ checkLoadingFinished();
+}
+
+void ResourceXMLRPC::fault( int error, const QString& errorMsg,
+ const QVariant& )
+{
+ kdError() << "Server send error " << error << ": " << errorMsg << endl;
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::readEvent( const QMap<QString, QVariant> &args, Event *event,
+ QString &uid )
+{
+ // for recurrence
+ int rType = CAL_RECUR_NONE;
+ int rInterval = 1;
+ int rData = 0;
+ int rights = 0;
+ QDateTime rEndDate;
+ QValueList<QDateTime> rExceptions;
+
+ QMap<QString, QVariant>::ConstIterator it;
+ for ( it = args.begin(); it != args.end(); ++it ) {
+ if ( it.key() == "id" ) {
+ uid = it.data().toString();
+ } else if ( it.key() == "rights" ) {
+ rights = it.data().toInt();
+ } else if ( it.key() == "start" ) {
+ event->setDtStart( it.data().toDateTime() );
+ } else if ( it.key() == "end" ) {
+ QDateTime start = args[ "start" ].toDateTime();
+ QDateTime end = it.data().toDateTime();
+ if ( start.time() == end.time() &&
+ start.time().hour() == 0 && start.time().minute() == 0 &&
+ start.time().second() == 0 ) {
+ event->setDtEnd( end.addDays( -1 ) );
+ event->setFloats( true );
+ } else {
+ event->setDtEnd( end );
+ event->setHasEndDate( true );
+ }
+ } else if ( it.key() == "modtime" ) {
+ event->setLastModified( it.data().toDateTime() );
+ } else if ( it.key() == "title" ) {
+ event->setSummary( it.data().toString() );
+ } else if ( it.key() == "description" ) {
+ event->setDescription( it.data().toString() );
+ } else if ( it.key() == "location" ) {
+ event->setLocation( it.data().toString() );
+ } else if ( it.key() == "access" ) {
+ event->setSecrecy( (it.data().toString() == "public" ?
+ Incidence::SecrecyPublic : Incidence::SecrecyPrivate) );
+ } else if ( it.key() == "category" ) {
+ const QMap<QString, QVariant> categories = it.data().toMap();
+ QMap<QString, QVariant>::ConstIterator catIt;
+
+ QStringList eventCategories;
+ for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
+ mEventCategoryMap.insert( catIt.data().toString(), catIt.key().toInt() );
+ eventCategories.append( catIt.data().toString() );
+ }
+
+ event->setCategories( eventCategories );
+ } else if ( it.key() == "priority" ) {
+ int priority = 0;
+
+ switch( it.data().toInt() ) {
+ case CAL_PRIO_LOW:
+ priority = 10;
+ break;
+ case CAL_PRIO_NORMAL:
+ priority = 5;
+ break;
+ case CAL_PRIO_HIGH:
+ priority = 1;
+ }
+
+ event->setPriority( priority );
+ } else if ( it.key() == "recur_type" ) {
+ rType = it.data().toInt();
+ } else if ( it.key() == "recur_interval" ) {
+ rInterval = it.data().toInt();
+ } else if ( it.key() == "recur_enddate" ) {
+ rEndDate = it.data().toDateTime();
+ } else if ( it.key() == "recur_data" ) {
+ rData = it.data().toInt();
+ } else if ( it.key() == "recur_exception" ) {
+ const QMap<QString, QVariant> dateList = it.data().toMap();
+ QMap<QString, QVariant>::ConstIterator dateIt;
+
+ for ( dateIt = dateList.begin(); dateIt != dateList.end(); ++dateIt )
+ rExceptions.append( (*dateIt).toDateTime() );
+ } else if ( it.key() == "participants" ) {
+ const QMap<QString, QVariant> persons = it.data().toMap();
+ QMap<QString, QVariant>::ConstIterator personsIt;
+
+ for ( personsIt = persons.begin(); personsIt != persons.end(); ++personsIt ) {
+ QMap<QString, QVariant> person = (*personsIt).toMap();
+ Attendee::PartStat status = Attendee::InProcess;
+ if ( person[ "status" ] == "A" )
+ status = Attendee::Accepted;
+ else if ( person[ "status" ] == "R" )
+ status = Attendee::Declined;
+ else if ( person[ "status" ] == "T" )
+ status = Attendee::Tentative;
+ else if ( person[ "status" ] == "N" )
+ status = Attendee::InProcess;
+
+ Attendee *attendee = new Attendee( person[ "name" ].toString(),
+ person[ "email" ].toString(),
+ false, status );
+ attendee->setUid( personsIt.key() );
+ event->addAttendee( attendee );
+ }
+ } else if ( it.key() == "alarm" ) {
+ const QMap<QString, QVariant> alarmList = it.data().toMap();
+ QMap<QString, QVariant>::ConstIterator alarmIt;
+
+ for ( alarmIt = alarmList.begin(); alarmIt != alarmList.end(); ++alarmIt ) {
+ QMap<QString, QVariant> alarm = (*alarmIt).toMap();
+
+ Alarm *vAlarm = event->newAlarm();
+ vAlarm->setText( event->summary() );
+ vAlarm->setTime( alarm[ "time" ].toDateTime() );
+ vAlarm->setStartOffset( alarm[ "offset" ].toInt() );
+ vAlarm->setEnabled( alarm[ "enabled" ].toBool() );
+ }
+ }
+ }
+
+ if ( rType != CAL_RECUR_NONE && rInterval > 0 ) {
+ Recurrence *re = event->recurrence();
+// re->setRecurStart( event->dtStart() );
+
+
+ if ( rInterval == 0 ) // libkcal crashes with rInterval == 0
+ rInterval = 1;
+
+ switch ( rType ) {
+ case CAL_RECUR_DAILY:
+ re->setDaily( rInterval );
+ break;
+ case CAL_RECUR_WEEKLY: {
+ QBitArray weekMask( 7 );
+ weekMask.setBit( 0, rData & CAL_MONDAY );
+ weekMask.setBit( 1, rData & CAL_TUESDAY );
+ weekMask.setBit( 2, rData & CAL_WEDNESDAY );
+ weekMask.setBit( 3, rData & CAL_THURSDAY );
+ weekMask.setBit( 4, rData & CAL_FRIDAY );
+ weekMask.setBit( 5, rData & CAL_SATURDAY );
+ weekMask.setBit( 6, rData & CAL_SUNDAY );
+
+ re->setWeekly( rInterval, weekMask );
+ break; }
+ case CAL_RECUR_MONTHLY_MDAY:
+ re->setMonthly( rInterval );
+ break;
+ case CAL_RECUR_MONTHLY_WDAY:
+ re->setMonthly( rInterval );
+ // TODO: Set the correct monthly pos
+ break;
+ case CAL_RECUR_YEARLY:
+ re->setYearly( rInterval );
+ break;
+ }
+ if ( rEndDate.date().isValid() )
+ re->setEndDate( rEndDate.date() );
+
+ QValueList<QDateTime>::ConstIterator exIt;
+ for ( exIt = rExceptions.begin(); exIt != rExceptions.end(); ++exIt )
+ re->addExDateTime( *exIt );
+ }
+
+ event->setReadOnly( !(rights & EGW_ACCESS_EDIT) );
+ setRights( event, rights );
+}
+
+void ResourceXMLRPC::writeEvent( Event *event, QMap<QString, QVariant> &args )
+{
+ args.insert( "start", event->dtStart() );
+
+ // handle all day events
+ if ( event->doesFloat() )
+ args.insert( "end", event->dtEnd().addDays( 1 ) );
+ else
+ args.insert( "end", event->dtEnd() );
+
+ args.insert( "modtime", event->lastModified() );
+ args.insert( "title", event->summary() );
+ args.insert( "description", event->description() );
+ args.insert( "location", event->location() );
+
+ // SECRECY
+ args.insert( "access", (event->secrecy() == Incidence::SecrecyPublic ? "public" : "private") );
+
+ // CATEGORY
+ const QStringList categories = event->categories();
+ QStringList::ConstIterator catIt;
+ QMap<QString, QVariant> catMap;
+ int counter = 0;
+ for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
+ QMap<QString, int>::Iterator it = mEventCategoryMap.find( *catIt );
+ if ( it == mEventCategoryMap.end() ) // new category
+ catMap.insert( QString::number( counter-- ), *catIt );
+ else
+ catMap.insert( QString::number( it.data() ), *catIt );
+ }
+ args.insert( "category", catMap );
+
+ // PRIORITY
+ int priority = 0;
+ if ( event->priority() == 1 )
+ priority = CAL_PRIO_HIGH;
+ else if ( event->priority() > 1 && event->priority() <= 5 )
+ priority = CAL_PRIO_NORMAL;
+ else
+ priority = CAL_PRIO_LOW;
+
+ args.insert( "priority", priority );
+
+ // RECURRENCE
+ Recurrence *rec = event->recurrence();
+ if ( !rec->doesRecur() ) {
+ args.insert( "recur_type", int( 0 ) );
+ args.insert( "recur_interval", int( 0 ) );
+ args.insert( "recur_enddate", QDateTime() );
+ args.insert( "recur_data", int( 0 ) );
+ args.insert( "recur_exception", QMap<QString, QVariant>() );
+ } else {
+ switch ( rec->recurrenceType() ) {
+ case Recurrence::rDaily:
+ args.insert( "recur_type", int( CAL_RECUR_DAILY ) );
+ break;
+ case Recurrence::rWeekly: {
+ int weekMask = 0;
+ if ( rec->days().testBit( 0 ) )
+ weekMask += CAL_MONDAY;
+ if ( rec->days().testBit( 1 ) )
+ weekMask += CAL_TUESDAY;
+ if ( rec->days().testBit( 2 ) )
+ weekMask += CAL_WEDNESDAY;
+ if ( rec->days().testBit( 3 ) )
+ weekMask += CAL_THURSDAY;
+ if ( rec->days().testBit( 4 ) )
+ weekMask += CAL_FRIDAY;
+ if ( rec->days().testBit( 5 ) )
+ weekMask += CAL_SATURDAY;
+ if ( rec->days().testBit( 6 ) )
+ weekMask += CAL_SUNDAY;
+
+ args.insert( "recur_data", weekMask );
+ args.insert( "recur_type", int( CAL_RECUR_WEEKLY ) );
+ }
+ break;
+ case Recurrence::rMonthlyPos:
+ args.insert( "recur_type", int( CAL_RECUR_MONTHLY_MDAY ) );
+ break;
+ case Recurrence::rMonthlyDay:
+ args.insert( "recur_type", int( CAL_RECUR_MONTHLY_WDAY ) );
+ break;
+ case Recurrence::rYearlyDay:
+ args.insert( "recur_type", int( CAL_RECUR_YEARLY ) );
+ break;
+ default:
+ break;
+ }
+
+ args.insert( "recur_interval", rec->frequency() );
+ args.insert( "recur_enddate", rec->endDateTime() );
+
+ // TODO: Also use exception dates!
+ const QValueList<QDateTime> dates = event->recurrence()->exDateTimes();
+ QValueList<QDateTime>::ConstIterator dateIt;
+ QMap<QString, QVariant> exMap;
+ int counter = 0;
+ for ( dateIt = dates.begin(); dateIt != dates.end(); ++dateIt, ++counter )
+ exMap.insert( QString::number( counter ), *dateIt );
+
+ args.insert( "recur_exception", exMap );
+ }
+
+ // PARTICIPANTS
+ const Attendee::List attendees = event->attendees();
+ Attendee::List::ConstIterator attIt;
+ QMap<QString, QVariant> persons;
+ for ( attIt = attendees.begin(); attIt != attendees.end(); ++attIt ) {
+ QMap<QString, QVariant> person;
+ QString status;
+
+ if ( (*attIt)->status() == Attendee::Accepted )
+ status = "A";
+ else if ( (*attIt)->status() == Attendee::Declined )
+ status = "R";
+ else if ( (*attIt)->status() == Attendee::Tentative )
+ status = "T";
+ else
+ status = "N";
+
+ person.insert( "status", status );
+ person.insert( "name", (*attIt)->name() );
+ person.insert( "email", (*attIt)->email() );
+
+ persons.insert( (*attIt)->uid(), person );
+ }
+ args.insert( "participants", persons );
+
+ // ALARMS
+ const Alarm::List alarms = event->alarms();
+ Alarm::List::ConstIterator alarmIt;
+ QMap<QString, QVariant> alarmMap;
+ for ( alarmIt = alarms.begin(); alarmIt != alarms.end(); ++alarmIt ) {
+ QMap<QString, QVariant> alarm;
+ alarm.insert( "time", (*alarmIt)->time() );
+ alarm.insert( "offset", (*alarmIt)->startOffset().asSeconds() );
+ alarm.insert( "enabled", ( (*alarmIt)->enabled() ? int( 1 ) : int( 0 ) ) );
+
+ alarmMap.insert( "id", alarm ); // that sucks...
+ }
+
+ args.insert( "alarm", alarmMap );
+}
+
+void ResourceXMLRPC::writeTodo( Todo* todo, QMap<QString, QVariant>& args )
+{
+ args.insert( "subject", todo->summary() );
+ args.insert( "des", todo->description() );
+ args.insert( "access",
+ (todo->secrecy() == Todo::SecrecyPublic ? "public" : "private" ) );
+
+ // CATEGORIES
+ QMap<QString, QVariant> catMap;
+
+ const QStringList categories = todo->categories();
+ QStringList::ConstIterator catIt;
+ int counter = 0;
+ for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
+ QMap<QString, int>::Iterator it = mTodoCategoryMap.find( *catIt );
+ if ( it == mTodoCategoryMap.end() )
+ catMap.insert( QString::number( counter-- ), *catIt );
+ else
+ catMap.insert( QString::number( it.data() ), *catIt );
+ }
+ args.insert( "category", catMap );
+
+ args.insert( "datemodified", todo->lastModified() );
+ args.insert( "startdate", todo->dtStart() );
+ args.insert( "enddate", todo->dtDue() );
+
+ // SUBTODO
+ Incidence *inc = todo->relatedTo();
+ if ( inc ) {
+ QString parentUid = idMapper().remoteId( inc->uid() );
+ args.insert( "id_parent", parentUid );
+ }
+
+ // STATE
+ QString remoteId = idMapper().remoteId( todo->uid() );
+ QString status = mTodoStateMapper.remoteState( remoteId, todo->percentComplete() );
+ args.insert( "status", status );
+}
+
+void ResourceXMLRPC::readTodo( const QMap<QString, QVariant>& args, Todo *todo, QString &uid )
+{
+ uid = args[ "id" ].toString();
+
+/*
+ info_from
+ info_addr
+ info_owner
+ info_responsible
+ info_modifier
+*/
+
+ todo->setSummary( args[ "subject" ].toString() );
+ todo->setDescription( args[ "des" ].toString() );
+ todo->setSecrecy( args[ "access" ].toString() == "public" ? Todo::SecrecyPublic : Todo::SecrecyPrivate );
+
+ // CATEGORIES
+ const QMap<QString, QVariant> categories = args[ "category" ].toMap();
+ QMap<QString, QVariant>::ConstIterator it;
+
+ QStringList todoCategories;
+ for ( it = categories.begin(); it != categories.end(); ++it ) {
+ mTodoCategoryMap.insert( it.data().toString(), it.key().toInt() );
+ todoCategories.append( it.data().toString() );
+ }
+
+ todo->setCategories( todoCategories );
+
+ todo->setLastModified( args[ "datemodified" ].toDateTime() );
+
+ todo->setFloats( true );
+ QDateTime dateTime = args[ "startdate" ].toDateTime();
+ if ( dateTime.isValid() ) {
+ todo->setDtStart( dateTime );
+ todo->setHasStartDate( true );
+ if ( !dateTime.time().isNull() )
+ todo->setFloats( false );
+ }
+
+ dateTime = args[ "enddate" ].toDateTime();
+ if ( dateTime.isValid() ) {
+ todo->setDtDue( dateTime );
+ todo->setHasDueDate( true );
+ if ( !dateTime.time().isNull() )
+ todo->setFloats( false );
+ }
+
+ // SUBTODO
+ QString parentId = args[ "id_parent" ].toString();
+ if ( parentId != "0" ) { // we are a sub todo
+ QString localParentUid = idMapper().localId( parentId );
+ if ( !localParentUid.isEmpty() ) { // found parent todo
+ Todo *parent = mCalendar.todo( localParentUid );
+ if ( parent )
+ todo->setRelatedTo( parent );
+ }
+ }
+
+ // STATE
+ QString status = args[ "status" ].toString();
+ int state = TodoStateMapper::toLocal( status );
+
+ mTodoStateMapper.addTodoState( uid, state, status );
+ todo->setPercentComplete( state );
+
+ int rights = args[ "rights" ].toInt();
+ todo->setReadOnly( !(rights & EGW_ACCESS_EDIT) );
+ setRights( todo, rights );
+}
+
+void ResourceXMLRPC::checkLoadingFinished()
+{
+ mLoaded++;
+ if ( mLoaded == 4 ) {
+ mLoaded = 0;
+ emit resourceLoaded( this );
+ }
+}
+
+#include "kcal_resourcexmlrpc.moc"
diff --git a/kresources/egroupware/kcal_resourcexmlrpc.h b/kresources/egroupware/kcal_resourcexmlrpc.h
new file mode 100644
index 000000000..fd9ad6826
--- /dev/null
+++ b/kresources/egroupware/kcal_resourcexmlrpc.h
@@ -0,0 +1,236 @@
+ /*
+ This file is part of kdepim.
+
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCAL_RESOURCEXMLRPC_H
+#define KCAL_RESOURCEXMLRPC_H
+
+#include <qdatetime.h>
+#include <qptrlist.h>
+#include <qstring.h>
+
+#include <kconfig.h>
+#include <kurl.h>
+
+#include <kdepimmacros.h>
+
+#include "libkcal/calendarlocal.h"
+#include "libkcal/incidence.h"
+#include "libkcal/resourcecached.h"
+#include "todostatemapper.h"
+
+namespace KXMLRPC {
+class Server;
+}
+
+class Synchronizer;
+class QTimer;
+
+namespace KCal {
+
+class EGroupwarePrefs;
+
+/**
+ This class provides access to php/eGroupware calendar via XML-RPC.
+*/
+class KDE_EXPORT ResourceXMLRPC : public ResourceCached
+{
+ Q_OBJECT
+
+ public:
+ ResourceXMLRPC( const KConfig* );
+ ResourceXMLRPC();
+ virtual ~ResourceXMLRPC();
+
+ void readConfig( const KConfig* config );
+ void writeConfig( KConfig* config );
+
+ EGroupwarePrefs *prefs() const { return mPrefs; }
+
+ bool isSaving();
+
+ KABC::Lock *lock();
+
+ /**
+ Add Event to calendar.
+ */
+ bool addEvent( Event* event );
+
+ /**
+ Deletes an event from this calendar.
+ */
+ bool deleteEvent( Event* );
+
+ /**
+ Retrieves an event on the basis of the unique string ID.
+ */
+ Event *event( const QString& uid );
+
+ /**
+ Return unfiltered list of all events in calendar.
+ */
+ Event::List rawEvents();
+
+ /**
+ Builds and then returns a list of all events that match for the
+ date specified. useful for dayView, etc. etc.
+ */
+ Event::List rawEventsForDate(
+ const QDate& date,
+ EventSortField sortField=EventSortUnsorted,
+ SortDirection sortDirection=SortDirectionAscending );
+
+ /**
+ Get unfiltered events for date \a qdt.
+ */
+ Event::List rawEventsForDate( const QDateTime& qdt );
+
+ /**
+ Get unfiltered events in a range of dates. If inclusive is set to true,
+ only events are returned, which are completely included in the range.
+ */
+ Event::List rawEvents( const QDate& start, const QDate& end,
+ bool inclusive = false );
+
+
+ /**
+ Add a todo to the todolist.
+ */
+ bool addTodo( Todo* todo );
+
+ /**
+ Remove a todo from the todolist.
+ */
+ bool deleteTodo( Todo* todo );
+
+ /**
+ Searches todolist for an event with this unique string identifier,
+ returns a pointer or null.
+ */
+ Todo *todo( const QString& uid );
+
+ /**
+ Return list of all todos.
+ */
+ Todo::List rawTodos();
+
+ /**
+ Returns list of todos due on the specified date.
+ */
+ Todo::List rawTodosForDate( const QDate& date );
+
+ /**
+ Add a Journal entry to calendar
+ */
+ virtual bool addJournal( Journal* journal );
+
+ /**
+ Remove journal from the calendar.
+ */
+ bool deleteJournal( Journal* journal );
+
+ /**
+ Return Journals for given date
+ */
+ virtual Journal::List journals( const QDate& );
+
+ /**
+ Return Journal with given UID
+ */
+ virtual Journal *journal( const QString& uid );
+
+ /**
+ Return all alarms, which ocur in the given time interval.
+ */
+ Alarm::List alarms( const QDateTime& from, const QDateTime& to );
+
+ /**
+ Return all alarms, which ocur before given date.
+ */
+ Alarm::List alarmsTo( const QDateTime& to );
+
+ /**
+ Public because needed in MultiCalendar::load()
+ */
+ bool doOpen();
+ void doClose();
+
+ void dump() const;
+
+ void setTimeZoneId( const QString& ) {}
+
+ protected slots:
+ void loginFinished( const QValueList<QVariant>&, const QVariant& );
+ void logoutFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void listEventsFinished( const QValueList<QVariant>&, const QVariant& );
+ void addEventFinished( const QValueList<QVariant>&, const QVariant& );
+ void updateEventFinished( const QValueList<QVariant>&, const QVariant& );
+ void deleteEventFinished( const QValueList<QVariant>&, const QVariant& );
+ void loadEventCategoriesFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void listTodosFinished( const QValueList<QVariant>&, const QVariant& );
+ void addTodoFinished( const QValueList<QVariant>&, const QVariant& );
+ void updateTodoFinished( const QValueList<QVariant>&, const QVariant& );
+ void deleteTodoFinished( const QValueList<QVariant>&, const QVariant& );
+ void loadTodoCategoriesFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void fault( int, const QString&, const QVariant& );
+
+ protected:
+ bool doLoad();
+ bool doSave();
+
+ private slots:
+ void reload();
+
+ private:
+ void init();
+ void initEGroupware();
+
+ void writeEvent( Event*, QMap<QString, QVariant>& );
+ void readEvent( const QMap<QString, QVariant>&, Event*, QString& );
+
+ void writeTodo( Todo*, QMap<QString, QVariant>& );
+ void readTodo( const QMap<QString, QVariant>&, Todo*, QString& );
+
+ void checkLoadingFinished();
+
+ KXMLRPC::Server *mServer;
+
+ EGroupwarePrefs *mPrefs;
+
+ QString mSessionID;
+ QString mKp3;
+
+ QMap<QString, int> mEventCategoryMap;
+ QMap<QString, int> mTodoCategoryMap;
+
+ TodoStateMapper mTodoStateMapper;
+
+ Synchronizer *mSynchronizer;
+
+ KABC::Lock *mLock;
+ int mLoaded;
+};
+
+}
+
+#endif
diff --git a/kresources/egroupware/kcal_resourcexmlrpcconfig.cpp b/kresources/egroupware/kcal_resourcexmlrpcconfig.cpp
new file mode 100644
index 000000000..450519aa4
--- /dev/null
+++ b/kresources/egroupware/kcal_resourcexmlrpcconfig.cpp
@@ -0,0 +1,98 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kurlrequester.h>
+
+#include "kcal_egroupwareprefs.h"
+#include "kcal_resourcexmlrpc.h"
+#include "kcal_resourcexmlrpcconfig.h"
+
+using namespace KCal;
+
+ResourceXMLRPCConfig::ResourceXMLRPCConfig( QWidget* parent, const char* name )
+ : KRES::ConfigWidget( parent, name )
+{
+ QGridLayout *mainLayout = new QGridLayout( this, 4, 2, 0, KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "URL:" ), this );
+ mURL = new KURLRequester( this );
+
+ mainLayout->addWidget( label, 0, 0 );
+ mainLayout->addWidget( mURL, 0, 1 );
+
+ label = new QLabel( i18n( "Domain:" ), this );
+ mDomain = new KLineEdit( this );
+
+ mainLayout->addWidget( label, 1, 0 );
+ mainLayout->addWidget( mDomain, 1, 1 );
+
+ label = new QLabel( i18n( "User:" ), this );
+ mUser = new KLineEdit( this );
+
+ mainLayout->addWidget( label, 2, 0 );
+ mainLayout->addWidget( mUser, 2, 1 );
+
+ label = new QLabel( i18n( "Password:" ), this );
+ mPassword = new KLineEdit( this );
+ mPassword->setEchoMode( QLineEdit::Password );
+
+ mainLayout->addWidget( label, 3, 0 );
+ mainLayout->addWidget( mPassword, 3, 1 );
+}
+
+void ResourceXMLRPCConfig::loadSettings( KRES::Resource *res )
+{
+ ResourceXMLRPC *resource = dynamic_cast<ResourceXMLRPC*>( res );
+
+ if ( !resource ) {
+ kdDebug(5700) << "ResourceXMLRPCConfig::loadSettings(): cast failed" << endl;
+ return;
+ }
+
+ mURL->setURL( resource->prefs()->url() );
+ mDomain->setText( resource->prefs()->domain() );
+ mUser->setText( resource->prefs()->user() );
+ mPassword->setText( resource->prefs()->password() );
+}
+
+void ResourceXMLRPCConfig::saveSettings( KRES::Resource *res )
+{
+ ResourceXMLRPC *resource = dynamic_cast<ResourceXMLRPC*>( res );
+
+ if ( !resource ) {
+ kdDebug(5700) << "ResourceXMLRPCConfig::saveSettings(): cast failed" << endl;
+ return;
+ }
+
+ resource->prefs()->setUrl( mURL->url() );
+ resource->prefs()->setDomain( mDomain->text() );
+ resource->prefs()->setUser( mUser->text() );
+ resource->prefs()->setPassword( mPassword->text() );
+}
+
+#include "kcal_resourcexmlrpcconfig.moc"
diff --git a/kresources/egroupware/kcal_resourcexmlrpcconfig.h b/kresources/egroupware/kcal_resourcexmlrpcconfig.h
new file mode 100644
index 000000000..c6a918f84
--- /dev/null
+++ b/kresources/egroupware/kcal_resourcexmlrpcconfig.h
@@ -0,0 +1,53 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RESOURCEXMLRPCCONFIG_H
+#define RESOURCEXMLRPCCONFIG_H
+
+#include <kresources/configwidget.h>
+#include <kdepimmacros.h>
+
+class KIntSpinBox;
+class KLineEdit;
+class KURLRequester;
+
+namespace KCal {
+
+class KDE_EXPORT ResourceXMLRPCConfig : public KRES::ConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ ResourceXMLRPCConfig( QWidget* parent = 0, const char* name = 0 );
+
+ public slots:
+ void loadSettings( KRES::Resource* );
+ void saveSettings( KRES::Resource* );
+
+ private:
+ KURLRequester *mURL;
+ KLineEdit *mDomain;
+ KLineEdit *mUser;
+ KLineEdit *mPassword;
+};
+
+}
+
+#endif
diff --git a/kresources/egroupware/kcal_resourcexmlrpcplugin.cpp b/kresources/egroupware/kcal_resourcexmlrpcplugin.cpp
new file mode 100644
index 000000000..1cc867b62
--- /dev/null
+++ b/kresources/egroupware/kcal_resourcexmlrpcplugin.cpp
@@ -0,0 +1,40 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kcal_resourcexmlrpc.h"
+#include "kcal_resourcexmlrpcconfig.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+
+using namespace KCal;
+
+typedef KRES::PluginFactory<ResourceXMLRPC, ResourceXMLRPCConfig> XMLRPCFactory;
+
+// FIXME: Use K_EXPORT_COMPONENT_FACTORY( kcal_xmlrpc, XMLRPCFactory ); here
+// Problem: How to insert the catalogue!
+extern "C"
+{
+ void *init_kcal_xmlrpc()
+ {
+ KGlobal::locale()->insertCatalogue( "kres_xmlrpc" );
+ return new XMLRPCFactory;
+ }
+}
diff --git a/kresources/egroupware/kcal_xmlrpc.desktop b/kresources/egroupware/kcal_xmlrpc.desktop
new file mode 100644
index 000000000..5480d86b6
--- /dev/null
+++ b/kresources/egroupware/kcal_xmlrpc.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=eGroupware Server (via XML-RPC)
+Name[af]=eGroupware Bediener (via XML-RPC)
+Name[bg]=Сървър eGroupware (чрез XML-RPC)
+Name[br]=Servijer eGroupware (gant XML-RPC)
+Name[ca]=Servidor eGroupware (via XML-RPC)
+Name[cs]=eGroupware Server (přes XML-RPC)
+Name[da]=eGroupware server (via XML-RPC)
+Name[el]=Εξυπηρετητής eGroupware (μέσω XML-RPC)
+Name[es]=Servidor de eGroupware (por medio de XML-RPC)
+Name[et]=eGroupware server (XML-RPC vahendusel)
+Name[eu]=eGroupware zerbitzaria (XML-RPC bidez)
+Name[fa]=کارساز eGroupware (از طریق XML-RPC)
+Name[fi]=eGroupware-palvelin (XML-RPC kautta)
+Name[fr]=Serveur eGroupware (via XML-RPC)
+Name[fy]=eGroupware-tsjinner (fia XML-RPC)
+Name[ga]=Freastalaí eGroupware (via XML-RPC)
+Name[gl]=Servidor eGroupware (mediante XML-RPC)
+Name[hu]=eGroupware-kiszolgáló (XML-RPC-n keresztül)
+Name[is]=eGroupware þjónn (gegnum XML-RPC)
+Name[it]=Server eGroupware (via XML-RPC)
+Name[ja]=eGroupware サーバ (XML-RPC 経由)
+Name[ka]=სერბერი eGroupware (XML-RPC-ის საშუალებით)
+Name[kk]=eGroupware сервері (XML-RPC арқылы)
+Name[km]=ម៉ាស៊ីន​បម្រើ eGroupware (តាម​រយៈ XML-RPC)
+Name[lt]=eGroupware serveris (per XML-RPC)
+Name[ms]=Pelayan eGroupware (melalui XML-RPC)
+Name[nb]=eGroupware-tjener (via XML-RPPC)
+Name[nds]=eGroupware-Server (över XML-RPC)
+Name[ne]=(XML-RPC मार्फत) eGroupware सर्भर
+Name[nl]=eGroupware-server (via XML-RPC)
+Name[nn]=eGroupware-tenar (via XML-RPC)
+Name[pl]=Serwer eGroupware (poprzez XML-RPC)
+Name[pt]=Servidor eGroupware (via XML-RPC)
+Name[pt_BR]=Servidor eGroupware (via XML-RPC)
+Name[ru]=Сервер eGroupware (через XML-RPC)
+Name[sk]=eGroupware Server (cez XML-RPC)
+Name[sl]=Strežnik eGroupware (preko XML-RPC)
+Name[sr]=eGroupware сервер (преко XML-RPC)
+Name[sr@Latn]=eGroupware server (preko XML-RPC)
+Name[sv]=eGroupware-server (via XML-RPC)
+Name[ta]=eGroupware சேவகன் (via XML-RPC)
+Name[tr]=eGroupware Sunucusu (XML-RPC ile)
+Name[uk]=Сервер eGroupware (через XML-RPC)
+Name[zh_CN]=eGroupware 服务器(通过 XML-RPC)
+Name[zh_TW]=eGroupware 伺服器(透過 XML-RPC)
+X-KDE-Library=kcal_xmlrpc
+Type=Service
+ServiceTypes=KResources/Plugin
+X-KDE-ResourceFamily=calendar
+X-KDE-ResourceType=xmlrpc
diff --git a/kresources/egroupware/knotes_egroupwareprefs.kcfgc b/kresources/egroupware/knotes_egroupwareprefs.kcfgc
new file mode 100644
index 000000000..782dd5673
--- /dev/null
+++ b/kresources/egroupware/knotes_egroupwareprefs.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=kresources_knotes_egroupware.kcfg
+ClassName=EGroupwarePrefs
+NameSpace=KNotes
+Singleton=false
+Mutators=true
+Inherits=KResourcePrefs
+IncludeFiles=libkdepim/kresourceprefs.h
+GlobalEnums=true
+#ItemAccessors=true
+#SetUserTexts=true
diff --git a/kresources/egroupware/knotes_resourcexmlrpc.cpp b/kresources/egroupware/knotes_resourcexmlrpc.cpp
new file mode 100644
index 000000000..c30da41f0
--- /dev/null
+++ b/kresources/egroupware/knotes_resourcexmlrpc.cpp
@@ -0,0 +1,333 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qapplication.h>
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+#include <kurl.h>
+
+#include "libkcal/journal.h"
+
+#include "knotes/resourcemanager.h"
+
+#include "knotes_egroupwareprefs.h"
+#include "knotes_resourcexmlrpc.h"
+#include "knotes_resourcexmlrpcconfig.h"
+
+#include "synchronizer.h"
+#include "xmlrpciface.h"
+
+using namespace KNotes;
+
+typedef KRES::PluginFactory< ResourceXMLRPC, ResourceXMLRPCConfig> XMLRPCFactory;
+K_EXPORT_COMPONENT_FACTORY( knotes_xmlrpc, XMLRPCFactory )
+
+static const QString SearchNotesCommand = "infolog.boinfolog.search";
+static const QString AddNoteCommand = "infolog.boinfolog.write";
+static const QString DeleteNoteCommand = "infolog.boinfolog.delete";
+static const QString LoadNoteCategoriesCommand = "infolog.boinfolog.categories";
+
+ResourceXMLRPC::ResourceXMLRPC( const KConfig* config )
+ : ResourceNotes( config ), mCalendar( QString::fromLatin1("UTC") ),
+ mServer( 0 )
+{
+ init();
+
+ mPrefs->addGroupPrefix( identifier() );
+
+ if ( config )
+ readConfig( config );
+}
+
+ResourceXMLRPC::ResourceXMLRPC( )
+ : ResourceNotes( 0 ), mCalendar( QString::fromLatin1("UTC") ),
+ mServer( 0 )
+{
+ init();
+
+ mPrefs->addGroupPrefix( identifier() );
+}
+
+ResourceXMLRPC::~ResourceXMLRPC()
+{
+ delete mServer;
+ mServer = 0;
+
+ delete mPrefs;
+ mPrefs = 0;
+
+ delete mSynchronizer;
+ mSynchronizer = 0;
+}
+
+void ResourceXMLRPC::init()
+{
+ setType( "xmlrpc" );
+
+ mPrefs = new EGroupwarePrefs;
+
+ mSynchronizer = new Synchronizer;
+}
+
+void ResourceXMLRPC::readConfig( const KConfig* )
+{
+ mPrefs->readConfig();
+}
+
+void ResourceXMLRPC::writeConfig( KConfig* config )
+{
+ ResourceNotes::writeConfig( config );
+
+ mPrefs->writeConfig();
+}
+
+bool ResourceXMLRPC::load()
+{
+ mCalendar.close();
+
+ if ( mServer )
+ delete mServer;
+
+ mServer = new KXMLRPC::Server( KURL(), this );
+ mServer->setUrl( KURL( mPrefs->url() ) );
+ mServer->setUserAgent( "KDE-Notes" );
+
+ QMap<QString, QVariant> args, columns;
+ args.insert( "domain", mPrefs->domain() );
+ args.insert( "username", mPrefs->user() );
+ args.insert( "password", mPrefs->password() );
+
+ mServer->call( "system.login", QVariant( args ),
+ this, SLOT( loginFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mSynchronizer->start();
+
+ columns.insert( "type", "note" );
+ args.clear();
+ args.insert( "filter", "none" );
+ args.insert( "col_filter", columns );
+ args.insert( "order", "id_parent" );
+
+ mServer->call( SearchNotesCommand, args,
+ this, SLOT( listNotesFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+
+ mSynchronizer->start();
+
+ return true;
+}
+
+bool ResourceXMLRPC::save()
+{
+ mCalendar.close();
+
+ return true;
+}
+
+bool ResourceXMLRPC::addNote( KCal::Journal *journal )
+{
+ QMap<QString, QVariant> args;
+ writeNote( journal, args );
+
+ KCal::Journal *oldJournal = mCalendar.journal( journal->uid() );
+
+ bool added = false;
+ if ( oldJournal ) {
+ if ( !oldJournal->isReadOnly() ) {
+ writeNote( journal, args );
+ args.insert( "id", mUidMap[ journal->uid() ].toInt() );
+ mServer->call( AddNoteCommand, QVariant( args ),
+ this, SLOT( updateNoteFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ) );
+ mCalendar.addJournal( journal );
+ added = true;
+ }
+ } else {
+ mServer->call( AddNoteCommand, QVariant( args ),
+ this, SLOT( addNoteFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ),
+ QVariant( journal->uid() ) );
+
+ mCalendar.addJournal( journal );
+ added = true;
+ }
+
+ if ( added )
+ mSynchronizer->start();
+
+ return true;
+}
+
+bool ResourceXMLRPC::deleteNote( KCal::Journal *journal )
+{
+ int id = mUidMap[ journal->uid() ].toInt();
+
+ mServer->call( DeleteNoteCommand, id,
+ this, SLOT( deleteNoteFinished( const QValueList<QVariant>&, const QVariant& ) ),
+ this, SLOT( fault( int, const QString&, const QVariant& ) ),
+ QVariant( journal->uid() ) );
+ mSynchronizer->start();
+
+ return true;
+}
+
+KCal::Alarm::List ResourceXMLRPC::alarms( const QDateTime& from, const QDateTime& to )
+{
+ KCal::Alarm::List alarms;
+ KCal::Journal::List notes = mCalendar.journals();
+ KCal::Journal::List::ConstIterator note;
+ for ( note = notes.begin(); note != notes.end(); ++note )
+ {
+ QDateTime preTime = from.addSecs( -1 );
+ KCal::Alarm::List::ConstIterator it;
+ for( it = (*note)->alarms().begin(); it != (*note)->alarms().end(); ++it )
+ {
+ if ( (*it)->enabled() )
+ {
+ QDateTime dt = (*it)->nextRepetition( preTime );
+ if ( dt.isValid() && dt <= to )
+ alarms.append( *it );
+ }
+ }
+ }
+
+ return alarms;
+}
+
+void ResourceXMLRPC::loginFinished( const QValueList<QVariant>& variant,
+ const QVariant& )
+{
+ QMap<QString, QVariant> map = variant[ 0 ].toMap();
+
+ KURL url = KURL( mPrefs->url() );
+ if ( map[ "GOAWAY" ].toString() == "XOXO" ) { // failed
+ mSessionID = mKp3 = "";
+ } else {
+ mSessionID = map[ "sessionid" ].toString();
+ mKp3 = map[ "kp3" ].toString();
+ }
+
+ url.setUser( mSessionID );
+ url.setPass( mKp3 );
+ mServer->setUrl( url );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::logoutFinished( const QValueList<QVariant>& variant,
+ const QVariant& )
+{
+ QMap<QString, QVariant> map = variant[ 0 ].toMap();
+
+ if ( map[ "GOODBYE" ].toString() != "XOXO" )
+ kdError() << "logout failed" << endl;
+
+ KURL url = KURL( mPrefs->url() );
+ mSessionID = mKp3 = "";
+ url.setUser( mSessionID );
+ url.setPass( mKp3 );
+ mServer->setUrl( url );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::listNotesFinished( const QValueList<QVariant> &list, const QVariant& )
+{
+ QMap<QString, QString>::Iterator uidIt;
+ for ( uidIt = mUidMap.begin(); uidIt != mUidMap.end(); ++uidIt ) {
+ KCal::Journal *journal = mCalendar.journal( uidIt.key() );
+ mCalendar.deleteJournal( journal );
+ }
+
+ mUidMap.clear();
+
+ QValueList<QVariant> noteList = list[ 0 ].toList();
+ QValueList<QVariant>::Iterator noteIt;
+
+ for ( noteIt = noteList.begin(); noteIt != noteList.end(); ++noteIt ) {
+ QMap<QString, QVariant> map = (*noteIt).toMap();
+
+ KCal::Journal *journal = new KCal::Journal();
+
+ QString uid;
+ readNote( map, journal, uid );
+ mUidMap.insert( journal->uid(), uid );
+
+ mCalendar.addJournal( journal );
+ manager()->registerNote( this, journal );
+ }
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::addNoteFinished( const QValueList<QVariant> &list, const QVariant &id )
+{
+ int uid = list[ 0 ].toInt();
+ mUidMap.insert( id.toString(), QString::number( uid ) );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::updateNoteFinished( const QValueList<QVariant>&, const QVariant& )
+{
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::deleteNoteFinished( const QValueList<QVariant>&, const QVariant &id )
+{
+ mUidMap.erase( id.toString() );
+
+ KCal::Journal *journal = mCalendar.journal( id.toString() );
+ mCalendar.deleteJournal( journal );
+
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::fault( int error, const QString& errorMsg, const QVariant& )
+{
+ kdError() << "Server send error " << error << ": " << errorMsg << endl;
+ mSynchronizer->stop();
+}
+
+void ResourceXMLRPC::writeNote( KCal::Journal* journal, QMap<QString, QVariant>& args )
+{
+ args.insert( "subject", journal->summary() );
+ args.insert( "des", journal->description() );
+ args.insert( "access",
+ (journal->secrecy() == KCal::Journal::SecrecyPublic ? "public" : "private" ) );
+}
+
+void ResourceXMLRPC::readNote( const QMap<QString, QVariant>& args, KCal::Journal *journal, QString &uid )
+{
+ uid = args[ "id" ].toString();
+
+ journal->setSummary( args[ "subject" ].toString() );
+ journal->setDescription( args[ "des" ].toString() );
+ journal->setSecrecy( args[ "access" ].toString() == "public" ?
+ KCal::Journal::SecrecyPublic : KCal::Journal::SecrecyPrivate );
+}
+
+#include "knotes_resourcexmlrpc.moc"
diff --git a/kresources/egroupware/knotes_resourcexmlrpc.h b/kresources/egroupware/knotes_resourcexmlrpc.h
new file mode 100644
index 000000000..2f2934320
--- /dev/null
+++ b/kresources/egroupware/knotes_resourcexmlrpc.h
@@ -0,0 +1,103 @@
+ /*
+ This file is part of kdepim.
+
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KNOTES_RESOURCEXMLRPC_H
+#define KNOTES_RESOURCEXMLRPC_H
+
+#include <qptrlist.h>
+#include <qstring.h>
+
+#include <kconfig.h>
+#include <kurl.h>
+#include <kdepimmacros.h>
+
+#include "libkcal/calendarlocal.h"
+#include "libkcal/journal.h"
+#include "knotes/resourcenotes.h"
+
+namespace KXMLRPC {
+class Server;
+}
+
+class Synchronizer;
+
+namespace KNotes {
+
+class EGroupwarePrefs;
+
+/**
+ This class provides access to eGroupware notes via XML-RPC.
+*/
+class KDE_EXPORT ResourceXMLRPC : public ResourceNotes
+{
+ Q_OBJECT
+
+ public:
+ ResourceXMLRPC( const KConfig* );
+ ResourceXMLRPC();
+ virtual ~ResourceXMLRPC();
+
+ void readConfig( const KConfig* config );
+ void writeConfig( KConfig* config );
+
+ EGroupwarePrefs *prefs() const { return mPrefs; }
+
+ bool load();
+ bool save();
+
+ bool addNote( KCal::Journal* );
+ bool deleteNote( KCal::Journal* );
+
+ KCal::Alarm::List alarms( const QDateTime& from, const QDateTime& to );
+
+ protected slots:
+ void loginFinished( const QValueList<QVariant>&, const QVariant& );
+ void logoutFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void listNotesFinished( const QValueList<QVariant>&, const QVariant& );
+ void addNoteFinished( const QValueList<QVariant>&, const QVariant& );
+ void updateNoteFinished( const QValueList<QVariant>&, const QVariant& );
+ void deleteNoteFinished( const QValueList<QVariant>&, const QVariant& );
+
+ void fault( int, const QString&, const QVariant& );
+
+ private:
+ void init();
+ void initEGroupware();
+
+ void writeNote( KCal::Journal*, QMap<QString, QVariant>& );
+ void readNote( const QMap<QString, QVariant>&, KCal::Journal*, QString& );
+
+ KCal::CalendarLocal mCalendar;
+ KXMLRPC::Server *mServer;
+
+ EGroupwarePrefs *mPrefs;
+
+ QString mSessionID;
+ QString mKp3;
+ QMap<QString, QString> mUidMap;
+
+ Synchronizer *mSynchronizer;
+};
+
+}
+
+#endif
diff --git a/kresources/egroupware/knotes_resourcexmlrpcconfig.cpp b/kresources/egroupware/knotes_resourcexmlrpcconfig.cpp
new file mode 100644
index 000000000..6eee548ce
--- /dev/null
+++ b/kresources/egroupware/knotes_resourcexmlrpcconfig.cpp
@@ -0,0 +1,98 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kurlrequester.h>
+
+#include "knotes_egroupwareprefs.h"
+#include "knotes_resourcexmlrpc.h"
+#include "knotes_resourcexmlrpcconfig.h"
+
+using namespace KNotes;
+
+ResourceXMLRPCConfig::ResourceXMLRPCConfig( QWidget* parent, const char* name )
+ : KRES::ConfigWidget( parent, name )
+{
+ QGridLayout *mainLayout = new QGridLayout( this, 4, 2, 0, KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "URL:" ), this );
+ mURL = new KURLRequester( this );
+
+ mainLayout->addWidget( label, 0, 0 );
+ mainLayout->addWidget( mURL, 0, 1 );
+
+ label = new QLabel( i18n( "Domain:" ), this );
+ mDomain = new KLineEdit( this );
+
+ mainLayout->addWidget( label, 1, 0 );
+ mainLayout->addWidget( mDomain, 1, 1 );
+
+ label = new QLabel( i18n( "User:" ), this );
+ mUser = new KLineEdit( this );
+
+ mainLayout->addWidget( label, 2, 0 );
+ mainLayout->addWidget( mUser, 2, 1 );
+
+ label = new QLabel( i18n( "Password:" ), this );
+ mPassword = new KLineEdit( this );
+ mPassword->setEchoMode( QLineEdit::Password );
+
+ mainLayout->addWidget( label, 3, 0 );
+ mainLayout->addWidget( mPassword, 3, 1 );
+}
+
+void ResourceXMLRPCConfig::loadSettings( KRES::Resource *res )
+{
+ ResourceXMLRPC *resource = dynamic_cast<ResourceXMLRPC*>( res );
+
+ if ( !resource ) {
+ kdDebug(5700) << "ResourceXMLRPCConfig::loadSettings(): cast failed" << endl;
+ return;
+ }
+
+ mURL->setURL( resource->prefs()->url() );
+ mDomain->setText( resource->prefs()->domain() );
+ mUser->setText( resource->prefs()->user() );
+ mPassword->setText( resource->prefs()->password() );
+}
+
+void ResourceXMLRPCConfig::saveSettings( KRES::Resource *res )
+{
+ ResourceXMLRPC *resource = dynamic_cast<ResourceXMLRPC*>( res );
+
+ if ( !resource ) {
+ kdDebug(5700) << "ResourceXMLRPCConfig::saveSettings(): cast failed" << endl;
+ return;
+ }
+
+ resource->prefs()->setUrl( mURL->url() );
+ resource->prefs()->setDomain( mDomain->text() );
+ resource->prefs()->setUser( mUser->text() );
+ resource->prefs()->setPassword( mPassword->text() );
+}
+
+#include "knotes_resourcexmlrpcconfig.moc"
diff --git a/kresources/egroupware/knotes_resourcexmlrpcconfig.h b/kresources/egroupware/knotes_resourcexmlrpcconfig.h
new file mode 100644
index 000000000..7b3edab2e
--- /dev/null
+++ b/kresources/egroupware/knotes_resourcexmlrpcconfig.h
@@ -0,0 +1,53 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RESOURCEXMLRPCCONFIG_H
+#define RESOURCEXMLRPCCONFIG_H
+
+#include <kresources/configwidget.h>
+#include <kdepimmacros.h>
+
+class KIntSpinBox;
+class KLineEdit;
+class KURLRequester;
+
+namespace KNotes {
+
+class KDE_EXPORT ResourceXMLRPCConfig : public KRES::ConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ ResourceXMLRPCConfig( QWidget* parent = 0, const char* name = 0 );
+
+ public slots:
+ void loadSettings( KRES::Resource* );
+ void saveSettings( KRES::Resource* );
+
+ private:
+ KURLRequester *mURL;
+ KLineEdit *mDomain;
+ KLineEdit *mUser;
+ KLineEdit *mPassword;
+};
+
+}
+
+#endif
diff --git a/kresources/egroupware/knotes_resourcexmlrpcplugin.cpp b/kresources/egroupware/knotes_resourcexmlrpcplugin.cpp
new file mode 100644
index 000000000..b3b6aabe3
--- /dev/null
+++ b/kresources/egroupware/knotes_resourcexmlrpcplugin.cpp
@@ -0,0 +1,40 @@
+/*
+ This file is part of kdepim.
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "knotes_resourcexmlrpc.h"
+#include "knotes_resourcexmlrpcconfig.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+
+using namespace KNotes;
+
+typedef KRES::PluginFactory<ResourceXMLRPC, ResourceXMLRPCConfig> XMLRPCFactory;
+
+// FIXME: Use K_EXPORT_COMPONENT_FACTORY( knotes_xmlrpc, XMLRPCFactory ); here
+// Problem: How to insert the catalogue!
+extern "C"
+{
+ void *init_knotes_xmlrpc()
+ {
+ KGlobal::locale()->insertCatalogue( "kres_xmlrpc" );
+ return new XMLRPCFactory;
+ }
+}
diff --git a/kresources/egroupware/knotes_xmlrpc.desktop b/kresources/egroupware/knotes_xmlrpc.desktop
new file mode 100644
index 000000000..61411ce01
--- /dev/null
+++ b/kresources/egroupware/knotes_xmlrpc.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=eGroupware Server (via XML-RPC)
+Name[af]=eGroupware Bediener (via XML-RPC)
+Name[bg]=Сървър eGroupware (чрез XML-RPC)
+Name[br]=Servijer eGroupware (gant XML-RPC)
+Name[ca]=Servidor eGroupware (via XML-RPC)
+Name[cs]=eGroupware Server (přes XML-RPC)
+Name[da]=eGroupware server (via XML-RPC)
+Name[el]=Εξυπηρετητής eGroupware (μέσω XML-RPC)
+Name[es]=Servidor de eGroupware (por medio de XML-RPC)
+Name[et]=eGroupware server (XML-RPC vahendusel)
+Name[eu]=eGroupware zerbitzaria (XML-RPC bidez)
+Name[fa]=کارساز eGroupware (از طریق XML-RPC)
+Name[fi]=eGroupware-palvelin (XML-RPC kautta)
+Name[fr]=Serveur eGroupware (via XML-RPC)
+Name[fy]=eGroupware-tsjinner (fia XML-RPC)
+Name[ga]=Freastalaí eGroupware (via XML-RPC)
+Name[gl]=Servidor eGroupware (mediante XML-RPC)
+Name[hu]=eGroupware-kiszolgáló (XML-RPC-n keresztül)
+Name[is]=eGroupware þjónn (gegnum XML-RPC)
+Name[it]=Server eGroupware (via XML-RPC)
+Name[ja]=eGroupware サーバ (XML-RPC 経由)
+Name[ka]=სერბერი eGroupware (XML-RPC-ის საშუალებით)
+Name[kk]=eGroupware сервері (XML-RPC арқылы)
+Name[km]=ម៉ាស៊ីន​បម្រើ eGroupware (តាម​រយៈ XML-RPC)
+Name[lt]=eGroupware serveris (per XML-RPC)
+Name[ms]=Pelayan eGroupware (melalui XML-RPC)
+Name[nb]=eGroupware-tjener (via XML-RPPC)
+Name[nds]=eGroupware-Server (över XML-RPC)
+Name[ne]=(XML-RPC मार्फत) eGroupware सर्भर
+Name[nl]=eGroupware-server (via XML-RPC)
+Name[nn]=eGroupware-tenar (via XML-RPC)
+Name[pl]=Serwer eGroupware (poprzez XML-RPC)
+Name[pt]=Servidor eGroupware (via XML-RPC)
+Name[pt_BR]=Servidor eGroupware (via XML-RPC)
+Name[ru]=Сервер eGroupware (через XML-RPC)
+Name[sk]=eGroupware Server (cez XML-RPC)
+Name[sl]=Strežnik eGroupware (preko XML-RPC)
+Name[sr]=eGroupware сервер (преко XML-RPC)
+Name[sr@Latn]=eGroupware server (preko XML-RPC)
+Name[sv]=eGroupware-server (via XML-RPC)
+Name[ta]=eGroupware சேவகன் (via XML-RPC)
+Name[tr]=eGroupware Sunucusu (XML-RPC ile)
+Name[uk]=Сервер eGroupware (через XML-RPC)
+Name[zh_CN]=eGroupware 服务器(通过 XML-RPC)
+Name[zh_TW]=eGroupware 伺服器(透過 XML-RPC)
+X-KDE-Library=knotes_xmlrpc
+Type=Service
+ServiceTypes=KResources/Plugin
+X-KDE-ResourceFamily=notes
+X-KDE-ResourceType=xmlrpc
diff --git a/kresources/egroupware/kresources_kabc_egroupware.kcfg b/kresources/egroupware/kresources_kabc_egroupware.kcfg
new file mode 100644
index 000000000..3655109b0
--- /dev/null
+++ b/kresources/egroupware/kresources_kabc_egroupware.kcfg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kresources_kabc_egroupwarerc"/>
+
+ <group name="General">
+ <entry type="String" name="Url">
+ <label>URL</label>
+ </entry>
+ <entry type="String" name="Domain">
+ <label>Domain</label>
+ <default>default</default>
+ </entry>
+ <entry type="String" name="User">
+ <label>User Name</label>
+ </entry>
+ <entry type="Password" name="Password">
+ <label>Password</label>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kresources/egroupware/kresources_kcal_egroupware.kcfg b/kresources/egroupware/kresources_kcal_egroupware.kcfg
new file mode 100644
index 000000000..91889d71e
--- /dev/null
+++ b/kresources/egroupware/kresources_kcal_egroupware.kcfg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kresources_kcal_egroupwarerc"/>
+
+ <group name="General">
+ <entry type="String" name="Url">
+ <label>URL</label>
+ </entry>
+ <entry type="String" name="Domain">
+ <label>Domain</label>
+ <default>default</default>
+ </entry>
+ <entry type="String" name="User">
+ <label>User Name</label>
+ </entry>
+ <entry type="Password" name="Password">
+ <label>Password</label>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kresources/egroupware/kresources_knotes_egroupware.kcfg b/kresources/egroupware/kresources_knotes_egroupware.kcfg
new file mode 100644
index 000000000..2fbb84a09
--- /dev/null
+++ b/kresources/egroupware/kresources_knotes_egroupware.kcfg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kresources_knotes_egroupwarerc"/>
+
+ <group name="General">
+ <entry type="String" name="Url">
+ <label>URL</label>
+ </entry>
+ <entry type="String" name="Domain">
+ <label>Domain</label>
+ <default>default</default>
+ </entry>
+ <entry type="String" name="User">
+ <label>User Name</label>
+ </entry>
+ <entry type="Password" name="Password">
+ <label>Password</label>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kresources/egroupware/synchronizer.cpp b/kresources/egroupware/synchronizer.cpp
new file mode 100644
index 000000000..928fc7e1d
--- /dev/null
+++ b/kresources/egroupware/synchronizer.cpp
@@ -0,0 +1,50 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kapplication.h>
+#include <qeventloop.h>
+
+#include <unistd.h>
+
+#include "synchronizer.h"
+
+Synchronizer::Synchronizer()
+ : mBlocked( false )
+{
+}
+
+void Synchronizer::start()
+{
+ mBlocked = true;
+
+ while ( mBlocked ) {
+ QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
+
+ // use sleep here to reduce cpu usage
+ usleep( 100 );
+ }
+}
+
+void Synchronizer::stop()
+{
+ mBlocked = false;
+}
+
diff --git a/kresources/egroupware/synchronizer.h b/kresources/egroupware/synchronizer.h
new file mode 100644
index 000000000..feac6bf31
--- /dev/null
+++ b/kresources/egroupware/synchronizer.h
@@ -0,0 +1,72 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SYNCHRONIZER_H
+#define SYNCHRONIZER_H
+
+#include <qobject.h>
+
+/**
+ A small helper class which blocks an asynchronous operation (e.g. a KIO request)
+ so that it can be used in a synchronous environment.
+
+ Example:
+
+ ...
+
+ Synchronizer mSynchronizer;
+
+ ...
+
+ job = KIO::file_copy( url, file, -1, true );
+ connect( job, SIGNAL( result( KIO::Job * ) ),
+ SLOT( slotResult( KIO::Job * ) ) );
+
+ mSynchronizer.start(); // will block here until the slot was called
+ ...
+
+
+ void slotResult( KIO::Job* )
+ {
+ mSynchronizer.stop();
+ }
+ */
+class Synchronizer
+{
+ public:
+ Synchronizer();
+
+ /**
+ Blocks the execution until @ref stop() is called.
+ */
+ void start();
+
+ /**
+ Unblocks the execution.
+ */
+ void stop();
+
+ private:
+ bool mBlocked;
+};
+
+#endif
+
diff --git a/kresources/egroupware/todostatemapper.cpp b/kresources/egroupware/todostatemapper.cpp
new file mode 100644
index 000000000..6c81ded33
--- /dev/null
+++ b/kresources/egroupware/todostatemapper.cpp
@@ -0,0 +1,167 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qdatastream.h>
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include "todostatemapper.h"
+
+QDataStream& operator<<( QDataStream &stream, const TodoStateMapper::TodoStateMapEntry &entry )
+{
+ stream << entry.uid << entry.localState << entry.remoteState;
+
+ return stream;
+}
+
+QDataStream& operator>>( QDataStream &stream, TodoStateMapper::TodoStateMapEntry &entry )
+{
+ stream >> entry.uid >> entry.localState >> entry.remoteState;
+
+ return stream;
+}
+
+TodoStateMapper::TodoStateMapper()
+{
+}
+
+TodoStateMapper::~TodoStateMapper()
+{
+}
+
+void TodoStateMapper::setPath( const QString &path )
+{
+ mPath = path;
+}
+
+void TodoStateMapper::setIdentifier( const QString &identifier )
+{
+ mIdentifier = identifier;
+}
+
+bool TodoStateMapper::load()
+{
+ QFile file( filename() );
+ if ( !file.open( IO_ReadOnly ) ) {
+ kdError() << "Can't read uid map file '" << filename() << "'" << endl;
+ return false;
+ }
+
+ clear();
+
+ QDataStream stream;
+ stream.setVersion( 6 );
+ stream.setDevice( &file );
+ stream >> mTodoStateMap;
+
+ file.close();
+
+ return true;
+}
+
+bool TodoStateMapper::save()
+{
+ QFile file( filename() );
+ if ( !file.open( IO_WriteOnly ) ) {
+ kdError() << "Can't write uid map file '" << filename() << "'" << endl;
+ return false;
+ }
+
+ QDataStream stream;
+ stream.setVersion( 6 );
+ stream.setDevice( &file );
+ stream << mTodoStateMap;
+
+ file.close();
+
+ return true;
+}
+
+void TodoStateMapper::clear()
+{
+ mTodoStateMap.clear();
+}
+
+void TodoStateMapper::addTodoState( const QString &uid, int localState, const QString &remoteState )
+{
+ TodoStateMapEntry entry;
+ entry.uid = uid;
+ entry.localState = localState;
+ entry.remoteState = remoteState;
+
+ mTodoStateMap.insert( uid, entry );
+}
+
+QString TodoStateMapper::remoteState( const QString &uid, int localState )
+{
+ if ( mTodoStateMap.find( uid ) == mTodoStateMap.end() )
+ kdError() << "TodoStateMapper: no entry for " << uid << " found" << endl;
+
+ TodoStateMapEntry entry = mTodoStateMap[ uid ];
+ if ( entry.localState == localState )
+ return entry.remoteState;
+ else
+ return toRemote( localState );
+}
+
+void TodoStateMapper::remove( const QString &uid )
+{
+ mTodoStateMap.remove( uid );
+}
+
+int TodoStateMapper::toLocal( const QString &remoteState )
+{
+ if ( remoteState == "offer" )
+ return 0;
+ else if ( remoteState == "ongoing" )
+ return 50;
+ else if ( remoteState == "done" || remoteState == "billed" )
+ return 100;
+ else {
+ QString number( remoteState );
+ number.replace( "%", "" );
+ return number.toInt();
+ }
+}
+
+QString TodoStateMapper::toRemote( int localState )
+{
+ if ( localState == 0 )
+ return "offer";
+ else if ( localState == 50 )
+ return "ongoing";
+ else if ( localState == 100 )
+ return "done";
+ else
+ return QString( "%1%" ).arg( localState );
+}
+
+QString TodoStateMapper::filename()
+{
+ QString file = mPath;
+ if ( !file.endsWith( "/" ) ) file += "/";
+ file += mIdentifier;
+
+ return locateLocal( "data", file );
+}
+
diff --git a/kresources/egroupware/todostatemapper.h b/kresources/egroupware/todostatemapper.h
new file mode 100644
index 000000000..c5590ef25
--- /dev/null
+++ b/kresources/egroupware/todostatemapper.h
@@ -0,0 +1,75 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TODOSTATEMAPPER_H
+#define TODOSTATEMAPPER_H
+
+#include <qdatastream.h>
+#include <qmap.h>
+
+class TodoStateMapper
+{
+ public:
+ /**
+ Create Id mapper. You have to set path and identifier before you can call
+ load() or save().
+ */
+ TodoStateMapper();
+ ~TodoStateMapper();
+
+ void setPath( const QString &path );
+ void setIdentifier( const QString &identifier );
+
+ bool load();
+ bool save();
+
+ void clear();
+
+ void addTodoState( const QString &uid, int localState, const QString &remoteState );
+
+ QString remoteState( const QString &uid, int localState );
+
+ void remove( const QString &uid );
+
+ static int toLocal( const QString &remoteState );
+ static QString toRemote( int localState );
+
+ protected:
+ QString filename();
+
+ private:
+ QString mPath;
+ QString mIdentifier;
+
+ typedef struct {
+ QString uid;
+ int localState;
+ QString remoteState;
+ } TodoStateMapEntry;
+
+ typedef QMap<QString, TodoStateMapEntry> TodoStateMap;
+ TodoStateMap mTodoStateMap;
+
+ friend QDataStream &operator<<( QDataStream&, const TodoStateMapEntry& );
+ friend QDataStream &operator>>( QDataStream&, TodoStateMapEntry& );
+};
+
+#endif
diff --git a/kresources/egroupware/xmlrpciface.cpp b/kresources/egroupware/xmlrpciface.cpp
new file mode 100644
index 000000000..0158e23d1
--- /dev/null
+++ b/kresources/egroupware/xmlrpciface.cpp
@@ -0,0 +1,464 @@
+/**************************************************************************
+* Copyright (C) 2003 - 2004 by Frerich Raabe <raabe@kde.org> *
+* Tobias Koenig <tokoe@kde.org> *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+***************************************************************************/
+
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <kio/job.h>
+#include <klocale.h>
+#include <kmdcodec.h>
+
+#include "debugdialog.h"
+#include "xmlrpciface.h"
+
+using namespace KXMLRPC;
+
+namespace KXMLRPC
+{
+ class Result
+ {
+ friend class Query;
+ public:
+ Result()
+ { }
+
+ bool success() const
+ {
+ return m_success;
+ }
+ int errorCode() const
+ {
+ return m_errorCode;
+ }
+ QString errorString() const
+ {
+ return m_errorString;
+ }
+ QValueList<QVariant> data() const
+ {
+ return m_data;
+ }
+
+ private:
+ bool m_success;
+ int m_errorCode;
+ QString m_errorString;
+ QValueList<QVariant> m_data;
+ };
+}
+
+Query *Query::create( const QVariant &id, QObject *parent, const char *name )
+{
+ return new Query( id, parent, name );
+}
+
+void Query::call( const QString &server, const QString &method,
+ const QValueList<QVariant> &args, const QString &userAgent )
+{
+ const QString xmlMarkup = markupCall( method, args );
+ DebugDialog::addMessage( xmlMarkup, DebugDialog::Output );
+
+ QByteArray postData;
+ QDataStream stream( postData, IO_WriteOnly );
+ stream.writeRawBytes( xmlMarkup.utf8(), xmlMarkup.utf8().length() );
+
+ KIO::TransferJob *job = KIO::http_post( KURL( server ), postData, false );
+ if ( !job ) {
+ kdWarning() << "Unable to create KIO job for " << server << endl;
+ return;
+ }
+ job->addMetaData( "UserAgent", userAgent );
+ job->addMetaData( "content-type", "Content-Type: text/xml; charset=utf-8" );
+ job->addMetaData( "ConnectTimeout", "50" );
+
+ connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
+ this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( job, SIGNAL( result( KIO::Job * ) ),
+ this, SLOT( slotResult( KIO::Job * ) ) );
+
+ m_pendingJobs.append( job );
+}
+
+void Query::slotData( KIO::Job *, const QByteArray &data )
+{
+ unsigned int oldSize = m_buffer.size();
+ m_buffer.resize( oldSize + data.size() );
+ memcpy( m_buffer.data() + oldSize, data.data(), data.size() );
+}
+
+void Query::slotResult( KIO::Job *job )
+{
+ m_pendingJobs.remove( job );
+
+ if ( job->error() != 0 )
+ {
+ emit fault( job->error(), job->errorString(), m_id );
+ emit finished( this );
+ return ;
+ }
+
+ QString data = QString::fromUtf8( m_buffer.data(), m_buffer.size() );
+ DebugDialog::addMessage( data, DebugDialog::Input );
+
+ QDomDocument doc;
+ QString errMsg;
+ int errLine, errCol;
+ if ( !doc.setContent( data, false, &errMsg, &errLine, &errCol ) )
+ {
+ emit fault( -1, i18n( "Received invalid XML markup: %1 at %2:%3" )
+ .arg( errMsg ).arg( errLine ).arg( errCol ), m_id );
+ emit finished( this );
+ return ;
+ }
+
+ m_buffer.truncate( 0 );
+
+ if ( isMessageResponse( doc ) )
+ emit message( parseMessageResponse( doc ).data(), m_id );
+ else if ( isFaultResponse( doc ) )
+ {
+ emit fault( parseFaultResponse( doc ).errorCode(), parseFaultResponse( doc ).errorString(), m_id );
+ }
+ else
+ {
+ emit fault( 1, i18n( "Unknown type of XML markup received" ), m_id );
+ }
+
+ emit finished( this );
+}
+
+bool Query::isMessageResponse( const QDomDocument &doc ) const
+{
+ return doc.documentElement().firstChild().toElement().tagName().lower() == "params";
+}
+
+Result Query::parseMessageResponse( const QDomDocument &doc ) const
+{
+ Result response;
+ response.m_success = true;
+
+ QDomNode paramNode = doc.documentElement().firstChild().firstChild();
+ while ( !paramNode.isNull() )
+ {
+ response.m_data << demarshal( paramNode.firstChild().toElement() );
+ paramNode = paramNode.nextSibling();
+ }
+
+ return response;
+}
+
+bool Query::isFaultResponse( const QDomDocument &doc ) const
+{
+ return doc.documentElement().firstChild().toElement().tagName().lower() == "fault";
+}
+
+Result Query::parseFaultResponse( const QDomDocument &doc ) const
+{
+ Result response;
+ response.m_success = false;
+
+ QDomNode errorNode = doc.documentElement().firstChild().firstChild();
+ const QVariant errorVariant = demarshal( errorNode.toElement() );
+ response.m_errorCode = errorVariant.toMap() [ "faultCode" ].toInt();
+ response.m_errorString = errorVariant.toMap() [ "faultString" ].toString();
+
+ return response;
+}
+
+QString Query::markupCall( const QString &cmd,
+ const QValueList<QVariant> &args ) const
+{
+ QString markup = "<?xml version=\"1.0\" ?>\r\n<methodCall>\r\n";
+
+ markup += "<methodName>" + cmd + "</methodName>\r\n";
+
+ if ( !args.isEmpty() )
+ {
+ markup += "<params>\r\n";
+ QValueList<QVariant>::ConstIterator it = args.begin();
+ QValueList<QVariant>::ConstIterator end = args.end();
+ for ( ; it != end; ++it )
+ markup += "<param>\r\n" + marshal( *it ) + "</param>\r\n";
+ markup += "</params>\r\n";
+ }
+
+ markup += "</methodCall>\r\n";
+
+ return markup;
+}
+
+QString Query::marshal( const QVariant &arg ) const
+{
+ switch ( arg.type() )
+ {
+ case QVariant::String:
+ case QVariant::CString:
+ {
+ QString result = arg.toString();
+ result = result.replace( "&", "&amp;" );
+ result = result.replace( "\"", "&quot;" );
+ result = result.replace( "<", "&lt;" );
+ result = result.replace( ">", "&gt;" );
+ return "<value><string>" + result + "</string></value>\r\n";
+ }
+ case QVariant::Int:
+ return "<value><int>" + QString::number( arg.toInt() ) + "</int></value>\r\n";
+ case QVariant::Double:
+ return "<value><double>" + QString::number( arg.toDouble() ) + "</double></value>\r\n";
+ case QVariant::Bool:
+ {
+ QString markup = "<value><boolean>";
+ markup += arg.toBool() ? "1" : "0";
+ markup += "</boolean></value>\r\n";
+ return markup;
+ }
+ case QVariant::ByteArray:
+ return "<value><base64>" + KCodecs::base64Encode( arg.toByteArray() ) + "</base64></value>\r\n";
+ case QVariant::DateTime:
+ return "<value><datetime.iso8601>" + arg.toDateTime().toString( Qt::ISODate ) + "</datetime.iso8601></value>\r\n";
+ case QVariant::List:
+ {
+ QString markup = "<value><array><data>\r\n";
+ const QValueList<QVariant> args = arg.toList();
+ QValueList<QVariant>::ConstIterator it = args.begin();
+ QValueList<QVariant>::ConstIterator end = args.end();
+ for ( ; it != end; ++it )
+ markup += marshal( *it );
+ markup += "</data></array></value>\r\n";
+ return markup;
+ }
+ case QVariant::Map:
+ {
+ QString markup = "<value><struct>\r\n";
+ QMap<QString, QVariant> map = arg.toMap();
+ QMap<QString, QVariant>::ConstIterator it = map.begin();
+ QMap<QString, QVariant>::ConstIterator end = map.end();
+ for ( ; it != end; ++it )
+ {
+ markup += "<member>\r\n";
+ markup += "<name>" + it.key() + "</name>\r\n";
+ markup += marshal( it.data() );
+ markup += "</member>\r\n";
+ }
+ markup += "</struct></value>\r\n";
+ return markup;
+ }
+ default:
+ kdWarning() << "Failed to marshal unknown variant type: " << arg.type() << endl;
+ };
+ return QString::null;
+}
+
+QVariant Query::demarshal( const QDomElement &elem ) const
+{
+ Q_ASSERT( elem.tagName().lower() == "value" );
+
+ const QDomElement typeElement = elem.firstChild().toElement();
+ const QString typeName = typeElement.tagName().lower();
+
+ if ( typeName == "string" )
+ return QVariant( typeElement.text() );
+ else if ( typeName == "i4" || typeName == "int" )
+ return QVariant( typeElement.text().toInt() );
+ else if ( typeName == "double" )
+ return QVariant( typeElement.text().toDouble() );
+ else if ( typeName == "boolean" )
+ {
+ if ( typeElement.text().lower() == "true" || typeElement.text() == "1" )
+ return QVariant( true );
+ else
+ return QVariant( false );
+ }
+ else if ( typeName == "base64" )
+ return QVariant( KCodecs::base64Decode( typeElement.text().latin1() ) );
+ else if ( typeName == "datetime" || typeName == "datetime.iso8601" )
+ return QVariant( QDateTime::fromString( typeElement.text(), Qt::ISODate ) );
+ else if ( typeName == "array" )
+ {
+ QValueList<QVariant> values;
+ QDomNode valueNode = typeElement.firstChild().firstChild();
+ while ( !valueNode.isNull() )
+ {
+ values << demarshal( valueNode.toElement() );
+ valueNode = valueNode.nextSibling();
+ }
+ return QVariant( values );
+ }
+ else if ( typeName == "struct" )
+ {
+ QMap<QString, QVariant> map;
+ QDomNode memberNode = typeElement.firstChild();
+ while ( !memberNode.isNull() )
+ {
+ const QString key = memberNode.toElement().elementsByTagName( "name" ).item( 0 ).toElement().text();
+ const QVariant data = demarshal( memberNode.toElement().elementsByTagName( "value" ).item( 0 ).toElement() );
+ map[ key ] = data;
+ memberNode = memberNode.nextSibling();
+ }
+ return QVariant( map );
+ }
+ else
+ kdWarning() << "Cannot demarshal unknown type " << typeName << endl;
+
+ return QVariant();
+}
+
+Query::Query( const QVariant &id, QObject *parent, const char *name )
+ : QObject( parent, name ), m_id( id )
+{}
+
+Query::~Query()
+{
+ QValueList<KIO::Job*>::Iterator it;
+ for ( it = m_pendingJobs.begin(); it != m_pendingJobs.end(); ++it )
+ (*it)->kill();
+}
+
+Server::Server( const KURL &url, QObject *parent, const char *name )
+ : QObject( parent, name )
+{
+ if ( url.isValid() )
+ m_url = url;
+
+ m_userAgent = "KDE XMLRPC resources";
+
+ DebugDialog::init();
+}
+
+Server::~Server()
+{
+ QValueList<Query*>::Iterator it;
+ for ( it = mPendingQueries.begin(); it !=mPendingQueries.end(); ++it )
+ (*it)->deleteLater();
+
+ mPendingQueries.clear();
+}
+
+void Server::queryFinished( Query *query )
+{
+ mPendingQueries.remove( query );
+ query->deleteLater();
+}
+
+void Server::setUrl( const KURL &url )
+{
+ m_url = url.isValid() ? url : KURL();
+}
+
+void Server::call( const QString &method, const QValueList<QVariant> &args,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot, const QVariant &id )
+{
+ if ( m_url.isEmpty() )
+ kdWarning() << "Cannot execute call to " << method << ": empty server URL" << endl;
+
+ Query *query = Query::create( id, this );
+ connect( query, SIGNAL( message( const QValueList<QVariant> &, const QVariant& ) ), msgObj, messageSlot );
+ connect( query, SIGNAL( fault( int, const QString&, const QVariant& ) ), faultObj, faultSlot );
+ connect( query, SIGNAL( finished( Query* ) ), this, SLOT( queryFinished( Query* ) ) );
+ mPendingQueries.append( query );
+
+ query->call( m_url.url(), method, args, m_userAgent );
+}
+
+void Server::call( const QString &method, const QVariant &arg,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << arg ;
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, int arg,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, bool arg,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, double arg ,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, const QString &arg ,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, const QCString &arg,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, const QByteArray &arg ,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, faultObj, faultSlot, msgObj, messageSlot, id );
+}
+
+void Server::call( const QString &method, const QDateTime &arg,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ args << QVariant( arg );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Server::call( const QString &method, const QStringList &arg,
+ QObject* msgObj, const char* messageSlot,
+ QObject* faultObj, const char* faultSlot,
+ const QVariant &id )
+{
+ QValueList<QVariant> args;
+ QStringList::ConstIterator it = arg.begin();
+ QStringList::ConstIterator end = arg.end();
+ for ( ; it != end; ++it )
+ args << QVariant( *it );
+ call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+#include "xmlrpciface.moc"
diff --git a/kresources/egroupware/xmlrpciface.h b/kresources/egroupware/xmlrpciface.h
new file mode 100644
index 000000000..0e5f6c927
--- /dev/null
+++ b/kresources/egroupware/xmlrpciface.h
@@ -0,0 +1,165 @@
+/**************************************************************************
+* Copyright (C) 2003 - 2004 by Frerich Raabe <raabe@kde.org> *
+* Tobias Koenig <tokoe@kde.org> *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+***************************************************************************/
+#ifndef KXMLRPCIFACE_H
+#define KXMLRPCIFACE_H
+
+#include <kurl.h>
+
+#include <qbuffer.h>
+#include <qdom.h>
+#include <qobject.h>
+#include <qvariant.h>
+#include <qvaluelist.h>
+
+namespace KIO
+{
+ class Job;
+}
+
+namespace KXMLRPC
+{
+ class Query;
+ class QueryResult;
+ class Server;
+ class Result;
+
+ class Query : public QObject
+ {
+ Q_OBJECT
+ public:
+
+
+ static Query *create( const QVariant &id = QVariant(),
+ QObject *parent = 0, const char *name = 0 );
+
+ public slots:
+ void call( const QString &server, const QString &method,
+ const QValueList<QVariant> &args = QValueList<QVariant>(),
+ const QString &userAgent = "KDE-XMLRPC" );
+
+ signals:
+ void message( const QValueList<QVariant> &result, const QVariant &id );
+ void fault( int, const QString&, const QVariant &id );
+ void finished( Query* );
+
+ private slots:
+ void slotData( KIO::Job *job, const QByteArray &data );
+ void slotResult( KIO::Job *job );
+
+ private:
+ bool isMessageResponse( const QDomDocument &doc ) const;
+ bool isFaultResponse( const QDomDocument &doc ) const;
+
+ Result parseMessageResponse( const QDomDocument &doc ) const;
+ Result parseFaultResponse( const QDomDocument &doc ) const;
+
+ QString markupCall( const QString &method,
+ const QValueList<QVariant> &args ) const;
+ QString marshal( const QVariant &v ) const;
+ QVariant demarshal( const QDomElement &e ) const;
+
+ Query( const QVariant &id, QObject *parent = 0, const char *name = 0 );
+ ~Query();
+
+ QByteArray m_buffer;
+ QVariant m_id;
+
+ QValueList<KIO::Job*> m_pendingJobs;
+ };
+
+ class Server : public QObject
+ {
+ Q_OBJECT
+ public:
+ Server( const KURL &url = KURL(),
+ QObject *parent = 0, const char *name = 0 );
+ ~Server();
+
+ const KURL &url() const { return m_url; }
+ void setUrl( const KURL &url );
+
+ QString userAgent() const { return m_userAgent; }
+ void setUserAgent( const QString &userAgent ) { m_userAgent = userAgent; }
+
+ template <typename T>
+ void call( const QString &method, const QValueList<T> &arg,
+ QObject* obj1, const char* faultSlot,
+ QObject* obj2, const char* messageSlot, const QVariant &id = QVariant() );
+
+
+ public slots:
+ void call( const QString &method, const QValueList<QVariant> &args,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, const QVariant &arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, int arg ,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, bool arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, double arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, const QString &arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, const QCString &arg ,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, const QByteArray &arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, const QDateTime &arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+ void call( const QString &method, const QStringList &arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot,
+ const QVariant &id = QVariant() );
+
+ private slots:
+ void queryFinished( Query* );
+
+ private:
+ KURL m_url;
+ QString m_userAgent;
+
+ QValueList<Query*> mPendingQueries;
+ };
+}
+
+template <typename T>
+void KXMLRPC::Server::call( const QString &method, const QValueList<T> &arg,
+ QObject* faultObj, const char* faultSlot,
+ QObject* msgObj, const char* messageSlot, const QVariant &id )
+{
+ QValueList<QVariant> args;
+
+ typename QValueList<T>::ConstIterator it = arg.begin();
+ typename QValueList<T>::ConstIterator end = arg.end();
+ for ( ; it != end; ++it )
+ args << QVariant( *it );
+
+ return call( method, args, faultObj, faultSlot, msgObj, messageSlot, id );
+}
+
+#endif