summaryrefslogtreecommitdiff
authoreilers <eilers>2002-11-09 14:34:52 (UTC)
committer eilers <eilers>2002-11-09 14:34:52 (UTC)
commit66b3123dabbad8bdfc75893e0e0c4c4e63301435 (patch) (unidiff)
tree24098aa7e3de8e2cead0a0dd70d6fb4d07111659
parentfe6a34ccbccac131c0421a06834ca33de33c0900 (diff)
downloadopie-66b3123dabbad8bdfc75893e0e0c4c4e63301435.zip
opie-66b3123dabbad8bdfc75893e0e0c4c4e63301435.tar.gz
opie-66b3123dabbad8bdfc75893e0e0c4c4e63301435.tar.bz2
Added VCard Backend.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.cpp549
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.h65
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp549
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.h65
4 files changed, 1228 insertions, 0 deletions
diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp
new file mode 100644
index 0000000..903c0b7
--- a/dev/null
+++ b/libopie/pim/ocontactaccessbackend_vcard.cpp
@@ -0,0 +1,549 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * ToDo:
13 *
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2002/11/09 14:34:52 eilers
20 * Added VCard Backend.
21 *
22 */
23#include "ocontactaccessbackend_vcard.h"
24#include "../../library/backend/vobject_p.h"
25#include "../../library/backend/qfiledirect_p.h"
26
27#include <qpe/timeconversion.h>
28
29#include <qfile.h>
30
31OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename = 0l ):
32 m_dirty( false ),
33 m_file( filename )
34{}
35
36
37bool OContactAccessBackend_VCard::load ()
38{
39 m_map.clear();
40 m_dirty = false;
41
42 VObject* obj = 0l;
43 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
44 if ( !obj )
45 return false;
46
47 while ( obj ) {
48 OContact con = parseVObject( obj );
49 /*
50 * if uid is 0 assign a new one
51 * this at least happens on
52 * Nokia6210
53 */
54 if ( con.uid() == 0 ){
55 con.setUid( 1 );
56 qWarning("assigned new uid %d",con.uid() );
57 }
58
59 m_map.insert( con.uid(), con );
60
61 VObject *t = obj;
62 obj = nextVObjectInList(obj);
63 cleanVObject( t );
64 }
65
66 return true;
67
68}
69bool OContactAccessBackend_VCard::reload()
70{
71 return load();
72}
73bool OContactAccessBackend_VCard::save()
74{
75 if (!m_dirty )
76 return true;
77
78 QFileDirect file( m_file );
79 if (!file.open(IO_WriteOnly ) )
80 return false;
81
82 VObject *obj;
83 obj = newVObject( VCCalProp );
84 addPropValue( obj, VCVersionProp, "1.0" );
85
86 VObject *vo;
87 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
88 vo = createVObject( *it );
89 addVObjectProp( obj, vo );
90 }
91 writeVObject( file.directHandle() , obj );
92 cleanVObject( obj );
93
94 cleanStrTbl();
95
96 m_dirty = false;
97 return true;
98
99
100}
101void OContactAccessBackend_VCard::clear ()
102{
103 m_map.clear();
104 m_dirty = true; // ??? sure ? (se)
105}
106
107bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
108{
109 m_map.insert( newcontact.uid(), newcontact );
110 m_dirty = true;
111 return true;
112}
113
114bool OContactAccessBackend_VCard::remove ( int uid )
115{
116 m_map.remove( uid );
117 m_dirty = true;
118 return true;
119}
120
121bool OContactAccessBackend_VCard::replace ( const OContact &contact )
122{
123 m_map.replace( contact.uid(), contact );
124 m_dirty = true;
125 return true;
126}
127
128OContact OContactAccessBackend_VCard::find ( int uid ) const
129{
130 return m_map[uid];
131}
132
133QArray<int> OContactAccessBackend_VCard::allRecords() const
134{
135 QArray<int> ar( m_map.count() );
136 QMap<int, OContact>::ConstIterator it;
137 int i = 0;
138 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
139 ar[i] = it.key();
140 i++;
141 }
142 return ar;
143}
144
145// Not implemented
146QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int )
147{
148 QArray<int> ar(0);
149 return ar;
150}
151
152// Not implemented
153QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
154{
155 QArray<int> ar(0);
156 return ar;
157}
158
159const uint OContactAccessBackend_VCard::querySettings()
160{
161 return 0; // No search possible
162}
163
164bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
165{
166 return false; // No search possible, therefore all settings invalid ;)
167}
168
169
170// *** Private stuff ***
171
172
173OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
174{
175 OContact c;
176
177 VObjectIterator it;
178 initPropIterator( &it, obj );
179 while( moreIteration( &it ) ) {
180 VObject *o = nextVObject( &it );
181 QCString name = vObjectName( o );
182 QCString value = vObjectStringZValue( o );
183 if ( name == VCNameProp ) {
184 VObjectIterator nit;
185 initPropIterator( &nit, o );
186 while( moreIteration( &nit ) ) {
187 VObject *o = nextVObject( &nit );
188 QCString name = vObjectTypeInfo( o );
189 QString value = vObjectStringZValue( o );
190 if ( name == VCNamePrefixesProp )
191 c.setTitle( value );
192 else if ( name == VCNameSuffixesProp )
193 c.setSuffix( value );
194 else if ( name == VCFamilyNameProp )
195 c.setLastName( value );
196 else if ( name == VCGivenNameProp )
197 c.setFirstName( value );
198 else if ( name == VCAdditionalNamesProp )
199 c.setMiddleName( value );
200 }
201 }
202 else if ( name == VCAdrProp ) {
203 bool work = TRUE; // default address is work address
204 QString street;
205 QString city;
206 QString region;
207 QString postal;
208 QString country;
209
210 VObjectIterator nit;
211 initPropIterator( &nit, o );
212 while( moreIteration( &nit ) ) {
213 VObject *o = nextVObject( &nit );
214 QCString name = vObjectName( o );
215 QString value = vObjectStringZValue( o );
216 if ( name == VCHomeProp )
217 work = FALSE;
218 else if ( name == VCWorkProp )
219 work = TRUE;
220 else if ( name == VCStreetAddressProp )
221 street = value;
222 else if ( name == VCCityProp )
223 city = value;
224 else if ( name == VCRegionProp )
225 region = value;
226 else if ( name == VCPostalCodeProp )
227 postal = value;
228 else if ( name == VCCountryNameProp )
229 country = value;
230 }
231 if ( work ) {
232 c.setBusinessStreet( street );
233 c.setBusinessCity( city );
234 c.setBusinessCountry( country );
235 c.setBusinessZip( postal );
236 c.setBusinessState( region );
237 } else {
238 c.setHomeStreet( street );
239 c.setHomeCity( city );
240 c.setHomeCountry( country );
241 c.setHomeZip( postal );
242 c.setHomeState( region );
243 }
244 }
245 else if ( name == VCTelephoneProp ) {
246 enum {
247 HOME = 0x01,
248 WORK = 0x02,
249 VOICE = 0x04,
250 CELL = 0x08,
251 FAX = 0x10,
252 PAGER = 0x20,
253 UNKNOWN = 0x80
254 };
255 int type = 0;
256
257 VObjectIterator nit;
258 initPropIterator( &nit, o );
259 while( moreIteration( &nit ) ) {
260 VObject *o = nextVObject( &nit );
261 QCString name = vObjectTypeInfo( o );
262 if ( name == VCHomeProp )
263 type |= HOME;
264 else if ( name == VCWorkProp )
265 type |= WORK;
266 else if ( name == VCVoiceProp )
267 type |= VOICE;
268 else if ( name == VCCellularProp )
269 type |= CELL;
270 else if ( name == VCFaxProp )
271 type |= FAX;
272 else if ( name == VCPagerProp )
273 type |= PAGER;
274 else if ( name == VCPreferredProp )
275 ;
276 else
277 type |= UNKNOWN;
278 }
279 if ( (type & UNKNOWN) != UNKNOWN ) {
280 if ( ( type & (HOME|WORK) ) == 0 ) // default
281 type |= HOME;
282 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
283 type |= VOICE;
284
285 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) )
286 c.setHomePhone( value );
287 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
288 c.setHomeFax( value );
289 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
290 c.setHomeMobile( value );
291 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) )
292 c.setBusinessPhone( value );
293 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
294 c.setBusinessFax( value );
295 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
296 c.setBusinessMobile( value );
297 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
298 c.setBusinessPager( value );
299 }
300 }
301 else if ( name == VCEmailAddressProp ) {
302 QString email = vObjectStringZValue( o );
303 bool valid = TRUE;
304 VObjectIterator nit;
305 initPropIterator( &nit, o );
306 while( moreIteration( &nit ) ) {
307 VObject *o = nextVObject( &nit );
308 QCString name = vObjectTypeInfo( o );
309 if ( name != VCInternetProp && name != VCHomeProp &&
310 name != VCWorkProp &&
311 name != VCPreferredProp )
312 // ### preffered should map to default email
313 valid = FALSE;
314 }
315 if ( valid ) {
316 c.insertEmail( email );
317 }
318 }
319 else if ( name == VCURLProp ) {
320 VObjectIterator nit;
321 initPropIterator( &nit, o );
322 while( moreIteration( &nit ) ) {
323 VObject *o = nextVObject( &nit );
324 QCString name = vObjectTypeInfo( o );
325 if ( name == VCHomeProp )
326 c.setHomeWebpage( value );
327 else if ( name == VCWorkProp )
328 c.setBusinessWebpage( value );
329 }
330 }
331 else if ( name == VCOrgProp ) {
332 VObjectIterator nit;
333 initPropIterator( &nit, o );
334 while( moreIteration( &nit ) ) {
335 VObject *o = nextVObject( &nit );
336 QCString name = vObjectName( o );
337 QString value = vObjectStringZValue( o );
338 if ( name == VCOrgNameProp )
339 c.setCompany( value );
340 else if ( name == VCOrgUnitProp )
341 c.setDepartment( value );
342 else if ( name == VCOrgUnit2Prop )
343 c.setOffice( value );
344 }
345 }
346 else if ( name == VCTitleProp ) {
347 c.setJobTitle( value );
348 }
349 else if ( name == "X-Qtopia-Profession" ) {
350 c.setProfession( value );
351 }
352 else if ( name == "X-Qtopia-Manager" ) {
353 c.setManager( value );
354 }
355 else if ( name == "X-Qtopia-Assistant" ) {
356 c.setAssistant( value );
357 }
358 else if ( name == "X-Qtopia-Spouse" ) {
359 c.setSpouse( value );
360 }
361 else if ( name == "X-Qtopia-Gender" ) {
362 c.setGender( value );
363 }
364 else if ( name == "X-Qtopia-Anniversary" ) {
365 c.setAnniversary( TimeConversion::fromString( value ) );
366 }
367 else if ( name == "X-Qtopia-Nickname" ) {
368 c.setNickname( value );
369 }
370 else if ( name == "X-Qtopia-Children" ) {
371 c.setChildren( value );
372 }
373 else if ( name == VCBirthDateProp ) {
374 // Reading Birthdate regarding RFC 2425 (5.8.4)
375 c.setBirthday( convVCardDateToDate( value ) );
376
377 }
378
379#if 0
380 else {
381 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
382 VObjectIterator nit;
383 initPropIterator( &nit, o );
384 while( moreIteration( &nit ) ) {
385 VObject *o = nextVObject( &nit );
386 QCString name = vObjectName( o );
387 QString value = vObjectStringZValue( o );
388 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
389 }
390 }
391#endif
392 }
393 c.setFileAs();
394 return c;
395}
396
397
398VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
399{
400 VObject *vcard = newVObject( VCCardProp );
401 safeAddPropValue( vcard, VCVersionProp, "2.1" );
402 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
403 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
404
405 // full name
406 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
407
408 // name properties
409 VObject *name = safeAddProp( vcard, VCNameProp );
410 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
411 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
412 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
413 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
414 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
415
416 // home properties
417 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
418 safeAddProp( home_adr, VCHomeProp );
419 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
420 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
421 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
422 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
423 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
424
425 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
426 safeAddProp( home_phone, VCHomeProp );
427 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
428 safeAddProp( home_phone, VCHomeProp );
429 safeAddProp( home_phone, VCCellularProp );
430 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
431 safeAddProp( home_phone, VCHomeProp );
432 safeAddProp( home_phone, VCFaxProp );
433
434 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
435 safeAddProp( url, VCHomeProp );
436
437 // work properties
438 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
439 safeAddProp( work_adr, VCWorkProp );
440 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
441 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
442 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
443 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
444 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
445
446 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
447 safeAddProp( work_phone, VCWorkProp );
448 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
449 safeAddProp( work_phone, VCWorkProp );
450 safeAddProp( work_phone, VCCellularProp );
451 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
452 safeAddProp( work_phone, VCWorkProp );
453 safeAddProp( work_phone, VCFaxProp );
454 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
455 safeAddProp( work_phone, VCWorkProp );
456 safeAddProp( work_phone, VCPagerProp );
457
458 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
459 safeAddProp( url, VCWorkProp );
460
461 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
462 safeAddProp( title, VCWorkProp );
463
464
465 QStringList emails = c.emailList();
466 emails.prepend( c.defaultEmail() );
467 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
468 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
469 safeAddProp( email, VCInternetProp );
470 }
471
472 safeAddPropValue( vcard, VCNoteProp, c.notes() );
473
474 // Exporting Birthday regarding RFC 2425 (5.8.4)
475 if ( c.birthday().isValid() ){
476 QString birthd_rfc2425 = QString("%1-%2-%3")
477 .arg( c.birthday().year() )
478 .arg( c.birthday().month(), 2 )
479 .arg( c.birthday().day(), 2 );
480 // Now replace spaces with "0"...
481 int pos = 0;
482 while ( ( pos = birthd_rfc2425.find (' ') ) > 0 )
483 birthd_rfc2425.replace( pos, 1, "0" );
484
485 qWarning("Exporting birthday as: %s", birthd_rfc2425.latin1());
486 safeAddPropValue( vcard, VCBirthDateProp, birthd_rfc2425.latin1() );
487 }
488
489 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
490 VObject *org = safeAddProp( vcard, VCOrgProp );
491 safeAddPropValue( org, VCOrgNameProp, c.company() );
492 safeAddPropValue( org, VCOrgUnitProp, c.department() );
493 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
494 }
495
496 // some values we have to export as custom fields
497 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
498 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
499 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
500
501 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
502 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
503 safeAddPropValue( vcard, "X-Qtopia-Anniversary", TimeConversion::toString( c.anniversary() ) );
504 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
505 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
506
507 return vcard;
508}
509
510QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
511{
512 int monthPos = datestr.find('-');
513 int dayPos = datestr.find('-', monthPos+1 );
514 int sep_ignore = 1;
515 if ( monthPos == -1 || dayPos == -1 ) {
516 qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
517 // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD )
518 if ( datestr.length() == 8 ){
519 monthPos = 4;
520 dayPos = 6;
521 sep_ignore = 0;
522 qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
523 } else {
524 return QDate();
525 }
526 }
527 int y = datestr.left( monthPos ).toInt();
528 int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
529 int d = datestr.mid( dayPos + sep_ignore ).toInt();
530 qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
531 QDate date ( y,m,d );
532 return date;
533}
534
535VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
536{
537 VObject *ret = 0;
538 if ( o && !value.isEmpty() )
539 ret = addPropValue( o, prop, value.latin1() );
540 return ret;
541}
542
543VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
544{
545 VObject *ret = 0;
546 if ( o )
547 ret = addProp( o, prop );
548 return ret;
549}
diff --git a/libopie/pim/ocontactaccessbackend_vcard.h b/libopie/pim/ocontactaccessbackend_vcard.h
new file mode 100644
index 0000000..c1422b0
--- a/dev/null
+++ b/libopie/pim/ocontactaccessbackend_vcard.h
@@ -0,0 +1,65 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * ToDo:
13 *
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2002/11/09 14:34:52 eilers
20 * Added VCard Backend.
21 *
22 */
23#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
24#define __OCONTACTACCESSBACKEND_VCARD_H_
25
26#include <opie/ocontact.h>
27
28#include "ocontactaccessbackend.h"
29
30class VObject;
31
32class OContactAccessBackend_VCard : public OContactAccessBackend {
33 public:
34 OContactAccessBackend_VCard ( QString appname, QString filename = 0l );
35
36 bool load ();
37 bool reload();
38 bool save();
39 void clear ();
40
41 bool add ( const OContact& newcontact );
42 bool remove ( int uid );
43 bool replace ( const OContact& contact );
44
45 OContact find ( int uid ) const;
46 QArray<int> allRecords() const;
47 QArray<int> queryByExample ( const OContact &query, int settings );
48 QArray<int> matchRegexp( const QRegExp &r ) const;
49
50 const uint querySettings();
51 bool hasQuerySettings (uint querySettings) const;
52
53private:
54 OContact parseVObject( VObject* obj );
55 VObject* createVObject( const OContact& c );
56 QDate convVCardDateToDate( const QString& datestr );
57 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
58 VObject *safeAddProp( VObject* o, const char* prop);
59
60 bool m_dirty : 1;
61 QString m_file;
62 QMap<int, OContact> m_map;
63};
64
65#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
new file mode 100644
index 0000000..903c0b7
--- a/dev/null
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
@@ -0,0 +1,549 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * ToDo:
13 *
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2002/11/09 14:34:52 eilers
20 * Added VCard Backend.
21 *
22 */
23#include "ocontactaccessbackend_vcard.h"
24#include "../../library/backend/vobject_p.h"
25#include "../../library/backend/qfiledirect_p.h"
26
27#include <qpe/timeconversion.h>
28
29#include <qfile.h>
30
31OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename = 0l ):
32 m_dirty( false ),
33 m_file( filename )
34{}
35
36
37bool OContactAccessBackend_VCard::load ()
38{
39 m_map.clear();
40 m_dirty = false;
41
42 VObject* obj = 0l;
43 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
44 if ( !obj )
45 return false;
46
47 while ( obj ) {
48 OContact con = parseVObject( obj );
49 /*
50 * if uid is 0 assign a new one
51 * this at least happens on
52 * Nokia6210
53 */
54 if ( con.uid() == 0 ){
55 con.setUid( 1 );
56 qWarning("assigned new uid %d",con.uid() );
57 }
58
59 m_map.insert( con.uid(), con );
60
61 VObject *t = obj;
62 obj = nextVObjectInList(obj);
63 cleanVObject( t );
64 }
65
66 return true;
67
68}
69bool OContactAccessBackend_VCard::reload()
70{
71 return load();
72}
73bool OContactAccessBackend_VCard::save()
74{
75 if (!m_dirty )
76 return true;
77
78 QFileDirect file( m_file );
79 if (!file.open(IO_WriteOnly ) )
80 return false;
81
82 VObject *obj;
83 obj = newVObject( VCCalProp );
84 addPropValue( obj, VCVersionProp, "1.0" );
85
86 VObject *vo;
87 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
88 vo = createVObject( *it );
89 addVObjectProp( obj, vo );
90 }
91 writeVObject( file.directHandle() , obj );
92 cleanVObject( obj );
93
94 cleanStrTbl();
95
96 m_dirty = false;
97 return true;
98
99
100}
101void OContactAccessBackend_VCard::clear ()
102{
103 m_map.clear();
104 m_dirty = true; // ??? sure ? (se)
105}
106
107bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
108{
109 m_map.insert( newcontact.uid(), newcontact );
110 m_dirty = true;
111 return true;
112}
113
114bool OContactAccessBackend_VCard::remove ( int uid )
115{
116 m_map.remove( uid );
117 m_dirty = true;
118 return true;
119}
120
121bool OContactAccessBackend_VCard::replace ( const OContact &contact )
122{
123 m_map.replace( contact.uid(), contact );
124 m_dirty = true;
125 return true;
126}
127
128OContact OContactAccessBackend_VCard::find ( int uid ) const
129{
130 return m_map[uid];
131}
132
133QArray<int> OContactAccessBackend_VCard::allRecords() const
134{
135 QArray<int> ar( m_map.count() );
136 QMap<int, OContact>::ConstIterator it;
137 int i = 0;
138 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
139 ar[i] = it.key();
140 i++;
141 }
142 return ar;
143}
144
145// Not implemented
146QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int )
147{
148 QArray<int> ar(0);
149 return ar;
150}
151
152// Not implemented
153QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
154{
155 QArray<int> ar(0);
156 return ar;
157}
158
159const uint OContactAccessBackend_VCard::querySettings()
160{
161 return 0; // No search possible
162}
163
164bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
165{
166 return false; // No search possible, therefore all settings invalid ;)
167}
168
169
170// *** Private stuff ***
171
172
173OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
174{
175 OContact c;
176
177 VObjectIterator it;
178 initPropIterator( &it, obj );
179 while( moreIteration( &it ) ) {
180 VObject *o = nextVObject( &it );
181 QCString name = vObjectName( o );
182 QCString value = vObjectStringZValue( o );
183 if ( name == VCNameProp ) {
184 VObjectIterator nit;
185 initPropIterator( &nit, o );
186 while( moreIteration( &nit ) ) {
187 VObject *o = nextVObject( &nit );
188 QCString name = vObjectTypeInfo( o );
189 QString value = vObjectStringZValue( o );
190 if ( name == VCNamePrefixesProp )
191 c.setTitle( value );
192 else if ( name == VCNameSuffixesProp )
193 c.setSuffix( value );
194 else if ( name == VCFamilyNameProp )
195 c.setLastName( value );
196 else if ( name == VCGivenNameProp )
197 c.setFirstName( value );
198 else if ( name == VCAdditionalNamesProp )
199 c.setMiddleName( value );
200 }
201 }
202 else if ( name == VCAdrProp ) {
203 bool work = TRUE; // default address is work address
204 QString street;
205 QString city;
206 QString region;
207 QString postal;
208 QString country;
209
210 VObjectIterator nit;
211 initPropIterator( &nit, o );
212 while( moreIteration( &nit ) ) {
213 VObject *o = nextVObject( &nit );
214 QCString name = vObjectName( o );
215 QString value = vObjectStringZValue( o );
216 if ( name == VCHomeProp )
217 work = FALSE;
218 else if ( name == VCWorkProp )
219 work = TRUE;
220 else if ( name == VCStreetAddressProp )
221 street = value;
222 else if ( name == VCCityProp )
223 city = value;
224 else if ( name == VCRegionProp )
225 region = value;
226 else if ( name == VCPostalCodeProp )
227 postal = value;
228 else if ( name == VCCountryNameProp )
229 country = value;
230 }
231 if ( work ) {
232 c.setBusinessStreet( street );
233 c.setBusinessCity( city );
234 c.setBusinessCountry( country );
235 c.setBusinessZip( postal );
236 c.setBusinessState( region );
237 } else {
238 c.setHomeStreet( street );
239 c.setHomeCity( city );
240 c.setHomeCountry( country );
241 c.setHomeZip( postal );
242 c.setHomeState( region );
243 }
244 }
245 else if ( name == VCTelephoneProp ) {
246 enum {
247 HOME = 0x01,
248 WORK = 0x02,
249 VOICE = 0x04,
250 CELL = 0x08,
251 FAX = 0x10,
252 PAGER = 0x20,
253 UNKNOWN = 0x80
254 };
255 int type = 0;
256
257 VObjectIterator nit;
258 initPropIterator( &nit, o );
259 while( moreIteration( &nit ) ) {
260 VObject *o = nextVObject( &nit );
261 QCString name = vObjectTypeInfo( o );
262 if ( name == VCHomeProp )
263 type |= HOME;
264 else if ( name == VCWorkProp )
265 type |= WORK;
266 else if ( name == VCVoiceProp )
267 type |= VOICE;
268 else if ( name == VCCellularProp )
269 type |= CELL;
270 else if ( name == VCFaxProp )
271 type |= FAX;
272 else if ( name == VCPagerProp )
273 type |= PAGER;
274 else if ( name == VCPreferredProp )
275 ;
276 else
277 type |= UNKNOWN;
278 }
279 if ( (type & UNKNOWN) != UNKNOWN ) {
280 if ( ( type & (HOME|WORK) ) == 0 ) // default
281 type |= HOME;
282 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
283 type |= VOICE;
284
285 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) )
286 c.setHomePhone( value );
287 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
288 c.setHomeFax( value );
289 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
290 c.setHomeMobile( value );
291 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) )
292 c.setBusinessPhone( value );
293 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
294 c.setBusinessFax( value );
295 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
296 c.setBusinessMobile( value );
297 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
298 c.setBusinessPager( value );
299 }
300 }
301 else if ( name == VCEmailAddressProp ) {
302 QString email = vObjectStringZValue( o );
303 bool valid = TRUE;
304 VObjectIterator nit;
305 initPropIterator( &nit, o );
306 while( moreIteration( &nit ) ) {
307 VObject *o = nextVObject( &nit );
308 QCString name = vObjectTypeInfo( o );
309 if ( name != VCInternetProp && name != VCHomeProp &&
310 name != VCWorkProp &&
311 name != VCPreferredProp )
312 // ### preffered should map to default email
313 valid = FALSE;
314 }
315 if ( valid ) {
316 c.insertEmail( email );
317 }
318 }
319 else if ( name == VCURLProp ) {
320 VObjectIterator nit;
321 initPropIterator( &nit, o );
322 while( moreIteration( &nit ) ) {
323 VObject *o = nextVObject( &nit );
324 QCString name = vObjectTypeInfo( o );
325 if ( name == VCHomeProp )
326 c.setHomeWebpage( value );
327 else if ( name == VCWorkProp )
328 c.setBusinessWebpage( value );
329 }
330 }
331 else if ( name == VCOrgProp ) {
332 VObjectIterator nit;
333 initPropIterator( &nit, o );
334 while( moreIteration( &nit ) ) {
335 VObject *o = nextVObject( &nit );
336 QCString name = vObjectName( o );
337 QString value = vObjectStringZValue( o );
338 if ( name == VCOrgNameProp )
339 c.setCompany( value );
340 else if ( name == VCOrgUnitProp )
341 c.setDepartment( value );
342 else if ( name == VCOrgUnit2Prop )
343 c.setOffice( value );
344 }
345 }
346 else if ( name == VCTitleProp ) {
347 c.setJobTitle( value );
348 }
349 else if ( name == "X-Qtopia-Profession" ) {
350 c.setProfession( value );
351 }
352 else if ( name == "X-Qtopia-Manager" ) {
353 c.setManager( value );
354 }
355 else if ( name == "X-Qtopia-Assistant" ) {
356 c.setAssistant( value );
357 }
358 else if ( name == "X-Qtopia-Spouse" ) {
359 c.setSpouse( value );
360 }
361 else if ( name == "X-Qtopia-Gender" ) {
362 c.setGender( value );
363 }
364 else if ( name == "X-Qtopia-Anniversary" ) {
365 c.setAnniversary( TimeConversion::fromString( value ) );
366 }
367 else if ( name == "X-Qtopia-Nickname" ) {
368 c.setNickname( value );
369 }
370 else if ( name == "X-Qtopia-Children" ) {
371 c.setChildren( value );
372 }
373 else if ( name == VCBirthDateProp ) {
374 // Reading Birthdate regarding RFC 2425 (5.8.4)
375 c.setBirthday( convVCardDateToDate( value ) );
376
377 }
378
379#if 0
380 else {
381 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
382 VObjectIterator nit;
383 initPropIterator( &nit, o );
384 while( moreIteration( &nit ) ) {
385 VObject *o = nextVObject( &nit );
386 QCString name = vObjectName( o );
387 QString value = vObjectStringZValue( o );
388 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
389 }
390 }
391#endif
392 }
393 c.setFileAs();
394 return c;
395}
396
397
398VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
399{
400 VObject *vcard = newVObject( VCCardProp );
401 safeAddPropValue( vcard, VCVersionProp, "2.1" );
402 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
403 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
404
405 // full name
406 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
407
408 // name properties
409 VObject *name = safeAddProp( vcard, VCNameProp );
410 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
411 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
412 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
413 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
414 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
415
416 // home properties
417 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
418 safeAddProp( home_adr, VCHomeProp );
419 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
420 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
421 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
422 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
423 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
424
425 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
426 safeAddProp( home_phone, VCHomeProp );
427 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
428 safeAddProp( home_phone, VCHomeProp );
429 safeAddProp( home_phone, VCCellularProp );
430 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
431 safeAddProp( home_phone, VCHomeProp );
432 safeAddProp( home_phone, VCFaxProp );
433
434 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
435 safeAddProp( url, VCHomeProp );
436
437 // work properties
438 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
439 safeAddProp( work_adr, VCWorkProp );
440 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
441 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
442 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
443 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
444 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
445
446 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
447 safeAddProp( work_phone, VCWorkProp );
448 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
449 safeAddProp( work_phone, VCWorkProp );
450 safeAddProp( work_phone, VCCellularProp );
451 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
452 safeAddProp( work_phone, VCWorkProp );
453 safeAddProp( work_phone, VCFaxProp );
454 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
455 safeAddProp( work_phone, VCWorkProp );
456 safeAddProp( work_phone, VCPagerProp );
457
458 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
459 safeAddProp( url, VCWorkProp );
460
461 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
462 safeAddProp( title, VCWorkProp );
463
464
465 QStringList emails = c.emailList();
466 emails.prepend( c.defaultEmail() );
467 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
468 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
469 safeAddProp( email, VCInternetProp );
470 }
471
472 safeAddPropValue( vcard, VCNoteProp, c.notes() );
473
474 // Exporting Birthday regarding RFC 2425 (5.8.4)
475 if ( c.birthday().isValid() ){
476 QString birthd_rfc2425 = QString("%1-%2-%3")
477 .arg( c.birthday().year() )
478 .arg( c.birthday().month(), 2 )
479 .arg( c.birthday().day(), 2 );
480 // Now replace spaces with "0"...
481 int pos = 0;
482 while ( ( pos = birthd_rfc2425.find (' ') ) > 0 )
483 birthd_rfc2425.replace( pos, 1, "0" );
484
485 qWarning("Exporting birthday as: %s", birthd_rfc2425.latin1());
486 safeAddPropValue( vcard, VCBirthDateProp, birthd_rfc2425.latin1() );
487 }
488
489 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
490 VObject *org = safeAddProp( vcard, VCOrgProp );
491 safeAddPropValue( org, VCOrgNameProp, c.company() );
492 safeAddPropValue( org, VCOrgUnitProp, c.department() );
493 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
494 }
495
496 // some values we have to export as custom fields
497 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
498 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
499 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
500
501 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
502 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
503 safeAddPropValue( vcard, "X-Qtopia-Anniversary", TimeConversion::toString( c.anniversary() ) );
504 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
505 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
506
507 return vcard;
508}
509
510QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
511{
512 int monthPos = datestr.find('-');
513 int dayPos = datestr.find('-', monthPos+1 );
514 int sep_ignore = 1;
515 if ( monthPos == -1 || dayPos == -1 ) {
516 qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
517 // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD )
518 if ( datestr.length() == 8 ){
519 monthPos = 4;
520 dayPos = 6;
521 sep_ignore = 0;
522 qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
523 } else {
524 return QDate();
525 }
526 }
527 int y = datestr.left( monthPos ).toInt();
528 int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
529 int d = datestr.mid( dayPos + sep_ignore ).toInt();
530 qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
531 QDate date ( y,m,d );
532 return date;
533}
534
535VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
536{
537 VObject *ret = 0;
538 if ( o && !value.isEmpty() )
539 ret = addPropValue( o, prop, value.latin1() );
540 return ret;
541}
542
543VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
544{
545 VObject *ret = 0;
546 if ( o )
547 ret = addProp( o, prop );
548 return ret;
549}
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
new file mode 100644
index 0000000..c1422b0
--- a/dev/null
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
@@ -0,0 +1,65 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * ToDo:
13 *
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2002/11/09 14:34:52 eilers
20 * Added VCard Backend.
21 *
22 */
23#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
24#define __OCONTACTACCESSBACKEND_VCARD_H_
25
26#include <opie/ocontact.h>
27
28#include "ocontactaccessbackend.h"
29
30class VObject;
31
32class OContactAccessBackend_VCard : public OContactAccessBackend {
33 public:
34 OContactAccessBackend_VCard ( QString appname, QString filename = 0l );
35
36 bool load ();
37 bool reload();
38 bool save();
39 void clear ();
40
41 bool add ( const OContact& newcontact );
42 bool remove ( int uid );
43 bool replace ( const OContact& contact );
44
45 OContact find ( int uid ) const;
46 QArray<int> allRecords() const;
47 QArray<int> queryByExample ( const OContact &query, int settings );
48 QArray<int> matchRegexp( const QRegExp &r ) const;
49
50 const uint querySettings();
51 bool hasQuerySettings (uint querySettings) const;
52
53private:
54 OContact parseVObject( VObject* obj );
55 VObject* createVObject( const OContact& c );
56 QDate convVCardDateToDate( const QString& datestr );
57 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
58 VObject *safeAddProp( VObject* o, const char* prop);
59
60 bool m_dirty : 1;
61 QString m_file;
62 QMap<int, OContact> m_map;
63};
64
65#endif