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