kaddressbook

vcard_xxport.cpp
1/*
2 This file is part of KAddressbook.
3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of TQt, and distribute the resulting executable,
21 without including the source code for TQt in the source distribution.
22*/
23
24#include <tqcheckbox.h>
25#include <tqfile.h>
26#include <tqfont.h>
27#include <tqlabel.h>
28#include <tqlayout.h>
29#include <tqpushbutton.h>
30
31#include <tdeabc/vcardconverter.h>
32#include <kdialogbase.h>
33#include <tdefiledialog.h>
34#include <tdeio/netaccess.h>
35#include <tdelocale.h>
36#include <tdemessagebox.h>
37#include <tdetempfile.h>
38#include <kurl.h>
39#include <tdeapplication.h>
40#include <libtdepim/addresseeview.h>
41
42#include "config.h" // ??
43
44#include "gpgmepp/context.h"
45#include "gpgmepp/data.h"
46#include "gpgmepp/key.h"
47#include "qgpgme/dataprovider.h"
48
49#include "xxportmanager.h"
50
51#include "vcard_xxport.h"
52
53K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_vcard_xxport, VCardXXPort )
54
55class VCardViewerDialog : public KDialogBase
56{
57 public:
58 VCardViewerDialog( const TDEABC::Addressee::List &list,
59 TQWidget *parent, const char *name = 0 );
60
61 TDEABC::Addressee::List contacts() const;
62
63 protected:
64 void slotUser1();
65 void slotUser2();
66 void slotApply();
67 void slotCancel();
68
69 private:
70 void updateView();
71
72 KPIM::AddresseeView *mView;
73
74 TDEABC::Addressee::List mContacts;
75 TDEABC::Addressee::List::Iterator mIt;
76};
77
78class VCardExportSelectionDialog : public KDialogBase
79{
80 public:
81 VCardExportSelectionDialog( TQWidget *parent, const char *name = 0 );
82 ~VCardExportSelectionDialog();
83
84 bool exportPrivateFields() const;
85 bool exportBusinessFields() const;
86 bool exportOtherFields() const;
87 bool exportEncryptionKeys() const;
88
89 private:
90 TQCheckBox *mPrivateBox;
91 TQCheckBox *mBusinessBox;
92 TQCheckBox *mOtherBox;
93 TQCheckBox *mEncryptionKeys;
94};
95
96VCardXXPort::VCardXXPort( TDEABC::AddressBook *ab, TQWidget *parent, const char *name )
97 : KAB::XXPort( ab, parent, name )
98{
99 createImportAction( i18n( "Import vCard..." ) );
100 createExportAction( i18n( "Export vCard 2.1..." ), "v21" );
101 createExportAction( i18n( "Export vCard 3.0..." ), "v30" );
102}
103
104bool VCardXXPort::exportContacts( const TDEABC::AddresseeList &addrList, const TQString &data )
105{
106 TDEABC::VCardConverter converter;
107 KURL url;
108 TDEABC::AddresseeList list;
109
110 list = filterContacts( addrList );
111
112 bool ok = true;
113 if ( list.isEmpty() ) {
114 return ok;
115 } else if ( list.count() == 1 ) {
116 url = KFileDialog::getSaveURL( list[ 0 ].givenName() + "_" + list[ 0 ].familyName() + ".vcf" );
117 if ( url.isEmpty() )
118 return true;
119
120 if ( data == "v21" )
121#if defined(KABC_VCARD_ENCODING_FIX)
122 ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v2_1 ) );
123 else
124 ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v3_0 ) );
125#else
126 ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v2_1 ) );
127 else
128 ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v3_0 ) );
129#endif
130 } else {
131 TQString msg = i18n( "You have selected a list of contacts, shall they be "
132 "exported to several files?" );
133
134 switch ( KMessageBox::questionYesNo( parentWidget(), msg, TQString(), i18n("Export to Several Files"), i18n("Export to One File") ) ) {
135 case KMessageBox::Yes: {
136 KURL baseUrl = KFileDialog::getExistingURL();
137 if ( baseUrl.isEmpty() )
138 return true;
139
140 TDEABC::AddresseeList::ConstIterator it;
141 uint counter = 0;
142 for ( it = list.begin(); it != list.end(); ++it ) {
143 TQString testUrl;
144 if ( (*it).givenName().isEmpty() && (*it).familyName().isEmpty() )
145 testUrl = baseUrl.url() + "/" + (*it).organization();
146 else
147 testUrl = baseUrl.url() + "/" + (*it).givenName() + "_" + (*it).familyName();
148
149 if ( TDEIO::NetAccess::exists( testUrl + (counter == 0 ? "" : TQString::number( counter )) + ".vcf", false, parentWidget() ) ) {
150 counter++;
151 url = testUrl + TQString::number( counter ) + ".vcf";
152 } else
153 url = testUrl + ".vcf";
154
155 bool tmpOk;
156 TDEABC::AddresseeList tmpList;
157 tmpList.append( *it );
158
159 if ( data == "v21" )
160#if defined(KABC_VCARD_ENCODING_FIX)
161 tmpOk = doExport( url, converter.createVCardsRaw( tmpList, TDEABC::VCardConverter::v2_1 ) );
162 else
163 tmpOk = doExport( url, converter.createVCardsRaw( tmpList, TDEABC::VCardConverter::v3_0 ) );
164#else
165 tmpOk = doExport( url, converter.createVCards( tmpList, TDEABC::VCardConverter::v2_1 ) );
166 else
167 tmpOk = doExport( url, converter.createVCards( tmpList, TDEABC::VCardConverter::v3_0 ) );
168#endif
169 ok = ok && tmpOk;
170 }
171 break;
172 }
173 case KMessageBox::No:
174 default: {
175 url = KFileDialog::getSaveURL( "addressbook.vcf" );
176 if ( url.isEmpty() )
177 return true;
178
179 if ( data == "v21" )
180#if defined(KABC_VCARD_ENCODING_FIX)
181 ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v2_1 ) );
182 else
183 ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v3_0 ) );
184#else
185 ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v2_1 ) );
186 else
187 ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v3_0 ) );
188#endif
189 }
190 }
191 }
192
193 return ok;
194}
195
196TDEABC::AddresseeList VCardXXPort::importContacts( const TQString& ) const
197{
198 TQString fileName;
199 TDEABC::AddresseeList addrList;
200 KURL::List urls;
201
202 if ( !XXPortManager::importData.isEmpty() ) {
203#if defined(KABC_VCARD_ENCODING_FIX)
204 TQCString data = XXPortManager::importData.ascii();
205 addrList = parseVCard( data );
206#else
207 addrList = parseVCard( XXPortManager::importData );
208#endif
209 } else {
210 if ( XXPortManager::importURL.isEmpty() )
211 urls = KFileDialog::getOpenURLs( TQString(), "*.vcf|vCards", parentWidget(),
212 i18n( "Select vCard to Import" ) );
213 else
214 urls.append( XXPortManager::importURL );
215
216 if ( urls.count() == 0 )
217 return addrList;
218
219 TQString caption( i18n( "vCard Import Failed" ) );
220 bool anyFailures = false;
221 KURL::List::Iterator it;
222 for ( it = urls.begin(); it != urls.end(); ++it ) {
223 if ( TDEIO::NetAccess::download( *it, fileName, parentWidget() ) ) {
224
225 TQFile file( fileName );
226
227 if ( file.open( IO_ReadOnly ) ) {
228#if defined(KABC_VCARD_ENCODING_FIX)
229 TQByteArray data = file.readAll();
230 file.close();
231 if ( data.size() > 0 )
232 addrList += parseVCard( data );
233#else
234 TQByteArray rawData = file.readAll();
235 file.close();
236 if ( rawData.size() > 0 ) {
237
238 TQString vCardText;
239
240 // With version 3.0, vCards are encoded with UTF-8 by default. Otherwise, use fromLatin1()
241 // and hope that are fields are encoded correctly.
242 if ( TQString::fromLatin1( rawData ).lower().contains( "version:3.0" ) ) {
243 vCardText = TQString::fromUtf8( rawData );
244 } else {
245 vCardText = TQString::fromLatin1( rawData );
246 }
247 addrList += parseVCard( vCardText );
248 }
249#endif
250 TDEIO::NetAccess::removeTempFile( fileName );
251 } else {
252 TQString text = i18n( "<qt>When trying to read the vCard, there was an error opening the file '%1': %2</qt>" );
253 text = text.arg( (*it).url() );
254 text = text.arg( kapp->translate( "TQFile",
255 TQString(file.errorString()).latin1() ) );
256 KMessageBox::error( parentWidget(), text, caption );
257 anyFailures = true;
258 }
259 } else {
260 TQString text = i18n( "<qt>Unable to access vCard: %1</qt>" );
261 text = text.arg( TDEIO::NetAccess::lastErrorString() );
262 KMessageBox::error( parentWidget(), text, caption );
263 anyFailures = true;
264 }
265 }
266
267 if ( !XXPortManager::importURL.isEmpty() ) { // a vcard was passed via cmd
268 if ( addrList.isEmpty() ) {
269 if ( anyFailures && urls.count() > 1 )
270 KMessageBox::information( parentWidget(),
271 i18n( "No contacts were imported, due to errors with the vCards." ) );
272 else if ( !anyFailures )
273 KMessageBox::information( parentWidget(), i18n( "The vCard does not contain any contacts." ) );
274 } else {
275 VCardViewerDialog dlg( addrList, parentWidget() );
276 dlg.exec();
277 addrList = dlg.contacts();
278 }
279 }
280 }
281
282 return addrList;
283}
284
285#if defined(KABC_VCARD_ENCODING_FIX)
286TDEABC::AddresseeList VCardXXPort::parseVCard( const TQByteArray &data ) const
287{
288 TDEABC::VCardConverter converter;
289
290 return converter.parseVCardsRaw( data.data() );
291}
292
293bool VCardXXPort::doExport( const KURL &url, const TQByteArray &data )
294{
295 if( TQFileInfo(url.path()).exists() ) {
296 if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No)
297 return false;
298 }
299 KTempFile tmpFile;
300 tmpFile.setAutoDelete( true );
301
302 tmpFile.file()->writeBlock( data.data(), data.size() );
303 tmpFile.close();
304
305 return TDEIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
306}
307#else
308TDEABC::AddresseeList VCardXXPort::parseVCard( const TQString &data ) const
309{
310 TDEABC::VCardConverter converter;
311
312 return converter.parseVCards( data );
313}
314
315bool VCardXXPort::doExport( const KURL &url, const TQString &data )
316{
317 if( TQFileInfo(url.path()).exists() ) {
318 if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No)
319 return false;
320 }
321 KTempFile tmpFile;
322 tmpFile.setAutoDelete( true );
323
324 TQTextStream stream( tmpFile.file() );
325 stream.setEncoding( TQTextStream::UnicodeUTF8 );
326
327 stream << data;
328 tmpFile.close();
329
330 return TDEIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
331}
332#endif
333
334TDEABC::AddresseeList VCardXXPort::filterContacts( const TDEABC::AddresseeList &addrList )
335{
336 TDEABC::AddresseeList list;
337
338 if ( addrList.isEmpty() )
339 return addrList;
340
341 VCardExportSelectionDialog dlg( parentWidget() );
342 if ( !dlg.exec() )
343 return list;
344
345 TDEABC::AddresseeList::ConstIterator it;
346 for ( it = addrList.begin(); it != addrList.end(); ++it ) {
347 TDEABC::Addressee addr;
348
349 addr.setUid( (*it).uid() );
350 addr.setFormattedName( (*it).formattedName() );
351 addr.setPrefix( (*it).prefix() );
352 addr.setGivenName( (*it).givenName() );
353 addr.setAdditionalName( (*it).additionalName() );
354 addr.setFamilyName( (*it).familyName() );
355 addr.setSuffix( (*it).suffix() );
356 addr.setNickName( (*it).nickName() );
357 addr.setMailer( (*it).mailer() );
358 addr.setTimeZone( (*it).timeZone() );
359 addr.setGeo( (*it).geo() );
360 addr.setProductId( (*it).productId() );
361 addr.setSortString( (*it).sortString() );
362 addr.setUrl( (*it).url() );
363 addr.setSecrecy( (*it).secrecy() );
364 addr.setSound( (*it).sound() );
365 addr.setEmails( (*it).emails() );
366 addr.setCategories( (*it).categories() );
367
368 if ( dlg.exportPrivateFields() ) {
369 addr.setBirthday( (*it).birthday() );
370 addr.setNote( (*it).note() );
371 addr.setPhoto( (*it).photo() );
372 }
373
374 if ( dlg.exportBusinessFields() ) {
375 addr.setTitle( (*it).title() );
376 addr.setRole( (*it).role() );
377 addr.setOrganization( (*it).organization() );
378
379 addr.setLogo( (*it).logo() );
380
381 TDEABC::PhoneNumber::List phones = (*it).phoneNumbers( TDEABC::PhoneNumber::Work );
382 TDEABC::PhoneNumber::List::Iterator phoneIt;
383 for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt )
384 addr.insertPhoneNumber( *phoneIt );
385
386 TDEABC::Address::List addresses = (*it).addresses( TDEABC::Address::Work );
387 TDEABC::Address::List::Iterator addrIt;
388 for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt )
389 addr.insertAddress( *addrIt );
390 }
391
392 TDEABC::PhoneNumber::List phones = (*it).phoneNumbers();
393 TDEABC::PhoneNumber::List::Iterator phoneIt;
394 for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) {
395 int type = (*phoneIt).type();
396
397 if ( type & TDEABC::PhoneNumber::Home && dlg.exportPrivateFields() )
398 addr.insertPhoneNumber( *phoneIt );
399 else if ( type & TDEABC::PhoneNumber::Work && dlg.exportBusinessFields() )
400 addr.insertPhoneNumber( *phoneIt );
401 else if ( dlg.exportOtherFields() )
402 addr.insertPhoneNumber( *phoneIt );
403 }
404
405 TDEABC::Address::List addresses = (*it).addresses();
406 TDEABC::Address::List::Iterator addrIt;
407 for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) {
408 int type = (*addrIt).type();
409
410 if ( type & TDEABC::Address::Home && dlg.exportPrivateFields() )
411 addr.insertAddress( *addrIt );
412 else if ( type & TDEABC::Address::Work && dlg.exportBusinessFields() )
413 addr.insertAddress( *addrIt );
414 else if ( dlg.exportOtherFields() )
415 addr.insertAddress( *addrIt );
416 }
417
418 if ( dlg.exportOtherFields() )
419 addr.setCustoms( (*it).customs() );
420
421 if ( dlg.exportEncryptionKeys() ) {
422 addKey( addr, TDEABC::Key::PGP );
423 addKey( addr, TDEABC::Key::X509 );
424 }
425
426 list.append( addr );
427 }
428
429 return list;
430}
431
432void VCardXXPort::addKey( TDEABC::Addressee &addr, TDEABC::Key::Types type )
433{
434 TQString fingerprint = addr.custom( "KADDRESSBOOK",
435 (type == TDEABC::Key::PGP ? "OPENPGPFP" : "SMIMEFP") );
436 if ( fingerprint.isEmpty() )
437 return;
438
439 GpgME::Context * context = GpgME::Context::createForProtocol( GpgME::Context::OpenPGP );
440 if ( !context ) {
441 kdError() << "No context available" << endl;
442 return;
443 }
444
445 context->setArmor( false );
446 context->setTextMode( false );
447
448 QGpgME::TQByteArrayDataProvider dataProvider;
449 GpgME::Data dataObj( &dataProvider );
450 GpgME::Error error = context->exportPublicKeys( fingerprint.latin1(), dataObj );
451 delete context;
452
453 if ( error ) {
454 kdError() << error.asString() << endl;
455 return;
456 }
457
458 TDEABC::Key key;
459 key.setType( type );
460 key.setBinaryData( dataProvider.data() );
461
462 addr.insertKey( key );
463}
464
465// ---------- VCardViewer Dialog ---------------- //
466
467VCardViewerDialog::VCardViewerDialog( const TDEABC::Addressee::List &list,
468 TQWidget *parent, const char *name )
469 : KDialogBase( Plain, i18n( "Import vCard" ), Yes | No | Apply | Cancel, Yes,
470 parent, name, true, true, KStdGuiItem::no(), KStdGuiItem::yes() ),
471 mContacts( list )
472{
473 TQFrame *page = plainPage();
474 TQVBoxLayout *layout = new TQVBoxLayout( page, marginHint(), spacingHint() );
475
476 TQLabel *label = new TQLabel( i18n( "Do you want to import this contact in your address book?" ), page );
477 TQFont font = label->font();
478 font.setBold( true );
479 label->setFont( font );
480 layout->addWidget( label );
481
482 mView = new KPIM::AddresseeView( page );
483 mView->enableLinks( 0 );
484 mView->setVScrollBarMode( TQScrollView::Auto );
485 layout->addWidget( mView );
486
487 setButtonText( Apply, i18n( "Import All..." ) );
488
489 mIt = mContacts.begin();
490
491 updateView();
492}
493
494TDEABC::Addressee::List VCardViewerDialog::contacts() const
495{
496 return mContacts;
497}
498
499void VCardViewerDialog::updateView()
500{
501 mView->setAddressee( *mIt );
502
503 TDEABC::Addressee::List::Iterator it = mIt;
504 actionButton( Apply )->setEnabled( (++it) != mContacts.end() );
505}
506
507void VCardViewerDialog::slotUser1()
508{
509 mIt = mContacts.remove( mIt );
510
511 if ( mIt == mContacts.end() )
512 slotApply();
513
514 updateView();
515}
516
517void VCardViewerDialog::slotUser2()
518{
519 mIt++;
520
521 if ( mIt == mContacts.end() )
522 slotApply();
523
524 updateView();
525}
526
527void VCardViewerDialog::slotApply()
528{
529 TQDialog::accept();
530}
531
532void VCardViewerDialog::slotCancel()
533{
534 mContacts.clear();
535 TQDialog::accept();
536}
537
538// ---------- VCardExportSelection Dialog ---------------- //
539
540VCardExportSelectionDialog::VCardExportSelectionDialog( TQWidget *parent,
541 const char *name )
542 : KDialogBase( Plain, i18n( "Select vCard Fields" ), Ok | Cancel, Ok,
543 parent, name, true, true )
544{
545 TQFrame *page = plainPage();
546
547 TQVBoxLayout *layout = new TQVBoxLayout( page, marginHint(), spacingHint() );
548
549 TQLabel *label = new TQLabel( i18n( "Select the fields which shall be exported in the vCard." ), page );
550 layout->addWidget( label );
551
552 mPrivateBox = new TQCheckBox( i18n( "Private fields" ), page );
553 layout->addWidget( mPrivateBox );
554
555 mBusinessBox = new TQCheckBox( i18n( "Business fields" ), page );
556 layout->addWidget( mBusinessBox );
557
558 mOtherBox = new TQCheckBox( i18n( "Other fields" ), page );
559 layout->addWidget( mOtherBox );
560
561 mEncryptionKeys = new TQCheckBox( i18n( "Encryption keys" ), page );
562 layout->addWidget( mEncryptionKeys );
563
564 TDEConfig config( "kaddressbookrc" );
565 config.setGroup( "XXPortVCard" );
566
567 mPrivateBox->setChecked( config.readBoolEntry( "ExportPrivateFields", true ) );
568 mBusinessBox->setChecked( config.readBoolEntry( "ExportBusinessFields", false ) );
569 mOtherBox->setChecked( config.readBoolEntry( "ExportOtherFields", false ) );
570 mEncryptionKeys->setChecked( config.readBoolEntry( "ExportEncryptionKeys", false ) );
571}
572
573VCardExportSelectionDialog::~VCardExportSelectionDialog()
574{
575 TDEConfig config( "kaddressbookrc" );
576 config.setGroup( "XXPortVCard" );
577
578 config.writeEntry( "ExportPrivateFields", mPrivateBox->isChecked() );
579 config.writeEntry( "ExportBusinessFields", mBusinessBox->isChecked() );
580 config.writeEntry( "ExportOtherFields", mOtherBox->isChecked() );
581 config.writeEntry( "ExportEncryptionKeys", mEncryptionKeys->isChecked() );
582}
583
584bool VCardExportSelectionDialog::exportPrivateFields() const
585{
586 return mPrivateBox->isChecked();
587}
588
589bool VCardExportSelectionDialog::exportBusinessFields() const
590{
591 return mBusinessBox->isChecked();
592}
593
594bool VCardExportSelectionDialog::exportOtherFields() const
595{
596 return mOtherBox->isChecked();
597}
598
599bool VCardExportSelectionDialog::exportEncryptionKeys() const
600{
601 return mEncryptionKeys->isChecked();
602}
603
604#include "vcard_xxport.moc"