00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #include "ocontactaccessbackend_vcard.h"
00092 #include "../../library/backend/vobject_p.h"
00093 #include "../../library/backend/qfiledirect_p.h"
00094
00095 #include <qpe/timeconversion.h>
00096
00097 #include <qfile.h>
00098
00099 OContactAccessBackend_VCard::OContactAccessBackend_VCard ( const QString& , const QString& filename ):
00100 m_dirty( false ),
00101 m_file( filename )
00102 {
00103 load();
00104 }
00105
00106
00107 bool OContactAccessBackend_VCard::load ()
00108 {
00109 m_map.clear();
00110 m_dirty = false;
00111
00112 VObject* obj = 0l;
00113
00114 if ( QFile::exists(m_file) ){
00115 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
00116 if ( !obj )
00117 return false;
00118 }else{
00119 qWarning("File \"%s\" not found !", m_file.latin1() );
00120 return false;
00121 }
00122
00123 while ( obj ) {
00124 OContact con = parseVObject( obj );
00125
00126
00127
00128
00129
00130 if ( con.uid() == 0 ){
00131 con.setUid( 1 );
00132 qWarning("assigned new uid %d",con.uid() );
00133 }
00134
00135 m_map.insert( con.uid(), con );
00136
00137 VObject *t = obj;
00138 obj = nextVObjectInList(obj);
00139 cleanVObject( t );
00140 }
00141
00142 return true;
00143
00144 }
00145 bool OContactAccessBackend_VCard::reload()
00146 {
00147 return load();
00148 }
00149 bool OContactAccessBackend_VCard::save()
00150 {
00151 if (!m_dirty )
00152 return true;
00153
00154 QFileDirect file( m_file );
00155 if (!file.open(IO_WriteOnly ) )
00156 return false;
00157
00158 VObject *obj;
00159 obj = newVObject( VCCalProp );
00160 addPropValue( obj, VCVersionProp, "1.0" );
00161
00162 VObject *vo;
00163 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
00164 vo = createVObject( *it );
00165 writeVObject( file.directHandle() , vo );
00166 cleanVObject( vo );
00167 }
00168 cleanStrTbl();
00169 deleteVObject( obj );
00170
00171 m_dirty = false;
00172 return true;
00173
00174
00175 }
00176 void OContactAccessBackend_VCard::clear ()
00177 {
00178 m_map.clear();
00179 m_dirty = true;
00180 }
00181
00182 bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
00183 {
00184 m_map.insert( newcontact.uid(), newcontact );
00185 m_dirty = true;
00186 return true;
00187 }
00188
00189 bool OContactAccessBackend_VCard::remove ( int uid )
00190 {
00191 m_map.remove( uid );
00192 m_dirty = true;
00193 return true;
00194 }
00195
00196 bool OContactAccessBackend_VCard::replace ( const OContact &contact )
00197 {
00198 m_map.replace( contact.uid(), contact );
00199 m_dirty = true;
00200 return true;
00201 }
00202
00203 OContact OContactAccessBackend_VCard::find ( int uid ) const
00204 {
00205 return m_map[uid];
00206 }
00207
00208 QArray<int> OContactAccessBackend_VCard::allRecords() const
00209 {
00210 QArray<int> ar( m_map.count() );
00211 QMap<int, OContact>::ConstIterator it;
00212 int i = 0;
00213 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
00214 ar[i] = it.key();
00215 i++;
00216 }
00217 return ar;
00218 }
00219
00220
00221 QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
00222 {
00223 QArray<int> ar(0);
00224 return ar;
00225 }
00226
00227
00228 QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
00229 {
00230 QArray<int> ar(0);
00231 return ar;
00232 }
00233
00234 const uint OContactAccessBackend_VCard::querySettings()
00235 {
00236 return 0;
00237 }
00238
00239 bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
00240 {
00241 return false;
00242 }
00243
00244 bool OContactAccessBackend_VCard::wasChangedExternally()
00245 {
00246 return false;
00247 }
00248
00249
00250 QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int )
00251 {
00252 QArray<int> ar(0);
00253 return ar;
00254 }
00255
00256
00257
00258
00259 OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
00260 {
00261 OContact c;
00262
00263 VObjectIterator it;
00264 initPropIterator( &it, obj );
00265 while( moreIteration( &it ) ) {
00266 VObject *o = nextVObject( &it );
00267 QCString name = vObjectName( o );
00268 QCString value = vObjectStringZValue( o );
00269 if ( name == VCNameProp ) {
00270 VObjectIterator nit;
00271 initPropIterator( &nit, o );
00272 while( moreIteration( &nit ) ) {
00273 VObject *o = nextVObject( &nit );
00274 QCString name = vObjectTypeInfo( o );
00275 QString value = vObjectStringZValue( o );
00276 if ( name == VCNamePrefixesProp )
00277 c.setTitle( value );
00278 else if ( name == VCNameSuffixesProp )
00279 c.setSuffix( value );
00280 else if ( name == VCFamilyNameProp )
00281 c.setLastName( value );
00282 else if ( name == VCGivenNameProp )
00283 c.setFirstName( value );
00284 else if ( name == VCAdditionalNamesProp )
00285 c.setMiddleName( value );
00286 }
00287 }
00288 else if ( name == VCAdrProp ) {
00289 bool work = TRUE;
00290 QString street;
00291 QString city;
00292 QString region;
00293 QString postal;
00294 QString country;
00295
00296 VObjectIterator nit;
00297 initPropIterator( &nit, o );
00298 while( moreIteration( &nit ) ) {
00299 VObject *o = nextVObject( &nit );
00300 QCString name = vObjectName( o );
00301 QString value = vObjectStringZValue( o );
00302 if ( name == VCHomeProp )
00303 work = FALSE;
00304 else if ( name == VCWorkProp )
00305 work = TRUE;
00306 else if ( name == VCStreetAddressProp )
00307 street = value;
00308 else if ( name == VCCityProp )
00309 city = value;
00310 else if ( name == VCRegionProp )
00311 region = value;
00312 else if ( name == VCPostalCodeProp )
00313 postal = value;
00314 else if ( name == VCCountryNameProp )
00315 country = value;
00316 }
00317 if ( work ) {
00318 c.setBusinessStreet( street );
00319 c.setBusinessCity( city );
00320 c.setBusinessCountry( country );
00321 c.setBusinessZip( postal );
00322 c.setBusinessState( region );
00323 } else {
00324 c.setHomeStreet( street );
00325 c.setHomeCity( city );
00326 c.setHomeCountry( country );
00327 c.setHomeZip( postal );
00328 c.setHomeState( region );
00329 }
00330 }
00331 else if ( name == VCTelephoneProp ) {
00332 enum {
00333 HOME = 0x01,
00334 WORK = 0x02,
00335 VOICE = 0x04,
00336 CELL = 0x08,
00337 FAX = 0x10,
00338 PAGER = 0x20,
00339 UNKNOWN = 0x80
00340 };
00341 int type = 0;
00342
00343 VObjectIterator nit;
00344 initPropIterator( &nit, o );
00345 while( moreIteration( &nit ) ) {
00346 VObject *o = nextVObject( &nit );
00347 QCString name = vObjectTypeInfo( o );
00348 if ( name == VCHomeProp )
00349 type |= HOME;
00350 else if ( name == VCWorkProp )
00351 type |= WORK;
00352 else if ( name == VCVoiceProp )
00353 type |= VOICE;
00354 else if ( name == VCCellularProp )
00355 type |= CELL;
00356 else if ( name == VCFaxProp )
00357 type |= FAX;
00358 else if ( name == VCPagerProp )
00359 type |= PAGER;
00360 else if ( name == VCPreferredProp )
00361 ;
00362 else
00363 type |= UNKNOWN;
00364 }
00365 if ( (type & UNKNOWN) != UNKNOWN ) {
00366 if ( ( type & (HOME|WORK) ) == 0 )
00367 type |= HOME;
00368 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 )
00369 type |= VOICE;
00370
00371 qWarning("value %s %d", value.data(), type );
00372 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) )
00373 c.setHomePhone( value );
00374 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
00375 c.setHomeFax( value );
00376 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
00377 c.setHomeMobile( value );
00378 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) )
00379 c.setBusinessPhone( value );
00380 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
00381 c.setBusinessFax( value );
00382 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
00383 c.setBusinessMobile( value );
00384 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
00385 c.setBusinessPager( value );
00386 }
00387 }
00388 else if ( name == VCEmailAddressProp ) {
00389 QString email = vObjectStringZValue( o );
00390 bool valid = TRUE;
00391 VObjectIterator nit;
00392 initPropIterator( &nit, o );
00393 while( moreIteration( &nit ) ) {
00394 VObject *o = nextVObject( &nit );
00395 QCString name = vObjectTypeInfo( o );
00396 if ( name != VCInternetProp && name != VCHomeProp &&
00397 name != VCWorkProp &&
00398 name != VCPreferredProp )
00399
00400 valid = FALSE;
00401 }
00402 if ( valid ) {
00403 c.insertEmail( email );
00404 }
00405 }
00406 else if ( name == VCURLProp ) {
00407 VObjectIterator nit;
00408 initPropIterator( &nit, o );
00409 while( moreIteration( &nit ) ) {
00410 VObject *o = nextVObject( &nit );
00411 QCString name = vObjectTypeInfo( o );
00412 if ( name == VCHomeProp )
00413 c.setHomeWebpage( value );
00414 else if ( name == VCWorkProp )
00415 c.setBusinessWebpage( value );
00416 }
00417 }
00418 else if ( name == VCOrgProp ) {
00419 VObjectIterator nit;
00420 initPropIterator( &nit, o );
00421 while( moreIteration( &nit ) ) {
00422 VObject *o = nextVObject( &nit );
00423 QCString name = vObjectName( o );
00424 QString value = vObjectStringZValue( o );
00425 if ( name == VCOrgNameProp )
00426 c.setCompany( value );
00427 else if ( name == VCOrgUnitProp )
00428 c.setDepartment( value );
00429 else if ( name == VCOrgUnit2Prop )
00430 c.setOffice( value );
00431 }
00432 }
00433 else if ( name == VCTitleProp ) {
00434 c.setJobTitle( value );
00435 }
00436 else if ( name == "X-Qtopia-Profession" ) {
00437 c.setProfession( value );
00438 }
00439 else if ( name == "X-Qtopia-Manager" ) {
00440 c.setManager( value );
00441 }
00442 else if ( name == "X-Qtopia-Assistant" ) {
00443 c.setAssistant( value );
00444 }
00445 else if ( name == "X-Qtopia-Spouse" ) {
00446 c.setSpouse( value );
00447 }
00448 else if ( name == "X-Qtopia-Gender" ) {
00449 c.setGender( value );
00450 }
00451 else if ( name == "X-Qtopia-Anniversary" ) {
00452 c.setAnniversary( convVCardDateToDate( value ) );
00453 }
00454 else if ( name == "X-Qtopia-Nickname" ) {
00455 c.setNickname( value );
00456 }
00457 else if ( name == "X-Qtopia-Children" ) {
00458 c.setChildren( value );
00459 }
00460 else if ( name == VCBirthDateProp ) {
00461
00462 c.setBirthday( convVCardDateToDate( value ) );
00463
00464 }
00465 else if ( name == VCCommentProp ) {
00466 c.setNotes( value );
00467 }
00468 #if 0
00469 else {
00470 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
00471 VObjectIterator nit;
00472 initPropIterator( &nit, o );
00473 while( moreIteration( &nit ) ) {
00474 VObject *o = nextVObject( &nit );
00475 QCString name = vObjectName( o );
00476 QString value = vObjectStringZValue( o );
00477 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
00478 }
00479 }
00480 #endif
00481 }
00482 c.setFileAs();
00483 return c;
00484 }
00485
00486
00487 VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
00488 {
00489 VObject *vcard = newVObject( VCCardProp );
00490 safeAddPropValue( vcard, VCVersionProp, "2.1" );
00491 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
00492 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
00493
00494
00495 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
00496
00497
00498 VObject *name = safeAddProp( vcard, VCNameProp );
00499 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
00500 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
00501 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
00502 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
00503 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
00504
00505
00506 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
00507 safeAddProp( home_adr, VCHomeProp );
00508 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
00509 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
00510 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
00511 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
00512 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
00513
00514 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
00515 safeAddProp( home_phone, VCHomeProp );
00516 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
00517 safeAddProp( home_phone, VCHomeProp );
00518 safeAddProp( home_phone, VCCellularProp );
00519 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
00520 safeAddProp( home_phone, VCHomeProp );
00521 safeAddProp( home_phone, VCFaxProp );
00522
00523 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
00524 safeAddProp( url, VCHomeProp );
00525
00526
00527 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
00528 safeAddProp( work_adr, VCWorkProp );
00529 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
00530 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
00531 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
00532 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
00533 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
00534
00535 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
00536 safeAddProp( work_phone, VCWorkProp );
00537 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
00538 safeAddProp( work_phone, VCWorkProp );
00539 safeAddProp( work_phone, VCCellularProp );
00540 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
00541 safeAddProp( work_phone, VCWorkProp );
00542 safeAddProp( work_phone, VCFaxProp );
00543 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
00544 safeAddProp( work_phone, VCWorkProp );
00545 safeAddProp( work_phone, VCPagerProp );
00546
00547 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
00548 safeAddProp( url, VCWorkProp );
00549
00550 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
00551 safeAddProp( title, VCWorkProp );
00552
00553
00554 QStringList emails = c.emailList();
00555
00556 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
00557 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
00558 safeAddProp( email, VCInternetProp );
00559 }
00560
00561 safeAddPropValue( vcard, VCNoteProp, c.notes() );
00562
00563
00564 if ( c.birthday().isValid() ){
00565 qWarning("Exporting birthday as: %s", convDateToVCardDate( c.birthday() ).latin1() );
00566 safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) );
00567 }
00568
00569 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
00570 VObject *org = safeAddProp( vcard, VCOrgProp );
00571 safeAddPropValue( org, VCOrgNameProp, c.company() );
00572 safeAddPropValue( org, VCOrgUnitProp, c.department() );
00573 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
00574 }
00575
00576
00577 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
00578 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
00579 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
00580
00581 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
00582 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
00583 if ( c.anniversary().isValid() ){
00584 qWarning("Exporting anniversary as: %s", convDateToVCardDate( c.anniversary() ).latin1() );
00585 safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) );
00586 }
00587 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
00588 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
00589
00590 return vcard;
00591 }
00592
00593 QString OContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const
00594 {
00595 QString str_rfc2425 = QString("%1-%2-%3")
00596 .arg( d.year() )
00597 .arg( d.month(), 2 )
00598 .arg( d.day(), 2 );
00599
00600 int pos = 0;
00601 while ( ( pos = str_rfc2425.find (' ') ) > 0 )
00602 str_rfc2425.replace( pos, 1, "0" );
00603
00604 return str_rfc2425;
00605 }
00606
00607 QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
00608 {
00609 int monthPos = datestr.find('-');
00610 int dayPos = datestr.find('-', monthPos+1 );
00611 int sep_ignore = 1;
00612 if ( monthPos == -1 || dayPos == -1 ) {
00613 qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
00614
00615 if ( datestr.length() == 8 ){
00616 monthPos = 4;
00617 dayPos = 6;
00618 sep_ignore = 0;
00619 qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
00620 } else {
00621 return QDate();
00622 }
00623 }
00624 int y = datestr.left( monthPos ).toInt();
00625 int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
00626 int d = datestr.mid( dayPos + sep_ignore ).toInt();
00627 qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
00628 QDate date ( y,m,d );
00629 return date;
00630 }
00631
00632 VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
00633 {
00634 VObject *ret = 0;
00635 if ( o && !value.isEmpty() )
00636 ret = addPropValue( o, prop, value.latin1() );
00637 return ret;
00638 }
00639
00640 VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
00641 {
00642 VObject *ret = 0;
00643 if ( o )
00644 ret = addProp( o, prop );
00645 return ret;
00646 }