/* This file is part of KAddressbook. Copyright (c) 2003 Tobias Koenig This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" // ?? #include "gpgmepp/context.h" #include "gpgmepp/data.h" #include "gpgmepp/key.h" #include "qgpgme/dataprovider.h" #include "xxportmanager.h" #include "vcard_xxport.h" K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_vcard_xxport, VCardXXPort ) class VCardViewerDialog : public KDialogBase { public: VCardViewerDialog( const TDEABC::Addressee::List &list, TQWidget *parent, const char *name = 0 ); TDEABC::Addressee::List contacts() const; protected: void slotUser1(); void slotUser2(); void slotApply(); void slotCancel(); private: void updateView(); KPIM::AddresseeView *mView; TDEABC::Addressee::List mContacts; TDEABC::Addressee::List::Iterator mIt; }; class VCardExportSelectionDialog : public KDialogBase { public: VCardExportSelectionDialog( TQWidget *parent, const char *name = 0 ); ~VCardExportSelectionDialog(); bool exportPrivateFields() const; bool exportBusinessFields() const; bool exportOtherFields() const; bool exportEncryptionKeys() const; private: TQCheckBox *mPrivateBox; TQCheckBox *mBusinessBox; TQCheckBox *mOtherBox; TQCheckBox *mEncryptionKeys; }; VCardXXPort::VCardXXPort( TDEABC::AddressBook *ab, TQWidget *parent, const char *name ) : KAB::XXPort( ab, parent, name ) { createImportAction( i18n( "Import vCard..." ) ); createExportAction( i18n( "Export vCard 2.1..." ), "v21" ); createExportAction( i18n( "Export vCard 3.0..." ), "v30" ); } bool VCardXXPort::exportContacts( const TDEABC::AddresseeList &addrList, const TQString &data ) { TDEABC::VCardConverter converter; KURL url; TDEABC::AddresseeList list; list = filterContacts( addrList ); bool ok = true; if ( list.isEmpty() ) { return ok; } else if ( list.count() == 1 ) { url = KFileDialog::getSaveURL( list[ 0 ].givenName() + "_" + list[ 0 ].familyName() + ".vcf" ); if ( url.isEmpty() ) return true; if ( data == "v21" ) #if defined(KABC_VCARD_ENCODING_FIX) ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v2_1 ) ); else ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v3_0 ) ); #else ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v2_1 ) ); else ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v3_0 ) ); #endif } else { TQString msg = i18n( "You have selected a list of contacts, shall they be " "exported to several files?" ); switch ( KMessageBox::questionYesNo( parentWidget(), msg, TQString(), i18n("Export to Several Files"), i18n("Export to One File") ) ) { case KMessageBox::Yes: { KURL baseUrl = KFileDialog::getExistingURL(); if ( baseUrl.isEmpty() ) return true; TDEABC::AddresseeList::ConstIterator it; uint counter = 0; for ( it = list.begin(); it != list.end(); ++it ) { TQString testUrl; if ( (*it).givenName().isEmpty() && (*it).familyName().isEmpty() ) testUrl = baseUrl.url() + "/" + (*it).organization(); else testUrl = baseUrl.url() + "/" + (*it).givenName() + "_" + (*it).familyName(); if ( TDEIO::NetAccess::exists( testUrl + (counter == 0 ? "" : TQString::number( counter )) + ".vcf", false, parentWidget() ) ) { counter++; url = testUrl + TQString::number( counter ) + ".vcf"; } else url = testUrl + ".vcf"; bool tmpOk; TDEABC::AddresseeList tmpList; tmpList.append( *it ); if ( data == "v21" ) #if defined(KABC_VCARD_ENCODING_FIX) tmpOk = doExport( url, converter.createVCardsRaw( tmpList, TDEABC::VCardConverter::v2_1 ) ); else tmpOk = doExport( url, converter.createVCardsRaw( tmpList, TDEABC::VCardConverter::v3_0 ) ); #else tmpOk = doExport( url, converter.createVCards( tmpList, TDEABC::VCardConverter::v2_1 ) ); else tmpOk = doExport( url, converter.createVCards( tmpList, TDEABC::VCardConverter::v3_0 ) ); #endif ok = ok && tmpOk; } break; } case KMessageBox::No: default: { url = KFileDialog::getSaveURL( "addressbook.vcf" ); if ( url.isEmpty() ) return true; if ( data == "v21" ) #if defined(KABC_VCARD_ENCODING_FIX) ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v2_1 ) ); else ok = doExport( url, converter.createVCardsRaw( list, TDEABC::VCardConverter::v3_0 ) ); #else ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v2_1 ) ); else ok = doExport( url, converter.createVCards( list, TDEABC::VCardConverter::v3_0 ) ); #endif } } } return ok; } TDEABC::AddresseeList VCardXXPort::importContacts( const TQString& ) const { TQString fileName; TDEABC::AddresseeList addrList; KURL::List urls; if ( !XXPortManager::importData.isEmpty() ) { #if defined(KABC_VCARD_ENCODING_FIX) TQCString data = XXPortManager::importData.ascii(); addrList = parseVCard( data ); #else addrList = parseVCard( XXPortManager::importData ); #endif } else { if ( XXPortManager::importURL.isEmpty() ) urls = KFileDialog::getOpenURLs( TQString(), "*.vcf|vCards", parentWidget(), i18n( "Select vCard to Import" ) ); else urls.append( XXPortManager::importURL ); if ( urls.count() == 0 ) return addrList; TQString caption( i18n( "vCard Import Failed" ) ); bool anyFailures = false; KURL::List::Iterator it; for ( it = urls.begin(); it != urls.end(); ++it ) { if ( TDEIO::NetAccess::download( *it, fileName, parentWidget() ) ) { TQFile file( fileName ); if ( file.open( IO_ReadOnly ) ) { #if defined(KABC_VCARD_ENCODING_FIX) TQByteArray data = file.readAll(); file.close(); if ( data.size() > 0 ) addrList += parseVCard( data ); #else TQByteArray rawData = file.readAll(); file.close(); if ( rawData.size() > 0 ) { TQString vCardText; // With version 3.0, vCards are encoded with UTF-8 by default. Otherwise, use fromLatin1() // and hope that are fields are encoded correctly. if ( TQString::fromLatin1( rawData ).lower().contains( "version:3.0" ) ) { vCardText = TQString::fromUtf8( rawData ); } else { vCardText = TQString::fromLatin1( rawData ); } addrList += parseVCard( vCardText ); } #endif TDEIO::NetAccess::removeTempFile( fileName ); } else { TQString text = i18n( "When trying to read the vCard, there was an error opening the file '%1': %2" ); text = text.arg( (*it).url() ); text = text.arg( kapp->translate( "TQFile", TQString(file.errorString()).latin1() ) ); KMessageBox::error( parentWidget(), text, caption ); anyFailures = true; } } else { TQString text = i18n( "Unable to access vCard: %1" ); text = text.arg( TDEIO::NetAccess::lastErrorString() ); KMessageBox::error( parentWidget(), text, caption ); anyFailures = true; } } if ( !XXPortManager::importURL.isEmpty() ) { // a vcard was passed via cmd if ( addrList.isEmpty() ) { if ( anyFailures && urls.count() > 1 ) KMessageBox::information( parentWidget(), i18n( "No contacts were imported, due to errors with the vCards." ) ); else if ( !anyFailures ) KMessageBox::information( parentWidget(), i18n( "The vCard does not contain any contacts." ) ); } else { VCardViewerDialog dlg( addrList, parentWidget() ); dlg.exec(); addrList = dlg.contacts(); } } } return addrList; } #if defined(KABC_VCARD_ENCODING_FIX) TDEABC::AddresseeList VCardXXPort::parseVCard( const TQByteArray &data ) const { TDEABC::VCardConverter converter; return converter.parseVCardsRaw( data.data() ); } bool VCardXXPort::doExport( const KURL &url, const TQByteArray &data ) { if( TQFileInfo(url.path()).exists() ) { if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No) return false; } KTempFile tmpFile; tmpFile.setAutoDelete( true ); tmpFile.file()->writeBlock( data.data(), data.size() ); tmpFile.close(); return TDEIO::NetAccess::upload( tmpFile.name(), url, parentWidget() ); } #else TDEABC::AddresseeList VCardXXPort::parseVCard( const TQString &data ) const { TDEABC::VCardConverter converter; return converter.parseVCards( data ); } bool VCardXXPort::doExport( const KURL &url, const TQString &data ) { if( TQFileInfo(url.path()).exists() ) { if(KMessageBox::questionYesNo( parentWidget(), i18n("Do you want to overwrite file \"%1\"").arg( url.path()) ) == KMessageBox::No) return false; } KTempFile tmpFile; tmpFile.setAutoDelete( true ); TQTextStream stream( tmpFile.file() ); stream.setEncoding( TQTextStream::UnicodeUTF8 ); stream << data; tmpFile.close(); return TDEIO::NetAccess::upload( tmpFile.name(), url, parentWidget() ); } #endif TDEABC::AddresseeList VCardXXPort::filterContacts( const TDEABC::AddresseeList &addrList ) { TDEABC::AddresseeList list; if ( addrList.isEmpty() ) return addrList; VCardExportSelectionDialog dlg( parentWidget() ); if ( !dlg.exec() ) return list; TDEABC::AddresseeList::ConstIterator it; for ( it = addrList.begin(); it != addrList.end(); ++it ) { TDEABC::Addressee addr; addr.setUid( (*it).uid() ); addr.setFormattedName( (*it).formattedName() ); addr.setPrefix( (*it).prefix() ); addr.setGivenName( (*it).givenName() ); addr.setAdditionalName( (*it).additionalName() ); addr.setFamilyName( (*it).familyName() ); addr.setSuffix( (*it).suffix() ); addr.setNickName( (*it).nickName() ); addr.setMailer( (*it).mailer() ); addr.setTimeZone( (*it).timeZone() ); addr.setGeo( (*it).geo() ); addr.setProductId( (*it).productId() ); addr.setSortString( (*it).sortString() ); addr.setUrl( (*it).url() ); addr.setSecrecy( (*it).secrecy() ); addr.setSound( (*it).sound() ); addr.setEmails( (*it).emails() ); addr.setCategories( (*it).categories() ); if ( dlg.exportPrivateFields() ) { addr.setBirthday( (*it).birthday() ); addr.setNote( (*it).note() ); addr.setPhoto( (*it).photo() ); } if ( dlg.exportBusinessFields() ) { addr.setTitle( (*it).title() ); addr.setRole( (*it).role() ); addr.setOrganization( (*it).organization() ); addr.setLogo( (*it).logo() ); TDEABC::PhoneNumber::List phones = (*it).phoneNumbers( TDEABC::PhoneNumber::Work ); TDEABC::PhoneNumber::List::Iterator phoneIt; for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) addr.insertPhoneNumber( *phoneIt ); TDEABC::Address::List addresses = (*it).addresses( TDEABC::Address::Work ); TDEABC::Address::List::Iterator addrIt; for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) addr.insertAddress( *addrIt ); } TDEABC::PhoneNumber::List phones = (*it).phoneNumbers(); TDEABC::PhoneNumber::List::Iterator phoneIt; for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) { int type = (*phoneIt).type(); if ( type & TDEABC::PhoneNumber::Home && dlg.exportPrivateFields() ) addr.insertPhoneNumber( *phoneIt ); else if ( type & TDEABC::PhoneNumber::Work && dlg.exportBusinessFields() ) addr.insertPhoneNumber( *phoneIt ); else if ( dlg.exportOtherFields() ) addr.insertPhoneNumber( *phoneIt ); } TDEABC::Address::List addresses = (*it).addresses(); TDEABC::Address::List::Iterator addrIt; for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) { int type = (*addrIt).type(); if ( type & TDEABC::Address::Home && dlg.exportPrivateFields() ) addr.insertAddress( *addrIt ); else if ( type & TDEABC::Address::Work && dlg.exportBusinessFields() ) addr.insertAddress( *addrIt ); else if ( dlg.exportOtherFields() ) addr.insertAddress( *addrIt ); } if ( dlg.exportOtherFields() ) addr.setCustoms( (*it).customs() ); if ( dlg.exportEncryptionKeys() ) { addKey( addr, TDEABC::Key::PGP ); addKey( addr, TDEABC::Key::X509 ); } list.append( addr ); } return list; } void VCardXXPort::addKey( TDEABC::Addressee &addr, TDEABC::Key::Types type ) { TQString fingerprint = addr.custom( "KADDRESSBOOK", (type == TDEABC::Key::PGP ? "OPENPGPFP" : "SMIMEFP") ); if ( fingerprint.isEmpty() ) return; GpgME::Context * context = GpgME::Context::createForProtocol( GpgME::Context::OpenPGP ); if ( !context ) { kdError() << "No context available" << endl; return; } context->setArmor( false ); context->setTextMode( false ); QGpgME::TQByteArrayDataProvider dataProvider; GpgME::Data dataObj( &dataProvider ); GpgME::Error error = context->exportPublicKeys( fingerprint.latin1(), dataObj ); delete context; if ( error ) { kdError() << error.asString() << endl; return; } TDEABC::Key key; key.setType( type ); key.setBinaryData( dataProvider.data() ); addr.insertKey( key ); } // ---------- VCardViewer Dialog ---------------- // VCardViewerDialog::VCardViewerDialog( const TDEABC::Addressee::List &list, TQWidget *parent, const char *name ) : KDialogBase( Plain, i18n( "Import vCard" ), Yes | No | Apply | Cancel, Yes, parent, name, true, true, KStdGuiItem::no(), KStdGuiItem::yes() ), mContacts( list ) { TQFrame *page = plainPage(); TQVBoxLayout *layout = new TQVBoxLayout( page, marginHint(), spacingHint() ); TQLabel *label = new TQLabel( i18n( "Do you want to import this contact in your address book?" ), page ); TQFont font = label->font(); font.setBold( true ); label->setFont( font ); layout->addWidget( label ); mView = new KPIM::AddresseeView( page ); mView->enableLinks( 0 ); mView->setVScrollBarMode( TQScrollView::Auto ); layout->addWidget( mView ); setButtonText( Apply, i18n( "Import All..." ) ); mIt = mContacts.begin(); updateView(); } TDEABC::Addressee::List VCardViewerDialog::contacts() const { return mContacts; } void VCardViewerDialog::updateView() { mView->setAddressee( *mIt ); TDEABC::Addressee::List::Iterator it = mIt; actionButton( Apply )->setEnabled( (++it) != mContacts.end() ); } void VCardViewerDialog::slotUser1() { mIt = mContacts.remove( mIt ); if ( mIt == mContacts.end() ) slotApply(); updateView(); } void VCardViewerDialog::slotUser2() { mIt++; if ( mIt == mContacts.end() ) slotApply(); updateView(); } void VCardViewerDialog::slotApply() { TQDialog::accept(); } void VCardViewerDialog::slotCancel() { mContacts.clear(); TQDialog::accept(); } // ---------- VCardExportSelection Dialog ---------------- // VCardExportSelectionDialog::VCardExportSelectionDialog( TQWidget *parent, const char *name ) : KDialogBase( Plain, i18n( "Select vCard Fields" ), Ok | Cancel, Ok, parent, name, true, true ) { TQFrame *page = plainPage(); TQVBoxLayout *layout = new TQVBoxLayout( page, marginHint(), spacingHint() ); TQLabel *label = new TQLabel( i18n( "Select the fields which shall be exported in the vCard." ), page ); layout->addWidget( label ); mPrivateBox = new TQCheckBox( i18n( "Private fields" ), page ); layout->addWidget( mPrivateBox ); mBusinessBox = new TQCheckBox( i18n( "Business fields" ), page ); layout->addWidget( mBusinessBox ); mOtherBox = new TQCheckBox( i18n( "Other fields" ), page ); layout->addWidget( mOtherBox ); mEncryptionKeys = new TQCheckBox( i18n( "Encryption keys" ), page ); layout->addWidget( mEncryptionKeys ); TDEConfig config( "kaddressbookrc" ); config.setGroup( "XXPortVCard" ); mPrivateBox->setChecked( config.readBoolEntry( "ExportPrivateFields", true ) ); mBusinessBox->setChecked( config.readBoolEntry( "ExportBusinessFields", false ) ); mOtherBox->setChecked( config.readBoolEntry( "ExportOtherFields", false ) ); mEncryptionKeys->setChecked( config.readBoolEntry( "ExportEncryptionKeys", false ) ); } VCardExportSelectionDialog::~VCardExportSelectionDialog() { TDEConfig config( "kaddressbookrc" ); config.setGroup( "XXPortVCard" ); config.writeEntry( "ExportPrivateFields", mPrivateBox->isChecked() ); config.writeEntry( "ExportBusinessFields", mBusinessBox->isChecked() ); config.writeEntry( "ExportOtherFields", mOtherBox->isChecked() ); config.writeEntry( "ExportEncryptionKeys", mEncryptionKeys->isChecked() ); } bool VCardExportSelectionDialog::exportPrivateFields() const { return mPrivateBox->isChecked(); } bool VCardExportSelectionDialog::exportBusinessFields() const { return mBusinessBox->isChecked(); } bool VCardExportSelectionDialog::exportOtherFields() const { return mOtherBox->isChecked(); } bool VCardExportSelectionDialog::exportEncryptionKeys() const { return mEncryptionKeys->isChecked(); } #include "vcard_xxport.moc"