kabc Library: ldifconverter.cpp Source File (kabc Library)

| # kabc Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ldifconverter.cpp

    00001 /*
    00002     This file is part of libkabc.
    00003     Copyright (c) 2003  Helge Deller <deller@kde.org>
    00004
    00005     This library is free software; you can redistribute it and/or
    00006     modify it under the terms of the GNU Library General Public
    00007     License as published by the Free Software Foundation; either
    00008     version 2 of the License, or (at your option) any later version.
    00009
    00010     This library is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013     Library General Public License for more details.
    00014
    00015     You should have received a copy of the GNU Library General Public License
    00016     along with this library; see the file COPYING.LIB.  If not, write to
    00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018     Boston, MA 02111-1307, USA.
    00019 */
    00020
    00021
    00022 /*
    00023     Useful links:
    00024         - http://tldp.org/HOWTO/LDAP-Implementation-HOWTO/schemas.html
    00025         - http://www.faqs.org/rfcs/rfc2849.html
    00026
    00027     Not yet handled items:
    00028         - objectclass microsoftaddressbook
    00029                 - info,
    00030                 - initials,
    00031                 - otherfacsimiletelephonenumber,
    00032                 - otherpager,
    00033                 - physicaldeliveryofficename,
    00034 */
    00035
    00036 #include <qstring.h>
    00037 #include <qstringlist.h>
    00038 #include <qregexp.h>
    00039 #include <qtextstream.h>
    00040
    00041 #include <klocale.h>
    00042 #include <kdebug.h>
    00043 #include <kmdcodec.h>
    00044
    00045 #include "addressee.h"
    00046 #include "address.h"
    00047
    00048 #include "ldif.h"
    00049 #include "ldifconverter.h"
    00050 #include "vcardconverter.h"
    00051
    00052 using namespace KABC;
    00053
    00054 /* generate LDIF stream */
    00055
    00056 bool LDIFConverter::addresseeToLDIF( const AddresseeList &addrList, QString &str )
    00057 {
    00058   AddresseeList::ConstIterator it;
    00059   for ( it = addrList.begin(); it != addrList.end(); ++it ) {
    00060     addresseeToLDIF( *it, str );
    00061   }
    00062   return true;
    00063 }
    00064
    00065
    00066
    00067 static void ldif_out( QTextStream &t, QString formatStr, QString value )
    00068 {
    00069   if ( value.isEmpty() )
    00070     return;
    00071
    00072   QCString txt = LDIF::assembleLine( formatStr, value, 72 );
    00073
    00074   // write the string
    00075   t << QString::fromUtf8(txt) << "\n";
    00076 }
    00077
    00078 bool LDIFConverter::addresseeToLDIF( const Addressee &addr, QString &str )
    00079 {
    00080   if ( addr.isEmpty() )
    00081       return false;
    00082
    00083   QTextStream t( str, IO_WriteOnly|IO_Append );
    00084   t.setEncoding( QTextStream::UnicodeUTF8 );
    00085
    00086   const Address homeAddr = addr.address( Address::Home );
    00087   const Address workAddr = addr.address( Address::Work );
    00088
    00089   ldif_out( t, "dn", QString( "cn=%1,mail=%2" )
    00090             .arg( addr.formattedName().simplifyWhiteSpace() )
    00091             .arg( addr.preferredEmail() ) );
    00092   ldif_out( t, "givenname", addr.givenName() );
    00093   ldif_out( t, "sn", addr.familyName() );
    00094   ldif_out( t, "cn", addr.formattedName().simplifyWhiteSpace() );
    00095   ldif_out( t, "uid", addr.uid() );
    00096   ldif_out( t, "nickname", addr.nickName() );
    00097   ldif_out( t, "xmozillanickname", addr.nickName() );
    00098
    00099   ldif_out( t, "mail", addr.preferredEmail() );
    00100   if ( addr.emails().count() > 1 )
    00101     ldif_out( t, "mozillasecondemail", addr.emails()[ 1 ] );
    00102 //ldif_out( t, "mozilla_AIMScreenName: %1\n", "screen_name" );
    00103
    00104   ldif_out( t, "telephonenumber", addr.phoneNumber( PhoneNumber::Work ).number() );
    00105   ldif_out( t, "facsimiletelephonenumber", addr.phoneNumber( PhoneNumber::Fax ).number() );
    00106   ldif_out( t, "homephone", addr.phoneNumber( PhoneNumber::Home ).number() );
    00107   ldif_out( t, "mobile", addr.phoneNumber( PhoneNumber::Cell ).number() ); // Netscape 7
    00108   ldif_out( t, "cellphone", addr.phoneNumber( PhoneNumber::Cell ).number() ); // Netscape 4.x
    00109   ldif_out( t, "pager", addr.phoneNumber( PhoneNumber::Pager ).number() );
    00110   ldif_out( t, "pagerphone", addr.phoneNumber( PhoneNumber::Pager ).number() );
    00111
    00112   ldif_out( t, "streethomeaddress", homeAddr.street() );
    00113   ldif_out( t, "postalcode", workAddr.postalCode() );
    00114   ldif_out( t, "postofficebox", workAddr.postOfficeBox() );
    00115
    00116   QStringList streets = QStringList::split( '\n', homeAddr.street() );
    00117   if ( streets.count() > 0 )
    00118     ldif_out( t, "homepostaladdress", streets[ 0 ] ); // Netscape 7
    00119   if ( streets.count() > 1 )
    00120     ldif_out( t, "mozillahomepostaladdress2", streets[ 1 ] ); // Netscape 7
    00121   ldif_out( t, "mozillahomelocalityname", homeAddr.locality() ); // Netscape 7
    00122   ldif_out( t, "mozillahomestate", homeAddr.region() );
    00123   ldif_out( t, "mozillahomepostalcode", homeAddr.postalCode() );
    00124   ldif_out( t, "mozillahomecountryname", Address::ISOtoCountry(homeAddr.country()) );
    00125   ldif_out( t, "locality", workAddr.locality() );
    00126   ldif_out( t, "streetaddress", workAddr.street() ); // Netscape 4.x
    00127
    00128   streets = QStringList::split( '\n', workAddr.street() );
    00129   if ( streets.count() > 0 )
    00130     ldif_out( t, "postaladdress", streets[ 0 ] );
    00131   if ( streets.count() > 1 )
    00132     ldif_out( t, "mozillapostaladdress2", streets[ 1 ] );
    00133   ldif_out( t, "countryname", Address::ISOtoCountry(workAddr.country()) );
    00134   ldif_out( t, "l", workAddr.locality() );
    00135   ldif_out( t, "c", Address::ISOtoCountry(workAddr.country()) );
    00136   ldif_out( t, "st", workAddr.region() );
    00137
    00138   ldif_out( t, "title", addr.title() );
    00139   ldif_out( t, "vocation", addr.prefix() );
    00140   ldif_out( t, "ou", addr.role() );
    00141   ldif_out( t, "o", addr.organization() );
    00142   ldif_out( t, "organization", addr.organization() );
    00143   ldif_out( t, "organizationname", addr.organization() );
    00144   ldif_out( t, "department", addr.custom("KADDRESSBOOK", "X-Department") );
    00145   ldif_out( t, "workurl", addr.url().prettyURL() );
    00146   ldif_out( t, "homeurl", addr.url().prettyURL() );
    00147   ldif_out( t, "description", addr.note() );
    00148   if (addr.revision().isValid())
    00149     ldif_out(t, "modifytimestamp", dateToVCardString( addr.revision()) );
    00150
    00151   t << "objectclass: top\n";
    00152   t << "objectclass: person\n";
    00153   t << "objectclass: organizationalPerson\n";
    00154
    00155   t << "\n";
    00156
    00157   return true;
    00158 }
    00159
    00160
    00161 /* convert from LDIF stream */
    00162
    00163 bool LDIFConverter::LDIFToAddressee( const QString &str, AddresseeList &addrList, QDateTime dt )
    00164 {
    00165   if (str.isEmpty())
    00166      return true;
    00167
    00168   bool endldif = false, end = false;
    00169   LDIF ldif;
    00170   LDIF::ParseVal ret;
    00171   const char *latinstr = str.latin1();
    00172   int latinstrlen = qstrlen( latinstr );
    00173   QByteArray data;
    00174   Addressee a;
    00175   Address homeAddr, workAddr;
    00176
    00177   data.setRawData( latinstr, latinstrlen );
    00178   ldif.setLDIF( data );
    00179   if (!dt.isValid())
    00180     dt = QDateTime::currentDateTime();
    00181   a.setRevision(dt);
    00182   homeAddr = Address( Address::Home );
    00183   workAddr = Address( Address::Work );
    00184
    00185   do {
    00186     ret = ldif.nextItem();
    00187     switch ( ret ) {
    00188       case LDIF::Item: {
    00189         QString fieldname = ldif.attr().lower();
    00190         QString value = QString::fromUtf8( ldif.val(), ldif.val().size() );
    00191         evaluatePair( a, homeAddr, workAddr, fieldname, value );
    00192         break;
    00193       }
    00194       case LDIF::EndEntry:
    00195       // if the new address is not empty, append it
    00196         if ( !a.formattedName().isEmpty() || !a.name().isEmpty() ||
    00197           !a.familyName().isEmpty() ) {
    00198           if ( !homeAddr.isEmpty() )
    00199             a.insertAddress( homeAddr );
    00200           if ( !workAddr.isEmpty() )
    00201             a.insertAddress( workAddr );
    00202           addrList.append( a );
    00203         }
    00204         a = Addressee();
    00205         a.setRevision(dt);
    00206         homeAddr = Address( Address::Home );
    00207         workAddr = Address( Address::Work );
    00208         break;
    00209       case LDIF::MoreData: {
    00210         if ( endldif )
    00211           end = true;
    00212         else {
    00213           ldif.endLDIF();
    00214           endldif = true;
    00215           break;
    00216         }
    00217       }
    00218       default:
    00219         break;
    00220     }
    00221   } while ( !end );
    00222
    00223   data.resetRawData( latinstr, latinstrlen );
    00224
    00225   return true;
    00226 }
    00227
    00228 bool LDIFConverter::evaluatePair( Addressee &a, Address &homeAddr,
    00229                                   Address &workAddr,
    00230                                   QString &fieldname, QString &value )
    00231 {
    00232   if ( fieldname == QString::fromLatin1( "dn" ) ) // ignore & return false!
    00233     return false;
    00234
    00235   if ( fieldname.startsWith("#") ) {
    00236     return true;
    00237   }
    00238
    00239   if ( fieldname.isEmpty() && !a.note().isEmpty() ) {
    00240     // some LDIF export filters are borken and add additional
    00241     // comments on stand-alone lines. Just add them to the notes for now.
    00242     a.setNote( a.note() + "\n" + value );
    00243     return true;
    00244   }
    00245
    00246   if ( fieldname == QString::fromLatin1( "givenname" ) ) {
    00247     a.setGivenName( value );
    00248     return true;
    00249   }
    00250
    00251   if ( fieldname == QString::fromLatin1( "xmozillanickname") ||
    00252        fieldname == QString::fromLatin1( "nickname") ) {
    00253     a.setNickName( value );
    00254     return true;
    00255   }
    00256
    00257   if ( fieldname == QString::fromLatin1( "sn" ) ) {
    00258     a.setFamilyName( value );
    00259     return true;
    00260   }
    00261
    00262   if ( fieldname == QString::fromLatin1( "uid" ) ) {
    00263     a.setUid( value );
    00264     return true;
    00265   }
    00266   if ( fieldname == QString::fromLatin1( "mail" ) ||
    00267        fieldname == QString::fromLatin1( "mozillasecondemail" ) ) { // mozilla
    00268     if ( a.emails().findIndex( value ) == -1 )
    00269       a.insertEmail( value );
    00270     return true;
    00271   }
    00272
    00273   if ( fieldname == QString::fromLatin1( "title" ) ) {
    00274     a.setTitle( value );
    00275     return true;
    00276   }
    00277
    00278   if ( fieldname == QString::fromLatin1( "vocation" ) ) {
    00279     a.setPrefix( value );
    00280     return true;
    00281   }
    00282
    00283   if ( fieldname == QString::fromLatin1( "cn" ) ) {
    00284     a.setFormattedName( value );
    00285     return true;
    00286   }
    00287
    00288   if ( fieldname == QString::fromLatin1( "o" ) ||
    00289        fieldname == QString::fromLatin1( "organization" ) ||      // Exchange
    00290        fieldname == QString::fromLatin1( "organizationname" ) ) { // Exchange
    00291     a.setOrganization( value );
    00292     return true;
    00293   }
    00294
    00295   if ( fieldname == QString::fromLatin1( "description" ) ) {
    00296 addComment:
    00297     if ( !a.note().isEmpty() )
    00298       a.setNote( a.note() + "\n" );
    00299     a.setNote( a.note() + value );
    00300     return true;
    00301   }
    00302
    00303   if ( fieldname == QString::fromLatin1( "custom1" ) ||
    00304        fieldname == QString::fromLatin1( "custom2" ) ||
    00305        fieldname == QString::fromLatin1( "custom3" ) ||
    00306        fieldname == QString::fromLatin1( "custom4" ) ) {
    00307     goto addComment;
    00308   }
    00309
    00310   if ( fieldname == QString::fromLatin1( "homeurl" ) ||
    00311        fieldname == QString::fromLatin1( "workurl" ) ) {
    00312     if (a.url().isEmpty()) {
    00313       a.setUrl( KURL( value ) );
    00314       return true;
    00315     }
    00316     if ( a.url().prettyURL() == KURL(value).prettyURL() )
    00317       return true;
    00318     // TODO: current version of kabc only supports one URL.
    00319     // TODO: change this with KDE 4
    00320   }
    00321
    00322   if ( fieldname == QString::fromLatin1( "homephone" ) ) {
    00323     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Home ) );
    00324     return true;
    00325   }
    00326
    00327   if ( fieldname == QString::fromLatin1( "telephonenumber" ) ) {
    00328     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) );
    00329     return true;
    00330   }
    00331
    00332   if ( fieldname == QString::fromLatin1( "mobile" ) ) {     // mozilla/Netscape 7
    00333     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) );
    00334     return true;
    00335   }
    00336
    00337   if ( fieldname == QString::fromLatin1( "cellphone" ) ) {
    00338     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) );
    00339     return true;
    00340   }
    00341
    00342   if ( fieldname == QString::fromLatin1( "pager" )  ||       // mozilla
    00343        fieldname == QString::fromLatin1( "pagerphone" ) ) {  // mozilla
    00344     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Pager ) );
    00345     return true;
    00346   }
    00347
    00348   if ( fieldname == QString::fromLatin1( "facsimiletelephonenumber" ) ) {
    00349     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Fax ) );
    00350     return true;
    00351   }
    00352
    00353   if ( fieldname == QString::fromLatin1( "xmozillaanyphone" ) ) { // mozilla
    00354     a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) );
    00355     return true;
    00356   }
    00357
    00358   if ( fieldname == QString::fromLatin1( "street" ) ||
    00359        fieldname == QString::fromLatin1( "streethomeaddress" ) ) {
    00360     homeAddr.setStreet( value );
    00361     return true;
    00362   }
    00363
    00364   if ( fieldname == QString::fromLatin1( "postaladdress" ) ) {  // mozilla
    00365     workAddr.setStreet( value );
    00366     return true;
    00367   }
    00368
    00369   if ( fieldname == QString::fromLatin1( "mozillapostaladdress2" ) ) {  // mozilla
    00370     workAddr.setStreet( workAddr.street() + QString::fromLatin1( "\n" ) + value );
    00371     return true;
    00372   }
    00373
    00374   if ( fieldname == QString::fromLatin1( "postalcode" ) ) {
    00375     workAddr.setPostalCode( value );
    00376     return true;
    00377   }
    00378
    00379   if ( fieldname == QString::fromLatin1( "postofficebox" ) ) {
    00380     workAddr.setPostOfficeBox( value );
    00381     return true;
    00382   }
    00383
    00384   if ( fieldname == QString::fromLatin1( "homepostaladdress" ) ) {  // Netscape 7
    00385     homeAddr.setStreet( value );
    00386     return true;
    00387   }
    00388
    00389   if ( fieldname == QString::fromLatin1( "mozillahomepostaladdress2" ) ) {  // mozilla
    00390     homeAddr.setStreet( homeAddr.street() + QString::fromLatin1( "\n" ) + value );
    00391     return true;
    00392   }
    00393
    00394   if ( fieldname == QString::fromLatin1( "mozillahomelocalityname" ) ) {  // mozilla
    00395     homeAddr.setLocality( value );
    00396     return true;
    00397   }
    00398
    00399   if ( fieldname == QString::fromLatin1( "mozillahomestate" )   ) { // mozilla
    00400     homeAddr.setRegion( value );
    00401     return true;
    00402   }
    00403
    00404   if ( fieldname == QString::fromLatin1( "mozillahomepostalcode" ) ) {  // mozilla
    00405     homeAddr.setPostalCode( value );
    00406     return true;
    00407   }
    00408
    00409   if ( fieldname == QString::fromLatin1( "mozillahomecountryname" ) ) { // mozilla
    00410     if ( value.length() <= 2 )
    00411       value = Address::ISOtoCountry(value);
    00412     homeAddr.setCountry( value );
    00413     return true;
    00414   }
    00415
    00416   if ( fieldname == QString::fromLatin1( "locality" ) ) {
    00417     workAddr.setLocality( value );
    00418     return true;
    00419   }
    00420
    00421   if ( fieldname == QString::fromLatin1( "streetaddress" ) ) { // Netscape 4.x
    00422     workAddr.setStreet( value );
    00423     return true;
    00424   }
    00425
    00426   if ( fieldname == QString::fromLatin1( "countryname" ) ||
    00427        fieldname == QString::fromLatin1( "c" ) ) {  // mozilla
    00428     if ( value.length() <= 2 )
    00429       value = Address::ISOtoCountry(value);
    00430     workAddr.setCountry( value );
    00431     return true;
    00432   }
    00433
    00434   if ( fieldname == QString::fromLatin1( "l" ) ) {  // mozilla
    00435     workAddr.setLocality( value );
    00436     return true;
    00437   }
    00438
    00439   if ( fieldname == QString::fromLatin1( "st" ) ) {
    00440     workAddr.setRegion( value );
    00441     return true;
    00442   }
    00443
    00444   if ( fieldname == QString::fromLatin1( "ou" ) ) {
    00445     a.setRole( value );
    00446     return true;
    00447   }
    00448
    00449   if ( fieldname == QString::fromLatin1( "department" ) ) {
    00450     a.insertCustom( "KADDRESSBOOK", "X-Department", value );
    00451     return true;
    00452   }
    00453
    00454   if ( fieldname == QString::fromLatin1( "member" ) ) {
    00455     // this is a mozilla list member (cn=xxx, mail=yyy)
    00456     QStringList list( QStringList::split( ',', value ) );
    00457     QString name, email;
    00458
    00459     QStringList::Iterator it;
    00460     for ( it = list.begin(); it != list.end(); ++it ) {
    00461       if ( (*it).startsWith( "cn=" ) )
    00462         name = (*it).mid( 3 ).stripWhiteSpace();
    00463       if ( (*it).startsWith( "mail=" ) )
    00464         email = (*it).mid( 5 ).stripWhiteSpace();
    00465     }
    00466     if ( !name.isEmpty() && !email.isEmpty() )
    00467       email = " <" + email + ">";
    00468     a.insertEmail( name + email );
    00469     a.insertCategory( i18n( "List of Emails" ) );
    00470     return true;
    00471   }
    00472
    00473   if ( fieldname == QString::fromLatin1( "modifytimestamp" ) ) {
    00474     if (value == QString::fromLatin1("0Z")) // ignore
    00475       return true;
    00476     QDateTime dt = VCardStringToDate( value );
    00477     if ( dt.isValid() ) {
    00478       a.setRevision(dt);
    00479       return true;
    00480     }
    00481   }
    00482
    00483   if ( fieldname == QString::fromLatin1( "objectclass" ) ) // ignore
    00484     return true;
    00485
    00486   kdWarning() << QString("LDIFConverter: Unknown field for '%1': '%2=%3'\n")
    00487                              .arg(a.formattedName()).arg(fieldname).arg(value);
    00488
    00489   return true;
    00490 }
    00491
    00492 /* The following functions are obsoleted. Similar functionality can be found
    00493  * in the LDIF class */
    00494
    00495 bool LDIFConverter::parseSingleLine( Addressee &a, Address &homeAddr,
    00496                                      Address &workAddr, QString &line )
    00497 {
    00498   if ( line.isEmpty() )
    00499     return true;
    00500
    00501   QString fieldname, value;
    00502   QByteArray val;
    00503
    00504   LDIF::splitLine( line.latin1(), fieldname, val );
    00505   value = QString::fromUtf8( val.data(), val.size() );
    00506   return evaluatePair( a, homeAddr, workAddr, fieldname, value);
    00507 }
    00508
    00509
    00510 bool LDIFConverter::splitLine( QString &line, QString &fieldname, QString &value)
    00511 {
    00512   QByteArray val;
    00513   bool ret = LDIF::splitLine( line.latin1(), fieldname, val );
    00514   value = QString::fromUtf8( val.data(), val.size() );
    00515   return ret;
    00516 }
    00517
    00518
    00519 QString LDIFConverter::makeLDIFfieldString( QString formatStr, QString value, bool allowEncode )
    00520 {
    00521   if ( value.isEmpty() )
    00522     return QString();
    00523
    00524   // append format if not given
    00525   if (formatStr.find(':') == -1)
    00526     formatStr.append(": %1\n");
    00527
    00528   // check if base64-encoding is needed
    00529   bool printable = true;
    00530   unsigned int i, len;
    00531   len = value.length();
    00532   for (i = 0; i<len; ++i ) {
    00533      if (!value[i].isPrint()) {
    00534         printable = false;
    00535         break;
    00536      }
    00537   }
    00538
    00539   if (printable) // always encode if we find special chars...
    00540     printable = (value.find('\n') == -1);
    00541
    00542   if (!printable && allowEncode) {
    00543     // encode to base64
    00544     value = KCodecs::base64Encode( value.utf8() );
    00545     int p = formatStr.find(':');
    00546     if (p>=0)
    00547       formatStr.insert(p, ':');
    00548   }
    00549
    00550   // generate the new string and split it to 72 chars/line
    00551   QCString txt = (formatStr.arg(value)).utf8();
    00552
    00553   if (allowEncode) {
    00554     len = txt.length();
    00555     if (len && txt[len-1] == '\n')
    00556       --len;
    00557     i = 72;
    00558     while (i < len) {
    00559       txt.insert(i, "\n ");
    00560       i += 72+1;
    00561       len += 2;
    00562     }
    00563   }
    00564
    00565   return QString::fromUtf8(txt);
    00566 }
    00567

This file is part of the documentation for kabc Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:30 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003