00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "vcardtool.h"
00022 #include "key.h"
00023 #include "picture.h"
00024 #include "secrecy.h"
00025 #include "sound.h"
00026
00027 #include <QtCore/QString>
00028 #include <QtCore/QBuffer>
00029
00030 using namespace KABC;
00031
00032 static bool needsEncoding( const QString &value )
00033 {
00034 uint length = value.length();
00035 for ( uint i = 0; i < length; ++i ) {
00036 char c = value.at( i ).toLatin1();
00037 if ( ( c < 33 || c > 126 ) && c != ' ' && c != '=' ) {
00038 return true;
00039 }
00040 }
00041
00042 return false;
00043 }
00044
00045 VCardTool::VCardTool()
00046 {
00047 mAddressTypeMap.insert( QLatin1String( "dom" ), Address::Dom );
00048 mAddressTypeMap.insert( QLatin1String( "intl" ), Address::Intl );
00049 mAddressTypeMap.insert( QLatin1String( "postal" ), Address::Postal );
00050 mAddressTypeMap.insert( QLatin1String( "parcel" ), Address::Parcel );
00051 mAddressTypeMap.insert( QLatin1String( "home" ), Address::Home );
00052 mAddressTypeMap.insert( QLatin1String( "work" ), Address::Work );
00053 mAddressTypeMap.insert( QLatin1String( "pref" ), Address::Pref );
00054
00055 mPhoneTypeMap.insert( QLatin1String( "HOME" ), PhoneNumber::Home );
00056 mPhoneTypeMap.insert( QLatin1String( "WORK" ), PhoneNumber::Work );
00057 mPhoneTypeMap.insert( QLatin1String( "MSG" ), PhoneNumber::Msg );
00058 mPhoneTypeMap.insert( QLatin1String( "PREF" ), PhoneNumber::Pref );
00059 mPhoneTypeMap.insert( QLatin1String( "VOICE" ), PhoneNumber::Voice );
00060 mPhoneTypeMap.insert( QLatin1String( "FAX" ), PhoneNumber::Fax );
00061 mPhoneTypeMap.insert( QLatin1String( "CELL" ), PhoneNumber::Cell );
00062 mPhoneTypeMap.insert( QLatin1String( "VIDEO" ), PhoneNumber::Video );
00063 mPhoneTypeMap.insert( QLatin1String( "BBS" ), PhoneNumber::Bbs );
00064 mPhoneTypeMap.insert( QLatin1String( "MODEM" ), PhoneNumber::Modem );
00065 mPhoneTypeMap.insert( QLatin1String( "CAR" ), PhoneNumber::Car );
00066 mPhoneTypeMap.insert( QLatin1String( "ISDN" ), PhoneNumber::Isdn );
00067 mPhoneTypeMap.insert( QLatin1String( "PCS" ), PhoneNumber::Pcs );
00068 mPhoneTypeMap.insert( QLatin1String( "PAGER" ), PhoneNumber::Pager );
00069 }
00070
00071 VCardTool::~VCardTool()
00072 {
00073 }
00074
00075 QByteArray VCardTool::createVCards( const Addressee::List &list, VCard::Version version ) const
00076 {
00077 VCard::List vCardList;
00078
00079 Addressee::List::ConstIterator addrIt;
00080 Addressee::List::ConstIterator listEnd( list.constEnd() );
00081 for ( addrIt = list.constBegin(); addrIt != listEnd; ++addrIt ) {
00082 VCard card;
00083 QStringList::ConstIterator strIt;
00084
00085
00086 const Address::List addresses = (*addrIt).addresses();
00087 for ( Address::List::ConstIterator it = addresses.begin(); it != addresses.end(); ++it ) {
00088 QStringList address;
00089
00090 const bool isEmpty = ( (*it).postOfficeBox().isEmpty() &&
00091 (*it).extended().isEmpty() &&
00092 (*it).street().isEmpty() &&
00093 (*it).locality().isEmpty() &&
00094 (*it).region().isEmpty() &&
00095 (*it).postalCode().isEmpty() &&
00096 (*it).country().isEmpty() );
00097
00098 address.append( (*it).postOfficeBox().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00099 address.append( (*it).extended().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00100 address.append( (*it).street().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00101 address.append( (*it).locality().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00102 address.append( (*it).region().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00103 address.append( (*it).postalCode().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00104 address.append( (*it).country().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00105
00106 VCardLine adrLine( QLatin1String( "ADR" ), address.join( QLatin1String( ";" ) ) );
00107 if ( version == VCard::v2_1 && needsEncoding( address.join( QLatin1String( ";" ) ) ) ) {
00108 adrLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00109 adrLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00110 }
00111
00112 VCardLine labelLine( QLatin1String( "LABEL" ), (*it).label() );
00113 if ( version == VCard::v2_1 && needsEncoding( (*it).label() ) ) {
00114 labelLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00115 labelLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00116 }
00117
00118 const bool hasLabel = !(*it).label().isEmpty();
00119 QMap<QString, Address::TypeFlag>::ConstIterator typeIt;
00120 for ( typeIt = mAddressTypeMap.constBegin();
00121 typeIt != mAddressTypeMap.constEnd(); ++typeIt ) {
00122 if ( typeIt.value() & (*it).type() ) {
00123 adrLine.addParameter( QLatin1String( "TYPE" ), typeIt.key() );
00124 if ( hasLabel ) {
00125 labelLine.addParameter( QLatin1String( "TYPE" ), typeIt.key() );
00126 }
00127 }
00128 }
00129
00130 if ( !isEmpty ) {
00131 card.addLine( adrLine );
00132 }
00133 if ( hasLabel ) {
00134 card.addLine( labelLine );
00135 }
00136 }
00137
00138
00139 card.addLine( VCardLine( QLatin1String( "BDAY" ), createDateTime( (*addrIt).birthday() ) ) );
00140
00141
00142 if ( version == VCard::v3_0 ) {
00143 QStringList categories = (*addrIt).categories();
00144 QStringList::Iterator catIt;
00145 for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
00146 (*catIt).replace( QLatin1Char( ',' ), QLatin1String( "\\," ) );
00147 }
00148
00149 VCardLine catLine( QLatin1String( "CATEGORIES" ), categories.join( QLatin1String( "," ) ) );
00150 card.addLine( catLine );
00151 }
00152
00153
00154 if ( version == VCard::v3_0 ) {
00155 card.addLine( createSecrecy( (*addrIt).secrecy() ) );
00156 }
00157
00158
00159 const QStringList emails = (*addrIt).emails();
00160 bool pref = true;
00161 for ( strIt = emails.begin(); strIt != emails.end(); ++strIt ) {
00162 VCardLine line( QLatin1String( "EMAIL" ), *strIt );
00163 if ( pref == true && emails.count() > 1 ) {
00164 line.addParameter( QLatin1String( "TYPE" ), QLatin1String( "PREF" ) );
00165 pref = false;
00166 }
00167 card.addLine( line );
00168 }
00169
00170
00171 VCardLine fnLine( QLatin1String( "FN" ), (*addrIt).formattedName() );
00172 if ( version == VCard::v2_1 && needsEncoding( (*addrIt).formattedName() ) ) {
00173 fnLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00174 fnLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00175 }
00176 card.addLine( fnLine );
00177
00178
00179 const Geo geo = (*addrIt).geo();
00180 if ( geo.isValid() ) {
00181 QString str;
00182 str.sprintf( "%.6f;%.6f", geo.latitude(), geo.longitude() );
00183 card.addLine( VCardLine( QLatin1String( "GEO" ), str ) );
00184 }
00185
00186
00187 const Key::List keys = (*addrIt).keys();
00188 Key::List::ConstIterator keyIt;
00189 for ( keyIt = keys.begin(); keyIt != keys.end(); ++keyIt ) {
00190 card.addLine( createKey( *keyIt ) );
00191 }
00192
00193
00194 card.addLine( createPicture( QLatin1String( "LOGO" ), (*addrIt).logo() ) );
00195
00196
00197 VCardLine mailerLine( QLatin1String( "MAILER" ), (*addrIt).mailer() );
00198 if ( version == VCard::v2_1 && needsEncoding( (*addrIt).mailer() ) ) {
00199 mailerLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00200 mailerLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00201 }
00202 card.addLine( mailerLine );
00203
00204
00205 QStringList name;
00206 name.append( (*addrIt).familyName().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00207 name.append( (*addrIt).givenName().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00208 name.append( (*addrIt).additionalName().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00209 name.append( (*addrIt).prefix().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00210 name.append( (*addrIt).suffix().replace( QLatin1Char( ';' ), QLatin1String( "\\;" ) ) );
00211
00212 VCardLine nLine( QLatin1String( "N" ), name.join( QLatin1String( ";" ) ) );
00213 if ( version == VCard::v2_1 && needsEncoding( name.join( QLatin1String( ";" ) ) ) ) {
00214 nLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00215 nLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00216 }
00217 card.addLine( nLine );
00218
00219
00220 VCardLine nameLine( QLatin1String( "NAME" ), (*addrIt).name() );
00221 if ( version == VCard::v2_1 && needsEncoding( (*addrIt).name() ) ) {
00222 nameLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00223 nameLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00224 }
00225 card.addLine( nameLine );
00226
00227
00228 if ( version == VCard::v3_0 ) {
00229 card.addLine( VCardLine( QLatin1String( "NICKNAME" ), (*addrIt).nickName() ) );
00230 }
00231
00232
00233 VCardLine noteLine( QLatin1String( "NOTE" ), (*addrIt).note() );
00234 if ( version == VCard::v2_1 && needsEncoding( (*addrIt).note() ) ) {
00235 noteLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00236 noteLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00237 }
00238 card.addLine( noteLine );
00239
00240
00241 QStringList organization;
00242 organization.append( ( *addrIt ).organization().replace( QLatin1Char( ';' ),
00243 QLatin1String( "\\;" ) ) );
00244 if ( !( *addrIt ).department().isEmpty() ) {
00245 organization.append( ( *addrIt ).department().replace( QLatin1Char( ';' ),
00246 QLatin1String( "\\;" ) ) );
00247 }
00248 VCardLine orgLine( QLatin1String( "ORG" ), organization.join( QLatin1String( ";" ) ) );
00249 if ( version == VCard::v2_1 && needsEncoding( organization.join( QLatin1String( ";" ) ) ) ) {
00250 orgLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00251 orgLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00252 }
00253 card.addLine( orgLine );
00254
00255
00256 card.addLine( createPicture( QLatin1String( "PHOTO" ), (*addrIt).photo() ) );
00257
00258
00259 if ( version == VCard::v3_0 ) {
00260 card.addLine( VCardLine( QLatin1String( "PRODID" ), (*addrIt).productId() ) );
00261 }
00262
00263
00264 card.addLine( VCardLine( QLatin1String( "REV" ), createDateTime( (*addrIt).revision() ) ) );
00265
00266
00267 VCardLine roleLine( QLatin1String( "ROLE" ), (*addrIt).role() );
00268 if ( version == VCard::v2_1 && needsEncoding( (*addrIt).role() ) ) {
00269 roleLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00270 roleLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00271 }
00272 card.addLine( roleLine );
00273
00274
00275 if ( version == VCard::v3_0 ) {
00276 card.addLine( VCardLine( QLatin1String( "SORT-STRING" ), (*addrIt).sortString() ) );
00277 }
00278
00279
00280 card.addLine( createSound( (*addrIt).sound() ) );
00281
00282
00283 const PhoneNumber::List phoneNumbers = (*addrIt).phoneNumbers();
00284 PhoneNumber::List::ConstIterator phoneIt;
00285 for ( phoneIt = phoneNumbers.begin(); phoneIt != phoneNumbers.end(); ++phoneIt ) {
00286 VCardLine line( QLatin1String( "TEL" ), (*phoneIt).number() );
00287
00288 QMap<QString, PhoneNumber::TypeFlag>::ConstIterator typeIt;
00289 for ( typeIt = mPhoneTypeMap.constBegin(); typeIt != mPhoneTypeMap.constEnd(); ++typeIt ) {
00290 if ( typeIt.value() & (*phoneIt).type() ) {
00291 line.addParameter( QLatin1String( "TYPE" ), typeIt.key() );
00292 }
00293 }
00294
00295 card.addLine( line );
00296 }
00297
00298
00299 VCardLine titleLine( QLatin1String( "TITLE" ), (*addrIt).title() );
00300 if ( version == VCard::v2_1 && needsEncoding( (*addrIt).title() ) ) {
00301 titleLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00302 titleLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00303 }
00304 card.addLine( titleLine );
00305
00306
00307 const TimeZone timeZone = (*addrIt).timeZone();
00308 if ( timeZone.isValid() ) {
00309 QString str;
00310
00311 int neg = 1;
00312 if ( timeZone.offset() < 0 ) {
00313 neg = -1;
00314 }
00315
00316 str.sprintf( "%c%02d:%02d", ( timeZone.offset() >= 0 ? '+' : '-' ),
00317 ( timeZone.offset() / 60 ) * neg,
00318 ( timeZone.offset() % 60 ) * neg );
00319
00320 card.addLine( VCardLine( QLatin1String( "TZ" ), str ) );
00321 }
00322
00323
00324 card.addLine( VCardLine( QLatin1String( "UID" ), (*addrIt).uid() ) );
00325
00326
00327 card.addLine( VCardLine( QLatin1String( "URL" ), (*addrIt).url().url() ) );
00328
00329
00330 if ( version == VCard::v2_1 ) {
00331 card.addLine( VCardLine( QLatin1String( "VERSION" ), QLatin1String( "2.1" ) ) );
00332 }
00333 if ( version == VCard::v3_0 ) {
00334 card.addLine( VCardLine( QLatin1String( "VERSION" ), QLatin1String( "3.0" ) ) );
00335 }
00336
00337
00338 const QStringList customs = (*addrIt).customs();
00339 for ( strIt = customs.begin(); strIt != customs.end(); ++strIt ) {
00340 const QString identifier = QLatin1String( "X-" ) +
00341 (*strIt).left( (*strIt).indexOf( QLatin1Char( ':' ) ) );
00342 const QString value = (*strIt).mid( (*strIt).indexOf( QLatin1Char( ':' ) ) + 1 );
00343 if ( value.isEmpty() ) {
00344 continue;
00345 }
00346
00347 VCardLine line( identifier, value );
00348 if ( version == VCard::v2_1 && needsEncoding( value ) ) {
00349 line.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
00350 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
00351 }
00352 card.addLine( line );
00353 }
00354
00355 vCardList.append( card );
00356 }
00357
00358 return VCardParser::createVCards( vCardList );
00359 }
00360
00361 Addressee::List VCardTool::parseVCards( const QByteArray &vcard ) const
00362 {
00363 static const QLatin1Char semicolonSep( ';' );
00364 static const QLatin1Char commaSep( ',' );
00365 QString identifier;
00366
00367 Addressee::List addrList;
00368 const VCard::List vCardList = VCardParser::parseVCards( vcard );
00369
00370 VCard::List::ConstIterator cardIt;
00371 VCard::List::ConstIterator listEnd( vCardList.end() );
00372 for ( cardIt = vCardList.begin(); cardIt != listEnd; ++cardIt ) {
00373 Addressee addr;
00374
00375 const QStringList idents = (*cardIt).identifiers();
00376 QStringList::ConstIterator identIt;
00377 QStringList::ConstIterator identEnd( idents.end() );
00378 for ( identIt = idents.begin(); identIt != identEnd; ++identIt ) {
00379 const VCardLine::List lines = (*cardIt).lines( (*identIt) );
00380 VCardLine::List::ConstIterator lineIt;
00381
00382
00383 for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) {
00384 identifier = (*lineIt).identifier().toLower();
00385
00386 if ( identifier == QLatin1String( "adr" ) ) {
00387 Address address;
00388 const QStringList addrParts = splitString( semicolonSep, (*lineIt).value().toString() );
00389 if ( addrParts.count() > 0 ) {
00390 address.setPostOfficeBox( addrParts[ 0 ] );
00391 }
00392 if ( addrParts.count() > 1 ) {
00393 address.setExtended( addrParts[ 1 ] );
00394 }
00395 if ( addrParts.count() > 2 ) {
00396 address.setStreet( addrParts[ 2 ] );
00397 }
00398 if ( addrParts.count() > 3 ) {
00399 address.setLocality( addrParts[ 3 ] );
00400 }
00401 if ( addrParts.count() > 4 ) {
00402 address.setRegion( addrParts[ 4 ] );
00403 }
00404 if ( addrParts.count() > 5 ) {
00405 address.setPostalCode( addrParts[ 5 ] );
00406 }
00407 if ( addrParts.count() > 6 ) {
00408 address.setCountry( addrParts[ 6 ] );
00409 }
00410
00411 Address::Type type;
00412
00413 const QStringList types = (*lineIt).parameters( QLatin1String( "type" ) );
00414 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) {
00415 type |= mAddressTypeMap[ (*it).toLower() ];
00416 }
00417
00418 address.setType( type );
00419 addr.insertAddress( address );
00420 }
00421
00422
00423 else if ( identifier == QLatin1String( "bday" ) ) {
00424 addr.setBirthday( parseDateTime( (*lineIt).value().toString() ) );
00425 }
00426
00427
00428 else if ( identifier == QLatin1String( "categories" ) ) {
00429 const QStringList categories = splitString( commaSep, (*lineIt).value().toString() );
00430 addr.setCategories( categories );
00431 }
00432
00433
00434 else if ( identifier == QLatin1String( "class" ) ) {
00435 addr.setSecrecy( parseSecrecy( *lineIt ) );
00436 }
00437
00438
00439 else if ( identifier == QLatin1String( "email" ) ) {
00440 const QStringList types = (*lineIt).parameters( QLatin1String( "type" ) );
00441 addr.insertEmail( (*lineIt).value().toString(),
00442 types.contains( QLatin1String( "PREF" ) ) );
00443 }
00444
00445
00446 else if ( identifier == QLatin1String( "fn" ) ) {
00447 addr.setFormattedName( (*lineIt).value().toString() );
00448 }
00449
00450
00451 else if ( identifier == QLatin1String( "geo" ) ) {
00452 Geo geo;
00453
00454 const QStringList geoParts =
00455 (*lineIt).value().toString().split( QLatin1Char( ';' ), QString::KeepEmptyParts );
00456 if ( geoParts.size() >= 2 ) {
00457 geo.setLatitude( geoParts[ 0 ].toFloat() );
00458 geo.setLongitude( geoParts[ 1 ].toFloat() );
00459 addr.setGeo( geo );
00460 }
00461 }
00462
00463
00464 else if ( identifier == QLatin1String( "key" ) ) {
00465 addr.insertKey( parseKey( *lineIt ) );
00466 }
00467
00468
00469 else if ( identifier == QLatin1String( "label" ) ) {
00470 Address::Type type;
00471
00472 const QStringList types = (*lineIt).parameters( QLatin1String( "type" ) );
00473 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) {
00474 type |= mAddressTypeMap[ (*it).toLower() ];
00475 }
00476
00477 bool available = false;
00478 KABC::Address::List addressList = addr.addresses();
00479 for ( KABC::Address::List::Iterator it = addressList.begin();
00480 it != addressList.end(); ++it ) {
00481 if ( (*it).type() == type ) {
00482 (*it).setLabel( (*lineIt).value().toString() );
00483 addr.insertAddress( *it );
00484 available = true;
00485 break;
00486 }
00487 }
00488
00489 if ( !available ) {
00490 KABC::Address address( type );
00491 address.setLabel( (*lineIt).value().toString() );
00492 addr.insertAddress( address );
00493 }
00494 }
00495
00496
00497 else if ( identifier == QLatin1String( "logo" ) ) {
00498 addr.setLogo( parsePicture( *lineIt ) );
00499 }
00500
00501
00502 else if ( identifier == QLatin1String( "mailer" ) ) {
00503 addr.setMailer( (*lineIt).value().toString() );
00504 }
00505
00506
00507 else if ( identifier == QLatin1String( "n" ) ) {
00508 const QStringList nameParts = splitString( semicolonSep, (*lineIt).value().toString() );
00509 if ( nameParts.count() > 0 ) {
00510 addr.setFamilyName( nameParts[ 0 ] );
00511 }
00512 if ( nameParts.count() > 1 ) {
00513 addr.setGivenName( nameParts[ 1 ] );
00514 }
00515 if ( nameParts.count() > 2 ) {
00516 addr.setAdditionalName( nameParts[ 2 ] );
00517 }
00518 if ( nameParts.count() > 3 ) {
00519 addr.setPrefix( nameParts[ 3 ] );
00520 }
00521 if ( nameParts.count() > 4 ) {
00522 addr.setSuffix( nameParts[ 4 ] );
00523 }
00524 }
00525
00526
00527 else if ( identifier == QLatin1String( "name" ) ) {
00528 addr.setName( (*lineIt).value().toString() );
00529 }
00530
00531
00532 else if ( identifier == QLatin1String( "nickname" ) ) {
00533 addr.setNickName( (*lineIt).value().toString() );
00534 }
00535
00536
00537 else if ( identifier == QLatin1String( "note" ) ) {
00538 addr.setNote( (*lineIt).value().toString() );
00539 }
00540
00541
00542 else if ( identifier == QLatin1String( "org" ) ) {
00543 const QStringList orgParts = splitString( semicolonSep, (*lineIt).value().toString() );
00544 if ( orgParts.count() > 0 ) {
00545 addr.setOrganization( orgParts[ 0 ] );
00546 }
00547 if ( orgParts.count() > 1 ) {
00548 addr.setDepartment( orgParts[ 1 ] );
00549 }
00550 }
00551
00552
00553 else if ( identifier == QLatin1String( "photo" ) ) {
00554 addr.setPhoto( parsePicture( *lineIt ) );
00555 }
00556
00557
00558 else if ( identifier == QLatin1String( "prodid" ) ) {
00559 addr.setProductId( (*lineIt).value().toString() );
00560 }
00561
00562
00563 else if ( identifier == QLatin1String( "rev" ) ) {
00564 addr.setRevision( parseDateTime( (*lineIt).value().toString() ) );
00565 }
00566
00567
00568 else if ( identifier == QLatin1String( "role" ) ) {
00569 addr.setRole( (*lineIt).value().toString() );
00570 }
00571
00572
00573 else if ( identifier == QLatin1String( "sort-string" ) ) {
00574 addr.setSortString( (*lineIt).value().toString() );
00575 }
00576
00577
00578 else if ( identifier == QLatin1String( "sound" ) ) {
00579 addr.setSound( parseSound( *lineIt ) );
00580 }
00581
00582
00583 else if ( identifier == QLatin1String( "tel" ) ) {
00584 PhoneNumber phone;
00585 phone.setNumber( (*lineIt).value().toString() );
00586
00587 PhoneNumber::Type type;
00588
00589 const QStringList types = (*lineIt).parameters( QLatin1String( "type" ) );
00590 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) {
00591 type |= mPhoneTypeMap[(*it).toUpper()];
00592 }
00593
00594 phone.setType( type );
00595
00596 addr.insertPhoneNumber( phone );
00597 }
00598
00599
00600 else if ( identifier == QLatin1String( "title" ) ) {
00601 addr.setTitle( (*lineIt).value().toString() );
00602 }
00603
00604
00605 else if ( identifier == QLatin1String( "tz" ) ) {
00606 TimeZone tz;
00607 const QString date = (*lineIt).value().toString();
00608
00609 int hours = date.mid( 1, 2 ).toInt();
00610 int minutes = date.mid( 4, 2 ).toInt();
00611 int offset = ( hours * 60 ) + minutes;
00612 offset = offset * ( date[ 0 ] == QLatin1Char( '+' ) ? 1 : -1 );
00613
00614 tz.setOffset( offset );
00615 addr.setTimeZone( tz );
00616 }
00617
00618
00619 else if ( identifier == QLatin1String( "uid" ) ) {
00620 addr.setUid( (*lineIt).value().toString() );
00621 }
00622
00623
00624 else if ( identifier == QLatin1String( "url" ) ) {
00625 addr.setUrl( KUrl( (*lineIt).value().toString() ) );
00626 }
00627
00628
00629 else if ( identifier.startsWith( QLatin1String( "x-" ) ) ) {
00630 const QString key = (*lineIt).identifier().mid( 2 );
00631 int dash = key.indexOf( QLatin1Char( '-' ) );
00632 addr.insertCustom( key.left( dash ), key.mid( dash + 1 ), (*lineIt).value().toString() );
00633 }
00634 }
00635 }
00636
00637 addrList.append( addr );
00638 }
00639
00640 return addrList;
00641 }
00642
00643 QDateTime VCardTool::parseDateTime( const QString &str ) const
00644 {
00645 QDate date;
00646 QTime time;
00647
00648 if ( str.indexOf( QLatin1Char( '-' ) ) == -1 ) {
00649 date = QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(),
00650 str.mid( 6, 2 ).toInt() );
00651 } else {
00652 date = QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(),
00653 str.mid( 8, 2 ).toInt() );
00654 }
00655
00656
00657 int timeStart = str.indexOf( QLatin1Char( 'T' ) );
00658 if ( timeStart >= 0 ) {
00659 int hour = 0, minute = 0, second = 0;
00660
00661 hour = str.mid( timeStart + 1, 2 ).toInt();
00662
00663 if ( str.indexOf( QLatin1Char( ':' ), timeStart + 1 ) > 0 ) {
00664 if ( str.length() >= ( timeStart + 5 ) ) {
00665 minute = str.mid( timeStart + 4, 2 ).toInt();
00666 if ( str.length() >= ( timeStart + 8 ) ) {
00667 second = str.mid( timeStart + 7, 2 ).toInt();
00668 }
00669 }
00670 } else {
00671 if ( str.length() >= ( timeStart + 4 ) ) {
00672 minute = str.mid( timeStart + 3, 2 ).toInt();
00673 if ( str.length() >= ( timeStart + 6 ) ) {
00674 second = str.mid( timeStart + 5, 2 ).toInt();
00675 }
00676 }
00677 }
00678
00679 time = QTime( hour, minute, second );
00680 }
00681
00682 Qt::TimeSpec spec = ( str.right( 1 ) == QLatin1String( "Z" ) ) ? Qt::UTC : Qt::LocalTime;
00683
00684 QDateTime dateTime(date);
00685
00686
00687
00688
00689
00690
00691
00692 dateTime.setTime(time);
00693
00694 dateTime.setTimeSpec(spec);
00695 return dateTime;
00696 }
00697
00698 QString VCardTool::createDateTime( const QDateTime &dateTime ) const
00699 {
00700 QString str;
00701
00702 if ( dateTime.date().isValid() ) {
00703 str.sprintf( "%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(),
00704 dateTime.date().day() );
00705 if ( dateTime.time().isValid() ) {
00706 QString tmp;
00707 tmp.sprintf( "T%02d:%02d:%02d", dateTime.time().hour(), dateTime.time().minute(),
00708 dateTime.time().second() );
00709 str += tmp;
00710
00711 if ( dateTime.timeSpec() == Qt::UTC ) {
00712 str += QLatin1Char( 'Z' );
00713 }
00714 }
00715 }
00716
00717 return str;
00718 }
00719
00720 Picture VCardTool::parsePicture( const VCardLine &line ) const
00721 {
00722 Picture pic;
00723
00724 const QStringList params = line.parameterList();
00725 if ( params.contains( QLatin1String( "encoding" ) ) ) {
00726 QImage img;
00727 img.loadFromData( line.value().toByteArray() );
00728 pic.setData( img );
00729 } else if ( params.contains( QLatin1String( "value" ) ) ) {
00730 if ( line.parameter( QLatin1String( "value" ) ).toLower() == QLatin1String( "uri" ) ) {
00731 pic.setUrl( line.value().toString() );
00732 }
00733 }
00734
00735 if ( params.contains( QLatin1String( "type" ) ) ) {
00736 pic.setType( line.parameter( QLatin1String( "type" ) ) );
00737 }
00738
00739 return pic;
00740 }
00741
00742 VCardLine VCardTool::createPicture( const QString &identifier, const Picture &pic ) const
00743 {
00744 VCardLine line( identifier );
00745
00746 if ( pic.isIntern() ) {
00747 if ( !pic.data().isNull() ) {
00748 QByteArray input;
00749 QBuffer buffer( &input );
00750 buffer.open( QIODevice::WriteOnly );
00751
00752 if ( !pic.data().hasAlphaChannel() ) {
00753 pic.data().save( &buffer, "JPEG" );
00754
00755 line.setValue( input );
00756 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00757 line.addParameter( QLatin1String( "type" ), QLatin1String( "image/jpeg" ) );
00758 } else {
00759 pic.data().save( &buffer, "PNG" );
00760
00761 line.setValue( input );
00762 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00763 line.addParameter( QLatin1String( "type" ), QLatin1String( "image/png" ) );
00764 }
00765 }
00766 } else if ( !pic.url().isEmpty() ) {
00767 line.setValue( pic.url() );
00768 line.addParameter( QLatin1String( "value" ), QLatin1String( "URI" ) );
00769 }
00770
00771 return line;
00772 }
00773
00774 Sound VCardTool::parseSound( const VCardLine &line ) const
00775 {
00776 Sound snd;
00777
00778 const QStringList params = line.parameterList();
00779 if ( params.contains( QLatin1String( "encoding" ) ) ) {
00780 snd.setData( line.value().toByteArray() );
00781 } else if ( params.contains( QLatin1String( "value" ) ) ) {
00782 if ( line.parameter( QLatin1String( "value" ) ).toLower() == QLatin1String( "uri" ) ) {
00783 snd.setUrl( line.value().toString() );
00784 }
00785 }
00786
00787
00788
00789
00790
00791
00792 return snd;
00793 }
00794
00795 VCardLine VCardTool::createSound( const Sound &snd ) const
00796 {
00797 VCardLine line( QLatin1String( "SOUND" ) );
00798
00799 if ( snd.isIntern() ) {
00800 if ( !snd.data().isEmpty() ) {
00801 line.setValue( snd.data() );
00802 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00803
00804 }
00805 } else if ( !snd.url().isEmpty() ) {
00806 line.setValue( snd.url() );
00807 line.addParameter( QLatin1String( "value" ), QLatin1String( "URI" ) );
00808 }
00809
00810 return line;
00811 }
00812
00813 Key VCardTool::parseKey( const VCardLine &line ) const
00814 {
00815 Key key;
00816
00817 const QStringList params = line.parameterList();
00818 if ( params.contains( QLatin1String( "encoding" ) ) ) {
00819 key.setBinaryData( line.value().toByteArray() );
00820 } else {
00821 key.setTextData( line.value().toString() );
00822 }
00823
00824 if ( params.contains( QLatin1String( "type" ) ) ) {
00825 if ( line.parameter( QLatin1String( "type" ) ).toLower() == QLatin1String( "x509" ) ) {
00826 key.setType( Key::X509 );
00827 } else if ( line.parameter( QLatin1String( "type" ) ).toLower() == QLatin1String( "pgp" ) ) {
00828 key.setType( Key::PGP );
00829 } else {
00830 key.setType( Key::Custom );
00831 key.setCustomTypeString( line.parameter( QLatin1String( "type" ) ) );
00832 }
00833 }
00834
00835 return key;
00836 }
00837
00838 VCardLine VCardTool::createKey( const Key &key ) const
00839 {
00840 VCardLine line( QLatin1String( "KEY" ) );
00841
00842 if ( key.isBinary() ) {
00843 if ( !key.binaryData().isEmpty() ) {
00844 line.setValue( key.binaryData() );
00845 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00846 }
00847 } else if ( !key.textData().isEmpty() ) {
00848 line.setValue( key.textData() );
00849 }
00850
00851 if ( key.type() == Key::X509 ) {
00852 line.addParameter( QLatin1String( "type" ), QLatin1String( "X509" ) );
00853 } else if ( key.type() == Key::PGP ) {
00854 line.addParameter( QLatin1String( "type" ), QLatin1String( "PGP" ) );
00855 } else if ( key.type() == Key::Custom ) {
00856 line.addParameter( QLatin1String( "type" ), key.customTypeString() );
00857 }
00858
00859 return line;
00860 }
00861
00862 Secrecy VCardTool::parseSecrecy( const VCardLine &line ) const
00863 {
00864 Secrecy secrecy;
00865
00866 const QString value = line.value().toString().toLower();
00867 if ( value == QLatin1String( "public" ) ) {
00868 secrecy.setType( Secrecy::Public );
00869 } else if ( value == QLatin1String( "private" ) ) {
00870 secrecy.setType( Secrecy::Private );
00871 } else if ( value == QLatin1String( "confidential" ) ) {
00872 secrecy.setType( Secrecy::Confidential );
00873 }
00874
00875 return secrecy;
00876 }
00877
00878 VCardLine VCardTool::createSecrecy( const Secrecy &secrecy ) const
00879 {
00880 VCardLine line( QLatin1String( "CLASS" ) );
00881
00882 int type = secrecy.type();
00883
00884 if ( type == Secrecy::Public ) {
00885 line.setValue( QLatin1String( "PUBLIC" ) );
00886 } else if ( type == Secrecy::Private ) {
00887 line.setValue( QLatin1String( "PRIVATE" ) );
00888 } else if ( type == Secrecy::Confidential ) {
00889 line.setValue( QLatin1String( "CONFIDENTIAL" ) );
00890 }
00891
00892 return line;
00893 }
00894
00895 QStringList VCardTool::splitString( const QChar &sep, const QString &str ) const
00896 {
00897 QStringList list;
00898 QString value( str );
00899
00900 int start = 0;
00901 int pos = value.indexOf( sep, start );
00902
00903 while ( pos != -1 ) {
00904 if ( pos == 0 || value[ pos - 1 ] != QLatin1Char( '\\' ) ) {
00905 if ( pos > start && pos <= (int)value.length() ) {
00906 list << value.mid( start, pos - start );
00907 } else {
00908 list << QString();
00909 }
00910
00911 start = pos + 1;
00912 pos = value.indexOf( sep, start );
00913 } else {
00914 value.replace( pos - 1, 2, sep );
00915 pos = value.indexOf( sep, pos );
00916 }
00917 }
00918
00919 int l = value.length() - 1;
00920 if ( value.mid( start, l - start + 1 ).length() > 0 ) {
00921 list << value.mid( start, l - start + 1 );
00922 } else {
00923 list << QString();
00924 }
00925
00926 return list;
00927 }