kabc
vcardtool.cpp
00001 /* 00002 This file is part of libkabc. 00003 Copyright (c) 2003 Tobias Koenig <tokoe@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 #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 // ADR + LABEL 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 // BDAY 00139 card.addLine( VCardLine( QLatin1String( "BDAY" ), createDateTime( (*addrIt).birthday() ) ) ); 00140 00141 // CATEGORIES 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 // CLASS 00154 if ( version == VCard::v3_0 ) { 00155 card.addLine( createSecrecy( (*addrIt).secrecy() ) ); 00156 } 00157 00158 // EMAIL 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 // FN 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 // GEO 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 // KEY 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 // LOGO 00194 card.addLine( createPicture( QLatin1String( "LOGO" ), (*addrIt).logo() ) ); 00195 00196 // MAILER 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 // N 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 // NAME 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 // NICKNAME 00228 if ( version == VCard::v3_0 ) { 00229 card.addLine( VCardLine( QLatin1String( "NICKNAME" ), (*addrIt).nickName() ) ); 00230 } 00231 00232 // NOTE 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 // ORG 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 // PHOTO 00256 card.addLine( createPicture( QLatin1String( "PHOTO" ), (*addrIt).photo() ) ); 00257 00258 // PROID 00259 if ( version == VCard::v3_0 ) { 00260 card.addLine( VCardLine( QLatin1String( "PRODID" ), (*addrIt).productId() ) ); 00261 } 00262 00263 // REV 00264 card.addLine( VCardLine( QLatin1String( "REV" ), createDateTime( (*addrIt).revision() ) ) ); 00265 00266 // ROLE 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 // SORT-STRING 00275 if ( version == VCard::v3_0 ) { 00276 card.addLine( VCardLine( QLatin1String( "SORT-STRING" ), (*addrIt).sortString() ) ); 00277 } 00278 00279 // SOUND 00280 card.addLine( createSound( (*addrIt).sound() ) ); 00281 00282 // TEL 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 // TITLE 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 // TZ 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 // UID 00324 card.addLine( VCardLine( QLatin1String( "UID" ), (*addrIt).uid() ) ); 00325 00326 // URL 00327 card.addLine( VCardLine( QLatin1String( "URL" ), (*addrIt).url().url() ) ); 00328 00329 // VERSION 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 // X- 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 // iterate over the lines 00383 for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) { 00384 identifier = (*lineIt).identifier().toLower(); 00385 // ADR 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 // BDAY 00423 else if ( identifier == QLatin1String( "bday" ) ) { 00424 addr.setBirthday( parseDateTime( (*lineIt).value().toString() ) ); 00425 } 00426 00427 // CATEGORIES 00428 else if ( identifier == QLatin1String( "categories" ) ) { 00429 const QStringList categories = splitString( commaSep, (*lineIt).value().toString() ); 00430 addr.setCategories( categories ); 00431 } 00432 00433 // CLASS 00434 else if ( identifier == QLatin1String( "class" ) ) { 00435 addr.setSecrecy( parseSecrecy( *lineIt ) ); 00436 } 00437 00438 // EMAIL 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 // FN 00446 else if ( identifier == QLatin1String( "fn" ) ) { 00447 addr.setFormattedName( (*lineIt).value().toString() ); 00448 } 00449 00450 // GEO 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 // KEY 00464 else if ( identifier == QLatin1String( "key" ) ) { 00465 addr.insertKey( parseKey( *lineIt ) ); 00466 } 00467 00468 // LABEL 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 ) { // a standalone LABEL tag 00490 KABC::Address address( type ); 00491 address.setLabel( (*lineIt).value().toString() ); 00492 addr.insertAddress( address ); 00493 } 00494 } 00495 00496 // LOGO 00497 else if ( identifier == QLatin1String( "logo" ) ) { 00498 addr.setLogo( parsePicture( *lineIt ) ); 00499 } 00500 00501 // MAILER 00502 else if ( identifier == QLatin1String( "mailer" ) ) { 00503 addr.setMailer( (*lineIt).value().toString() ); 00504 } 00505 00506 // N 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 // NAME 00527 else if ( identifier == QLatin1String( "name" ) ) { 00528 addr.setName( (*lineIt).value().toString() ); 00529 } 00530 00531 // NICKNAME 00532 else if ( identifier == QLatin1String( "nickname" ) ) { 00533 addr.setNickName( (*lineIt).value().toString() ); 00534 } 00535 00536 // NOTE 00537 else if ( identifier == QLatin1String( "note" ) ) { 00538 addr.setNote( (*lineIt).value().toString() ); 00539 } 00540 00541 // ORGANIZATION 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 // PHOTO 00553 else if ( identifier == QLatin1String( "photo" ) ) { 00554 addr.setPhoto( parsePicture( *lineIt ) ); 00555 } 00556 00557 // PROID 00558 else if ( identifier == QLatin1String( "prodid" ) ) { 00559 addr.setProductId( (*lineIt).value().toString() ); 00560 } 00561 00562 // REV 00563 else if ( identifier == QLatin1String( "rev" ) ) { 00564 addr.setRevision( parseDateTime( (*lineIt).value().toString() ) ); 00565 } 00566 00567 // ROLE 00568 else if ( identifier == QLatin1String( "role" ) ) { 00569 addr.setRole( (*lineIt).value().toString() ); 00570 } 00571 00572 // SORT-STRING 00573 else if ( identifier == QLatin1String( "sort-string" ) ) { 00574 addr.setSortString( (*lineIt).value().toString() ); 00575 } 00576 00577 // SOUND 00578 else if ( identifier == QLatin1String( "sound" ) ) { 00579 addr.setSound( parseSound( *lineIt ) ); 00580 } 00581 00582 // TEL 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 // TITLE 00600 else if ( identifier == QLatin1String( "title" ) ) { 00601 addr.setTitle( (*lineIt).value().toString() ); 00602 } 00603 00604 // TZ 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 // UID 00621 else if ( identifier == QLatin1String( "uid" ) ) { 00622 addr.setUid( (*lineIt).value().toString() ); 00623 } 00624 00625 // URL 00626 else if ( identifier == QLatin1String( "url" ) ) { 00627 addr.setUrl( KUrl( (*lineIt).value().toString() ) ); 00628 } 00629 00630 // X- 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 ) { // is base format (yyyymmdd) 00651 date = QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(), 00652 str.mid( 6, 2 ).toInt() ); 00653 } else { // is extended format yyyy-mm-dd 00654 date = QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(), 00655 str.mid( 8, 2 ).toInt() ); 00656 } 00657 00658 // does it also contain a time ? (Note: mm, ss are optional according ISO-8601) 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(); // hour must always be given 00664 00665 if ( str.indexOf( QLatin1Char( ':' ), timeStart + 1 ) > 0 ) { // extended format (hh:mm:ss) 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 { // basic format (hhmmss) 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 // explicitly set the time, which might be invalid, to keep the information 00689 // that the time is invalid. In createDateTime() the time/invalid flag is 00690 // checked which omits then to print the timestamp 00691 // This is needed to reproduce the given string in input 00692 // e.g. BDAY:2008-12-30 00693 // without time shall also result in a string without a time 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 /* TODO: support sound types 00790 if ( params.contains( "type" ) ) 00791 snd.setType( line.parameter( "type" ) ); 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 // TODO: need to store sound type!!! 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 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:05:48 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:48 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.