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
#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 *mVCard = VCard21ParserImpl::parseVCard(data);
00212
QString tmpStr;
00213
00214
00215
if (mVCard == 0)
00216 {
00217
kdDebug() <<
"Parsing failed" <<
endl;
00218
return addressee;
00219 }
00220
00221
QStringList tmpList = mVCard->
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 = (mVCard->
getValue(VCARD_FN));
00235
if (!tmpStr.isEmpty())
00236 addressee.
setFormattedName(tmpStr);
00237
00238
00239 tmpStr = mVCard->
getValue(VCARD_NICKNAME);
00240 addressee.
setNickName(tmpStr);
00241
00242 tmpStr = mVCard->
getValue(VCARD_ORG);
00243 addressee.
setOrganization(tmpStr);
00244
00245 tmpStr = mVCard->
getValue(VCARD_TITLE);
00246 addressee.
setTitle(tmpStr);
00247
00248 tmpStr = mVCard->
getValue(VCARD_EMAIL, VCARD_EMAIL_INTERNET);
00249 addressee.
insertEmail(tmpStr,
false);
00250 tmpStr = mVCard->
getValue(VCARD_EMAIL,VCARD_EMAIL_PREF);
00251 addressee.
insertEmail(tmpStr,
true);
00252
00253 tmpStr = mVCard->
getValue(VCARD_URL);
00254
if (tmpStr.isEmpty()) tmpStr = mVCard->
getValue(VCARD_URL, VCARD_ADR_WORK);
00255
if (tmpStr.isEmpty()) tmpStr = mVCard->
getValue(VCARD_URL, VCARD_ADR_HOME);
00256
if (!tmpStr.isEmpty()) {
00257 addressee.
setUrl(
KURL(tmpStr));
00258 }
00259
00260
00261 tmpStr = mVCard->
getValue(VCARD_BDAY);
00262 addressee.
setBirthday(
VCardStringToDate(tmpStr));
00263
00264
00265
for (
QValueListIterator<VCardLineX> i = mVCard->
_vcdata->begin();i != mVCard->
_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 = mVCard->
_vcdata->begin();i != mVCard->
_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 = mVCard->
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 = mVCard->
getValue(VCARD_NOTE);
00337 tmpStr.replace(
"\r\n",
"\n");
00338 addressee.
setNote(tmpStr);
00339
00340
00341 tmpStr = mVCard->
getValue(VCARD_TZ);
00342
TimeZone tmpZone(tmpStr.toInt());
00343 addressee.
setTimeZone(tmpZone);
00344
00345
00346 tmpList = mVCard->
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 = mVCard->
getValue(VCARD_REV);
00359 addressee.
setRevision(
VCardStringToDate(tmpStr));
00360
00361
00362 tmpStr = mVCard->
getValue(VCARD_ROLE);
00363 addressee.
setRole(tmpStr);
00364
00365
return addressee;
00366 }
00367
00368
00369
00370 KABC::Address VCard21Parser::readAddressFromQStringList (
const QStringList &data,
const int type )
00371 {
00372
KABC::Address mAddress;
00373 mAddress.
setType( type );
00374
00375
if ( data.count() > 0 )
00376 mAddress.
setPostOfficeBox( data[0] );
00377
if ( data.count() > 1 )
00378 mAddress.
setExtended( data[1] );
00379
if ( data.count() > 2 )
00380 mAddress.
setStreet( data[2] );
00381
if ( data.count() > 3 )
00382 mAddress.
setLocality( data[3] );
00383
if ( data.count() > 4 )
00384 mAddress.
setRegion( data[4] );
00385
if ( data.count() > 5 )
00386 mAddress.
setPostalCode( data[5] );
00387
if ( data.count() > 6 )
00388 mAddress.
setCountry( data[6] );
00389
00390
return mAddress;
00391 }
00392
00393
00394
VCard21ParserImpl *VCard21ParserImpl::parseVCard(
const QString& vc,
int *err )
00395 {
00396
int _err = 0;
00397
int _state = VC_STATE_BEGIN;
00398
00399
QValueList<VCardLineX> *_vcdata;
00400
QValueList<QString> lines;
00401
00402 _vcdata =
new QValueList<VCardLineX>;
00403
00404 lines = QStringList::split(
QRegExp(
"[\x0d\x0a]" ), vc );
00405
00406
00407
for ( QStringList::Iterator j = lines.begin(); j != lines.end(); ++j ) {
00408
VCardLineX _vcl;
00409
00410
00411
for (
int g = (*j).length()-1; g > 0 && (*j)[g].isSpace(); --g )
00412 (*j)[g] = 0;
00413
00414
00415
00416
if ( _state & VC_STATE_BEGIN) {
00417
if ( !qstricmp( (*j).latin1(), VCARD_BEGIN ) ) {
00418 _state = VC_STATE_BODY;
00419
continue;
00420 }
else {
00421 _err = VC_ERR_NO_BEGIN;
00422
break;
00423 }
00424 }
else if ( _state & VC_STATE_BODY ) {
00425
if ( !qstricmp( (*j).latin1(), VCARD_END ) ) {
00426 _state |= VC_STATE_END;
00427
break;
00428 }
00429
00430
00431
int colon = (*j).find(
':' );
00432
if ( colon < 0 ) {
00433 _err = VC_ERR_INVALID_LINE;
00434
break;
00435 }
00436
00437
QString key = (*j).left( colon );
00438
QString value = (*j).mid( colon + 1 );
00439
00440
00441
00442
QStringList keyTokens = QStringList::split(
';', key );
00443
bool qp =
false, first_pass =
true;
00444
bool b64 =
false;
00445
00446
if ( keyTokens.count() > 0 ) {
00447 _vcl.
qualified =
false;
00448 _vcl.
name = keyTokens[ 0 ].lower();
00449
00450
for ( QStringList::Iterator z = keyTokens.begin(); z != keyTokens.end(); ++z ) {
00451
QString zz = (*z).lower();
00452
if ( zz == VCARD_QUOTED_PRINTABLE || zz == VCARD_ENCODING_QUOTED_PRINTABLE ) {
00453 qp =
true;
00454 }
else if ( zz == VCARD_BASE64 ) {
00455 b64 =
true;
00456 }
else if ( !first_pass ) {
00457 _vcl.
qualified =
true;
00458 _vcl.
qualifiers.append( zz );
00459 }
00460 first_pass =
false;
00461 }
00462 }
else {
00463 _err = VC_ERR_INVALID_LINE;
00464 }
00465
00466
if ( _err != 0 )
00467
break;
00468
00469
if ( _vcl.
name == VCARD_VERSION )
00470 _state |= VC_STATE_HAVE_VERSION;
00471
00472
if ( _vcl.
name == VCARD_N || _vcl.
name == VCARD_FN )
00473 _state |= VC_STATE_HAVE_N;
00474
00475
00476
00477
00478
if ( b64 ) {
00479
if ( value[ value.length() - 1 ] !=
'=' )
00480
do {
00481 value += *( ++j );
00482 }
while ( (*j)[ (*j).length() - 1 ] !=
'=' );
00483 }
else {
00484
if ( qp ) {
00485
while ( value[ value.length() - 1 ] ==
'=' ) {
00486 value.remove( value.length() - 1, 1 );
00487 value.append(*( ++j ));
00488 }
00489 }
00490 _vcl.
parameters = QStringList::split(
';', value,
true );
00491
if ( qp ) {
00492
for ( QStringList::Iterator z = _vcl.
parameters.begin(); z != _vcl.
parameters.end(); ++z )
00493 *z =
KCodecs::quotedPrintableDecode( (*z).latin1() );
00494 }
00495 }
00496 }
else {
00497 _err = VC_ERR_INTERNAL;
00498
break;
00499 }
00500
00501
00502
if ( !_vcl.
isValid() ) {
00503 _err = VC_ERR_INVALID_LINE;
00504
break;
00505 }
00506
00507
00508 _vcdata->append( _vcl );
00509 }
00510
00511
00512
if ( _err == 0 ) {
00513
if ( !( _state & VC_STATE_END ) )
00514 _err = VC_ERR_NO_END;
00515
00516
if ( !( _state & VC_STATE_HAVE_N ) ||
00517 !( _state & VC_STATE_HAVE_VERSION ) )
00518 _err = VC_ERR_MISSING_MANDATORY;
00519 }
00520
00521
00522
00523
if ( err )
00524 *err = _err;
00525
00526
if ( _err != 0 ) {
00527
delete _vcdata;
00528
return 0;
00529 }
00530
00531
return new VCard21ParserImpl( _vcdata );
00532 }
00533
00534 VCard21ParserImpl::VCard21ParserImpl(QValueList<VCardLineX> *_vcd) : _vcdata(_vcd)
00535 {
00536 }
00537
00538
00539
QString VCard21ParserImpl::getValue(
const QString& name,
const QString& qualifier)
00540 {
00541
QString failed;
00542
const QString lowname =
name.lower();
00543
const QString lowqualifier = qualifier.lower();
00544
00545
for (
QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) {
00546
if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier)) {
00547
if ((*i).parameters.count() > 0)
00548
return (*i).parameters[0];
00549
else return failed;
00550 }
00551 }
00552
return failed;
00553 }
00554
00555
00556
QString VCard21ParserImpl::getValue(
const QString& name)
00557 {
00558
QString failed;
00559
const QString lowname =
name.lower();
00560
00561
for (
QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) {
00562
if ((*i).name == lowname && !(*i).qualified) {
00563
if ((*i).parameters.count() > 0)
00564
return (*i).parameters[0];
00565
else return failed;
00566 }
00567 }
00568
return failed;
00569 }
00570
00571
00572
QStringList VCard21ParserImpl::getValues(
const QString& name)
00573 {
00574
const QString lowname =
name.lower();
00575
for (
QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) {
00576
if ((*i).name == lowname && !(*i).qualified)
00577
return (*i).parameters;
00578 }
00579
00580
return QStringList();
00581 }
00582
00583
QStringList VCard21ParserImpl::getValues(
const QString& name,
const QString& qualifier)
00584 {
00585
const QString lowname =
name.lower();
00586
const QString lowqualifier = qualifier.lower();
00587
for (
QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) {
00588
if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier))
00589
return (*i).parameters;
00590 }
00591
00592
return QStringList();
00593 }
00594
00595