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 if ( streets.count() > 0 ) { 00126 ldif_out( t, QLatin1String( "homepostaladdress" ), streets[ 0 ] ); // Netscape 7 00127 } 00128 if ( streets.count() > 1 ) { 00129 ldif_out( t, QLatin1String( "mozillahomepostaladdress2" ), streets[ 1 ] ); // Netscape 7 00130 } 00131 ldif_out( t, QLatin1String( "mozillahomelocalityname" ), homeAddr.locality() ); // Netscape 7 00132 ldif_out( t, QLatin1String( "mozillahomestate" ), homeAddr.region() ); 00133 ldif_out( t, QLatin1String( "mozillahomepostalcode" ), homeAddr.postalCode() ); 00134 ldif_out( t, QLatin1String( "mozillahomecountryname" ), 00135 Address::ISOtoCountry( homeAddr.country() ) ); 00136 ldif_out( t, QLatin1String( "locality" ), workAddr.locality() ); 00137 ldif_out( t, QLatin1String( "streetaddress" ), workAddr.street() ); // Netscape 4.x 00138 00139 streets = workAddr.street().split( QLatin1Char( '\n' ) ); 00140 if ( streets.count() > 0 ) { 00141 ldif_out( t, QLatin1String( "postaladdress" ), streets[ 0 ] ); 00142 } 00143 if ( streets.count() > 1 ) { 00144 ldif_out( t, QLatin1String( "mozillapostaladdress2" ), streets[ 1 ] ); 00145 } 00146 ldif_out( t, QLatin1String( "countryname" ), Address::ISOtoCountry( workAddr.country() ) ); 00147 ldif_out( t, QLatin1String( "l" ), workAddr.locality() ); 00148 ldif_out( t, QLatin1String( "c" ), Address::ISOtoCountry( workAddr.country() ) ); 00149 ldif_out( t, QLatin1String( "st" ), workAddr.region() ); 00150 00151 ldif_out( t, QLatin1String( "title" ), addr.title() ); 00152 ldif_out( t, QLatin1String( "vocation" ), addr.prefix() ); 00153 ldif_out( t, QLatin1String( "ou" ), addr.role() ); 00154 ldif_out( t, QLatin1String( "o" ), addr.organization() ); 00155 ldif_out( t, QLatin1String( "organization" ), addr.organization() ); 00156 ldif_out( t, QLatin1String( "organizationname" ), addr.organization() ); 00157 00158 // Compatibility with older kabc versions. 00159 if ( !addr.department().isEmpty() ) { 00160 ldif_out( t, QLatin1String( "department" ), addr.department() ); 00161 } else { 00162 ldif_out( t, QLatin1String( "department" ), addr.custom( QLatin1String( "KADDRESSBOOK" ), 00163 QLatin1String( "X-Department" ) ) ); 00164 } 00165 00166 ldif_out( t, QLatin1String( "workurl" ), addr.url().prettyUrl() ); 00167 ldif_out( t, QLatin1String( "homeurl" ), addr.url().prettyUrl() ); 00168 ldif_out( t, QLatin1String( "mozillahomeurl" ), addr.url().prettyUrl() ); 00169 00170 ldif_out( t, QLatin1String( "description" ), addr.note() ); 00171 if ( addr.revision().isValid() ) { 00172 ldif_out( t, QLatin1String( "modifytimestamp" ), dateToVCardString( addr.revision() ) ); 00173 } 00174 00175 const QDateTime birthday = addr.birthday(); 00176 if ( birthday.isValid() ) { 00177 const QDate date = birthday.date(); 00178 ldif_out( t, QLatin1String( "birthyear" ), QString::number( date.year() ) ); 00179 ldif_out( t, QLatin1String( "birthmonth" ), QString::number( date.month() ) ); 00180 ldif_out( t, QLatin1String( "birthday" ), QString::number( date.day() ) ); 00181 } 00182 00183 t << "objectclass: top\n"; 00184 t << "objectclass: person\n"; 00185 t << "objectclass: organizationalPerson\n"; 00186 00187 t << "\n"; 00188 00189 return true; 00190 } 00191 00192 /* convert from LDIF stream */ 00193 00194 bool LDIFConverter::LDIFToAddressee( const QString &str, AddresseeList &addrList, 00195 const QDateTime &dt ) 00196 { 00197 if ( str.isEmpty() ) { 00198 return true; 00199 } 00200 00201 bool endldif = false, end = false; 00202 Ldif ldif; 00203 Ldif::ParseValue ret; 00204 Addressee a; 00205 Address homeAddr, workAddr; 00206 int birthday = -1; 00207 int birthmonth = -1; 00208 int birthyear = -1; 00209 00210 ldif.setLdif( str.toLatin1() ); 00211 QDateTime qdt = dt; 00212 if ( !qdt.isValid() ) { 00213 qdt = QDateTime::currentDateTime(); 00214 } 00215 a.setRevision( qdt ); 00216 homeAddr = Address( Address::Home ); 00217 workAddr = Address( Address::Work ); 00218 00219 do { 00220 ret = ldif.nextItem(); 00221 switch ( ret ) { 00222 case Ldif::Item: 00223 { 00224 QString fieldname = ldif.attr().toLower(); 00225 QString value = QString::fromUtf8( ldif.value(), ldif.value().size() ); 00226 evaluatePair( a, homeAddr, workAddr, fieldname, value, birthday, birthmonth,birthyear ); 00227 break; 00228 } 00229 case Ldif::EndEntry: 00230 { 00231 // if the new address is not empty, append it 00232 QDateTime birthDate( QDate( birthyear, birthmonth, birthday ) ); 00233 if ( birthDate.isValid() ) { 00234 a.setBirthday( birthDate ); 00235 } 00236 00237 if ( !a.formattedName().isEmpty() || !a.name().isEmpty() || 00238 !a.familyName().isEmpty() ) { 00239 if ( !homeAddr.isEmpty() ) { 00240 a.insertAddress( homeAddr ); 00241 } 00242 if ( !workAddr.isEmpty() ) { 00243 a.insertAddress( workAddr ); 00244 } 00245 addrList.append( a ); 00246 } 00247 a = Addressee(); 00248 a.setRevision( qdt ); 00249 homeAddr = Address( Address::Home ); 00250 workAddr = Address( Address::Work ); 00251 } 00252 break; 00253 case Ldif::MoreData: 00254 { 00255 if ( endldif ) { 00256 end = true; 00257 } else { 00258 ldif.endLdif(); 00259 endldif = true; 00260 break; 00261 } 00262 } 00263 default: 00264 break; 00265 } 00266 } while ( !end ); 00267 00268 return true; 00269 } 00270 00271 bool LDIFConverter::evaluatePair( Addressee &a, Address &homeAddr, 00272 Address &workAddr, 00273 QString &fieldname, QString &value, int &birthday, int &birthmonth, int &birthyear ) 00274 { 00275 if ( fieldname == QLatin1String( "dn" ) ) { // ignore & return false! 00276 return false; 00277 } 00278 00279 if ( fieldname.startsWith( QLatin1Char( '#' ) ) ) { 00280 return true; 00281 } 00282 00283 if ( fieldname.isEmpty() && !a.note().isEmpty() ) { 00284 // some LDIF export filters are borken and add additional 00285 // comments on stand-alone lines. Just add them to the notes for now. 00286 a.setNote( a.note() + QLatin1Char( '\n' ) + value ); 00287 return true; 00288 } 00289 00290 if ( fieldname == QLatin1String( "givenname" ) ) { 00291 a.setGivenName( value ); 00292 return true; 00293 } 00294 00295 if ( fieldname == QLatin1String( "xmozillanickname" ) || 00296 fieldname == QLatin1String( "nickname" ) || 00297 fieldname == QLatin1String( "mozillanickname" ) ) { 00298 a.setNickName( value ); 00299 return true; 00300 } 00301 00302 if ( fieldname == QLatin1String( "sn" ) ) { 00303 a.setFamilyName( value ); 00304 return true; 00305 } 00306 00307 if ( fieldname == QLatin1String( "uid" ) ) { 00308 a.setUid( value ); 00309 return true; 00310 } 00311 if ( fieldname == QLatin1String( "mail" ) || 00312 fieldname == QLatin1String( "mozillasecondemail" ) ) { // mozilla 00313 if ( a.emails().indexOf( value ) == -1 ) { 00314 a.insertEmail( value ); 00315 } 00316 return true; 00317 } 00318 00319 if ( fieldname == QLatin1String( "title" ) ) { 00320 a.setTitle( value ); 00321 return true; 00322 } 00323 00324 if ( fieldname == QLatin1String( "vocation" ) ) { 00325 a.setPrefix( value ); 00326 return true; 00327 } 00328 00329 if ( fieldname == QLatin1String( "cn" ) ) { 00330 a.setFormattedName( value ); 00331 return true; 00332 } 00333 00334 if ( fieldname == QLatin1String( "o" ) || 00335 fieldname == QLatin1String( "organization" ) || // Exchange 00336 fieldname == QLatin1String( "organizationname" ) ) { // Exchange 00337 a.setOrganization( value ); 00338 return true; 00339 } 00340 00341 if ( fieldname == QLatin1String( "description" ) ) { 00342 addComment: 00343 if ( !a.note().isEmpty() ) { 00344 a.setNote( a.note() + QLatin1Char( '\n' ) ); 00345 } 00346 a.setNote( a.note() + value ); 00347 return true; 00348 } 00349 00350 if ( fieldname == QLatin1String( "custom1" ) || 00351 fieldname == QLatin1String( "custom2" ) || 00352 fieldname == QLatin1String( "custom3" ) || 00353 fieldname == QLatin1String( "custom4" ) ) { 00354 goto addComment; 00355 } 00356 00357 if ( fieldname == QLatin1String( "homeurl" ) || 00358 fieldname == QLatin1String( "workurl" ) || 00359 fieldname == QLatin1String( "mozillahomeurl" )) { 00360 if ( a.url().isEmpty() ) { 00361 a.setUrl( KUrl( value ) ); 00362 return true; 00363 } 00364 if ( a.url().prettyUrl() == KUrl( value ).prettyUrl() ) { 00365 return true; 00366 } 00367 // TODO: current version of kabc only supports one URL. 00368 // TODO: change this with KDE 4 00369 } 00370 00371 if ( fieldname == QLatin1String( "homephone" ) ) { 00372 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Home ) ); 00373 return true; 00374 } 00375 00376 if ( fieldname == QLatin1String( "telephonenumber" ) ) { 00377 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) ); 00378 return true; 00379 } 00380 00381 if ( fieldname == QLatin1String( "mobile" ) ) { // mozilla/Netscape 7 00382 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) ); 00383 return true; 00384 } 00385 00386 if ( fieldname == QLatin1String( "cellphone" ) ) { 00387 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) ); 00388 return true; 00389 } 00390 00391 if ( fieldname == QLatin1String( "pager" ) || // mozilla 00392 fieldname == QLatin1String( "pagerphone" ) ) { // mozilla 00393 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Pager ) ); 00394 return true; 00395 } 00396 00397 if ( fieldname == QLatin1String( "facsimiletelephonenumber" ) ) { 00398 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Fax ) ); 00399 return true; 00400 } 00401 00402 if ( fieldname == QLatin1String( "xmozillaanyphone" ) ) { // mozilla 00403 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) ); 00404 return true; 00405 } 00406 00407 if ( fieldname == QLatin1String( "street" ) || 00408 fieldname == QLatin1String( "streethomeaddress" ) ) { 00409 homeAddr.setStreet( value ); 00410 return true; 00411 } 00412 00413 if ( fieldname == QLatin1String( "postaladdress" ) ) { // mozilla 00414 workAddr.setStreet( value ); 00415 return true; 00416 } 00417 00418 if ( fieldname == QLatin1String( "mozillapostaladdress2" ) ) { // mozilla 00419 workAddr.setStreet( workAddr.street() + QLatin1String( "\n" ) + value ); 00420 return true; 00421 } 00422 00423 if ( fieldname == QLatin1String( "postalcode" ) ) { 00424 workAddr.setPostalCode( value ); 00425 return true; 00426 } 00427 00428 if ( fieldname == QLatin1String( "postofficebox" ) ) { 00429 workAddr.setPostOfficeBox( value ); 00430 return true; 00431 } 00432 00433 if ( fieldname == QLatin1String( "homepostaladdress" ) ) { // Netscape 7 00434 homeAddr.setStreet( value ); 00435 return true; 00436 } 00437 00438 if ( fieldname == QLatin1String( "mozillahomepostaladdress2" ) ) { // mozilla 00439 homeAddr.setStreet( homeAddr.street() + QLatin1String( "\n" ) + value ); 00440 return true; 00441 } 00442 00443 if ( fieldname == QLatin1String( "mozillahomelocalityname" ) ) { // mozilla 00444 homeAddr.setLocality( value ); 00445 return true; 00446 } 00447 00448 if ( fieldname == QLatin1String( "mozillahomestate" ) ) { // mozilla 00449 homeAddr.setRegion( value ); 00450 return true; 00451 } 00452 00453 if ( fieldname == QLatin1String( "mozillahomepostalcode" ) ) { // mozilla 00454 homeAddr.setPostalCode( value ); 00455 return true; 00456 } 00457 00458 if ( fieldname == QLatin1String( "mozillahomecountryname" ) ) { // mozilla 00459 if ( value.length() <= 2 ) { 00460 value = Address::ISOtoCountry( value ); 00461 } 00462 homeAddr.setCountry( value ); 00463 return true; 00464 } 00465 00466 if ( fieldname == QLatin1String( "locality" ) ) { 00467 workAddr.setLocality( value ); 00468 return true; 00469 } 00470 00471 if ( fieldname == QLatin1String( "streetaddress" ) ) { // Netscape 4.x 00472 workAddr.setStreet( value ); 00473 return true; 00474 } 00475 00476 if ( fieldname == QLatin1String( "countryname" ) || 00477 fieldname == QLatin1String( "c" ) ) { // mozilla 00478 if ( value.length() <= 2 ) { 00479 value = Address::ISOtoCountry( value ); 00480 } 00481 workAddr.setCountry( value ); 00482 return true; 00483 } 00484 00485 if ( fieldname == QLatin1String( "l" ) ) { // mozilla 00486 workAddr.setLocality( value ); 00487 return true; 00488 } 00489 00490 if ( fieldname == QLatin1String( "st" ) ) { 00491 workAddr.setRegion( value ); 00492 return true; 00493 } 00494 00495 if ( fieldname == QLatin1String( "ou" ) ) { 00496 a.setRole( value ); 00497 return true; 00498 } 00499 00500 if ( fieldname == QLatin1String( "department" ) ) { 00501 a.setDepartment( value ); 00502 return true; 00503 } 00504 00505 if ( fieldname == QLatin1String( "member" ) ) { 00506 // this is a mozilla list member (cn=xxx, mail=yyy) 00507 QStringList list = value.split( QLatin1Char( ',' ) ); 00508 QString name, email; 00509 00510 QStringList::Iterator it; 00511 for ( it = list.begin(); it != list.end(); ++it ) { 00512 if ( (*it).startsWith( QLatin1String( "cn=" ) ) ) { 00513 name = (*it).mid( 3 ).trimmed(); 00514 } 00515 if ( (*it).startsWith( QLatin1String( "mail=" ) ) ) { 00516 email = (*it).mid( 5 ).trimmed(); 00517 } 00518 } 00519 if ( !name.isEmpty() && !email.isEmpty() ) { 00520 email = QLatin1String( " <" ) + email + QLatin1Char( '>' ); 00521 } 00522 a.insertEmail( name + email ); 00523 a.insertCategory( i18n( "List of Emails" ) ); 00524 return true; 00525 } 00526 00527 if ( fieldname == QLatin1String( "modifytimestamp" ) ) { 00528 if ( value == QLatin1String( "0Z" ) ) { // ignore 00529 return true; 00530 } 00531 QDateTime dt = VCardStringToDate( value ); 00532 if ( dt.isValid() ) { 00533 a.setRevision( dt ); 00534 return true; 00535 } 00536 } 00537 00538 if ( fieldname == QLatin1String( "objectclass" ) ) { // ignore 00539 return true; 00540 } 00541 00542 if ( fieldname == QLatin1String( "birthyear" ) ) { 00543 birthyear = value.toInt(); 00544 return true; 00545 } 00546 if ( fieldname == QLatin1String( "birthmonth" ) ) { 00547 birthmonth = value.toInt(); 00548 return true; 00549 } 00550 if ( fieldname == QLatin1String( "birthday" ) ) { 00551 birthday = value.toInt(); 00552 return true; 00553 } 00554 00555 kWarning(5700) << QString::fromLatin1( "LDIFConverter: Unknown field for '%1': '%2=%3'\n" ). 00556 arg( a.formattedName() ).arg( fieldname ).arg( value ); 00557 00558 return true; 00559 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:05:41 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:05:41 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.