/* This file is part of the exchange resource. Copyright (c) 2004 Reinhold Kainhofer 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 #include #include using namespace TDEABC; 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( TQDomDocument &doc, TQDomElement &props ) { TQDomAttr att_c = doc.createAttribute( "xmlns:c" ); att_c.setValue( "urn:schemas:contacts:" ); doc.documentElement().setAttributeNode( att_c ); TQDomAttr 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 TQDomElement &node, Addressee &addressee, int type, const TQString &street, const TQString &pobox, const TQString &location, const TQString &postalcode, const TQString &state, const TQString &country, const TQString &/*countycode*/ ) { bool haveAddr = false; Address addr( type ); TQString 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 TQDomElement &node, Addressee &addressee ) { TQString 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"<writeUrl( addressee.preferredEmail(), tmpstr ); KCal::FreeBusyUrlStore::self()->sync(); } // General stuff: TQStringList 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( TDEABC::Secrecy::Public ); break; case 1: case 2: addressee.setSecrecy( TDEABC::Secrecy::Private ); break; case 3: addressee.setSecrecy( TDEABC::Secrecy::Confidential ); break; default: kdWarning() << "Unknown sensitivity: " << tmplng << endl; } } #define insertPhone( name, type ) \ if ( WebdavHandler::extractString( node, name, tmpstr ) ) \ addressee.insertPhoneNumber( TDEABC::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 ); TQDateTime 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 TQDomDocument& davdata ) { // TODO: Handle multiple addressees per reply! Addressee::List list; TQDomElement prop = davdata.documentElement().namedItem( "response" ) .namedItem( "propstat" ).namedItem( "prop" ).toElement(); if ( prop.isNull() ) { kdDebug()<<"ExchangeConverterContact::parseWebDAV, no response->propstat->prop element!"< 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() ); TQString fburl = KCal::FreeBusyUrlStore::self()->readUrl( addr.preferredEmail() ); if ( !fburl.isEmpty() ) { domContactProperty( "fburl", fburl ); } /* FIXME: This doesn't work! TQStringList cats = addr.categories(); if ( cats.isEmpty() ) { TQDomElement catsnode = WebdavHandler::addElementNS( doc, prop, "urn:schemas-microsoft-com:office:office", "Keywords" ); for ( TQStringList::Iterator it = cats.begin(); it != cats.end(); ++it ) { WebdavHandler::addElementNS( doc, catsnode, "xml:", "v", *it ); } } else { // TQDomElement catsnode = addProperty( doc, prop, // "urn:schemas-microsoft-com:office:office", "Keywords", "" ); }*/ // Exchange sentitivity values: // 0 None, 1 Personal, 2 Private, 3 Company Confidential TQString value; switch ( addr.secrecy().type() ) { case TDEABC::Secrecy::Private: value = "2"; break; case TDEABC::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? /* TQDate dt = addr.birthday().date(); TQString str = (dt.isValid())?(dt.toString( TQt::ISODate )):(TQString()); if ( !str.isEmpty() ) { TQDomElement el = domContactProperty( "bday", str ); el.setAttribute( "b:dt", "date" ); } dt = TQDate::fromString( addr.custom( "KADDRESSBOOK", "X-Anniversary" ), TQt::ISODate ); str = (dt.isValid())?(dt.toString( TQt::ISODate )):(TQString()); if ( !str.isEmpty() ) { TQDomElement el = domContactProperty( "weddinganniversary", str ); el.setAttribute( "b:dt", "date" ); }*/ // ? TODO: timeZone() /* TDEABC::Geo geo = addr.geo(); if ( geo.isValid() ) { // TODO: Do we need to set any other attribute to make it a float? TQDomAttr att_cal = doc.createAttribute( "xmlns:cal" ); att_cal.setValue( "urn:schemas:calendar:" ); doc.documentElement().setAttributeNode( att_cal ); TQDomElement el = domCalendarProperty( "geolatitude", TQString::number( geo.latitude() ) ); el.setAttribute( "b:dt", "float" ); el = domCalendarProperty( "geolongitude", TQString::number( geo.longitude() ) ); el.setAttribute( "b:dt", "float" ); } */ domContactProperty( "textdescription", addr.note() ); // TODO:usercertificate // TODO: custom fields kdDebug()<<"DOM document: "<