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

mailtransport

  • sources
  • kde-4.14
  • kdepimlibs
  • 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  const QString storePassword = d->password;
236  Wallet *wallet = TransportManager::self()->wallet();
237  if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) {
238  // wallet saving failed, ask if we should store in the config file instead
239  if ( d->storePasswordInFile || KMessageBox::warningYesNo(
240  0,
241  i18n( "KWallet is not available. It is strongly recommended to use "
242  "KWallet for managing your passwords.\n"
243  "However, the password can be stored in the configuration "
244  "file instead. The password is stored in an obfuscated format, "
245  "but should not be considered secure from decryption efforts "
246  "if access to the configuration file is obtained.\n"
247  "Do you want to store the password for server '%1' in the "
248  "configuration file?", name() ),
249  i18n( "KWallet Not Available" ),
250  KGuiItem( i18n( "Store Password" ) ),
251  KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) {
252  // write to config file
253  KConfigGroup group( config(), currentGroup() );
254  group.writeEntry( "password", KStringHandler::obscure( storePassword ) );
255  d->storePasswordInFile = true;
256  }
257  }
258  d->passwordDirty = false;
259  }
260 
261  TransportBase::usrWriteConfig();
262  TransportManager::self()->emitChangesCommitted();
263  if ( name() != d->oldName ) {
264  emit TransportManager::self()->transportRenamed( id(), d->oldName, name() );
265  d->oldName = name();
266  }
267 }
268 
269 void Transport::readPassword()
270 {
271  // no need to load a password if the account doesn't require auth
272  if ( !requiresAuthentication() ) {
273  return;
274  }
275  d->passwordLoaded = true;
276 
277  // check whether there is a chance to find our password at all
278  if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) ||
279  Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER,
280  QString::number( id() ) ) ) {
281  // try migrating password from kmail
282  if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) ||
283  Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER,
284  QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) {
285  return;
286  }
287  kDebug() << "migrating password from kmail wallet";
288  KWallet::Wallet *wallet = TransportManager::self()->wallet();
289  if ( wallet ) {
290  QString pwd;
291  wallet->setFolder( KMAIL_WALLET_FOLDER );
292  if ( wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), pwd ) == 0 ) {
293  setPassword( pwd );
294  writeConfig();
295  } else {
296  d->password.clear();
297  d->passwordLoaded = false;
298  }
299  wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) );
300  wallet->setFolder( WALLET_FOLDER );
301  }
302  return;
303  }
304 
305  // finally try to open the wallet and read the password
306  KWallet::Wallet *wallet = TransportManager::self()->wallet();
307  if ( wallet ) {
308  QString pwd;
309  if ( wallet->readPassword( QString::number( id() ), pwd ) == 0 ) {
310  setPassword( pwd );
311  } else {
312  d->password.clear();
313  d->passwordLoaded = false;
314  }
315  }
316 }
317 
318 bool Transport::needsWalletMigration() const
319 {
320  return d->needsWalletMigration;
321 }
322 
323 void Transport::migrateToWallet()
324 {
325  kDebug() << "migrating" << id() << "to wallet";
326  d->needsWalletMigration = false;
327  KConfigGroup group( config(), currentGroup() );
328  group.deleteEntry( "password" );
329  group.deleteEntry( "password-kmail" );
330  group.deleteEntry( "password-knode" );
331  d->passwordDirty = true;
332  d->storePasswordInFile = false;
333  writeConfig();
334 }
335 
336 Transport *Transport::clone() const
337 {
338  QString id = currentGroup().mid( 10 );
339  return new Transport( id );
340 }
341 
342 TransportType Transport::transportType() const
343 {
344  if ( !d->transportType.isValid() ) {
345  kWarning() << "Invalid transport type.";
346  }
347  return d->transportType;
348 }
349 
350 void Transport::setTransportType( const TransportType &type )
351 {
352  Q_ASSERT( type.isValid() );
353  d->transportType = type;
354  setType( type.type() );
355 }
356 
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:323
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:162
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:574
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
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
MailTransport::Transport::setTransportType
void setTransportType(const TransportType &type)
Sets the type of this transport.
Definition: transport.cpp:350
QList::indexOf
int indexOf(const T &value, int from) const
QString::clear
void clear()
QString::number
QString number(int n, int base)
TransportPrivate
Private class that helps to provide binary compatibility between releases.
Definition: transport_p.h:29
QString::isEmpty
bool isEmpty() const
MailTransport::Transport::authenticationTypeString
QString authenticationTypeString() const
Returns a string representation of the authentication type.
Definition: transport.cpp:122
QString
QList
MailTransport::Transport::needsWalletMigration
bool needsWalletMigration() const
Returns true if the password was not stored in the wallet.
Definition: transport.cpp:318
QStringList
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's legacy encryption.
Definition: legacydecrypt.cpp:29
QString::mid
QString mid(int position, int n) const
QLatin1String
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:336
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.
QString::fromLatin1
QString fromLatin1(const char *str, int size)
MailTransport::Legacy::decryptKNode
static QString decryptKNode(const QString &data)
Read data encrypted using KNode'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:171
MailTransport::Transport::~Transport
virtual ~Transport()
Destructor.
Definition: transport.cpp:54
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
MailTransport::TransportManager::types
TransportType::List types() const
Returns a list of all available transport types.
Definition: transportmanager.cpp:203
QTimer::singleShot
singleShot
MailTransport::Transport::transportType
TransportType transportType() const
Returns the type of this transport.
Definition: transport.cpp:342
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:48 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs 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

Search



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