diff --git a/mailtransport/addtransportdialog.cpp b/mailtransport/addtransportdialog.cpp index 69e1f50a0..ae6d98273 100644 --- a/mailtransport/addtransportdialog.cpp +++ b/mailtransport/addtransportdialog.cpp @@ -1,147 +1,144 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "addtransportdialog.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportmanager.h" #include "transporttype.h" #include "ui_addtransportdialog.h" #include #include #include using namespace MailTransport; /** @internal */ class AddTransportDialog::Private { public: Private( AddTransportDialog *qq ) : q( qq ) { } /** Returns the currently selected type in the type selection widget, or an invalid type if none is selected. */ TransportType selectedType() const; /** Enables the OK button if a type is selected. */ void typeListClicked(); // slot AddTransportDialog *const q; Ui::AddTransportDialog ui; }; TransportType AddTransportDialog::Private::selectedType() const { QList sel = ui.typeListView->selectedItems(); - if( !sel.empty() ) { + if ( !sel.empty() ) { return sel.first()->data( 0, Qt::UserRole ).value(); } return TransportType(); } void AddTransportDialog::Private::typeListClicked() { // Make sure a type is selected before allowing the user to continue. q->enableButtonOk( selectedType().isValid() ); } - - AddTransportDialog::AddTransportDialog( QWidget *parent ) - : KDialog( parent ) - , d( new Private( this ) ) + : KDialog( parent ), d( new Private( this ) ) { // Setup UI. { QWidget *widget = new QWidget( this ); d->ui.setupUi( widget ); setMainWidget( widget ); setCaption( i18n( "Create Outgoing Account" ) ); setButtons( Ok|Cancel ); enableButtonOk( false ); setButtonText( Ok, i18nc( "create and configure a mail transport", "Create and Configure" ) ); } // Populate type list. - foreach( const TransportType &type, TransportManager::self()->types() ) { + foreach ( const TransportType &type, TransportManager::self()->types() ) { QTreeWidgetItem *treeItem = new QTreeWidgetItem( d->ui.typeListView ); treeItem->setText( 0, type.name() ); treeItem->setText( 1, type.description() ); treeItem->setData( 0, Qt::UserRole, QVariant::fromValue( type ) ); // the transport type } d->ui.typeListView->resizeColumnToContents( 0 ); updateGeometry(); d->ui.typeListView->setFocus(); // Connect user input. connect( d->ui.typeListView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(typeListClicked()) ); connect( d->ui.typeListView, SIGNAL(itemSelectionChanged()), this, SLOT(typeListClicked()) ); } AddTransportDialog::~AddTransportDialog() { delete d; } void AddTransportDialog::accept() { if( !d->selectedType().isValid() ) { return; } // Create a new transport and configure it. Transport *transport = TransportManager::self()->createTransport(); transport->setTransportType( d->selectedType() ); if( d->selectedType().type() == Transport::EnumType::Akonadi ) { // Create a resource instance if Akonadi-type transport. using namespace Akonadi; AgentInstanceCreateJob *cjob = new AgentInstanceCreateJob( d->selectedType().agentType() ); if( !cjob->exec() ) { kWarning() << "Failed to create agent instance of type" << d->selectedType().agentType().identifier(); return; } transport->setHost( cjob->instance().identifier() ); } transport->setName( d->ui.name->text() ); transport->forceUniqueName(); if( TransportManager::self()->configureTransport( transport, this ) ) { // The user clicked OK and the transport settings were saved. TransportManager::self()->addTransport( transport ); if( d->ui.setDefault->isChecked() ) { TransportManager::self()->setDefaultTransport( transport->id() ); } KDialog::accept(); } } #include "addtransportdialog.moc" diff --git a/mailtransport/addtransportdialog.ui b/mailtransport/addtransportdialog.ui index 0f5761712..a5f19d5ea 100644 --- a/mailtransport/addtransportdialog.ui +++ b/mailtransport/addtransportdialog.ui @@ -1,90 +1,90 @@ AddTransportDialog 0 0 482 353 0 0 Step One: Select Transport Type 0 0 Select an account type from the list below: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true true false Type Description - Name: + Name: Make this the default outgoing account. KLineEdit QLineEdit
klineedit.h
diff --git a/mailtransport/akonadijob.cpp b/mailtransport/akonadijob.cpp index b61d49650..7e81619db 100644 --- a/mailtransport/akonadijob.cpp +++ b/mailtransport/akonadijob.cpp @@ -1,111 +1,112 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "akonadijob.h" #include "transport.h" #include #include #include #include #include using namespace Akonadi; using namespace MailTransport; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class AkonadiJobPrivate { public: Item::Id itemId; QDBusInterface *iface; }; AkonadiJob::AkonadiJob( Transport *transport, QObject *parent ) : TransportJob( transport, parent ), d( new AkonadiJobPrivate ) { d->itemId = -1; d->iface = 0; } AkonadiJob::~ AkonadiJob() { delete d; } Akonadi::Item::Id AkonadiJob::itemId() const { return d->itemId; } void AkonadiJob::setItemId( Akonadi::Item::Id id ) { d->itemId = id; } void AkonadiJob::doStart() { if( !d->itemId < 0 ) { // TODO should this check be performed here or somewhere on a higher level? setError( UserDefinedError ); setErrorText( i18n( "Asked to send invalid item with id %1.", d->itemId ) ); emitResult(); return; } - d->iface = new QDBusInterface( QLatin1String( "org.freedesktop.Akonadi.Resource." ) + transport()->host(), - QLatin1String( "/" ), QLatin1String( "org.freedesktop.Akonadi.Resource.Transport" ), - QDBusConnection::sessionBus(), this ); + d->iface = new QDBusInterface( + QLatin1String( "org.freedesktop.Akonadi.Resource." ) + transport()->host(), + QLatin1String( "/" ), QLatin1String( "org.freedesktop.Akonadi.Resource.Transport" ), + QDBusConnection::sessionBus(), this ); if( !d->iface->isValid() ) { setError( UserDefinedError ); setErrorText( i18n( "Failed to get D-Bus interface of resource %1.", transport()->host() ) ); emitResult(); return; } connect( d->iface, SIGNAL(transportResult(qlonglong,bool,QString)), this, SLOT(resourceResult(qlonglong,bool,QString)) ); // What TODO about timeouts? It is quite possible that the result D-Bus signal // will get lost, and then what? QDBusReply reply = d->iface->call( QLatin1String( "send" ), d->itemId ); if( !reply.isValid() ) { setError( UserDefinedError ); setErrorText( i18n( "Invalid D-Bus reply from resource %1.", transport()->host() ) ); emitResult(); return; } } void AkonadiJob::resourceResult( qlonglong itemId, bool success, const QString &message ) { Q_ASSERT( itemId == d->itemId ); if( !success ) { setError( UserDefinedError ); setErrorText( message ); } emitResult(); } #include "akonadijob.moc" diff --git a/mailtransport/sendmailconfigwidget.cpp b/mailtransport/sendmailconfigwidget.cpp index 739fb0e0b..229fcda44 100644 --- a/mailtransport/sendmailconfigwidget.cpp +++ b/mailtransport/sendmailconfigwidget.cpp @@ -1,73 +1,72 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sendmailconfigwidget.h" #include "transportconfigwidget_p.h" #include "ui_sendmailsettings.h" #include using namespace MailTransport; - class MailTransport::SendmailConfigWidgetPrivate : public TransportConfigWidgetPrivate { public: Ui::SendmailSettings ui; }; SendmailConfigWidget::SendmailConfigWidget( Transport *transport, QWidget *parent ) : TransportConfigWidget( *new SendmailConfigWidgetPrivate, transport, parent ) { init(); } -SendmailConfigWidget::SendmailConfigWidget( SendmailConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ) +SendmailConfigWidget::SendmailConfigWidget( SendmailConfigWidgetPrivate &dd, + Transport *transport, QWidget *parent ) : TransportConfigWidget( dd, transport, parent ) { init(); } void SendmailConfigWidget::init() { Q_D( SendmailConfigWidget ); d->ui.setupUi( this ); d->ui.kcfg_host->setMode( KFile::File|KFile::ExistingOnly|KFile::LocalOnly ); d->manager->addWidget( this ); // otherwise it doesn't find out about these widgets d->manager->updateWidgets(); if( d->ui.kcfg_host->url().isEmpty() ) { // Locate sendmail. // This is imperfect, because it shows the standard path if an empty path // is saved in the config. d->ui.kcfg_host->setText( KStandardDirs::findExe( QLatin1String( "sendmail" ) ) ); } } - #include "sendmailconfigwidget.moc" diff --git a/mailtransport/smtpconfigwidget.cpp b/mailtransport/smtpconfigwidget.cpp index 294467534..a280fcb21 100644 --- a/mailtransport/smtpconfigwidget.cpp +++ b/mailtransport/smtpconfigwidget.cpp @@ -1,326 +1,327 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "smtpconfigwidget.h" #include "transportconfigwidget_p.h" #include "transport.h" #include "transportmanager.h" #include "servertest.h" #include "mailtransport_defs.h" #include "ui_smtpsettings.h" #include #include #include namespace { // TODO: is this really necessary? class BusyCursorHelper : public QObject { public: inline BusyCursorHelper( QObject *parent ) : QObject( parent ) { qApp->setOverrideCursor( Qt::BusyCursor ); } inline ~BusyCursorHelper() { qApp->restoreOverrideCursor(); } }; } using namespace MailTransport; class MailTransport::SMTPConfigWidgetPrivate : public TransportConfigWidgetPrivate { public: Ui::SMTPSettings ui; ServerTest *serverTest; QButtonGroup *encryptionGroup; QButtonGroup *authGroup; // detected authentication capabilities QList noEncCapa, sslCapa, tlsCapa; bool serverTestFailed; void resetAuthCapabilities() { noEncCapa.clear(); noEncCapa << Transport::EnumAuthenticationType::LOGIN << Transport::EnumAuthenticationType::PLAIN << Transport::EnumAuthenticationType::CRAM_MD5 << Transport::EnumAuthenticationType::DIGEST_MD5 << Transport::EnumAuthenticationType::NTLM << Transport::EnumAuthenticationType::GSSAPI; sslCapa = tlsCapa = noEncCapa; if ( authGroup ) { updateAuthCapbilities(); } } void updateAuthCapbilities() { if ( serverTestFailed ) { return; } QList capa = noEncCapa; if ( ui.ssl->isChecked() ) { capa = sslCapa; } else if ( ui.tls->isChecked() ) { capa = tlsCapa; } for ( int i = 0; i < authGroup->buttons().count(); ++i ) { authGroup->buttons().at( i )->setEnabled( capa.contains( i ) ); } if ( capa.count() == 0 ) { ui.noAuthPossible->setVisible( true ); ui.kcfg_requiresAuthentication->setChecked( false ); ui.kcfg_requiresAuthentication->setEnabled( false ); } else { ui.noAuthPossible->setVisible( false ); ui.kcfg_requiresAuthentication->setEnabled( true ); } } }; SMTPConfigWidget::SMTPConfigWidget( Transport *transport, QWidget *parent ) : TransportConfigWidget( *new SMTPConfigWidgetPrivate, transport, parent ) { init(); } -SMTPConfigWidget::SMTPConfigWidget( SMTPConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ) +SMTPConfigWidget::SMTPConfigWidget( SMTPConfigWidgetPrivate &dd, + Transport *transport, QWidget *parent ) : TransportConfigWidget( dd, transport, parent ) { init(); } void SMTPConfigWidget::init() { Q_D( SMTPConfigWidget ); d->serverTest = 0; connect( TransportManager::self(), SIGNAL(passwordsChanged()), SLOT(passwordsLoaded()) ); d->ui.setupUi( this ); d->manager->addWidget( this ); // otherwise it doesn't find out about these widgets d->manager->updateWidgets(); d->encryptionGroup = new QButtonGroup( this ); d->encryptionGroup->addButton( d->ui.none ); d->encryptionGroup->addButton( d->ui.ssl ); d->encryptionGroup->addButton( d->ui.tls ); d->authGroup = new QButtonGroup( this ); d->authGroup->addButton( d->ui.login ); d->authGroup->addButton( d->ui.plain ); d->authGroup->addButton( d->ui.crammd5 ); d->authGroup->addButton( d->ui.digestmd5 ); d->authGroup->addButton( d->ui.gssapi ); d->authGroup->addButton( d->ui.ntlm ); d->resetAuthCapabilities(); if ( KProtocolInfo::capabilities( SMTP_PROTOCOL ).contains( QLatin1String( "SASL" ) ) == 0 ) { d->ui.ntlm->hide(); d->ui.gssapi->hide(); } connect( d->ui.checkCapabilities, SIGNAL( clicked() ), SLOT( checkSmtpCapabilities() ) ); connect( d->ui.kcfg_host, SIGNAL( textChanged(QString) ), SLOT( hostNameChanged(QString) ) ); connect( d->ui.kcfg_encryption, SIGNAL( clicked(int) ), SLOT( encryptionChanged(int) ) ); connect( d->ui.kcfg_requiresAuthentication, SIGNAL( toggled(bool) ), SLOT( ensureValidAuthSelection() ) ); // load the password d->transport->updatePasswordState(); if ( d->transport->isComplete() ) { d->ui.password->setText( d->transport->password() ); } else { if ( d->transport->requiresAuthentication() ) { TransportManager::self()->loadPasswordsAsync(); } } hostNameChanged( d->transport->host() ); } void SMTPConfigWidget::checkSmtpCapabilities() { Q_D( SMTPConfigWidget ); d->serverTest = new ServerTest( this ); d->serverTest->setProtocol( SMTP_PROTOCOL ); d->serverTest->setServer( d->ui.kcfg_host->text().trimmed() ); if ( d->ui.kcfg_specifyHostname->isChecked() ) { d->serverTest->setFakeHostname( d->ui.kcfg_localHostname->text() ); } d->serverTest->setProgressBar( d->ui.checkCapabilitiesProgress ); BusyCursorHelper *busyCursorHelper = new BusyCursorHelper( d->serverTest ); connect( d->serverTest, SIGNAL( finished( QList ) ), SLOT(slotFinished( QList ))); connect( d->serverTest, SIGNAL( finished( QList ) ), busyCursorHelper, SLOT( deleteLater() ) ); d->ui.checkCapabilities->setEnabled( false ); d->serverTest->start(); d->serverTestFailed = false; } void SMTPConfigWidget::apply() { Q_D( SMTPConfigWidget ); Q_ASSERT( d->manager ); d->manager->updateSettings(); d->transport->setPassword( d->ui.password->text() ); TransportConfigWidget::apply(); } void SMTPConfigWidget::passwordsLoaded() { Q_D( SMTPConfigWidget ); // Load the password from the original to our cloned copy d->transport->updatePasswordState(); if ( d->ui.password->text().isEmpty() ) { d->ui.password->setText( d->transport->password() ); } } static void checkHighestEnabledButton( QButtonGroup *group ) { Q_ASSERT( group ); for ( int i = group->buttons().count() - 1; i >= 0; --i ) { QAbstractButton *b = group->buttons().at( i ); if ( b && b->isEnabled() ) { b->animateClick(); return; } } } // TODO rename void SMTPConfigWidget::slotFinished( QList results ) { Q_D( SMTPConfigWidget ); d->ui.checkCapabilities->setEnabled( true ); d->serverTest->deleteLater(); // If the servertest did not find any useable authentication modes, assume the // connection failed and don't disable any of the radioboxes. if ( results.isEmpty() ) { d->serverTestFailed = true; return; } // encryption method d->ui.none->setEnabled( results.contains( Transport::EnumEncryption::None ) ); d->ui.ssl->setEnabled( results.contains( Transport::EnumEncryption::SSL ) ); d->ui.tls->setEnabled( results.contains( Transport::EnumEncryption::TLS ) ); checkHighestEnabledButton( d->encryptionGroup ); d->noEncCapa = d->serverTest->normalProtocols(); if ( d->ui.tls->isEnabled() ) { d->tlsCapa = d->serverTest->tlsProtocols(); } else { d->tlsCapa.clear(); } d->sslCapa = d->serverTest->secureProtocols(); d->updateAuthCapbilities(); checkHighestEnabledButton( d->authGroup ); } void SMTPConfigWidget::hostNameChanged( const QString &text ) { // TODO: really? is this done at every change? wtf Q_D( SMTPConfigWidget ); // sanitize hostname... int pos = d->ui.kcfg_host->cursorPosition(); d->ui.kcfg_host->blockSignals( true ); d->ui.kcfg_host->setText( text.trimmed() ); d->ui.kcfg_host->blockSignals( false ); d->ui.kcfg_host->setCursorPosition( pos ); d->resetAuthCapabilities(); for ( int i = 0; d->encryptionGroup && i < d->encryptionGroup->buttons().count(); i++ ) { d->encryptionGroup->buttons().at( i )->setEnabled( true ); } } void SMTPConfigWidget::ensureValidAuthSelection() { Q_D( SMTPConfigWidget ); // adjust available authentication methods d->updateAuthCapbilities(); foreach ( QAbstractButton *b, d->authGroup->buttons() ) { if ( b->isChecked() && !b->isEnabled() ) { checkHighestEnabledButton( d->authGroup ); break; } } } void SMTPConfigWidget::encryptionChanged( int enc ) { Q_D( SMTPConfigWidget ); kDebug() << enc; // adjust port if ( enc == Transport::EnumEncryption::SSL ) { if ( d->ui.kcfg_port->value() == SMTP_PORT ) { d->ui.kcfg_port->setValue( SMTPS_PORT ); } } else { if ( d->ui.kcfg_port->value() == SMTPS_PORT ) { d->ui.kcfg_port->setValue( SMTP_PORT ); } } ensureValidAuthSelection(); } #include "smtpconfigwidget.moc" diff --git a/mailtransport/transport.cpp b/mailtransport/transport.cpp index 33e56534e..263530ee9 100644 --- a/mailtransport/transport.cpp +++ b/mailtransport/transport.cpp @@ -1,338 +1,338 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transport.h" #include "legacydecrypt.h" #include "mailtransport_defs.h" #include "transportmanager.h" #include "transporttype_p.h" #include #include #include #include #include #include #include #include #include using namespace MailTransport; using namespace KWallet; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportPrivate { public: TransportType transportType; QString password; bool passwordLoaded; bool passwordDirty; bool storePasswordInFile; bool needsWalletMigration; QString oldName; }; Transport::Transport( const QString &cfgGroup ) : TransportBase( cfgGroup ), d( new TransportPrivate ) { kDebug() << cfgGroup; d->passwordLoaded = false; d->passwordDirty = false; d->storePasswordInFile = false; d->needsWalletMigration = false; readConfig(); } Transport::~Transport() { delete d; } bool Transport::isValid() const { return ( id() > 0 ) && !host().isEmpty() && port() <= 65536; } QString Transport::password() { if ( !d->passwordLoaded && requiresAuthentication() && storePassword() && d->password.isEmpty() ) { TransportManager::self()->loadPasswords(); d->password = TransportManager::self()->transportById( id(), false )->password(); } return d->password; } void Transport::setPassword( const QString &passwd ) { d->passwordLoaded = true; if ( d->password == passwd ) { return; } d->passwordDirty = true; d->password = passwd; } void Transport::forceUniqueName() { QStringList existingNames; foreach ( Transport *t, TransportManager::self()->transports() ) { if ( t->id() != id() ) { existingNames << t->name(); } } int suffix = 1; QString origName = name(); while ( existingNames.contains( name() ) ) { setName( i18nc( "%1: name; %2: number appended to it to make " "it unique among a list of names", "%1 #%2", origName, suffix ) ); ++suffix; } } void Transport::updatePasswordState() { Transport *original = TransportManager::self()->transportById( id(), false ); if ( original == this ) { kWarning() << "Tried to update password state of non-cloned transport."; return; } if ( original ) { d->password = original->d->password; d->passwordLoaded = original->d->passwordLoaded; d->passwordDirty = original->d->passwordDirty; } else { kWarning() << "Transport with this ID not managed by transport manager."; } } bool Transport::isComplete() const { return !requiresAuthentication() || !storePassword() || d->passwordLoaded; } QString Transport::authenticationTypeString() const { switch ( authenticationType() ) { case EnumAuthenticationType::LOGIN: return QLatin1String( "LOGIN" ); case EnumAuthenticationType::PLAIN: return QLatin1String( "PLAIN" ); case EnumAuthenticationType::CRAM_MD5: return QLatin1String( "CRAM-MD5" ); case EnumAuthenticationType::DIGEST_MD5: return QLatin1String( "DIGEST-MD5" ); case EnumAuthenticationType::NTLM: return QLatin1String( "NTLM" ); case EnumAuthenticationType::GSSAPI: return QLatin1String( "GSSAPI" ); } Q_ASSERT( false ); return QString(); } void Transport::usrReadConfig() { TransportBase::usrReadConfig(); setHost( host().trimmed() ); if ( d->oldName.isEmpty() ) { d->oldName = name(); } // Set TransportType. { using namespace Akonadi; d->transportType = TransportType(); d->transportType.d->mType = type(); kDebug() << "type" << type(); if( type() == EnumType::Akonadi ) { const AgentInstance instance = AgentManager::self()->instance( host() ); if( !instance.isValid() ) { kWarning() << "Akonadi transport with invalid resource instance."; } d->transportType.d->mAgentType = instance.type(); kDebug() << "agent type" << instance.type().name() << "id" << instance.type().identifier(); } // Now we have the type and possibly agentType. Get the name, description // etc. from TransportManager. const TransportType::List &types = TransportManager::self()->types(); int index = types.indexOf( d->transportType ); if( index != -1 ) { d->transportType = types[ index ]; } else { kWarning() << "Type unknown to manager."; - d->transportType.d->mName = i18n( "Unknown" ); + d->transportType.d->mName = i18nc( "An unknown transport type", "Unknown" ); } } // we have everything we need if ( !storePassword() || d->passwordLoaded ) { return; } // try to find a password in the config file otherwise KConfigGroup group( config(), currentGroup() ); if ( group.hasKey( "password" ) ) { d->password = KStringHandler::obscure( group.readEntry( "password" ) ); } else if ( group.hasKey( "password-kmail" ) ) { d->password = Legacy::decryptKMail( group.readEntry( "password-kmail" ) ); } else if ( group.hasKey( "password-knode" ) ) { d->password = Legacy::decryptKNode( group.readEntry( "password-knode" ) ); } if ( !d->password.isEmpty() ) { d->passwordLoaded = true; if ( Wallet::isEnabled() ) { d->needsWalletMigration = true; } else { d->storePasswordInFile = true; } } else { // read password if wallet is open, defer otherwise if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) { // Don't read the password right away because this can lead // to reentrancy problems in KDBusServiceStarter when an application // run in Kontact creates the transports (due to a QEventLoop in the // synchronous KWallet openWallet call). QTimer::singleShot( 0, this, SLOT(readPassword()) ); } } } void Transport::usrWriteConfig() { if ( requiresAuthentication() && storePassword() && d->passwordDirty ) { Wallet *wallet = TransportManager::self()->wallet(); if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) { // wallet saving failed, ask if we should store in the config file instead if ( d->storePasswordInFile || KMessageBox::warningYesNo( 0, i18n( "KWallet is not available. It is strongly recommended to use " "KWallet for managing your passwords.\n" "However, the password can be stored in the configuration " "file instead. The password is stored in an obfuscated format, " "but should not be considered secure from decryption efforts " "if access to the configuration file is obtained.\n" "Do you want to store the password for server '%1' in the " "configuration file?", name() ), i18n( "KWallet Not Available" ), KGuiItem( i18n( "Store Password" ) ), KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) { // write to config file KConfigGroup group( config(), currentGroup() ); group.writeEntry( "password", KStringHandler::obscure( d->password ) ); d->storePasswordInFile = true; } } d->passwordDirty = false; } TransportBase::usrWriteConfig(); TransportManager::self()->emitChangesCommitted(); if ( name() != d->oldName ) { emit TransportManager::self()->transportRenamed( id(), d->oldName, name() ); d->oldName = name(); } } void Transport::readPassword() { // no need to load a password if the account doesn't require auth if ( !requiresAuthentication() ) { return; } d->passwordLoaded = true; // check whether there is a chance to find our password at all if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) || Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER, QString::number( id() ) ) ) { // try migrating password from kmail if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) || Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER, QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) { return; } kDebug() << "migrating password from kmail wallet"; KWallet::Wallet *wallet = TransportManager::self()->wallet(); if ( wallet ) { wallet->setFolder( KMAIL_WALLET_FOLDER ); wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), d->password ); wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) ); wallet->setFolder( WALLET_FOLDER ); d->passwordDirty = true; writeConfig(); } return; } // finally try to open the wallet and read the password KWallet::Wallet *wallet = TransportManager::self()->wallet(); if ( wallet ) { wallet->readPassword( QString::number( id() ), d->password ); } } bool Transport::needsWalletMigration() const { return d->needsWalletMigration; } void Transport::migrateToWallet() { kDebug() << "migrating" << id() << "to wallet"; d->needsWalletMigration = false; KConfigGroup group( config(), currentGroup() ); group.deleteEntry( "password" ); d->passwordDirty = true; d->storePasswordInFile = false; writeConfig(); } Transport *Transport::clone() const { QString id = currentGroup().mid( 10 ); return new Transport( id ); } TransportType Transport::transportType() const { if( !d->transportType.isValid() ) { kWarning() << "Invalid transport type."; } return d->transportType; } void Transport::setTransportType( const TransportType &type ) { Q_ASSERT( type.isValid() ); d->transportType = type; setType( type.type() ); } #include "transport.moc" diff --git a/mailtransport/transportconfigdialog.cpp b/mailtransport/transportconfigdialog.cpp index f069fcfeb..c1efd5bcf 100644 --- a/mailtransport/transportconfigdialog.cpp +++ b/mailtransport/transportconfigdialog.cpp @@ -1,104 +1,101 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Copyright (c) 2009 Constantin Berzan Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportconfigdialog.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportmanager.h" #include "transporttype.h" #include "sendmailconfigwidget.h" #include "smtpconfigwidget.h" #include #include #include #include using namespace MailTransport; class MailTransport::TransportConfigDialog::Private { public: Transport *transport; QWidget *configWidget; // slots void okClicked(); }; void TransportConfigDialog::Private::okClicked() { if( TransportConfigWidget *w = dynamic_cast( configWidget ) ) { // It is not an Akonadi transport. w->apply(); transport->writeConfig(); } } - - TransportConfigDialog::TransportConfigDialog( Transport *transport, QWidget *parent ) - : KDialog( parent ) - , d( new Private ) + : KDialog( parent ), d( new Private ) { Q_ASSERT( transport ); d->transport = transport; switch( transport->type() ) { case Transport::EnumType::SMTP: { d->configWidget = new SMTPConfigWidget( transport, this ); break; } case Transport::EnumType::Sendmail: { d->configWidget = new SendmailConfigWidget( transport, this ); break; } case Transport::EnumType::Akonadi: { kWarning() << "Tried to configure an Akonadi transport."; d->configWidget = new QLabel( i18n( "This transport cannot be configured." ), this ); break; } default: { Q_ASSERT( false ); d->configWidget = 0; break; } } setMainWidget( d->configWidget ); setButtons( Ok|Cancel ); connect( this, SIGNAL(okClicked()), this, SLOT(okClicked()) ); } TransportConfigDialog::~TransportConfigDialog() { delete d; } #include "transportconfigdialog.moc" diff --git a/mailtransport/transportconfigwidget.cpp b/mailtransport/transportconfigwidget.cpp index adf8cc49e..ab9afab31 100644 --- a/mailtransport/transportconfigwidget.cpp +++ b/mailtransport/transportconfigwidget.cpp @@ -1,83 +1,82 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportconfigwidget.h" #include "transportconfigwidget_p.h" #include "transport.h" #include "transportmanager.h" #include #include using namespace MailTransport; TransportConfigWidget::TransportConfigWidget( Transport *transport, QWidget *parent ) - : QWidget( parent ) - , d_ptr( new TransportConfigWidgetPrivate ) + : QWidget( parent ), d_ptr( new TransportConfigWidgetPrivate ) { init( transport ); } -TransportConfigWidget::TransportConfigWidget( TransportConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ) - : QWidget( parent ) - , d_ptr( &dd ) +TransportConfigWidget::TransportConfigWidget( TransportConfigWidgetPrivate &dd, + Transport *transport, QWidget *parent ) + : QWidget( parent ), d_ptr( &dd ) { init( transport ); } TransportConfigWidget::~ TransportConfigWidget() { delete d_ptr; } void TransportConfigWidget::init( Transport *transport ) { Q_D( TransportConfigWidget ); kDebug() << "this" << this << "d" << d; Q_ASSERT( transport ); d->transport = transport; d->manager = new KConfigDialogManager( this, transport ); //d->manager->updateWidgets(); // no-op; ui is set up in subclasses. } KConfigDialogManager *TransportConfigWidget::configManager() const { Q_D( const TransportConfigWidget ); Q_ASSERT( d->manager ); return d->manager; } void TransportConfigWidget::apply() { Q_D( TransportConfigWidget ); d->manager->updateSettings(); d->transport->forceUniqueName(); d->transport->writeConfig(); kDebug() << "Config written."; } #include "transportconfigwidget.moc" diff --git a/mailtransport/transportconfigwidget.h b/mailtransport/transportconfigwidget.h index fc6b4f54f..71f92637f 100644 --- a/mailtransport/transportconfigwidget.h +++ b/mailtransport/transportconfigwidget.h @@ -1,107 +1,108 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTCONFIGWIDGET_H #define MAILTRANSPORT_TRANSPORTCONFIGWIDGET_H #include class KConfigDialogManager; namespace MailTransport { class Transport; class TransportConfigWidgetPrivate; /** @internal Abstract configuration widget for a mail transport. It makes sure that the configured transport has a unique name, and takes care of writing its settings to the config file. If it is a new transport, the caller must still call TransportManager::addTransport() to register the transport. Concrete configuration is done in subclasses SMTPConfigWidget and SendmailConfigWidget. Akonadi-type transports are not configured by MailTransport directly, instead the configure() method of their agent instance is called. To configure a transport from applications, use TransportManager::configureTransport(). You still need to call TransportManager::addTransport() if this is a new transport, not registered with TransportManager. @author Constantin Berzan @since 4.4 */ class TransportConfigWidget : public QWidget { Q_OBJECT public: /** Creates a new mail transport configuration widget for the given Transport object. @param transport The Transport object to configure. @param parent The parent widget. */ explicit TransportConfigWidget( Transport *transport, QWidget *parent = 0 ); /** Destroys the widget. */ virtual ~TransportConfigWidget(); /** @internal Get the KConfigDialogManager for this widget. */ KConfigDialogManager *configManager() const; public Q_SLOTS: /** Saves the transport's settings. The base implementation writes the settings to the config file and makes sure the transport has a unique name. Reimplement in derived classes to save your custom settings, and call the base implementation. */ // TODO: do we also want to check for invalid settings? virtual void apply(); protected: TransportConfigWidgetPrivate *const d_ptr; - TransportConfigWidget( TransportConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ); + TransportConfigWidget( TransportConfigWidgetPrivate &dd, + Transport *transport, QWidget *parent ); private: Q_DECLARE_PRIVATE( TransportConfigWidget ) void init( Transport *transport ); }; } // namespace MailTransport #endif // MAILTRANSPORT_TRANSPORTCONFIGWIDGET_H diff --git a/mailtransport/transportmanager.cpp b/mailtransport/transportmanager.cpp index f64e85a6e..bc54bfa18 100644 --- a/mailtransport/transportmanager.cpp +++ b/mailtransport/transportmanager.cpp @@ -1,769 +1,770 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportmanager.h" #include "addtransportdialog.h" #include "akonadijob.h" #include "mailtransport_defs.h" #include "sendmailconfigwidget.h" #include "sendmailjob.h" #include "smtpconfigwidget.h" #include "smtpjob.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportjob.h" #include "transporttype.h" #include "transporttype_p.h" #include "transportconfigdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace MailTransport; using namespace KWallet; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportManager::Private { public: Private() {} ~Private() { delete config; qDeleteAll( transports ); } KConfig *config; QList transports; TransportType::List types; bool myOwnChange; bool appliedChange; KWallet::Wallet *wallet; bool walletOpenFailed; bool walletAsyncOpen; int defaultTransportId; bool isMainInstance; QList walletQueue; }; class StaticTransportManager : public TransportManager { public: StaticTransportManager() : TransportManager() {} }; StaticTransportManager *sSelf = 0; static void destroyStaticTransportManager() { delete sSelf; } TransportManager::TransportManager() : QObject(), d( new Private ) { KGlobal::locale()->insertCatalog( QLatin1String( "libmailtransport" ) ); qAddPostRoutine( destroyStaticTransportManager ); d->myOwnChange = false; d->appliedChange = false; d->wallet = 0; d->walletOpenFailed = false; d->walletAsyncOpen = false; d->defaultTransportId = -1; d->config = new KConfig( QLatin1String( "mailtransports" ) ); QDBusConnection::sessionBus().registerObject( DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals ); QDBusConnection::sessionBus().connect( QString(), QString(), DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL, this, SLOT(slotTransportsChanged()) ); d->isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(dbusServiceOwnerChanged(QString,QString,QString)) ); fillTypes(); } TransportManager::~TransportManager() { qRemovePostRoutine( destroyStaticTransportManager ); delete d; } TransportManager *TransportManager::self() { if ( !sSelf ) { sSelf = new StaticTransportManager; sSelf->readConfig(); } return sSelf; } Transport *TransportManager::transportById( int id, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->id() == id ) { return t; } } if ( def || ( id == 0 && d->defaultTransportId != id ) ) { return transportById( d->defaultTransportId, false ); } return 0; } Transport *TransportManager::transportByName( const QString &name, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->name() == name ) { return t; } } if ( def ) { return transportById( 0, false ); } return 0; } QList< Transport * > TransportManager::transports() const { return d->transports; } -const TransportType::List &TransportManager::types() const +TransportType::List TransportManager::types() const { return d->types; } Transport *TransportManager::createTransport() const { int id = createId(); Transport *t = new Transport( QString::number( id ) ); t->setId( id ); return t; } void TransportManager::addTransport( Transport *transport ) { if ( d->transports.contains( transport ) ) { kDebug() << "Already have this transport."; return; } kDebug() << "Added transport" << transport; d->transports.append( transport ); validateDefault(); emitChangesCommitted(); } void TransportManager::schedule( TransportJob *job ) { connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); // check if the job is waiting for the wallet if ( !job->transport()->isComplete() ) { kDebug() << "job waits for wallet:" << job; d->walletQueue << job; loadPasswordsAsync(); return; } job->start(); } void TransportManager::createDefaultTransport() { KEMailSettings kes; Transport *t = createTransport(); t->setName( i18n( "Default Transport" ) ); t->setHost( kes.getSetting( KEMailSettings::OutServer ) ); if ( t->isValid() ) { t->writeConfig(); addTransport( t ); } else { kWarning() << "KEMailSettings does not contain a valid transport."; } } bool TransportManager::showNewTransportDialog( QWidget *parent ) { QPointer dialog = new AddTransportDialog( parent ); bool accepted = ( dialog->exec() == QDialog::Accepted ); delete dialog; return accepted; } bool TransportManager::promptCreateTransportIfNoneExists( QWidget *parent ) { - if ( !isEmpty() ) + if ( !isEmpty() ) { return true; + } const int response = KMessageBox::messageBox( parent, KMessageBox::WarningContinueCancel, - i18n("You must create an outgoing account before sending."), - i18n("Create Account Now?"), - KGuiItem( i18n("Create Account Now") ) ); + i18n( "You must create an outgoing account before sending." ), + i18n( "Create Account Now?" ), + KGuiItem( i18n( "Create Account Now" ) ) ); if ( response == KMessageBox::Continue ) { return showNewTransportDialog( parent ); } return false; } bool TransportManager::configureTransport( Transport *transport, QWidget *parent ) { if( transport->type() == Transport::EnumType::Akonadi ) { using namespace Akonadi; AgentInstance instance = AgentManager::self()->instance( transport->host() ); if( !instance.isValid() ) { kWarning() << "Invalid resource instance" << transport->host(); } instance.configure( parent ); // Async... transport->writeConfig(); return true; // No way to know here if the user cancelled or not. } QPointer dialog = new KDialog( parent ); TransportConfigWidget *configWidget = 0; switch( transport->type() ) { case Transport::EnumType::SMTP: { configWidget = new SMTPConfigWidget( transport, dialog ); break; } case Transport::EnumType::Sendmail: { configWidget = new SendmailConfigWidget( transport, dialog ); break; } default: { Q_ASSERT( false ); delete dialog; return false; } } dialog->setMainWidget( configWidget ); dialog->setCaption( i18n( "Configure account" ) ); dialog->setButtons( KDialog::Ok | KDialog::Cancel ); bool okClicked = ( dialog->exec() == QDialog::Accepted ); if( okClicked ) { configWidget->apply(); // calls transport->writeConfig() } delete dialog; return okClicked; } TransportJob *TransportManager::createTransportJob( int transportId ) { Transport *t = transportById( transportId, false ); if ( !t ) { return 0; } t = t->clone(); // Jobs delete their transports. switch ( t->type() ) { case Transport::EnumType::SMTP: return new SmtpJob( t, this ); case Transport::EnumType::Sendmail: return new SendmailJob( t, this ); case Transport::EnumType::Akonadi: return new AkonadiJob( t, this ); } Q_ASSERT( false ); return 0; } TransportJob *TransportManager::createTransportJob( const QString &transport ) { bool ok = false; Transport *t = 0; int transportId = transport.toInt( &ok ); if ( ok ) { t = transportById( transportId ); } if ( !t ) { t = transportByName( transport, false ); } if ( t ) { return createTransportJob( t->id() ); } return 0; } bool TransportManager::isEmpty() const { return d->transports.isEmpty(); } QList TransportManager::transportIds() const { QList rv; foreach ( Transport *t, d->transports ) { rv << t->id(); } return rv; } QStringList TransportManager::transportNames() const { QStringList rv; foreach ( Transport *t, d->transports ) { rv << t->name(); } return rv; } QString TransportManager::defaultTransportName() const { Transport *t = transportById( d->defaultTransportId, false ); if ( t ) { return t->name(); } return QString(); } int TransportManager::defaultTransportId() const { return d->defaultTransportId; } void TransportManager::setDefaultTransport( int id ) { if ( id == d->defaultTransportId || !transportById( id, false ) ) { return; } d->defaultTransportId = id; writeConfig(); } void TransportManager::removeTransport( int id ) { Transport *t = transportById( id, false ); if ( !t ) { return; } emit transportRemoved( t->id(), t->name() ); // Kill the resource, if Akonadi-type transport. if( t->type() == Transport::EnumType::Akonadi ) { using namespace Akonadi; const AgentInstance instance = AgentManager::self()->instance( t->host() ); if( !instance.isValid() ) { kWarning() << "Could not find resource instance."; } AgentManager::self()->removeInstance( instance ); } d->transports.removeAll( t ); validateDefault(); QString group = t->currentGroup(); delete t; d->config->deleteGroup( group ); writeConfig(); } void TransportManager::readConfig() { QList oldTransports = d->transports; d->transports.clear(); QRegExp re( QLatin1String( "^Transport (.+)$" ) ); QStringList groups = d->config->groupList().filter( re ); foreach ( const QString &s, groups ) { re.indexIn( s ); Transport *t = 0; // see if we happen to have that one already foreach ( Transport *old, oldTransports ) { if ( old->currentGroup() == QLatin1String( "Transport " ) + re.cap( 1 ) ) { kDebug() << "reloading existing transport:" << s; t = old; t->readConfig(); oldTransports.removeAll( old ); break; } } if ( !t ) { t = new Transport( re.cap( 1 ) ); } if ( t->id() <= 0 ) { t->setId( createId() ); t->writeConfig(); } d->transports.append( t ); } qDeleteAll( oldTransports ); oldTransports.clear(); // read default transport KConfigGroup group( d->config, "General" ); d->defaultTransportId = group.readEntry( "default-transport", 0 ); if ( d->defaultTransportId == 0 ) { // migrated default transport contains the name instead QString name = group.readEntry( "default-transport", QString() ); if ( !name.isEmpty() ) { Transport *t = transportByName( name, false ); if ( t ) { d->defaultTransportId = t->id(); writeConfig(); } } } validateDefault(); migrateToWallet(); } void TransportManager::writeConfig() { KConfigGroup group( d->config, "General" ); group.writeEntry( "default-transport", d->defaultTransportId ); d->config->sync(); emitChangesCommitted(); } void TransportManager::fillTypes() { Q_ASSERT( d->types.isEmpty() ); // SMTP. { TransportType type; type.d->mType = Transport::EnumType::SMTP; type.d->mName = i18nc( "@option SMTP transport", "SMTP" ); type.d->mDescription = i18n( "An SMTP server on the internet" ); d->types << type; } // Sendmail. { TransportType type; type.d->mType = Transport::EnumType::Sendmail; type.d->mName = i18nc( "@option sendmail transport", "Sendmail" ); type.d->mDescription = i18n( "A local sendmail installation" ); d->types << type; } - + // All Akonadi resources with MailTransport capability. { using namespace Akonadi; - foreach( const AgentType &atype, AgentManager::self()->types() ) { + foreach ( const AgentType &atype, AgentManager::self()->types() ) { // TODO probably the string "MailTransport" should be #defined somewhere // and used like that in the resources (?) if( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { TransportType type; type.d->mType = Transport::EnumType::Akonadi; type.d->mAgentType = atype; type.d->mName = atype.name(); type.d->mDescription = atype.description(); d->types << type; kDebug() << "Found Akonadi type" << atype.name(); } } // Watch for appearing and disappearing types. connect( AgentManager::self(), SIGNAL(typeAdded(Akonadi::AgentType)), this, SLOT(agentTypeAdded(Akonadi::AgentType)) ); connect( AgentManager::self(), SIGNAL(typeRemoved(Akonadi::AgentType)), this, SLOT(agentTypeRemoved(Akonadi::AgentType)) ); } kDebug() << "Have SMTP, Sendmail, and" << d->types.count() - 2 << "Akonadi types."; } void TransportManager::emitChangesCommitted() { d->myOwnChange = true; // prevent us from reading our changes again d->appliedChange = false; // but we have to read them at least once emit transportsChanged(); emit changesCommitted(); } void TransportManager::slotTransportsChanged() { if ( d->myOwnChange && d->appliedChange ) { d->myOwnChange = false; d->appliedChange = false; return; } kDebug(); d->config->reparseConfiguration(); // FIXME: this deletes existing transport objects! readConfig(); d->appliedChange = true; // to prevent recursion emit transportsChanged(); } int TransportManager::createId() const { QList usedIds; foreach ( Transport *t, d->transports ) { usedIds << t->id(); } usedIds << 0; // 0 is default for unknown int newId; do { newId = KRandom::random(); } while ( usedIds.contains( newId ) ); return newId; } KWallet::Wallet * TransportManager::wallet() { if ( d->wallet && d->wallet->isOpen() ) { return d->wallet; } if ( !Wallet::isEnabled() || d->walletOpenFailed ) { return 0; } WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } delete d->wallet; d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window ); if ( !d->wallet ) { d->walletOpenFailed = true; return 0; } prepareWallet(); return d->wallet; } void TransportManager::prepareWallet() { if ( !d->wallet ) { return; } if ( !d->wallet->hasFolder( WALLET_FOLDER ) ) { d->wallet->createFolder( WALLET_FOLDER ); } d->wallet->setFolder( WALLET_FOLDER ); } void TransportManager::loadPasswords() { foreach ( Transport *t, d->transports ) { t->readPassword(); } // flush the wallet queue foreach ( TransportJob *job, d->walletQueue ) { job->start(); } d->walletQueue.clear(); emit passwordsChanged(); } void TransportManager::loadPasswordsAsync() { kDebug(); // check if there is anything to do at all bool found = false; foreach ( Transport *t, d->transports ) { if ( !t->isComplete() ) { found = true; break; } } if ( !found ) { return; } // async wallet opening if ( !d->wallet && !d->walletOpenFailed ) { WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window, Wallet::Asynchronous ); if ( d->wallet ) { connect( d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)) ); d->walletAsyncOpen = true; } else { d->walletOpenFailed = true; loadPasswords(); } return; } if ( d->wallet && !d->walletAsyncOpen ) { loadPasswords(); } } void TransportManager::slotWalletOpened( bool success ) { kDebug(); d->walletAsyncOpen = false; if ( !success ) { d->walletOpenFailed = true; delete d->wallet; d->wallet = 0; } else { prepareWallet(); } loadPasswords(); } void TransportManager::validateDefault() { if ( !transportById( d->defaultTransportId, false ) ) { if ( isEmpty() ) { d->defaultTransportId = -1; } else { d->defaultTransportId = d->transports.first()->id(); writeConfig(); } } } void TransportManager::migrateToWallet() { // check if we tried this already static bool firstRun = true; if ( !firstRun ) { return; } firstRun = false; // check if we are the main instance if ( !d->isMainInstance ) { return; } // check if migration is needed QStringList names; foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { names << t->name(); } } if ( names.isEmpty() ) { return; } // ask user if he wants to migrate int result = KMessageBox::questionYesNoList( 0, i18n( "The following mail transports store their passwords in an " "unencrypted configuration file.\nFor security reasons, " "please consider migrating these passwords to KWallet, the " "KDE Wallet management tool,\nwhich stores sensitive data " "for you in a strongly encrypted file.\n" "Do you want to migrate your passwords to KWallet?" ), names, i18n( "Question" ), KGuiItem( i18n( "Migrate" ) ), KGuiItem( i18n( "Keep" ) ), QString::fromAscii( "WalletMigrate" ) ); if ( result != KMessageBox::Yes ) { return; } // perform migration foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { t->migrateToWallet(); } } } void TransportManager::dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ) { Q_UNUSED( oldOwner ); if ( service == DBUS_SERVICE_NAME && newOwner.isEmpty() ) { QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); } } void TransportManager::agentTypeAdded( const Akonadi::AgentType &atype ) { using namespace Akonadi; if( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { TransportType type; type.d->mType = Transport::EnumType::Akonadi; type.d->mAgentType = atype; type.d->mName = atype.name(); type.d->mDescription = atype.description(); d->types << type; kDebug() << "Added new Akonadi type" << atype.name(); } } void TransportManager::agentTypeRemoved( const Akonadi::AgentType &atype ) { using namespace Akonadi; - foreach( const TransportType &type, d->types ) { + foreach ( const TransportType &type, d->types ) { if( type.type() == Transport::EnumType::Akonadi && type.agentType() == atype ) { d->types.removeAll( type ); kDebug() << "Removed Akonadi type" << atype.name(); } } } void TransportManager::jobResult( KJob *job ) { d->walletQueue.removeAll( static_cast( job ) ); } #include "transportmanager.moc" diff --git a/mailtransport/transportmanager.h b/mailtransport/transportmanager.h index ba1ac1fc3..ef960a007 100644 --- a/mailtransport/transportmanager.h +++ b/mailtransport/transportmanager.h @@ -1,299 +1,299 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTMANAGER_H #define MAILTRANSPORT_TRANSPORTMANAGER_H #include #include #include #include #include class KJob; namespace KWallet { class Wallet; } namespace MailTransport { class Transport; class TransportConfigWidget; class TransportJob; /** @short Central transport management interface. This class manages the creation, configuration, and removal of mail transports, as well as the loading and storing of mail transport settings, and creation of transport jobs. */ class MAILTRANSPORT_EXPORT TransportManager : public QObject { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kde.pim.TransportManager" ) friend class Transport; friend class Private; public: class Private; /** Destructor. */ virtual ~TransportManager(); /** Returns the TransportManager instance. */ static TransportManager *self(); /** Tries to load passwords asynchronously from KWallet if needed. The passwordsChanged() signal is emitted once the passwords have been loaded. Nothing happens if the passwords were already available. */ void loadPasswordsAsync(); /** Returns the Transport object with the given id. @param id The identifier of the Transport. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use. It might become invalid as soon as the event loop is entered again due to remote changes. If you need to store a Transport object, store the transport identifier instead. */ Transport *transportById( int id, bool def = true ) const; /** Returns the transport object with the given name. @param name The transport name. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use, see transportById() for limitations. */ Transport *transportByName( const QString &name, bool def = true ) const; /** Returns a list of all available transports. Note: The Transport objects become invalid as soon as a change occur, so they are only suitable for immediate use. */ QListtransports() const; /** Returns a list of all available transport types. */ - const TransportType::List &types() const; + TransportType::List types() const; /** Creates a new, empty Transport object. The object is owned by the caller. If you want to add the Transport permanently (eg. after configuring it) call addTransport(). */ Transport *createTransport() const; /** Adds the given transport. The object ownership is transferred to TransportMananger, ie. you must not delete @p transport. @param transport The Transport object to add. */ void addTransport( Transport *transport ); /** Creates a mail transport job for the given transport identifier. Returns 0 if the specified transport is invalid. @param transportId The transport identifier. */ TransportJob *createTransportJob( int transportId ); /** Creates a mail transport job for the given transport identifer, or transport name. Returns 0 if the specified transport is invalid. @param transport A string defining a mail transport. */ TransportJob *createTransportJob( const QString &transport ); /** Executes the given transport job. This is the preferred way to start transport jobs. It takes care of asynchronously loading passwords from KWallet if necessary. @param job The completely configured transport job to execute. */ void schedule( TransportJob *job ); /** Tries to create a transport based on KEMailSettings. If the data in KEMailSettings is incomplete, no transport is created. */ void createDefaultTransport(); /** Shows a dialog for creating and configuring a new transport. @param parent Parent widget of the dialog. @return True if a new transport has been created and configured. @since 4.4 */ bool showNewTransportDialog( QWidget *parent ); /** If no transport exists, asks the user to create and configure one. Returns true if a transport exists or the user created one. Otherwise returns false. @param parent Parent widget of the dialog. @since 4.4 */ bool promptCreateTransportIfNoneExists( QWidget *parent ); /** Open a configuration dialog for an existing transport. @param transport The transport to configure. It can be a new transport, or one already managed by TransportManager. @param parent The parent widget for the dialog. @return True if the user clicked Ok, false if the user cancelled. @since 4.4 */ bool configureTransport( Transport *transport, QWidget *parent ); public Q_SLOTS: /** Returns true if there are no mail transports at all. */ Q_SCRIPTABLE bool isEmpty() const; /** Returns a list of transport identifiers. */ Q_SCRIPTABLE QList transportIds() const; /** Returns a list of transport names. */ Q_SCRIPTABLE QStringList transportNames() const; /** Returns the default transport name. */ Q_SCRIPTABLE QString defaultTransportName() const; /** Returns the default transport identifier. Invalid if there are no transports at all. */ Q_SCRIPTABLE int defaultTransportId() const; /** Sets the default transport. The change will be in effect immediately. @param id The identifier of the new default transport. */ Q_SCRIPTABLE void setDefaultTransport( int id ); /** Deletes the specified transport. @param id The identifier of the mail transport to remove. */ Q_SCRIPTABLE void removeTransport( int id ); Q_SIGNALS: /** Emitted when transport settings have changed (by this or any other TransportManager instance). */ Q_SCRIPTABLE void transportsChanged(); /** Internal signal to synchronize all TransportManager instances. This signal is emitted by the instance writing the changes. You probably want to use transportsChanged() instead. */ Q_SCRIPTABLE void changesCommitted(); /** Emitted when passwords have been loaded from the wallet. If you made a deep copy of a transport, you should call updatePasswordState() for the cloned transport to ensure its password is updated as well. */ void passwordsChanged(); /** Emitted when a transport is deleted. @param id The identifier of the deleted transport. @param name The name of the deleted transport. */ void transportRemoved( int id, const QString &name ); /** Emitted when a transport has been renamed. @param id The identifier of the renamed transport. @param oldName The old name. @param newName The new name. */ void transportRenamed( int id, const QString &oldName, const QString &newName ); protected: /** Returns a pointer to an open wallet if available, 0 otherwise. The wallet is opened synchronously if necessary. */ KWallet::Wallet *wallet(); /** Loads all passwords synchronously. */ void loadPasswords(); /** Singleton class, the only instance resides in the static object sSelf. */ TransportManager(); private: void readConfig(); void writeConfig(); void fillTypes(); void emitChangesCommitted(); int createId() const; void prepareWallet(); void validateDefault(); void migrateToWallet(); private Q_SLOTS: void slotTransportsChanged(); void slotWalletOpened( bool success ); void dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ); void agentTypeAdded( const Akonadi::AgentType &atype ); void agentTypeRemoved( const Akonadi::AgentType &atype ); void jobResult( KJob *job ); private: Private *const d; }; } // namespace MailTransport #endif // MAILTRANSPORT_TRANSPORTMANAGER_H diff --git a/mailtransport/transporttype.cpp b/mailtransport/transporttype.cpp index f62cd6062..d913a67df 100644 --- a/mailtransport/transporttype.cpp +++ b/mailtransport/transporttype.cpp @@ -1,90 +1,90 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transporttype.h" #include "transporttype_p.h" #include "transport.h" #include using namespace MailTransport; TransportType::TransportType() : d( new Private ) { } TransportType::TransportType( const TransportType &other ) : d( other.d ) { } TransportType::~TransportType() { } -TransportType& TransportType::operator=( const TransportType &other ) +TransportType &TransportType::operator=( const TransportType &other ) { if( this != &other ) { d = other.d; } return *this; } bool TransportType::operator==( const TransportType &other ) const { if( d->mType == Transport::EnumType::Akonadi && other.d->mType == Transport::EnumType::Akonadi ) { return ( d->mAgentType == other.d->mAgentType ); } return ( d->mType == other.d->mType ); } bool TransportType::isValid() const { using namespace Akonadi; if( d->mType == Transport::EnumType::Akonadi ) { return d->mAgentType.isValid() && AgentManager::self()->types().contains( d->mAgentType ); } else { return d->mType >= 0; } } int TransportType::type() const { return d->mType; } QString TransportType::name() const { return d->mName; } QString TransportType::description() const { return d->mDescription; } Akonadi::AgentType TransportType::agentType() const { Q_ASSERT( d->mType == Transport::EnumType::Akonadi ); return d->mAgentType; } diff --git a/mailtransport/transporttype.h b/mailtransport/transporttype.h index 76b90218f..03afbd18b 100644 --- a/mailtransport/transporttype.h +++ b/mailtransport/transporttype.h @@ -1,128 +1,128 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTTYPE_H #define MAILTRANSPORT_TRANSPORTTYPE_H #include "mailtransport_export.h" #include "transport.h" #include #include namespace MailTransport { class AddTransportDialog; class TransportManager; /** @short A representation of a transport type. Represents an available transport type. SMTP and Sendmail are available, as well as a number of Akonadi-based types. Each Akonadi-based type corresponds to an Akonadi resource type that supports sending messages. This class provides information about the type, such as name and description. Additionally, for Akonadi types, it provides the corresponding Akonadi AgentType. All available transport types can be retrieved via TransportManager::types(). @author Constantin Berzan @since 4.4 */ class MAILTRANSPORT_EXPORT TransportType { friend class AddTransportDialog; friend class Transport; friend class TransportManager; public: /** Describes a list of transport types. */ typedef QList List; /** Constructs a new TransportType. */ TransportType(); /** Creates a copy of the @p other TransportType. */ TransportType( const TransportType &other ); /** Destroys the TransportType. */ ~TransportType(); /** @internal */ - TransportType& operator=( const TransportType &other ); - + TransportType &operator=( const TransportType &other ); + /** @internal Compares two transport types. */ bool operator==( const TransportType &other ) const; /** Returns whether the transport type is valid. */ bool isValid() const; /** @internal Returns the numeric type of the transport. This corresponds to Transport::EnumType::type. */ // TODO should this be Transport::EnumType::type instead of int? int type() const; /** Returns the i18n'ed name of the transport type. */ QString name() const; /** Returns a description of the transport type. */ QString description() const; /** Returns the corresponding Akonadi::AgentType that this transport type represents. Only valid if type() is Transport::EnumType::Akonadi. */ Akonadi::AgentType agentType() const; private: class Private; QSharedDataPointer d; }; } // namespace MailTransport Q_DECLARE_METATYPE( MailTransport::TransportType ) #endif // MAILTRANSPORT_TRANSPORTTYPE_H