vcard_xxport.cpp
00001 /* 00002 This file is part of KAddressbook. 00003 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 00019 As a special exception, permission is given to link this program 00020 with any edition of TQt, and distribute the resulting executable, 00021 without including the source code for TQt in the source distribution. 00022 */ 00023 00024 #include <tqcheckbox.h> 00025 #include <tqfile.h> 00026 #include <tqfont.h> 00027 #include <tqlabel.h> 00028 #include <tqlayout.h> 00029 #include <tqpushbutton.h> 00030 00031 #include <kabc/vcardconverter.h> 00032 #include <kdialogbase.h> 00033 #include <kfiledialog.h> 00034 #include <kio/netaccess.h> 00035 #include <klocale.h> 00036 #include <kmessagebox.h> 00037 #include <ktempfile.h> 00038 #include <kurl.h> 00039 #include <kapplication.h> 00040 #include <libkdepim/addresseeview.h> 00041 00042 #include "config.h" // ?? 00043 00044 #include "gpgmepp/context.h" 00045 #include "gpgmepp/data.h" 00046 #include "gpgmepp/key.h" 00047 #include "qgpgme/dataprovider.h" 00048 00049 #include "xxportmanager.h" 00050 00051 #include "vcard_xxport.h" 00052 00053 K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_vcard_xxport, VCardXXPort ) 00054 00055 class VCardViewerDialog : public KDialogBase 00056 { 00057 public: 00058 VCardViewerDialog( const KABC::Addressee::List &list, 00059 TQWidget *parent, const char *name = 0 ); 00060 00061 KABC::Addressee::List contacts() const; 00062 00063 protected: 00064 void slotUser1(); 00065 void slotUser2(); 00066 void slotApply(); 00067 void slotCancel(); 00068 00069 private: 00070 void updateView(); 00071 00072 KPIM::AddresseeView *mView; 00073 00074 KABC::Addressee::List mContacts; 00075 KABC::Addressee::List::Iterator mIt; 00076 }; 00077 00078 class VCardExportSelectionDialog : public KDialogBase 00079 { 00080 public: 00081 VCardExportSelectionDialog( TQWidget *parent, const char *name = 0 ); 00082 ~VCardExportSelectionDialog(); 00083 00084 bool exportPrivateFields() const; 00085 bool exportBusinessFields() const; 00086 bool exportOtherFields() const; 00087 bool exportEncryptionKeys() const; 00088 00089 private: 00090 TQCheckBox *mPrivateBox; 00091 TQCheckBox *mBusinessBox; 00092 TQCheckBox *mOtherBox; 00093 TQCheckBox *mEncryptionKeys; 00094 }; 00095 00096 VCardXXPort::VCardXXPort( KABC::AddressBook *ab, TQWidget *parent, const char *name ) 00097 : KAB::XXPort( ab, parent, name ) 00098 { 00099 createImportAction( i18n( "Import vCard..." ) ); 00100 createExportAction( i18n( "Export vCard 2.1..." ), "v21" ); 00101 createExportAction( i18n( "Export vCard 3.0..." ), "v30" ); 00102 } 00103 00104 bool VCardXXPort::exportContacts( const KABC::AddresseeList &addrList, const TQString &data ) 00105 { 00106 KABC::VCardConverter converter; 00107 KURL url; 00108 KABC::AddresseeList list; 00109 00110 list = filterContacts( addrList ); 00111 00112 bool ok = true; 00113 if ( list.isEmpty() ) { 00114 return ok; 00115 } else if ( list.count() == 1 ) { 00116 url = KFileDialog::getSaveURL( list[ 0 ].givenName() + "_" + list[ 0 ].familyName() + ".vcf" ); 00117 if ( url.isEmpty() ) 00118 return true; 00119 00120 if ( data == "v21" ) 00121 #if defined(KABC_VCARD_ENCODING_FIX) 00122 ok = doExport( url, converter.createVCardsRaw( list, KABC::VCardConverter::v2_1 ) ); 00123 else 00124 ok = doExport( url, converter.createVCardsRaw( list, KABC::VCardConverter::v3_0 ) ); 00125 #else 00126 ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v2_1 ) ); 00127 else 00128 ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v3_0 ) ); 00129 #endif 00130 } else { 00131 TQString msg = i18n( "You have selected a list of contacts, shall they be " 00132 "exported to several files?" ); 00133 00134 switch ( KMessageBox::questionYesNo( parentWidget(), msg, TQString(), i18n("Export to Several Files"), i18n("Export to One File") ) ) { 00135 case KMessageBox::Yes: { 00136 KURL baseUrl = KFileDialog::getExistingURL(); 00137 if ( baseUrl.isEmpty() ) 00138 return true; 00139 00140 KABC::AddresseeList::ConstIterator it; 00141 uint counter = 0; 00142 for ( it = list.begin(); it != list.end(); ++it ) { 00143 TQString testUrl; 00144 if ( (*it).givenName().isEmpty() && (*it).familyName().isEmpty() ) 00145 testUrl = baseUrl.url() + "/" + (*it).organization(); 00146 else 00147 testUrl = baseUrl.url() + "/" + (*it).givenName() + "_" + (*it).familyName(); 00148 00149 if ( KIO::NetAccess::exists( testUrl + (counter == 0 ? "" : TQString::number( counter )) + ".vcf", false, parentWidget() ) ) { 00150 counter++; 00151 url = testUrl + TQString::number( counter ) + ".vcf"; 00152 } else 00153 url = testUrl + ".vcf"; 00154 00155 bool tmpOk; 00156 KABC::AddresseeList tmpList; 00157 tmpList.append( *it ); 00158 00159 if ( data == "v21" ) 00160 #if defined(KABC_VCARD_ENCODING_FIX) 00161 tmpOk = doExport( url, converter.createVCardsRaw( tmpList, KABC::VCardConverter::v2_1 ) ); 00162 else 00163 tmpOk = doExport( url, converter.createVCardsRaw( tmpList, KABC::VCardConverter::v3_0 ) ); 00164 #else 00165 tmpOk = doExport( url, converter.createVCards( tmpList, KABC::VCardConverter::v2_1 ) ); 00166 else 00167 tmpOk = doExport( url, converter.createVCards( tmpList, KABC::VCardConverter::v3_0 ) ); 00168 #endif 00169 ok = ok && tmpOk; 00170 } 00171 break; 00172 } 00173 case KMessageBox::No: 00174 default: { 00175 url = KFileDialog::getSaveURL( "addressbook.vcf" ); 00176 if ( url.isEmpty() ) 00177 return true; 00178 00179 if ( data == "v21" ) 00180 #if defined(KABC_VCARD_ENCODING_FIX) 00181 ok = doExport( url, converter.createVCardsRaw( list, KABC::VCardConverter::v2_1 ) ); 00182 else 00183 ok = doExport( url, converter.createVCardsRaw( list, KABC::VCardConverter::v3_0 ) ); 00184 #else 00185 ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v2_1 ) ); 00186 else 00187 ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v3_0 ) ); 00188 #endif 00189 } 00190 } 00191 } 00192 00193 return ok; 00194 } 00195 00196 KABC::AddresseeList VCardXXPort::importContacts( const TQString& ) const 00197 { 00198 TQString fileName; 00199 KABC::AddresseeList addrList; 00200 KURL::List urls; 00201 00202 if ( !XXPortManager::importData.isEmpty() ) { 00203 #if defined(KABC_VCARD_ENCODING_FIX) 00204 TQCString data = XXPortManager::importData.ascii(); 00205 addrList = parseVCard( data ); 00206 #else 00207 addrList = parseVCard( XXPortManager::importData ); 00208 #endif 00209 } else { 00210 if ( XXPortManager::importURL.isEmpty() ) 00211 urls = KFileDialog::getOpenURLs( TQString(), "*.vcf|vCards", parentWidget(), 00212 i18n( "Select vCard to Import" ) ); 00213 else 00214 urls.append( XXPortManager::importURL ); 00215 00216 if ( urls.count() == 0 ) 00217 return addrList; 00218 00219 TQString caption( i18n( "vCard Import Failed" ) ); 00220 bool anyFailures = false; 00221 KURL::List::Iterator it; 00222 for ( it = urls.begin(); it != urls.end(); ++it ) { 00223 if ( KIO::NetAccess::download( *it, fileName, parentWidget() ) ) { 00224 00225 TQFile file( fileName ); 00226 00227 if ( file.open( IO_ReadOnly ) ) { 00228 #if defined(KABC_VCARD_ENCODING_FIX) 00229 TQByteArray data = file.readAll(); 00230 file.close(); 00231 if ( data.size() > 0 ) 00232 addrList += parseVCard( data ); 00233 #else 00234 TQByteArray rawData = file.readAll(); 00235 file.close(); 00236 if ( rawData.size() > 0 ) { 00237 00238 TQString vCardText; 00239 00240 // With version 3.0, vCards are encoded with UTF-8 by default. Otherwise, use fromLatin1() 00241 // and hope that are fields are encoded correctly. 00242 if ( TQString::fromLatin1( rawData ).lower().contains( "version:3.0" ) ) { 00243 vCardText = TQString::fromUtf8( rawData ); 00244 } else { 00245 vCardText = TQString::fromLatin1( rawData ); 00246 } 00247 addrList += parseVCard( vCardText ); 00248 } 00249 #endif 00250 KIO::NetAccess::removeTempFile( fileName ); 00251 } else { 00252 TQString text = i18n( "<qt>When trying to read the vCard, there was an error opening the file '%1': %2</qt>" ); 00253 text = text.arg( (*it).url() ); 00254 text = text.arg( kapp->translate( "TQFile", 00255 TQString(file.errorString()).latin1() ) ); 00256 KMessageBox::error( parentWidget(), text, caption ); 00257 anyFailures = true; 00258 } 00259 } else { 00260 TQString text = i18n( "<qt>Unable to access vCard: %1</qt>" ); 00261 text = text.arg( KIO::NetAccess::lastErrorString() ); 00262 KMessageBox::error( parentWidget(), text, caption ); 00263 anyFailures = true; 00264 } 00265 } 00266 00267 if ( !XXPortManager::importURL.isEmpty() ) { // a vcard was passed via cmd 00268 if ( addrList.isEmpty() ) { 00269 if ( anyFailures && urls.count() > 1 ) 00270 KMessageBox::information( parentWidget(), 00271 i18n( "No contacts were imported, due to errors with the vCards." ) ); 00272 else if ( !anyFailures ) 00273 KMessageBox::information( parentWidget(), i18n( "The vCard does not contain any contacts." ) ); 00274 } else { 00275 VCardViewerDialog dlg( addrList, parentWidget() ); 00276 dlg.exec(); 00277 addrList = dlg.contacts(); 00278 } 00279 } 00280 } 00281 00282 return addrList; 00283 } 00284 00285 #if defined(KABC_VCARD_ENCODING_FIX) 00286 KABC::AddresseeList VCardXXPort::parseVCard( const TQByteArray &data ) const 00287 { 00288 KABC::VCardConverter converter; 00289 00290 return converter.parseVCardsRaw( data.data() ); 00291 } 00292 00293 bool VCardXXPort::doExport( const KURL &url, const TQByteArray &data ) 00294 { 00295 if( TQFileInfo(url.path()).exists() ) { 00296 if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No) 00297 return false; 00298 } 00299 KTempFile tmpFile; 00300 tmpFile.setAutoDelete( true ); 00301 00302 tmpFile.file()->writeBlock( data.data(), data.size() ); 00303 tmpFile.close(); 00304 00305 return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() ); 00306 } 00307 #else 00308 KABC::AddresseeList VCardXXPort::parseVCard( const TQString &data ) const 00309 { 00310 KABC::VCardConverter converter; 00311 00312 return converter.parseVCards( data ); 00313 } 00314 00315 bool VCardXXPort::doExport( const KURL &url, const TQString &data ) 00316 { 00317 if( TQFileInfo(url.path()).exists() ) { 00318 if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No) 00319 return false; 00320 } 00321 KTempFile tmpFile; 00322 tmpFile.setAutoDelete( true ); 00323 00324 TQTextStream stream( tmpFile.file() ); 00325 stream.setEncoding( TQTextStream::UnicodeUTF8 ); 00326 00327 stream << data; 00328 tmpFile.close(); 00329 00330 return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() ); 00331 } 00332 #endif 00333 00334 KABC::AddresseeList VCardXXPort::filterContacts( const KABC::AddresseeList &addrList ) 00335 { 00336 KABC::AddresseeList list; 00337 00338 if ( addrList.isEmpty() ) 00339 return addrList; 00340 00341 VCardExportSelectionDialog dlg( parentWidget() ); 00342 if ( !dlg.exec() ) 00343 return list; 00344 00345 KABC::AddresseeList::ConstIterator it; 00346 for ( it = addrList.begin(); it != addrList.end(); ++it ) { 00347 KABC::Addressee addr; 00348 00349 addr.setUid( (*it).uid() ); 00350 addr.setFormattedName( (*it).formattedName() ); 00351 addr.setPrefix( (*it).prefix() ); 00352 addr.setGivenName( (*it).givenName() ); 00353 addr.setAdditionalName( (*it).additionalName() ); 00354 addr.setFamilyName( (*it).familyName() ); 00355 addr.setSuffix( (*it).suffix() ); 00356 addr.setNickName( (*it).nickName() ); 00357 addr.setMailer( (*it).mailer() ); 00358 addr.setTimeZone( (*it).timeZone() ); 00359 addr.setGeo( (*it).geo() ); 00360 addr.setProductId( (*it).productId() ); 00361 addr.setSortString( (*it).sortString() ); 00362 addr.setUrl( (*it).url() ); 00363 addr.setSecrecy( (*it).secrecy() ); 00364 addr.setSound( (*it).sound() ); 00365 addr.setEmails( (*it).emails() ); 00366 addr.setCategories( (*it).categories() ); 00367 00368 if ( dlg.exportPrivateFields() ) { 00369 addr.setBirthday( (*it).birthday() ); 00370 addr.setNote( (*it).note() ); 00371 addr.setPhoto( (*it).photo() ); 00372 } 00373 00374 if ( dlg.exportBusinessFields() ) { 00375 addr.setTitle( (*it).title() ); 00376 addr.setRole( (*it).role() ); 00377 addr.setOrganization( (*it).organization() ); 00378 00379 addr.setLogo( (*it).logo() ); 00380 00381 KABC::PhoneNumber::List phones = (*it).phoneNumbers( KABC::PhoneNumber::Work ); 00382 KABC::PhoneNumber::List::Iterator phoneIt; 00383 for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) 00384 addr.insertPhoneNumber( *phoneIt ); 00385 00386 KABC::Address::List addresses = (*it).addresses( KABC::Address::Work ); 00387 KABC::Address::List::Iterator addrIt; 00388 for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) 00389 addr.insertAddress( *addrIt ); 00390 } 00391 00392 KABC::PhoneNumber::List phones = (*it).phoneNumbers(); 00393 KABC::PhoneNumber::List::Iterator phoneIt; 00394 for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) { 00395 int type = (*phoneIt).type(); 00396 00397 if ( type & KABC::PhoneNumber::Home && dlg.exportPrivateFields() ) 00398 addr.insertPhoneNumber( *phoneIt ); 00399 else if ( type & KABC::PhoneNumber::Work && dlg.exportBusinessFields() ) 00400 addr.insertPhoneNumber( *phoneIt ); 00401 else if ( dlg.exportOtherFields() ) 00402 addr.insertPhoneNumber( *phoneIt ); 00403 } 00404 00405 KABC::Address::List addresses = (*it).addresses(); 00406 KABC::Address::List::Iterator addrIt; 00407 for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) { 00408 int type = (*addrIt).type(); 00409 00410 if ( type & KABC::Address::Home && dlg.exportPrivateFields() ) 00411 addr.insertAddress( *addrIt ); 00412 else if ( type & KABC::Address::Work && dlg.exportBusinessFields() ) 00413 addr.insertAddress( *addrIt ); 00414 else if ( dlg.exportOtherFields() ) 00415 addr.insertAddress( *addrIt ); 00416 } 00417 00418 if ( dlg.exportOtherFields() ) 00419 addr.setCustoms( (*it).customs() ); 00420 00421 if ( dlg.exportEncryptionKeys() ) { 00422 addKey( addr, KABC::Key::PGP ); 00423 addKey( addr, KABC::Key::X509 ); 00424 } 00425 00426 list.append( addr ); 00427 } 00428 00429 return list; 00430 } 00431 00432 void VCardXXPort::addKey( KABC::Addressee &addr, KABC::Key::Types type ) 00433 { 00434 TQString fingerprint = addr.custom( "KADDRESSBOOK", 00435 (type == KABC::Key::PGP ? "OPENPGPFP" : "SMIMEFP") ); 00436 if ( fingerprint.isEmpty() ) 00437 return; 00438 00439 GpgME::Context * context = GpgME::Context::createForProtocol( GpgME::Context::OpenPGP ); 00440 if ( !context ) { 00441 kdError() << "No context available" << endl; 00442 return; 00443 } 00444 00445 context->setArmor( false ); 00446 context->setTextMode( false ); 00447 00448 QGpgME::TQByteArrayDataProvider dataProvider; 00449 GpgME::Data dataObj( &dataProvider ); 00450 GpgME::Error error = context->exportPublicKeys( fingerprint.latin1(), dataObj ); 00451 delete context; 00452 00453 if ( error ) { 00454 kdError() << error.asString() << endl; 00455 return; 00456 } 00457 00458 KABC::Key key; 00459 key.setType( type ); 00460 key.setBinaryData( dataProvider.data() ); 00461 00462 addr.insertKey( key ); 00463 } 00464 00465 // ---------- VCardViewer Dialog ---------------- // 00466 00467 VCardViewerDialog::VCardViewerDialog( const KABC::Addressee::List &list, 00468 TQWidget *parent, const char *name ) 00469 : KDialogBase( Plain, i18n( "Import vCard" ), Yes | No | Apply | Cancel, Yes, 00470 parent, name, true, true, KStdGuiItem::no(), KStdGuiItem::yes() ), 00471 mContacts( list ) 00472 { 00473 TQFrame *page = plainPage(); 00474 TQVBoxLayout *layout = new TQVBoxLayout( page, marginHint(), spacingHint() ); 00475 00476 TQLabel *label = new TQLabel( i18n( "Do you want to import this contact in your address book?" ), page ); 00477 TQFont font = label->font(); 00478 font.setBold( true ); 00479 label->setFont( font ); 00480 layout->addWidget( label ); 00481 00482 mView = new KPIM::AddresseeView( page ); 00483 mView->enableLinks( 0 ); 00484 mView->setVScrollBarMode( TQScrollView::Auto ); 00485 layout->addWidget( mView ); 00486 00487 setButtonText( Apply, i18n( "Import All..." ) ); 00488 00489 mIt = mContacts.begin(); 00490 00491 updateView(); 00492 } 00493 00494 KABC::Addressee::List VCardViewerDialog::contacts() const 00495 { 00496 return mContacts; 00497 } 00498 00499 void VCardViewerDialog::updateView() 00500 { 00501 mView->setAddressee( *mIt ); 00502 00503 KABC::Addressee::List::Iterator it = mIt; 00504 actionButton( Apply )->setEnabled( (++it) != mContacts.end() ); 00505 } 00506 00507 void VCardViewerDialog::slotUser1() 00508 { 00509 mIt = mContacts.remove( mIt ); 00510 00511 if ( mIt == mContacts.end() ) 00512 slotApply(); 00513 00514 updateView(); 00515 } 00516 00517 void VCardViewerDialog::slotUser2() 00518 { 00519 mIt++; 00520 00521 if ( mIt == mContacts.end() ) 00522 slotApply(); 00523 00524 updateView(); 00525 } 00526 00527 void VCardViewerDialog::slotApply() 00528 { 00529 TQDialog::accept(); 00530 } 00531 00532 void VCardViewerDialog::slotCancel() 00533 { 00534 mContacts.clear(); 00535 TQDialog::accept(); 00536 } 00537 00538 // ---------- VCardExportSelection Dialog ---------------- // 00539 00540 VCardExportSelectionDialog::VCardExportSelectionDialog( TQWidget *parent, 00541 const char *name ) 00542 : KDialogBase( Plain, i18n( "Select vCard Fields" ), Ok | Cancel, Ok, 00543 parent, name, true, true ) 00544 { 00545 TQFrame *page = plainPage(); 00546 00547 TQVBoxLayout *layout = new TQVBoxLayout( page, marginHint(), spacingHint() ); 00548 00549 TQLabel *label = new TQLabel( i18n( "Select the fields which shall be exported in the vCard." ), page ); 00550 layout->addWidget( label ); 00551 00552 mPrivateBox = new TQCheckBox( i18n( "Private fields" ), page ); 00553 layout->addWidget( mPrivateBox ); 00554 00555 mBusinessBox = new TQCheckBox( i18n( "Business fields" ), page ); 00556 layout->addWidget( mBusinessBox ); 00557 00558 mOtherBox = new TQCheckBox( i18n( "Other fields" ), page ); 00559 layout->addWidget( mOtherBox ); 00560 00561 mEncryptionKeys = new TQCheckBox( i18n( "Encryption keys" ), page ); 00562 layout->addWidget( mEncryptionKeys ); 00563 00564 KConfig config( "kaddressbookrc" ); 00565 config.setGroup( "XXPortVCard" ); 00566 00567 mPrivateBox->setChecked( config.readBoolEntry( "ExportPrivateFields", true ) ); 00568 mBusinessBox->setChecked( config.readBoolEntry( "ExportBusinessFields", false ) ); 00569 mOtherBox->setChecked( config.readBoolEntry( "ExportOtherFields", false ) ); 00570 mEncryptionKeys->setChecked( config.readBoolEntry( "ExportEncryptionKeys", false ) ); 00571 } 00572 00573 VCardExportSelectionDialog::~VCardExportSelectionDialog() 00574 { 00575 KConfig config( "kaddressbookrc" ); 00576 config.setGroup( "XXPortVCard" ); 00577 00578 config.writeEntry( "ExportPrivateFields", mPrivateBox->isChecked() ); 00579 config.writeEntry( "ExportBusinessFields", mBusinessBox->isChecked() ); 00580 config.writeEntry( "ExportOtherFields", mOtherBox->isChecked() ); 00581 config.writeEntry( "ExportEncryptionKeys", mEncryptionKeys->isChecked() ); 00582 } 00583 00584 bool VCardExportSelectionDialog::exportPrivateFields() const 00585 { 00586 return mPrivateBox->isChecked(); 00587 } 00588 00589 bool VCardExportSelectionDialog::exportBusinessFields() const 00590 { 00591 return mBusinessBox->isChecked(); 00592 } 00593 00594 bool VCardExportSelectionDialog::exportOtherFields() const 00595 { 00596 return mOtherBox->isChecked(); 00597 } 00598 00599 bool VCardExportSelectionDialog::exportEncryptionKeys() const 00600 { 00601 return mEncryptionKeys->isChecked(); 00602 } 00603 00604 #include "vcard_xxport.moc"