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

qca

qca_keystore.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2008  Justin Karneges <justin@affinix.com>
00003  * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library 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  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018  * 02110-1301  USA
00019  *
00020  */
00021 
00022 #include "qca_keystore.h"
00023 
00024 #include <QCoreApplication>
00025 #include <QAbstractEventDispatcher>
00026 #include <QPointer>
00027 #include <QSet>
00028 #include <QMutex>
00029 #include <QWaitCondition>
00030 
00031 #include <stdlib.h> // abort
00032 #include <stdio.h>  // fprintf
00033 
00034 #include "qcaprovider.h"
00035 
00036 Q_DECLARE_METATYPE(QCA::KeyStoreEntry)
00037 Q_DECLARE_METATYPE(QList<QCA::KeyStoreEntry>)
00038 Q_DECLARE_METATYPE(QList<QCA::KeyStoreEntry::Type>)
00039 Q_DECLARE_METATYPE(QCA::KeyBundle)
00040 Q_DECLARE_METATYPE(QCA::Certificate)
00041 Q_DECLARE_METATYPE(QCA::CRL)
00042 Q_DECLARE_METATYPE(QCA::PGPKey)
00043 
00044 namespace QCA {
00045 
00046 Provider::Context *getContext(const QString &type, Provider *p);
00047 
00048 // from qca_plugin.cpp
00049 QString truncate_log(const QString &in, int size);
00050 
00051 /*
00052   How this stuff works:
00053 
00054   KeyStoreListContext is queried for a list of store context ids.  A signal
00055   is used to indicate when the list may have changed, so polling for changes
00056   is not necessary.  Context ids change for every new presence of a store.
00057   Even if a user removes and inserts the same smart card device, which has
00058   the same storeId, the context id will ALWAYS be different.  If a previously
00059   known context id is missing from a later queried list, then it means the
00060   associated store is unavailable.  It is recommended that the provider just
00061   use a counter for the contextId, incrementing the value anytime a new
00062   context is made.
00063 
00064   KeyStoreTracker manages all of the keystore stuff, and exists in its own
00065   thread (called the tracker thread).  All of the KeyStoreListContext
00066   objects exist in the tracker thread.
00067 */
00068 
00069 /*
00070   scenarios to handle:
00071   - ksm.start shouldn't block
00072   - keystore in available list, but gone by the time it is requested
00073   - keystore is unavailable during a call to a keystoreentry method
00074   - keystore/keystoreentry methods called simultaneously from different threads
00075   - and of course, objects from keystores should work, despite being created
00076     in the keystore thread
00077 */
00078 
00079 //----------------------------------------------------------------------------
00080 // KeyStoreTracker
00081 //----------------------------------------------------------------------------
00082 static int tracker_id_at = 0;
00083 
00084 class KeyStoreTracker : public QObject
00085 {
00086     Q_OBJECT
00087 public:
00088     static KeyStoreTracker *self;
00089 
00090     class Item
00091     {
00092     public:
00093         // combine keystore owner and contextid into a single id
00094         int trackerId;
00095 
00096         // number of times the keystore has been updated
00097         int updateCount;
00098 
00099         // keystore context
00100         KeyStoreListContext *owner;
00101         int storeContextId;
00102 
00103         // properties
00104         QString storeId;
00105         QString name;
00106         KeyStore::Type type;
00107         bool isReadOnly;
00108 
00109         Item() : trackerId(-1), updateCount(0), owner(0), storeContextId(-1)
00110         {
00111         }
00112     };
00113 
00114     QMutex m;
00115     QSet<KeyStoreListContext*> sources;
00116     QSet<KeyStoreListContext*> busySources;
00117     QList<Item> items;
00118     QString dtext;
00119     bool startedAll;
00120     bool busy;
00121 
00122     QMutex updateMutex;
00123 
00124     KeyStoreTracker()
00125     {
00126         self = this;
00127 
00128         qRegisterMetaType<KeyStoreEntry>();
00129         qRegisterMetaType< QList<KeyStoreEntry> >();
00130         qRegisterMetaType< QList<KeyStoreEntry::Type> >();
00131         qRegisterMetaType<KeyBundle>();
00132         qRegisterMetaType<Certificate>();
00133         qRegisterMetaType<CRL>();
00134         qRegisterMetaType<PGPKey>();
00135 
00136         connect(this, SIGNAL(updated_p()), SLOT(updated_locked()), Qt::QueuedConnection);
00137 
00138         startedAll = false;
00139         busy = true; // we start out busy
00140     }
00141 
00142     ~KeyStoreTracker()
00143     {
00144         qDeleteAll(sources);
00145         self = 0;
00146     }
00147 
00148     static KeyStoreTracker *instance()
00149     {
00150         return self;
00151     }
00152 
00153     // thread-safe
00154     bool isBusy()
00155     {
00156         QMutexLocker locker(&m);
00157         return busy;
00158     }
00159 
00160     // thread-safe
00161     QList<Item> getItems()
00162     {
00163         QMutexLocker locker(&m);
00164         return items;
00165     }
00166 
00167     // thread-safe
00168     QString getDText()
00169     {
00170         QMutexLocker locker(&m);
00171         return dtext;
00172     }
00173 
00174     // thread-safe
00175     void clearDText()
00176     {
00177         QMutexLocker locker(&m);
00178         dtext.clear();
00179     }
00180 
00181     // thread-safe
00182     void addTarget(QObject *ksm)
00183     {
00184         QMutexLocker locker(&updateMutex);
00185         ksm->connect(this, SIGNAL(updated()), SLOT(tracker_updated()), Qt::DirectConnection);
00186     }
00187 
00188     // thread-safe
00189     void removeTarget(QObject *ksm)
00190     {
00191         QMutexLocker locker(&updateMutex);
00192         disconnect(ksm);
00193     }
00194 
00195 public slots:
00196     void spinEventLoop()
00197     {
00198         QAbstractEventDispatcher::instance()->processEvents(QEventLoop::AllEvents);
00199     }
00200 
00201     void start()
00202     {
00203         // grab providers (and default)
00204         ProviderList list = providers();
00205         list.append(defaultProvider());
00206 
00207         for(int n = 0; n < list.count(); ++n)
00208         {
00209             Provider *p = list[n];
00210             if(p->features().contains("keystorelist") && !haveProviderSource(p))
00211                 startProvider(p);
00212         }
00213 
00214         startedAll = true;
00215     }
00216 
00217     void start(const QString &provider)
00218     {
00219         // grab providers (and default)
00220         ProviderList list = providers();
00221         list.append(defaultProvider());
00222 
00223         Provider *p = 0;
00224         for(int n = 0; n < list.count(); ++n)
00225         {
00226             if(list[n]->name() == provider)
00227             {
00228                 p = list[n];
00229                 break;
00230             }
00231         }
00232 
00233         if(p && p->features().contains("keystorelist") && !haveProviderSource(p))
00234             startProvider(p);
00235     }
00236 
00237     void scan()
00238     {
00239         if(startedAll)
00240             start();
00241     }
00242 
00243     QList<QCA::KeyStoreEntry> entryList(int trackerId)
00244     {
00245         QList<KeyStoreEntry> out;
00246         int at = findItem(trackerId);
00247         if(at == -1)
00248             return out;
00249         Item &i = items[at];
00250         QList<KeyStoreEntryContext*> list = i.owner->entryList(i.storeContextId);
00251         for(int n = 0; n < list.count(); ++n)
00252         {
00253             KeyStoreEntry entry;
00254             entry.change(list[n]);
00255             out.append(entry);
00256         }
00257         return out;
00258     }
00259 
00260     QList<QCA::KeyStoreEntry::Type> entryTypes(int trackerId)
00261     {
00262         QList<KeyStoreEntry::Type> out;
00263         int at = findItem(trackerId);
00264         if(at == -1)
00265             return out;
00266         Item &i = items[at];
00267         return i.owner->entryTypes(i.storeContextId);
00268     }
00269 
00270     // hack with void *
00271     void *entry(const QString &storeId, const QString &entryId)
00272     {
00273         KeyStoreListContext *c = 0;
00274         int contextId = -1;
00275         m.lock();
00276         foreach(const Item &i, items)
00277         {
00278             if(i.storeId == storeId)
00279             {
00280                 c = i.owner;
00281                 contextId = i.storeContextId;
00282                 break;
00283             }
00284         }
00285         m.unlock();
00286         if(!c)
00287             return 0;
00288 
00289         return c->entry(contextId, entryId);
00290     }
00291 
00292     // hack with void *
00293     void *entryPassive(const QString &serialized)
00294     {
00295         foreach(KeyStoreListContext *ksl, sources)
00296         {
00297             // "is this yours?"
00298             KeyStoreEntryContext *e = ksl->entryPassive(serialized);
00299             if(e)
00300                 return e;
00301         }
00302         return 0;
00303     }
00304 
00305     QString writeEntry(int trackerId, const QVariant &v)
00306     {
00307         int at = findItem(trackerId);
00308         if(at == -1)
00309             return QString();
00310         Item &i = items[at];
00311         if(qVariantCanConvert<KeyBundle>(v))
00312             return i.owner->writeEntry(i.storeContextId, qVariantValue<KeyBundle>(v));
00313         else if(qVariantCanConvert<Certificate>(v))
00314             return i.owner->writeEntry(i.storeContextId, qVariantValue<Certificate>(v));
00315         else if(qVariantCanConvert<CRL>(v))
00316             return i.owner->writeEntry(i.storeContextId, qVariantValue<CRL>(v));
00317         else if(qVariantCanConvert<PGPKey>(v))
00318             return i.owner->writeEntry(i.storeContextId, qVariantValue<PGPKey>(v));
00319         else
00320             return QString();
00321     }
00322 
00323     QString writeEntry(int trackerId, const QCA::KeyBundle &v)
00324     {
00325         int at = findItem(trackerId);
00326         if(at == -1)
00327             return QString();
00328         Item &i = items[at];
00329 
00330         return i.owner->writeEntry(i.storeContextId, v);
00331     }
00332 
00333     QString writeEntry(int trackerId, const QCA::Certificate &v)
00334     {
00335         int at = findItem(trackerId);
00336         if(at == -1)
00337             return QString();
00338         Item &i = items[at];
00339 
00340         return i.owner->writeEntry(i.storeContextId, v);
00341     }
00342 
00343     QString writeEntry(int trackerId, const QCA::CRL &v)
00344     {
00345         int at = findItem(trackerId);
00346         if(at == -1)
00347             return QString();
00348         Item &i = items[at];
00349 
00350         return i.owner->writeEntry(i.storeContextId, v);
00351     }
00352 
00353     QString writeEntry(int trackerId, const QCA::PGPKey &v)
00354     {
00355         int at = findItem(trackerId);
00356         if(at == -1)
00357             return QString();
00358         Item &i = items[at];
00359 
00360         return i.owner->writeEntry(i.storeContextId, v);
00361     }
00362 
00363     bool removeEntry(int trackerId, const QString &entryId)
00364     {
00365         int at = findItem(trackerId);
00366         if(at == -1)
00367             return false;
00368         Item &i = items[at];
00369         return i.owner->removeEntry(i.storeContextId, entryId);
00370     }
00371 
00372 signals:
00373     // emit this when items or busy state changes
00374     void updated();
00375     void updated_p();
00376 
00377 private slots:
00378     void updated_locked()
00379     {
00380         QMutexLocker locker(&updateMutex);
00381         emit updated();
00382     }
00383 
00384 private:
00385     bool haveProviderSource(Provider *p) const
00386     {
00387         foreach(KeyStoreListContext *ksl, sources)
00388         {
00389             if(ksl->provider() == p)
00390                 return true;
00391         }
00392         return false;
00393     }
00394 
00395     int findItem(int trackerId)
00396     {
00397         for(int n = 0; n < items.count(); ++n)
00398         {
00399             if(items[n].trackerId == trackerId)
00400                 return n;
00401         }
00402         return -1;
00403     }
00404 
00405     void startProvider(Provider *p)
00406     {
00407         KeyStoreListContext *c = static_cast<KeyStoreListContext *>(getContext("keystorelist", p));
00408         if(!c)
00409             return;
00410 
00411         sources += c;
00412         busySources += c;
00413         connect(c, SIGNAL(busyStart()), SLOT(ksl_busyStart()));
00414         connect(c, SIGNAL(busyEnd()), SLOT(ksl_busyEnd()));
00415         connect(c, SIGNAL(updated()), SLOT(ksl_updated()));
00416         connect(c, SIGNAL(diagnosticText(const QString &)), SLOT(ksl_diagnosticText(const QString &)));
00417         connect(c, SIGNAL(storeUpdated(int)), SLOT(ksl_storeUpdated(int)));
00418         c->start();
00419         c->setUpdatesEnabled(true);
00420 
00421         QCA_logTextMessage(QString("keystore: startProvider %1").arg(p->name()), Logger::Information);
00422     }
00423 
00424     bool updateStores(KeyStoreListContext *c)
00425     {
00426         bool changed = false;
00427 
00428         QMutexLocker locker(&m);
00429 
00430         QList<int> keyStores = c->keyStores();
00431 
00432         // remove any contexts that are gone
00433         for(int n = 0; n < items.count(); ++n)
00434         {
00435             if(items[n].owner == c && !keyStores.contains(items[n].storeContextId))
00436             {
00437                 QCA_logTextMessage(QString("keystore: updateStores remove %1").arg(items[n].storeContextId), Logger::Information);
00438 
00439                 items.removeAt(n);
00440                 --n; // adjust position
00441 
00442                 changed = true;
00443             }
00444         }
00445 
00446         // handle add/updates
00447         foreach(int id, keyStores)
00448         {
00449             // do we have it already?
00450             int at = -1;
00451             for(int n = 0; n < items.count(); ++n)
00452             {
00453                 if(items[n].owner == c && items[n].storeContextId == id)
00454                 {
00455                     at = n;
00456                     break;
00457                 }
00458             }
00459 
00460             // if so, update it
00461             if(at != -1)
00462             {
00463                 Item &i = items[at];
00464 
00465                 QString name = c->name(id);
00466                 bool isReadOnly = c->isReadOnly(id);
00467                 if(i.name != name || i.isReadOnly != isReadOnly)
00468                 {
00469                     QCA_logTextMessage(QString("keystore: updateStores update %1").arg(id), Logger::Information);
00470                     i.name = name;
00471                     i.isReadOnly = isReadOnly;
00472                     changed = true;
00473                 }
00474             }
00475             // otherwise, add it
00476             else
00477             {
00478                 QCA_logTextMessage(QString("keystore: updateStores add %1").arg(id), Logger::Information);
00479 
00480                 Item i;
00481                 i.trackerId = tracker_id_at++;
00482                 i.updateCount = 0;
00483                 i.owner = c;
00484                 i.storeContextId = id;
00485                 i.storeId = c->storeId(id);
00486                 i.name = c->name(id);
00487                 i.type = c->type(id);
00488                 i.isReadOnly = c->isReadOnly(id);
00489                 items += i;
00490 
00491                 changed = true;
00492             }
00493         }
00494 
00495         return changed;
00496     }
00497 
00498 private slots:
00499     void ksl_busyStart()
00500     {
00501         KeyStoreListContext *c = (KeyStoreListContext *)sender();
00502 
00503         QCA_logTextMessage(QString("keystore: ksl_busyStart %1").arg(c->provider()->name()), Logger::Information);
00504 
00505         if(!busySources.contains(c))
00506         {
00507             busySources += c;
00508 
00509             QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
00510             emit updated_p();
00511         }
00512     }
00513 
00514     void ksl_busyEnd()
00515     {
00516         KeyStoreListContext *c = (KeyStoreListContext *)sender();
00517 
00518         QCA_logTextMessage(QString("keystore: ksl_busyEnd %1").arg(c->provider()->name()), Logger::Information);
00519 
00520         busySources.remove(c);
00521         bool changed = updateStores(c);
00522         bool any_busy = !busySources.isEmpty();
00523 
00524         if(!any_busy)
00525         {
00526             m.lock();
00527             busy = false;
00528             m.unlock();
00529         }
00530 
00531         if(!any_busy || changed)
00532         {
00533             QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
00534             emit updated_p();
00535         }
00536     }
00537 
00538     void ksl_updated()
00539     {
00540         KeyStoreListContext *c = (KeyStoreListContext *)sender();
00541 
00542         QCA_logTextMessage(QString("keystore: ksl_updated %1").arg(c->provider()->name()), Logger::Information);
00543 
00544         bool changed = updateStores(c);
00545         if(changed)
00546         {
00547             QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
00548             emit updated_p();
00549         }
00550     }
00551 
00552     void ksl_diagnosticText(const QString &str)
00553     {
00554         QMutexLocker locker(&m);
00555         dtext += str;
00556         dtext = truncate_log(dtext, 100000);
00557     }
00558 
00559     void ksl_storeUpdated(int id)
00560     {
00561         KeyStoreListContext *c = (KeyStoreListContext *)sender();
00562 
00563         QCA_logTextMessage(QString("keystore: ksl_storeUpdated %1 %2").arg(c->provider()->name(), QString::number(id)), Logger::Information);
00564 
00565         QMutexLocker locker(&m);
00566         for(int n = 0; n < items.count(); ++n)
00567         {
00568             Item &i = items[n];
00569             if(i.owner == c && i.storeContextId == id)
00570             {
00571                 ++i.updateCount;
00572 
00573                 QCA_logTextMessage(QString("keystore: %1 updateCount = %2").arg(i.name, QString::number(i.updateCount)), Logger::Information);
00574 
00575                 QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
00576                 emit updated_p();
00577                 return;
00578             }
00579         }
00580     }
00581 };
00582 
00583 KeyStoreTracker *KeyStoreTracker::self = 0;
00584 
00585 //----------------------------------------------------------------------------
00586 // KeyStoreThread
00587 //----------------------------------------------------------------------------
00588 class KeyStoreThread : public SyncThread
00589 {
00590     Q_OBJECT
00591 public:
00592     KeyStoreTracker *tracker;
00593     QMutex call_mutex;
00594 
00595     KeyStoreThread(QObject *parent = 0) : SyncThread(parent)
00596     {
00597     }
00598 
00599     ~KeyStoreThread()
00600     {
00601         stop();
00602     }
00603 
00604     void atStart()
00605     {
00606         tracker = new KeyStoreTracker;
00607     }
00608 
00609     void atEnd()
00610     {
00611         delete tracker;
00612     }
00613 };
00614 
00615 //----------------------------------------------------------------------------
00616 // KeyStoreGlobal
00617 //----------------------------------------------------------------------------
00618 class KeyStoreManagerGlobal;
00619 
00620 Q_GLOBAL_STATIC(QMutex, ksm_mutex)
00621 static KeyStoreManagerGlobal *g_ksm = 0;
00622 
00623 class KeyStoreManagerGlobal
00624 {
00625 public:
00626     KeyStoreThread *thread;
00627 
00628     KeyStoreManagerGlobal()
00629     {
00630         thread = new KeyStoreThread;
00631         thread->moveToThread(QCoreApplication::instance()->thread());
00632         thread->start();
00633     }
00634 
00635     ~KeyStoreManagerGlobal()
00636     {
00637         delete thread;
00638     }
00639 };
00640 
00641 // this function is thread-safe
00642 static QVariant trackercall(const char *method, const QVariantList &args = QVariantList())
00643 {
00644     QVariant ret;
00645     bool ok;
00646 
00647     g_ksm->thread->call_mutex.lock();
00648     ret = g_ksm->thread->call(KeyStoreTracker::instance(), method, args, &ok);
00649     g_ksm->thread->call_mutex.unlock();
00650 
00651     Q_ASSERT(ok);
00652     if(!ok)
00653     {
00654         fprintf(stderr, "QCA: KeyStoreTracker call [%s] failed.\n", method);
00655         abort();
00656         return QVariant();
00657     }
00658     return ret;
00659 }
00660 
00661 //----------------------------------------------------------------------------
00662 // KeyStoreEntry
00663 //----------------------------------------------------------------------------
00664 class KeyStoreEntry::Private
00665 {
00666 public:
00667     bool accessible;
00668 
00669     Private()
00670     {
00671         accessible = false;
00672     }
00673 };
00674 
00675 KeyStoreEntry::KeyStoreEntry()
00676 :d(new Private)
00677 {
00678 }
00679 
00680 KeyStoreEntry::KeyStoreEntry(const QString &serialized)
00681 :d(new Private)
00682 {
00683     *this = fromString(serialized);
00684 }
00685 
00686 KeyStoreEntry::KeyStoreEntry(const KeyStoreEntry &from)
00687 :Algorithm(from), d(new Private(*from.d))
00688 {
00689 }
00690 
00691 KeyStoreEntry::~KeyStoreEntry()
00692 {
00693     delete d;
00694 }
00695 
00696 KeyStoreEntry & KeyStoreEntry::operator=(const KeyStoreEntry &from)
00697 {
00698     Algorithm::operator=(from);
00699     *d = *from.d;
00700     return *this;
00701 }
00702 
00703 bool KeyStoreEntry::isNull() const
00704 {
00705     return (!context() ? true : false);
00706 }
00707 
00708 bool KeyStoreEntry::isAvailable() const
00709 {
00710     return static_cast<const KeyStoreEntryContext *>(context())->isAvailable();
00711 }
00712 
00713 bool KeyStoreEntry::isAccessible() const
00714 {
00715     return d->accessible;
00716 }
00717 
00718 KeyStoreEntry::Type KeyStoreEntry::type() const
00719 {
00720     return static_cast<const KeyStoreEntryContext *>(context())->type();
00721 }
00722 
00723 QString KeyStoreEntry::name() const
00724 {
00725     return static_cast<const KeyStoreEntryContext *>(context())->name();
00726 }
00727 
00728 QString KeyStoreEntry::id() const
00729 {
00730     return static_cast<const KeyStoreEntryContext *>(context())->id();
00731 }
00732 
00733 QString KeyStoreEntry::storeName() const
00734 {
00735     return static_cast<const KeyStoreEntryContext *>(context())->storeName();
00736 }
00737 
00738 QString KeyStoreEntry::storeId() const
00739 {
00740     return static_cast<const KeyStoreEntryContext *>(context())->storeId();
00741 }
00742 
00743 QString KeyStoreEntry::toString() const
00744 {
00745     return static_cast<const KeyStoreEntryContext *>(context())->serialize();
00746 }
00747 
00748 KeyStoreEntry KeyStoreEntry::fromString(const QString &serialized)
00749 {
00750     KeyStoreEntry e;
00751     KeyStoreEntryContext *c = (KeyStoreEntryContext *)KeyStoreTracker::instance()->entryPassive(serialized);
00752     if(c)
00753         e.change(c);
00754     return e;
00755 }
00756 
00757 KeyBundle KeyStoreEntry::keyBundle() const
00758 {
00759     return static_cast<const KeyStoreEntryContext *>(context())->keyBundle();
00760 }
00761 
00762 Certificate KeyStoreEntry::certificate() const
00763 {
00764     return static_cast<const KeyStoreEntryContext *>(context())->certificate();
00765 }
00766 
00767 CRL KeyStoreEntry::crl() const
00768 {
00769     return static_cast<const KeyStoreEntryContext *>(context())->crl();
00770 }
00771 
00772 PGPKey KeyStoreEntry::pgpSecretKey() const
00773 {
00774     return static_cast<const KeyStoreEntryContext *>(context())->pgpSecretKey();
00775 }
00776 
00777 PGPKey KeyStoreEntry::pgpPublicKey() const
00778 {
00779     return static_cast<const KeyStoreEntryContext *>(context())->pgpPublicKey();
00780 }
00781 
00782 bool KeyStoreEntry::ensureAvailable()
00783 {
00784     QString storeId = this->storeId();
00785     QString entryId = id();
00786     KeyStoreEntryContext *c = (KeyStoreEntryContext *)qVariantValue<void*>(trackercall("entry", QVariantList() << storeId << entryId));
00787     if(c)
00788         change(c);
00789     return isAvailable();
00790 }
00791 
00792 bool KeyStoreEntry::ensureAccess()
00793 {
00794     if(!ensureAvailable())
00795     {
00796         d->accessible = false;
00797         return false;
00798     }
00799     bool ok = static_cast<KeyStoreEntryContext *>(context())->ensureAccess();
00800     d->accessible = ok;
00801     return d->accessible;
00802 }
00803 
00804 //----------------------------------------------------------------------------
00805 // KeyStoreEntryWatcher
00806 //----------------------------------------------------------------------------
00807 class KeyStoreEntryWatcher::Private : public QObject
00808 {
00809     Q_OBJECT
00810 public:
00811     KeyStoreEntryWatcher *q;
00812     KeyStoreManager ksm;
00813     KeyStoreEntry entry;
00814     QString storeId, entryId;
00815     KeyStore *ks;
00816     bool avail;
00817 
00818     Private(KeyStoreEntryWatcher *_q) : QObject(_q), q(_q), ksm(this)
00819     {
00820         ks = 0;
00821         avail = false;
00822         connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ksm_available(const QString &)));
00823     }
00824 
00825     ~Private()
00826     {
00827         delete ks;
00828     }
00829 
00830     void start()
00831     {
00832         QStringList list = ksm.keyStores();
00833         foreach(const QString &storeId, list)
00834             ksm_available(storeId);
00835     }
00836 
00837 private slots:
00838     void ksm_available(const QString &_storeId)
00839     {
00840         // we only care about one store
00841         if(_storeId == storeId)
00842         {
00843             ks = new KeyStore(storeId, &ksm);
00844             connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
00845             ks->startAsynchronousMode();
00846         }
00847     }
00848 
00849     void ks_updated()
00850     {
00851         bool found = false;
00852         QList<KeyStoreEntry> list = ks->entryList();
00853         foreach(const KeyStoreEntry &e, list)
00854         {
00855             if(e.id() == entryId && e.isAvailable())
00856             {
00857                 found = true;
00858                 if(!avail)
00859                     entry = e;
00860                 break;
00861             }
00862         }
00863 
00864         if(found && !avail)
00865         {
00866             avail = true;
00867             emit q->available();
00868         }
00869         else if(!found && avail)
00870         {
00871             avail = false;
00872             emit q->unavailable();
00873         }
00874     }
00875 
00876     void ks_unavailable()
00877     {
00878         delete ks;
00879         ks = 0;
00880 
00881         if(avail)
00882         {
00883             avail = false;
00884             emit q->unavailable();
00885         }
00886     }
00887 };
00888 
00889 KeyStoreEntryWatcher::KeyStoreEntryWatcher(const KeyStoreEntry &e, QObject *parent)
00890 :QObject(parent)
00891 {
00892     d = new Private(this);
00893     if(!e.isNull())
00894     {
00895         d->entry = e;
00896         d->storeId = e.storeId();
00897         d->entryId = e.id();
00898         d->start();
00899     }
00900 }
00901 
00902 KeyStoreEntryWatcher::~KeyStoreEntryWatcher()
00903 {
00904     delete d;
00905 }
00906 
00907 KeyStoreEntry KeyStoreEntryWatcher::entry() const
00908 {
00909     return d->entry;
00910 }
00911 
00912 //----------------------------------------------------------------------------
00913 // KeyStore
00914 //----------------------------------------------------------------------------
00915 // union thingy
00916 class KeyStoreWriteEntry
00917 {
00918 public:
00919     enum Type { TypeKeyBundle, TypeCertificate, TypeCRL, TypePGPKey };
00920 
00921     Type type;
00922     KeyBundle keyBundle;
00923     Certificate cert;
00924     CRL crl;
00925     PGPKey pgpKey;
00926 
00927     KeyStoreWriteEntry()
00928     {
00929     }
00930 
00931     KeyStoreWriteEntry(const KeyBundle &_keyBundle)
00932     :type(TypeKeyBundle), keyBundle(_keyBundle)
00933     {
00934     }
00935 
00936     KeyStoreWriteEntry(const Certificate &_cert)
00937     :type(TypeCertificate), cert(_cert)
00938     {
00939     }
00940 
00941     KeyStoreWriteEntry(const CRL &_crl)
00942     :type(TypeCRL), crl(_crl)
00943     {
00944     }
00945 
00946     KeyStoreWriteEntry(const PGPKey &_pgpKey)
00947     :type(TypePGPKey), pgpKey(_pgpKey)
00948     {
00949     }
00950 };
00951 
00952 class KeyStoreOperation : public QThread
00953 {
00954     Q_OBJECT
00955 public:
00956     enum Type { EntryList, WriteEntry, RemoveEntry };
00957 
00958     Type type;
00959     int trackerId;
00960 
00961     KeyStoreWriteEntry wentry; // in: WriteEntry
00962     QList<KeyStoreEntry> entryList; // out: EntryList
00963     QString entryId; // in: RemoveEntry, out: WriteEntry
00964     bool success; // out: RemoveEntry
00965 
00966     KeyStoreOperation(QObject *parent = 0)
00967     :QThread(parent)
00968     {
00969     }
00970 
00971     ~KeyStoreOperation()
00972     {
00973         wait();
00974     }
00975 
00976 protected:
00977     virtual void run()
00978     {
00979         if(type == EntryList)
00980             entryList = qVariantValue< QList<KeyStoreEntry> >(trackercall("entryList", QVariantList() << trackerId));
00981         else if(type == WriteEntry)
00982         {
00983             QVariant arg;
00984             if(wentry.type == KeyStoreWriteEntry::TypeKeyBundle)
00985                 qVariantSetValue<KeyBundle>(arg, wentry.keyBundle);
00986             else if(wentry.type == KeyStoreWriteEntry::TypeCertificate)
00987                 qVariantSetValue<Certificate>(arg, wentry.cert);
00988             else if(wentry.type == KeyStoreWriteEntry::TypeCRL)
00989                 qVariantSetValue<CRL>(arg, wentry.crl);
00990             else if(wentry.type == KeyStoreWriteEntry::TypePGPKey)
00991                 qVariantSetValue<PGPKey>(arg, wentry.pgpKey);
00992 
00993             // note: each variant in the argument list is resolved
00994             //   to its native type.  so even though it looks like
00995             //   we're attempting to call a method named
00996             //   writeEntry(QString,QVariant), we're actually
00997             //   calling one of many possible methods, such as
00998             //   writeEntry(QString,PGPKey) or
00999             //   writeEntry(QString,Certificate), etc, depending
01000             //   on the type of object we put in the variant.
01001             entryId = trackercall("writeEntry", QVariantList() << trackerId << arg).toString();
01002         }
01003         else // RemoveEntry
01004         {
01005             success = trackercall("removeEntry", QVariantList() << trackerId << entryId).toBool();
01006         }
01007     }
01008 };
01009 
01010 class KeyStorePrivate : public QObject
01011 {
01012     Q_OBJECT
01013 public:
01014     KeyStore *q;
01015     KeyStoreManager *ksm;
01016     int trackerId;
01017     KeyStoreTracker::Item item;
01018     bool async;
01019     bool need_update;
01020     QList<KeyStoreEntry> latestEntryList;
01021     QList<KeyStoreOperation*> ops;
01022 
01023     KeyStorePrivate(KeyStore *_q) : QObject(_q), q(_q), async(false)
01024     {
01025     }
01026 
01027     ~KeyStorePrivate()
01028     {
01029         qDeleteAll(ops);
01030     }
01031 
01032     // implemented below, after KeyStorePrivate is declared
01033     void reg();
01034     void unreg();
01035     KeyStoreTracker::Item *getItem(const QString &storeId);
01036     KeyStoreTracker::Item *getItem(int trackerId);
01037 
01038     void invalidate()
01039     {
01040         trackerId = -1;
01041         unreg();
01042     }
01043 
01044     bool have_entryList_op() const
01045     {
01046         foreach(KeyStoreOperation *op, ops)
01047         {
01048             if(op->type == KeyStoreOperation::EntryList)
01049                 return true;
01050         }
01051         return false;
01052     }
01053 
01054     void handle_updated()
01055     {
01056         if(async)
01057         {
01058             if(!have_entryList_op())
01059                 async_entryList();
01060             else
01061                 need_update = true;
01062         }
01063         else
01064             emit q->updated();
01065     }
01066 
01067     void async_entryList()
01068     {
01069         KeyStoreOperation *op = new KeyStoreOperation(this);
01070         // use queued for signal-safety
01071         connect(op, SIGNAL(finished()), SLOT(op_finished()), Qt::QueuedConnection);
01072         op->type = KeyStoreOperation::EntryList;
01073         op->trackerId = trackerId;
01074         ops += op;
01075         op->start();
01076     }
01077 
01078     void async_writeEntry(const KeyStoreWriteEntry &wentry)
01079     {
01080         KeyStoreOperation *op = new KeyStoreOperation(this);
01081         // use queued for signal-safety
01082         connect(op, SIGNAL(finished()), SLOT(op_finished()), Qt::QueuedConnection);
01083         op->type = KeyStoreOperation::WriteEntry;
01084         op->trackerId = trackerId;
01085         op->wentry = wentry;
01086         ops += op;
01087         op->start();
01088     }
01089 
01090     void async_removeEntry(const QString &entryId)
01091     {
01092         KeyStoreOperation *op = new KeyStoreOperation(this);
01093         // use queued for signal-safety
01094         connect(op, SIGNAL(finished()), SLOT(op_finished()), Qt::QueuedConnection);
01095         op->type = KeyStoreOperation::RemoveEntry;
01096         op->trackerId = trackerId;
01097         op->entryId = entryId;
01098         ops += op;
01099         op->start();
01100     }
01101 
01102 private slots:
01103     void op_finished()
01104     {
01105         KeyStoreOperation *op = (KeyStoreOperation *)sender();
01106 
01107         if(op->type == KeyStoreOperation::EntryList)
01108         {
01109             latestEntryList = op->entryList;
01110             ops.removeAll(op);
01111             delete op;
01112 
01113             if(need_update)
01114             {
01115                 need_update = false;
01116                 async_entryList();
01117             }
01118 
01119             emit q->updated();
01120         }
01121         else if(op->type == KeyStoreOperation::WriteEntry)
01122         {
01123             QString entryId = op->entryId;
01124             ops.removeAll(op);
01125             delete op;
01126 
01127             emit q->entryWritten(entryId);
01128         }
01129         else // RemoveEntry
01130         {
01131             bool success = op->success;
01132             ops.removeAll(op);
01133             delete op;
01134 
01135             emit q->entryRemoved(success);
01136         }
01137     }
01138 };
01139 
01140 KeyStore::KeyStore(const QString &id, KeyStoreManager *keyStoreManager)
01141 :QObject(keyStoreManager)
01142 {
01143     d = new KeyStorePrivate(this);
01144     d->ksm = keyStoreManager;
01145 
01146     KeyStoreTracker::Item *i = d->getItem(id);
01147     if(i)
01148     {
01149         d->trackerId = i->trackerId;
01150         d->item = *i;
01151         d->reg();
01152     }
01153     else
01154         d->trackerId = -1;
01155 }
01156 
01157 KeyStore::~KeyStore()
01158 {
01159     if(d->trackerId != -1)
01160         d->unreg();
01161     delete d;
01162 }
01163 
01164 bool KeyStore::isValid() const
01165 {
01166     return (d->getItem(d->trackerId) ? true : false);
01167 }
01168 
01169 KeyStore::Type KeyStore::type() const
01170 {
01171     return d->item.type;
01172 }
01173 
01174 QString KeyStore::name() const
01175 {
01176     return d->item.name;
01177 }
01178 
01179 QString KeyStore::id() const
01180 {
01181     return d->item.storeId;
01182 }
01183 
01184 bool KeyStore::isReadOnly() const
01185 {
01186     return d->item.isReadOnly;
01187 }
01188 
01189 void KeyStore::startAsynchronousMode()
01190 {
01191     if(d->async)
01192         return;
01193 
01194     d->async = true;
01195 
01196     // initial entrylist
01197     d->need_update = false;
01198     d->async_entryList();
01199 }
01200 
01201 QList<KeyStoreEntry> KeyStore::entryList() const
01202 {
01203     if(d->async)
01204         return d->latestEntryList;
01205 
01206     if(d->trackerId == -1)
01207         return QList<KeyStoreEntry>();
01208     return qVariantValue< QList<KeyStoreEntry> >(trackercall("entryList", QVariantList() << d->trackerId));
01209 }
01210 
01211 bool KeyStore::holdsTrustedCertificates() const
01212 {
01213     QList<KeyStoreEntry::Type> list;
01214     if(d->trackerId == -1)
01215         return false;
01216     list = qVariantValue< QList<KeyStoreEntry::Type> >(trackercall("entryTypes", QVariantList() << d->trackerId));
01217     if(list.contains(KeyStoreEntry::TypeCertificate) || list.contains(KeyStoreEntry::TypeCRL))
01218         return true;
01219     return false;
01220 }
01221 
01222 bool KeyStore::holdsIdentities() const
01223 {
01224     QList<KeyStoreEntry::Type> list;
01225     if(d->trackerId == -1)
01226         return false;
01227     list = qVariantValue< QList<KeyStoreEntry::Type> >(trackercall("entryTypes", QVariantList() << d->trackerId));
01228     if(list.contains(KeyStoreEntry::TypeKeyBundle) || list.contains(KeyStoreEntry::TypePGPSecretKey))
01229         return true;
01230     return false;
01231 }
01232 
01233 bool KeyStore::holdsPGPPublicKeys() const
01234 {
01235     QList<KeyStoreEntry::Type> list;
01236     if(d->trackerId == -1)
01237         return false;
01238     list = qVariantValue< QList<KeyStoreEntry::Type> >(trackercall("entryTypes", QVariantList() << d->trackerId));
01239     if(list.contains(KeyStoreEntry::TypePGPPublicKey))
01240         return true;
01241     return false;
01242 }
01243 
01244 QString KeyStore::writeEntry(const KeyBundle &kb)
01245 {
01246     if(d->async)
01247     {
01248         d->async_writeEntry(KeyStoreWriteEntry(kb));
01249         return QString();
01250     }
01251     else
01252     {
01253         QVariant arg;
01254         qVariantSetValue<KeyBundle>(arg, kb);
01255         return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
01256     }
01257 }
01258 
01259 QString KeyStore::writeEntry(const Certificate &cert)
01260 {
01261     if(d->async)
01262     {
01263         d->async_writeEntry(KeyStoreWriteEntry(cert));
01264         return QString();
01265     }
01266     else
01267     {
01268         QVariant arg;
01269         qVariantSetValue<Certificate>(arg, cert);
01270         return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
01271     }
01272 }
01273 
01274 QString KeyStore::writeEntry(const CRL &crl)
01275 {
01276     if(d->async)
01277     {
01278         d->async_writeEntry(KeyStoreWriteEntry(crl));
01279         return QString();
01280     }
01281     else
01282     {
01283         QVariant arg;
01284         qVariantSetValue<CRL>(arg, crl);
01285         return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
01286     }
01287 }
01288 
01289 QString KeyStore::writeEntry(const PGPKey &key)
01290 {
01291     if(d->async)
01292     {
01293         d->async_writeEntry(KeyStoreWriteEntry(key));
01294         return QString();
01295     }
01296     else
01297     {
01298         QVariant arg;
01299         qVariantSetValue<PGPKey>(arg, key);
01300         return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
01301     }
01302 }
01303 
01304 bool KeyStore::removeEntry(const QString &id)
01305 {
01306     if(d->async)
01307     {
01308         d->async_removeEntry(id);
01309         return false;
01310     }
01311     else
01312     {
01313         return trackercall("removeEntry", QVariantList() << d->trackerId << id).toBool();
01314     }
01315 }
01316 
01317 //----------------------------------------------------------------------------
01318 // KeyStoreManager
01319 //----------------------------------------------------------------------------
01320 static void ensure_init()
01321 {
01322     QMutexLocker locker(ksm_mutex());
01323     if(!g_ksm)
01324         g_ksm = new KeyStoreManagerGlobal;
01325 }
01326 
01327 // static functions
01328 void KeyStoreManager::start()
01329 {
01330     ensure_init();
01331     QMetaObject::invokeMethod(KeyStoreTracker::instance(), "start", Qt::QueuedConnection);
01332     trackercall("spinEventLoop");
01333 }
01334 
01335 void KeyStoreManager::start(const QString &provider)
01336 {
01337     ensure_init();
01338     QMetaObject::invokeMethod(KeyStoreTracker::instance(), "start", Qt::QueuedConnection, Q_ARG(QString, provider));
01339     trackercall("spinEventLoop");
01340 }
01341 
01342 QString KeyStoreManager::diagnosticText()
01343 {
01344     ensure_init();
01345 
01346     // spin one event cycle in the tracker, to receive any pending text.
01347     //   note that since trackercall also goes through the eventloop,
01348     //   this may end up doing two rounds.  probably no big deal.
01349     trackercall("spinEventLoop");
01350 
01351     return KeyStoreTracker::instance()->getDText();
01352 }
01353 
01354 void KeyStoreManager::clearDiagnosticText()
01355 {
01356     ensure_init();
01357     KeyStoreTracker::instance()->clearDText();
01358 }
01359 
01360 void KeyStoreManager::scan()
01361 {
01362     ensure_init();
01363     QMetaObject::invokeMethod(KeyStoreTracker::instance(), "scan", Qt::QueuedConnection);
01364 }
01365 
01366 void KeyStoreManager::shutdown()
01367 {
01368     QMutexLocker locker(ksm_mutex());
01369     delete g_ksm;
01370     g_ksm = 0;
01371 }
01372 
01373 // object
01374 class KeyStoreManagerPrivate : public QObject
01375 {
01376     Q_OBJECT
01377 public:
01378     KeyStoreManager *q;
01379 
01380     QMutex m;
01381     QWaitCondition w;
01382     bool busy;
01383     QList<KeyStoreTracker::Item> items;
01384     bool pending, waiting;
01385 
01386     QMultiHash<int,KeyStore*> keyStoreForTrackerId;
01387     QHash<KeyStore*,int> trackerIdForKeyStore;
01388 
01389     KeyStoreManagerPrivate(KeyStoreManager *_q) : QObject(_q), q(_q)
01390     {
01391         pending = false;
01392         waiting = false;
01393     }
01394 
01395     ~KeyStoreManagerPrivate()
01396     {
01397         // invalidate registered keystores
01398         QList<KeyStore*> list;
01399         QHashIterator<KeyStore*,int> it(trackerIdForKeyStore);
01400         while(it.hasNext())
01401         {
01402             it.next();
01403             list += it.key();
01404         }
01405         foreach(KeyStore *ks, list)
01406             ks->d->invalidate();
01407     }
01408 
01409     // for keystore
01410     void reg(KeyStore *ks, int trackerId)
01411     {
01412         keyStoreForTrackerId.insert(trackerId, ks);
01413         trackerIdForKeyStore.insert(ks, trackerId);
01414     }
01415 
01416     void unreg(KeyStore *ks)
01417     {
01418         int trackerId = trackerIdForKeyStore.take(ks);
01419 
01420         // this is the only way I know to remove one item from a multihash
01421         QList<KeyStore*> vals = keyStoreForTrackerId.values(trackerId);
01422         keyStoreForTrackerId.remove(trackerId);
01423         vals.removeAll(ks);
01424         foreach(KeyStore *i, vals)
01425             keyStoreForTrackerId.insert(trackerId, i);
01426     }
01427 
01428     KeyStoreTracker::Item *getItem(const QString &storeId)
01429     {
01430         for(int n = 0; n < items.count(); ++n)
01431         {
01432             KeyStoreTracker::Item *i = &items[n];
01433             if(i->storeId == storeId)
01434                 return i;
01435         }
01436         return 0;
01437     }
01438 
01439     KeyStoreTracker::Item *getItem(int trackerId)
01440     {
01441         for(int n = 0; n < items.count(); ++n)
01442         {
01443             KeyStoreTracker::Item *i = &items[n];
01444             if(i->trackerId == trackerId)
01445                 return i;
01446         }
01447         return 0;
01448     }
01449 
01450     void do_update()
01451     {
01452         // ksm doesn't have reset or state changes so we can
01453         //   use QPointer here for full SS.
01454         QPointer<QObject> self(this);
01455 
01456         bool newbusy = KeyStoreTracker::instance()->isBusy();
01457         QList<KeyStoreTracker::Item> newitems = KeyStoreTracker::instance()->getItems();
01458 
01459         if(!busy && newbusy)
01460         {
01461             emit q->busyStarted();
01462             if(!self)
01463                 return;
01464         }
01465         if(busy && !newbusy)
01466         {
01467             emit q->busyFinished();
01468             if(!self)
01469                 return;
01470         }
01471 
01472         QStringList here;
01473         QList<int> changed;
01474         QList<int> gone;
01475 
01476         // removed
01477         for(int n = 0; n < items.count(); ++n)
01478         {
01479             KeyStoreTracker::Item &i = items[n];
01480             bool found = false;
01481             for(int k = 0; k < newitems.count(); ++k)
01482             {
01483                 if(i.trackerId == newitems[k].trackerId)
01484                 {
01485                     found = true;
01486                     break;
01487                 }
01488             }
01489             if(!found)
01490                 gone += i.trackerId;
01491         }
01492 
01493         // changed
01494         for(int n = 0; n < items.count(); ++n)
01495         {
01496             KeyStoreTracker::Item &i = items[n];
01497             for(int k = 0; k < newitems.count(); ++k)
01498             {
01499                 if(i.trackerId == newitems[k].trackerId)
01500                 {
01501                     if(i.updateCount < newitems[k].updateCount)
01502                         changed += i.trackerId;
01503                     break;
01504                 }
01505             }
01506         }
01507 
01508         // added
01509         for(int n = 0; n < newitems.count(); ++n)
01510         {
01511             KeyStoreTracker::Item &i = newitems[n];
01512             bool found = false;
01513             for(int k = 0; k < items.count(); ++k)
01514             {
01515                 if(i.trackerId == items[k].trackerId)
01516                 {
01517                     found = true;
01518                     break;
01519                 }
01520             }
01521             if(!found)
01522                 here += i.storeId;
01523         }
01524 
01525         busy = newbusy;
01526         items = newitems;
01527 
01528         // signals
01529         foreach(int trackerId, gone)
01530         {
01531             KeyStore *ks = keyStoreForTrackerId.value(trackerId);
01532             if(ks)
01533             {
01534                 ks->d->invalidate();
01535                 emit ks->unavailable();
01536                 if(!self)
01537                     return;
01538             }
01539         }
01540 
01541         foreach(int trackerId, changed)
01542         {
01543             KeyStore *ks = keyStoreForTrackerId.value(trackerId);
01544             if(ks)
01545             {
01546                 ks->d->handle_updated();
01547                 if(!self)
01548                     return;
01549             }
01550         }
01551 
01552         foreach(const QString &storeId, here)
01553         {
01554             emit q->keyStoreAvailable(storeId);
01555             if(!self)
01556                 return;
01557         }
01558     }
01559 
01560 public slots:
01561     void tracker_updated()
01562     {
01563         QCA_logTextMessage(QString().sprintf("keystore: %p: tracker_updated start", q), Logger::Information);
01564 
01565         QMutexLocker locker(&m);
01566         if(!pending)
01567         {
01568             QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
01569             pending = true;
01570         }
01571         if(waiting && !KeyStoreTracker::instance()->isBusy())
01572         {
01573             busy = false;
01574             items = KeyStoreTracker::instance()->getItems();
01575             w.wakeOne();
01576         }
01577 
01578         QCA_logTextMessage(QString().sprintf("keystore: %p: tracker_updated end", q), Logger::Information);
01579     }
01580 
01581     void update()
01582     {
01583         m.lock();
01584         pending = false;
01585         m.unlock();
01586 
01587         do_update();
01588     }
01589 };
01590 
01591 // from KeyStorePrivate
01592 void KeyStorePrivate::reg()
01593 {
01594     ksm->d->reg(q, trackerId);
01595 }
01596 
01597 void KeyStorePrivate::unreg()
01598 {
01599     ksm->d->unreg(q);
01600 }
01601 
01602 KeyStoreTracker::Item *KeyStorePrivate::getItem(const QString &storeId)
01603 {
01604     return ksm->d->getItem(storeId);
01605 }
01606 
01607 KeyStoreTracker::Item *KeyStorePrivate::getItem(int trackerId)
01608 {
01609     return ksm->d->getItem(trackerId);
01610 }
01611 
01612 KeyStoreManager::KeyStoreManager(QObject *parent)
01613 :QObject(parent)
01614 {
01615     ensure_init();
01616     d = new KeyStoreManagerPrivate(this);
01617     KeyStoreTracker::instance()->addTarget(d);
01618     sync();
01619 }
01620 
01621 KeyStoreManager::~KeyStoreManager()
01622 {
01623     Q_ASSERT(KeyStoreTracker::instance());
01624     KeyStoreTracker::instance()->removeTarget(d);
01625     delete d;
01626 }
01627 
01628 bool KeyStoreManager::isBusy() const
01629 {
01630     return d->busy;
01631 }
01632 
01633 void KeyStoreManager::waitForBusyFinished()
01634 {
01635     d->m.lock();
01636     d->busy = KeyStoreTracker::instance()->isBusy();
01637     if(d->busy)
01638     {
01639         d->waiting = true;
01640         d->w.wait(&d->m);
01641         d->waiting = false;
01642     }
01643     d->m.unlock();
01644 }
01645 
01646 QStringList KeyStoreManager::keyStores() const
01647 {
01648     QStringList out;
01649     for(int n = 0; n < d->items.count(); ++n)
01650         out += d->items[n].storeId;
01651     return out;
01652 }
01653 
01654 void KeyStoreManager::sync()
01655 {
01656     d->busy = KeyStoreTracker::instance()->isBusy();
01657     d->items = KeyStoreTracker::instance()->getItems();
01658 }
01659 
01660 //----------------------------------------------------------------------------
01661 // KeyStoreInfo
01662 //----------------------------------------------------------------------------
01663 class KeyStoreInfo::Private : public QSharedData
01664 {
01665 public:
01666     KeyStore::Type type;
01667     QString id, name;
01668 };
01669 
01670 KeyStoreInfo::KeyStoreInfo()
01671 {
01672 }
01673 
01674 KeyStoreInfo::KeyStoreInfo(KeyStore::Type type, const QString &id, const QString &name)
01675 :d(new Private)
01676 {
01677     d->type = type;
01678     d->id = id;
01679     d->name = name;
01680 }
01681 
01682 KeyStoreInfo::KeyStoreInfo(const KeyStoreInfo &from)
01683 :d(from.d)
01684 {
01685 }
01686 
01687 KeyStoreInfo::~KeyStoreInfo()
01688 {
01689 }
01690 
01691 KeyStoreInfo & KeyStoreInfo::operator=(const KeyStoreInfo &from)
01692 {
01693     d = from.d;
01694     return *this;
01695 }
01696 
01697 bool KeyStoreInfo::isNull() const
01698 {
01699     return (d ? false: true);
01700 }
01701 
01702 KeyStore::Type KeyStoreInfo::type() const
01703 {
01704     return d->type;
01705 }
01706 
01707 QString KeyStoreInfo::id() const
01708 {
01709     return d->id;
01710 }
01711 
01712 QString KeyStoreInfo::name() const
01713 {
01714     return d->name;
01715 }
01716 
01717 }
01718 
01719 #include "qca_keystore.moc"

qca

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

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
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