00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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 "ldifconverter.h"
00049 #include "vcardconverter.h"
00050
00051 using namespace KABC;
00052
00053
00054
00055 bool LDIFConverter::addresseeToLDIF( const AddresseeList &addrList, QString &str )
00056 {
00057 AddresseeList::ConstIterator it;
00058 for ( it = addrList.begin(); it != addrList.end(); ++it ) {
00059 addresseeToLDIF( *it, str );
00060 }
00061 return true;
00062 }
00063
00064 QString LDIFConverter::makeLDIFfieldString( QString formatStr, QString value, bool allowEncode )
00065 {
00066 if ( value.isEmpty() )
00067 return QString();
00068
00069
00070 if (formatStr.find(':') == -1)
00071 formatStr.append(": %1\n");
00072
00073
00074 bool printable = true;
00075 unsigned int i, len;
00076 len = value.length();
00077 for (i = 0; i<len; ++i ) {
00078 if (!value[i].isPrint()) {
00079 printable = false;
00080 break;
00081 }
00082 }
00083
00084 if (printable)
00085 printable = (value.find('\n') == -1);
00086
00087 if (!printable && allowEncode) {
00088
00089 value = KCodecs::base64Encode( value.utf8() );
00090 int p = formatStr.find(':');
00091 if (p>=0)
00092 formatStr.insert(p, ':');
00093 }
00094
00095
00096 QCString txt = (formatStr.arg(value)).utf8();
00097
00098 if (allowEncode) {
00099 len = txt.length();
00100 if (len && txt[len-1] == '\n')
00101 --len;
00102 i = 72;
00103 while (i < len) {
00104 txt.insert(i, "\n ");
00105 i += 72+1;
00106 len += 2;
00107 }
00108 }
00109
00110 return QString::fromUtf8(txt);
00111 }
00112
00113
00114
00115 static void ldif_out( QTextStream &t, QString formatStr, QString value, bool allowEncode = true )
00116 {
00117 if ( value.isEmpty() )
00118 return;
00119
00120 QString txt = LDIFConverter::makeLDIFfieldString( formatStr, value, allowEncode );
00121
00122
00123 t << txt;
00124 }
00125
00126
00127 bool LDIFConverter::addresseeToLDIF( const Addressee &addr, QString &str )
00128 {
00129 if ( addr.isEmpty() )
00130 return false;
00131
00132 QTextStream t( str, IO_WriteOnly|IO_Append );
00133 t.setEncoding( QTextStream::UnicodeUTF8 );
00134
00135 const Address homeAddr = addr.address( Address::Home );
00136 const Address workAddr = addr.address( Address::Work );
00137
00138 ldif_out( t, "dn: %1", QString( "cn=%1,mail=%2\n" )
00139 .arg( addr.formattedName().simplifyWhiteSpace() )
00140 .arg( addr.preferredEmail() ), false );
00141 ldif_out( t, "givenname: %1\n", addr.givenName() );
00142 ldif_out( t, "sn: %1\n", addr.familyName() );
00143 ldif_out( t, "cn: %1\n", addr.formattedName().simplifyWhiteSpace() );
00144 ldif_out( t, "uid: %1\n", addr.uid() );
00145 ldif_out( t, "nickname: %1\n", addr.nickName() );
00146 ldif_out( t, "xmozillanickname: %1\n", addr.nickName() );
00147
00148 ldif_out( t, "mail: %1\n", addr.preferredEmail() );
00149 if ( addr.emails().count() > 1 )
00150 ldif_out( t, "mozillasecondemail: %1\n", addr.emails()[ 1 ] );
00151
00152
00153 ldif_out( t, "telephonenumber: %1\n", addr.phoneNumber( PhoneNumber::Work ).number() );
00154 ldif_out( t, "facsimiletelephonenumber: %1\n", addr.phoneNumber( PhoneNumber::Fax ).number() );
00155 ldif_out( t, "homephone: %1\n", addr.phoneNumber( PhoneNumber::Home ).number() );
00156 ldif_out( t, "mobile: %1\n", addr.phoneNumber( PhoneNumber::Cell ).number() );
00157 ldif_out( t, "cellphone: %1\n", addr.phoneNumber( PhoneNumber::Cell ).number() );
00158 ldif_out( t, "pager: %1\n", addr.phoneNumber( PhoneNumber::Pager ).number() );
00159 ldif_out( t, "pagerphone: %1\n", addr.phoneNumber( PhoneNumber::Pager ).number() );
00160
00161 ldif_out( t, "streethomeaddress: %1\n", homeAddr.street() );
00162 ldif_out( t, "postalcode: %1\n", workAddr.postalCode() );
00163 ldif_out( t, "postofficebox: %1\n", workAddr.postOfficeBox() );
00164
00165 QStringList streets = QStringList::split( '\n', homeAddr.street() );
00166 if ( streets.count() > 0 )
00167 ldif_out( t, "homepostaladdress: %1\n", streets[ 0 ] );
00168 if ( streets.count() > 1 )
00169 ldif_out( t, "mozillahomepostaladdress2: %1\n", streets[ 1 ] );
00170 ldif_out( t, "mozillahomelocalityname: %1\n", homeAddr.locality() );
00171 ldif_out( t, "mozillahomestate: %1\n", homeAddr.region() );
00172 ldif_out( t, "mozillahomepostalcode: %1\n", homeAddr.postalCode() );
00173 ldif_out( t, "mozillahomecountryname: %1\n", Address::ISOtoCountry(homeAddr.country()) );
00174 ldif_out( t, "locality: %1\n", workAddr.locality() );
00175 ldif_out( t, "streetaddress: %1\n", workAddr.street() );
00176
00177 streets = QStringList::split( '\n', workAddr.street() );
00178 if ( streets.count() > 0 )
00179 ldif_out( t, "postaladdress: %1\n", streets[ 0 ] );
00180 if ( streets.count() > 1 )
00181 ldif_out( t, "mozillapostaladdress2: %1\n", streets[ 1 ] );
00182 ldif_out( t, "countryname: %1\n", Address::ISOtoCountry(workAddr.country()) );
00183 ldif_out( t, "l: %1\n", workAddr.locality() );
00184 ldif_out( t, "c: %1\n", Address::ISOtoCountry(workAddr.country()) );
00185 ldif_out( t, "st: %1\n", workAddr.region() );
00186
00187 ldif_out( t, "title: %1\n", addr.title() );
00188 ldif_out( t, "vocation: %1\n", addr.prefix() );
00189 ldif_out( t, "ou: %1\n", addr.role() );
00190 ldif_out( t, "o: %1\n", addr.organization() );
00191 ldif_out( t, "organization: %1\n", addr.organization() );
00192 ldif_out( t, "organizationname: %1\n", addr.organization() );
00193 ldif_out( t, "department: %1\n", addr.custom("KADDRESSBOOK", "X-Department") );
00194 ldif_out( t, "workurl: %1\n", addr.url().prettyURL() );
00195 ldif_out( t, "homeurl: %1\n", addr.url().prettyURL() );
00196 ldif_out( t, "description: %1\n", addr.note() );
00197 if (addr.revision().isValid())
00198 ldif_out(t, "modifytimestamp: %1\n", dateToVCardString( addr.revision()) );
00199
00200 t << "objectclass: top\n";
00201 t << "objectclass: person\n";
00202 t << "objectclass: organizationalPerson\n";
00203
00204 t << "\n";
00205
00206 return true;
00207 }
00208
00209
00210
00211
00212 bool LDIFConverter::LDIFToAddressee( const QString &str, AddresseeList &addrList, QDateTime dt )
00213 {
00214 QStringList lines;
00215
00216 if (!dt.isValid())
00217 dt = QDateTime::currentDateTime();
00218
00219 lines = QStringList::split( QRegExp("[\x0d\x0a]"), str, false );
00220
00221
00222 QStringList::Iterator last = lines.end();
00223 for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
00224 if ( (*it).startsWith("#") ) {
00225 it = lines.remove(it);
00226 it--;
00227 continue;
00228 }
00229 if ( last == lines.end() ) {
00230 last = it;
00231 continue;
00232 }
00233 if ((*last).find("::")!=-1 && (*it).find(":")==-1) {
00234 *last += (*it);
00235 lines.remove(it);
00236 it = last;
00237 continue;
00238 }
00239 if ((*last).find(":")!=-1 && (*it).startsWith(" ")) {
00240 *last += (*it).mid(1);
00241 lines.remove(it);
00242 it = last;
00243 continue;
00244 }
00245 last = it;
00246 }
00247
00248
00249 addrList = AddresseeList();
00250
00251 Addressee a;
00252 Address homeAddr, workAddr;
00253 bool cont;
00254 QStringList dnList;
00255 QString dnEntry;
00256
00257
00258 for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
00259
00260
00261 a = Addressee();
00262 a.setRevision(dt);
00263 homeAddr = Address( Address::Home );
00264 workAddr = Address( Address::Work );
00265
00266
00267 if (dnList.count()) {
00268 for ( QStringList::Iterator dne = dnList.begin(); dne != dnList.end(); ++dne ) {
00269 parseSingleLine( a, homeAddr, workAddr, *dne );
00270 }
00271 }
00272
00273
00274 do {
00275 cont = parseSingleLine( a, homeAddr, workAddr, *it );
00276 if (cont && it!=lines.end()) {
00277 ++it;
00278 }
00279 } while (cont && it!=lines.end());
00280
00281
00282 if ( !a.formattedName().isEmpty() || !a.name().isEmpty() ||
00283 !a.familyName().isEmpty() ) {
00284 if ( !homeAddr.isEmpty() )
00285 a.insertAddress( homeAddr );
00286 if ( !workAddr.isEmpty() )
00287 a.insertAddress( workAddr );
00288 addrList.append( a );
00289 }
00290
00291
00292 if ( it == lines.end() )
00293 break;
00294
00295
00296
00297 dnEntry = (*it).replace( '=', ": " );
00298 dnList = QStringList::split( ',', dnEntry, false );
00299 dnList.pop_front();
00300
00301 }
00302
00303 return true;
00304 }
00305
00306 bool LDIFConverter::parseSingleLine( Addressee &a, Address &homeAddr,
00307 Address &workAddr, QString &line )
00308 {
00309 if ( line.isEmpty() )
00310 return true;
00311
00312 QString fieldname, value;
00313 splitLine( line, fieldname, value);
00314 return evaluatePair( a, homeAddr, workAddr, fieldname, value);
00315 }
00316
00317
00318 bool LDIFConverter::splitLine( QString &line, QString &fieldname, QString &value)
00319 {
00320 int position;
00321
00322 position = line.find( "::" );
00323 if ( position != -1 ) {
00324
00325 fieldname = line.left( position ).lower();
00326 value = QString::fromUtf8( KCodecs::base64Decode(
00327 line.mid( position + 3, line.length() - position - 2 ).latin1() ) )
00328 .simplifyWhiteSpace();
00329 return true;
00330 }
00331
00332 position = line.find( ":" );
00333 if ( position != -1 ) {
00334 fieldname = line.left( position ).lower();
00335
00336
00337
00338 value = QString::fromUtf8( line.mid( position + 2, line.length() - position - 2 ).latin1() );
00339 return true;
00340 }
00341
00342
00343 fieldname = "";
00344 value = line;
00345 return true;
00346 }
00347
00348
00349 bool LDIFConverter::evaluatePair( Addressee &a, Address &homeAddr,
00350 Address &workAddr,
00351 QString &fieldname, QString &value )
00352 {
00353 if ( fieldname == QString::fromLatin1( "dn" ) )
00354 return false;
00355
00356 if ( fieldname.startsWith("#") ) {
00357 return true;
00358 }
00359
00360 if ( fieldname.isEmpty() && !a.note().isEmpty() ) {
00361
00362
00363 a.setNote( a.note() + "\n" + value );
00364 return true;
00365 }
00366
00367 if ( fieldname == QString::fromLatin1( "givenname" ) ) {
00368 a.setGivenName( value );
00369 return true;
00370 }
00371
00372 if ( fieldname == QString::fromLatin1( "xmozillanickname") ||
00373 fieldname == QString::fromLatin1( "nickname") ) {
00374 a.setNickName( value );
00375 return true;
00376 }
00377
00378 if ( fieldname == QString::fromLatin1( "sn" ) ) {
00379 a.setFamilyName( value );
00380 return true;
00381 }
00382
00383 if ( fieldname == QString::fromLatin1( "uid" ) ) {
00384 a.setUid( value );
00385 return true;
00386 }
00387 if ( fieldname == QString::fromLatin1( "mail" ) ||
00388 fieldname == QString::fromLatin1( "mozillasecondemail" ) ) {
00389 if ( a.emails().findIndex( value ) == -1 )
00390 a.insertEmail( value );
00391 return true;
00392 }
00393
00394 if ( fieldname == QString::fromLatin1( "title" ) ) {
00395 a.setTitle( value );
00396 return true;
00397 }
00398
00399 if ( fieldname == QString::fromLatin1( "vocation" ) ) {
00400 a.setPrefix( value );
00401 return true;
00402 }
00403
00404 if ( fieldname == QString::fromLatin1( "cn" ) ) {
00405 a.setFormattedName( value );
00406 return true;
00407 }
00408
00409 if ( fieldname == QString::fromLatin1( "o" ) ||
00410 fieldname == QString::fromLatin1( "organization" ) ||
00411 fieldname == QString::fromLatin1( "organizationname" ) ) {
00412 a.setOrganization( value );
00413 return true;
00414 }
00415
00416 if ( fieldname == QString::fromLatin1( "description" ) ) {
00417 addComment:
00418 if ( !a.note().isEmpty() )
00419 a.setNote( a.note() + "\n" );
00420 a.setNote( a.note() + value );
00421 return true;
00422 }
00423
00424 if ( fieldname == QString::fromLatin1( "custom1" ) ||
00425 fieldname == QString::fromLatin1( "custom2" ) ||
00426 fieldname == QString::fromLatin1( "custom3" ) ||
00427 fieldname == QString::fromLatin1( "custom4" ) ) {
00428 goto addComment;
00429 }
00430
00431 if ( fieldname == QString::fromLatin1( "homeurl" ) ||
00432 fieldname == QString::fromLatin1( "workurl" ) ) {
00433 if (a.url().isEmpty()) {
00434 a.setUrl( value );
00435 return true;
00436 }
00437 if ( a.url().prettyURL() == KURL(value).prettyURL() )
00438 return true;
00439
00440
00441 }
00442
00443 if ( fieldname == QString::fromLatin1( "homephone" ) ) {
00444 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Home ) );
00445 return true;
00446 }
00447
00448 if ( fieldname == QString::fromLatin1( "telephonenumber" ) ) {
00449 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) );
00450 return true;
00451 }
00452
00453 if ( fieldname == QString::fromLatin1( "mobile" ) ) {
00454 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) );
00455 return true;
00456 }
00457
00458 if ( fieldname == QString::fromLatin1( "cellphone" ) ) {
00459 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Cell ) );
00460 return true;
00461 }
00462
00463 if ( fieldname == QString::fromLatin1( "pager" ) ||
00464 fieldname == QString::fromLatin1( "pagerphone" ) ) {
00465 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Pager ) );
00466 return true;
00467 }
00468
00469 if ( fieldname == QString::fromLatin1( "facsimiletelephonenumber" ) ) {
00470 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Fax ) );
00471 return true;
00472 }
00473
00474 if ( fieldname == QString::fromLatin1( "xmozillaanyphone" ) ) {
00475 a.insertPhoneNumber( PhoneNumber( value, PhoneNumber::Work ) );
00476 return true;
00477 }
00478
00479 if ( fieldname == QString::fromLatin1( "street" ) ||
00480 fieldname == QString::fromLatin1( "streethomeaddress" ) ) {
00481 homeAddr.setStreet( value );
00482 return true;
00483 }
00484
00485 if ( fieldname == QString::fromLatin1( "postaladdress" ) ) {
00486 workAddr.setStreet( value );
00487 return true;
00488 }
00489
00490 if ( fieldname == QString::fromLatin1( "mozillapostaladdress2" ) ) {
00491 workAddr.setStreet( workAddr.street() + QString::fromLatin1( "\n" ) + value );
00492 return true;
00493 }
00494
00495 if ( fieldname == QString::fromLatin1( "postalcode" ) ) {
00496 workAddr.setPostalCode( value );
00497 return true;
00498 }
00499
00500 if ( fieldname == QString::fromLatin1( "postofficebox" ) ) {
00501 workAddr.setPostOfficeBox( value );
00502 return true;
00503 }
00504
00505 if ( fieldname == QString::fromLatin1( "homepostaladdress" ) ) {
00506 homeAddr.setStreet( value );
00507 return true;
00508 }
00509
00510 if ( fieldname == QString::fromLatin1( "mozillahomepostaladdress2" ) ) {
00511 homeAddr.setStreet( homeAddr.street() + QString::fromLatin1( "\n" ) + value );
00512 return true;
00513 }
00514
00515 if ( fieldname == QString::fromLatin1( "mozillahomelocalityname" ) ) {
00516 homeAddr.setLocality( value );
00517 return true;
00518 }
00519
00520 if ( fieldname == QString::fromLatin1( "mozillahomestate" ) ) {
00521 homeAddr.setRegion( value );
00522 return true;
00523 }
00524
00525 if ( fieldname == QString::fromLatin1( "mozillahomepostalcode" ) ) {
00526 homeAddr.setPostalCode( value );
00527 return true;
00528 }
00529
00530 if ( fieldname == QString::fromLatin1( "mozillahomecountryname" ) ) {
00531 if ( value.length() <= 2 )
00532 value = Address::ISOtoCountry(value);
00533 homeAddr.setCountry( value );
00534 return true;
00535 }
00536
00537 if ( fieldname == QString::fromLatin1( "locality" ) ) {
00538 workAddr.setLocality( value );
00539 return true;
00540 }
00541
00542 if ( fieldname == QString::fromLatin1( "streetaddress" ) ) {
00543 workAddr.setStreet( value );
00544 return true;
00545 }
00546
00547 if ( fieldname == QString::fromLatin1( "countryname" ) ||
00548 fieldname == QString::fromLatin1( "c" ) ) {
00549 if ( value.length() <= 2 )
00550 value = Address::ISOtoCountry(value);
00551 workAddr.setCountry( value );
00552 return true;
00553 }
00554
00555 if ( fieldname == QString::fromLatin1( "l" ) ) {
00556 workAddr.setLocality( value );
00557 return true;
00558 }
00559
00560 if ( fieldname == QString::fromLatin1( "st" ) ) {
00561 workAddr.setRegion( value );
00562 return true;
00563 }
00564
00565 if ( fieldname == QString::fromLatin1( "ou" ) ) {
00566 a.setRole( value );
00567 return true;
00568 }
00569
00570 if ( fieldname == QString::fromLatin1( "department" ) ) {
00571 a.insertCustom( "KADDRESSBOOK", "X-Department", value );
00572 return true;
00573 }
00574
00575 if ( fieldname == QString::fromLatin1( "member" ) ) {
00576
00577 QStringList list( QStringList::split( ',', value ) );
00578 QString name, email;
00579
00580 QStringList::Iterator it;
00581 for ( it = list.begin(); it != list.end(); ++it ) {
00582 if ( (*it).startsWith( "cn=" ) )
00583 name = (*it).mid( 3 ).stripWhiteSpace();
00584 if ( (*it).startsWith( "mail=" ) )
00585 email = (*it).mid( 5 ).stripWhiteSpace();
00586 }
00587 if ( !name.isEmpty() && !email.isEmpty() )
00588 email = " <" + email + ">";
00589 a.insertEmail( name + email );
00590 a.insertCategory( i18n( "List of Emails" ) );
00591 return true;
00592 }
00593
00594 if ( fieldname == QString::fromLatin1( "modifytimestamp" ) ) {
00595 if (value == QString::fromLatin1("0Z"))
00596 return true;
00597 QDateTime dt = VCardStringToDate( value );
00598 if ( dt.isValid() ) {
00599 a.setRevision(dt);
00600 return true;
00601 }
00602 }
00603
00604 if ( fieldname == QString::fromLatin1( "objectclass" ) )
00605 return true;
00606
00607 kdWarning() << QString("LDIFConverter: Unknown field for '%1': '%2=%3'\n")
00608 .arg(a.formattedName()).arg(fieldname).arg(value);
00609
00610 return true;
00611 }
00612