kpasswdserver.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kpasswdserver.cpp

    00001 /*
    00002     This file is part of the KDE Cookie Jar
    00003
    00004     Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
    00005
    00006     This library is free software; you can redistribute it and/or
    00007     modify it under the terms of the GNU General Public License
    00008     version 2 as published by the Free Software Foundation.
    00009
    00010     This software is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013     General Public License for more details.
    00014
    00015     You should have received a copy of the GNU General Public License
    00016     along with this library; see the file COPYING. If not, write to
    00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018     Boston, MA 02111-1307, USA.
    00019 */
    00020 //----------------------------------------------------------------------------
    00021 //
    00022 // KDE Password Server
    00023 // $Id: kpasswdserver.cpp,v 1.5.2.3 2003/05/17 11:19:24 mueller Exp $
    00024
    00025 #include <time.h>
    00026
    00027 #include <qtimer.h>
    00028
    00029 #include <kapplication.h>
    00030 #include <klocale.h>
    00031 #include <kmessagebox.h>
    00032 #include <kdebug.h>
    00033 #include <kio/passdlg.h>
    00034
    00035 #ifdef Q_WS_X11
    00036 #include <X11/X.h>
    00037 #include <X11/Xlib.h>
    00038 #endif
    00039
    00040 #include "kpasswdserver.h"
    00041
    00042 extern "C" {
    00043     KDEDModule *create_kpasswdserver(const QCString &name)
    00044     {
    00045        return new KPasswdServer(name);
    00046     }
    00047 }
    00048
    00049 int
    00050 KPasswdServer::AuthInfoList::compareItems(QPtrCollection::Item n1, QPtrCollection::Item n2)
    00051 {
    00052    if (!n1 || !n2)
    00053       return 0;
    00054
    00055    AuthInfo *i1 = (AuthInfo *) n1;
    00056    AuthInfo *i2 = (AuthInfo *) n2;
    00057
    00058    int l1 = i1->directory.length();
    00059    int l2 = i2->directory.length();
    00060
    00061    if (l1 > l2)
    00062       return -1;
    00063    if (l1 < l2)
    00064       return 1;
    00065    return 0;
    00066 }
    00067
    00068
    00069 KPasswdServer::KPasswdServer(const QCString &name)
    00070  : KDEDModule(name)
    00071 {
    00072     m_authDict.setAutoDelete(true);
    00073     m_authPending.setAutoDelete(true);
    00074     m_seqNr = 0;
    00075     connect(this, SIGNAL(windowUnregistered(long)),
    00076             this, SLOT(removeAuthForWindowId(long)));
    00077 }
    00078
    00079 KPasswdServer::~KPasswdServer()
    00080 {
    00081 }
    00082
    00083 KIO::AuthInfo
    00084 KPasswdServer::checkAuthInfo(KIO::AuthInfo info, long windowId)
    00085 {
    00086     kdDebug(130) << "KPasswdServer::checkAuthInfo: User= " << info.username
    00087               << ", WindowId = " << windowId << endl;
    00088
    00089     QString key = createCacheKey(info);
    00090
    00091     Request *request = m_authPending.first();
    00092     QString path2 = info.url.directory(false, false);
    00093     for(; request; request = m_authPending.next())
    00094     {
    00095        if (request->key != key)
    00096            continue;
    00097
    00098        if (info.verifyPath)
    00099        {
    00100           QString path1 = request->info.url.directory(false, false);
    00101           if (!path2.startsWith(path1))
    00102              continue;
    00103        }
    00104
    00105        request = new Request;
    00106        request->client = callingDcopClient();
    00107        request->transaction = request->client->beginTransaction();
    00108        request->key = key;
    00109        request->info = info;
    00110        m_authWait.append(request);
    00111        return info;
    00112     }
    00113
    00114     const AuthInfo *result = findAuthInfoItem(key, info);
    00115     if (!result || result->isCanceled)
    00116     {
    00117        info.setModified(false);
    00118        return info;
    00119     }
    00120
    00121     updateAuthExpire(key, result, windowId, false);
    00122
    00123     return copyAuthInfo(result);
    00124 }
    00125
    00126 KIO::AuthInfo
    00127 KPasswdServer::queryAuthInfo(KIO::AuthInfo info, QString errorMsg, long windowId, long seqNr)
    00128 {
    00129     kdDebug(130) << "KPasswdServer::queryAuthInfo: User= " << info.username
    00130               << ", Message= " << info.prompt << ", WindowId = " << windowId << endl;
    00131     QString key = createCacheKey(info);
    00132     Request *request = new Request;
    00133     request->client = callingDcopClient();
    00134     request->transaction = request->client->beginTransaction();
    00135     request->key = key;
    00136     request->info = info;
    00137     request->windowId = windowId;
    00138     request->seqNr = seqNr;
    00139     if (errorMsg == "<NoAuthPrompt>")
    00140     {
    00141        request->errorMsg = QString::null;
    00142        request->prompt = false;
    00143     }
    00144     else
    00145     {
    00146        request->errorMsg = errorMsg;
    00147        request->prompt = true;
    00148     }
    00149     m_authPending.append(request);
    00150
    00151     if (m_authPending.count() == 1)
    00152        QTimer::singleShot(0, this, SLOT(processRequest()));
    00153
    00154     return info;
    00155 }
    00156
    00157 void
    00158 KPasswdServer::addAuthInfo(KIO::AuthInfo info, long windowId)
    00159 {
    00160     kdDebug(130) << "KPasswdServer::addAuthInfo: User= " << info.username
    00161               << ", RealmValue= " << info.realmValue << ", WindowId = " << windowId << endl;
    00162     QString key = createCacheKey(info);
    00163
    00164     m_seqNr++;
    00165
    00166     addAuthInfoItem(key, info, windowId, m_seqNr, false);
    00167 }
    00168
    00169 void
    00170 KPasswdServer::processRequest()
    00171 {
    00172     Request *request = m_authPending.first();
    00173     if (!request)
    00174        return;
    00175
    00176     KIO::AuthInfo &info = request->info;
    00177
    00178     kdDebug(130) << "KPasswdServer::processRequest: User= " << info.username
    00179               << ", Message= " << info.prompt << endl;
    00180
    00181     const AuthInfo *result = findAuthInfoItem(request->key, request->info);
    00182
    00183     if (result && (request->seqNr < result->seqNr))
    00184     {
    00185         kdDebug(130) << "KPasswdServer::processRequest: auto retry!" << endl;
    00186         if (result->isCanceled)
    00187         {
    00188            info.setModified(false);
    00189         }
    00190         else
    00191         {
    00192            updateAuthExpire(request->key, result, request->windowId, false);
    00193            info = copyAuthInfo(result);
    00194         }
    00195     }
    00196     else
    00197     {
    00198         m_seqNr++;
    00199         bool askPw = request->prompt;
    00200         if (result && !info.username.isEmpty() &&
    00201             !request->errorMsg.isEmpty())
    00202         {
    00203            QString prompt = request->errorMsg;
    00204            prompt += i18n("  Do you want to retry?");
    00205            int dlgResult = KMessageBox::warningContinueCancel(0, prompt,
    00206                            i18n("Authentication"), i18n("Retry"));
    00207            if (dlgResult != KMessageBox::Continue)
    00208               askPw = false;
    00209         }
    00210
    00211         int dlgResult = QDialog::Rejected;
    00212         if (askPw)
    00213         {
    00214             KIO::PasswordDialog dlg( info.prompt, info.username, info.keepPassword );
    00215             if (info.caption.isEmpty())
    00216                dlg.setPlainCaption( i18n("Authorization Dialog") );
    00217             else
    00218                dlg.setPlainCaption( info.caption );
    00219
    00220             if ( !info.comment.isEmpty() )
    00221                dlg.addCommentLine( info.commentLabel, info.comment );
    00222
    00223             if ( !info.password.isEmpty() )
    00224                dlg.setPassword( info.password );
    00225
    00226             if (info.readOnly)
    00227                dlg.setUserReadOnly( true );
    00228
    00229             XSetTransientForHint( qt_xdisplay(), dlg.winId(), request->windowId);
    00230
    00231             dlgResult = dlg.exec();
    00232
    00233             if (dlgResult == QDialog::Accepted)
    00234             {
    00235                info.username = dlg.username();
    00236                info.password = dlg.password();
    00237                info.keepPassword = dlg.keepPassword();
    00238             }
    00239         }
    00240         if ( dlgResult != QDialog::Accepted )
    00241         {
    00242             addAuthInfoItem(request->key, info, 0, m_seqNr, true);
    00243             info.setModified( false );
    00244         }
    00245         else
    00246         {
    00247             addAuthInfoItem(request->key, info, request->windowId, m_seqNr, false);
    00248             info.setModified( true );
    00249         }
    00250     }
    00251
    00252     QCString replyType;
    00253     QByteArray replyData;
    00254
    00255     QDataStream stream2(replyData, IO_WriteOnly);
    00256     stream2 << info << m_seqNr;
    00257     replyType = "KIO::AuthInfo";
    00258     request->client->endTransaction( request->transaction,
    00259                                      replyType, replyData);
    00260
    00261     m_authPending.remove((unsigned int) 0);
    00262
    00263     // Check all requests in the wait queue.
    00264     for(Request *waitRequest = m_authWait.first();
    00265         waitRequest; )
    00266     {
    00267        bool keepQueued = false;
    00268        QString key = waitRequest->key;
    00269
    00270        request = m_authPending.first();
    00271        QString path2 = waitRequest->info.url.directory(false, false);
    00272        for(; request; request = m_authPending.next())
    00273        {
    00274            if (request->key != key)
    00275                continue;
    00276
    00277            if (info.verifyPath)
    00278            {
    00279                QString path1 = request->info.url.directory(false, false);
    00280                if (!path2.startsWith(path1))
    00281                    continue;
    00282            }
    00283
    00284            keepQueued = true;
    00285            break;
    00286        }
    00287        if (keepQueued)
    00288        {
    00289            waitRequest = m_authWait.next();
    00290        }
    00291        else
    00292        {
    00293            const AuthInfo *result = findAuthInfoItem(waitRequest->key, waitRequest->info);
    00294
    00295            QCString replyType;
    00296            QByteArray replyData;
    00297
    00298            QDataStream stream2(replyData, IO_WriteOnly);
    00299
    00300            if (!result || result->isCanceled)
    00301            {
    00302                waitRequest->info.setModified(false);
    00303                stream2 << waitRequest->info;
    00304            }
    00305            else
    00306            {
    00307                updateAuthExpire(waitRequest->key, result, waitRequest->windowId, false);
    00308                KIO::AuthInfo info = copyAuthInfo(result);
    00309                stream2 << info;
    00310            }
    00311
    00312            replyType = "KIO::AuthInfo";
    00313            waitRequest->client->endTransaction( waitRequest->transaction,
    00314                                                 replyType, replyData);
    00315
    00316            m_authWait.remove();
    00317            waitRequest = m_authWait.current();
    00318        }
    00319     }
    00320
    00321     if (m_authPending.count())
    00322        QTimer::singleShot(0, this, SLOT(processRequest()));
    00323
    00324 }
    00325
    00326 QString KPasswdServer::createCacheKey( const KIO::AuthInfo &info )
    00327 {
    00328     if( info.url.isMalformed() )
    00329         return QString::null;
    00330
    00331     // Generate the basic key sequence.
    00332     QString key = info.url.protocol();
    00333     key += '-';
    00334     if (!info.url.user().isEmpty())
    00335     {
    00336        key += info.url.user();
    00337        key += "@";
    00338     }
    00339     key += info.url.host();
    00340     int port = info.url.port();
    00341     if( port )
    00342     {
    00343       key += ':';
    00344       key += QString::number(port);
    00345     }
    00346
    00347     return key;
    00348 }
    00349
    00350 KIO::AuthInfo
    00351 KPasswdServer::copyAuthInfo(const AuthInfo *i)
    00352 {
    00353     KIO::AuthInfo result;
    00354     result.url = i->url;
    00355     result.username = i->username;
    00356     result.password = i->password;
    00357     result.realmValue = i->realmValue;
    00358     result.digestInfo = i->digestInfo;
    00359     result.setModified(true);
    00360
    00361     return result;
    00362 }
    00363
    00364 const KPasswdServer::AuthInfo *
    00365 KPasswdServer::findAuthInfoItem(const QString &key, const KIO::AuthInfo &info)
    00366 {
    00367    AuthInfoList *authList = m_authDict.find(key);
    00368    if (!authList)
    00369       return 0;
    00370
    00371    QString path2 = info.url.directory(false, false);
    00372    for(AuthInfo *current = authList->first();
    00373        current; )
    00374    {
    00375        if ((current->expire == AuthInfo::expTime) &&
    00376           (difftime(time(0), current->expireTime) > 0))
    00377        {
    00378           authList->remove();
    00379           current = authList->current();
    00380           continue;
    00381        }
    00382
    00383        if (info.verifyPath)
    00384        {
    00385           QString path1 = current->directory;
    00386           if (path2.startsWith(path1))
    00387              return current;
    00388        }
    00389        else
    00390        {
    00391           if (current->realmValue == info.realmValue)
    00392              return current; // TODO: Update directory info,
    00393        }
    00394
    00395        current = authList->next();
    00396    }
    00397    return 0;
    00398 }
    00399
    00400 void
    00401 KPasswdServer::removeAuthInfoItem(const QString &key, const KIO::AuthInfo &info)
    00402 {
    00403    AuthInfoList *authList = m_authDict.find(key);
    00404    if (!authList)
    00405       return;
    00406
    00407    for(AuthInfo *current = authList->first();
    00408        current; )
    00409    {
    00410        if (current->realmValue == info.realmValue)
    00411        {
    00412           authList->remove();
    00413           current = authList->current();
    00414        }
    00415        else
    00416        {
    00417           current = authList->next();
    00418        }
    00419    }
    00420    if (authList->isEmpty())
    00421    {
    00422        m_authDict.remove(key);
    00423    }
    00424 }
    00425
    00426
    00427 void
    00428 KPasswdServer::addAuthInfoItem(const QString &key, const KIO::AuthInfo &info, long windowId, long seqNr, bool canceled)
    00429 {
    00430    AuthInfoList *authList = m_authDict.find(key);
    00431    if (!authList)
    00432    {
    00433       authList = new AuthInfoList;
    00434       m_authDict.insert(key, authList);
    00435    }
    00436    AuthInfo *current = authList->first();
    00437    for(; current; current = authList->next())
    00438    {
    00439        if (current->realmValue == info.realmValue)
    00440        {
    00441           authList->take();
    00442           break;
    00443        }
    00444    }
    00445
    00446    if (!current)
    00447    {
    00448       current = new AuthInfo;
    00449       current->expire = AuthInfo::expTime;
    00450       kdDebug(130) << "Creating AuthInfo" << endl;
    00451    }
    00452    else
    00453    {
    00454       kdDebug(130) << "Updating AuthInfo" << endl;
    00455    }
    00456
    00457    current->url = info.url;
    00458    current->directory = info.url.directory(false, false);
    00459    current->username = info.username;
    00460    current->password = info.password;
    00461    current->realmValue = info.realmValue;
    00462    current->digestInfo = info.digestInfo;
    00463    current->seqNr = seqNr;
    00464    current->isCanceled = canceled;
    00465
    00466    updateAuthExpire(key, current, windowId, info.keepPassword && !canceled);
    00467
    00468    // Insert into list, keep the list sorted "longest path" first.
    00469    authList->inSort(current);
    00470 }
    00471
    00472 void
    00473 KPasswdServer::updateAuthExpire(const QString &key, const AuthInfo *auth, long windowId, bool keep)
    00474 {
    00475    AuthInfo *current = const_cast<AuthInfo *>(auth);
    00476    if (keep)
    00477    {
    00478       current->expire = AuthInfo::expNever;
    00479    }
    00480    else if (windowId && (current->expire != AuthInfo::expNever))
    00481    {
    00482       current->expire = AuthInfo::expWindowClose;
    00483       if (!current->windowList.contains(windowId))
    00484          current->windowList.append(windowId);
    00485    }
    00486    else if (current->expire == AuthInfo::expTime)
    00487    {
    00488       current->expireTime = time(0)+10;
    00489    }
    00490
    00491    // Update mWindowIdList
    00492    if (windowId)
    00493    {
    00494       QStringList *keysChanged = mWindowIdList.find(windowId);
    00495       if (!keysChanged)
    00496       {
    00497          keysChanged = new QStringList;
    00498          mWindowIdList.insert(windowId, keysChanged);
    00499       }
    00500       if (!keysChanged->contains(key))
    00501          keysChanged->append(key);
    00502    }
    00503 }
    00504
    00505 void
    00506 KPasswdServer::removeAuthForWindowId(long windowId)
    00507 {
    00508    QStringList *keysChanged = mWindowIdList.find(windowId);
    00509    if (!keysChanged) return;
    00510
    00511    for(QStringList::ConstIterator it = keysChanged->begin();
    00512        it != keysChanged->end(); ++it)
    00513    {
    00514       QString key = *it;
    00515       AuthInfoList *authList = m_authDict.find(key);
    00516       if (!authList)
    00517          continue;
    00518
    00519       AuthInfo *current = authList->first();
    00520       for(; current; )
    00521       {
    00522         if (current->expire == AuthInfo::expWindowClose)
    00523         {
    00524            if (current->windowList.remove(windowId) && current->windowList.isEmpty())
    00525            {
    00526               authList->remove();
    00527               current = authList->current();
    00528               continue;
    00529            }
    00530         }
    00531         current = authList->next();
    00532       }
    00533    }
    00534 }
    00535
    00536 #include "kpasswdserver.moc"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:13:56 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001