• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

kpasswdserver.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of the KDE Password Server
00003 
00004     Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
00005     Copyright (C) 2005 David Faure (faure@kde.org)
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License
00009     version 2 as published by the Free Software Foundation.
00010 
00011     This software is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this library; see the file COPYING. If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 //----------------------------------------------------------------------------
00022 //
00023 // KDE Password Server
00024 // $Id: kpasswdserver.cpp 849216 2008-08-19 09:08:55Z duffeck $
00025 
00026 #include "kpasswdserver.h"
00027 
00028 #include <time.h>
00029 
00030 #include <qtimer.h>
00031 
00032 #include <kapplication.h>
00033 #include <klocale.h>
00034 #include <kmessagebox.h>
00035 #include <kdebug.h>
00036 #include <kio/passdlg.h>
00037 #include <kwallet.h>
00038 
00039 #include "config.h"
00040 #ifdef Q_WS_X11
00041 #include <X11/X.h>
00042 #include <X11/Xlib.h>
00043 #endif
00044 
00045 extern "C" {
00046     KDE_EXPORT KDEDModule *create_kpasswdserver(const QCString &name)
00047     {
00048        return new KPasswdServer(name);
00049     }
00050 }
00051 
00052 int
00053 KPasswdServer::AuthInfoList::compareItems(QPtrCollection::Item n1, QPtrCollection::Item n2)
00054 {
00055    if (!n1 || !n2)
00056       return 0;
00057 
00058    AuthInfo *i1 = (AuthInfo *) n1;
00059    AuthInfo *i2 = (AuthInfo *) n2;
00060 
00061    int l1 = i1->directory.length();
00062    int l2 = i2->directory.length();
00063 
00064    if (l1 > l2)
00065       return -1;
00066    if (l1 < l2)
00067       return 1;
00068    return 0;
00069 }
00070 
00071 
00072 KPasswdServer::KPasswdServer(const QCString &name)
00073  : KDEDModule(name)
00074 {
00075     m_authDict.setAutoDelete(true);
00076     m_authPending.setAutoDelete(true);
00077     m_seqNr = 0;
00078     m_wallet = 0;
00079     connect(this, SIGNAL(windowUnregistered(long)),
00080             this, SLOT(removeAuthForWindowId(long)));
00081 }
00082 
00083 KPasswdServer::~KPasswdServer()
00084 {
00085     delete m_wallet;
00086 }
00087 
00088 // Helper - returns the wallet key to use for read/store/checking for existence.
00089 static QString makeWalletKey( const QString& key, const QString& realm )
00090 {
00091     return realm.isEmpty() ? key : key + '-' + realm;
00092 }
00093 
00094 // Helper for storeInWallet/readFromWallet
00095 static QString makeMapKey( const char* key, int entryNumber )
00096 {
00097     QString str = QString::fromLatin1( key );
00098     if ( entryNumber > 1 )
00099         str += "-" + QString::number( entryNumber );
00100     return str;
00101 }
00102 
00103 static bool storeInWallet( KWallet::Wallet* wallet, const QString& key, const KIO::AuthInfo &info )
00104 {
00105     if ( !wallet->hasFolder( KWallet::Wallet::PasswordFolder() ) )
00106         if ( !wallet->createFolder( KWallet::Wallet::PasswordFolder() ) )
00107             return false;
00108     wallet->setFolder( KWallet::Wallet::PasswordFolder() );
00109     // Before saving, check if there's already an entry with this login.
00110     // If so, replace it (with the new password). Otherwise, add a new entry.
00111     typedef QMap<QString,QString> Map;
00112     int entryNumber = 1;
00113     Map map;
00114     QString walletKey = makeWalletKey( key, info.realmValue );
00115     kdDebug(130) << "storeInWallet: walletKey=" << walletKey << "  reading existing map" << endl;
00116     if ( wallet->readMap( walletKey, map ) == 0 ) {
00117         Map::ConstIterator end = map.end();
00118         Map::ConstIterator it = map.find( "login" );
00119         while ( it != end ) {
00120             if ( it.data() == info.username ) {
00121                 break; // OK, overwrite this entry
00122             }
00123             it = map.find( QString( "login-" ) + QString::number( ++entryNumber ) );
00124         }
00125         // If no entry was found, create a new entry - entryNumber is set already.
00126     }
00127     const QString loginKey = makeMapKey( "login", entryNumber );
00128     const QString passwordKey = makeMapKey( "password", entryNumber );
00129     kdDebug(130) << "storeInWallet: writing to " << loginKey << "," << passwordKey << endl;
00130     // note the overwrite=true by default
00131     map.insert( loginKey, info.username );
00132     map.insert( passwordKey, info.password );
00133     wallet->writeMap( walletKey, map );
00134     return true;
00135 }
00136 
00137 
00138 static bool readFromWallet( KWallet::Wallet* wallet, const QString& key, const QString& realm, QString& username, QString& password, bool userReadOnly, QMap<QString,QString>& knownLogins )
00139 {
00140     //kdDebug(130) << "readFromWallet: key=" << key << " username=" << username << " password=" /*<< password*/ << " userReadOnly=" << userReadOnly << " realm=" << realm << endl;
00141     if ( wallet->hasFolder( KWallet::Wallet::PasswordFolder() ) )
00142     {
00143         wallet->setFolder( KWallet::Wallet::PasswordFolder() );
00144 
00145         QMap<QString,QString> map;
00146         if ( wallet->readMap( makeWalletKey( key, realm ), map ) == 0 )
00147         {
00148             typedef QMap<QString,QString> Map;
00149             int entryNumber = 1;
00150             Map::ConstIterator end = map.end();
00151             Map::ConstIterator it = map.find( "login" );
00152             while ( it != end ) {
00153                 //kdDebug(130) << "readFromWallet: found " << it.key() << "=" << it.data() << endl;
00154                 Map::ConstIterator pwdIter = map.find( makeMapKey( "password", entryNumber ) );
00155                 if ( pwdIter != end ) {
00156                     if ( it.data() == username )
00157                         password = pwdIter.data();
00158                     knownLogins.insert( it.data(), pwdIter.data() );
00159                 }
00160 
00161                 it = map.find( QString( "login-" ) + QString::number( ++entryNumber ) );
00162             }
00163             //kdDebug(130) << knownLogins.count() << " known logins" << endl;
00164 
00165             if ( !userReadOnly && !knownLogins.isEmpty() && username.isEmpty() ) {
00166                 // Pick one, any one...
00167                 username = knownLogins.begin().key();
00168                 password = knownLogins.begin().data();
00169                 //kdDebug(130) << "readFromWallet: picked the first one : " << username << endl;
00170             }
00171 
00172             return true;
00173         }
00174     }
00175     return false;
00176 }
00177 
00178 KIO::AuthInfo
00179 KPasswdServer::checkAuthInfo(KIO::AuthInfo info, long windowId)
00180 {
00181     return checkAuthInfo(info, windowId, 0);
00182 }
00183 
00184 KIO::AuthInfo
00185 KPasswdServer::checkAuthInfo(KIO::AuthInfo info, long windowId, unsigned long usertime)
00186 {
00187     kdDebug(130) << "KPasswdServer::checkAuthInfo: User= " << info.username
00188               << ", WindowId = " << windowId << endl;
00189     if( usertime != 0 )
00190         kapp->updateUserTimestamp( usertime );
00191 
00192     QString key = createCacheKey(info);
00193 
00194     Request *request = m_authPending.first();
00195     QString path2 = info.url.directory(false, false);
00196     for(; request; request = m_authPending.next())
00197     {
00198        if (request->key != key)
00199            continue;
00200 
00201        if (info.verifyPath)
00202        {
00203           QString path1 = request->info.url.directory(false, false);
00204           if (!path2.startsWith(path1))
00205              continue;
00206        }
00207 
00208        request = new Request;
00209        request->client = callingDcopClient();
00210        request->transaction = request->client->beginTransaction();
00211        request->key = key;
00212        request->info = info;
00213        m_authWait.append(request);
00214        return info;
00215     }
00216 
00217     const AuthInfo *result = findAuthInfoItem(key, info);
00218     if (!result || result->isCanceled)
00219     {
00220        if (!result &&
00221            (info.username.isEmpty() || info.password.isEmpty()) &&
00222            !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(),
00223                                              KWallet::Wallet::PasswordFolder(), makeWalletKey(key, info.realmValue)))
00224        {
00225           QMap<QString, QString> knownLogins;
00226           if (openWallet(windowId)) {
00227               if (readFromWallet(m_wallet, key, info.realmValue, info.username, info.password,
00228                              info.readOnly, knownLogins))
00229           {
00230               info.setModified(true);
00231               return info;
00232           }
00233       }
00234        }
00235 
00236        info.setModified(false);
00237        return info;
00238     }
00239 
00240     updateAuthExpire(key, result, windowId, false);
00241 
00242     return copyAuthInfo(result);
00243 }
00244 
00245 KIO::AuthInfo
00246 KPasswdServer::queryAuthInfo(KIO::AuthInfo info, QString errorMsg, long windowId, long seqNr)
00247 {
00248     return queryAuthInfo(info, errorMsg, windowId, seqNr, 0 );
00249 }
00250 
00251 KIO::AuthInfo
00252 KPasswdServer::queryAuthInfo(KIO::AuthInfo info, QString errorMsg, long windowId, long seqNr, unsigned long usertime)
00253 {
00254     kdDebug(130) << "KPasswdServer::queryAuthInfo: User= " << info.username
00255               << ", Message= " << info.prompt << ", WindowId = " << windowId << endl;
00256     if ( !info.password.isEmpty() ) // should we really allow the caller to pre-fill the password?
00257         kdDebug(130) <<  "password was set by caller" << endl;
00258     if( usertime != 0 )
00259         kapp->updateUserTimestamp( usertime );
00260 
00261     QString key = createCacheKey(info);
00262     Request *request = new Request;
00263     request->client = callingDcopClient();
00264     request->transaction = request->client->beginTransaction();
00265     request->key = key;
00266     request->info = info;
00267     request->windowId = windowId;
00268     request->seqNr = seqNr;
00269     if (errorMsg == "<NoAuthPrompt>")
00270     {
00271        request->errorMsg = QString::null;
00272        request->prompt = false;
00273     }
00274     else
00275     {
00276        request->errorMsg = errorMsg;
00277        request->prompt = true;
00278     }
00279     m_authPending.append(request);
00280 
00281     if (m_authPending.count() == 1)
00282        QTimer::singleShot(0, this, SLOT(processRequest()));
00283 
00284     return info;
00285 }
00286 
00287 void
00288 KPasswdServer::addAuthInfo(KIO::AuthInfo info, long windowId)
00289 {
00290     kdDebug(130) << "KPasswdServer::addAuthInfo: User= " << info.username
00291               << ", RealmValue= " << info.realmValue << ", WindowId = " << windowId << endl;
00292     QString key = createCacheKey(info);
00293 
00294     m_seqNr++;
00295 
00296     addAuthInfoItem(key, info, windowId, m_seqNr, false);
00297 }
00298 
00299 bool
00300 KPasswdServer::openWallet( WId windowId )
00301 {
00302     if ( m_wallet && !m_wallet->isOpen() ) { // forced closed
00303         delete m_wallet;
00304         m_wallet = 0;
00305     }
00306     if ( !m_wallet )
00307         m_wallet = KWallet::Wallet::openWallet(
00308             KWallet::Wallet::NetworkWallet(), windowId );
00309     return m_wallet != 0;
00310 }
00311 
00312 void
00313 KPasswdServer::processRequest()
00314 {
00315     Request *request = m_authPending.first();
00316     if (!request)
00317        return;
00318 
00319     KIO::AuthInfo &info = request->info;
00320 
00321     kdDebug(130) << "KPasswdServer::processRequest: User= " << info.username
00322               << ", Message= " << info.prompt << endl;
00323     const AuthInfo *result = findAuthInfoItem(request->key, request->info);
00324 
00325     if (result && (request->seqNr < result->seqNr))
00326     {
00327         kdDebug(130) << "KPasswdServer::processRequest: auto retry!" << endl;
00328         if (result->isCanceled)
00329         {
00330            info.setModified(false);
00331         }
00332         else
00333         {
00334            updateAuthExpire(request->key, result, request->windowId, false);
00335            info = copyAuthInfo(result);
00336         }
00337     }
00338     else
00339     {
00340         m_seqNr++;
00341         bool askPw = request->prompt;
00342         if (result && !info.username.isEmpty() &&
00343             !request->errorMsg.isEmpty())
00344         {
00345            QString prompt = request->errorMsg;
00346            prompt += i18n("  Do you want to retry?");
00347            int dlgResult = KMessageBox::warningContinueCancelWId(request->windowId, prompt,
00348                            i18n("Authentication"), i18n("Retry"));
00349            if (dlgResult != KMessageBox::Continue)
00350               askPw = false;
00351         }
00352 
00353         int dlgResult = QDialog::Rejected;
00354         if (askPw)
00355         {
00356             QString username = info.username;
00357             QString password = info.password;
00358             bool hasWalletData = false;
00359             QMap<QString, QString> knownLogins;
00360 
00361             if ( ( username.isEmpty() || password.isEmpty() )
00362                 && !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::PasswordFolder(), makeWalletKey( request->key, info.realmValue )) )
00363             {
00364                 // no login+pass provided, check if kwallet has one
00365                 if ( openWallet( request->windowId ) )
00366                     hasWalletData = readFromWallet( m_wallet, request->key, info.realmValue, username, password, info.readOnly, knownLogins );
00367             }
00368 
00369             KIO::PasswordDialog dlg( info.prompt, username, info.keepPassword );
00370             if (info.caption.isEmpty())
00371                dlg.setPlainCaption( i18n("Authorization Dialog") );
00372             else
00373                dlg.setPlainCaption( info.caption );
00374 
00375             if ( !info.comment.isEmpty() )
00376                dlg.addCommentLine( info.commentLabel, info.comment );
00377 
00378             if ( !password.isEmpty() )
00379                dlg.setPassword( password );
00380 
00381             if (info.readOnly)
00382                dlg.setUserReadOnly( true );
00383             else
00384                dlg.setKnownLogins( knownLogins );
00385 
00386             if (hasWalletData)
00387                 dlg.setKeepPassword( true );
00388 
00389 #ifdef Q_WS_X11
00390             XSetTransientForHint( qt_xdisplay(), dlg.winId(), request->windowId);
00391 #endif
00392 
00393             dlgResult = dlg.exec();
00394 
00395             if (dlgResult == QDialog::Accepted)
00396             {
00397                info.username = dlg.username();
00398                info.password = dlg.password();
00399                info.keepPassword = dlg.keepPassword();
00400 
00401                // When the user checks "keep password", that means:
00402                // * if the wallet is enabled, store it there for long-term, and in kpasswdserver
00403                // only for the duration of the window (#92928)
00404                // * otherwise store in kpasswdserver for the duration of the KDE session.
00405                if ( info.keepPassword ) {
00406                    if ( openWallet( request->windowId ) ) {
00407                        if ( storeInWallet( m_wallet, request->key, info ) )
00408                            // password is in wallet, don't keep it in memory after window is closed
00409                            info.keepPassword = false;
00410                    }
00411                }
00412             }
00413         }
00414         if ( dlgResult != QDialog::Accepted )
00415         {
00416             addAuthInfoItem(request->key, info, 0, m_seqNr, true);
00417             info.setModified( false );
00418         }
00419         else
00420         {
00421             addAuthInfoItem(request->key, info, request->windowId, m_seqNr, false);
00422             info.setModified( true );
00423         }
00424     }
00425 
00426     QCString replyType;
00427     QByteArray replyData;
00428 
00429     QDataStream stream2(replyData, IO_WriteOnly);
00430     stream2 << info << m_seqNr;
00431     replyType = "KIO::AuthInfo";
00432     request->client->endTransaction( request->transaction,
00433                                      replyType, replyData);
00434 
00435     m_authPending.remove((unsigned int) 0);
00436 
00437     // Check all requests in the wait queue.
00438     for(Request *waitRequest = m_authWait.first();
00439         waitRequest; )
00440     {
00441        bool keepQueued = false;
00442        QString key = waitRequest->key;
00443 
00444        request = m_authPending.first();
00445        QString path2 = waitRequest->info.url.directory(false, false);
00446        for(; request; request = m_authPending.next())
00447        {
00448            if (request->key != key)
00449                continue;
00450 
00451            if (info.verifyPath)
00452            {
00453                QString path1 = request->info.url.directory(false, false);
00454                if (!path2.startsWith(path1))
00455                    continue;
00456            }
00457 
00458            keepQueued = true;
00459            break;
00460        }
00461        if (keepQueued)
00462        {
00463            waitRequest = m_authWait.next();
00464        }
00465        else
00466        {
00467            const AuthInfo *result = findAuthInfoItem(waitRequest->key, waitRequest->info);
00468 
00469            QCString replyType;
00470            QByteArray replyData;
00471 
00472            QDataStream stream2(replyData, IO_WriteOnly);
00473 
00474            if (!result || result->isCanceled)
00475            {
00476                waitRequest->info.setModified(false);
00477                stream2 << waitRequest->info;
00478            }
00479            else
00480            {
00481                updateAuthExpire(waitRequest->key, result, waitRequest->windowId, false);
00482                KIO::AuthInfo info = copyAuthInfo(result);
00483                stream2 << info;
00484            }
00485 
00486            replyType = "KIO::AuthInfo";
00487            waitRequest->client->endTransaction( waitRequest->transaction,
00488                                                 replyType, replyData);
00489 
00490            m_authWait.remove();
00491            waitRequest = m_authWait.current();
00492        }
00493     }
00494 
00495     if (m_authPending.count())
00496        QTimer::singleShot(0, this, SLOT(processRequest()));
00497 
00498 }
00499 
00500 QString KPasswdServer::createCacheKey( const KIO::AuthInfo &info )
00501 {
00502     if( !info.url.isValid() ) {
00503         // Note that a null key will break findAuthInfoItem later on...
00504         kdWarning(130) << "createCacheKey: invalid URL " << info.url << endl;
00505         return QString::null;
00506     }
00507 
00508     // Generate the basic key sequence.
00509     QString key = info.url.protocol();
00510     key += '-';
00511     if (!info.url.user().isEmpty())
00512     {
00513        key += info.url.user();
00514        key += "@";
00515     }
00516     key += info.url.host();
00517     int port = info.url.port();
00518     if( port )
00519     {
00520       key += ':';
00521       key += QString::number(port);
00522     }
00523 
00524     return key;
00525 }
00526 
00527 KIO::AuthInfo
00528 KPasswdServer::copyAuthInfo(const AuthInfo *i)
00529 {
00530     KIO::AuthInfo result;
00531     result.url = i->url;
00532     result.username = i->username;
00533     result.password = i->password;
00534     result.realmValue = i->realmValue;
00535     result.digestInfo = i->digestInfo;
00536     result.setModified(true);
00537 
00538     return result;
00539 }
00540 
00541 const KPasswdServer::AuthInfo *
00542 KPasswdServer::findAuthInfoItem(const QString &key, const KIO::AuthInfo &info)
00543 {
00544    AuthInfoList *authList = m_authDict.find(key);
00545    if (!authList)
00546       return 0;
00547 
00548    QString path2 = info.url.directory(false, false);
00549    for(AuthInfo *current = authList->first();
00550        current; )
00551    {
00552        if ((current->expire == AuthInfo::expTime) &&
00553           (difftime(time(0), current->expireTime) > 0))
00554        {
00555           authList->remove();
00556           current = authList->current();
00557           continue;
00558        }
00559 
00560        if (info.verifyPath)
00561        {
00562           QString path1 = current->directory;
00563           if (path2.startsWith(path1) &&
00564               (info.username.isEmpty() || info.username == current->username))
00565              return current;
00566        }
00567        else
00568        {
00569           if (current->realmValue == info.realmValue &&
00570               (info.username.isEmpty() || info.username == current->username))
00571              return current; // TODO: Update directory info,
00572        }
00573 
00574        current = authList->next();
00575    }
00576    return 0;
00577 }
00578 
00579 void
00580 KPasswdServer::removeAuthInfoItem(const QString &key, const KIO::AuthInfo &info)
00581 {
00582    AuthInfoList *authList = m_authDict.find(key);
00583    if (!authList)
00584       return;
00585 
00586    for(AuthInfo *current = authList->first();
00587        current; )
00588    {
00589        if (current->realmValue == info.realmValue)
00590        {
00591           authList->remove();
00592           current = authList->current();
00593        }
00594        else
00595        {
00596           current = authList->next();
00597        }
00598    }
00599    if (authList->isEmpty())
00600    {
00601        m_authDict.remove(key);
00602    }
00603 }
00604 
00605 
00606 void
00607 KPasswdServer::addAuthInfoItem(const QString &key, const KIO::AuthInfo &info, long windowId, long seqNr, bool canceled)
00608 {
00609    AuthInfoList *authList = m_authDict.find(key);
00610    if (!authList)
00611    {
00612       authList = new AuthInfoList;
00613       m_authDict.insert(key, authList);
00614    }
00615    AuthInfo *current = authList->first();
00616    for(; current; current = authList->next())
00617    {
00618        if (current->realmValue == info.realmValue)
00619        {
00620           authList->take();
00621           break;
00622        }
00623    }
00624 
00625    if (!current)
00626    {
00627       current = new AuthInfo;
00628       current->expire = AuthInfo::expTime;
00629       kdDebug(130) << "Creating AuthInfo" << endl;
00630    }
00631    else
00632    {
00633       kdDebug(130) << "Updating AuthInfo" << endl;
00634    }
00635 
00636    current->url = info.url;
00637    current->directory = info.url.directory(false, false);
00638    current->username = info.username;
00639    current->password = info.password;
00640    current->realmValue = info.realmValue;
00641    current->digestInfo = info.digestInfo;
00642    current->seqNr = seqNr;
00643    current->isCanceled = canceled;
00644 
00645    updateAuthExpire(key, current, windowId, info.keepPassword && !canceled);
00646 
00647    // Insert into list, keep the list sorted "longest path" first.
00648    authList->inSort(current);
00649 }
00650 
00651 void
00652 KPasswdServer::updateAuthExpire(const QString &key, const AuthInfo *auth, long windowId, bool keep)
00653 {
00654    AuthInfo *current = const_cast<AuthInfo *>(auth);
00655    if (keep)
00656    {
00657       current->expire = AuthInfo::expNever;
00658    }
00659    else if (windowId && (current->expire != AuthInfo::expNever))
00660    {
00661       current->expire = AuthInfo::expWindowClose;
00662       if (!current->windowList.contains(windowId))
00663          current->windowList.append(windowId);
00664    }
00665    else if (current->expire == AuthInfo::expTime)
00666    {
00667       current->expireTime = time(0)+10;
00668    }
00669 
00670    // Update mWindowIdList
00671    if (windowId)
00672    {
00673       QStringList *keysChanged = mWindowIdList.find(windowId);
00674       if (!keysChanged)
00675       {
00676          keysChanged = new QStringList;
00677          mWindowIdList.insert(windowId, keysChanged);
00678       }
00679       if (!keysChanged->contains(key))
00680          keysChanged->append(key);
00681    }
00682 }
00683 
00684 void
00685 KPasswdServer::removeAuthForWindowId(long windowId)
00686 {
00687    QStringList *keysChanged = mWindowIdList.find(windowId);
00688    if (!keysChanged) return;
00689 
00690    for(QStringList::ConstIterator it = keysChanged->begin();
00691        it != keysChanged->end(); ++it)
00692    {
00693       QString key = *it;
00694       AuthInfoList *authList = m_authDict.find(key);
00695       if (!authList)
00696          continue;
00697 
00698       AuthInfo *current = authList->first();
00699       for(; current; )
00700       {
00701         if (current->expire == AuthInfo::expWindowClose)
00702         {
00703            if (current->windowList.remove(windowId) && current->windowList.isEmpty())
00704            {
00705               authList->remove();
00706               current = authList->current();
00707               continue;
00708            }
00709         }
00710         current = authList->next();
00711       }
00712    }
00713 }
00714 
00715 #include "kpasswdserver.moc"

kio

Skip menu "kio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal