summaryrefslogtreecommitdiff
path: root/libopie/pim/ocontactaccessbackend_vcard.cpp
Unidiff
Diffstat (limited to 'libopie/pim/ocontactaccessbackend_vcard.cpp') (more/less context) (show whitespace changes)
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.cpp646
1 files changed, 0 insertions, 646 deletions
diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp
deleted file mode 100644
index b60c5be..0000000
--- a/libopie/pim/ocontactaccessbackend_vcard.cpp
+++ b/dev/null
@@ -1,646 +0,0 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 * =====================================================================
13 * ToDo:
14 *
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.11 2003/08/01 12:30:16 eilers
21 * Merging changes from BRANCH_1_0 to HEAD
22 *
23 * Revision 1.10.4.3 2003/07/23 08:54:37 eilers
24 * Default email was added to the list of all emails, which already contains
25 * the default email..
26 * This closes bug #1045
27 *
28 * Revision 1.10.4.2 2003/07/23 08:44:45 eilers
29 * Importing of Notes in vcard files wasn't implemented.
30 * Closes bug #1044
31 *
32 * Revision 1.10.4.1 2003/06/02 13:37:49 eilers
33 * Fixing memory leak
34 *
35 * Revision 1.10 2003/04/13 18:07:10 zecke
36 * More API doc
37 * QString -> const QString&
38 * QString = 0l -> QString::null
39 *
40 * Revision 1.9 2003/03/21 10:33:09 eilers
41 * Merged speed optimized xml backend for contacts to main.
42 * Added QDateTime to querybyexample. For instance, it is now possible to get
43 * all Birthdays/Anniversaries between two dates. This should be used
44 * to show all birthdays in the datebook..
45 * This change is sourcecode backward compatible but you have to upgrade
46 * the binaries for today-addressbook.
47 *
48 * Revision 1.8 2003/02/21 16:52:49 zecke
49 * -Remove old Todo classes they're deprecated and today I already using the
50 * new API
51 * -Guard against self assignment in OTodo
52 * -Add test apps for OPIM
53 * -Opiefied Event classes
54 * -Added TimeZone handling and pinning of TimeZones to OEvent
55 * -Adjust ORecur and the widget to better timezone behaviour
56 *
57 * Revision 1.7 2003/02/16 22:25:46 zecke
58 * 0000276 Fix for that bug.. or better temp workaround
59 * A Preferred Number is HOME|VOICE
60 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test
61 * triggers both
62 * and the cell phone number overrides the other entries..
63 *
64 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the
65 * number
66 *
67 * The right and final fix would be to reorder the if statement to make it
68 * if else based and the less common thing put to the bottom
69 *
70 * OTodoAccessVcal fix the date for beaming
71 *
72 * Revision 1.6 2003/01/13 15:49:31 eilers
73 * Fixing crash when businesscard.vcf is missing..
74 *
75 * Revision 1.5 2002/12/07 13:26:22 eilers
76 * Fixing bug in storing anniversary..
77 *
78 * Revision 1.4 2002/11/13 14:14:51 eilers
79 * Added sorted for Contacts..
80 *
81 * Revision 1.3 2002/11/11 16:41:09 kergoth
82 * no default arguments in implementation
83 *
84 * Revision 1.2 2002/11/10 15:41:53 eilers
85 * Bugfixes..
86 *
87 * Revision 1.1 2002/11/09 14:34:52 eilers
88 * Added VCard Backend.
89 *
90 */
91#include "ocontactaccessbackend_vcard.h"
92#include "../../library/backend/vobject_p.h"
93#include "../../library/backend/qfiledirect_p.h"
94
95#include <qpe/timeconversion.h>
96
97#include <qfile.h>
98
99OContactAccessBackend_VCard::OContactAccessBackend_VCard ( const QString& , const QString& filename ):
100 m_dirty( false ),
101 m_file( filename )
102{
103 load();
104}
105
106
107bool OContactAccessBackend_VCard::load ()
108{
109 m_map.clear();
110 m_dirty = false;
111
112 VObject* obj = 0l;
113
114 if ( QFile::exists(m_file) ){
115 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
116 if ( !obj )
117 return false;
118 }else{
119 qWarning("File \"%s\" not found !", m_file.latin1() );
120 return false;
121 }
122
123 while ( obj ) {
124 OContact con = parseVObject( obj );
125 /*
126 * if uid is 0 assign a new one
127 * this at least happens on
128 * Nokia6210
129 */
130 if ( con.uid() == 0 ){
131 con.setUid( 1 );
132 qWarning("assigned new uid %d",con.uid() );
133 }
134
135 m_map.insert( con.uid(), con );
136
137 VObject *t = obj;
138 obj = nextVObjectInList(obj);
139 cleanVObject( t );
140 }
141
142 return true;
143
144}
145bool OContactAccessBackend_VCard::reload()
146{
147 return load();
148}
149bool OContactAccessBackend_VCard::save()
150{
151 if (!m_dirty )
152 return true;
153
154 QFileDirect file( m_file );
155 if (!file.open(IO_WriteOnly ) )
156 return false;
157
158 VObject *obj;
159 obj = newVObject( VCCalProp );
160 addPropValue( obj, VCVersionProp, "1.0" );
161
162 VObject *vo;
163 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
164 vo = createVObject( *it );
165 writeVObject( file.directHandle() , vo );
166 cleanVObject( vo );
167 }
168 cleanStrTbl();
169 deleteVObject( obj );
170
171 m_dirty = false;
172 return true;
173
174
175}
176void OContactAccessBackend_VCard::clear ()
177{
178 m_map.clear();
179 m_dirty = true; // ??? sure ? (se)
180}
181
182bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
183{
184 m_map.insert( newcontact.uid(), newcontact );
185 m_dirty = true;
186 return true;
187}
188
189bool OContactAccessBackend_VCard::remove ( int uid )
190{
191 m_map.remove( uid );
192 m_dirty = true;
193 return true;
194}
195
196bool OContactAccessBackend_VCard::replace ( const OContact &contact )
197{
198 m_map.replace( contact.uid(), contact );
199 m_dirty = true;
200 return true;
201}
202
203OContact OContactAccessBackend_VCard::find ( int uid ) const
204{
205 return m_map[uid];
206}
207
208QArray<int> OContactAccessBackend_VCard::allRecords() const
209{
210 QArray<int> ar( m_map.count() );
211 QMap<int, OContact>::ConstIterator it;
212 int i = 0;
213 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
214 ar[i] = it.key();
215 i++;
216 }
217 return ar;
218}
219
220// Not implemented
221QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
222{
223 QArray<int> ar(0);
224 return ar;
225}
226
227// Not implemented
228QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
229{
230 QArray<int> ar(0);
231 return ar;
232}
233
234const uint OContactAccessBackend_VCard::querySettings()
235{
236 return 0; // No search possible
237}
238
239bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
240{
241 return false; // No search possible, therefore all settings invalid ;)
242}
243
244bool OContactAccessBackend_VCard::wasChangedExternally()
245{
246 return false; // Don't expect concurrent access
247}
248
249// Not implemented
250QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int )
251{
252 QArray<int> ar(0);
253 return ar;
254}
255
256// *** Private stuff ***
257
258
259OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
260{
261 OContact c;
262
263 VObjectIterator it;
264 initPropIterator( &it, obj );
265 while( moreIteration( &it ) ) {
266 VObject *o = nextVObject( &it );
267 QCString name = vObjectName( o );
268 QCString value = vObjectStringZValue( o );
269 if ( name == VCNameProp ) {
270 VObjectIterator nit;
271 initPropIterator( &nit, o );
272 while( moreIteration( &nit ) ) {
273 VObject *o = nextVObject( &nit );
274 QCString name = vObjectTypeInfo( o );
275 QString value = vObjectStringZValue( o );
276 if ( name == VCNamePrefixesProp )
277 c.setTitle( value );
278 else if ( name == VCNameSuffixesProp )
279 c.setSuffix( value );
280 else if ( name == VCFamilyNameProp )
281 c.setLastName( value );
282 else if ( name == VCGivenNameProp )
283 c.setFirstName( value );
284 else if ( name == VCAdditionalNamesProp )
285 c.setMiddleName( value );
286 }
287 }
288 else if ( name == VCAdrProp ) {
289 bool work = TRUE; // default address is work address
290 QString street;
291 QString city;
292 QString region;
293 QString postal;
294 QString country;
295
296 VObjectIterator nit;
297 initPropIterator( &nit, o );
298 while( moreIteration( &nit ) ) {
299 VObject *o = nextVObject( &nit );
300 QCString name = vObjectName( o );
301 QString value = vObjectStringZValue( o );
302 if ( name == VCHomeProp )
303 work = FALSE;
304 else if ( name == VCWorkProp )
305 work = TRUE;
306 else if ( name == VCStreetAddressProp )
307 street = value;
308 else if ( name == VCCityProp )
309 city = value;
310 else if ( name == VCRegionProp )
311 region = value;
312 else if ( name == VCPostalCodeProp )
313 postal = value;
314 else if ( name == VCCountryNameProp )
315 country = value;
316 }
317 if ( work ) {
318 c.setBusinessStreet( street );
319 c.setBusinessCity( city );
320 c.setBusinessCountry( country );
321 c.setBusinessZip( postal );
322 c.setBusinessState( region );
323 } else {
324 c.setHomeStreet( street );
325 c.setHomeCity( city );
326 c.setHomeCountry( country );
327 c.setHomeZip( postal );
328 c.setHomeState( region );
329 }
330 }
331 else if ( name == VCTelephoneProp ) {
332 enum {
333 HOME = 0x01,
334 WORK = 0x02,
335 VOICE = 0x04,
336 CELL = 0x08,
337 FAX = 0x10,
338 PAGER = 0x20,
339 UNKNOWN = 0x80
340 };
341 int type = 0;
342
343 VObjectIterator nit;
344 initPropIterator( &nit, o );
345 while( moreIteration( &nit ) ) {
346 VObject *o = nextVObject( &nit );
347 QCString name = vObjectTypeInfo( o );
348 if ( name == VCHomeProp )
349 type |= HOME;
350 else if ( name == VCWorkProp )
351 type |= WORK;
352 else if ( name == VCVoiceProp )
353 type |= VOICE;
354 else if ( name == VCCellularProp )
355 type |= CELL;
356 else if ( name == VCFaxProp )
357 type |= FAX;
358 else if ( name == VCPagerProp )
359 type |= PAGER;
360 else if ( name == VCPreferredProp )
361 ;
362 else
363 type |= UNKNOWN;
364 }
365 if ( (type & UNKNOWN) != UNKNOWN ) {
366 if ( ( type & (HOME|WORK) ) == 0 ) // default
367 type |= HOME;
368 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
369 type |= VOICE;
370
371 qWarning("value %s %d", value.data(), type );
372 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) )
373 c.setHomePhone( value );
374 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
375 c.setHomeFax( value );
376 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
377 c.setHomeMobile( value );
378 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) )
379 c.setBusinessPhone( value );
380 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
381 c.setBusinessFax( value );
382 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
383 c.setBusinessMobile( value );
384 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
385 c.setBusinessPager( value );
386 }
387 }
388 else if ( name == VCEmailAddressProp ) {
389 QString email = vObjectStringZValue( o );
390 bool valid = TRUE;
391 VObjectIterator nit;
392 initPropIterator( &nit, o );
393 while( moreIteration( &nit ) ) {
394 VObject *o = nextVObject( &nit );
395 QCString name = vObjectTypeInfo( o );
396 if ( name != VCInternetProp && name != VCHomeProp &&
397 name != VCWorkProp &&
398 name != VCPreferredProp )
399 // ### preffered should map to default email
400 valid = FALSE;
401 }
402 if ( valid ) {
403 c.insertEmail( email );
404 }
405 }
406 else if ( name == VCURLProp ) {
407 VObjectIterator nit;
408 initPropIterator( &nit, o );
409 while( moreIteration( &nit ) ) {
410 VObject *o = nextVObject( &nit );
411 QCString name = vObjectTypeInfo( o );
412 if ( name == VCHomeProp )
413 c.setHomeWebpage( value );
414 else if ( name == VCWorkProp )
415 c.setBusinessWebpage( value );
416 }
417 }
418 else if ( name == VCOrgProp ) {
419 VObjectIterator nit;
420 initPropIterator( &nit, o );
421 while( moreIteration( &nit ) ) {
422 VObject *o = nextVObject( &nit );
423 QCString name = vObjectName( o );
424 QString value = vObjectStringZValue( o );
425 if ( name == VCOrgNameProp )
426 c.setCompany( value );
427 else if ( name == VCOrgUnitProp )
428 c.setDepartment( value );
429 else if ( name == VCOrgUnit2Prop )
430 c.setOffice( value );
431 }
432 }
433 else if ( name == VCTitleProp ) {
434 c.setJobTitle( value );
435 }
436 else if ( name == "X-Qtopia-Profession" ) {
437 c.setProfession( value );
438 }
439 else if ( name == "X-Qtopia-Manager" ) {
440 c.setManager( value );
441 }
442 else if ( name == "X-Qtopia-Assistant" ) {
443 c.setAssistant( value );
444 }
445 else if ( name == "X-Qtopia-Spouse" ) {
446 c.setSpouse( value );
447 }
448 else if ( name == "X-Qtopia-Gender" ) {
449 c.setGender( value );
450 }
451 else if ( name == "X-Qtopia-Anniversary" ) {
452 c.setAnniversary( convVCardDateToDate( value ) );
453 }
454 else if ( name == "X-Qtopia-Nickname" ) {
455 c.setNickname( value );
456 }
457 else if ( name == "X-Qtopia-Children" ) {
458 c.setChildren( value );
459 }
460 else if ( name == VCBirthDateProp ) {
461 // Reading Birthdate regarding RFC 2425 (5.8.4)
462 c.setBirthday( convVCardDateToDate( value ) );
463
464 }
465 else if ( name == VCCommentProp ) {
466 c.setNotes( value );
467 }
468#if 0
469 else {
470 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
471 VObjectIterator nit;
472 initPropIterator( &nit, o );
473 while( moreIteration( &nit ) ) {
474 VObject *o = nextVObject( &nit );
475 QCString name = vObjectName( o );
476 QString value = vObjectStringZValue( o );
477 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
478 }
479 }
480#endif
481 }
482 c.setFileAs();
483 return c;
484}
485
486
487VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
488{
489 VObject *vcard = newVObject( VCCardProp );
490 safeAddPropValue( vcard, VCVersionProp, "2.1" );
491 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
492 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
493
494 // full name
495 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
496
497 // name properties
498 VObject *name = safeAddProp( vcard, VCNameProp );
499 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
500 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
501 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
502 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
503 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
504
505 // home properties
506 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
507 safeAddProp( home_adr, VCHomeProp );
508 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
509 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
510 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
511 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
512 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
513
514 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
515 safeAddProp( home_phone, VCHomeProp );
516 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
517 safeAddProp( home_phone, VCHomeProp );
518 safeAddProp( home_phone, VCCellularProp );
519 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
520 safeAddProp( home_phone, VCHomeProp );
521 safeAddProp( home_phone, VCFaxProp );
522
523 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
524 safeAddProp( url, VCHomeProp );
525
526 // work properties
527 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
528 safeAddProp( work_adr, VCWorkProp );
529 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
530 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
531 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
532 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
533 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
534
535 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
536 safeAddProp( work_phone, VCWorkProp );
537 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
538 safeAddProp( work_phone, VCWorkProp );
539 safeAddProp( work_phone, VCCellularProp );
540 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
541 safeAddProp( work_phone, VCWorkProp );
542 safeAddProp( work_phone, VCFaxProp );
543 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
544 safeAddProp( work_phone, VCWorkProp );
545 safeAddProp( work_phone, VCPagerProp );
546
547 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
548 safeAddProp( url, VCWorkProp );
549
550 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
551 safeAddProp( title, VCWorkProp );
552
553
554 QStringList emails = c.emailList();
555 // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045
556 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
557 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
558 safeAddProp( email, VCInternetProp );
559 }
560
561 safeAddPropValue( vcard, VCNoteProp, c.notes() );
562
563 // Exporting Birthday regarding RFC 2425 (5.8.4)
564 if ( c.birthday().isValid() ){
565 qWarning("Exporting birthday as: %s", convDateToVCardDate( c.birthday() ).latin1() );
566 safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) );
567 }
568
569 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
570 VObject *org = safeAddProp( vcard, VCOrgProp );
571 safeAddPropValue( org, VCOrgNameProp, c.company() );
572 safeAddPropValue( org, VCOrgUnitProp, c.department() );
573 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
574 }
575
576 // some values we have to export as custom fields
577 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
578 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
579 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
580
581 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
582 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
583 if ( c.anniversary().isValid() ){
584 qWarning("Exporting anniversary as: %s", convDateToVCardDate( c.anniversary() ).latin1() );
585 safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) );
586 }
587 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
588 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
589
590 return vcard;
591}
592
593QString OContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const
594{
595 QString str_rfc2425 = QString("%1-%2-%3")
596 .arg( d.year() )
597 .arg( d.month(), 2 )
598 .arg( d.day(), 2 );
599 // Now replace spaces with "0"...
600 int pos = 0;
601 while ( ( pos = str_rfc2425.find (' ') ) > 0 )
602 str_rfc2425.replace( pos, 1, "0" );
603
604 return str_rfc2425;
605}
606
607QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
608{
609 int monthPos = datestr.find('-');
610 int dayPos = datestr.find('-', monthPos+1 );
611 int sep_ignore = 1;
612 if ( monthPos == -1 || dayPos == -1 ) {
613 qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
614 // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD )
615 if ( datestr.length() == 8 ){
616 monthPos = 4;
617 dayPos = 6;
618 sep_ignore = 0;
619 qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
620 } else {
621 return QDate();
622 }
623 }
624 int y = datestr.left( monthPos ).toInt();
625 int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
626 int d = datestr.mid( dayPos + sep_ignore ).toInt();
627 qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
628 QDate date ( y,m,d );
629 return date;
630}
631
632VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
633{
634 VObject *ret = 0;
635 if ( o && !value.isEmpty() )
636 ret = addPropValue( o, prop, value.latin1() );
637 return ret;
638}
639
640VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
641{
642 VObject *ret = 0;
643 if ( o )
644 ret = addProp( o, prop );
645 return ret;
646}