[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Question: KIO Scheduler
From:       Dawit Alemayehu <adawit () kde ! org>
Date:       2000-10-30 3:08:04
[Download RAW message or body]

Hello,

I am trying to add support for automatic deletion of passwords when the applications \
that cached them are closed by the user.  To achieve this I put the code that tracks \
and deletes cached passwords in KIO's scheduler since there is one instance of it per \
app (unlike the slaves and the jobs).  Hence, when the app exists we are able to \
correctly deal with the cached passwords (remove them as necessary).  However, I \
cannot get this to work no matter what I tried and need help.  From what I gathered \
so far it seems to me that my problem stems from the fact that the scheduler is a \
static object.  I have attached a patch below to show what I have done.  Below is a \
brief description of how this deletion is supposed(intended) to work:

1.) Whenever a unique new password is cached the SlaveBase responsible for this stuff \
sends a message to the application-side of the house (SlaveInterface).  The message \
is the key under which the password is cached in the kdesud daemon.

2.) When the SlaveInterface gets this message it emits a signal with this key at \
hand.  And since the scheduler is connected to this signal when it first created the \
io-slave, it gets its hand on it.

3) The SLOT connected to the signal in KIO::Scheduler then store the key in a list \
(QValueList) and registers itself with the kdesu daemon as an owner of this key.

So far so good.  I was able to get this to work for a while consistently, but now for \
whatever reason it seems not to anymore.  I do not get the debug statements I should \
when I test it.  But do not worry about this as it seems to be something wrong on my \
end

4.) When the application is then destroyed, I put a statement that calls \
delCachedAuthKeys in KIO::Scheduler's dtor.  The above method determines whether or \
not the cached entries should be deleted or not.  This is the point  of failure.  I \
always get the following FATAL error and konqueror aborts in the process of shutting \
down.

Fatal error: you need to have a KInstance object before
you do anything that requires it! Examples of this are config
objects, standard directories or translations.
zsh: 9755 abort      konqueror  

If I then remove the method that attempts to call the afformentioned method from the \
destructor, I do not get the above message.

Thus, the question is where is the correct place to put this stuff such that when \
this static object is destroyed or about to be destroyed the cached entries, if any, \
can be cleaned as well...

Any suggestions, comments, flames etc are all welcome...

Regards,
Dawit A.


["scheduler.diff" (text/x-c)]

Index: scheduler.cpp
===================================================================
RCS file: /home/kde/kdelibs/kio/scheduler.cpp,v
retrieving revision 1.38
diff -u -r1.38 scheduler.cpp
--- scheduler.cpp	2000/10/16 01:20:39	1.38
+++ scheduler.cpp	2000/10/30 03:00:47
@@ -26,6 +26,7 @@
 #include <kprotocolmanager.h>
 #include <assert.h>
 #include <kstaticdeleter.h>
+#include <kdesu/client.h>
 
 //
 // Slaves may be idle for MAX_SLAVE_IDLE time before they are being returned
@@ -36,6 +37,19 @@
 
 Scheduler *Scheduler::instance = 0;
 
+/*
+* Structure to cache authorization info from io-slaves.
+*/
+struct KIO::AuthKey
+{
+  AuthKey() {}
+  AuthKey(const QString& k,int d,bool p):key(k),duration(d),persist(p) {}
+  QString key;
+  int duration;
+  bool persist;
+};
+
+
 class KIO::Scheduler::ProtocolInfo
 {
   public:
@@ -97,7 +111,13 @@
 
 Scheduler::~Scheduler()
 {
-//fprintf(stderr, "Destructing KIO::Scheduler...\n");
+    fprintf(stdout, "Destructing KIO::Scheduler...\n");
+    kdDebug(7600) << "Destructing KIO::Scheduler..." << endl;
+
+    // Delete any stored authorization info now...
+    if( !cachedAuthKeys.isEmpty() )
+      delCachedAuthKeys( cachedAuthKeys );
+
     protInfoDict->setAutoDelete(true);
     delete protInfoDict; protInfoDict = 0;
     delete idleSlaves; idleSlaves = 0;
@@ -268,6 +288,7 @@
 			SLOT(slotSlaveDied(KIO::Slave *)));
                 connect(slave, SIGNAL(slaveStatus(pid_t,const QCString &,const \
                QString &, bool)),
                         SLOT(slotSlaveStatus(pid_t,const QCString &, const QString \
&, bool))); +                connect(slave,SIGNAL(authKey(const \
QString&)),SLOT(slotAuthKey(const QString&)));  }
              else
              {
@@ -350,6 +371,96 @@
     }
 }
 
+bool Scheduler::pingCacheDaemon() const
+{
+    KDEsuClient client;
+    int sucess = client.ping();
+    if( sucess == -1 )
+    {
+        kdDebug(7006) << "No running \"kdesu\" daemon found. Attempting to start \
one..." << endl; +        sucess = client.startServer();
+        if( sucess == -1 )
+        {
+            kdDebug(7006) << "Cannot start a new \"kdesu\" deamon!!" << endl;
+            return false;
+        }
+        kdDebug(7006) << "New \"kdesu\" daemon was sucessfully started..." << endl;
+    }
+    return true;
+}
+
+void Scheduler::slotAuthKey( const QString& auth_key )
+{
+    cachedAuthKeys.append( AuthKey( auth_key, 0, false ) );
+    regCachedAuthKey( auth_key );
+}
+
+void Scheduler::slotDestroyed()
+{
+    kdDebug(7006) << "About to destroy the scheduler..." << endl;
+    kdDebug(7006) << "Is authentication cache empty ? "<< cachedAuthKeys.isEmpty() \
<< endl; +    if( !cachedAuthKeys.isEmpty() )
+      delCachedAuthKeys( cachedAuthKeys );
+}
+
+bool Scheduler::regCachedAuthKey( const QString& grpname )
+{
+    kdDebug(7006) << "Register authentication key for: " << grpname << endl;
+    KDEsuClient client;
+    if( pingCacheDaemon() && !client.getVar((grpname + \
"-hasEntry").utf8()).isEmpty() ) +    {
+      bool ok;
+      int count = client.getVar( (grpname + "-refcount").utf8() ).toInt( &ok );
+      if( ok )
+        client.setVar( (grpname + "-refcount").utf8(), \
QString("%1").arg(count+1).utf8(), 0, grpname.utf8() ); +      else
+        client.setVar( (grpname + "-refcount").utf8(), "2", 0, grpname.utf8() );
+      return true;
+    }
+    return false;
+}
+
+void Scheduler::delCachedAuthKeys( const AuthKeyList& grpname )
+{
+    kdDebug(7006) << "Attempting to delete cached Authentication..." << endl;
+
+    if( !pingCacheDaemon() )
+        return;
+
+    bool ok;
+    int count;
+    KDEsuClient client;
+    AuthKeyList::ConstIterator it = grpname.begin();
+    for( ; it != grpname.end(); ++it )
+    {
+      // Do not delete passwords that are meant to
+      // be persistant!
+      if( (*it).persist )
+        continue;
+
+      count = client.getVar( ((*it).key + "-refcount").utf8() ).toInt( &ok );
+      // Test point though I know that this value is going to be an integer
+      kdDebug(7006) << "Delete key " << (*it).key << "? " << ok << endl;
+      if( ok )
+      {
+          if( count > 1 )
+          {
+             client.setVar(((*it).key + "-refcount").utf8(),
+                            QString("%1").arg( count - 1 ).utf8(), 0,
+                            (*it).key.utf8() );
+              kdDebug(7006) << "Key registered by multiple processes. "
+                            << "Decrementing reference count to: "
+                            << count-1 << endl;
+          }
+          else
+          {
+              kdDebug(7006) << "Last reference. Deleting the whole group..." << \
endl; +              client.delGroup((*it).key.utf8());
+          }
+      }
+    }
+}
+
 void Scheduler::slotSlaveDied(KIO::Slave *slave)
 {
     ProtocolInfo *protInfo = protInfoDict->get(slave->protocol());
@@ -438,8 +549,9 @@
 static KStaticDeleter<Scheduler> ksds;
 
 Scheduler* Scheduler::self() {
-    if ( !instance )
-	instance = ksds.setObject(new Scheduler);
+    if ( !instance ) {
+	    instance = ksds.setObject(new Scheduler);
+    }
 
     return instance;
 }
Index: scheduler.h
===================================================================
RCS file: /home/kde/kdelibs/kio/scheduler.h,v
retrieving revision 1.19
diff -u -r1.19 scheduler.h
--- scheduler.h	2000/09/22 17:19:47	1.19
+++ scheduler.h	2000/10/30 03:00:49
@@ -31,6 +31,7 @@
 
     class Slave;
     class SlaveList;
+    struct AuthKey;
 
     class Scheduler : public QObject, virtual public DCOPObject {
 	Q_OBJECT
@@ -46,7 +47,7 @@
 		{ self()->_cancelJob(job); }
         static void jobFinished(KIO::SimpleJob *job, KIO::Slave *slave)
             	{ self()->_jobFinished(job, slave); }
-            	
+
         static void putSlaveOnHold(KIO::SimpleJob *job, const KURL &url)
         	{ self()->_putSlaveOnHold(job, url); }
 
@@ -68,6 +69,8 @@
     protected slots:
         void startStep();
         void slotCleanIdleSlaves();
+        void slotAuthKey( const QString& auth_key );
+        void slotDestroyed();
 
     protected:
         bool startStep(ProtocolInfo *protInfo);
@@ -100,12 +103,47 @@
 	 */
 	SlaveList *slaveList;
 	SlaveList *idleSlaves;
-	
+
 	ProtocolInfoDict *protInfoDict;
-	
+
 	Slave *slaveOnHold;
 	KURL urlOnHold;
-    };
+
+
+    typedef QValueList<AuthKey> AuthKeyList;
+    AuthKeyList cachedAuthKeys;
+
+    /**
+     * Checks whether the password daemon kdesud is
+     * running or if it can be started if it is not.
+     *
+     * @return true if password daemon is/can be started successfully.
+     */
+    bool pingCacheDaemon() const;
+
+    /**
+     * Increments the reference count for application using the
+     * give authorization key.
+     *
+     * The reference counting is used by @ref delCachedAuthentication
+     * to determine when it is safe to delete the key from the cache.
+     *
+     * A call to this function will fail, i.e. return false, if there
+     * is no entry for the given @p groupname value and/or the cache
+     * deamon, @p kdesud, cannot be contacted.
+     *
+     * @return true if the registration succeeds.
+     */
+    bool regCachedAuthKey( const QString& grpname );
+
+    /**
+     * Deletes any cached keys for the given group.
+     *
+     * @param grpname cached authentication key to be deleted.
+     */
+    void delCachedAuthKeys( const AuthKeyList& grpname );
+
 };
 
+};
 #endif



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic