• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.11.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  }
230 }
231 
232 void Transport::usrWriteConfig()
233 {
234  if ( requiresAuthentication() && storePassword() && d->passwordDirty ) {
235  Wallet *wallet = TransportManager::self()->wallet();
236  if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) {
237  // wallet saving failed, ask if we should store in the config file instead
238  if ( d->storePasswordInFile || KMessageBox::warningYesNo(
239  0,
240  i18n( "KWallet is not available. It is strongly recommended to use "
241  "KWallet for managing your passwords.\n"
242  "However, the password can be stored in the configuration "
243  "file instead. The password is stored in an obfuscated format, "
244  "but should not be considered secure from decryption efforts "
245  "if access to the configuration file is obtained.\n"
246  "Do you want to store the password for server '%1' in the "
247  "configuration file?", name() ),
248  i18n( "KWallet Not Available" ),
249  KGuiItem( i18n( "Store Password" ) ),
250  KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) {
251  // write to config file
252  KConfigGroup group( config(), currentGroup() );
253  group.writeEntry( "password", KStringHandler::obscure( d->password ) );
254  d->storePasswordInFile = true;
255  }
256  }
257  d->passwordDirty = false;
258  }
259 
260  TransportBase::usrWriteConfig();
261  TransportManager::self()->emitChangesCommitted();
262  if ( name() != d->oldName ) {
263  emit TransportManager::self()->transportRenamed( id(), d->oldName, name() );
264  d->oldName = name();
265  }
266 }
267 
268 void Transport::readPassword()
269 {
270  // no need to load a password if the account doesn't require auth
271  if ( !requiresAuthentication() ) {
272  return;
273  }
274  d->passwordLoaded = true;
275 
276  // check whether there is a chance to find our password at all
277  if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) ||
278  Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER,
279  QString::number( id() ) ) ) {
280  // try migrating password from kmail
281  if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) ||
282  Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER,
283  QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) {
284  return;
285  }
286  kDebug() << "migrating password from kmail wallet";
287  KWallet::Wallet *wallet = TransportManager::self()->wallet();
288  if ( wallet ) {
289  QString pwd;
290  wallet->setFolder( KMAIL_WALLET_FOLDER );
291  if ( wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), pwd ) == 0 ) {
292  setPassword( pwd );
293  writeConfig();
294  } else {
295  d->password.clear();
296  d->passwordLoaded = false;
297  }
298  wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) );
299  wallet->setFolder( WALLET_FOLDER );
300  }
301  return;
302  }
303 
304  // finally try to open the wallet and read the password
305  KWallet::Wallet *wallet = TransportManager::self()->wallet();
306  if ( wallet ) {
307  QString pwd;
308  if ( wallet->readPassword( QString::number( id() ), pwd ) == 0 ) {
309  setPassword( pwd );
310  } else {
311  d->password.clear();
312  d->passwordLoaded = false;
313  }
314  }
315 }
316 
317 bool Transport::needsWalletMigration() const
318 {
319  return d->needsWalletMigration;
320 }
321 
322 void Transport::migrateToWallet()
323 {
324  kDebug() << "migrating" << id() << "to wallet";
325  d->needsWalletMigration = false;
326  KConfigGroup group( config(), currentGroup() );
327  group.deleteEntry( "password" );
328  group.deleteEntry( "password-kmail" );
329  group.deleteEntry( "password-knode" );
330  d->passwordDirty = true;
331  d->storePasswordInFile = false;
332  writeConfig();
333 }
334 
335 Transport *Transport::clone() const
336 {
337  QString id = currentGroup().mid( 10 );
338  return new Transport( id );
339 }
340 
341 TransportType Transport::transportType() const
342 {
343  if ( !d->transportType.isValid() ) {
344  kWarning() << "Invalid transport type.";
345  }
346  return d->transportType;
347 }
348 
349 void Transport::setTransportType( const TransportType &type )
350 {
351  Q_ASSERT( type.isValid() );
352  d->transportType = type;
353  setType( type.type() );
354 }
355 
MailTransport::TransportType
A representation of a transport type.
Definition: transporttype.h:51
MailTransport::Transport::migrateToWallet
void migrateToWallet()
Try to migrate the password from the config file to the wallet.
Definition: transport.cpp:322
MailTransport::Transport::isComplete
bool isComplete() const
Returns true if all settings have been loaded.
Definition: transport.cpp:117
MailTransport::TransportManager::self
static TransportManager * self()
Returns the TransportManager instance.
Definition: transportmanager.cpp:163
MailTransport::Transport::setPassword
void setPassword(const QString &passwd)
Sets the password of this transport.
Definition: transport.cpp:73
MailTransport::TransportManager::wallet
KWallet::Wallet * wallet()
Returns a pointer to an open wallet if available, 0 otherwise.
Definition: transportmanager.cpp:568
MailTransport::TransportType::isValid
bool isValid() const
Returns whether the transport type is valid.
Definition: transporttype.cpp:59
MailTransport::Transport::password
QString password()
Returns the password of this transport.
Definition: transport.cpp:64
MailTransport::Transport::setTransportType
void setTransportType(const TransportType &type)
Sets the type of this transport.
Definition: transport.cpp:349
TransportPrivate
Private class that helps to provide binary compatibility between releases.
Definition: transport_p.h:29
MailTransport::Transport::authenticationTypeString
QString authenticationTypeString() const
Returns a string representation of the authentication type.
Definition: transport.cpp:122
MailTransport::Transport::needsWalletMigration
bool needsWalletMigration() const
Returns true if the password was not stored in the wallet.
Definition: transport.cpp:317
MailTransport::Transport::isValid
bool isValid() const
Returns true if this transport is valid, ie.
Definition: transport.cpp:59
MailTransport::Legacy::decryptKMail
static QString decryptKMail(const QString &data)
Read data encrypted using KMail&#39;s legacy encryption.
Definition: legacydecrypt.cpp:29
MailTransport::TransportManager::transportRenamed
void transportRenamed(int id, const QString &oldName, const QString &newName)
Emitted when a transport has been renamed.
MailTransport::Transport::clone
Transport * clone() const
Returns a deep copy of this Transport object which will no longer be automatically updated...
Definition: transport.cpp:335
MailTransport::Transport::forceUniqueName
void forceUniqueName()
Makes sure the transport has a unique name.
Definition: transport.cpp:83
mailtransport_defs.h
Internal file containing constant definitions etc.
MailTransport::TransportType::List
QList< TransportType > List
Describes a list of transport types.
Definition: transporttype.h:62
MailTransport::Legacy::decryptKNode
static QString decryptKNode(const QString &data)
Read data encrypted using KNode&#39;s legacy encryption.
Definition: legacydecrypt.cpp:34
MailTransport::Transport::updatePasswordState
void updatePasswordState()
This function synchronizes the password of this transport with the password of the transport with the...
Definition: transport.cpp:101
MailTransport::TransportType::type
TransportBase::EnumType::type type() const
Definition: transporttype.cpp:71
MailTransport::Transport::Transport
Transport(const QString &cfgGroup)
Creates a Transport object.
Definition: transport.cpp:42
MailTransport::Transport
Represents the settings of a specific mail transport.
Definition: transport.h:50
MailTransport::TransportManager::transportById
Transport * transportById(int id, bool def=true) const
Returns the Transport object with the given id.
Definition: transportmanager.cpp:172
MailTransport::Transport::~Transport
virtual ~Transport()
Destructor.
Definition: transport.cpp:54
MailTransport::TransportManager::types
TransportType::List types() const
Returns a list of all available transport types.
Definition: transportmanager.cpp:204
MailTransport::Transport::transportType
TransportType transportType() const
Returns the type of this transport.
Definition: transport.cpp:341
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Nov 26 2013 09:03:01 by doxygen 1.8.5 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.11.3 API Reference

Skip menu "kdepimlibs-4.11.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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