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