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 if ( !date.isEmpty() ) {
00610 int hours = date.mid( 1, 2 ).toInt();
00611 int minutes = date.mid( 4, 2 ).toInt();
00612 int offset = ( hours * 60 ) + minutes;
00613 offset = offset * ( date[ 0 ] == QLatin1Char( '+' ) ? 1 : -1 );
00614
00615 tz.setOffset( offset );
00616 addr.setTimeZone( tz );
00617 }
00618 }
00619
00620
00621 else if ( identifier == QLatin1String( "uid" ) ) {
00622 addr.setUid( (*lineIt).value().toString() );
00623 }
00624
00625
00626 else if ( identifier == QLatin1String( "url" ) ) {
00627 addr.setUrl( KUrl( (*lineIt).value().toString() ) );
00628 }
00629
00630
00631 else if ( identifier.startsWith( QLatin1String( "x-" ) ) ) {
00632 const QString key = (*lineIt).identifier().mid( 2 );
00633 int dash = key.indexOf( QLatin1Char( '-' ) );
00634 addr.insertCustom( key.left( dash ), key.mid( dash + 1 ), (*lineIt).value().toString() );
00635 }
00636 }
00637 }
00638
00639 addrList.append( addr );
00640 }
00641
00642 return addrList;
00643 }
00644
00645 QDateTime VCardTool::parseDateTime( const QString &str ) const
00646 {
00647 QDate date;
00648 QTime time;
00649
00650 if ( str.indexOf( QLatin1Char( '-' ) ) == -1 ) {
00651 date = QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(),
00652 str.mid( 6, 2 ).toInt() );
00653 } else {
00654 date = QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(),
00655 str.mid( 8, 2 ).toInt() );
00656 }
00657
00658
00659 int timeStart = str.indexOf( QLatin1Char( 'T' ) );
00660 if ( timeStart >= 0 ) {
00661 int hour = 0, minute = 0, second = 0;
00662
00663 hour = str.mid( timeStart + 1, 2 ).toInt();
00664
00665 if ( str.indexOf( QLatin1Char( ':' ), timeStart + 1 ) > 0 ) {
00666 if ( str.length() >= ( timeStart + 5 ) ) {
00667 minute = str.mid( timeStart + 4, 2 ).toInt();
00668 if ( str.length() >= ( timeStart + 8 ) ) {
00669 second = str.mid( timeStart + 7, 2 ).toInt();
00670 }
00671 }
00672 } else {
00673 if ( str.length() >= ( timeStart + 4 ) ) {
00674 minute = str.mid( timeStart + 3, 2 ).toInt();
00675 if ( str.length() >= ( timeStart + 6 ) ) {
00676 second = str.mid( timeStart + 5, 2 ).toInt();
00677 }
00678 }
00679 }
00680
00681 time = QTime( hour, minute, second );
00682 }
00683
00684 Qt::TimeSpec spec = ( str.right( 1 ) == QLatin1String( "Z" ) ) ? Qt::UTC : Qt::LocalTime;
00685
00686 QDateTime dateTime(date);
00687
00688
00689
00690
00691
00692
00693
00694 dateTime.setTime(time);
00695
00696 dateTime.setTimeSpec(spec);
00697 return dateTime;
00698 }
00699
00700 QString VCardTool::createDateTime( const QDateTime &dateTime ) const
00701 {
00702 QString str;
00703
00704 if ( dateTime.date().isValid() ) {
00705 str.sprintf( "%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(),
00706 dateTime.date().day() );
00707 if ( dateTime.time().isValid() ) {
00708 QString tmp;
00709 tmp.sprintf( "T%02d:%02d:%02d", dateTime.time().hour(), dateTime.time().minute(),
00710 dateTime.time().second() );
00711 str += tmp;
00712
00713 if ( dateTime.timeSpec() == Qt::UTC ) {
00714 str += QLatin1Char( 'Z' );
00715 }
00716 }
00717 }
00718
00719 return str;
00720 }
00721
00722 Picture VCardTool::parsePicture( const VCardLine &line ) const
00723 {
00724 Picture pic;
00725
00726 const QStringList params = line.parameterList();
00727 if ( params.contains( QLatin1String( "encoding" ) ) ) {
00728 QImage img;
00729 img.loadFromData( line.value().toByteArray() );
00730 pic.setData( img );
00731 } else if ( params.contains( QLatin1String( "value" ) ) ) {
00732 if ( line.parameter( QLatin1String( "value" ) ).toLower() == QLatin1String( "uri" ) ) {
00733 pic.setUrl( line.value().toString() );
00734 }
00735 }
00736
00737 if ( params.contains( QLatin1String( "type" ) ) ) {
00738 pic.setType( line.parameter( QLatin1String( "type" ) ) );
00739 }
00740
00741 return pic;
00742 }
00743
00744 VCardLine VCardTool::createPicture( const QString &identifier, const Picture &pic ) const
00745 {
00746 VCardLine line( identifier );
00747
00748 if ( pic.isIntern() ) {
00749 if ( !pic.data().isNull() ) {
00750 QByteArray input;
00751 QBuffer buffer( &input );
00752 buffer.open( QIODevice::WriteOnly );
00753
00754 if ( !pic.data().hasAlphaChannel() ) {
00755 pic.data().save( &buffer, "JPEG" );
00756
00757 line.setValue( input );
00758 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00759 line.addParameter( QLatin1String( "type" ), QLatin1String( "image/jpeg" ) );
00760 } else {
00761 pic.data().save( &buffer, "PNG" );
00762
00763 line.setValue( input );
00764 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00765 line.addParameter( QLatin1String( "type" ), QLatin1String( "image/png" ) );
00766 }
00767 }
00768 } else if ( !pic.url().isEmpty() ) {
00769 line.setValue( pic.url() );
00770 line.addParameter( QLatin1String( "value" ), QLatin1String( "URI" ) );
00771 }
00772
00773 return line;
00774 }
00775
00776 Sound VCardTool::parseSound( const VCardLine &line ) const
00777 {
00778 Sound snd;
00779
00780 const QStringList params = line.parameterList();
00781 if ( params.contains( QLatin1String( "encoding" ) ) ) {
00782 snd.setData( line.value().toByteArray() );
00783 } else if ( params.contains( QLatin1String( "value" ) ) ) {
00784 if ( line.parameter( QLatin1String( "value" ) ).toLower() == QLatin1String( "uri" ) ) {
00785 snd.setUrl( line.value().toString() );
00786 }
00787 }
00788
00789
00790
00791
00792
00793
00794 return snd;
00795 }
00796
00797 VCardLine VCardTool::createSound( const Sound &snd ) const
00798 {
00799 VCardLine line( QLatin1String( "SOUND" ) );
00800
00801 if ( snd.isIntern() ) {
00802 if ( !snd.data().isEmpty() ) {
00803 line.setValue( snd.data() );
00804 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00805
00806 }
00807 } else if ( !snd.url().isEmpty() ) {
00808 line.setValue( snd.url() );
00809 line.addParameter( QLatin1String( "value" ), QLatin1String( "URI" ) );
00810 }
00811
00812 return line;
00813 }
00814
00815 Key VCardTool::parseKey( const VCardLine &line ) const
00816 {
00817 Key key;
00818
00819 const QStringList params = line.parameterList();
00820 if ( params.contains( QLatin1String( "encoding" ) ) ) {
00821 key.setBinaryData( line.value().toByteArray() );
00822 } else {
00823 key.setTextData( line.value().toString() );
00824 }
00825
00826 if ( params.contains( QLatin1String( "type" ) ) ) {
00827 if ( line.parameter( QLatin1String( "type" ) ).toLower() == QLatin1String( "x509" ) ) {
00828 key.setType( Key::X509 );
00829 } else if ( line.parameter( QLatin1String( "type" ) ).toLower() == QLatin1String( "pgp" ) ) {
00830 key.setType( Key::PGP );
00831 } else {
00832 key.setType( Key::Custom );
00833 key.setCustomTypeString( line.parameter( QLatin1String( "type" ) ) );
00834 }
00835 }
00836
00837 return key;
00838 }
00839
00840 VCardLine VCardTool::createKey( const Key &key ) const
00841 {
00842 VCardLine line( QLatin1String( "KEY" ) );
00843
00844 if ( key.isBinary() ) {
00845 if ( !key.binaryData().isEmpty() ) {
00846 line.setValue( key.binaryData() );
00847 line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
00848 }
00849 } else if ( !key.textData().isEmpty() ) {
00850 line.setValue( key.textData() );
00851 }
00852
00853 if ( key.type() == Key::X509 ) {
00854 line.addParameter( QLatin1String( "type" ), QLatin1String( "X509" ) );
00855 } else if ( key.type() == Key::PGP ) {
00856 line.addParameter( QLatin1String( "type" ), QLatin1String( "PGP" ) );
00857 } else if ( key.type() == Key::Custom ) {
00858 line.addParameter( QLatin1String( "type" ), key.customTypeString() );
00859 }
00860
00861 return line;
00862 }
00863
00864 Secrecy VCardTool::parseSecrecy( const VCardLine &line ) const
00865 {
00866 Secrecy secrecy;
00867
00868 const QString value = line.value().toString().toLower();
00869 if ( value == QLatin1String( "public" ) ) {
00870 secrecy.setType( Secrecy::Public );
00871 } else if ( value == QLatin1String( "private" ) ) {
00872 secrecy.setType( Secrecy::Private );
00873 } else if ( value == QLatin1String( "confidential" ) ) {
00874 secrecy.setType( Secrecy::Confidential );
00875 }
00876
00877 return secrecy;
00878 }
00879
00880 VCardLine VCardTool::createSecrecy( const Secrecy &secrecy ) const
00881 {
00882 VCardLine line( QLatin1String( "CLASS" ) );
00883
00884 int type = secrecy.type();
00885
00886 if ( type == Secrecy::Public ) {
00887 line.setValue( QLatin1String( "PUBLIC" ) );
00888 } else if ( type == Secrecy::Private ) {
00889 line.setValue( QLatin1String( "PRIVATE" ) );
00890 } else if ( type == Secrecy::Confidential ) {
00891 line.setValue( QLatin1String( "CONFIDENTIAL" ) );
00892 }
00893
00894 return line;
00895 }
00896
00897 QStringList VCardTool::splitString( const QChar &sep, const QString &str ) const
00898 {
00899 QStringList list;
00900 QString value( str );
00901
00902 int start = 0;
00903 int pos = value.indexOf( sep, start );
00904
00905 while ( pos != -1 ) {
00906 if ( pos == 0 || value[ pos - 1 ] != QLatin1Char( '\\' ) ) {
00907 if ( pos > start && pos <= (int)value.length() ) {
00908 list << value.mid( start, pos - start );
00909 } else {
00910 list << QString();
00911 }
00912
00913 start = pos + 1;
00914 pos = value.indexOf( sep, start );
00915 } else {
00916 value.replace( pos - 1, 2, sep );
00917 pos = value.indexOf( sep, pos );
00918 }
00919 }
00920
00921 int l = value.length() - 1;
00922 if ( value.mid( start, l - start + 1 ).length() > 0 ) {
00923 list << value.mid( start, l - start + 1 );
00924 } else {
00925 list << QString();
00926 }
00927
00928 return list;
00929 }