1 | /* |
2 | Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "transportmanager.h" |
21 | #include "resourcesendjob_p.h" |
22 | #include "mailtransport_defs.h" |
23 | #include "sendmailjob.h" |
24 | #include "smtpjob.h" |
25 | #include "transport.h" |
26 | #include "transport_p.h" |
27 | #include "transportjob.h" |
28 | #include "transporttype.h" |
29 | #include "transporttype_p.h" |
30 | #include "addtransportdialog.h" |
31 | #include "transportconfigdialog.h" |
32 | #include "transportconfigwidget.h" |
33 | #include "sendmailconfigwidget.h" |
34 | #include "smtpconfigwidget.h" |
35 | |
36 | #include <QApplication> |
37 | #include <QtDBus/QDBusConnection> |
38 | #include <QtDBus/QDBusConnectionInterface> |
39 | #include <QtDBus/QDBusServiceWatcher> |
40 | #include <QPointer> |
41 | #include <QRegExp> |
42 | #include <QStringList> |
43 | |
44 | #include <KConfig> |
45 | #include <KConfigGroup> |
46 | #include <KDebug> |
47 | #include <KEMailSettings> |
48 | #include <KLocale> |
49 | #include <KLocalizedString> |
50 | #include <KMessageBox> |
51 | #include <KRandom> |
52 | #include <KGlobal> |
53 | #include <KWallet/Wallet> |
54 | |
55 | #include <akonadi/agentinstance.h> |
56 | #include <akonadi/agentmanager.h> |
57 | |
58 | using namespace MailTransport; |
59 | using namespace KWallet; |
60 | |
61 | namespace MailTransport { |
62 | /** |
63 | * Private class that helps to provide binary compatibility between releases. |
64 | * @internal |
65 | */ |
66 | class TransportManagerPrivate |
67 | { |
68 | public: |
69 | TransportManagerPrivate( TransportManager *parent ) |
70 | : q( parent ) |
71 | { |
72 | } |
73 | |
74 | ~TransportManagerPrivate() { |
75 | delete config; |
76 | qDeleteAll( transports ); |
77 | } |
78 | |
79 | KConfig *config; |
80 | QList<Transport *> transports; |
81 | TransportType::List types; |
82 | bool myOwnChange; |
83 | bool appliedChange; |
84 | KWallet::Wallet *wallet; |
85 | bool walletOpenFailed; |
86 | bool walletAsyncOpen; |
87 | int defaultTransportId; |
88 | bool isMainInstance; |
89 | QList<TransportJob *> walletQueue; |
90 | TransportManager *q; |
91 | |
92 | void readConfig(); |
93 | void writeConfig(); |
94 | void fillTypes(); |
95 | int createId() const; |
96 | void prepareWallet(); |
97 | void validateDefault(); |
98 | void migrateToWallet(); |
99 | |
100 | // Slots |
101 | void slotTransportsChanged(); |
102 | void slotWalletOpened( bool success ); |
103 | void dbusServiceUnregistered(); |
104 | void agentTypeAdded( const Akonadi::AgentType &atype ); |
105 | void agentTypeRemoved( const Akonadi::AgentType &atype ); |
106 | void jobResult( KJob *job ); |
107 | }; |
108 | |
109 | } |
110 | |
111 | class StaticTransportManager : public TransportManager |
112 | { |
113 | public: |
114 | StaticTransportManager() : TransportManager() {} |
115 | }; |
116 | |
117 | StaticTransportManager *sSelf = 0; |
118 | |
119 | static void destroyStaticTransportManager() { |
120 | delete sSelf; |
121 | } |
122 | |
123 | TransportManager::TransportManager() |
124 | : QObject(), d( new TransportManagerPrivate( this ) ) |
125 | { |
126 | KGlobal::locale()->insertCatalog( QLatin1String( "libmailtransport" ) ); |
127 | KGlobal::locale()->insertCatalog( QLatin1String( "libakonadi-kmime" ) ); |
128 | qAddPostRoutine( destroyStaticTransportManager ); |
129 | d->myOwnChange = false; |
130 | d->appliedChange = false; |
131 | d->wallet = 0; |
132 | d->walletOpenFailed = false; |
133 | d->walletAsyncOpen = false; |
134 | d->defaultTransportId = -1; |
135 | d->config = new KConfig( QLatin1String( "mailtransports" ) ); |
136 | |
137 | QDBusConnection::sessionBus().registerObject( DBUS_OBJECT_PATH, this, |
138 | QDBusConnection::ExportScriptableSlots | |
139 | QDBusConnection::ExportScriptableSignals ); |
140 | |
141 | QDBusServiceWatcher *watcher = |
142 | new QDBusServiceWatcher( DBUS_SERVICE_NAME, QDBusConnection::sessionBus(), |
143 | QDBusServiceWatcher::WatchForUnregistration, this ); |
144 | connect( watcher, SIGNAL(serviceUnregistered(QString)), |
145 | SLOT(dbusServiceUnregistered()) ); |
146 | |
147 | QDBusConnection::sessionBus().connect( QString(), QString(), |
148 | DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL, |
149 | this, SLOT(slotTransportsChanged()) ); |
150 | |
151 | d->isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); |
152 | |
153 | d->fillTypes(); |
154 | } |
155 | |
156 | TransportManager::~TransportManager() |
157 | { |
158 | qRemovePostRoutine( destroyStaticTransportManager ); |
159 | delete d; |
160 | } |
161 | |
162 | TransportManager *TransportManager::self() |
163 | { |
164 | if ( !sSelf ) { |
165 | sSelf = new StaticTransportManager; |
166 | sSelf->d->readConfig(); |
167 | } |
168 | return sSelf; |
169 | } |
170 | |
171 | Transport *TransportManager::transportById( int id, bool def ) const |
172 | { |
173 | foreach ( Transport *t, d->transports ) { |
174 | if ( t->id() == id ) { |
175 | return t; |
176 | } |
177 | } |
178 | |
179 | if ( def || ( id == 0 && d->defaultTransportId != id ) ) { |
180 | return transportById( d->defaultTransportId, false ); |
181 | } |
182 | return 0; |
183 | } |
184 | |
185 | Transport *TransportManager::transportByName( const QString &name, bool def ) const |
186 | { |
187 | foreach ( Transport *t, d->transports ) { |
188 | if ( t->name() == name ) { |
189 | return t; |
190 | } |
191 | } |
192 | if ( def ) { |
193 | return transportById( 0, false ); |
194 | } |
195 | return 0; |
196 | } |
197 | |
198 | QList< Transport * > TransportManager::transports() const |
199 | { |
200 | return d->transports; |
201 | } |
202 | |
203 | TransportType::List TransportManager::types() const |
204 | { |
205 | return d->types; |
206 | } |
207 | |
208 | Transport *TransportManager::createTransport() const |
209 | { |
210 | int id = d->createId(); |
211 | Transport *t = new Transport( QString::number( id ) ); |
212 | t->setId( id ); |
213 | return t; |
214 | } |
215 | |
216 | void TransportManager::addTransport( Transport *transport ) |
217 | { |
218 | if ( d->transports.contains( transport ) ) { |
219 | kDebug() << "Already have this transport." ; |
220 | return; |
221 | } |
222 | |
223 | kDebug() << "Added transport" << transport; |
224 | d->transports.append( transport ); |
225 | d->validateDefault(); |
226 | emitChangesCommitted(); |
227 | } |
228 | |
229 | void TransportManager::schedule( TransportJob *job ) |
230 | { |
231 | connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); |
232 | |
233 | // check if the job is waiting for the wallet |
234 | if ( !job->transport()->isComplete() ) { |
235 | kDebug() << "job waits for wallet:" << job; |
236 | d->walletQueue << job; |
237 | loadPasswordsAsync(); |
238 | return; |
239 | } |
240 | |
241 | job->start(); |
242 | } |
243 | |
244 | void TransportManager::createDefaultTransport() |
245 | { |
246 | KEMailSettings kes; |
247 | Transport *t = createTransport(); |
248 | t->setName( i18n( "Default Transport" ) ); |
249 | t->setHost( kes.getSetting( KEMailSettings::OutServer ) ); |
250 | if ( t->isValid() ) { |
251 | t->writeConfig(); |
252 | addTransport( t ); |
253 | } else { |
254 | kWarning() << "KEMailSettings does not contain a valid transport." ; |
255 | } |
256 | } |
257 | |
258 | bool TransportManager::showTransportCreationDialog( QWidget *parent, |
259 | ShowCondition showCondition ) |
260 | { |
261 | if ( showCondition == IfNoTransportExists ) { |
262 | if ( !isEmpty() ) { |
263 | return true; |
264 | } |
265 | |
266 | const int response = KMessageBox::messageBox( parent, |
267 | KMessageBox::WarningContinueCancel, |
268 | i18n( "You must create an outgoing account before sending." ), |
269 | i18n( "Create Account Now?" ), |
270 | KGuiItem( i18n( "Create Account Now" ) ) ); |
271 | if ( response != KMessageBox::Continue ) { |
272 | return false; |
273 | } |
274 | } |
275 | |
276 | QPointer<AddTransportDialog> dialog = new AddTransportDialog( parent ); |
277 | const bool accepted = ( dialog->exec() == QDialog::Accepted ); |
278 | delete dialog; |
279 | return accepted; |
280 | } |
281 | |
282 | bool TransportManager::configureTransport( Transport *transport, QWidget *parent ) |
283 | { |
284 | if ( transport->type() == Transport::EnumType::Akonadi ) { |
285 | using namespace Akonadi; |
286 | AgentInstance instance = AgentManager::self()->instance( transport->host() ); |
287 | if ( !instance.isValid() ) { |
288 | kWarning() << "Invalid resource instance" << transport->host(); |
289 | } |
290 | instance.configure( parent ); // Async... |
291 | transport->writeConfig(); |
292 | return true; // No way to know here if the user cancelled or not. |
293 | } |
294 | |
295 | QPointer<TransportConfigDialog> transportConfigDialog = |
296 | new TransportConfigDialog( transport, parent ); |
297 | transportConfigDialog->setCaption( i18n( "Configure account" ) ); |
298 | bool okClicked = ( transportConfigDialog->exec() == QDialog::Accepted ); |
299 | delete transportConfigDialog; |
300 | return okClicked; |
301 | } |
302 | |
303 | TransportJob *TransportManager::createTransportJob( int transportId ) |
304 | { |
305 | Transport *t = transportById( transportId, false ); |
306 | if ( !t ) { |
307 | return 0; |
308 | } |
309 | t = t->clone(); // Jobs delete their transports. |
310 | t->updatePasswordState(); |
311 | switch ( t->type() ) { |
312 | case Transport::EnumType::SMTP: |
313 | return new SmtpJob( t, this ); |
314 | case Transport::EnumType::Sendmail: |
315 | return new SendmailJob( t, this ); |
316 | case Transport::EnumType::Akonadi: |
317 | return new ResourceSendJob( t, this ); |
318 | } |
319 | Q_ASSERT( false ); |
320 | return 0; |
321 | } |
322 | |
323 | TransportJob *TransportManager::createTransportJob( const QString &transport ) |
324 | { |
325 | bool ok = false; |
326 | Transport *t = 0; |
327 | |
328 | int transportId = transport.toInt( &ok ); |
329 | if ( ok ) { |
330 | t = transportById( transportId ); |
331 | } |
332 | |
333 | if ( !t ) { |
334 | t = transportByName( transport, false ); |
335 | } |
336 | |
337 | if ( t ) { |
338 | return createTransportJob( t->id() ); |
339 | } |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | bool TransportManager::isEmpty() const |
345 | { |
346 | return d->transports.isEmpty(); |
347 | } |
348 | |
349 | QList<int> TransportManager::transportIds() const |
350 | { |
351 | QList<int> rv; |
352 | foreach ( Transport *t, d->transports ) { |
353 | rv << t->id(); |
354 | } |
355 | return rv; |
356 | } |
357 | |
358 | QStringList TransportManager::transportNames() const |
359 | { |
360 | QStringList rv; |
361 | foreach ( Transport *t, d->transports ) { |
362 | rv << t->name(); |
363 | } |
364 | return rv; |
365 | } |
366 | |
367 | QString TransportManager::defaultTransportName() const |
368 | { |
369 | Transport *t = transportById( d->defaultTransportId, false ); |
370 | if ( t ) { |
371 | return t->name(); |
372 | } |
373 | return QString(); |
374 | } |
375 | |
376 | int TransportManager::defaultTransportId() const |
377 | { |
378 | return d->defaultTransportId; |
379 | } |
380 | |
381 | void TransportManager::setDefaultTransport( int id ) |
382 | { |
383 | if ( id == d->defaultTransportId || !transportById( id, false ) ) { |
384 | return; |
385 | } |
386 | d->defaultTransportId = id; |
387 | d->writeConfig(); |
388 | } |
389 | |
390 | void TransportManager::removeTransport( int id ) |
391 | { |
392 | Transport *t = transportById( id, false ); |
393 | if ( !t ) { |
394 | return; |
395 | } |
396 | emit transportRemoved( t->id(), t->name() ); |
397 | |
398 | // Kill the resource, if Akonadi-type transport. |
399 | if ( t->type() == Transport::EnumType::Akonadi ) { |
400 | using namespace Akonadi; |
401 | const AgentInstance instance = AgentManager::self()->instance( t->host() ); |
402 | if ( !instance.isValid() ) { |
403 | kWarning() << "Could not find resource instance." ; |
404 | } |
405 | AgentManager::self()->removeInstance( instance ); |
406 | } |
407 | |
408 | d->transports.removeAll( t ); |
409 | d->validateDefault(); |
410 | QString group = t->currentGroup(); |
411 | delete t; |
412 | d->config->deleteGroup( group ); |
413 | d->writeConfig(); |
414 | |
415 | } |
416 | |
417 | void TransportManagerPrivate::readConfig() |
418 | { |
419 | QList<Transport *> oldTransports = transports; |
420 | transports.clear(); |
421 | |
422 | QRegExp re( QLatin1String( "^Transport (.+)$" ) ); |
423 | QStringList groups = config->groupList().filter( re ); |
424 | foreach ( const QString &s, groups ) { |
425 | if (re.indexIn( s ) == -1) |
426 | continue; |
427 | Transport *t = 0; |
428 | |
429 | // see if we happen to have that one already |
430 | foreach ( Transport *old, oldTransports ) { |
431 | if ( old->currentGroup() == QLatin1String( "Transport " ) + re.cap( 1 ) ) { |
432 | kDebug() << "reloading existing transport:" << s; |
433 | t = old; |
434 | t->d->passwordNeedsUpdateFromWallet = true; |
435 | t->readConfig(); |
436 | oldTransports.removeAll( old ); |
437 | break; |
438 | } |
439 | } |
440 | |
441 | if ( !t ) { |
442 | t = new Transport( re.cap( 1 ) ); |
443 | } |
444 | if ( t->id() <= 0 ) { |
445 | t->setId( createId() ); |
446 | t->writeConfig(); |
447 | } |
448 | transports.append( t ); |
449 | } |
450 | |
451 | qDeleteAll( oldTransports ); |
452 | oldTransports.clear(); |
453 | |
454 | // read default transport |
455 | KConfigGroup group( config, "General" ); |
456 | defaultTransportId = group.readEntry( "default-transport" , 0 ); |
457 | if ( defaultTransportId == 0 ) { |
458 | // migrated default transport contains the name instead |
459 | QString name = group.readEntry( "default-transport" , QString() ); |
460 | if ( !name.isEmpty() ) { |
461 | Transport *t = q->transportByName( name, false ); |
462 | if ( t ) { |
463 | defaultTransportId = t->id(); |
464 | writeConfig(); |
465 | } |
466 | } |
467 | } |
468 | validateDefault(); |
469 | migrateToWallet(); |
470 | q->loadPasswordsAsync(); |
471 | } |
472 | |
473 | void TransportManagerPrivate::writeConfig() |
474 | { |
475 | KConfigGroup group( config, "General" ); |
476 | group.writeEntry( "default-transport" , defaultTransportId ); |
477 | config->sync(); |
478 | q->emitChangesCommitted(); |
479 | } |
480 | |
481 | void TransportManagerPrivate::fillTypes() |
482 | { |
483 | Q_ASSERT( types.isEmpty() ); |
484 | |
485 | // SMTP. |
486 | { |
487 | TransportType type; |
488 | type.d->mType = Transport::EnumType::SMTP; |
489 | type.d->mName = i18nc( "@option SMTP transport" , "SMTP" ); |
490 | type.d->mDescription = i18n( "An SMTP server on the Internet" ); |
491 | types << type; |
492 | } |
493 | |
494 | // Sendmail. |
495 | { |
496 | TransportType type; |
497 | type.d->mType = Transport::EnumType::Sendmail; |
498 | type.d->mName = i18nc( "@option sendmail transport" , "Sendmail" ); |
499 | type.d->mDescription = i18n( "A local sendmail installation" ); |
500 | types << type; |
501 | } |
502 | |
503 | // All Akonadi resources with MailTransport capability. |
504 | { |
505 | using namespace Akonadi; |
506 | foreach ( const AgentType &atype, AgentManager::self()->types() ) { |
507 | // TODO probably the string "MailTransport" should be #defined somewhere |
508 | // and used like that in the resources (?) |
509 | if ( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { |
510 | TransportType type; |
511 | type.d->mType = Transport::EnumType::Akonadi; |
512 | type.d->mAgentType = atype; |
513 | type.d->mName = atype.name(); |
514 | type.d->mDescription = atype.description(); |
515 | types << type; |
516 | kDebug() << "Found Akonadi type" << atype.name(); |
517 | } |
518 | } |
519 | |
520 | // Watch for appearing and disappearing types. |
521 | QObject::connect( AgentManager::self(), SIGNAL(typeAdded(Akonadi::AgentType)), |
522 | q, SLOT(agentTypeAdded(Akonadi::AgentType)) ); |
523 | QObject::connect( AgentManager::self(), SIGNAL(typeRemoved(Akonadi::AgentType)), |
524 | q, SLOT(agentTypeRemoved(Akonadi::AgentType)) ); |
525 | } |
526 | |
527 | kDebug() << "Have SMTP, Sendmail, and" << types.count() - 2 << "Akonadi types." ; |
528 | } |
529 | |
530 | void TransportManager::emitChangesCommitted() |
531 | { |
532 | d->myOwnChange = true; // prevent us from reading our changes again |
533 | d->appliedChange = false; // but we have to read them at least once |
534 | emit transportsChanged(); |
535 | emit changesCommitted(); |
536 | } |
537 | |
538 | void TransportManagerPrivate::slotTransportsChanged() |
539 | { |
540 | if ( myOwnChange && appliedChange ) { |
541 | myOwnChange = false; |
542 | appliedChange = false; |
543 | return; |
544 | } |
545 | |
546 | kDebug(); |
547 | config->reparseConfiguration(); |
548 | // FIXME: this deletes existing transport objects! |
549 | readConfig(); |
550 | appliedChange = true; // to prevent recursion |
551 | emit q->transportsChanged(); |
552 | } |
553 | |
554 | int TransportManagerPrivate::createId() const |
555 | { |
556 | QList<int> usedIds; |
557 | foreach ( Transport *t, transports ) { |
558 | usedIds << t->id(); |
559 | } |
560 | usedIds << 0; // 0 is default for unknown |
561 | int newId; |
562 | do { |
563 | newId = KRandom::random(); |
564 | } while ( usedIds.contains( newId ) ); |
565 | return newId; |
566 | } |
567 | |
568 | KWallet::Wallet * TransportManager::wallet() |
569 | { |
570 | if ( d->wallet && d->wallet->isOpen() ) { |
571 | return d->wallet; |
572 | } |
573 | |
574 | if ( !Wallet::isEnabled() || d->walletOpenFailed ) { |
575 | return 0; |
576 | } |
577 | |
578 | WId window = 0; |
579 | if ( qApp->activeWindow() ) { |
580 | window = qApp->activeWindow()->winId(); |
581 | } else if ( !QApplication::topLevelWidgets().isEmpty() ) { |
582 | window = qApp->topLevelWidgets().first()->winId(); |
583 | } |
584 | |
585 | delete d->wallet; |
586 | d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window ); |
587 | |
588 | if ( !d->wallet ) { |
589 | d->walletOpenFailed = true; |
590 | return 0; |
591 | } |
592 | |
593 | d->prepareWallet(); |
594 | return d->wallet; |
595 | } |
596 | |
597 | void TransportManagerPrivate::prepareWallet() |
598 | { |
599 | if ( !wallet ) { |
600 | return; |
601 | } |
602 | if ( !wallet->hasFolder( WALLET_FOLDER ) ) { |
603 | wallet->createFolder( WALLET_FOLDER ); |
604 | } |
605 | wallet->setFolder( WALLET_FOLDER ); |
606 | } |
607 | |
608 | void TransportManager::loadPasswords() |
609 | { |
610 | foreach ( Transport *t, d->transports ) { |
611 | t->readPassword(); |
612 | } |
613 | |
614 | // flush the wallet queue |
615 | const QList<TransportJob*> copy = d->walletQueue; |
616 | d->walletQueue.clear(); |
617 | foreach ( TransportJob *job, copy ) { |
618 | job->start(); |
619 | } |
620 | |
621 | emit passwordsChanged(); |
622 | } |
623 | |
624 | void TransportManager::loadPasswordsAsync() |
625 | { |
626 | kDebug(); |
627 | |
628 | // check if there is anything to do at all |
629 | bool found = false; |
630 | foreach ( Transport *t, d->transports ) { |
631 | if ( !t->isComplete() ) { |
632 | found = true; |
633 | break; |
634 | } |
635 | } |
636 | if ( !found ) { |
637 | return; |
638 | } |
639 | |
640 | // async wallet opening |
641 | if ( !d->wallet && !d->walletOpenFailed ) { |
642 | WId window = 0; |
643 | if ( qApp->activeWindow() ) { |
644 | window = qApp->activeWindow()->winId(); |
645 | } else if ( !QApplication::topLevelWidgets().isEmpty() ) { |
646 | window = qApp->topLevelWidgets().first()->winId(); |
647 | } |
648 | |
649 | d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window, |
650 | Wallet::Asynchronous ); |
651 | if ( d->wallet ) { |
652 | connect( d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)) ); |
653 | d->walletAsyncOpen = true; |
654 | } else { |
655 | d->walletOpenFailed = true; |
656 | loadPasswords(); |
657 | } |
658 | return; |
659 | } |
660 | if ( d->wallet && !d->walletAsyncOpen ) { |
661 | loadPasswords(); |
662 | } |
663 | } |
664 | |
665 | void TransportManagerPrivate::slotWalletOpened( bool success ) |
666 | { |
667 | kDebug(); |
668 | walletAsyncOpen = false; |
669 | if ( !success ) { |
670 | walletOpenFailed = true; |
671 | delete wallet; |
672 | wallet = 0; |
673 | } else { |
674 | prepareWallet(); |
675 | } |
676 | q->loadPasswords(); |
677 | } |
678 | |
679 | void TransportManagerPrivate::validateDefault() |
680 | { |
681 | if ( !q->transportById( defaultTransportId, false ) ) { |
682 | if ( q->isEmpty() ) { |
683 | defaultTransportId = -1; |
684 | } else { |
685 | defaultTransportId = transports.first()->id(); |
686 | writeConfig(); |
687 | } |
688 | } |
689 | } |
690 | |
691 | void TransportManagerPrivate::migrateToWallet() |
692 | { |
693 | // check if we tried this already |
694 | static bool firstRun = true; |
695 | if ( !firstRun ) { |
696 | return; |
697 | } |
698 | firstRun = false; |
699 | |
700 | // check if we are the main instance |
701 | if ( !isMainInstance ) { |
702 | return; |
703 | } |
704 | |
705 | // check if migration is needed |
706 | QStringList names; |
707 | foreach ( Transport *t, transports ) { |
708 | if ( t->needsWalletMigration() ) { |
709 | names << t->name(); |
710 | } |
711 | } |
712 | if ( names.isEmpty() ) { |
713 | return; |
714 | } |
715 | |
716 | // ask user if he wants to migrate |
717 | int result = KMessageBox::questionYesNoList( |
718 | 0, |
719 | i18n( "The following mail transports store their passwords in an " |
720 | "unencrypted configuration file.\nFor security reasons, " |
721 | "please consider migrating these passwords to KWallet, the " |
722 | "KDE Wallet management tool,\nwhich stores sensitive data " |
723 | "for you in a strongly encrypted file.\n" |
724 | "Do you want to migrate your passwords to KWallet?" ), |
725 | names, i18n( "Question" ), |
726 | KGuiItem( i18n( "Migrate" ) ), KGuiItem( i18n( "Keep" ) ), |
727 | QString::fromLatin1( "WalletMigrate" ) ); |
728 | if ( result != KMessageBox::Yes ) { |
729 | return; |
730 | } |
731 | |
732 | // perform migration |
733 | foreach ( Transport *t, transports ) { |
734 | if ( t->needsWalletMigration() ) { |
735 | t->migrateToWallet(); |
736 | } |
737 | } |
738 | } |
739 | |
740 | void TransportManagerPrivate::dbusServiceUnregistered() |
741 | { |
742 | QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); |
743 | } |
744 | |
745 | void TransportManagerPrivate::agentTypeAdded( const Akonadi::AgentType &atype ) |
746 | { |
747 | using namespace Akonadi; |
748 | if ( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { |
749 | TransportType type; |
750 | type.d->mType = Transport::EnumType::Akonadi; |
751 | type.d->mAgentType = atype; |
752 | type.d->mName = atype.name(); |
753 | type.d->mDescription = atype.description(); |
754 | types << type; |
755 | kDebug() << "Added new Akonadi type" << atype.name(); |
756 | } |
757 | } |
758 | |
759 | void TransportManagerPrivate::agentTypeRemoved( const Akonadi::AgentType &atype ) |
760 | { |
761 | using namespace Akonadi; |
762 | foreach ( const TransportType &type, types ) { |
763 | if ( type.type() == Transport::EnumType::Akonadi && |
764 | type.agentType() == atype ) { |
765 | types.removeAll( type ); |
766 | kDebug() << "Removed Akonadi type" << atype.name(); |
767 | } |
768 | } |
769 | } |
770 | |
771 | void TransportManagerPrivate::jobResult( KJob *job ) |
772 | { |
773 | walletQueue.removeAll( static_cast<TransportJob*>( job ) ); |
774 | } |
775 | |
776 | #include "moc_transportmanager.cpp" |
777 | |