diff options
Diffstat (limited to 'kresources/newexchange')
23 files changed, 3238 insertions, 0 deletions
diff --git a/kresources/newexchange/Incidence.mapping b/kresources/newexchange/Incidence.mapping new file mode 100644 index 000000000..ef0914b56 --- /dev/null +++ b/kresources/newexchange/Incidence.mapping @@ -0,0 +1,177 @@ +GENERAL Properties (for all types): +=================================== + +WebDAV property | Incidence:: method +---------------------------------------------+---------------------- +DAV:contentclass | "urn:content-classes:appointment" / :task / :message +DAV:getcontenttype | "message/rfc822" +http://schemas.microsoft.com/mapi/proptag/0x001A001F | "IPM.Appointment" / .Task / .Journal/.Post +http://schemas.microsoft.com/exchange/outlookmessageclass | "IPM.Appointment" +DAV:getetag | FINGERPRINT +DAV:href | CUSTOM +DAV:creationdate | created() +DAV:getlastmodified | lastModified() +DAV:isreadonly | isReadOnly() +http://schemas.microsoft.com/repl/repl-uid | schedulingID() + | +DAV:uid | uid() +urn:schemas:mailheader:subject | summary() +urn:schemas:httpmail:subject | summary() (welches der beiden?) +urn:schemas:httpmail:textdescription | description() +urn:schemas:httpmail:date | ? (datestamp, no method in libkcal!) +DAV:comment | comments() + | +urn:schemas-microsoft-com:office:office#Keywords | categories() + | +http://schemas.microsoft.com/exchange/sensitivity | secrecy() +urn:schemas:httpmail:priority | priority() + | +urn:schemas:httpmail:from | organizer() +urn:schemas:httpmail:to | attendees(), required +urn:schemas:httpmail:cc | attendees(), optional + | resources ??? + | +urn:schemas:httpmail:hasattachment | attachments() ??? + + + + +Event: +====== +See +-) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_urn_content-classes_appointment.asp +-) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_cdo_schema_dav.asp +-) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_cdo_schema_httpmail.asp + +h="http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/" + + +WebDAV property | Incidence:: method +---------------------------------------------+---------------------- +urn:schemas:calendar:created | created() ?, siehe DAV:creationdate +urn:schemas:calendar:lastmodified | lastModified() ?, siehe DAV:getlastmodified +urn:schemas:calendar:dtstamp | ?? +urn:schemas:calendar:sequence | revision() + | +urn:schemas:calendar:location | location() + | +//urn:schemas:calendar:organizer | organizer() +//urn:schemas:calendar:method | ?? +//urn:schemas:calendar:responserequested | ?? +//urn:schemas:calendar:meetingstatus | ?? +//urn:schemas:calendar:replytime | ?? + +urn:schemas:calendar:busystatus | status() +urn:schemas:calendar:transparent | transparency(): Event::Transparent, Event::Opaque + | +urn:schemas:calendar:timezone | ?? +urn:schemas:calendar:alldayevent | doesFloat() +urn:schemas:calendar:dtstart | dtStart() +urn:schemas:calendar:dtend | dtEnd() +urn:schemas:calendar:duration | duration() + | +urn:schemas:calendar:rrule | recurrence(), doesRecur() +urn:schemas:calendar:rdate | -- +urn:schemas:calendar:exrule | -- +urn:schemas:calendar:exdate | recurrence()->exDates(), recurrence()->exDateTimes() +urn:schemas:calendar:recurrenceid | recurrenceId() ?? (protected?) +urn:schemas:calendar:instancetype | ?? + | +urn:schemas:calendar:reminderoffset | alarms() + | +urn:schemas:calendar:resources | resources() + | +? | custom items? + + +No correspondence: +================== +urn:schemas:calendar:timezoneid +urn:schemas:calendar:geolatitude +urn:schemas:calendar:geolongitude +urn:schemas:calendar:contacturl +urn:schemas:calendar:descriptionurl +urn:schemas:calendar:locationurl +urn:schemas:httpmail:htmldescription +urn:schemas:httpmail:priority +urn:schemas:calendar:recurrenceidrange +urn:schemas:contacts:billinginformation +http://schemas.microsoft.com/exchange/companies +http://schemas.microsoft.com/exchange/mileage +urn:schemas:httpmail:normalizedsubject +DAV:displayname +DAV:id + + +Incidence::pilotId() +Incidence::syncStatus() +Incidence::relatedToUid() + + + + + +Task: +===== +For the mapping of the MAPI properties and the hex codes to access them via +WebDAV, see http://www.cdolive.com/cdo10.htm + +h1="http://schemas.microsoft.com/mapi/id/{00062003-0000-0000-C000-000000000046}/" (CdoPropSetID2) +h2="http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/" (CdoPropSetID4) +b='urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/' +oder: +b="urn:schemas-microsoft-com:datatypes" + + +WebDAV property | Incidence:: method +---------------------------------------------+---------------------- +?? -------------------------- | revision() +----------------------------- | location() +----------------------------- | status() +----------------------------- | doesFloat() + | +h1:0x00008104 b:dt="dateTime.tz" | dtStart() (or h2:0x00008516), z.B. 2003-09-11T18:45:00.00Z +h1:0x00008105 b:dt="dateTime.tz" | dtDue() (or h2:0x00008517) +h1:0x00008106 | duration() + | +h1:0x0000811C b:dt="boolean" | isCompleted() (0/1) +h1:0x00008102 b:dt='float' | percentComplete(), 0.0-1.0 +h1:0x0000810f b:dt="dateTime.tz" | completed() +----------------------------- | hasCompletedDate() + | +h1:0x00008126 b:dt="boolean" | doesRecur() +----------------------------- | recurrence() +----------------------------- | recurrence()->exDates(), recurrence()->exDateTimes() +----------------------------- | recurrenceId() ?? (protected?) + | +h2:0x00008503 b:dt="boolean" (reminder set: 0/1) | alarms() +h2:0x00008502 b:dt="dateTime.tz" | ? (reminder date/time) +h2:0x0000851E | ReminderPlaySound +h2:0x0000851F | ReminderSoundFile + | +h1:0x00008101 b:dt='int' | status: 0_Open, 1_InProgress, 2_Completed, 3_WaitingForSomeoneElse, 4_Deferred + | + + +No correspondence: +================== +Incidence::pilotId() +Incidence::syncStatus() +Incidence::relatedToUid() +Incidence::custom() + +h1:0x00008103 TeamTask (b:dt="boolean") +h1:0x00008110 ActualWork: In minutes +h1:0x00008111 TotalWork: In minutes +h1:0x00008129 assignment + + +Journal: +======== + +#define E2K_NS_OUTLOOK_JOURNAL E2K_NS_MAPI_ID "{0006200A-0000-0000-C000-000000000046}/" + +WebDAV property | Journal:: method +----------------------------------------------------------+--------------------------------- +urn:schemas:httpmail:importance | ? +urn:schemas:httpmail:date | dtStart() diff --git a/kresources/newexchange/Makefile.am b/kresources/newexchange/Makefile.am new file mode 100644 index 000000000..317e9863c --- /dev/null +++ b/kresources/newexchange/Makefile.am @@ -0,0 +1,45 @@ +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/kresources/lib \ + -I$(top_builddir)/kresources/lib $(all_includes) + +lib_LTLIBRARIES = libkabc_newexchange.la libkcal_newexchange.la +noinst_LTLIBRARIES = libknewexchange.la + +libknewexchange_la_SOURCES = exchangeglobals.cpp exchangeconvertercalendar.cpp exchangeconvertercontact.cpp + +libkcal_newexchange_la_SOURCES = exchangecalendaradaptor.cpp kcal_resourceexchange.cpp +libkcal_newexchange_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) \ + -version-info 1:0:0 -no-undefined +libkcal_newexchange_la_LIBADD = \ + libknewexchange.la ../lib/libkgroupwaredav.la \ + $(top_builddir)/libkcal/libkcal.la $(top_builddir)/libkdepim/libkdepim.la \ + -lkabc + +libkabc_newexchange_la_SOURCES = kabc_resourceexchange.cpp exchangeaddressbookadaptor.cpp +libkabc_newexchange_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) \ + -version-info 1:0:0 -no-undefined +libkabc_newexchange_la_LIBADD = \ + libknewexchange.la ../lib/libkgroupwaredav.la \ + $(top_builddir)/libkcal/libkcal.la $(top_builddir)/libkdepim/libkdepim.la \ + -lkabc + +kde_module_LTLIBRARIES = kcal_newexchange.la kabc_newexchange.la + +kcal_newexchange_la_SOURCES = kcal_resourceexchange_plugin.cpp +kcal_newexchange_la_LDFLAGS = $(all_libraries) -module -no-undefined $(KDE_PLUGIN) +kcal_newexchange_la_LIBADD = libkcal_newexchange.la + +kabc_newexchange_la_SOURCES = kabc_resourceexchange_plugin.cpp +kabc_newexchange_la_LDFLAGS = $(all_libraries) -module -no-undefined $(KDE_PLUGIN) +kabc_newexchange_la_LIBADD = libkabc_newexchange.la + + +kcal_servicedir = $(kde_servicesdir)/kresources/kcal +kcal_service_DATA = kcal_newexchange.desktop + +kabc_servicedir = $(kde_servicesdir)/kresources/kabc +kabc_service_DATA = kabc_newexchange.desktop + +METASOURCES = AUTO + +kcal_resourceexchange.lo kabc_resourceexchange.lo: ../lib/kresources_groupwareprefs.h + diff --git a/kresources/newexchange/Person.mapping b/kresources/newexchange/Person.mapping new file mode 100644 index 000000000..d7571e773 --- /dev/null +++ b/kresources/newexchange/Person.mapping @@ -0,0 +1,184 @@ +http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_cdo_schema_contacts_c.asp +http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_urn_content-classes_person.asp + +/* KDE4: addressee does not have any creation or modification date :-(( */ +/* KDE4: read-only not supported by libkabc */ + +WebDAV property | Addressee:: method +---------------------------------------------+---------------------- +DAV:contentclass | "urn:content-classes:appointment" +http://schemas.microsoft.com/exchange/outlookmessageclass | "IPM.Contact" +DAV:getetag | FINGERPRINT +DAV:href | CUSTOM +DAV:creationdate | created() +DAV:getlastmodified | lastModified() +DAV:isreadonly | isReadOnly() +//urn:schemas:calendar:dtstamp | ?? +//urn:schemas:calendar:sequence | revision() +//http://schemas.microsoft.com/repl/uid | schedulingID() + +urn:schemas:contacts:cn | uid() +urn:schemas:contacts:uid | uid() + | +urn:schemas:contacts:fileas (niceName) | formattedName() +//urn:schemas:contacts:cn | formattedName() +urn:schemas:contacts:givenName | givenName() +urn:schemas:contacts:initials | - +urn:schemas:contacts:middlename | additionalName() +urn:schemas:contacts:namesuffix | suffix() +urn:schemas:contacts:personaltitle | prefix() +urn:schemas:contacts:sn (surname) | familyName() + | +urn:schemas:contacts:title | role() / title() + | +urn:schemas:contacts:o (org.) | organization() +urn:schemas:contacts:department | custom( "KADDRESSBOOK", "X-Department" ) +urn:schemas:contacts:roomnumber | custom( "KADDRESSBOOK", "X-Office" ) +urn:schemas:contacts:profession | custom( "KADDRESSBOOK", "X-Profession" ) +urn:schemas:contacts:manager | custom( "KADDRESSBOOK", "X-ManagersName" ) +urn:schemas:contacts:secretarycn | custom( "KADDRESSBOOK", "X-AssistantsName" ) + | +urn:schemas:contacts:email1 | emails(); +urn:schemas:contacts:email2 | -"- +urn:schemas:contacts:email3 | -"- + | +urn:schemas:contacts:personalHomePage | - +urn:schemas:contacts:businesshomepage | url() + | +urn:schemas:calendar:fburl | KCal::FreeBusyUrlStore::self()->readUrl( addr.preferredEmail() ) + | +urn:schemas-microsoft-com:office:office#Keywords | categories() + | +DAV:sensitivity | secrecy() + | +urn:schemas:contacts:telephoneNumber | phoneNumber( Home ) +urn:schemas:contacts:telephonenumber2 | phoneNumber( Home ) +urn:schemas:contacts:officetelephonenumber | phoneNumber( Work ) +urn:schemas:contacts:office2telephonenumber | phoneNumber( Work ) +urn:schemas:contacts:secretaryphone | phoneNumber( Work ) +urn:schemas:contacts:organizationmainphone | phoneNumber( Work ) +urn:schemas:contacts:otherTelephone | phoneNumber( ) +urn:schemas:contacts:homePhone | phoneNumber( Home ) +urn:schemas:contacts:homephone2 | phoneNumber( Home ) +urn:schemas:contacts:mobile | phoneNumber( Cell | Pref ) +urn:schemas:contacts:othermobile | phoneNumber( Cell ) +urn:schemas:contacts:facsimiletelephonenumber| phoneNumber( Fax ) +urn:schemas:contacts:homefax | phoneNumber( Fax | Home ) +urn:schemas:contacts:otherfax | phoneNumber( Fax | Work) +urn:schemas:contacts:pager | phoneNumber( Pager | Work ) +urn:schemas:contacts:otherpager | phoneNumber( Pager ) +urn:schemas:contacts:internationalisdnnumber | + (isdn number) | phoneNumber( Isdn ) +urn:schemas:contacts:callbackphone | phoneNumber( Msg ) +urn:schemas:contacts:telexnumber | phoneNumber( Bbs ) +urn:schemas:contacts:ttytddphone | phoneNumber( Pcs ) + | + | +// work address: | +urn:schemas:contacts:workaddress | address(Work|Pref). +urn:schemas:contacts:street | address(Work|Pref).street() +urn:schemas:contacts:postofficebox | address(Work|Pref).postOfficeBox() +urn:schemas:contacts:l (city) | address(Work|Pref).locality() +urn:schemas:contacts:postalcode | address(Work|Pref).postalCode() +urn:schemas:contacts:st (work state) | address(Work|Pref).region() +urn:schemas:contacts:co (full ctry/region) | address(Work|Pref).country() +urn:schemas:contacts:c (ctry/region abbrev.)| address(Work|Pref).countryCode() + | +// home address: | +urn:schemas:contacts:homepostaladdress | address(Home). +urn:schemas:contacts:homeStreet | address(Home).street() +urn:schemas:contacts:homepostofficebox | address(Home).postOfficeBox() +urn:schemas:contacts:homeCity | address(Home).locality() +urn:schemas:contacts:homePostalCode | address(Home).postalCode() +urn:schemas:contacts:homeState | address(Home).region() +urn:schemas:contacts:homeCountry | address(Home).country() +urn:schemas:contacts:homeCountrycode | address(Home).countryCode() + | +// mailing address: | +urn:schemas:contacts:mailingpostaladdress | address(Postal). +urn:schemas:contacts:mailingstreet | address(Postal).street() +urn:schemas:contacts:mailingpostofficebox | address(Postal).postOfficeBox() +urn:schemas:contacts:mailingcity | address(Postal).locality() +urn:schemas:contacts:mailingpostalcode | address(Postal).postalCode() +urn:schemas:contacts:mailingstate | address(Postal).region() +urn:schemas:contacts:mailingcountry | address(Postal).country() +urn:schemas:contacts:mailingcountrycode | address(Postal).countryCode() + | +// other address: | +urn:schemas:contacts:otherpostaladdress | address(). +urn:schemas:contacts:otherstreet | address().street() +urn:schemas:contacts:otherpostofficebox | address().postOfficeBox() +urn:schemas:contacts:othercity | address().locality() +urn:schemas:contacts:otherpostalcode | address().postalCode() +urn:schemas:contacts:otherstate | address().region() +urn:schemas:contacts:othercountry | address().country() +urn:schemas:contacts:othercountrycode | address().countryCode() + | + | +urn:schemas:contacts:nickname | nickName() +urn:schemas:contacts:spousecn | custom( "KADDRESSBOOK", "X-SpousesName" ) + | +urn:schemas:contacts:bday | birthday() +urn:schemas:contacts:weddinganniversary | custom( "KADDRESSBOOK", "X-Anniversary" ) + | +? | timeZone() + | +urn:schemas:calendar:geolatitude | geo() +urn:schemas:calendar:geolongitude | geo() +urn:schemas:contacts:mapurl | - +urn:schemas:contacts:location | - + | +urn:schemas:httpmail:textdescription | note() + | +urn:schemas:contacts:usercertificate | keys() + | +- | custom( app, name ) + | +// http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/0x00008025 | Journal +// http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/0x00008056 | NetMeeting +http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/0x00008062 | IM Address + + + +KABC::Addressee method not used: +logo() +photo() +sound() +agent() +revision() +productId() +mailer() + + +KABC::Address methods not used: +id() +type() +extended () + + + Not used: +urn:schemas:contacts:computernetworkname +urn:schemas:contacts:customerid +urn:schemas:contacts:dn +urn:schemas:contacts:employeenumber +urn:schemas:contacts:fileasid +urn:schemas:contacts:ftpsite +urn:schemas:contacts:gender +urn:schemas:contacts:governmentid +urn:schemas:contacts:hobbies +urn:schemas:contacts:homelatitude +urn:schemas:contacts:homelongitude +urn:schemas:contacts:hometimezone +urn:schemas:contacts:language +urn:schemas:contacts:mailingaddressid +urn:schemas:contacts:othertimezone +urn:schemas:contacts:proxyaddresses +urn:schemas:contacts:referredby +urn:schemas:contacts:secretaryurl +urn:schemas:contacts:sourceurl +urn:schemas:httpmail:hasattachment +urn:schemas:httpmail:htmldescription +urn:schemas:httpmail:outbox +urn:schemas:httpmail:subject +urn:schemas:mailheader:subject + diff --git a/kresources/newexchange/exchangeaddressbookadaptor.cpp b/kresources/newexchange/exchangeaddressbookadaptor.cpp new file mode 100644 index 000000000..469d15c36 --- /dev/null +++ b/kresources/newexchange/exchangeaddressbookadaptor.cpp @@ -0,0 +1,95 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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 "exchangeaddressbookadaptor.h" +#include "exchangeconvertercontact.h" +#include <davgroupwareglobals.h> +#include "exchangeglobals.h" +#include <webdavhandler.h> +#include <kdebug.h> +#include <kio/davjob.h> + +using namespace KABC; + +ExchangeAddressBookUploadItem::ExchangeAddressBookUploadItem( AddressBookAdaptor *adaptor, KABC::Addressee addr, KPIM::GroupwareUploadItem::UploadType type ) + : GroupwareUploadItem( type ) +{ + if ( adaptor && !addr.isEmpty() ) { + mItemType = KPIM::FolderLister::Contact; + + setUrl( addr.custom( adaptor->identifier(), "storagelocation" ) ); + setUid( addr.uid() ); + + ExchangeConverterContact format; + mDavData = format.createWebDAV( addr ); + } +} + +KIO::TransferJob *ExchangeAddressBookUploadItem::createUploadJob( KPIM::GroupwareDataAdaptor *adaptor, const KURL &/*baseurl*/ ) +{ +kdDebug()<<"ExchangeAddressBookUploadItem::createUploadJob"<<endl; + Q_ASSERT( adaptor ); + if ( !adaptor ) return 0; + KURL upUrl( url() ); + adaptor->adaptUploadUrl( upUrl ); + kdDebug() << "Uploading to: " << upUrl.prettyURL() << endl; + KIO::DavJob *job = KIO::davPropPatch( upUrl, mDavData, false ); + return job; +} + +KIO::TransferJob *ExchangeAddressBookUploadItem::createUploadNewJob( KPIM::GroupwareDataAdaptor *adaptor, const KURL &baseurl ) +{ +kdDebug()<<"ExchangeAddressBookUploadItem::createUploadNewJob"<<endl; + KURL url( baseurl ); + // TODO: Check that this URL doesn't exist yet + url.addPath( uid() + ".EML" ); + setUrl( url ); +//url.addPath("newItem.EML"); +kdDebug()<<"Upload path: "<<url.url()<<endl; + return createUploadJob( adaptor, url ); +} + +ExchangeAddressBookAdaptor::ExchangeAddressBookAdaptor() : DavAddressBookAdaptor() +{ +} + +void ExchangeAddressBookAdaptor::customAdaptDownloadUrl( KURL &url ) +{ + url = WebdavHandler::toDAV( url ); +} + +void ExchangeAddressBookAdaptor::customAdaptUploadUrl( KURL &url ) +{ + url = WebdavHandler::toDAV( url ); +// url.setPath( url.path() + "/NewItem.EML" ); +} + +QString ExchangeAddressBookAdaptor::defaultNewItemName( KPIM::GroupwareUploadItem *item ) { + if ( item ) return item->uid()+".EML"; + else return QString::null; +} + + +KPIM::GroupwareUploadItem *ExchangeAddressBookAdaptor::newUploadItem( KABC::Addressee addr, + KPIM::GroupwareUploadItem::UploadType type ) +{ + return new ExchangeAddressBookUploadItem( this, addr, type ); +} diff --git a/kresources/newexchange/exchangeaddressbookadaptor.h b/kresources/newexchange/exchangeaddressbookadaptor.h new file mode 100644 index 000000000..7d340bfb9 --- /dev/null +++ b/kresources/newexchange/exchangeaddressbookadaptor.h @@ -0,0 +1,102 @@ + /* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + + 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_EXCHANGEADDRESSBOOKADAPTOR_H +#define KABC_EXCHANGEADDRESSBOOKADAPTOR_H + +#include "exchangeglobals.h" + +#include <groupwareresourcejob.h> +#include <davaddressbookadaptor.h> + +#include <folderlister.h> + +#include <kabc/addressee.h> +#include <kurl.h> +#include <qdom.h> + +namespace KABC { + +class ExchangeAddressBookUploadItem : public KPIM::GroupwareUploadItem +{ + public: + ExchangeAddressBookUploadItem( AddressBookAdaptor *adaptor, KABC::Addressee addr, UploadType type ); + virtual ~ExchangeAddressBookUploadItem() {} +/**/ virtual KIO::TransferJob *createUploadJob( + KPIM::GroupwareDataAdaptor *adaptor, const KURL &baseurl ); +/**/ virtual KIO::TransferJob *createUploadNewJob( + KPIM::GroupwareDataAdaptor *adaptor, const KURL &baseurl ); + + protected: + ExchangeAddressBookUploadItem( UploadType type ) : KPIM::GroupwareUploadItem( type ) {} + QDomDocument mDavData; +}; + +class ExchangeAddressBookAdaptor : public DavAddressBookAdaptor +{ + public: + ExchangeAddressBookAdaptor(); + + void customAdaptDownloadUrl( KURL &url ); + void customAdaptUploadUrl( KURL &url ); + QString mimeType() const { return "message/rfc822"; } + QCString identifier() const { return "KABCResourceExchange"; } + QString defaultNewItemName( KPIM::GroupwareUploadItem *item ); + long flags() const { return GWResBatchDelete; } + + + + // Creating Jobs + KIO::Job *createListFoldersJob( const KURL &url ) + { return ExchangeGlobals::createListFoldersJob( url ); } + KIO::TransferJob *createListItemsJob( const KURL &url ) + { return ExchangeGlobals::createListItemsJob( url ); } + KIO::TransferJob *createDownloadJob( const KURL &url, KPIM::FolderLister::ContentType ctype ) + { return ExchangeGlobals::createDownloadJob( this, url, ctype ); } + KIO::Job *createRemoveJob( const KURL &uploadurl, const KPIM::GroupwareUploadItem::List &deletedItems ) + { return ExchangeGlobals::createRemoveJob( uploadurl, deletedItems ); } + + + + // Interpreting Jobs + bool interpretListItemsJob( KIO::Job *job, const QString &jobData ) + { return ExchangeGlobals::interpretListItemsJob( this, job, jobData ); } + bool interpretDownloadItemsJob( KIO::Job *job, const QString &jobData ) + { return ExchangeGlobals::interpretAddressBookDownloadItemsJob( this, job, jobData ); } + + + + +/**/ KPIM::GroupwareUploadItem *newUploadItem( KABC::Addressee addr, + KPIM::GroupwareUploadItem::UploadType type ); + + + + + bool getFolderHasSubs( const QDomNode &folderNode ) + { return ExchangeGlobals::getFolderHasSubs( folderNode ); } + KPIM::FolderLister::ContentType getContentType( const QDomNode &folderNode ) + { return ExchangeGlobals::getContentType( folderNode ); } +}; + +} + +#endif diff --git a/kresources/newexchange/exchangecalendaradaptor.cpp b/kresources/newexchange/exchangecalendaradaptor.cpp new file mode 100644 index 000000000..254eb4da1 --- /dev/null +++ b/kresources/newexchange/exchangecalendaradaptor.cpp @@ -0,0 +1,183 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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 "exchangecalendaradaptor.h" +#include "exchangeglobals.h" +#include "exchangeconvertercalendar.h" +#include <davgroupwareglobals.h> +#include <webdavhandler.h> +#include <kdebug.h> +#include <klocale.h> +#include <kio/davjob.h> +#include <libkcal/resourcecached.h> +#include "davcalendaradaptor.h" + +using namespace KCal; + +ExchangeCalendarUploadItem::ExchangeCalendarUploadItem( CalendarAdaptor *adaptor, KCal::Incidence *incidence, KPIM::GroupwareUploadItem::UploadType type ) + : GroupwareUploadItem( type ) +{ + if ( incidence && adaptor ) { + if ( incidence->type() == "Event" ) mItemType = KPIM::FolderLister::Event; + else if ( incidence->type() == "Todo" ) mItemType = KPIM::FolderLister::Todo; + else if ( incidence->type() == "Journal" ) mItemType = KPIM::FolderLister::Journal; +kdDebug()<<"mItemType=="<<mItemType<<endl; + + setUrl( incidence->customProperty( adaptor->identifier(), "storagelocation" ) ); + setUid( incidence->uid() ); + + ExchangeConverterCalendar format; + format.setTimeZone( adaptor->resource()->timeZoneId() ); + mDavData = format.createWebDAV( incidence ); + } +} + +KIO::TransferJob *ExchangeCalendarUploadItem::createUploadJob( KPIM::GroupwareDataAdaptor *adaptor, const KURL &baseUrl ) +{ +kdDebug()<<"ExchangeCalendarUploadItem::createUploadJob, adaptor="<<adaptor<<", URL="<<baseUrl.url()<<endl; + Q_ASSERT( adaptor ); + if ( !adaptor ) return 0; + KURL upUrl( url() ); + adaptor->adaptUploadUrl( upUrl ); + kdDebug() << "Uploading to: " << upUrl.prettyURL() << endl; + + KIO::DavJob *job = KIO::davPropPatch( upUrl, mDavData, false ); + return job; +} + +KIO::TransferJob *ExchangeCalendarUploadItem::createUploadNewJob( KPIM::GroupwareDataAdaptor *adaptor, const KURL &baseurl ) +{ +kdDebug()<<"ExchangeCalendarUploadItem::createUploadNewJob"<<endl; + KURL url( baseurl ); + // TODO: Check if this URL doesn't exist yet! + url.addPath( uid() + ".EML" ); + setUrl( url ); +//url.addPath("newItem.EML"); +kdDebug()<<"Upload path: "<<url.url()<<endl; + return createUploadJob( adaptor, url ); +} + + + +ExchangeCalendarAdaptor::ExchangeCalendarAdaptor() : DavCalendarAdaptor() +{ + /* FIXME Set the progress item messages from the concrete job?*/ + setDownloadProgressMessage( i18n( "Downloading items" ) ); + setUploadProgressMessage( i18n( "Uploading items" ) ); +} + +void ExchangeCalendarAdaptor::customAdaptDownloadUrl( KURL &url ) +{ + url = WebdavHandler::toDAV( url ); +} + +void ExchangeCalendarAdaptor::customAdaptUploadUrl( KURL &url ) +{ + url = WebdavHandler::toDAV( url ); +// url.setPath( url.path() + "/NewItem.EML" ); +} + + +/* Removing items: old version of the exchange resource: If the event is part + of a sequence of recurring event, we need to delete the master! +void ExchangeDelete::findUidSingleMaster( QString const& uid ) +{ + QString query = + "SELECT \"DAV:href\", \"urn:schemas:calendar:uid\"\r\n" + "FROM Scope('shallow traversal of \"\"')\r\n" + "WHERE \"urn:schemas:calendar:uid\" = '" + uid + "'\r\n" + " AND (\"urn:schemas:calendar:instancetype\" = 0\r\n" + " OR \"urn:schemas:calendar:instancetype\" = 1)\r\n"; + + KIO::DavJob* job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql", query, false ); + job->setWindow( mWindow ); + connect(job, SIGNAL(result( KIO::Job * )), this, SLOT(slotFindUidResult(KIO::Job *))); +} + +*/ + + +QString ExchangeCalendarAdaptor::defaultNewItemName( KPIM::GroupwareUploadItem *item ) { + if ( item ) return item->uid()+".EML"; + else return QString::null; +} + +KPIM::GroupwareUploadItem *ExchangeCalendarAdaptor::newUploadItem( KCal::Incidence*it, + KPIM::GroupwareUploadItem::UploadType type ) +{ + return new ExchangeCalendarUploadItem( this, it, type ); +} + +bool ExchangeCalendarAdaptor::interpretUploadJob( KIO::Job *job, const QString &/*jobData*/ ) +{ + kdDebug(7000) << "ExchangeCalendarAdaptor::interpretUploadJob " << endl; + KIO::DavJob *davjob = dynamic_cast<KIO::DavJob*>(job); + bool error = job->error(); + const QString err = job->errorString(); + + if ( davjob ) { + if ( error ) { + emit itemUploadError( davjob->url(), err ); + return false; + } else { + QDomDocument doc( davjob->response() ); + // TODO: extract the href and the items that got a 404. If there's + // something important among them, issue the "usual" not-all-settings-uploaded + // warning to the user. + + // We don't know the local id here (and we don't want to extract it from + // the idMapper, that's the task of the receiver + emit itemUploaded( uidFromJob( job ), davjob->url() ); + } + return true; + } else { + return false; + } +} + +bool ExchangeCalendarAdaptor::interpretUploadNewJob( KIO::Job *job, const QString &/*jobData*/ ) +{ +// TODO: How does the incidence mapper know the old/new ids??? + kdDebug(7000) << "ExchangeCalendarAdaptor::interpretUploadNewJob " << endl; + KIO::DavJob *davjob = dynamic_cast<KIO::DavJob*>(job); + bool error = job->error(); + const QString err = job->errorString(); + + if ( davjob ) { + if ( error ) { + emit itemUploadNewError( idMapper()->localId( davjob->url().path() ), err ); + return false; + } else { + QDomDocument doc( davjob->response() ); + // TODO: extract the href and the items that got a 404. If there's + // something important among them, issue the "usual" not-all-settings-uploaded + // warning to the user. + + // We don't know the local id here (and we don't want to extract it from + // the idMapper, that's the task of the receiver + emit itemUploadedNew( uidFromJob( job ), davjob->url() ); + } + return true; + } else { + return false; + } +} + diff --git a/kresources/newexchange/exchangecalendaradaptor.h b/kresources/newexchange/exchangecalendaradaptor.h new file mode 100644 index 000000000..7e772302d --- /dev/null +++ b/kresources/newexchange/exchangecalendaradaptor.h @@ -0,0 +1,99 @@ + /* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + + 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 KPIM_EXCHANGECALENDARADAPTOR_H +#define KPIM_EXCHANGECALENDARADAPTOR_H + +#include "exchangeglobals.h" + +#include <groupwareresourcejob.h> +#include <davcalendaradaptor.h> +#include <kurl.h> +#include <qdom.h> + +namespace KCal { + +class Incidence; + +class ExchangeCalendarUploadItem : public KPIM::GroupwareUploadItem +{ + public: + ExchangeCalendarUploadItem( CalendarAdaptor *adaptor, KCal::Incidence *incidence, UploadType type ); + virtual ~ExchangeCalendarUploadItem() {} + virtual KIO::TransferJob *createUploadNewJob( + KPIM::GroupwareDataAdaptor *adaptor, const KURL &baseurl ); + virtual KIO::TransferJob *createUploadJob( + KPIM::GroupwareDataAdaptor *adaptor, const KURL &url ); + + protected: + ExchangeCalendarUploadItem( UploadType type ) : KPIM::GroupwareUploadItem( type ) {} + QDomDocument mDavData; +}; + +class ExchangeCalendarAdaptor : public DavCalendarAdaptor +{ + public: + ExchangeCalendarAdaptor(); + + void customAdaptDownloadUrl( KURL &url ); + void customAdaptUploadUrl( KURL &url ); + QString mimeType() const { return "message/rfc822"; } + QCString identifier() const { return "KCalResourceExchange"; } + QString defaultNewItemName( KPIM::GroupwareUploadItem *item ); + long flags() const { return GWResBatchDelete; } + + + + // Creating Jobs + KIO::Job *createListFoldersJob( const KURL &url ) + { return ExchangeGlobals::createListFoldersJob( url ); } + KIO::TransferJob *createListItemsJob( const KURL &url ) + { return ExchangeGlobals::createListItemsJob( url ); } + KIO::TransferJob *createDownloadJob( const KURL &url, KPIM::FolderLister::ContentType ctype ) + { return ExchangeGlobals::createDownloadJob( this, url, ctype ); } + KIO::Job *createRemoveJob( const KURL &uploadurl, const KPIM::GroupwareUploadItem::List &deletedItems ) + { return ExchangeGlobals::createRemoveJob( uploadurl, deletedItems ); } + + + // Interpreting Jobs + bool interpretListItemsJob( KIO::Job *job, const QString &jobData ) + { return ExchangeGlobals::interpretListItemsJob( this, job, jobData ); } + bool interpretDownloadItemsJob( KIO::Job *job, const QString &jobData ) + { return ExchangeGlobals::interpretCalendarDownloadItemsJob( this, job, jobData ); } + bool interpretUploadJob( KIO::Job *job, const QString &/*jobData*/ ); + bool interpretUploadNewJob( KIO::Job *job, const QString &/*jobData*/ ); + + + + KPIM::GroupwareUploadItem *newUploadItem( KCal::Incidence*it, + KPIM::GroupwareUploadItem::UploadType type ); + + + + bool getFolderHasSubs( const QDomNode &folderNode ) + { return ExchangeGlobals::getFolderHasSubs( folderNode ); } + KPIM::FolderLister::ContentType getContentType( const QDomNode &folderNode ) + { return ExchangeGlobals::getContentType( folderNode ); } +}; + +} + +#endif diff --git a/kresources/newexchange/exchangeconvertercalendar.cpp b/kresources/newexchange/exchangeconvertercalendar.cpp new file mode 100644 index 000000000..bc0481daf --- /dev/null +++ b/kresources/newexchange/exchangeconvertercalendar.cpp @@ -0,0 +1,820 @@ +/* + This file is part of the exchange resource. + Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + Parts are derived from the old libkpimexchange library: + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.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 "exchangeconvertercalendar.h" +#include <webdavhandler.h> +#include <libkcal/incidence.h> +#include <libkcal/event.h> +#include <libkcal/journal.h> +#include <libkcal/todo.h> +#include <libkcal/icalformat.h> +#include <libemailfunctions/email.h> + +#include <kdebug.h> + +using namespace KCal; + +#define TaskNamespace1 "http://schemas.microsoft.com/mapi/id/{00062003-0000-0000-C000-000000000046}/" +#define TaskProp_Status "0x00008101" +#define TaskProp_PercentCompleted "0x00008102" +#define TaskProp_DtStart "0x00008104" +#define TaskProp_DtDue "0x00008105" +#define TaskProp_Duration "0x00008106" +#define TaskProp_CompletionDate "0x0000810f" +#define TaskProp_IsCompleted "0x0000811C" +#define TaskProp_Owner "0x0000811F" +#define TaskProp_DoesRecur "0x00008126" + +#define TaskNamespace2 "http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/" +#define TaskProp_ReminderTime "0x00008502" +#define TaskProp_ReminderSet "0x00008503" +#define TaskProp_ReminderPlaySound "0x0000851E" +#define TaskProp_ReminderSoundFile "0x0000851F" +#define TaskProp_ContactNames "0x0000853A" + + +ExchangeConverterCalendar::ExchangeConverterCalendar() +{ +} + +void ExchangeConverterCalendar::setTimeZone( const QString &id ) +{ + // kdDebug() << "Setting timezone to: " << id << endl; + mFormat.setTimeZone( id, true ); +} + +#define propertyDAV( prop ) \ + WebdavHandler::addElement( doc, root, "d:"prop ) +#define propertyNS( ns, prop ) \ + WebdavHandler::addElementNS( doc, root, ns, prop ) +#define propertyCalendar( prop ) \ + WebdavHandler::addElement( doc, root, "c:"prop ) +#define propertyHTTPMail( prop ) \ + WebdavHandler::addElement( doc, root, "m:"prop ) +#define propertyMailHeader( prop ) \ + WebdavHandler::addElement( doc, root, "h:"prop ) +#define property( prop ) \ + WebdavHandler::addElement( doc, root, prop ) + +void ExchangeConverterCalendar::createRequestIncidence( QDomDocument &doc, QDomElement &root ) +{ + propertyDAV( "contentclass" ); + propertyDAV( "getcontenttype" ); + propertyNS( "http://schemas.microsoft.com/exchange/", "outlookmessageclass" ); + propertyDAV( "getetag" ); + propertyDAV( "href" ); + propertyDAV( "isreadonly" ); + propertyNS( "http://schemas.microsoft.com/repl/", "repl-uid" ); + propertyHTTPMail( "subject" ); + propertyHTTPMail( "textdescription" ); + propertyHTTPMail( "date" ); + propertyDAV( "comment" ); + propertyNS( "urn:schemas-microsoft-com:office:office", "Keywords" ); + propertyNS( "http://schemas.microsoft.com/exchange/", "sensitivity" ); + propertyHTTPMail( "priority" ); + propertyHTTPMail( "from" ); + propertyHTTPMail( "to" ); + propertyHTTPMail( "cc" ); + propertyHTTPMail( "bcc" ); + propertyHTTPMail( "hasattachment" ); +} + +void ExchangeConverterCalendar::createRequestAppointment( QDomDocument &doc, QDomElement &root ) +{ + createRequestIncidence( doc, root ); + QDomAttr att_c = doc.createAttribute( "xmlns:c" ); + att_c.setValue( "urn:schemas:calendar:" ); + doc.documentElement().setAttributeNode( att_c ); + propertyCalendar( "uid" ); + propertyCalendar( "created" ); + propertyCalendar( "lastmodified" ); + propertyCalendar( "dtstamp" ); + propertyCalendar( "sequence" ); + propertyCalendar( "location" ); + propertyCalendar( "busystatus" ); + propertyCalendar( "transparent" ); + propertyCalendar( "timezone" ); + propertyCalendar( "alldayevent" ); + propertyCalendar( "dtstart" ); + propertyCalendar( "dtend" ); + propertyCalendar( "duration" ); + propertyCalendar( "rrule" ); + propertyCalendar( "rdate" ); + propertyCalendar( "exrule" ); + propertyCalendar( "exdate" ); + propertyCalendar( "recurrenceid" ); + propertyCalendar( "instancetype" ); + propertyCalendar( "reminderoffset" ); + propertyCalendar( "resources" ); +} + +#define propertyTask1( prop ) \ + WebdavHandler::addElement( doc, props, "t1:"prop ) +#define propertyTask2( prop ) \ + WebdavHandler::addElement( doc, props, "t2:"prop ) + +void ExchangeConverterCalendar::createRequestTask( QDomDocument &doc, QDomElement &props ) +{ + createRequestIncidence( doc, props ); + + QDomElement root = doc.documentElement(); + + QDomAttr att_t1 = doc.createAttribute( "xmlns:t1" ); + att_t1.setValue( TaskNamespace1 ); + root.setAttributeNode( att_t1 ); + + QDomAttr att_t2 = doc.createAttribute( "xmlns:t2" ); + att_t2.setValue( TaskNamespace2 ); + root.setAttributeNode( att_t2 ); + + // TODO: Insert the correct namespaces here: +// propertyTask1( TaskProp_UID ); + propertyDAV( "creationdate" ); + propertyDAV( "getlastmodified" ); + propertyTask1( TaskProp_Owner ); + propertyTask2( TaskProp_ContactNames ); + propertyTask1( TaskProp_DtStart ); + propertyTask1( TaskProp_DtDue ); + propertyTask1( TaskProp_Duration ); + propertyTask1( TaskProp_IsCompleted ); + propertyTask1( TaskProp_PercentCompleted ); + propertyTask1( TaskProp_CompletionDate ); + propertyTask1( TaskProp_DoesRecur ); + // What to do about recurrence rules? + propertyTask2( TaskProp_ReminderSet ); + propertyTask2( TaskProp_ReminderTime ); + propertyTask2( TaskProp_ReminderPlaySound ); + propertyTask2( TaskProp_ReminderSoundFile ); + propertyTask1( TaskProp_Status ); +} +#undef propertyTask1 +#undef propertyTask2 + +void ExchangeConverterCalendar::createRequestJournal( QDomDocument &doc, QDomElement &root ) +{ + createRequestIncidence( doc, root ); + propertyDAV( "uid" ); + propertyDAV( "creationdate" ); + propertyDAV( "getlastmodified" ); +} +#undef propertyDAV +#undef propertyNS +#undef propertyCalendar +#undef propertyHTTPMail +#undef propertyMailHeader +#undef property + +bool ExchangeConverterCalendar::readTZ( const QDomElement &node, Incidence */*incidence*/ ) +{ + QString timezoneid; + if ( WebdavHandler::extractString( node, "timezoneid", timezoneid ) ) { + // kdDebug() << "DEBUG: timezoneid = " << timezoneid << endl; + } + + QString timezone; + if ( WebdavHandler::extractString( node, "timezone", timezone ) ) { + // kdDebug() << "DEBUG: timezone = " << timezone << endl; + } + + // TODO: +/* // mFormat is used for parsing recurrence rules. + QString localTimeZoneId; + if ( mCalendar ) { + mFormat.setTimeZone( mCalendar->timeZoneId(), !mCalendar->isLocalTime() ); + localTimeZoneId = mCalendar->timeZoneId(); + } else { + localTimeZoneId = "UTC"; + // If no mCalendar, stay in UTC + } +*/ + return true; +} + +bool ExchangeConverterCalendar::readIncidence( const QDomElement &node, Incidence *incidence ) +{ +kdDebug()<<"ExchangeConverterCalendar::readIncidencd"<<endl; + QDateTime tmpdt; + bool tmpbool; + QString tmpstr; + long tmplng; + QStringList tmplst; + + readTZ( node, incidence ); + + if ( WebdavHandler::extractString( node, "getetag", tmpstr ) ) + incidence->setCustomProperty( "KDEPIM-Exchange-Resource", "fingerprint", tmpstr ); + if ( WebdavHandler::extractString( node, "href", tmpstr ) ) + incidence->setCustomProperty( "KDEPIM-Exchange-Resource", "href", tmpstr ); + + // FIXME: use repl-uid as scheduling id? + if ( WebdavHandler::extractString( node, "textdescription", tmpstr ) ) + incidence->setDescription( tmpstr ); + if ( WebdavHandler::extractString( node, "subject", tmpstr ) ) + incidence->setSummary( tmpstr ); + if ( WebdavHandler::extractStringList( node, "Keywords", tmplst ) ) + incidence->setCategories( tmplst ); + + // Use "created" or "creationdate"? + if ( WebdavHandler::extractBool( node, "isreadonly" , tmpbool ) ) + incidence->setReadOnly( tmpbool ); + + // FIXME: Ignore the comment for now + + // Exchange sentitivity values: + // 0 None, 1 Personal, 2 Private, 3 Company Confidential + if ( WebdavHandler::extractLong( node, "sensitivity", tmplng ) ) { + switch( tmplng ) { + case 0: incidence->setSecrecy( KCal::Incidence::SecrecyPublic ); break; + case 1: + case 2: incidence->setSecrecy( KCal::Incidence::SecrecyPrivate ); break; + case 3: incidence->setSecrecy( KCal::Incidence::SecrecyConfidential ); break; + default: kdWarning() << "Unknown sensitivity: " << tmplng << endl; + } + } + + if ( WebdavHandler::extractBool( node, "hasattachment", tmpbool ) && tmpbool ) { + // FIXME: Extract attachments... + } + + if ( WebdavHandler::extractLong( node, "priority", tmplng ) ) + incidence->setPriority( tmplng ); + + // FIXME: Use the urn:schemes:httpmail:date property for what? + + // Organizer, required and optional Attendees: + if ( WebdavHandler::extractString( node, "from", tmpstr ) ) + incidence->setOrganizer( tmpstr ); + if ( WebdavHandler::extractString( node, "to", tmpstr ) ) { + QStringList atts( KPIM::splitEmailAddrList( tmpstr ) ); + for ( QStringList::Iterator it = atts.begin(); it != atts.end(); ++it ) { + QString name, email; + KPIM::getNameAndMail( *it, name, email ); + Attendee *att = new Attendee( name, email ); + att->setRole( KCal::Attendee::ReqParticipant ); + // FIXME: Retrieve the other attendee properties somehow... + // urn:schemas:calendar:method + // urn:schemas:calendar:responserequested + // urn:schemas:calendar:meetingstatus + // urn:schemas:calendar:replytime + incidence->addAttendee( att ); + } + } + if ( WebdavHandler::extractString( node, "cc", tmpstr ) ) { + QStringList atts( KPIM::splitEmailAddrList( tmpstr ) ); + for ( QStringList::Iterator it = atts.begin(); it != atts.end(); ++it ) { + QString name, email; + KPIM::getNameAndMail( *it, name, email ); + Attendee *att = new Attendee( name, email ); + att->setRole( KCal::Attendee::OptParticipant ); + // FIXME: Retrieve the other attendee properties somehow... + // urn:schemas:calendar:method + // urn:schemas:calendar:responserequested + // urn:schemas:calendar:meetingstatus + // urn:schemas:calendar:replytime + incidence->addAttendee( att ); + } + } + + return true; +} + +/* FIXME: Handle recurrences +void ExchangeDownload::handleRecurrence( QString uid ) +{ + // kdDebug() << "Handling recurrence info for uid=" << uid << endl; + QString query = + "SELECT \"DAV:href\", \"urn:schemas:calendar:instancetype\"\r\n" + "FROM Scope('shallow traversal of \"\"')\r\n" + "WHERE \"urn:schemas:calendar:uid\" = '" + uid + "'\r\n" + " AND (\"urn:schemas:calendar:instancetype\" = 1)\r\n"; +// " OR \"urn:schemas:calendar:instancetype\" = 3)\r\n" // FIXME: exception are not handled + + // kdDebug() << "Exchange master query: " << endl << query << endl; + + KIO::DavJob* job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql", + query, false ); + KIO::Scheduler::scheduleJob( job ); + job->setWindow( mWindow ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotMasterResult( KIO::Job * ) ) ); +} +*/ + +bool ExchangeConverterCalendar::readEvent( const QDomElement &node, Event *event ) +{ + if ( !readIncidence( node, event ) ) return false; +kdDebug()<<"ExchangeConverterCalendar::readEvent"<<endl; + + QDateTime tmpdt; + QString tmpstr; + long tmplng; + bool tmpbool; + + // The UID is absolutely required! + if ( WebdavHandler::extractString( node, "uid", tmpstr ) ) { + event->setUid( tmpstr ); + } else { +kdDebug()<<"ExchangeConverterCalendar::readIncidence: ERROR: No UID given"<<endl; + return false; + } + if ( WebdavHandler::extractDateTime( node, "created", tmpdt ) ) + event->setCreated( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + if ( WebdavHandler::extractDateTime( node, "lastmodified", tmpdt ) ) + event->setLastModified( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + // FIXME: Retrieve time zone: "timezone" + // FIXME: Use the "recurrenceid" prop for the recurrenceId of the event (which is protected!) + + // FIXME: Retrieve MICROSOFT-CDO-* tags first + + if ( WebdavHandler::extractLong( node, "sequence", tmplng ) ) + event->setRevision( tmplng ); + + if ( WebdavHandler::extractString( node, "location", tmpstr ) ) + event->setLocation( tmpstr ); + + // FIXME: Use "organizer" here instead of the From: person? +/* if ( WebdavHandler::extractString( node, "organizer", tmpstr ) ) + incidence->setOrganizer( tmpstr );*/ + + if ( WebdavHandler::extractDateTime( node, "dtstart", tmpdt ) ) { + event->setDtStart( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + } + + bool allDay = false; + if ( WebdavHandler::extractBool( node, "alldayevent", allDay ) ) + event->setFloats( allDay ); + + if ( WebdavHandler::extractLong( node, "duration", tmplng ) ) { + if (allDay) + tmplng--; // Otherwise event extends into next day + event->setDuration( tmplng ); + // kdDebug() << "DURATION " << tmplng << "\n"; + } else if ( WebdavHandler::extractDateTime( node, "dtend", tmpdt ) ) { + event->setDtEnd( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + } + + // FIXME: Here we have two different props for the same thing?!?!? + if ( WebdavHandler::extractLong( node, "transparent", tmplng ) ) + event->setTransparency( tmplng>0 ? Event::Transparent : Event::Opaque ); + if ( WebdavHandler::extractString( node, "busystatus", tmpstr ) ) { + if ( tmpstr == "FREE" ) + event->setTransparency( KCal::Event::Transparent ); + if ( tmpstr == "BUSY" ) + event->setTransparency( KCal::Event::Opaque ); + } + + if ( WebdavHandler::extractLong( node, "reminderoffset", tmplng ) ) { + // Duration before event in seconds + KCal::Duration offset( -tmplng ); + KCal::Alarm *alarm = event->newAlarm(); + alarm->setStartOffset( offset ); + alarm->setEnabled( true ); + alarm->setType( KCal::Alarm::Display); + // TODO: multiple alarms; + } + + + if ( WebdavHandler::extractString( node, "rrule", tmpstr ) && !tmpstr.isEmpty() ) { + kdDebug() << "Got rrule: " << tmpstr << endl; + // Timezone should be handled automatically + // because we used mFormat.setTimeZone() earlier + // FIXME: Implement this using the format! + RecurrenceRule *rrule = event->recurrence()->defaultRRule( true ); + if ( ! mFormat.fromString( rrule, tmpstr ) ) { + kdError() << "ERROR parsing rrule " << tmpstr << endl; + event->recurrence()->addRRule( rrule ); + } + } + + QStringList tmplst; + if ( WebdavHandler::extractStringList( node, "exdate", tmplst ) ) { + QStringList::Iterator it = tmplst.begin(); + KCal::DateList exdates; + for ( ; it != tmplst.end(); ++it ) { + exdates.append( /*utcAsZone(*/ QDateTime::fromString( *it, Qt::ISODate )/*, + localTimeZoneId )*/.date() ); + } + event->recurrence()->setExDates( exdates ); + } + // FIXME: use rdate and exrule! +/* FIXME: Recurring events, they are split up + QDomElement instancetypeElement = prop.namedItem( "instancetype" ).toElement(); + if ( instancetypeElement.isNull() ) { + kdError() << "Error: no instance type in Exchange server reply" << endl; + continue; + } + int instanceType = instancetypeElement.text().toInt(); + //kdDebug() << "Instance type: " << instanceType << endl; + + if ( recurrence && instanceType > 0 ) { + QDomElement uidElement = prop.namedItem( "uid" ).toElement(); + if ( uidElement.isNull() ) { + kdError() << "Error: no uid in Exchange server reply" << endl; + continue; + } + QString uid = uidElement.text(); + if ( ! m_uids.contains( uid ) ) { + m_uids[uid] = 1; + handleRecurrence(uid); + successCount++; + } + continue; + } +*/ + + + // FIXME: read the resources from the "resources" tag + + // FIXME: Custom fields not yet implemented + return true; +} + +bool ExchangeConverterCalendar::readTodo( const QDomElement &node, Todo *todo ) +{ + if ( !readIncidence( node, todo ) ) return false; +kdDebug()<<"ExchangeConverterCalendar::readTodo"<<endl; + + // FIXME: Retrieve time zone: "timezone" + // FIXME: What to with TaskProp_Owner and TaskProp_ContactNames? + + QDateTime tmpdt; + float tmpfloat; + long tmplong; + bool tmpbool; + QString tmpstr; + + // The UID is absolutely required! + // FIXME: Which field shall be used as uid??? +/* if ( WebdavHandler::extractString( node, "uid", tmpstr ) ) { + todo->setUid( tmpstr ); + } else { +kdDebug()<<"ExchangeConverterCalendar::readIncidence: ERROR: No UID given"<<endl; + return false; + }*/ +// if ( WebdavHandler::extractDateTime( node, "created", tmpdt ) ) +/* FIXME: creation and last modification dates: + if ( WebdavHandler::extractDateTime( node, "creationdate", tmpdt ) ) + incidence->setCreated( tmpdt ); + if ( WebdavHandler::extractDateTime( node, "getlastmodified", tmpdt ) ) + incidence->setLastModified( tmpdt );*/ + + if ( WebdavHandler::extractDateTime( node, TaskProp_DtStart, tmpdt ) ) + todo->setDtStart( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + if ( WebdavHandler::extractDateTime( node, TaskProp_DtDue, tmpdt ) ) + todo->setDtDue( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + if ( WebdavHandler::extractLong( node, TaskProp_Duration, tmplong ) ) + todo->setDuration( tmplong ); + + if ( WebdavHandler::extractBool( node, TaskProp_IsCompleted, tmpbool ) && tmpbool ) { + todo->setCompleted( tmpbool ); + if ( tmpbool && WebdavHandler::extractDateTime( node, TaskProp_CompletionDate, tmpdt ) ) { + todo->setCompleted( WebdavHandler::utcAsZone( tmpdt, mFormat.timeZoneId() ) ); + } + } + if ( WebdavHandler::extractFloat( node, TaskProp_PercentCompleted, tmpfloat ) ) + todo->setPercentComplete( (int)(tmpfloat*100) ); + + // FIXME: Recurrence, using TaskProp_DoesRecur + // What to do about recurrence rules? + + // FIXME: Reminders, use TaskProp_ReminderSet, TaskProp_ReminderTime, + // TaskProp_ReminderPlaySound, TaskProp_ReminderSoundFile, TaskProp_Status + // But how do I get the offset? + + return true; +} + +bool ExchangeConverterCalendar::readJournal( const QDomElement &node, Journal *journal ) +{ + if ( !readIncidence( node, journal ) ) return false; +kdDebug()<<"ExchangeConverterCalendar::readJournal"<<endl; + QDateTime tmpdt; + QString tmpstr; + // The UID is absolutely required! + // FIXME: Which field shall be used as UID? + if ( WebdavHandler::extractString( node, "uid", tmpstr ) ) { + journal->setUid( tmpstr ); + } else { +kdDebug()<<"ExchangeConverterCalendar::readJournal: ERROR: No UID given"<<endl; + return false; + } +/* FIXME: creation and last modification times: + if ( WebdavHandler::extractDateTime( node, "created", tmpdt ) ) + incidence->setCreated( tmpdt ); + if ( WebdavHandler::extractDateTime( node, "lastmodified", tmpdt ) ) + incidence->setLastModified( tmpdt );*/ + + if ( WebdavHandler::extractDateTime( node, "date", tmpdt ) ) + journal->setDtStart( tmpdt ); + return true; +} + +Incidence::List ExchangeConverterCalendar::parseWebDAV( const QDomDocument& davdata ) +{ + QDomElement prop = davdata.documentElement().namedItem( "response" ) + .namedItem( "propstat" ).namedItem( "prop" ).toElement(); + if ( prop.isNull() ) return Incidence::List(); + + QString contentclass; + bool success = WebdavHandler::extractString( prop, "contentclass", contentclass ); + if ( !success ) return Incidence::List(); + + Incidence *incidence = 0; + success = false; + if ( contentclass == "urn:content-classes:appointment" ) { + Event *event = new Event(); + success = readEvent( prop, event ); + incidence = event; + } else if ( contentclass == "urn:content-classes:task" ) { + Todo *todo = new Todo(); + success = readTodo( prop, todo ); + incidence = todo; + } else if ( contentclass == "urn:content-classes:journal" || + contentclass == "urn:content-classes:message" ) { + Journal *journal = new Journal(); + success = readJournal( prop, journal ); + incidence = journal; + } + + Incidence::List list; + if ( success ) { + list.append( incidence ); + } + return list; +} + + +#define domDavProperty( name, value ) \ + WebdavHandler::addElement( mDoc, mElement, "d:"name, value ) +#define domProperty( NS, name, value ) \ + WebdavHandler::addElementNS( mDoc, mElement, NS, name, value ) +#define domCalendarProperty( name, value ) \ + WebdavHandler::addElement( mDoc, mElement, "c:"name, value ) +#define domHTTPMailProperty( name, value ) \ + WebdavHandler::addElement( mDoc, mElement, "m:"name, value ) +#define domMailHeaderProperty( name, value ) \ + WebdavHandler::addElement( mDoc, mElement, "h:"name, value ) + + + + +class ExchangeConverterCalendar::createWebDAVVisitor : public IncidenceBase::Visitor +{ + public: + createWebDAVVisitor() : Visitor() {} + bool act( QDomDocument doc, QDomElement el, IncidenceBase *incidence, const QString &timeZoneId ) + { + mDoc = doc; + mElement = el; + mTimeZoneId = timeZoneId; + return incidence->accept( *this ); + } + protected: + void addBoolProp( QDomElement &el ) { el.setAttribute( "b:dt", "boolean" ); } + void addDateProp( QDomElement &el ) { el.setAttribute( "b:dt", "dateTime.tz" ); } + void addFloatProp( QDomElement &el ) { el.setAttribute( "b:dt", "float" ); } + void addIntProp( QDomElement &el ) { el.setAttribute( "b:dt", "int" ); } + QString timePropString( const QDateTime &dt ) { return dt.toString( Qt::ISODate )+"Z"; } + + bool visitIncidence( Incidence *incidence ) + { + QString tmpstr; + domDavProperty( "isreadonly", (incidence->isReadOnly())?"1":"0" ); + // FIXME: scheduling ID +// domProperty( "http://schemas.microsoft.com/repl/", "repl-uid", ??? ); + domHTTPMailProperty( "subject", incidence->summary() ); + domHTTPMailProperty( "textdescription", incidence->description() ); + // FIXME: timestampt, comments and categories +// domHTTPMailProperty( "date", ??? ); // timestamp not available in libkcal +// domDavProperty( "comment", incidence->comments() ); // libkcal has a QStringlist, not one string +// domProperty( "urn:schemas-microsoft-com:office:office", "Keywords", ??? ); // It's a <v>entyr1</v><v>entry2</v> String list! + tmpstr = QString::null; + switch ( incidence->secrecy() ) { + case KCal::Incidence::SecrecyPublic: tmpstr = "0"; break; + case KCal::Incidence::SecrecyPrivate: tmpstr = "2"; break; + case KCal::Incidence::SecrecyConfidential: tmpstr = "3"; break; + default: break; + } + if ( !tmpstr.isEmpty() ) + domProperty( "http://schemas.microsoft.com/exchange/", "sensitivity", tmpstr ); + + domHTTPMailProperty( "priority", QString::number(incidence->priority()) ); + + domMailHeaderProperty( "from", incidence->organizer().fullName() ); + + // Attendees: + tmpstr = QString::null; + QStringList reqattnames; + QStringList optattnames; + Attendee::List atts = incidence->attendees(); + for ( Attendee::List::Iterator it = atts.begin(); it != atts.end(); ++it ) { + switch ( (*it)->role() ) { + case KCal::Attendee::Chair: + case KCal::Attendee::ReqParticipant: + reqattnames << (*it)->fullName(); + break; + case KCal::Attendee::OptParticipant: + case KCal::Attendee::NonParticipant: + optattnames << (*it)->fullName(); + break; + default: break; + } + } + + domMailHeaderProperty( "to", reqattnames.join(", ") ); + + domMailHeaderProperty( "cc", optattnames.join(", ") ); + + // FIXME: Attachments: propertyHTTPMail( "hasattachment" ); + + return true; + } + bool visit( Event *event ) + { + if ( !visitIncidence(event) ) return false; + + QDomAttr att_c = mDoc.createAttribute( "xmlns:c" ); + att_c.setValue( "urn:schemas:calendar:" ); + mDoc.documentElement().setAttributeNode( att_c ); + + domDavProperty( "contentclass", "urn:content-classes:appointment" ); + domProperty( "http://schemas.microsoft.com/exchange/", + "outlookmessageclass", "IPM.Appointment" ); + domCalendarProperty( "uid", event->uid() ); + QDomElement el = domCalendarProperty( "created", timePropString( WebdavHandler::zoneAsUtc( event->created(), mTimeZoneId ) ) ); + addDateProp( el ); + el = domCalendarProperty( "lastmodified", timePropString( WebdavHandler::zoneAsUtc( event->lastModified(), mTimeZoneId ) ) ); + addDateProp( el ); + // FIXME: domCalendarProperty( "dtstamp", ??); +// FIXME: domCalendarProperty( "sequence", event->sequence() ); + domCalendarProperty( "location", event->location() ); + + QString tmpstr( QString::null ); + switch ( event->transparency() ) { + case KCal::Event::Transparent: tmpstr = "FREE"; break; + case KCal::Event::Opaque: tmpstr = "BUSY"; break; + } + if ( !tmpstr.isEmpty() ) + domCalendarProperty( "busystatus", tmpstr ); +// FIXME: What do do with the "transparent" property? +// FIXME: Use the "timezone" property... + domCalendarProperty( "alldayevent", event->doesFloat()?"1":"0" ); + el = domCalendarProperty( "dtstart", timePropString( WebdavHandler::zoneAsUtc( event->dtStart(), mTimeZoneId ) ) ); + addDateProp( el ); + if ( event->hasEndDate() ) { + el = domCalendarProperty( "dtend", timePropString( WebdavHandler::zoneAsUtc( event->dtEnd(), mTimeZoneId ) ) ); + addDateProp( el ); + } else { + domCalendarProperty( "duration", QString::number( event->duration() ) ); + } + // FIXME: Convert the recurrence rule to a string: + if ( event->doesRecur() ) { +// tmpstr = event->recurrence()..... +// domCalendarProperty( "rrule", tmpstr ); + // FIXME: Use "rdate" and "exrule" + // FIXME: Use "exdate", what's the syntax? + // FIXME: use the "instancetype" property + } + // FIXME: RecurrenceID is protected! +// domCalendarProperty( "recurrenceid", event->recurrenceId() ); + // FIXME: "reminderoffset" + // FIXME: "resources" Alarm::List alarms = event->alarms(); + + Alarm::List::ConstIterator it; + Alarm::List alarms = event->alarms(); + for( it = alarms.begin(); it != alarms.end(); ++it ) { + if ((*it)->hasStartOffset()) { + domCalendarProperty( "reminderoffset", QString::number( (*it)->startOffset().asSeconds() * -1 ) ); + } else { + kdDebug() << "ExchangeConverterCalendar::createWebDAVVisitor: Alarm type not supported\n"; + } + } + + return true; + } + bool visit( Todo *todo ) + { + if ( !visitIncidence(todo) ) return false; + + QDomAttr att_t1 = mDoc.createAttribute( "xmlns:t1" ); + att_t1.setValue( TaskNamespace1 ); + mDoc.documentElement().setAttributeNode( att_t1 ); + + QDomAttr att_t2 = mDoc.createAttribute( "xmlns:t2" ); + att_t2.setValue( TaskNamespace2 ); + mDoc.documentElement().setAttributeNode( att_t2 ); + + + domDavProperty( "contentclass", "urn:content-classes:task" ); + domProperty( "http://schemas.microsoft.com/exchange/", + "outlookmessageclass", "IPM.Task" ); + +/* FIXME: + domCalendarProperty( "uid", todo->uid() ); + domCalendarProperty( "created", todo->created().toString( Qt::ISODate ) ); + domCalendarProperty( "lastmodified", todo->lastModified().toString( Qt::ISODate ) );*/ + // TODO +/*propertyTask1( TaskProp_Owner ); + propertyTask2( TaskProp_ContactNames ); + propertyTask1( TaskProp_DtStart ); + propertyTask1( TaskProp_DtDue ); + propertyTask1( TaskProp_Duration ); + propertyTask1( TaskProp_IsCompleted ); + propertyTask1( TaskProp_PercentCompleted ); + propertyTask1( TaskProp_CompetionDate ); + propertyTask1( TaskProp_DoesRecur ); + // What to do about recurrence rules? + propertyTask2( TaskProp_ReminderSet ); + propertyTask2( TaskProp_ReminderTime ); + propertyTask2( TaskProp_ReminderPlaySound ); + propertyTask2( TaskProp_ReminderSoundFile ); + propertyTask1( TaskProp_Status );*/ + return true; + } + bool visit( Journal *journal ) + { + if ( !visitIncidence(journal) ) return false; + domDavProperty( "contentclass", "urn:content-classes:journal" ); + domProperty( "http://schemas.microsoft.com/exchange/", + "outlookmessageclass", "IPM.Journal" ); +/* FIXME: + domCalendarProperty( "uid", todo->uid() ); + domCalendarProperty( "created", todo->created().toString( Qt::ISODate ) ); + domCalendarProperty( "lastmodified", todo->lastModified().toString( Qt::ISODate ) );*/ + // TODO + return true; + } + + protected: + QDomDocument mDoc; + QDomElement mElement; + QString mTimeZoneId; +}; + +// Prefixes for the namespaces: +// d... DAV: +// b... urn:schemas-microsoft-com:datatypes +// c... calendar +// m... httpmail +// h... httpheader +// p... mapi +// o... office +// + +QDomDocument ExchangeConverterCalendar::createWebDAV( Incidence *incidence ) +{ + // TODO + QDomDocument doc; + QDomElement root = WebdavHandler::addDavElement( doc, doc, "d:propertyupdate" ); + QDomElement set = WebdavHandler::addElement( doc, root, "d:set" ); + QDomElement prop = WebdavHandler::addElement( doc, set, "d:prop" ); + + QDomAttr att_b = doc.createAttribute( "xmlns:b" ); + att_b.setValue( "urn:schemas-microsoft-com:datatypes" ); + root.setAttributeNode( att_b ); + + QDomAttr att_h = doc.createAttribute( "xmlns:h" ); + att_h.setValue( "urn:schemas:mailheader:" ); + root.setAttributeNode( att_h ); + + QDomAttr att_m = doc.createAttribute( "xmlns:m" ); + att_m.setValue( "urn:schemas:httpmail:" ); + root.setAttributeNode( att_m ); + +// QDomAttr att1 = doc.createAttributeNS( "do:whatever:you:like", "x:attname"); +// att1.setValue( "value" ); +// prop.setAttributeNodeNS( att1 ); +// root.setAttributeNodeNS( att1 ); +// set.setAttributeNode( att1 ); +// // prop.setAttributeNS ( "xmlns:b", "xmlns:b", "urn:schemas-microsoft-com:datatypes" ); + + ExchangeConverterCalendar::createWebDAVVisitor v; + v.act( doc, prop, incidence, mFormat.timeZoneId() ); + kdDebug() << "ExchangeConverterCalendar::createWebDAVVisitor=" << doc.toString() << "\n"; + + return doc; +} +#undef domDavProperty +#undef domProperty +#undef domCalendarProperty +#undef domHTTPMailProperty +#undef domMailHeaderProperty diff --git a/kresources/newexchange/exchangeconvertercalendar.h b/kresources/newexchange/exchangeconvertercalendar.h new file mode 100644 index 000000000..346b2a954 --- /dev/null +++ b/kresources/newexchange/exchangeconvertercalendar.h @@ -0,0 +1,63 @@ +/* + This file is part of the exchange resource. + Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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_EXCHANGECONVERTERCONTACT_H +#define KCal_EXCHANGECONVERTERCONTACT_H + +#include <qstring.h> +#include <qdom.h> + +#include <libkcal/incidence.h> +#include <libkcal/icalformat.h> + +namespace KCal { +class ICalFormat; + +class ExchangeConverterCalendar +{ + public: + + ExchangeConverterCalendar(); + + void setTimeZone( const QString &id ); + + static void createRequestAppointment( QDomDocument &doc, QDomElement &root ); + static void createRequestTask( QDomDocument &doc, QDomElement &root ); + static void createRequestJournal( QDomDocument &doc, QDomElement &root ); + + QDomDocument createWebDAV( Incidence *incidence ); + + Incidence::List parseWebDAV( const QDomDocument& davdata ); + bool readIncidence( const QDomElement &node, Incidence *incidence ); + + protected: + static void createRequestIncidence( QDomDocument &doc, QDomElement &root ); + bool readEvent( const QDomElement &node, Event *event ); + bool readTodo( const QDomElement &node, Todo *todo ); + bool readJournal( const QDomElement &node, Journal *journal ); + bool readTZ( const QDomElement &node, Incidence *incidence ); + + KCal::ICalFormat mFormat; + class createWebDAVVisitor; +}; + +} + +#endif diff --git a/kresources/newexchange/exchangeconvertercontact.cpp b/kresources/newexchange/exchangeconvertercontact.cpp new file mode 100644 index 000000000..1e756574f --- /dev/null +++ b/kresources/newexchange/exchangeconvertercontact.cpp @@ -0,0 +1,615 @@ +/* + This file is part of the exchange resource. + Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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 "exchangeconvertercontact.h" +#include <libkcal/freebusyurlstore.h> +#include <webdavhandler.h> +#include <kdebug.h> + + +using namespace KABC; + +ExchangeConverterContact::ExchangeConverterContact() +{ +} + + +#define propertyDAV( prop ) \ + WebdavHandler::addElement( doc, props, "d:" prop ) +#define propertyNS( ns, prop ) \ + WebdavHandler::addElementNS( doc, props, ns, prop ) +#define propertyContact( prop ) \ + WebdavHandler::addElement( doc, props, "c:" prop ) +#define propertyCalendar( prop ) \ + WebdavHandler::addElement( doc, props, "cal:" prop ) +#define propertyHTTPMail( prop ) \ + WebdavHandler::addElement( doc, props, "m:" prop ) +#define property( prop ) \ + Webdavhandler::addElement( doc, props, prop ) + +void ExchangeConverterContact::createRequest( QDomDocument &doc, QDomElement &props ) +{ + QDomAttr att_c = doc.createAttribute( "xmlns:c" ); + att_c.setValue( "urn:schemas:contacts:" ); + doc.documentElement().setAttributeNode( att_c ); + QDomAttr att_cal = doc.createAttribute( "xmlns:cal" ); + att_cal.setValue( "urn:schemas:calendar:" ); + doc.documentElement().setAttributeNode( att_cal ); + + propertyDAV( "contentclass" ); + propertyDAV( "getcontenttype" ); + propertyNS( "http://schemas.microsoft.com/exchange/", "outlookmessageclass" ); + propertyDAV( "getetag" ); + propertyDAV( "href" ); + propertyDAV( "creationdate" ); + propertyDAV( "getlastmodified" ); + propertyDAV( "isreadonly" ); + propertyContact( "cn" ); +// propertyContact( "uid" ); + propertyDAV( "uid" ); + propertyContact( "fileas" ); + propertyContact( "cn" ); + propertyContact( "givenName" ); + propertyContact( "initials" ); + propertyContact( "middlename" ); + propertyContact( "namesuffix" ); + propertyContact( "personaltitle" ); + propertyContact( "sn" ); + propertyContact( "title" ); + propertyContact( "o" ); + propertyContact( "department" ); + propertyContact( "roomnumber" ); + propertyContact( "profession" ); + propertyContact( "manager" ); + propertyContact( "secretarycn" ); + propertyContact( "email1" ); + propertyContact( "email2" ); + propertyContact( "email3" ); + propertyContact( "personalHomePage" ); + propertyContact( "businesshomepage" ); + propertyContact( "fburl" ); + // TODO: Does this work? +// propertyNS( "urn:schemas-microsoft-com:office:office", "Keywords" ); + propertyDAV( "sensitivity" ); + propertyContact( "telephoneNumber" ); + propertyContact( "telephonenumber2" ); + propertyContact( "officetelephonenumber" ); + propertyContact( "office2telephonenumber" ); + propertyContact( "secretaryphone" ); + propertyContact( "organizationmainphone" ); + propertyContact( "otherTelephone" ); + propertyContact( "homePhone" ); + propertyContact( "homephone2" ); + propertyContact( "mobile" ); + propertyContact( "othermobile" ); + propertyContact( "facsimiletelephonenumber" ); + propertyContact( "homefax" ); + propertyContact( "otherfax" ); + propertyContact( "pager" ); + propertyContact( "otherpager" ); + propertyContact( "internationalisdnnumber" ); + propertyContact( "callbackphone" ); + propertyContact( "telexnumber" ); + propertyContact( "ttytddphone" ); + propertyContact( "workaddress" ); + propertyContact( "street" ); + propertyContact( "postofficebox" ); + propertyContact( "l" ); + propertyContact( "postalcode" ); + propertyContact( "st" ); + propertyContact( "co" ); + propertyContact( "c" ); + propertyContact( "homepostaladdress" ); + propertyContact( "homeStreet" ); + propertyContact( "homepostofficebox" ); + propertyContact( "homeCity" ); + propertyContact( "homePostalCode" ); + propertyContact( "homeState" ); + propertyContact( "homeCountry" ); + propertyContact( "homeCountrycode" ); + propertyContact( "mailingpostaladdress" ); + propertyContact( "mailingstreet" ); + propertyContact( "mailingpostofficebox" ); + propertyContact( "mailingcity" ); + propertyContact( "mailingpostalcode" ); + propertyContact( "mailingstate" ); + propertyContact( "mailingcountry" ); + propertyContact( "mailingcountrycode" ); + propertyContact( "otherpostaladdress" ); + propertyContact( "otherstreet" ); + propertyContact( "otherpostofficebox" ); + propertyContact( "othercity" ); + propertyContact( "otherpostalcode" ); + propertyContact( "otherstate" ); + propertyContact( "othercountry" ); + propertyContact( "othercountrycode" ); + propertyContact( "nickname" ); + propertyContact( "spousecn" ); + propertyContact( "bday" ); + propertyContact( "weddinganniversary" ); + propertyCalendar( "geolatitude" ); + propertyCalendar( "geolongitude" ); + propertyContact( "mapurl" ); + propertyContact( "location" ); + propertyHTTPMail( "textdescription" ); + propertyHTTPMail( "date" ); + propertyContact( "usercertificate" ); +} +#undef propertyDAV +#undef propertyNS +#undef propertyContact +#undef propertyCalendar +#undef propertyHTTPMail +#undef property + + +bool ExchangeConverterContact::extractAddress( const QDomElement &node, + Addressee &addressee, int type, + const QString &street, const QString &pobox, const QString &location, + const QString &postalcode, const QString &state, const QString &country, + const QString &/*countycode*/ ) +{ + bool haveAddr = false; + Address addr( type ); + QString tmpstr; + + if ( WebdavHandler::extractString( node, street, tmpstr ) ) { + addr.setStreet( tmpstr ); + haveAddr = true; + } + if ( WebdavHandler::extractString( node, pobox, tmpstr ) ) { + addr.setPostOfficeBox( tmpstr ); + haveAddr = true; + } + if ( WebdavHandler::extractString( node, location, tmpstr ) ) { + addr.setLocality( tmpstr ); + haveAddr = true; + } + if ( WebdavHandler::extractString( node, postalcode, tmpstr ) ) { + addr.setPostalCode( tmpstr ); + haveAddr = true; + } + if ( WebdavHandler::extractString( node, state, tmpstr ) ) { + addr.setRegion( tmpstr ); + haveAddr = true; + } + if ( WebdavHandler::extractString( node, country, tmpstr ) ) { + addr.setCountry( tmpstr ); + haveAddr = true; + } +// if ( WebdavHandler::extractString( node, countrycode, tmpstr ) ) { +// addr.setCountryCode( tmpstr ); +// haveAddr = true; +// } + if ( haveAddr ) { + addressee.insertAddress( addr ); + } + return haveAddr; +} + + +/** +For the complete list of Exchange <=> KABC field mappings see the file +Person.mapping */ +bool ExchangeConverterContact::readAddressee( const QDomElement &node, Addressee &addressee ) +{ + QString tmpstr; + long tmplng; + + // The UID is absolutely required! + if ( WebdavHandler::extractString( node, "uid", tmpstr ) ) { + addressee.setUid( tmpstr ); + } else { + kdDebug()<<"Addressee does not have a UID"<<endl; + return false; + } + if ( WebdavHandler::extractString( node, "getetag", tmpstr ) ) + addressee.insertCustom( "KDEPIM-Exchange-Resource", "fingerprint", tmpstr ); + if ( WebdavHandler::extractString( node, "href", tmpstr ) ) + addressee.insertCustom( "KDEPIM-Exchange-Resource", "href", tmpstr ); + +/* KDE4: addressee does not have any creation or modification date :-(( */ +/* KDE4: read-only not supported by libkabc */ + + // Name: first, family, pre/postfixes, common name + if ( WebdavHandler::extractString( node, "fileas", tmpstr ) || + WebdavHandler::extractString( node, "cn", tmpstr ) ) + addressee.setFormattedName( tmpstr ); + if ( WebdavHandler::extractString( node, "givenName", tmpstr ) ) + addressee.setGivenName( tmpstr ); + if ( WebdavHandler::extractString( node, "middlename", tmpstr ) ) + addressee.setAdditionalName( tmpstr ); + if ( WebdavHandler::extractString( node, "sn", tmpstr ) ) + addressee.setFamilyName( tmpstr ); + //urn:schemas:contacts:initials not used - + if ( WebdavHandler::extractString( node, "namesuffix", tmpstr ) ) + addressee.setSuffix( tmpstr ); + if ( WebdavHandler::extractString( node, "personaltitle", tmpstr ) ) + addressee.setPrefix( tmpstr ); + + // Role + if ( WebdavHandler::extractString( node, "title", tmpstr ) ) + addressee.setRole( tmpstr ); + + // Company-Related settings + if ( WebdavHandler::extractString( node, "o", tmpstr ) ) + addressee.setOrganization( tmpstr ); + if ( WebdavHandler::extractString( node, "department", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-Department", tmpstr ); + if ( WebdavHandler::extractString( node, "roomnumber", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-Office", tmpstr ); + if ( WebdavHandler::extractString( node, "profession", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-Profession", tmpstr ); + if ( WebdavHandler::extractString( node, "manager", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-ManagersName", tmpstr ); + + if ( WebdavHandler::extractString( node, "secretarycn", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-AssistantsName", tmpstr ); + + + // Web-Related settings + if ( WebdavHandler::extractString( node, "email1", tmpstr ) ) + addressee.insertEmail( tmpstr, true ); + if ( WebdavHandler::extractString( node, "email2", tmpstr ) ) + addressee.insertEmail( tmpstr ); + if ( WebdavHandler::extractString( node, "email3", tmpstr ) ) + addressee.insertEmail( tmpstr ); + + // No kabc field for personalHomePage + if ( WebdavHandler::extractString( node, "businesshomepage", tmpstr ) ) + addressee.setUrl( tmpstr ); + + if ( WebdavHandler::extractString( node, "fburl", tmpstr ) ) { + KCal::FreeBusyUrlStore::self()->writeUrl( addressee.preferredEmail(), tmpstr ); + KCal::FreeBusyUrlStore::self()->sync(); + } + + + // General stuff: + QStringList tmplst; + if ( WebdavHandler::extractStringList( node, "Keywords", tmplst ) ) + addressee.setCategories( tmplst ); + // Exchange sentitivity values: + // 0 None, 1 Personal, 2 Private, 3 Company Confidential + if ( WebdavHandler::extractLong( node, "sensitivity", tmplng ) ) { + switch( tmplng ) { + case 0: addressee.setSecrecy( KABC::Secrecy::Public ); break; + case 1: + case 2: addressee.setSecrecy( KABC::Secrecy::Private ); break; + case 3: addressee.setSecrecy( KABC::Secrecy::Confidential ); break; + default: kdWarning() << "Unknown sensitivity: " << tmplng << endl; + } + } + +#define insertPhone( name, type ) \ + if ( WebdavHandler::extractString( node, name, tmpstr ) ) \ + addressee.insertPhoneNumber( KABC::PhoneNumber( tmpstr, type ) ); + // Phone numbers + insertPhone( "telephoneNumber", PhoneNumber::Work ); +//insertPhone( "telephonenumber2", PhoneNumber::Work ); + insertPhone( "officetelephonenumber", PhoneNumber::Work ); +//insertPhone( "office2telephonenumber", PhoneNumber::Work ); +//insertPhone( "secretaryphone", PhoneNumber::Work ); +//insertPhone( "organizationmainphone", PhoneNumber::Work ); + insertPhone( "otherTelephone", 0 ); + insertPhone( "homePhone", PhoneNumber::Home ); +//insertPhone( "homephone2", PhoneNumber::Home ); + insertPhone( "mobile", PhoneNumber::Cell ); +//insertPhone( "othermobile", PhoneNumber::Cell ); + insertPhone( "facsimiletelephonenumber",PhoneNumber::Fax ); + insertPhone( "homefax", PhoneNumber::Fax | PhoneNumber::Home ); + insertPhone( "otherfax", PhoneNumber::Fax | PhoneNumber::Work ); + insertPhone( "pager", PhoneNumber::Pager | PhoneNumber::Work ); + insertPhone( "otherpager", PhoneNumber::Pager ); + insertPhone( "internationalisdnnumber", PhoneNumber::Isdn ); + insertPhone( "callbackphone", PhoneNumber::Msg ); + insertPhone( "telexnumber", PhoneNumber::Bbs ); + insertPhone( "ttytddphone", PhoneNumber::Pcs ); +#undef insertPhone + + // Addresses: Work, Home, Mailing and Other: + extractAddress( node, addressee, Address::Work | Address::Pref, + "street", "postofficebox", "l", "postalcode", "st", "co", "c" ); + extractAddress( node, addressee, Address::Home, + "homeStreet", "homepostofficebox", "homeCity", "homePostalCode", + "homeState", "homeCountry", "homeCountrycode" ); + // Exchange doesn't support writing/changing the mailing address fields, + // so don't download it. It's equal to either the home or work address anyway +/* extractAddress( node, addressee, Address::Postal, + "mailingstreet", "mailingpostofficebox", "mailingcity", "mailingpostalcode", + "mailingstate", "mailingcountry", "mailingcountrycode" );*/ + extractAddress( node, addressee, 0, + "otherstreet", "otherpostofficebox", "othercity", "otherpostalcode", + "otherstate", "othercountry", "othercountrycode" ); + + + if ( WebdavHandler::extractString( node, "nickname", tmpstr ) ) + addressee.setNickName( tmpstr ); + if ( WebdavHandler::extractString( node, "spousecn", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-SpousesName", tmpstr ); + + QDateTime tmpdt; + if ( WebdavHandler::extractDateTime( node, "bday", tmpdt ) ) + addressee.setBirthday( tmpdt.date() ); + if ( WebdavHandler::extractString( node, "weddinganniversary", tmpstr ) ) + addressee.insertCustom( "KADDRESSBOOK", "X-Anniversary", tmpstr ); + +// TODO? timeZone() + + float lt,lng; + if ( WebdavHandler::extractFloat( node, "geolatitude", lt ) && + WebdavHandler::extractFloat( node, "geolongitude", lng ) ) + addressee.setGeo( Geo( lt, lng ) ); + // TODO: mapurl + // TODO: location + + if ( WebdavHandler::extractString( node, "textdescription", tmpstr ) ) + addressee.setNote( tmpstr ); + +// if ( WebdavHandler::extractString( node, "usercertificate", tmpstr ) ) +// addressee.setKeys() + + return true; +} + +Addressee::List ExchangeConverterContact::parseWebDAV( const QDomDocument& davdata ) +{ + // TODO: Handle multiple addressees per reply! + Addressee::List list; + + QDomElement prop = davdata.documentElement().namedItem( "response" ) + .namedItem( "propstat" ).namedItem( "prop" ).toElement(); + if ( prop.isNull() ) { +kdDebug()<<"ExchangeConverterContact::parseWebDAV, no response->propstat->prop element!"<<endl; + return list; + } + + QString contentclass; + bool success = WebdavHandler::extractString( prop, "contentclass", contentclass ); + if ( !success ) { +kdDebug()<<"ExchangeConverterContact::parseWebDAV, No contentclass entry"<<endl; + return list; + } + + success = false; + Addressee addressee; + if ( contentclass == "urn:content-classes:person" ) { + success = readAddressee( prop, addressee ); + } + + if ( success ) { + list.append( addressee ); + } else { + + } + return list; +} + +#define domDavProperty( name, value ) \ + WebdavHandler::addElement( doc, prop, "d:" name, value ); +#define domProperty( NS, name, value ) \ + WebdavHandler::addElementNS( doc, prop, NS, name, value ); +#define domContactProperty( name, value ) \ + WebdavHandler::addElement( doc, prop, "c:" name, value ); +#define domCalendarProperty( name, value ) \ + WebdavHandler::addElement( doc, prop, "cal:" name, value ); +#define domPhoneProperty( name, type ) \ + domContactProperty( name, addr.phoneNumber( type ).number() ); + + +QDomDocument ExchangeConverterContact::createWebDAV( Addressee addr ) +{ + QDomDocument doc; + QDomElement root = WebdavHandler::addDavElement( doc, doc, "d:propertyupdate" ); + QDomElement set = WebdavHandler::addElement( doc, root, "d:set" ); + QDomElement prop = WebdavHandler::addElement( doc, set, "d:prop" ); + + QDomAttr att_c = doc.createAttribute( "xmlns:c" ); + att_c.setValue( "urn:schemas:contacts:" ); + doc.documentElement().setAttributeNode( att_c ); + + QDomAttr att_b = doc.createAttribute( "xmlns:b" ); + att_b.setValue( "urn:schemas-microsoft-com:datatypes" ); + root.setAttributeNode( att_b ); + + domDavProperty( "contentclass", "urn:content-classes:person" ); + domProperty( "http://schemas.microsoft.com/exchange/", + "outlookmessageclass", "IPM.Contact" ); +// domContactProperty( "uid", addr.uid() ); + + domContactProperty( "fileas", addr.formattedName() ); + domContactProperty( "givenName", addr.givenName() ); + domContactProperty( "middlename", addr.additionalName() ); + domContactProperty( "sn", addr.familyName() ); + domContactProperty( "namesuffix", addr.suffix() ); + domContactProperty( "personaltitle", addr.prefix() ); + + domContactProperty( "title", addr.role() ); + domContactProperty( "o", addr.organization() ); + domContactProperty( "department", addr.custom( "KADDRESSBOOK", "X-Department" ) ); + domContactProperty( "roomnumber", addr.custom( "KADDRESSBOOK", "X-Office" ) ); + domContactProperty( "profession", addr.custom( "KADDRESSBOOK", "X-Profession" ) ); + domContactProperty( "manager", addr.custom( "KADDRESSBOOK", "X-ManagersName" ) ); + domContactProperty( "secretarycn", addr.custom( "KADDRESSBOOK", "X-AssistantsName" ) ); + + QStringList emails = addr.emails(); + QString prefemail = addr.preferredEmail(); + if ( emails.contains( prefemail ) ) + emails.remove( prefemail ); + emails.prepend( prefemail ); + if ( emails.count() > 0 ) { + domContactProperty( "email1", emails[0] ); + } + if ( emails.count() > 1 ) { + domContactProperty( "email2", emails[1] ); + } + if ( emails.count() > 2 ) { + domContactProperty( "email3", emails[2] ); + } + + // No value for "personalHomePage" + domContactProperty( "businesshomepage", addr.url().url() ); + + QString fburl = KCal::FreeBusyUrlStore::self()->readUrl( addr.preferredEmail() ); + if ( !fburl.isEmpty() ) { + domContactProperty( "fburl", fburl ); + } + +/* FIXME: This doesn't work! + QStringList cats = addr.categories(); + if ( cats.isEmpty() ) { + QDomElement catsnode = WebdavHandler::addElementNS( doc, prop, + "urn:schemas-microsoft-com:office:office", "Keywords" ); + for ( QStringList::Iterator it = cats.begin(); it != cats.end(); ++it ) { + WebdavHandler::addElementNS( doc, catsnode, "xml:", "v", *it ); + } + } else { +// QDomElement catsnode = addProperty( doc, prop, +// "urn:schemas-microsoft-com:office:office", "Keywords", "" ); + }*/ + + // Exchange sentitivity values: + // 0 None, 1 Personal, 2 Private, 3 Company Confidential + QString value; + switch ( addr.secrecy().type() ) { + case KABC::Secrecy::Private: value = "2"; break; + case KABC::Secrecy::Confidential: value = "3"; break; + default: value = "0"; + } + domDavProperty( "sensitivity", value ); + + // Phone numbers + domPhoneProperty( "telephoneNumber", PhoneNumber::Work ); +// domPhoneProperty( "telephonenumber2", PhoneNumber::Work ); + domPhoneProperty( "officetelephonenumber", PhoneNumber::Work ); +// domPhoneProperty( "office2telephonenumber", PhoneNumber::Work ); +// domPhoneProperty( "secretaryphone", PhoneNumber::Work ); +// domPhoneProperty( "organizationmainphone", PhoneNumber::Work ); + domPhoneProperty( "otherTelephone", 0 ); + domPhoneProperty( "homePhone", PhoneNumber::Home ); +// domPhoneProperty( "homephone2", PhoneNumber::Home ); + domPhoneProperty( "mobile", PhoneNumber::Cell ); + domPhoneProperty( "othermobile", PhoneNumber::Cell | PhoneNumber::Home ); + domPhoneProperty( "facsimiletelephonenumber", PhoneNumber::Fax ); + domPhoneProperty( "homefax", PhoneNumber::Fax | PhoneNumber::Home ); + domPhoneProperty( "otherfax", PhoneNumber::Fax | PhoneNumber::Work ); + domPhoneProperty( "pager", PhoneNumber::Pager | PhoneNumber::Work ); + domPhoneProperty( "otherpager", PhoneNumber::Pager ); + domPhoneProperty( "internationalisdnnumber", PhoneNumber::Isdn ); + domPhoneProperty( "callbackphone", PhoneNumber::Msg ); + domPhoneProperty( "telexnumber", PhoneNumber::Bbs ); + domPhoneProperty( "ttytddphone", PhoneNumber::Pcs ); + + +// work address: + Address workaddr = addr.address( Address::Work | Address::Pref ); + if ( !workaddr.isEmpty() ) { + domContactProperty( "street", workaddr.street() ); + domContactProperty( "postofficebox", workaddr.postOfficeBox() ); + domContactProperty( "l", workaddr.locality() ); + domContactProperty( "postalcode", workaddr.postalCode() ); + domContactProperty( "st", workaddr.region() ); + domContactProperty( "co", workaddr.country() ); + // domContactProperty( "c", workaddr.countryCode() ); + } + + // home address: + Address homeaddr = addr.address( Address::Home ); + if ( !homeaddr.isEmpty() ) { + domContactProperty( "homeStreet", homeaddr.street() ); + domContactProperty( "homepostofficebox", homeaddr.postOfficeBox() ); + domContactProperty( "homeCity", homeaddr.locality() ); + domContactProperty( "homePostalCode", homeaddr.postalCode() ); + domContactProperty( "homeState", homeaddr.region() ); + domContactProperty( "homeCountry", homeaddr.country() ); + // domContactProperty( "homeCountrycode", homeaddr.countryCode() ); + } + + // mailing address: + // Exchange doesn't support writing/changing the mailing address fields +/* Address mailingaddr = addr.address( Address::Postal ); + if ( !mailingaddr.isEmpty() ) { + domContactProperty( "mailingstreet", mailingaddr.street() ); + domContactProperty( "mailingpostofficebox", mailingaddr.postOfficeBox() ); + domContactProperty( "mailingcity", mailingaddr.locality() ); + domContactProperty( "mailingpostalcode", mailingaddr.postalCode() ); + domContactProperty( "mailingstate", mailingaddr.region() ); + domContactProperty( "mailingcountry", mailingaddr.country() ); + // domContactProperty( "mailingcountrycode", mailingaddr.countryCode() ); + }*/ + + // other address: + Address otheraddr = addr.address( 0 ); + if ( !otheraddr.isEmpty() ) { + domContactProperty( "otherstreet", otheraddr.street() ); + domContactProperty( "otherpostofficebox", otheraddr.postOfficeBox() ); + domContactProperty( "othercity", otheraddr.locality() ); + domContactProperty( "otherpostalcode", otheraddr.postalCode() ); + domContactProperty( "otherstate", otheraddr.region() ); + domContactProperty( "othercountry", otheraddr.country() ); + // domContactProperty( "othercountrycode", otheraddr.countryCode() ); + } + + + domContactProperty( "nickname", addr.nickName() ); + domContactProperty( "spousecn", addr.custom( "KADDRESSBOOK", "X-SpousesName" ) ); + + // TODO: Birthday and Anniversary: + // FIXME: Exchange uses the date in the form 8/13, i.e. possibly without a + // year! How shall I deal with this? +/* QDate dt = addr.birthday().date(); + QString str = (dt.isValid())?(dt.toString( Qt::ISODate )):(QString::null); + if ( !str.isEmpty() ) { + QDomElement el = domContactProperty( "bday", str ); + el.setAttribute( "b:dt", "date" ); + } + dt = QDate::fromString( addr.custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate ); + str = (dt.isValid())?(dt.toString( Qt::ISODate )):(QString::null); + if ( !str.isEmpty() ) { + QDomElement el = domContactProperty( "weddinganniversary", str ); + el.setAttribute( "b:dt", "date" ); + }*/ + +// ? TODO: timeZone() +/* + KABC::Geo geo = addr.geo(); + if ( geo.isValid() ) { + // TODO: Do we need to set any other attribute to make it a float? + QDomAttr att_cal = doc.createAttribute( "xmlns:cal" ); + att_cal.setValue( "urn:schemas:calendar:" ); + doc.documentElement().setAttributeNode( att_cal ); + QDomElement el = domCalendarProperty( "geolatitude", QString::number( geo.latitude() ) ); + el.setAttribute( "b:dt", "float" ); + el = domCalendarProperty( "geolongitude", QString::number( geo.longitude() ) ); + el.setAttribute( "b:dt", "float" ); + } +*/ + domContactProperty( "textdescription", addr.note() ); + + // TODO:usercertificate + // TODO: custom fields +kdDebug()<<"DOM document: "<<doc.toString() << endl; + + return doc; +} +#undef domDavProperty +#undef domProperty +#undef domContactProperty +#undef domPhoneProperty diff --git a/kresources/newexchange/exchangeconvertercontact.h b/kresources/newexchange/exchangeconvertercontact.h new file mode 100644 index 000000000..45ee7c7ca --- /dev/null +++ b/kresources/newexchange/exchangeconvertercontact.h @@ -0,0 +1,53 @@ +/* + This file is part of the exchange resource. + Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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_EXCHANGECONVERTERCONTACT_H +#define KABC_EXCHANGECONVERTERCONTACT_H + +#include <qstring.h> +#include <qdom.h> + +#include <kabc/addressee.h> + +namespace KABC { + +class ExchangeConverterContact +{ + public: + + ExchangeConverterContact(); + + static void createRequest( QDomDocument &doc, QDomElement &root ); + + QDomDocument createWebDAV( Addressee addr ); + + Addressee::List parseWebDAV( const QDomDocument& davdata ); + bool readAddressee( const QDomElement &node, Addressee &addressee ); + + protected: + bool extractAddress( const QDomElement &node, Addressee &addressee, int type, + const QString &street, const QString &pobox, const QString &location, + const QString &postalcode, const QString &state, const QString &country, + const QString &countycode ); +}; + +} + +#endif diff --git a/kresources/newexchange/exchangeglobals.cpp b/kresources/newexchange/exchangeglobals.cpp new file mode 100644 index 000000000..7cca837df --- /dev/null +++ b/kresources/newexchange/exchangeglobals.cpp @@ -0,0 +1,286 @@ +/* + This file is part of kdepim. + + Copyright (c) 2005 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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 "exchangeglobals.h" +#include <webdavhandler.h> +#include <groupwaredataadaptor.h> +#include "exchangeconvertercalendar.h" +#include "exchangeconvertercontact.h" +#include <calendaradaptor.h> +#include <addressbookadaptor.h> + +#include <libkcal/resourcecached.h> +#include <libemailfunctions/idmapper.h> +#include <kio/job.h> +#include <kio/davjob.h> +#include <kdebug.h> + +KPIM::FolderLister::ContentType ExchangeGlobals::getContentType( const QDomElement &prop ) +{ + const QString &contentclass = prop.namedItem("contentclass").toElement().text(); +kdDebug()<<"contentclass: "<<contentclass<<endl; + return getContentType( contentclass ); +} + +KPIM::FolderLister::ContentType ExchangeGlobals::getContentType( const QString &contentclass ) +{ + if ( contentclass == "urn:content-classes:appointment" ) + return KPIM::FolderLister::Event; + if ( contentclass == "urn:content-classes:task" ) + return KPIM::FolderLister::Todo; + if ( contentclass == "urn:content-classes:message" ) + return KPIM::FolderLister::Message; + if ( contentclass == "urn:content-classes:person" ) + return KPIM::FolderLister::Contact; + return KPIM::FolderLister::Unknown; +} + + +KPIM::FolderLister::ContentType ExchangeGlobals::getContentType( const QDomNode &folderNode ) +{ +kdDebug()<<"ExchangeGlobals::getContentType(...)"<<endl; + QDomNode n4; + for( n4 = folderNode.firstChild(); !n4.isNull(); n4 = n4.nextSibling() ) { + QDomElement e = n4.toElement(); + + if ( e.tagName() == "contentclass" ) { + QString contentclass( e.text() ); + if ( contentclass == "urn:content-classes:contactfolder" ) + return KPIM::FolderLister::Contact; + if ( contentclass == "urn:content-classes:calendarfolder" ) + return KPIM::FolderLister::Event; + if ( contentclass == "urn:content-classes:taskfolder" ) + return KPIM::FolderLister::Todo; + if ( contentclass == "urn:content-classes:journalfolder" ) + return KPIM::FolderLister::Journal; + if ( contentclass == "urn:content-classes:folder" ) + return KPIM::FolderLister::Folder; + } + } + return KPIM::FolderLister::Unknown; +} + +bool ExchangeGlobals::getFolderHasSubs( const QDomNode &folderNode ) +{ + QString hassubs = folderNode.namedItem( "hassubs" ).toElement().text(); + return hassubs == "1"; +} + + + + +KIO::Job *ExchangeGlobals::createListFoldersJob( const KURL &url ) +{ + QDomDocument doc; + QDomElement root = WebdavHandler::addDavElement( doc, doc, "d:propfind" ); + QDomElement prop = WebdavHandler::addElement( doc, root, "d:prop" ); + WebdavHandler::addElement( doc, prop, "d:displayname" ); + WebdavHandler::addElement( doc, prop, "d:contentclass" ); + WebdavHandler::addElement( doc, prop, "d:hassubs" ); + + kdDebug(7000) << "props: " << doc.toString() << endl; + return KIO::davPropFind( url, doc, "1", false ); +} + + +KIO::TransferJob *ExchangeGlobals::createListItemsJob( const KURL &url ) +{ + QDomDocument doc; + QDomElement root = WebdavHandler::addDavElement( doc, doc, "d:propfind" ); + QDomElement prop = WebdavHandler::addElement( doc, root, "d:prop" ); + WebdavHandler::addElement( doc, prop, "d:getetag" ); + WebdavHandler::addElement( doc, prop, "d:contentclass" ); + kdDebug(5800) << "props = "<< doc.toString() << endl; + return KIO::davPropFind( url, doc, "1", false ); +} + + +KIO::TransferJob *ExchangeGlobals::createDownloadJob( KPIM::GroupwareDataAdaptor *adaptor, + const KURL &url, KPIM::FolderLister::ContentType ctype ) +{ +kdDebug() << "ExchangeGlobals::createDownloadJob()" << endl; +kdDebug() << "ctype=" << ctype << endl; +kdDebug() << "Person=" << KPIM::FolderLister::Contact << ", " + << "Appointment=" << KPIM::FolderLister::Event << ", " + << "Task=" << KPIM::FolderLister::Todo << ", " + << "Journal=" << KPIM::FolderLister::Journal << ", " + << "Message=" << KPIM::FolderLister::Message << endl; + // Don't use an <allprop/> request! + + QDomDocument doc; + QDomElement root = WebdavHandler::addDavElement( doc, doc, "d:propfind" ); + QDomElement prop = WebdavHandler::addElement( doc, root, "d:prop" ); + QDomAttr att_h = doc.createAttribute( "xmlns:h" ); + att_h.setValue( "urn:schemas:mailheader:" ); + root.setAttributeNode( att_h ); + + QDomAttr att_m = doc.createAttribute( "xmlns:m" ); + att_m.setValue( "urn:schemas:httpmail:" ); + root.setAttributeNode( att_m ); + + switch ( ctype ) { + case KPIM::FolderLister::Event: + KCal::ExchangeConverterCalendar::createRequestAppointment( doc, prop ); + break; + case KPIM::FolderLister::Todo: + KCal::ExchangeConverterCalendar::createRequestTask( doc, prop ); + break; + case KPIM::FolderLister::Journal: + case KPIM::FolderLister::Message: + KCal::ExchangeConverterCalendar::createRequestJournal( doc, prop ); + break; + case KPIM::FolderLister::Contact: + KABC::ExchangeConverterContact::createRequest( doc, prop ); + break; + default: + break; + } + + kdDebug(7000) << "doc: " << doc.toString() << endl; + KURL authURL = url; + KIO::DavJob *job = KIO::davPropFind( authURL, doc, "0", false ); +/* KURL httpurl( url ); + QString proto("http"); + httpurl.setProtocol( proto ); + KIO::TransferJob *job = KIO::get(httpurl, false, false); + job->addMetaData("customHTTPHeader", "Translate: f"); + job->addMetaData("cache", "reload");*/ + return job; +} + + +KIO::Job *ExchangeGlobals::createRemoveJob( const KURL &uploadurl, + const KPIM::GroupwareUploadItem::List &deletedItems ) +{ + QStringList urls; + KPIM::GroupwareUploadItem::List::const_iterator it; + kdDebug() << " ExchangeGlobals::createRemoveJob: , URL="<<uploadurl.url()<<endl; + for ( it = deletedItems.begin(); it != deletedItems.end(); ++it ) { + //kdDebug(7000) << "Delete: " << endl << format.toICalString(*it) << endl; + kdDebug() << "Delete: " << (*it)->url().url() << endl; + KURL url( uploadurl ); + url.setPath( (*it)->url().path() ); + if ( !url.isEmpty() ) + urls << url.url(); + kdDebug() << "Delete (Mod) : " << url.url() << endl; + } + return KIO::del( urls, false, false ); +} + + + + +// FIXME: This is exactly the same code as in the OGo resource, except that +// it calls getContentType of the ExchangeGlobals class, instead of the one +// from OGoGlobals!!!! +bool ExchangeGlobals::interpretListItemsJob( KPIM::GroupwareDataAdaptor *adaptor, + KIO::Job *job, const QString &/*jobData*/ ) +{ +kdDebug()<<"ExchangeGlobals::interpretListItemsJob"<<endl; + KIO::DavJob *davjob = dynamic_cast<KIO::DavJob *>(job); + + if ( !davjob ) { + return false; + } + QDomDocument doc = davjob->response(); + + kdDebug(7000) << " Doc: " << doc.toString() << endl; + kdDebug(7000) << " IdMapper: " << adaptor->idMapper()->asString() << endl; + + QDomElement docElem = doc.documentElement(); + QDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + QDomElement e = n.toElement(); // try to convert the node to an element. + n = n.nextSibling(); + if ( e.isNull() ) + continue; + + const KURL &entry( e.namedItem("href").toElement().text() ); + QDomElement propstat = e.namedItem("propstat").toElement(); + if ( propstat.isNull() ) + continue; + QDomElement prop = propstat.namedItem( "prop" ).toElement(); + if ( prop.isNull() ) + continue; + QDomElement elem = prop.namedItem("getetag").toElement(); + const QString &newFingerprint = elem.text(); + if ( elem.isNull() || newFingerprint.isEmpty() ) + continue; + + KPIM::FolderLister::ContentType type = getContentType( prop ); + + if (type != KPIM::FolderLister::Unknown) { // Don't queue bad entries + adaptor->processDownloadListItem( entry, newFingerprint, type ); + } + } + + return true; +} + + +bool ExchangeGlobals::interpretCalendarDownloadItemsJob( KCal::CalendarAdaptor *adaptor, + KIO::Job *job, const QString &/*jobData*/ ) +{ + KIO::DavJob *davjob = dynamic_cast<KIO::DavJob*>(job); + if ( !davjob || !adaptor ) return false; + +kdDebug() << "ExchangeGlobals::interpretCalendarDownloadItemsJob(): QDomDocument=" + << endl << davjob->response().toString() << endl; + KCal::ExchangeConverterCalendar conv; + conv.setTimeZone( adaptor->resource()->timeZoneId() ); + KCal::Incidence::List incidences = conv.parseWebDAV( davjob->response() ); + + bool res = false; + KCal::Incidence::List::Iterator it = incidences.begin(); + for ( ; it != incidences.end(); ++it ) { + QString fpr = (*it)->customProperty( "KDEPIM-Exchange-Resource", "fingerprint" ); + KURL href( (*it)->customProperty( "KDEPIM-Exchange-Resource", "href" ) ); + adaptor->calendarItemDownloaded( (*it), (*it)->uid(), href, fpr, href.prettyURL() ); + res = true; + } + return res; +} + + +bool ExchangeGlobals::interpretAddressBookDownloadItemsJob( + KABC::AddressBookAdaptor *adaptor, KIO::Job *job, const QString &/*jobData*/ ) +{ + KIO::DavJob *davjob = dynamic_cast<KIO::DavJob*>(job); + if ( !davjob || !adaptor ) return false; + +kdDebug() << "ExchangeGlobals::interpretAddressBookDownloadItemsJob(): QDomDocument=" + << endl << davjob->response().toString() << endl; + KABC::ExchangeConverterContact conv; + KABC::Addressee::List addressees = conv.parseWebDAV( davjob->response() ); + + bool res = false; + KABC::Addressee::List::Iterator it = addressees.begin(); + for ( ; it != addressees.end(); ++it ) { + QString fpr = (*it).custom( "KDEPIM-Exchange-Resource", "fingerprint" ); + KURL href( (*it).custom( "KDEPIM-Exchange-Resource", "href" ) ); + adaptor->addressbookItemDownloaded( (*it), (*it).uid(), href, fpr, href.prettyURL() ); + res = true; + } + return res; +} + + + diff --git a/kresources/newexchange/exchangeglobals.h b/kresources/newexchange/exchangeglobals.h new file mode 100644 index 000000000..ba56830d7 --- /dev/null +++ b/kresources/newexchange/exchangeglobals.h @@ -0,0 +1,70 @@ + /* + This file is part of kdepim. + + Copyright (c) 2005 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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 EXCHANGEGLOBALS_H +#define EXCHANGEGLOBALS_H + +#include <kurl.h> +#include <groupwareuploadjob.h> +#include <qdom.h> + +namespace KIO { +class Job; +class TransferJob; +} + +namespace KPIM { +class GroupwareDataAdaptor; +class GroupwareUploadItem; +} +namespace KABC { +class AddressBookAdaptor; +} +namespace KCal { +class CalendarAdaptor; +} + +class ExchangeGlobals +{ + public: + ExchangeGlobals() {} + static KPIM::FolderLister::ContentType getContentType( const QDomElement &prop ); + static KPIM::FolderLister::ContentType getContentType( const QString &contentclass ); + static KPIM::FolderLister::ContentType getContentType( const QDomNode &folderNode ); + static bool getFolderHasSubs( const QDomNode &folderNode ); + + + static KIO::Job *createListFoldersJob( const KURL &url ); + static KIO::TransferJob *createListItemsJob( const KURL &url ); + static KIO::TransferJob *createDownloadJob( KPIM::GroupwareDataAdaptor *adaptor, + const KURL &url, KPIM::FolderLister::ContentType ctype ); + static KIO::Job *createRemoveJob( const KURL &uploadurl, + const KPIM::GroupwareUploadItem::List &deletedItems ); + + + static bool interpretListItemsJob( KPIM::GroupwareDataAdaptor *adaptor, + KIO::Job *job, const QString &jobData ); + static bool interpretCalendarDownloadItemsJob( KCal::CalendarAdaptor *adaptor, + KIO::Job *job, const QString &jobData ); + static bool interpretAddressBookDownloadItemsJob( KABC::AddressBookAdaptor *adaptor, + KIO::Job *job, const QString &jobData ); +}; + +#endif diff --git a/kresources/newexchange/kabc_newexchange.desktop b/kresources/newexchange/kabc_newexchange.desktop new file mode 100644 index 000000000..b829ace7d --- /dev/null +++ b/kresources/newexchange/kabc_newexchange.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Name=Addressbook on an Exchange Server (experimental) +Name[af]=Adresboek op 'n Exchange bediener (eksperimenteel) +Name[bg]=Адресник на сървър Exchange (експериментално) +Name[ca]=Llibreta d'adreces a un servidor Exchange (experimental) +Name[cs]=Kniha adres na serveru Exchange (experimentální) +Name[da]=Adressebog på en Exchange-server (eksperimentel) +Name[de]=Adressbuch auf einem Exchange-Server (experimentell) +Name[el]=Βιβλίο διευθύνσεων σε εξυπηρετητή Exchange (πειραματικό) +Name[es]=Libreta de direcciones en un servidor Exchange (experimental) +Name[et]=Aadressiraamat Exchange-serveris (eksperimentaalne) +Name[eu]=Helbide-liburua Exchange zerbitzari batean (esperimentala) +Name[fa]=کتاب نشانی روی یک کارساز مبادله )تجربی( +Name[fi]=Osoitekirja Exchange-palvelimella (kokeellinen) +Name[fr]=Carnet d'adresse sur un serveur Exchange (expérimental) +Name[fy]=Adresboek op in Exchange-tsjinner (eksperimenteel) +Name[ga]=Leabhar Seoltaí ar Fhreastalaí Exchange (trialach) +Name[gl]=Caderno de enderezos no Servidor Exchange2000 (experimental) +Name[hu]=Exchange-kiszolgáló címjegyzéke (kísérleti) +Name[is]=Vistfangaskrá Exchange þjóni (á tilraunarstigi) +Name[it]=Rubrica indirizzi su un server Exchange (sperimentale) +Name[ja]=Exchange サーバのアドレス帳 (実験版) +Name[ka]=წიგნაკი Exchange სერვერზე(ექსპერიმენტული) +Name[kk]=Exchange серверіндегі адрестік кітапша (сынақтағы) +Name[km]=សៀវភៅអាសយដ្ឋានលើម៉ាស៊ីនបម្រើ Exchange (សម្រាប់អ្នកមានបទពិសោធន៍) +Name[lt]=Adresų knygelė Exchange serveryje (eksperimentine tvarka) +Name[mk]=Адресар на Exchange-сервер (експериментално) +Name[ms]=Buku Alamat pada pelayan Exchange (ujikaji) +Name[nb]=Adressebok på en Exchange-tjener (forsøksvis) +Name[nds]=Adressbook op en Exchange-Server (warrt utprobeert) +Name[ne]=एक्सचेन्ज सर्भरमा ठेगाना पुस्तिका (प्रयोगात्मक) +Name[nl]=Adresboek op een Exchange-server (experimenteel) +Name[nn]=Adressebok på ein Exchange-tenar (eksperimentelt) +Name[pl]=Książka adresowa na serwerze Exchange (eksperymentalne) +Name[pt]=Livro de endereços em servidor Exchange (experimental) +Name[pt_BR]=Livro de Endereços em um Servidor Exchange (experimenal) +Name[ru]=Адресная книга на сервере Exchange (экспериментально) +Name[sk]=Adresár na Exchange serveri (experimentálne) +Name[sl]=Adresar na strežniku Exchange (poskusno) +Name[sr]=Адресар на Exchange серверу (експериментално) +Name[sr@Latn]=Adresar na Exchange serveru (eksperimentalno) +Name[sv]=Adressbok på en Exchange-server (experimentell) +Name[ta]=IMAP சேவையக வழியாக கேஅஞ்சலில் நாள்காட்டி(சோதனைக்குரியது) +Name[tr]=Bir Exchange Sunucusu üzerinde Adres Defteri (deneyimsel) +Name[uk]=Адресна книга на сервері Exchange (експериментальне) +Name[zh_CN]=Exchange 服务器上的地址簿(试验性) +Name[zh_TW]=Exchanger 伺服器的通訊錄(實驗中) +X-KDE-Library=kabc_newexchange +Type=Service +ServiceTypes=KResources/Plugin +X-KDE-ResourceFamily=contact +X-KDE-ResourceType=newexchange diff --git a/kresources/newexchange/kabc_newexchange_final.desktop b/kresources/newexchange/kabc_newexchange_final.desktop new file mode 100644 index 000000000..7069b14d8 --- /dev/null +++ b/kresources/newexchange/kabc_newexchange_final.desktop @@ -0,0 +1,49 @@ +[Desktop Entry] +Name=Addressbook on an Exchange Server +Name[af]=Adresboek op 'n Exchange bediener +Name[bg]=Адресник на сървър Exchange +Name[br]=Karned chomlec'hioù war ur servijer Exchange +Name[ca]=Llibreta d'adreces a un servidor Exchange +Name[cs]=Kniha adres na serveru Exchange +Name[da]=Adressebog på en Exchange-server +Name[de]=Adressbuch auf einem Exchange-Server +Name[el]=Βιβλίο διευθύνσεων σε εξυπηρετητή Exchange +Name[es]=Libreta de direcciones en un servidor Exchange +Name[et]=Aadressiraamat Exchange-serveris +Name[eu]=Helbide-liburua Exchange zerbitzari (esperimentala) +Name[fa]=کتاب نشانی روی یک کارساز مبادله +Name[fi]=Osoitekirja Exchange-palvelimella +Name[fr]=Carnet d'adresse sur un serveur Exchange +Name[fy]=Adresboek op in Exchange-tsjinner +Name[ga]=Leabhar Seoltaí ar Fhreastalaí Exchange +Name[gl]=Caderno de enderezos nun Servidor Exchange +Name[he]=פנקס כתובות בשרת Exchange +Name[hu]=Exchange-kiszolgáló címjegyzéke +Name[is]=Vistfangaskrá á Exchange þjóni +Name[it]=Rubrica indirizzi su un server Exchange +Name[ja]=Exchange サーバのアドレス帳 +Name[ka]=წიგნაკი Exchange სერვერზე +Name[kk]=Exchange серверіндегі адрестік кітапша +Name[km]=សៀវភៅអាសយដ្ឋានលើម៉ាស៊ីនបម្រើ Exchange +Name[lt]=Adresų knygelė Exchange serveryje +Name[mk]=Адресар на Exchange-сервер +Name[ms]=Buku alamat pada pelayan Exchange +Name[nb]=Adressebok på en Exchange-tjener +Name[nds]=Adressbook op en Exchange-Server +Name[ne]=एक्सचेन्ज सर्भरमा ठेगाना पुस्तिका +Name[nl]=Adresboek op een Exchange-server +Name[nn]=Adressebok på ein Exchange-tenar +Name[pl]=Książka adresowa na serwerze Exchange +Name[pt]=Livro de endereços em servidor Exchange +Name[pt_BR]=Livro de Endereços em um Servidor Exchange +Name[ru]=Адресная книга на сервере Exchange +Name[sk]=Adresár na Exchange serveri +Name[sl]=Adresar na strežniko Exchange +Name[sr]=Адресар на Exchange серверу +Name[sr@Latn]=Adresar na Exchange serveru +Name[sv]=Adressbok på en Exchange-server +Name[ta]=ஒருமாற்று சேவகனில் முகவரிப்புத்தகம் +Name[tr]=Bir Exchange Sunucusu üzerinde Adres Defteri +Name[uk]=Адресна книга на сервері Exchange +Name[zh_CN]=Exchange 服务器上的地址簿 +Name[zh_TW]=Exchanger 伺服器上的通訊錄 diff --git a/kresources/newexchange/kabc_resourceexchange.cpp b/kresources/newexchange/kabc_resourceexchange.cpp new file mode 100644 index 000000000..8b32a4fac --- /dev/null +++ b/kresources/newexchange/kabc_resourceexchange.cpp @@ -0,0 +1,48 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "exchangeaddressbookadaptor.h" + +#include "kabc_resourceexchange.h" +#include "groupwaredownloadjob.h" +#include "groupwareuploadjob.h" +#include "kresources_groupwareprefs.h" + +using namespace KABC; + +ResourceExchange::ResourceExchange( const KConfig *config ) + : ResourceGroupwareBase( config ) +{ + init(); + if ( config ) readConfig( config ); +} + +void ResourceExchange::init() +{ + setType( "ResourceExchange" ); + setPrefs( createPrefs() ); + setFolderLister( new KPIM::FolderLister( KPIM::FolderLister::AddressBook ) ); + setAdaptor( new ExchangeAddressBookAdaptor() ); + + ResourceGroupwareBase::init(); +} + +#include "kabc_resourceexchange.moc" diff --git a/kresources/newexchange/kabc_resourceexchange.h b/kresources/newexchange/kabc_resourceexchange.h new file mode 100644 index 000000000..542b79955 --- /dev/null +++ b/kresources/newexchange/kabc_resourceexchange.h @@ -0,0 +1,42 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef KABC_RESOURCEEXCHANGE_H +#define KABC_RESOURCEEXCHANGE_H + +#include <kabc_resourcegroupwarebase.h> + +namespace KABC { + +class KDE_EXPORT ResourceExchange : public ResourceGroupwareBase +{ + Q_OBJECT + + public: + ResourceExchange( const KConfig * ); +/* ResourceExchange( const KURL &url, + const QString &user, const QString &password );*/ + protected: + void init(); +}; + +} + +#endif diff --git a/kresources/newexchange/kabc_resourceexchange_plugin.cpp b/kresources/newexchange/kabc_resourceexchange_plugin.cpp new file mode 100644 index 000000000..d324be10d --- /dev/null +++ b/kresources/newexchange/kabc_resourceexchange_plugin.cpp @@ -0,0 +1,27 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "kabc_resourceexchange.h" +#include "kabc_resourcegroupwarebaseconfig.h" + +using namespace KABC; + +typedef KRES::PluginFactory<ResourceExchange,ResourceGroupwareBaseConfig> ExchangeFactory; +K_EXPORT_COMPONENT_FACTORY( kabc_newexchange, ExchangeFactory ) diff --git a/kresources/newexchange/kcal_newexchange.desktop b/kresources/newexchange/kcal_newexchange.desktop new file mode 100644 index 000000000..b94e28ce9 --- /dev/null +++ b/kresources/newexchange/kcal_newexchange.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Name=Calendar on an Exchange Server (experimental) +Name[af]=Kalender op 'n Exchange bediener (eksperimenteel) +Name[bg]=Календар на сървър Exchange (експериментално) +Name[ca]=Calendari a un servidor Exchange (experimental) +Name[cs]=Kalendář na serveru Exchange (experimentální) +Name[da]=Kalender på en Exchange-server (eksperimentel) +Name[de]=Kalender auf einem Exchange-Server (experimentell) +Name[el]=Ημερολόγιο σε εξυπηρετητή Exchange (πειραματικό) +Name[es]=Calendario en un servidor Exchange (experimental) +Name[et]=Kalender Exchange-serveris (eksperimentaalne) +Name[eu]=Egutegia Exchange zerbitzari batean (esperimentala) +Name[fa]=تقویم روی یک کارساز مبادله )تجربی( +Name[fi]=Kalenteri Exchange-palvelimella (kokeellinen) +Name[fr]=Agenda sur un serveur Exchange (expérimental) +Name[fy]=Aginda op in Exchange-tsjinner (eksperimenteel) +Name[ga]=Féilire ar Fhreastalaí Exchange (trialach) +Name[gl]=Calendario nun servidor Exchange (experimental) +Name[hu]=Exchange 2000-kiszolgáló naptára (kísérleti) +Name[is]=Dagatal á Exchange þjóni (á tilraunarstigi) +Name[it]=Calendario su un server Exchange (sperimentale) +Name[ja]=Exchange サーバのカレンダー (実験版) +Name[ka]=კალენდარი Exchange სერვერზე (ექსპერიმენტული) +Name[kk]=Exchange серверіндегі күнтізбе (сынақтағы) +Name[km]=ប្រតិទិនលើម៉ាស៊ីនបម្រើ Exchange (សម្រាប់អ្នកមានបទពិសោធន៍) +Name[lt]=Kalendorius Exchange serveryje (eksperimentine tvarka) +Name[mk]=Календар на Exchange-сервер (експериментално) +Name[ms]=Kalendar pada pelayan Exchange (ujikaji) +Name[nb]=Kalender på en Exchange-tjener (forsøksvis) +Name[nds]=Kalenner op en Exchange-Server (warrt utprobeert) +Name[ne]=एक्सचेन्ज सर्भरमा क्यालेन्डर (प्रयोगात्मक) +Name[nl]=Agenda op een Exchange-server (experimenteel) +Name[nn]=Kalender på ein Exchange-tenar (eksperimentelt) +Name[pl]=Kalendarz na serwerze Exchange (eksperymentalne) +Name[pt]=Calendário em servidor Exchange (experimental) +Name[pt_BR]=Calendário em um Servidor Exchange (experimental) +Name[ru]=Календарь на сервере Exchange (экспериментально) +Name[sk]=Kalendár na Exchange serveri (experimentálne) +Name[sl]=Koledar na strežniku Exchange (poskusno) +Name[sr]=Календар на Exchange серверу (експериментално) +Name[sr@Latn]=Kalendar na Exchange serveru (eksperimentalno) +Name[sv]=Kalender på en Exchange-server (experimentell) +Name[ta]=பரிமாற்ற சேவகனில் நாட்காட்டி (சோதனைக்குரியது) +Name[tr]=Bir Exchange Sunucusu üzerinde Takvim (deneyimsel) +Name[uk]=Календар на сервері Exchange (експериментальне) +Name[zh_CN]=Exchange 服务器上的日历(试验性) +Name[zh_TW]=Exchanger 伺服器上的行事曆(實驗中) +X-KDE-Library=kcal_newexchange +Type=Service +ServiceTypes=KResources/Plugin +X-KDE-ResourceFamily=calendar +X-KDE-ResourceType=newexchange diff --git a/kresources/newexchange/kcal_newexchange_final.desktop b/kresources/newexchange/kcal_newexchange_final.desktop new file mode 100644 index 000000000..fd159051d --- /dev/null +++ b/kresources/newexchange/kcal_newexchange_final.desktop @@ -0,0 +1,49 @@ +[Desktop Entry] +Hidden=true +Name=Calendar on an Exchange Server +Name[af]=Kalender op 'n Exchange bediener +Name[bg]=Календар на сървър Exchange +Name[br]=Deiziadur en ur servijer Exchange +Name[ca]=Calendari a un servidor Exchange +Name[cs]=Kalendář na serveru Exchange +Name[da]=Kalender på en Exchange-server +Name[de]=Kalender auf einem Exchange-Server +Name[el]=Ημερολόγιο σε εξυπηρετητή Exchange +Name[es]=Calendario en un servidor Exchange +Name[et]=Kalender Exchange-serveris +Name[eu]=Egutegia Exchange zerbitzari batean +Name[fa]=تقویم روی یک کارساز مبادله +Name[fi]=Kalenteri Exchange-palvelimella +Name[fr]=Agenda sur un serveur Exchange +Name[fy]=Aginda op in Exchange-tsjinner +Name[ga]=Féilire ar Fhreastalaí Exchange +Name[gl]=Calendario nun servidor Exchange +Name[hu]=Exchange 2000-kiszolgáló naptára +Name[is]=Dagatal á Exchange þjóni +Name[it]=Calendario su un server Exchange +Name[ja]=Exchange サーバのカレンダー +Name[ka]=კალენდარი Exchange სერვერზე +Name[kk]=Exchange серверіндегі күнтізбе +Name[km]=ប្រតិទិនលើម៉ាស៊ីនបម្រើ Exchange +Name[lt]=Kalendorius Exchange serveryje +Name[mk]=Календар на Exchange-сервер +Name[ms]=Kalendar pada pelayan Exchange +Name[nb]=Kalender på en Exchange-tjener +Name[nds]=Kalenner op en Exchange-Server +Name[ne]=एक्सचेन्ज सर्भरमा क्यालेन्डर +Name[nl]=Agenda op een Exchange-server +Name[nn]=Kalender på ein Exchange-tenar +Name[pl]=Kalendarz na serwerze Exchange +Name[pt]=Calendário em servidor Exchange +Name[pt_BR]=Calendário em um Servidor Exchange +Name[ru]=Календарь на сервере Exchange +Name[sk]=Kalendár na Exchange serveri +Name[sl]=Koledar na strežniku Exchange +Name[sr]=Календар на Exchange серверу +Name[sr@Latn]=Kalendar na Exchange serveru +Name[sv]=Kalender på en Exchange-server +Name[ta]=ஒரு பரிமாற்ற சேவகனில் நாட்காட்சி +Name[tr]=Bir Exchange Sunucusu üzerinde Takvim +Name[uk]=Календар на сервері Exchange +Name[zh_CN]=Exchange 服务器上的日历 +Name[zh_TW]=Exchanger 伺服器上的行事曆 diff --git a/kresources/newexchange/kcal_resourceexchange.cpp b/kresources/newexchange/kcal_resourceexchange.cpp new file mode 100644 index 000000000..4c9f7726d --- /dev/null +++ b/kresources/newexchange/kcal_resourceexchange.cpp @@ -0,0 +1,54 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + + 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 General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "exchangecalendaradaptor.h" + +#include "kcal_resourceexchange.h" +#include <groupwaredownloadjob.h> +#include <groupwareuploadjob.h> +#include <kresources_groupwareprefs.h> + +using namespace KCal; + +ResourceExchange::ResourceExchange() + : ResourceGroupwareBase() +{ + init(); +} + +ResourceExchange::ResourceExchange( const KConfig *config ) + : ResourceGroupwareBase( config ) +{ + init(); + if ( config ) readConfig( config ); +} + +void ResourceExchange::init() +{ + setType( "ResourceExchange" ); + setPrefs( createPrefs() ); + setFolderLister( new KPIM::FolderLister( KPIM::FolderLister::Calendar ) ); + setAdaptor( new ExchangeCalendarAdaptor() ); + + ResourceGroupwareBase::init(); +} + +#include "kcal_resourceexchange.moc" diff --git a/kresources/newexchange/kcal_resourceexchange.h b/kresources/newexchange/kcal_resourceexchange.h new file mode 100644 index 000000000..2a6d01675 --- /dev/null +++ b/kresources/newexchange/kcal_resourceexchange.h @@ -0,0 +1,45 @@ + /* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + + 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_RESOURCEEXCHANGE_H +#define KCAL_RESOURCEEXCHANGE_H + +#include <kcal_resourcegroupwarebase.h> + +namespace KCal { + +/** + This class provides a resource for accessing an Exchange server +*/ +class KDE_EXPORT ResourceExchange : public ResourceGroupwareBase +{ + Q_OBJECT + public: + ResourceExchange(); + ResourceExchange( const KConfig * ); + + protected: + void init(); +}; + +} + +#endif diff --git a/kresources/newexchange/kcal_resourceexchange_plugin.cpp b/kresources/newexchange/kcal_resourceexchange_plugin.cpp new file mode 100644 index 000000000..e2b1d5396 --- /dev/null +++ b/kresources/newexchange/kcal_resourceexchange_plugin.cpp @@ -0,0 +1,28 @@ +/* + This file is part of kdepim. + + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + 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_resourceexchange.h" +#include "kcal_resourcegroupwarebaseconfig.h" + +using namespace KCal; + +typedef KRES::PluginFactory< ResourceExchange, ResourceGroupwareBaseConfig > ExchangeFactory; +K_EXPORT_COMPONENT_FACTORY( kcal_newexchange, ExchangeFactory ) |