• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.9.3 API Reference
  • KDE Home
  • Contact Us
 

mailtransport

  • mailtransport
transport.cpp
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 "transport.h"
21 #include "transport_p.h"
22 #include "legacydecrypt.h"
23 #include "mailtransport_defs.h"
24 #include "transportmanager.h"
25 #include "transporttype_p.h"
26 
27 #include <QTimer>
28 
29 #include <KConfigGroup>
30 #include <KDebug>
31 #include <KLocalizedString>
32 #include <KMessageBox>
33 #include <KStringHandler>
34 #include <KWallet/Wallet>
35 
36 #include <akonadi/agentinstance.h>
37 #include <akonadi/agentmanager.h>
38 
39 using namespace MailTransport;
40 using namespace KWallet;
41 
42 Transport::Transport( const QString &cfgGroup ) :
43  TransportBase( cfgGroup ), d( new TransportPrivate )
44 {
45  kDebug() << cfgGroup;
46  d->passwordLoaded = false;
47  d->passwordDirty = false;
48  d->storePasswordInFile = false;
49  d->needsWalletMigration = false;
50  d->passwordNeedsUpdateFromWallet = false;
51  readConfig();
52 }
53 
54 Transport::~Transport()
55 {
56  delete d;
57 }
58 
59 bool Transport::isValid() const
60 {
61  return ( id() > 0 ) && !host().isEmpty() && port() <= 65536;
62 }
63 
64 QString Transport::password()
65 {
66  if ( !d->passwordLoaded && requiresAuthentication() && storePassword() &&
67  d->password.isEmpty() ) {
68  readPassword();
69  }
70  return d->password;
71 }
72 
73 void Transport::setPassword( const QString &passwd )
74 {
75  d->passwordLoaded = true;
76  if ( d->password == passwd ) {
77  return;
78  }
79  d->passwordDirty = true;
80  d->password = passwd;
81 }
82 
83 void Transport::forceUniqueName()
84 {
85  QStringList existingNames;
86  foreach ( Transport *t, TransportManager::self()->transports() ) {
87  if ( t->id() != id() ) {
88  existingNames << t->name();
89  }
90  }
91  int suffix = 1;
92  QString origName = name();
93  while ( existingNames.contains( name() ) ) {
94  setName( i18nc( "%1: name; %2: number appended to it to make "
95  "it unique among a list of names", "%1 #%2", origName, suffix ) );
96  ++suffix;
97  }
98 
99 }
100 
101 void Transport::updatePasswordState()
102 {
103  Transport *original = TransportManager::self()->transportById( id(), false );
104  if ( original == this ) {
105  kWarning() << "Tried to update password state of non-cloned transport.";
106  return;
107  }
108  if ( original ) {
109  d->password = original->d->password;
110  d->passwordLoaded = original->d->passwordLoaded;
111  d->passwordDirty = original->d->passwordDirty;
112  } else {
113  kWarning() << "Transport with this ID not managed by transport manager.";
114  }
115 }
116 
117 bool Transport::isComplete() const
118 {
119  return !requiresAuthentication() || !storePassword() || d->passwordLoaded;
120 }
121 
122 QString Transport::authenticationTypeString() const
123 {
124  return Transport::authenticationTypeString( authenticationType() );
125 }
126 
127 QString Transport::authenticationTypeString( int type )
128 {
129  switch ( type ) {
130  case EnumAuthenticationType::LOGIN:
131  return QLatin1String( "LOGIN" );
132  case EnumAuthenticationType::PLAIN:
133  return QLatin1String( "PLAIN" );
134  case EnumAuthenticationType::CRAM_MD5:
135  return QLatin1String( "CRAM-MD5" );
136  case EnumAuthenticationType::DIGEST_MD5:
137  return QLatin1String( "DIGEST-MD5" );
138  case EnumAuthenticationType::NTLM:
139  return QLatin1String( "NTLM" );
140  case EnumAuthenticationType::GSSAPI:
141  return QLatin1String( "GSSAPI" );
142  case EnumAuthenticationType::CLEAR:
143  return i18nc( "Authentication method", "Clear text" );
144  case EnumAuthenticationType::APOP:
145  return QLatin1String( "APOP" );
146  case EnumAuthenticationType::ANONYMOUS:
147  return i18nc( "Authentication method", "Anonymous" );
148  }
149  Q_ASSERT( false );
150  return QString();
151 }
152 
153 void Transport::usrReadConfig()
154 {
155  TransportBase::usrReadConfig();
156 
157  setHost( host().trimmed() );
158 
159  if ( d->oldName.isEmpty() ) {
160  d->oldName = name();
161  }
162 
163  // Set TransportType.
164  {
165  using namespace Akonadi;
166  d->transportType = TransportType();
167  d->transportType.d->mType = type();
168  kDebug() << "type" << type();
169  if ( type() == EnumType::Akonadi ) {
170  const AgentInstance instance = AgentManager::self()->instance( host() );
171  if ( !instance.isValid() ) {
172  kWarning() << "Akonadi transport with invalid resource instance.";
173  }
174  d->transportType.d->mAgentType = instance.type();
175  kDebug() << "agent type" << instance.type().name() << "id" << instance.type().identifier();
176  }
177  // Now we have the type and possibly agentType. Get the name, description
178  // etc. from TransportManager.
179  const TransportType::List &types = TransportManager::self()->types();
180  int index = types.indexOf( d->transportType );
181  if ( index != -1 ) {
182  d->transportType = types[ index ];
183  } else {
184  kWarning() << "Type unknown to manager.";
185  d->transportType.d->mName = i18nc( "An unknown transport type", "Unknown" );
186  }
187  }
188 
189  // we have everything we need
190  if ( !storePassword() ) {
191  return;
192  }
193 
194  if ( d->passwordLoaded ) {
195  if ( d->passwordNeedsUpdateFromWallet ) {
196  d->passwordNeedsUpdateFromWallet = false;
197  // read password if wallet is open, defer otherwise
198  if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) {
199  // Don't read the password right away because this can lead
200  // to reentrancy problems in KDBusServiceStarter when an application
201  // run in Kontact creates the transports (due to a QEventLoop in the
202  // synchronous KWallet openWallet call).
203  QTimer::singleShot( 0, this, SLOT(readPassword()) );
204  } else {
205  d->passwordLoaded = false;
206  }
207  }
208 
209  return;
210  }
211 
212  // try to find a password in the config file otherwise
213  KConfigGroup group( config(), currentGroup() );
214  if ( group.hasKey( "password" ) ) {
215  d->password = KStringHandler::obscure( group.readEntry( "password" ) );
216  } else if ( group.hasKey( "password-kmail" ) ) {
217  d->password = Legacy::decryptKMail( group.readEntry( "password-kmail" ) );
218  } else if ( group.hasKey( "password-knode" ) ) {
219  d->password = Legacy::decryptKNode( group.readEntry( "password-knode" ) );
220  }
221 
222  if ( !d->password.isEmpty() ) {
223  d->passwordLoaded = true;
224  if ( Wallet::isEnabled() ) {
225  d->needsWalletMigration = true;
226  } else {
227  d->storePasswordInFile = true;
228  }
229  } else {
230  // read password if wallet is open, defer otherwise
231  if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) {
232  // Don't read the password right away because this can lead
233  // to reentrancy problems in KDBusServiceStarter when an application
234  // run in Kontact creates the transports (due to a QEventLoop in the
235  // synchronous KWallet openWallet call).
236  QTimer::singleShot( 0, this, SLOT(readPassword()) );
237  }
238  }
239 }
240 
241 void Transport::usrWriteConfig()
242 {
243  if ( requiresAuthentication() && storePassword() && d->passwordDirty ) {
244  Wallet *wallet = TransportManager::self()->wallet();
245  if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) {
246  // wallet saving failed, ask if we should store in the config file instead
247  if ( d->storePasswordInFile || KMessageBox::warningYesNo(
248  0,
249  i18n( "KWallet is not available. It is strongly recommended to use "
250  "KWallet for managing your passwords.\n"
251  "However, the password can be stored in the configuration "
252  "file instead. The password is stored in an obfuscated format, "
253  "but should not be considered secure from decryption efforts "
254  "if access to the configuration file is obtained.\n"
255  "Do you want to store the password for server '%1' in the "
256  "configuration file?", name() ),
257  i18n( "KWallet Not Available" ),
258  KGuiItem( i18n( "Store Password" ) ),
259  KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) {
260  // write to config file
261  KConfigGroup group( config(), currentGroup() );
262  group.writeEntry( "password", KStringHandler::obscure( d->password ) );
263  d->storePasswordInFile = true;
264  }
265  }
266  d->passwordDirty = false;
267  }
268 
269  TransportBase::usrWriteConfig();
270  TransportManager::self()->emitChangesCommitted();
271  if ( name() != d->oldName ) {
272  emit TransportManager::self()->transportRenamed( id(), d->oldName, name() );
273  d->oldName = name();
274  }
275 }
276 
277 void Transport::readPassword()
278 {
279  // no need to load a password if the account doesn't require auth
280  if ( !requiresAuthentication() ) {
281  return;
282  }
283  d->passwordLoaded = true;
284 
285  // check whether there is a chance to find our password at all
286  if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) ||
287  Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER,
288  QString::number( id() ) ) ) {
289  // try migrating password from kmail
290  if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) ||
291  Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER,
292  QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) {
293  return;
294  }
295  kDebug() << "migrating password from kmail wallet";
296  KWallet::Wallet *wallet = TransportManager::self()->wallet();
297  if ( wallet ) {
298  QString pwd;
299  wallet->setFolder( KMAIL_WALLET_FOLDER );
300  if ( wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), pwd ) == 0 ) {
301  setPassword( pwd );
302  writeConfig();
303  } else {
304  d->password.clear();
305  d->passwordLoaded = false;
306  }
307  wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) );
308  wallet->setFolder( WALLET_FOLDER );
309  }
310  return;
311  }
312 
313  // finally try to open the wallet and read the password
314  KWallet::Wallet *wallet = TransportManager::self()->wallet();
315  if ( wallet ) {
316  QString pwd;
317  if ( wallet->readPassword( QString::number( id() ), pwd ) == 0 ) {
318  setPassword( pwd );
319  } else {
320  d->password.clear();
321  d->passwordLoaded = false;
322  }
323  }
324 }
325 
326 bool Transport::needsWalletMigration() const
327 {
328  return d->needsWalletMigration;
329 }
330 
331 void Transport::migrateToWallet()
332 {
333  kDebug() << "migrating" << id() << "to wallet";
334  d->needsWalletMigration = false;
335  KConfigGroup group( config(), currentGroup() );
336  group.deleteEntry( "password" );
337  group.deleteEntry( "password-kmail" );
338  group.deleteEntry( "password-knode" );
339  d->passwordDirty = true;
340  d->storePasswordInFile = false;
341  writeConfig();
342 }
343 
344 Transport *Transport::clone() const
345 {
346  QString id = currentGroup().mid( 10 );
347  return new Transport( id );
348 }
349 
350 TransportType Transport::transportType() const
351 {
352  if ( !d->transportType.isValid() ) {
353  kWarning() << "Invalid transport type.";
354  }
355  return d->transportType;
356 }
357 
358 void Transport::setTransportType( const TransportType &type )
359 {
360  Q_ASSERT( type.isValid() );
361  d->transportType = type;
362  setType( type.type() );
363 }
364 
365 #include "transport.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Nov 26 2012 16:47:55 by doxygen 1.8.1.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

mailtransport

Skip menu "mailtransport"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.9.3 API Reference

Skip menu "kdepimlibs-4.9.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal