kaddressbook

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 Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 #include <qcheckbox.h>
00025 #include <qfile.h>
00026 #include <qfont.h>
00027 #include <qlabel.h>
00028 #include <qlayout.h>
00029 #include <qpushbutton.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                        QWidget *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( QWidget *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     QCheckBox *mPrivateBox;
00091     QCheckBox *mBusinessBox;
00092     QCheckBox *mOtherBox;
00093     QCheckBox *mEncryptionKeys;
00094 };
00095 
00096 VCardXXPort::VCardXXPort( KABC::AddressBook *ab, QWidget *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 QString &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       ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v2_1 ) );
00122     else
00123       ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v3_0 ) );
00124   } else {
00125     QString msg = i18n( "You have selected a list of contacts, shall they be "
00126                         "exported to several files?" );
00127 
00128     switch ( KMessageBox::questionYesNo( parentWidget(), msg, QString::null, i18n("Export to Several Files"), i18n("Export to One File") ) ) {
00129       case KMessageBox::Yes: {
00130         KURL baseUrl = KFileDialog::getExistingURL();
00131         if ( baseUrl.isEmpty() )
00132           return true;
00133 
00134         KABC::AddresseeList::ConstIterator it;
00135         uint counter = 0;
00136         for ( it = list.begin(); it != list.end(); ++it ) {
00137           QString testUrl;
00138           if ( (*it).givenName().isEmpty() && (*it).familyName().isEmpty() )
00139             testUrl = baseUrl.url() + "/" + (*it).organization();
00140           else
00141             testUrl = baseUrl.url() + "/" + (*it).givenName() + "_" + (*it).familyName();
00142 
00143           if ( KIO::NetAccess::exists( testUrl + (counter == 0 ? "" : QString::number( counter )) + ".vcf", false, parentWidget() ) ) {
00144             counter++;
00145             url = testUrl + QString::number( counter ) + ".vcf";
00146           } else
00147             url = testUrl + ".vcf";
00148 
00149           bool tmpOk;
00150           KABC::AddresseeList tmpList;
00151           tmpList.append( *it );
00152 
00153           if ( data == "v21" )
00154             tmpOk = doExport( url, converter.createVCards( tmpList, KABC::VCardConverter::v2_1 ) );
00155           else
00156             tmpOk = doExport( url, converter.createVCards( tmpList, KABC::VCardConverter::v3_0 ) );
00157 
00158           ok = ok && tmpOk;
00159         }
00160         break;
00161       }
00162       case KMessageBox::No:
00163       default: {
00164         url = KFileDialog::getSaveURL( "addressbook.vcf" );
00165         if ( url.isEmpty() )
00166           return true;
00167 
00168         if ( data == "v21" )
00169           ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v2_1 ) );
00170         else
00171           ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v3_0 ) );
00172       }
00173     }
00174   }
00175 
00176   return ok;
00177 }
00178 
00179 KABC::AddresseeList VCardXXPort::importContacts( const QString& ) const
00180 {
00181   QString fileName;
00182   KABC::AddresseeList addrList;
00183   KURL::List urls;
00184 
00185   if ( !XXPortManager::importData.isEmpty() )
00186     addrList = parseVCard( XXPortManager::importData );
00187   else {
00188     if ( XXPortManager::importURL.isEmpty() )
00189       urls = KFileDialog::getOpenURLs( QString::null, "*.vcf|vCards", parentWidget(),
00190                                        i18n( "Select vCard to Import" ) );
00191     else
00192       urls.append( XXPortManager::importURL );
00193 
00194     if ( urls.count() == 0 )
00195       return addrList;
00196 
00197     QString caption( i18n( "vCard Import Failed" ) );
00198     bool anyFailures = false;
00199     KURL::List::Iterator it;
00200     for ( it = urls.begin(); it != urls.end(); ++it ) {
00201       if ( KIO::NetAccess::download( *it, fileName, parentWidget() ) ) {
00202 
00203         QFile file( fileName );
00204 
00205         if ( file.open( IO_ReadOnly ) ) {
00206           QByteArray rawData = file.readAll();
00207           file.close();
00208           if ( rawData.size() > 0 )
00209             addrList += parseVCard( rawData );
00210 
00211           KIO::NetAccess::removeTempFile( fileName );
00212         } else {
00213           QString text = i18n( "<qt>When trying to read the vCard, there was an error opening the file '%1': %2</qt>" );
00214           text = text.arg( (*it).url() );
00215           text = text.arg( kapp->translate( "QFile",
00216                                             file.errorString().latin1() ) );
00217           KMessageBox::error( parentWidget(), text, caption );
00218           anyFailures = true;
00219         }
00220       } else {
00221         QString text = i18n( "<qt>Unable to access vCard: %1</qt>" );
00222         text = text.arg( KIO::NetAccess::lastErrorString() );
00223         KMessageBox::error( parentWidget(), text, caption );
00224         anyFailures = true;
00225       }
00226     }
00227 
00228     if ( !XXPortManager::importURL.isEmpty() ) { // a vcard was passed via cmd
00229       if ( addrList.isEmpty() ) {
00230         if ( anyFailures && urls.count() > 1 )
00231           KMessageBox::information( parentWidget(),
00232                                     i18n( "No contacts were imported, due to errors with the vCards." ) );
00233         else if ( !anyFailures )
00234           KMessageBox::information( parentWidget(), i18n( "The vCard does not contain any contacts." ) );
00235       } else {
00236         VCardViewerDialog dlg( addrList, parentWidget() );
00237         dlg.exec();
00238         addrList = dlg.contacts();
00239       }
00240     }
00241   }
00242 
00243   return addrList;
00244 }
00245 
00246 KABC::AddresseeList VCardXXPort::parseVCard( const QString &data ) const
00247 {
00248   KABC::VCardConverter converter;
00249 
00250   return converter.parseVCards( data );
00251 }
00252 
00253 bool VCardXXPort::doExport( const KURL &url, const QString &data )
00254 {
00255   if( QFileInfo(url.path()).exists() ) {
00256       if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No)
00257         return false;
00258   } 
00259   KTempFile tmpFile;
00260   tmpFile.setAutoDelete( true );
00261 
00262   QTextStream stream( tmpFile.file() );
00263   stream.setEncoding( QTextStream::UnicodeUTF8 );
00264 
00265   stream << data;
00266   tmpFile.close();
00267 
00268   return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
00269 }
00270 
00271 KABC::AddresseeList VCardXXPort::filterContacts( const KABC::AddresseeList &addrList )
00272 {
00273   KABC::AddresseeList list;
00274 
00275   if ( addrList.isEmpty() )
00276     return addrList;
00277 
00278   VCardExportSelectionDialog dlg( parentWidget() );
00279   if ( !dlg.exec() )
00280     return list;
00281 
00282   KABC::AddresseeList::ConstIterator it;
00283   for ( it = addrList.begin(); it != addrList.end(); ++it ) {
00284     KABC::Addressee addr;
00285 
00286     addr.setUid( (*it).uid() );
00287     addr.setFormattedName( (*it).formattedName() );
00288     addr.setPrefix( (*it).prefix() );
00289     addr.setGivenName( (*it).givenName() );
00290     addr.setAdditionalName( (*it).additionalName() );
00291     addr.setFamilyName( (*it).familyName() );
00292     addr.setSuffix( (*it).suffix() );
00293     addr.setNickName( (*it).nickName() );
00294     addr.setMailer( (*it).mailer() );
00295     addr.setTimeZone( (*it).timeZone() );
00296     addr.setGeo( (*it).geo() );
00297     addr.setProductId( (*it).productId() );
00298     addr.setSortString( (*it).sortString() );
00299     addr.setUrl( (*it).url() );
00300     addr.setSecrecy( (*it).secrecy() );
00301     addr.setSound( (*it).sound() );
00302     addr.setEmails( (*it).emails() );
00303     addr.setCategories( (*it).categories() );
00304 
00305     if ( dlg.exportPrivateFields() ) {
00306       addr.setBirthday( (*it).birthday() );
00307       addr.setNote( (*it).note() );
00308       addr.setPhoto( (*it).photo() );
00309     }
00310 
00311     if ( dlg.exportBusinessFields() ) {
00312       addr.setTitle( (*it).title() );
00313       addr.setRole( (*it).role() );
00314       addr.setOrganization( (*it).organization() );
00315 
00316       addr.setLogo( (*it).logo() );
00317 
00318       KABC::PhoneNumber::List phones = (*it).phoneNumbers( KABC::PhoneNumber::Work );
00319       KABC::PhoneNumber::List::Iterator phoneIt;
00320       for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt )
00321         addr.insertPhoneNumber( *phoneIt );
00322 
00323       KABC::Address::List addresses = (*it).addresses( KABC::Address::Work );
00324       KABC::Address::List::Iterator addrIt;
00325       for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt )
00326         addr.insertAddress( *addrIt );
00327     }
00328 
00329     KABC::PhoneNumber::List phones = (*it).phoneNumbers();
00330     KABC::PhoneNumber::List::Iterator phoneIt;
00331     for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) {
00332       int type = (*phoneIt).type();
00333 
00334       if ( type & KABC::PhoneNumber::Home && dlg.exportPrivateFields() )
00335         addr.insertPhoneNumber( *phoneIt );
00336       else if ( type & KABC::PhoneNumber::Work && dlg.exportBusinessFields() )
00337         addr.insertPhoneNumber( *phoneIt );
00338       else if ( dlg.exportOtherFields() )
00339         addr.insertPhoneNumber( *phoneIt );
00340     }
00341 
00342     KABC::Address::List addresses = (*it).addresses();
00343     KABC::Address::List::Iterator addrIt;
00344     for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) {
00345       int type = (*addrIt).type();
00346 
00347       if ( type & KABC::Address::Home && dlg.exportPrivateFields() )
00348         addr.insertAddress( *addrIt );
00349       else if ( type & KABC::Address::Work && dlg.exportBusinessFields() )
00350         addr.insertAddress( *addrIt );
00351       else if ( dlg.exportOtherFields() )
00352         addr.insertAddress( *addrIt );
00353     }
00354 
00355     if ( dlg.exportOtherFields() )
00356       addr.setCustoms( (*it).customs() );
00357 
00358     if ( dlg.exportEncryptionKeys() ) {
00359       addKey( addr, KABC::Key::PGP );
00360       addKey( addr, KABC::Key::X509 );
00361     }
00362 
00363     list.append( addr );
00364   }
00365 
00366   return list;
00367 }
00368 
00369 void VCardXXPort::addKey( KABC::Addressee &addr, KABC::Key::Types type )
00370 {
00371   QString fingerprint = addr.custom( "KADDRESSBOOK",
00372                                      (type == KABC::Key::PGP ? "OPENPGPFP" : "SMIMEFP") );
00373   if ( fingerprint.isEmpty() )
00374     return;
00375 
00376   GpgME::Context * context = GpgME::Context::createForProtocol( GpgME::Context::OpenPGP );
00377   if ( !context ) {
00378     kdError() << "No context available" << endl;
00379     return;
00380   }
00381 
00382   context->setArmor( false );
00383   context->setTextMode( false );
00384 
00385   QGpgME::QByteArrayDataProvider dataProvider;
00386   GpgME::Data dataObj( &dataProvider );
00387   GpgME::Error error = context->exportPublicKeys( fingerprint.latin1(), dataObj );
00388   delete context;
00389 
00390   if ( error ) {
00391     kdError() << error.asString() << endl;
00392     return;
00393   }
00394 
00395   KABC::Key key;
00396   key.setType( type );
00397   key.setBinaryData( dataProvider.data() );
00398 
00399   addr.insertKey( key );
00400 }
00401 
00402 // ---------- VCardViewer Dialog ---------------- //
00403 
00404 VCardViewerDialog::VCardViewerDialog( const KABC::Addressee::List &list,
00405                                       QWidget *parent, const char *name )
00406   : KDialogBase( Plain, i18n( "Import vCard" ), Yes | No | Apply | Cancel, Yes,
00407                  parent, name, true, true, KStdGuiItem::no(), KStdGuiItem::yes() ),
00408     mContacts( list )
00409 {
00410   QFrame *page = plainPage();
00411   QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
00412 
00413   QLabel *label = new QLabel( i18n( "Do you want to import this contact in your address book?" ), page );
00414   QFont font = label->font();
00415   font.setBold( true );
00416   label->setFont( font );
00417   layout->addWidget( label );
00418 
00419   mView = new KPIM::AddresseeView( page );
00420   mView->enableLinks( 0 );
00421   mView->setVScrollBarMode( QScrollView::Auto );
00422   layout->addWidget( mView );
00423 
00424   setButtonText( Apply, i18n( "Import All..." ) );
00425 
00426   mIt = mContacts.begin();
00427 
00428   updateView();
00429 }
00430 
00431 KABC::Addressee::List VCardViewerDialog::contacts() const
00432 {
00433   return mContacts;
00434 }
00435 
00436 void VCardViewerDialog::updateView()
00437 {
00438   mView->setAddressee( *mIt );
00439 
00440   KABC::Addressee::List::Iterator it = mIt;
00441   actionButton( Apply )->setEnabled( (++it) != mContacts.end() );
00442 }
00443 
00444 void VCardViewerDialog::slotUser1()
00445 {
00446   mIt = mContacts.remove( mIt );
00447 
00448   if ( mIt == mContacts.end() )
00449     slotApply();
00450 
00451   updateView();
00452 }
00453 
00454 void VCardViewerDialog::slotUser2()
00455 {
00456   mIt++;
00457 
00458   if ( mIt == mContacts.end() )
00459     slotApply();
00460 
00461   updateView();
00462 }
00463 
00464 void VCardViewerDialog::slotApply()
00465 {
00466   QDialog::accept();
00467 }
00468 
00469 void VCardViewerDialog::slotCancel()
00470 {
00471   mContacts.clear();
00472   QDialog::accept();
00473 }
00474 
00475 // ---------- VCardExportSelection Dialog ---------------- //
00476 
00477 VCardExportSelectionDialog::VCardExportSelectionDialog( QWidget *parent,
00478                                                         const char *name )
00479   : KDialogBase( Plain, i18n( "Select vCard Fields" ), Ok | Cancel, Ok,
00480                  parent, name, true, true )
00481 {
00482   QFrame *page = plainPage();
00483 
00484   QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
00485 
00486   QLabel *label = new QLabel( i18n( "Select the fields which shall be exported in the vCard." ), page );
00487   layout->addWidget( label );
00488 
00489   mPrivateBox = new QCheckBox( i18n( "Private fields" ), page );
00490   layout->addWidget( mPrivateBox );
00491 
00492   mBusinessBox = new QCheckBox( i18n( "Business fields" ), page );
00493   layout->addWidget( mBusinessBox );
00494 
00495   mOtherBox = new QCheckBox( i18n( "Other fields" ), page );
00496   layout->addWidget( mOtherBox );
00497 
00498   mEncryptionKeys = new QCheckBox( i18n( "Encryption keys" ), page );
00499   layout->addWidget( mEncryptionKeys );
00500 
00501   KConfig config( "kaddressbookrc" );
00502   config.setGroup( "XXPortVCard" );
00503 
00504   mPrivateBox->setChecked( config.readBoolEntry( "ExportPrivateFields", true ) );
00505   mBusinessBox->setChecked( config.readBoolEntry( "ExportBusinessFields", false ) );
00506   mOtherBox->setChecked( config.readBoolEntry( "ExportOtherFields", false ) );
00507   mEncryptionKeys->setChecked( config.readBoolEntry( "ExportEncryptionKeys", false ) );
00508 }
00509 
00510 VCardExportSelectionDialog::~VCardExportSelectionDialog()
00511 {
00512   KConfig config( "kaddressbookrc" );
00513   config.setGroup( "XXPortVCard" );
00514 
00515   config.writeEntry( "ExportPrivateFields", mPrivateBox->isChecked() );
00516   config.writeEntry( "ExportBusinessFields", mBusinessBox->isChecked() );
00517   config.writeEntry( "ExportOtherFields", mOtherBox->isChecked() );
00518   config.writeEntry( "ExportEncryptionKeys", mEncryptionKeys->isChecked() );
00519 }
00520 
00521 bool VCardExportSelectionDialog::exportPrivateFields() const
00522 {
00523   return mPrivateBox->isChecked();
00524 }
00525 
00526 bool VCardExportSelectionDialog::exportBusinessFields() const
00527 {
00528   return mBusinessBox->isChecked();
00529 }
00530 
00531 bool VCardExportSelectionDialog::exportOtherFields() const
00532 {
00533   return mOtherBox->isChecked();
00534 }
00535 
00536 bool VCardExportSelectionDialog::exportEncryptionKeys() const
00537 {
00538   return mEncryptionKeys->isChecked();
00539 }
00540 
00541 #include "vcard_xxport.moc"