vcard21parser.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qmap.h>
00022 #include <qregexp.h>
00023
00024 #include "vcard21parser.h"
00025
00026 using namespace KABC;
00027
00028 bool VCardLine::isValid() const
00029 {
00030
00031 if ( name == VCARD_BEGIN_N || name == VCARD_END_N )
00032 return false;
00033
00034 if ( name[0] == 'x' && name[1] == '-' )
00035 return true;
00036
00037
00038
00039 switch( name[0] ) {
00040 case 'a':
00041 if ( name == VCARD_ADR && qualified &&
00042 (qualifiers.contains(VCARD_ADR_DOM) ||
00043 qualifiers.contains(VCARD_ADR_INTL) ||
00044 qualifiers.contains(VCARD_ADR_POSTAL) ||
00045 qualifiers.contains(VCARD_ADR_HOME) ||
00046 qualifiers.contains(VCARD_ADR_WORK) ||
00047 qualifiers.contains(VCARD_ADR_PREF)
00048 ) )
00049 return true;
00050
00051 if ( name == VCARD_AGENT )
00052 return true;
00053 break;
00054
00055 case 'b':
00056 if ( name == VCARD_BDAY )
00057 return true;
00058 break;
00059
00060 case 'c':
00061 if ( name == VCARD_CATEGORIES )
00062 return true;
00063 if ( name == VCARD_CLASS && qualified &&
00064 (qualifiers.contains(VCARD_CLASS_PUBLIC) ||
00065 qualifiers.contains(VCARD_CLASS_PRIVATE) ||
00066 qualifiers.contains(VCARD_CLASS_CONFIDENTIAL)
00067 ) )
00068 return true;
00069 break;
00070
00071 case 'e':
00072 if ( name == VCARD_EMAIL && qualified &&
00073 (qualifiers.contains(VCARD_EMAIL_INTERNET) ||
00074 qualifiers.contains(VCARD_EMAIL_PREF) ||
00075 qualifiers.contains(VCARD_EMAIL_X400)
00076 ) )
00077 return true;
00078 break;
00079
00080 case 'f':
00081 if ( name == VCARD_FN )
00082 return true;
00083 break;
00084
00085 case 'g':
00086 if ( name == VCARD_GEO )
00087 return true;
00088 break;
00089
00090 case 'k':
00091 if ( name == VCARD_KEY && qualified &&
00092 (qualifiers.contains(VCARD_KEY_X509) ||
00093 qualifiers.contains(VCARD_KEY_PGP)
00094 ) )
00095 return true;
00096 break;
00097
00098 case 'l':
00099 if ( name == VCARD_LABEL )
00100 return true;
00101 if ( name == VCARD_LOGO )
00102 return true;
00103 break;
00104
00105 case 'm':
00106 if ( name == VCARD_MAILER )
00107 return true;
00108 break;
00109
00110 case 'n':
00111 if ( name == VCARD_N )
00112 return true;
00113 if ( name == VCARD_NAME )
00114 return true;
00115 if ( name == VCARD_NICKNAME )
00116 return true;
00117 if ( name == VCARD_NOTE )
00118 return true;
00119 break;
00120
00121 case 'o':
00122 if ( name == VCARD_ORG )
00123 return true;
00124 break;
00125
00126 case 'p':
00127 if ( name == VCARD_PHOTO )
00128 return true;
00129 if ( name == VCARD_PROFILE )
00130 return true;
00131 if ( name == VCARD_PRODID )
00132 return true;
00133 break;
00134
00135 case 'r':
00136 if ( name == VCARD_ROLE )
00137 return true;
00138 if ( name == VCARD_REV )
00139 return true;
00140 break;
00141
00142 case 's':
00143 if ( name == VCARD_SOURCE )
00144 return true;
00145 if ( name == VCARD_SOUND )
00146 return true;
00147 break;
00148
00149 case 't':
00150 if ( name == VCARD_TEL && qualified &&
00151 (qualifiers.contains(VCARD_TEL_HOME) ||
00152 qualifiers.contains(VCARD_TEL_WORK) ||
00153 qualifiers.contains(VCARD_TEL_PREF) ||
00154 qualifiers.contains(VCARD_TEL_VOICE) ||
00155 qualifiers.contains(VCARD_TEL_FAX) ||
00156 qualifiers.contains(VCARD_TEL_MSG) ||
00157 qualifiers.contains(VCARD_TEL_CELL) ||
00158 qualifiers.contains(VCARD_TEL_PAGER) ||
00159 qualifiers.contains(VCARD_TEL_BBS) ||
00160 qualifiers.contains(VCARD_TEL_MODEM) ||
00161 qualifiers.contains(VCARD_TEL_CAR) ||
00162 qualifiers.contains(VCARD_TEL_ISDN) ||
00163 qualifiers.contains(VCARD_TEL_VIDEO) ||
00164 qualifiers.contains(VCARD_TEL_PCS)
00165 ) )
00166 return true;
00167 if ( name == VCARD_TZ )
00168 return true;
00169 if ( name == VCARD_TITLE )
00170 return true;
00171 break;
00172
00173 case 'u':
00174 if ( name == VCARD_URL )
00175 return true;
00176 if ( name == VCARD_UID )
00177 return true;
00178 break;
00179
00180 case 'v':
00181 if ( name == VCARD_VERSION )
00182 return true;
00183 break;
00184 default:
00185 break;
00186 }
00187
00188 return false;
00189 }
00190
00191
00192 void VCardLine::qpDecode( QString& x )
00193 {
00194 QString y = x;
00195 int c;
00196
00197 x = "";
00198 c = y.length();
00199
00200 for (int i = 0; i < c; i++) {
00201 if (y[i] == '=') {
00202 char p = y[++i].latin1();
00203 char q = y[++i].latin1();
00204 x += (char) ((p <= '9' ? p - '0': p - 'A' + 10)*16 +
00205 (q <= '9' ? q - '0': q - 'A' + 10));
00206 } else {
00207 x += y[i];
00208 }
00209 }
00210 }
00211
00212
00213 VCard21Parser::VCard21Parser()
00214 {
00215 }
00216
00217 VCard21Parser::~VCard21Parser()
00218 {
00219 }
00220
00221 void VCard21Parser::readFromString(KABC::AddressBook *addressbook, const QString &data)
00222 {
00223 KABC::Addressee mAddressee = readFromString(data);
00224 addressbook->insertAddressee(mAddressee);
00225 }
00226
00227 KABC::Addressee VCard21Parser::readFromString( const QString &data)
00228 {
00229 KABC::Addressee addressee;
00230 VCard21ParserImpl *mVCard = VCard21ParserImpl::parseVCard(data);
00231 QString tmpStr;
00232
00233
00234 if (mVCard == 0)
00235 {
00236 kdDebug() << "Parsing failed" << endl;
00237 return addressee;
00238 }
00239
00240 QStringList tmpList = mVCard->getValues(VCARD_N);
00241 QString formattedName = "";
00242 if (tmpList.count() > 0)
00243 addressee.setFamilyName(tmpList[0]);
00244 if (tmpList.count() > 1)
00245 addressee.setGivenName(tmpList[1]);
00246 if (tmpList.count() > 2)
00247 addressee.setAdditionalName(tmpList[2]);
00248 if (tmpList.count() > 3)
00249 addressee.setPrefix(tmpList[3]);
00250 if (tmpList.count() > 4)
00251 addressee.setSuffix(tmpList[4]);
00252
00253 tmpStr = (mVCard->getValue(VCARD_FN));
00254 if (!tmpStr.isEmpty())
00255 addressee.setFormattedName(tmpStr);
00256
00257
00258 tmpStr = mVCard->getValue(VCARD_NICKNAME);
00259 addressee.setNickName(tmpStr);
00260
00261 tmpStr = mVCard->getValue(VCARD_ORG);
00262 addressee.setOrganization(tmpStr);
00263
00264 tmpStr = mVCard->getValue(VCARD_TITLE);
00265 addressee.setTitle(tmpStr);
00266
00267 tmpStr = mVCard->getValue(VCARD_EMAIL, VCARD_EMAIL_INTERNET);
00268 addressee.insertEmail(tmpStr, false);
00269 tmpStr = mVCard->getValue(VCARD_EMAIL,VCARD_EMAIL_PREF);
00270 addressee.insertEmail(tmpStr, true);
00271
00272 tmpStr = mVCard->getValue(VCARD_URL);
00273
00274 if (!tmpStr.isEmpty()) {
00275 KURL url(tmpStr);
00276 addressee.setUrl(url);
00277 }
00278
00279
00280 tmpStr = mVCard->getValue(VCARD_BDAY);
00281 addressee.setBirthday(QDateTime::fromString(tmpStr,Qt::ISODate));
00282
00283
00284 for ( QValueListIterator<VCardLine> i = mVCard->_vcdata->begin();i != mVCard->_vcdata->end(); ++i ) {
00285 if ( (*i).name == VCARD_TEL ) {
00286 int type = 0;
00287 if ( (*i).qualified ) {
00288 if ( (*i).qualifiers.contains( VCARD_TEL_HOME ) )
00289 type |= PhoneNumber::Home;
00290 if ( (*i).qualifiers.contains( VCARD_TEL_WORK ) )
00291 type |= PhoneNumber::Work;
00292 if ( (*i).qualifiers.contains( VCARD_TEL_PREF ) )
00293 type |= PhoneNumber::Pref;
00294 if ( (*i).qualifiers.contains( VCARD_TEL_VOICE ) )
00295 type |= PhoneNumber::Voice;
00296 if ( (*i).qualifiers.contains( VCARD_TEL_FAX ) )
00297 type |= PhoneNumber::Fax;
00298 if ( (*i).qualifiers.contains( VCARD_TEL_MSG ) )
00299 type |= PhoneNumber::Msg;
00300 if ( (*i).qualifiers.contains( VCARD_TEL_CELL ) )
00301 type |= PhoneNumber::Cell;
00302 if ( (*i).qualifiers.contains( VCARD_TEL_PAGER ) )
00303 type |= PhoneNumber::Pager;
00304 if ( (*i).qualifiers.contains( VCARD_TEL_BBS ) )
00305 type |= PhoneNumber::Bbs;
00306 if ( (*i).qualifiers.contains( VCARD_TEL_MODEM ) )
00307 type |= PhoneNumber::Modem;
00308 if ( (*i).qualifiers.contains( VCARD_TEL_CAR ) )
00309 type |= PhoneNumber::Car;
00310 if ( (*i).qualifiers.contains( VCARD_TEL_ISDN ) )
00311 type |= PhoneNumber::Isdn;
00312 if ( (*i).qualifiers.contains( VCARD_TEL_VIDEO ) )
00313 type |= PhoneNumber::Video;
00314 if ( (*i).qualifiers.contains( VCARD_TEL_PCS ) )
00315 type |= PhoneNumber::Pcs;
00316 }
00317 addressee.insertPhoneNumber( PhoneNumber( (*i).parameters[ 0 ], type ) );
00318 }
00319 }
00320
00321
00322 for ( QValueListIterator<VCardLine> i = mVCard->_vcdata->begin();i != mVCard->_vcdata->end(); ++i ) {
00323 if ( (*i).name == VCARD_ADR ) {
00324 int type = 0;
00325 if ( (*i).qualified ) {
00326 if ( (*i).qualifiers.contains( VCARD_ADR_DOM ) )
00327 type |= Address::Dom;
00328 if ( (*i).qualifiers.contains( VCARD_ADR_INTL ) )
00329 type |= Address::Intl;
00330 if ( (*i).qualifiers.contains( VCARD_ADR_POSTAL ) )
00331 type |= Address::Postal;
00332 if ( (*i).qualifiers.contains( VCARD_ADR_PARCEL ) )
00333 type |= Address::Parcel;
00334 if ( (*i).qualifiers.contains( VCARD_ADR_HOME ) )
00335 type |= Address::Home;
00336 if ( (*i).qualifiers.contains( VCARD_ADR_WORK ) )
00337 type |= Address::Work;
00338 if ( (*i).qualifiers.contains( VCARD_ADR_PREF ) )
00339 type |= Address::Pref;
00340 }
00341 addressee.insertAddress( readAddressFromQStringList( (*i).parameters, type ) );
00342 }
00343 }
00344
00345
00346 tmpStr = mVCard->getValue(VCARD_LABEL);
00347 if (!tmpStr.isEmpty()) {
00348 tmpStr.replace(QRegExp("\\r\\n"),"\n");
00349 Address tmpAddress;
00350 tmpAddress.setLabel(tmpStr);
00351 addressee.insertAddress(tmpAddress);
00352 }
00353
00354
00355 tmpStr = mVCard->getValue(VCARD_NOTE);
00356 tmpStr.replace(QRegExp("\\r\\n"),"\n");
00357 addressee.setNote(tmpStr);
00358
00359
00360 tmpStr = mVCard->getValue(VCARD_TZ);
00361 TimeZone tmpZone(tmpStr.toInt());
00362 addressee.setTimeZone(tmpZone);
00363
00364
00365 tmpList = mVCard->getValues(VCARD_GEO);
00366 if (tmpList.count()==2)
00367 {
00368 tmpStr = tmpList[0];
00369 float glat = tmpStr.toFloat();
00370 tmpStr = tmpList[1];
00371 float glong = tmpStr.toFloat();
00372 Geo tmpGeo(glat,glong);
00373 addressee.setGeo(tmpGeo);
00374 }
00375
00376
00377 tmpStr = mVCard->getValue(VCARD_REV);
00378 addressee.setRevision(QDateTime::fromString(tmpStr,Qt::ISODate));
00379
00380
00381 tmpStr = mVCard->getValue(VCARD_ROLE);
00382 addressee.setRole(tmpStr);
00383
00384 return addressee;
00385 }
00386
00387
00388
00389 KABC::Address VCard21Parser::readAddressFromQStringList ( const QStringList &data, const int type )
00390 {
00391 KABC::Address mAddress;
00392 mAddress.setType( type );
00393
00394 if ( data.count() > 0 )
00395 mAddress.setPostOfficeBox( data[0] );
00396 if ( data.count() > 1 )
00397 mAddress.setExtended( data[1] );
00398 if ( data.count() > 2 )
00399 mAddress.setStreet( data[2] );
00400 if ( data.count() > 3 )
00401 mAddress.setLocality( data[3] );
00402 if ( data.count() > 4 )
00403 mAddress.setRegion( data[4] );
00404 if ( data.count() > 5 )
00405 mAddress.setPostalCode( data[5] );
00406 if ( data.count() > 6 )
00407 mAddress.setCountry( data[6] );
00408
00409 return mAddress;
00410 }
00411
00412
00413 VCard21ParserImpl *VCard21ParserImpl::parseVCard( const QString& vc, int *err )
00414 {
00415 int _err = 0;
00416 int _state = VC_STATE_BEGIN;
00417
00418 QValueList<VCardLine> *_vcdata;
00419 QValueList<QString> lines;
00420
00421 _vcdata = new QValueList<VCardLine>;
00422
00423 lines = QStringList::split( QRegExp( "[\x0d\x0a]" ), vc );
00424
00425
00426 for ( QStringList::Iterator j = lines.begin(); j != lines.end(); ++j ) {
00427 VCardLine _vcl;
00428
00429
00430 for ( int g = (*j).length()-1; g > 0 && (*j)[g].isSpace(); --g )
00431 (*j)[g] = 0;
00432
00433
00434
00435 if ( _state & VC_STATE_BEGIN) {
00436 if ( !qstricmp( (*j).latin1(), VCARD_BEGIN ) ) {
00437 _state = VC_STATE_BODY;
00438 continue;
00439 } else {
00440 _err = VC_ERR_NO_BEGIN;
00441 break;
00442 }
00443 } else if ( _state & VC_STATE_BODY ) {
00444 if ( !qstricmp( (*j).latin1(), VCARD_END ) ) {
00445 _state |= VC_STATE_END;
00446 break;
00447 }
00448
00449
00450 int colon = (*j).find( ':' );
00451 if ( colon < 0 ) {
00452 _err = VC_ERR_INVALID_LINE;
00453 break;
00454 }
00455
00456 QString key = (*j).left( colon );
00457 QString value = (*j).mid( colon + 1 );
00458
00459
00460
00461 QStringList keyTokens = QStringList::split( QRegExp(";"), key );
00462 bool qp = false, first_pass = true;
00463 bool b64 = false;
00464
00465 if ( keyTokens.count() > 0 ) {
00466 _vcl.qualified = false;
00467 _vcl.name = keyTokens[ 0 ].lower();
00468
00469 for ( QStringList::Iterator z = keyTokens.begin(); z != keyTokens.end(); ++z ) {
00470 QString zz = (*z).lower();
00471 if ( zz == VCARD_QUOTED_PRINTABLE || zz == VCARD_ENCODING_QUOTED_PRINTABLE ) {
00472 qp = true;
00473 } else if ( zz == VCARD_BASE64 ) {
00474 b64 = true;
00475 } else if ( !first_pass ) {
00476 _vcl.qualified = true;
00477 _vcl.qualifiers.append( zz );
00478 }
00479 first_pass = false;
00480 }
00481 } else {
00482 _err = VC_ERR_INVALID_LINE;
00483 }
00484
00485 if ( _err != 0 )
00486 break;
00487
00488 if ( _vcl.name == VCARD_VERSION )
00489 _state |= VC_STATE_HAVE_VERSION;
00490
00491 if ( _vcl.name == VCARD_N || _vcl.name == VCARD_FN )
00492 _state |= VC_STATE_HAVE_N;
00493
00494
00495
00496
00497 if ( b64 ) {
00498 if ( value[ value.length() - 1 ] != '=' )
00499 do {
00500 value += *( ++j );
00501 } while ( (*j)[ (*j).length() - 1 ] != '=' );
00502 } else {
00503 if ( qp ) {
00504 while ( value[ value.length() - 1 ] == '=' ) {
00505 value.remove( value.length() - 1, 1 );
00506 value.append(*( ++j ));
00507 }
00508 }
00509 _vcl.parameters = QStringList::split( QRegExp(";"), value, true );
00510 if ( qp ) {
00511 for ( QStringList::Iterator z = _vcl.parameters.begin(); z != _vcl.parameters.end(); ++z )
00512 _vcl.qpDecode( *z );
00513 }
00514 }
00515 } else {
00516 _err = VC_ERR_INTERNAL;
00517 break;
00518 }
00519
00520
00521 if ( !_vcl.isValid() ) {
00522 _err = VC_ERR_INVALID_LINE;
00523 break;
00524 }
00525
00526
00527 _vcdata->append( _vcl );
00528 }
00529
00530
00531 if ( _err == 0 ) {
00532 if ( !( _state & VC_STATE_END ) )
00533 _err = VC_ERR_NO_END;
00534
00535 if ( !( _state & VC_STATE_HAVE_N ) ||
00536 !( _state & VC_STATE_HAVE_VERSION ) )
00537 _err = VC_ERR_MISSING_MANDATORY;
00538 }
00539
00540
00541
00542 if ( err )
00543 *err = _err;
00544
00545 if ( _err != 0 ) {
00546 delete _vcdata;
00547 return 0;
00548 }
00549
00550 return new VCard21ParserImpl( _vcdata );
00551 }
00552
00553 VCard21ParserImpl::VCard21ParserImpl(QValueList<VCardLine> *_vcd) : _vcdata(_vcd)
00554 {
00555 }
00556
00557
00558 QString VCard21ParserImpl::getValue(const QString& name, const QString& qualifier)
00559 {
00560 QString failed = "";
00561 const QString lowname = name.lower();
00562 const QString lowqualifier = qualifier.lower();
00563
00564 for (QValueListIterator<VCardLine> i = _vcdata->begin();i != _vcdata->end();++i) {
00565 if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier)) {
00566 if ((*i).parameters.count() > 0)
00567 return (*i).parameters[0];
00568 else return failed;
00569 }
00570 }
00571 return failed;
00572 }
00573
00574
00575 QString VCard21ParserImpl::getValue(const QString& name)
00576 {
00577 QString failed = "";
00578 const QString lowname = name.lower();
00579
00580 for (QValueListIterator<VCardLine> i = _vcdata->begin();i != _vcdata->end();++i) {
00581 if ((*i).name == lowname && !(*i).qualified) {
00582 if ((*i).parameters.count() > 0)
00583 return (*i).parameters[0];
00584 else return failed;
00585 }
00586 }
00587 return failed;
00588 }
00589
00590
00591 QStringList VCard21ParserImpl::getValues(const QString& name)
00592 {
00593
00594 QStringList failed;
00595 const QString lowname = name.lower();
00596 for (QValueListIterator<VCardLine> i = _vcdata->begin();i != _vcdata->end();++i) {
00597 if ((*i).name == lowname && !(*i).qualified)
00598 return (*i).parameters;
00599 }
00600
00601 return failed;
00602 }
00603
00604 QStringList VCard21ParserImpl::getValues(const QString& name, const QString& qualifier)
00605 {
00606
00607 QStringList failed;
00608 const QString lowname = name.lower();
00609 const QString lowqualifier = qualifier.lower();
00610 for (QValueListIterator<VCardLine> i = _vcdata->begin();i != _vcdata->end();++i) {
00611 if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier))
00612 return (*i).parameters;
00613 }
00614
00615 return failed;
00616 }
This file is part of the documentation for kdelibs Version 3.1.5.