kabc
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., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 /* 00022 Useful links: 00023 - http://tldp.org/HOWTO/LDAP-Implementation-HOWTO/schemas.html 00024 - http://www.faqs.org/rfcs/rfc2849.html 00025 00026 Not yet handled items: 00027 - objectclass microsoftaddressbook 00028 - info, 00029 - initials, 00030 - otherfacsimiletelephonenumber, 00031 - otherpager, 00032 - physicaldeliveryofficename, 00033 */ 00034 00035 #include "ldifconverter.h" 00036 #include "vcardconverter.h" 00037 #include "address.h" 00038 #include "addressee.h" 00039 00040 #include "ldif_p.h" 00041 00042 #include <kdebug.h> 00043 #include <klocale.h> 00044 00045 #include <QtCore/QRegExp> 00046 #include <QtCore/QStringList> 00047 #include <QtCore/QTextCodec> 00048 #include <QtCore/QTextStream> 00049 00050 using namespace KABC; 00051 00052 /* generate LDIF stream */ 00053 00054 bool LDIFConverter::addresseeToLDIF( const AddresseeList &addrList, QString &str ) 00055 { 00056 AddresseeList::ConstIterator it; 00057 for ( it = addrList.begin(); it != addrList.end(); ++it ) { 00058 addresseeToLDIF( *it, str ); 00059 } 00060 return true; 00061 } 00062 00063 static void ldif_out( QTextStream &t, const QString &formatStr, 00064 const QString &value ) 00065 { 00066 if ( value.isEmpty() ) { 00067 return; 00068 } 00069 00070 QByteArray txt = Ldif::assembleLine( formatStr, value, 72 ); 00071 00072 // write the string 00073 t << QString::fromUtf8( txt ) << "\n"; 00074 } 00075 00076 bool LDIFConverter::addresseeToLDIF( const Addressee &addr, QString &str ) 00077 { 00078 if ( addr.isEmpty() ) { 00079 return false; 00080 } 00081 00082 QTextStream t( &str, QIODevice::WriteOnly|QIODevice::Append ); 00083 t.setCodec( QTextCodec::codecForName( "UTF-8" ) ); 00084 00085 const Address homeAddr = addr.address( Address::Home ); 00086 const Address workAddr = addr.address( Address::Work ); 00087 00088 ldif_out( t, QLatin1String( "dn" ), QString::fromLatin1( "cn=%1,mail=%2" ). 00089 arg( addr.formattedName().simplified() ). 00090 arg( addr.preferredEmail() ) ); 00091 ldif_out( t, QLatin1String( "givenname" ), addr.givenName() ); 00092 ldif_out( t, QLatin1String( "sn" ), addr.familyName() ); 00093 ldif_out( t, QLatin1String( "cn" ), addr.formattedName().simplified() ); 00094 ldif_out( t, QLatin1String( "uid" ), addr.uid() ); 00095 ldif_out( t, QLatin1String( "nickname" ), addr.nickName() ); 00096 ldif_out( t, QLatin1String( "xmozillanickname" ), addr.nickName() ); 00097 ldif_out( t, QLatin1String( "mozillanickname" ), addr.nickName() ); 00098 00099 ldif_out( t, QLatin1String( "mail" ), addr.preferredEmail() ); 00100 if ( addr.emails().count() > 1 ) { 00101 ldif_out( t, QLatin1String( "mozillasecondemail" ), addr.emails()[ 1 ] ); 00102 } 00103 //ldif_out( t, "mozilla_AIMScreenName: %1\n", "screen_name" ); 00104 00105 ldif_out( t, QLatin1String( "telephonenumber" ), 00106 addr.phoneNumber( PhoneNumber::Work ).number() ); 00107 ldif_out( t, QLatin1String( "facsimiletelephonenumber" ), 00108 addr.phoneNumber( PhoneNumber::Fax ).number() ); 00109 ldif_out( t, QLatin1String( "homephone" ), 00110 addr.phoneNumber( PhoneNumber::Home ).number() ); 00111 ldif_out( t, QLatin1String( "mobile" ), 00112 addr.phoneNumber( PhoneNumber::Cell ).number() ); // Netscape 7 00113 ldif_out( t, QLatin1String( "cellphone" ), 00114 addr.phoneNumber( PhoneNumber::Cell ).number() ); // Netscape 4.x 00115 ldif_out( t, QLatin1String( "pager" ), 00116 addr.phoneNumber( PhoneNumber::Pager ).number() ); 00117 ldif_out( t, QLatin1String( "pagerphone" ), 00118 addr.phoneNumber( PhoneNumber::Pager ).number() ); 00119 00120 ldif_out( t, QLatin1String( "streethomeaddress" ), homeAddr.street() ); 00121 ldif_out( t, QLatin1String( "postalcode" ), workAddr.postalCode() ); 00122 ldif_out( t, QLatin1String( "postofficebox" ), workAddr.postOfficeBox() ); 00123 00124 QStringList streets = homeAddr.street().split( QLatin1Char( '\n' ) ); 00125 const int numberOfStreets(streets.count()); 00126 if ( numberOfStreets > 0 ) { 00127 ldif_out( t, QLatin1String( "homepostaladdress" ), streets[ 0 ] ); // Netscape 7 00128 } 00129 if ( numberOfStreets > 1 ) { 00130 ldif_out( t, QLatin1String( "mozillahomepostaladdress2" ), streets[ 1 ] ); // Netscape 7 00131 } 00132 ldif_out( t, QLatin1String( "mozillahomelocalityname" ), homeAddr.locality() ); // Netscape 7 00133 ldif_out( t, QLatin1String( "mozillahomestate" ), homeAddr.region() ); 00134 ldif_out( t, QLatin1String( "mozillahomepostalcode" ), homeAddr.postalCode() ); 00135 ldif_out( t, QLatin1String( "mozillahomecountryname" ), 00136 Address::ISOtoCountry( homeAddr.country() ) ); 00137 ldif_out( t, QLatin1String( "locality" ), workAddr.locality() ); 00138 ldif_out( t, QLatin1String( "streetaddress" ), workAddr.street() ); // Netscape 4.x 00139 00140 streets = workAddr.street().split( QLatin1Char( '\n' ) ); 00141 if ( streets.count() > 0 ) { 00142 ldif_out( t, QLatin1String( "postaladdress" ), streets[ 0 ] ); 00143 } 00144 if ( streets.count() > 1 ) { 00145 ldif_out( t, QLatin1String( "mozillapostaladdress2" ), streets[ 1 ] ); 00146 } 00147 ldif_out( t, QLatin1String( "countryname" ), Address::ISOtoCountry( workAddr.country() ) ); 00148 ldif_out( t, QLatin1String( "l" ), workAddr.locality() ); 00149 ldif_out( t, QLatin1String( "c" ), Address::ISOtoCountry( workAddr.country() ) ); 00150 ldif_out( t, QLatin1String( "st" ), workAddr.region() ); 00151 00152 ldif_out( t, QLatin1String( "title" ), addr.title() ); 00153 ldif_out( t, QLatin1String( "vocation" ), addr.prefix() ); 00154 ldif_out( t, QLatin1String( "ou" ), addr.role() ); 00155 ldif_out( t, QLatin1String( "o" ), addr.organization() ); 00156 ldif_out( t, QLatin1String( "organization" ), addr.organization() ); 00157 ldif_out( t, QLatin1String( "organizationname" ), addr.organization() ); 00158 00159 // Compatibility with older kabc versions. 00160 if ( !addr.department().isEmpty() ) { 00161 ldif_out( t, QLatin1String( "department" ), addr.department() ); 00162 } else { 00163 ldif_out( t, QLatin1String( "department" ), addr.custom( QLatin1String( "KADDRESSBOOK" ), 00164 QLatin1String( "X-Department" ) ) ); 00165 } 00166 00167 ldif_out( t, QLatin1String( "workurl" ), addr.url().prettyUrl() ); 00168 ldif_out( t, QLatin1String( "homeurl" ), addr.url().prettyUrl() ); 00169 ldif_out( t, QLatin1String( "mozillahomeurl" ), addr.url().prettyUrl() ); 00170 00171 ldif_out( t, QLatin1String( "description" ), addr.note() ); 00172 if ( addr.revision().isValid() ) { 00173 ldif_out( t, QLatin1String( "modifytimestamp" ), dateToVCardString( addr.revision() ) ); 00174 } 00175 00176 const QDateTime birthday = addr.birthday(); 00177 if ( birthday.isValid() ) { 00178 const QDate date = birthday.date(); 00179 ldif_out( t, QLatin1String( "birthyear" ), QString::number( date.year() ) ); 00180 ldif_out( t, QLatin1String( "birthmonth" ), QString::number( date.month() ) ); 00181 ldif_out( t, QLatin1String( "birthday" ), QString::number( date.day() ) ); 00182 } 00183 00184 t << "objectclass: top\n"; 00185 t << "objectclass: person\n"; 00186 t << "objectclass: organizationalPerson\n"; 00187 00188 t << "\n"; 00189 00190 return true; 00191 } 00192 00193 /* convert from LDIF stream */ 00194 00195 bool LDIFConverter::LDIFToAddressee( const QString &str, AddresseeList &addrList, 00196 const QDateTime &dt ) 00197 { 00198 if ( str.isEmpty() ) { 00199 return true; 00200 } 00201 00202 bool endldif = false, end = false; 00203 Ldif ldif; 00204 Ldif::ParseValue ret; 00205 Addressee a; 00206 Address homeAddr, workAddr; 00207 int birthday = -1; 00208 int birthmonth = -1; 00209 int birthyear = -1; 00210 00211 ldif.setLdif( str.toLatin1() ); 00212 QDateTime qdt = dt; 00213 if ( !qdt.isValid() ) { 00214 qdt = QDateTime::currentDateTime(); 00215 } 00216 a.setRevision( qdt ); 00217 homeAddr = Address( Address::Home ); 00218 workAddr = Address( Address::Work ); 00219 00220 do { 00221 ret = ldif.nextItem(); 00222 switch ( ret ) { 00223 case Ldif::Item: 00224 { 00225 QString fieldname = ldif.attr().toLower(); 00226 QString value = QString::fromUtf8( ldif.value(), ldif.value().size() ); 00227 evaluatePair( a, homeAddr, workAddr, fieldname, value, birthday, birthmonth,birthyear ); 00228 break; 00229 } 00230 case Ldif::EndEntry: 00231 { 00232 // if the new address is not empty, append it 00233 QDateTime birthDate( QDate( birthyear, birthmonth, birthday ) ); 00234 if ( birthDate.isValid() ) { 00235 a.setBirthday( birthDate ); 00236 } 00237 00238 if ( !a.formattedName().isEmpty() || !a.name().isEmpty() || 00239 !a.familyName().isEmpty() ) { 00240 if ( !homeAddr.isEmpty() ) { 00241 a.insertAddress( homeAddr ); 00242 } 00243 if ( !workAddr.isEmpty() ) { 00244 a.insertAddress( workAddr ); 00245 } 00246 addrList.append( a ); 00247 } 00248 a = Addressee(); 00249 a.setRevision( qdt ); 00250 homeAddr = Address( Address::Home ); 00251 workAddr = Address( Address::Work ); 00252 } 00253 break; 00254 case Ldif::MoreData: 00255 { 00256 if ( endldif ) { 00257 end = true; 00258 } else { 00259 ldif.endLdif(); 00260 endldif = true; 00261 break; 00262 } 00263 } 00264 default: 00265 break; 00266 } 00267 } while ( !end ); 00268 00269 return true; 00270 } 00271 00272 bool LDIFConverter::evaluatePair( Addressee &a, Address &homeAddr, 00273 Address &workAddr, 00274 QString &fieldname, QString &value, int &birthday, int &birthmonth, int &birthyear ) 00275 { 00276 if ( fieldname == QLatin1String( "dn" ) ) { // ignore & return false! 00277 return false; 00278 } 00279 00280 if ( fieldname.startsWith( QLatin1Char( '#' ) ) ) { 00281 return true; 00282 } 00283 00284 if ( fieldname.isEmpty() && !a.note().isEmpty() ) { 00285 // some LDIF export filters are borken and add additional 00286 // comments on stand-alone lines. Just add them to the notes for now. 00287 a.setNote( a.note() + QLatin1Char( '\n' ) + value ); 00288 return true; 00289 } 00290 00291 if ( fieldname == QLatin1String( "givenname" ) ) { 00292 a.setGivenName( value ); 00293 return true; 00294 } 00295 00296 if ( fieldname == QLatin1String( "xmozillanickname" ) || 00297 fieldname == QLatin1String( "nickname" ) || 00298 fieldname == QLatin1String( "mozillanickname" ) ) { 00299 a.setNickName( value ); 00300 return true; 00301 } 00302 00303 if ( fieldname == QLatin1String( "sn" ) ) { 00304 a.setFamilyName( value ); 00305 return true; 00306 } 00307 00308 if ( fieldname == QLatin1String( "uid" ) ) { 00309 a.setUid( value ); 00310 return true; 00311 } 00312 if ( fieldname == QLatin1String( "mail" ) || 00313 fieldname == QLatin1String( "mozillasecondemail" ) ) { // mozilla 00314 if ( a.emails().indexOf( value ) == -1 ) { 00315 a.insertEmail( value ); 00316 } 00317 return true; 00318 } 00319 00320 if ( fieldname == QLatin1String( "title" ) ) { 00321 a.setTitle( value ); 00322 return true; 00323 } 00324 00325 if ( fieldname == QLatin1String( "vocation" ) ) { 00326 a.setPrefix( value ); 00327 return true; 00328 } 00329 00330 if ( fieldname == QLatin1String( "cn" ) ) { 00331 a.setFormattedName( value ); 00332 return true; 00333 } 00334 00335 if ( fieldname == QLatin1String( "o" ) || 00336 fieldname == QLatin1String( "organization" ) || // Exchange 00337 fieldname == QLatin1String( "organizationname" ) ) { // Exchange 00338 a.setOrganization( value ); 00339 return true; 00340 } 00341 00342 if ( fieldname == QLatin1String( "description" ) ) { 00343 addComment: 00344 if ( !a.note().isEmpty() ) { 00345 a.setNote( a.note() + QLatin1Char( '\n' ) ); 00346 } 00347 a.setNote( a.note() + value ); 00348 return true; 00349 } 00350 00351 if ( fieldname == QLatin1String( "custom1" ) || 00352 fieldname == QLatin1String( "custom2" ) || 00353 fieldname == QLatin1String( "custom3" ) || 00354 fieldname == QLatin1String( "custom4" ) ) { 00355 goto addComment; 00356 } 00357 00358 if ( fieldname == QLatin1String( "homeurl" ) || 00359 fieldname == QLatin1String( "workurl" ) || 00360 fieldname == QLatin1String( "mozillahomeurl" )) { 00361 if ( a.url().isEmpty() ) { 00362 a.setUrl( KUrl( value ) ); 00363 return true; 00364 } 00365 if ( a.url().prettyUrl() == KUrl( value ).prettyUrl() ) { 00366 return true; 00367 } 00368 // TODO: current version of kabc only supports one URL. 00369 // TODO: change this with KDE 4 00370 } 00371 00372 if ( fieldname == QLatin1String( "homephone" ) ) { 00373 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Home ) ); 00374 return true; 00375 } 00376 00377 if ( fieldname == QLatin1String( "telephonenumber" ) ) { 00378 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) ); 00379 return true; 00380 } 00381 00382 if ( fieldname == QLatin1String( "mobile" ) ) { // mozilla/Netscape 7 00383 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) ); 00384 return true; 00385 } 00386 00387 if ( fieldname == QLatin1String( "cellphone" ) ) { 00388 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) ); 00389 return true; 00390 } 00391 00392 if ( fieldname == QLatin1String( "pager" ) || // mozilla 00393 fieldname == QLatin1String( "pagerphone" ) ) { // mozilla 00394 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Pager ) ); 00395 return true; 00396 } 00397 00398 if ( fieldname == QLatin1String( "facsimiletelephonenumber" ) ) { 00399 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Fax ) ); 00400 return true; 00401 } 00402 00403 if ( fieldname == QLatin1String( "xmozillaanyphone" ) ) { // mozilla 00404 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) ); 00405 return true; 00406 } 00407 00408 if ( fieldname == QLatin1String( "street" ) || 00409 fieldname == QLatin1String( "streethomeaddress" ) || 00410 fieldname == QLatin1String( "mozillahomestreet" ) /*thunderbird*/ ) { 00411 homeAddr.setStreet( value ); 00412 return true; 00413 } 00414 00415 if ( fieldname == QLatin1String( "postaladdress" ) ) { // mozilla 00416 workAddr.setStreet( value ); 00417 return true; 00418 } 00419 00420 if ( fieldname == QLatin1String( "mozillapostaladdress2" ) ) { // mozilla 00421 workAddr.setStreet( workAddr.street() + QLatin1String( "\n" ) + value ); 00422 return true; 00423 } 00424 00425 if ( fieldname == QLatin1String( "postalcode" ) ) { 00426 workAddr.setPostalCode( value ); 00427 return true; 00428 } 00429 00430 if ( fieldname == QLatin1String( "postofficebox" ) ) { 00431 workAddr.setPostOfficeBox( value ); 00432 return true; 00433 } 00434 00435 if ( fieldname == QLatin1String( "homepostaladdress" ) ) { // Netscape 7 00436 homeAddr.setStreet( value ); 00437 return true; 00438 } 00439 00440 if ( fieldname == QLatin1String( "mozillahomepostaladdress2" ) ) { // mozilla 00441 homeAddr.setStreet( homeAddr.street() + QLatin1String( "\n" ) + value ); 00442 return true; 00443 } 00444 00445 if ( fieldname == QLatin1String( "mozillahomelocalityname" ) ) { // mozilla 00446 homeAddr.setLocality( value ); 00447 return true; 00448 } 00449 00450 if ( fieldname == QLatin1String( "mozillahomestate" ) ) { // mozilla 00451 homeAddr.setRegion( value ); 00452 return true; 00453 } 00454 00455 if ( fieldname == QLatin1String( "mozillahomepostalcode" ) ) { // mozilla 00456 homeAddr.setPostalCode( value ); 00457 return true; 00458 } 00459 00460 if ( fieldname == QLatin1String( "mozillahomecountryname" ) ) { // mozilla 00461 if ( value.length() <= 2 ) { 00462 value = Address::ISOtoCountry( value ); 00463 } 00464 homeAddr.setCountry( value ); 00465 return true; 00466 } 00467 00468 if ( fieldname == QLatin1String( "locality" ) ) { 00469 workAddr.setLocality( value ); 00470 return true; 00471 } 00472 00473 if ( fieldname == QLatin1String( "streetaddress" ) ) { // Netscape 4.x 00474 workAddr.setStreet( value ); 00475 return true; 00476 } 00477 00478 if ( fieldname == QLatin1String( "countryname" ) || 00479 fieldname == QLatin1String( "c" ) ) { // mozilla 00480 if ( value.length() <= 2 ) { 00481 value = Address::ISOtoCountry( value ); 00482 } 00483 workAddr.setCountry( value ); 00484 return true; 00485 } 00486 00487 if ( fieldname == QLatin1String( "l" ) ) { // mozilla 00488 workAddr.setLocality( value ); 00489 return true; 00490 } 00491 00492 if ( fieldname == QLatin1String( "st" ) ) { 00493 workAddr.setRegion( value ); 00494 return true; 00495 } 00496 00497 if ( fieldname == QLatin1String( "ou" ) ) { 00498 a.setRole( value ); 00499 return true; 00500 } 00501 00502 if ( fieldname == QLatin1String( "department" ) ) { 00503 a.setDepartment( value ); 00504 return true; 00505 } 00506 00507 if ( fieldname == QLatin1String( "member" ) ) { 00508 // this is a mozilla list member (cn=xxx, mail=yyy) 00509 QStringList list = value.split( QLatin1Char( ',' ) ); 00510 QString name, email; 00511 00512 QStringList::Iterator it; 00513 for ( it = list.begin(); it != list.end(); ++it ) { 00514 if ( (*it).startsWith( QLatin1String( "cn=" ) ) ) { 00515 name = (*it).mid( 3 ).trimmed(); 00516 } 00517 if ( (*it).startsWith( QLatin1String( "mail=" ) ) ) { 00518 email = (*it).mid( 5 ).trimmed(); 00519 } 00520 } 00521 if ( !name.isEmpty() && !email.isEmpty() ) { 00522 email = QLatin1String( " <" ) + email + QLatin1Char( '>' ); 00523 } 00524 a.insertEmail( name + email ); 00525 a.insertCategory( i18n( "List of Emails" ) ); 00526 return true; 00527 } 00528 00529 if ( fieldname == QLatin1String( "modifytimestamp" ) ) { 00530 if ( value == QLatin1String( "0Z" ) ) { // ignore 00531 return true; 00532 } 00533 QDateTime dt = VCardStringToDate( value ); 00534 if ( dt.isValid() ) { 00535 a.setRevision( dt ); 00536 return true; 00537 } 00538 } 00539 00540 if ( fieldname == QLatin1String( "objectclass" ) ) { // ignore 00541 return true; 00542 } 00543 00544 if ( fieldname == QLatin1String( "birthyear" ) ) { 00545 birthyear = value.toInt(); 00546 return true; 00547 } 00548 if ( fieldname == QLatin1String( "birthmonth" ) ) { 00549 birthmonth = value.toInt(); 00550 return true; 00551 } 00552 if ( fieldname == QLatin1String( "birthday" ) ) { 00553 birthday = value.toInt(); 00554 return true; 00555 } 00556 00557 kWarning(5700) << QString::fromLatin1( "LDIFConverter: Unknown field for '%1': '%2=%3'\n" ). 00558 arg( a.formattedName() ).arg( fieldname ).arg( value ); 00559 00560 return true; 00561 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:10:23 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:10:23 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.