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