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 
00210             QString vCardText;
00211 
00212             // With version 3.0, vCards are encoded with UTF-8 by default. Otherwise, use fromLatin1()
00213             // and hope that are fields are encoded correctly.
00214             if ( QString::fromLatin1( rawData ).lower().contains( "version:3.0" ) ) {
00215               vCardText = QString::fromUtf8( rawData );
00216             } else {
00217               vCardText = QString::fromLatin1( rawData );
00218             }
00219             addrList += parseVCard( vCardText );
00220           }
00221 
00222           KIO::NetAccess::removeTempFile( fileName );
00223         } else {
00224           QString text = i18n( "<qt>When trying to read the vCard, there was an error opening the file '%1': %2</qt>" );
00225           text = text.arg( (*it).url() );
00226           text = text.arg( kapp->translate( "QFile",
00227                                             file.errorString().latin1() ) );
00228           KMessageBox::error( parentWidget(), text, caption );
00229           anyFailures = true;
00230         }
00231       } else {
00232         QString text = i18n( "<qt>Unable to access vCard: %1</qt>" );
00233         text = text.arg( KIO::NetAccess::lastErrorString() );
00234         KMessageBox::error( parentWidget(), text, caption );
00235         anyFailures = true;
00236       }
00237     }
00238 
00239     if ( !XXPortManager::importURL.isEmpty() ) { // a vcard was passed via cmd
00240       if ( addrList.isEmpty() ) {
00241         if ( anyFailures && urls.count() > 1 )
00242           KMessageBox::information( parentWidget(),
00243                                     i18n( "No contacts were imported, due to errors with the vCards." ) );
00244         else if ( !anyFailures )
00245           KMessageBox::information( parentWidget(), i18n( "The vCard does not contain any contacts." ) );
00246       } else {
00247         VCardViewerDialog dlg( addrList, parentWidget() );
00248         dlg.exec();
00249         addrList = dlg.contacts();
00250       }
00251     }
00252   }
00253 
00254   return addrList;
00255 }
00256 
00257 KABC::AddresseeList VCardXXPort::parseVCard( const QString &data ) const
00258 {
00259   KABC::VCardConverter converter;
00260 
00261   return converter.parseVCards( data );
00262 }
00263 
00264 bool VCardXXPort::doExport( const KURL &url, const QString &data )
00265 {
00266   if( QFileInfo(url.path()).exists() ) {
00267       if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No)
00268         return false;
00269   } 
00270   KTempFile tmpFile;
00271   tmpFile.setAutoDelete( true );
00272 
00273   QTextStream stream( tmpFile.file() );
00274   stream.setEncoding( QTextStream::UnicodeUTF8 );
00275 
00276   stream << data;
00277   tmpFile.close();
00278 
00279   return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
00280 }
00281 
00282 KABC::AddresseeList VCardXXPort::filterContacts( const KABC::AddresseeList &addrList )
00283 {
00284   KABC::AddresseeList list;
00285 
00286   if ( addrList.isEmpty() )
00287     return addrList;
00288 
00289   VCardExportSelectionDialog dlg( parentWidget() );
00290   if ( !dlg.exec() )
00291     return list;
00292 
00293   KABC::AddresseeList::ConstIterator it;
00294   for ( it = addrList.begin(); it != addrList.end(); ++it ) {
00295     KABC::Addressee addr;
00296 
00297     addr.setUid( (*it).uid() );
00298     addr.setFormattedName( (*it).formattedName() );
00299     addr.setPrefix( (*it).prefix() );
00300     addr.setGivenName( (*it).givenName() );
00301     addr.setAdditionalName( (*it).additionalName() );
00302     addr.setFamilyName( (*it).familyName() );
00303     addr.setSuffix( (*it).suffix() );
00304     addr.setNickName( (*it).nickName() );
00305     addr.setMailer( (*it).mailer() );
00306     addr.setTimeZone( (*it).timeZone() );
00307     addr.setGeo( (*it).geo() );
00308     addr.setProductId( (*it).productId() );
00309     addr.setSortString( (*it).sortString() );
00310     addr.setUrl( (*it).url() );
00311     addr.setSecrecy( (*it).secrecy() );
00312     addr.setSound( (*it).sound() );
00313     addr.setEmails( (*it).emails() );
00314     addr.setCategories( (*it).categories() );
00315 
00316     if ( dlg.exportPrivateFields() ) {
00317       addr.setBirthday( (*it).birthday() );
00318       addr.setNote( (*it).note() );
00319       addr.setPhoto( (*it).photo() );
00320     }
00321 
00322     if ( dlg.exportBusinessFields() ) {
00323       addr.setTitle( (*it).title() );
00324       addr.setRole( (*it).role() );
00325       addr.setOrganization( (*it).organization() );
00326 
00327       addr.setLogo( (*it).logo() );
00328 
00329       KABC::PhoneNumber::List phones = (*it).phoneNumbers( KABC::PhoneNumber::Work );
00330       KABC::PhoneNumber::List::Iterator phoneIt;
00331       for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt )
00332         addr.insertPhoneNumber( *phoneIt );
00333 
00334       KABC::Address::List addresses = (*it).addresses( KABC::Address::Work );
00335       KABC::Address::List::Iterator addrIt;
00336       for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt )
00337         addr.insertAddress( *addrIt );
00338     }
00339 
00340     KABC::PhoneNumber::List phones = (*it).phoneNumbers();
00341     KABC::PhoneNumber::List::Iterator phoneIt;
00342     for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) {
00343       int type = (*phoneIt).type();
00344 
00345       if ( type & KABC::PhoneNumber::Home && dlg.exportPrivateFields() )
00346         addr.insertPhoneNumber( *phoneIt );
00347       else if ( type & KABC::PhoneNumber::Work && dlg.exportBusinessFields() )
00348         addr.insertPhoneNumber( *phoneIt );
00349       else if ( dlg.exportOtherFields() )
00350         addr.insertPhoneNumber( *phoneIt );
00351     }
00352 
00353     KABC::Address::List addresses = (*it).addresses();
00354     KABC::Address::List::Iterator addrIt;
00355     for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) {
00356       int type = (*addrIt).type();
00357 
00358       if ( type & KABC::Address::Home && dlg.exportPrivateFields() )
00359         addr.insertAddress( *addrIt );
00360       else if ( type & KABC::Address::Work && dlg.exportBusinessFields() )
00361         addr.insertAddress( *addrIt );
00362       else if ( dlg.exportOtherFields() )
00363         addr.insertAddress( *addrIt );
00364     }
00365 
00366     if ( dlg.exportOtherFields() )
00367       addr.setCustoms( (*it).customs() );
00368 
00369     if ( dlg.exportEncryptionKeys() ) {
00370       addKey( addr, KABC::Key::PGP );
00371       addKey( addr, KABC::Key::X509 );
00372     }
00373 
00374     list.append( addr );
00375   }
00376 
00377   return list;
00378 }
00379 
00380 void VCardXXPort::addKey( KABC::Addressee &addr, KABC::Key::Types type )
00381 {
00382   QString fingerprint = addr.custom( "KADDRESSBOOK",
00383                                      (type == KABC::Key::PGP ? "OPENPGPFP" : "SMIMEFP") );
00384   if ( fingerprint.isEmpty() )
00385     return;
00386 
00387   GpgME::Context * context = GpgME::Context::createForProtocol( GpgME::Context::OpenPGP );
00388   if ( !context ) {
00389     kdError() << "No context available" << endl;
00390     return;
00391   }
00392 
00393   context->setArmor( false );
00394   context->setTextMode( false );
00395 
00396   QGpgME::QByteArrayDataProvider dataProvider;
00397   GpgME::Data dataObj( &dataProvider );
00398   GpgME::Error error = context->exportPublicKeys( fingerprint.latin1(), dataObj );
00399   delete context;
00400 
00401   if ( error ) {
00402     kdError() << error.asString() << endl;
00403     return;
00404   }
00405 
00406   KABC::Key key;
00407   key.setType( type );
00408   key.setBinaryData( dataProvider.data() );
00409 
00410   addr.insertKey( key );
00411 }
00412 
00413 // ---------- VCardViewer Dialog ---------------- //
00414 
00415 VCardViewerDialog::VCardViewerDialog( const KABC::Addressee::List &list,
00416                                       QWidget *parent, const char *name )
00417   : KDialogBase( Plain, i18n( "Import vCard" ), Yes | No | Apply | Cancel, Yes,
00418                  parent, name, true, true, KStdGuiItem::no(), KStdGuiItem::yes() ),
00419     mContacts( list )
00420 {
00421   QFrame *page = plainPage();
00422   QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
00423 
00424   QLabel *label = new QLabel( i18n( "Do you want to import this contact in your address book?" ), page );
00425   QFont font = label->font();
00426   font.setBold( true );
00427   label->setFont( font );
00428   layout->addWidget( label );
00429 
00430   mView = new KPIM::AddresseeView( page );
00431   mView->enableLinks( 0 );
00432   mView->setVScrollBarMode( QScrollView::Auto );
00433   layout->addWidget( mView );
00434 
00435   setButtonText( Apply, i18n( "Import All..." ) );
00436 
00437   mIt = mContacts.begin();
00438 
00439   updateView();
00440 }
00441 
00442 KABC::Addressee::List VCardViewerDialog::contacts() const
00443 {
00444   return mContacts;
00445 }
00446 
00447 void VCardViewerDialog::updateView()
00448 {
00449   mView->setAddressee( *mIt );
00450 
00451   KABC::Addressee::List::Iterator it = mIt;
00452   actionButton( Apply )->setEnabled( (++it) != mContacts.end() );
00453 }
00454 
00455 void VCardViewerDialog::slotUser1()
00456 {
00457   mIt = mContacts.remove( mIt );
00458 
00459   if ( mIt == mContacts.end() )
00460     slotApply();
00461 
00462   updateView();
00463 }
00464 
00465 void VCardViewerDialog::slotUser2()
00466 {
00467   mIt++;
00468 
00469   if ( mIt == mContacts.end() )
00470     slotApply();
00471 
00472   updateView();
00473 }
00474 
00475 void VCardViewerDialog::slotApply()
00476 {
00477   QDialog::accept();
00478 }
00479 
00480 void VCardViewerDialog::slotCancel()
00481 {
00482   mContacts.clear();
00483   QDialog::accept();
00484 }
00485 
00486 // ---------- VCardExportSelection Dialog ---------------- //
00487 
00488 VCardExportSelectionDialog::VCardExportSelectionDialog( QWidget *parent,
00489                                                         const char *name )
00490   : KDialogBase( Plain, i18n( "Select vCard Fields" ), Ok | Cancel, Ok,
00491                  parent, name, true, true )
00492 {
00493   QFrame *page = plainPage();
00494 
00495   QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
00496 
00497   QLabel *label = new QLabel( i18n( "Select the fields which shall be exported in the vCard." ), page );
00498   layout->addWidget( label );
00499 
00500   mPrivateBox = new QCheckBox( i18n( "Private fields" ), page );
00501   layout->addWidget( mPrivateBox );
00502 
00503   mBusinessBox = new QCheckBox( i18n( "Business fields" ), page );
00504   layout->addWidget( mBusinessBox );
00505 
00506   mOtherBox = new QCheckBox( i18n( "Other fields" ), page );
00507   layout->addWidget( mOtherBox );
00508 
00509   mEncryptionKeys = new QCheckBox( i18n( "Encryption keys" ), page );
00510   layout->addWidget( mEncryptionKeys );
00511 
00512   KConfig config( "kaddressbookrc" );
00513   config.setGroup( "XXPortVCard" );
00514 
00515   mPrivateBox->setChecked( config.readBoolEntry( "ExportPrivateFields", true ) );
00516   mBusinessBox->setChecked( config.readBoolEntry( "ExportBusinessFields", false ) );
00517   mOtherBox->setChecked( config.readBoolEntry( "ExportOtherFields", false ) );
00518   mEncryptionKeys->setChecked( config.readBoolEntry( "ExportEncryptionKeys", false ) );
00519 }
00520 
00521 VCardExportSelectionDialog::~VCardExportSelectionDialog()
00522 {
00523   KConfig config( "kaddressbookrc" );
00524   config.setGroup( "XXPortVCard" );
00525 
00526   config.writeEntry( "ExportPrivateFields", mPrivateBox->isChecked() );
00527   config.writeEntry( "ExportBusinessFields", mBusinessBox->isChecked() );
00528   config.writeEntry( "ExportOtherFields", mOtherBox->isChecked() );
00529   config.writeEntry( "ExportEncryptionKeys", mEncryptionKeys->isChecked() );
00530 }
00531 
00532 bool VCardExportSelectionDialog::exportPrivateFields() const
00533 {
00534   return mPrivateBox->isChecked();
00535 }
00536 
00537 bool VCardExportSelectionDialog::exportBusinessFields() const
00538 {
00539   return mBusinessBox->isChecked();
00540 }
00541 
00542 bool VCardExportSelectionDialog::exportOtherFields() const
00543 {
00544   return mOtherBox->isChecked();
00545 }
00546 
00547 bool VCardExportSelectionDialog::exportEncryptionKeys() const
00548 {
00549   return mEncryptionKeys->isChecked();
00550 }
00551 
00552 #include "vcard_xxport.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys