diff --git a/src/certificatemodel.cpp b/src/certificatemodel.cpp index 4a37eb6892b68c1a78eb5e5eecacdcfbaa72fe5c..8f9c05e63113fdf827d238d7a6759bea54e02ded 100644 --- a/src/certificatemodel.cpp +++ b/src/certificatemodel.cpp @@ -102,6 +102,7 @@ public: CertificateNode* m_pDefaultCategory ; QMutex m_CertLoader ; QHash<const Account*,CertificateNode*> m_hAccToCat ; + QHash<const QString&,CertificateNode*> m_hStrToCat ; QHash<const Certificate*,CertificateNode*> m_hNodes ; //Singleton @@ -141,7 +142,10 @@ CertificateModel::CertificateModel(QObject* parent) : QAbstractItemModel(parent) { setObjectName("CertificateModel"); //TODO replace with something else - m_pFallbackCollection = addCollection<FolderCertificateCollection>(); + m_pFallbackCollection = addCollection<FolderCertificateCollection,QString,FlagPack<FolderCertificateCollection::Options>, QString>(QString(), + FolderCertificateCollection::Options::FALLBACK | FolderCertificateCollection::Options::READ_WRITE, + QObject::tr("Local certificate store") + ); m_pFallbackCollection->load(); } @@ -203,6 +207,8 @@ CertificateNode* CertificateModelPrivate::createCategory(const QString& name, co m_lTopLevelNodes << n; q_ptr->endInsertRows(); + m_hStrToCat[name] = n; + return n; } @@ -479,7 +485,7 @@ Certificate* CertificateModel::getCertificate(const QUrl& path, Certificate::Typ } //TODO Make this private -Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawContent, Account* a, bool save) +Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawContent, Account* a, bool save, const QString& category) { QCryptographicHash hash(QCryptographicHash::Sha1); hash.addData(rawContent); @@ -492,7 +498,17 @@ Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawCo cert = new Certificate(rawContent); d_ptr->m_hCertificates[id] = cert; - d_ptr->addToTree(cert,a); + if ((!a) && (!category.isEmpty())) { + CertificateNode* cat = d_ptr->m_hStrToCat[category]; + + if (!cat) { + cat = d_ptr->createCategory(category, QString(), QString()); + } + + d_ptr->addToTree(cert,cat); + } + else + d_ptr->addToTree(cert,a); if (save) { //TODO this shouldn't be necessary @@ -505,6 +521,11 @@ Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawCo return cert; } +Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawContent, const QString& category, bool save) +{ + return getCertificateFromContent(rawContent,nullptr,save,category); +} + CertificateProxyModel::CertificateProxyModel(CertificateModel* parent, CertificateNode* root) : QAbstractProxyModel(parent),m_pRoot(root) { //For debugging diff --git a/src/certificatemodel.h b/src/certificatemodel.h index b9c2576d2c271641ae4452fe3f445342dcf6ef96..ad29b7d77e6037034153ac41f7d33c05039c1f5b 100644 --- a/src/certificatemodel.h +++ b/src/certificatemodel.h @@ -78,7 +78,8 @@ public: //Mutator Certificate* getCertificate(const QUrl& path, Certificate::Type type = Certificate::Type::NONE); Certificate* getCertificate(const QUrl& path, Account* a); - Certificate* getCertificateFromContent(const QByteArray& rawContent, Account* a = nullptr, bool save = true); + Certificate* getCertificateFromContent(const QByteArray& rawContent, Account* a = nullptr, bool save = true, const QString& category = QString()); + Certificate* getCertificateFromContent(const QByteArray& rawContent, const QString& category, bool save = true); //Singleton static CertificateModel* instance(); diff --git a/src/foldercertificatecollection.cpp b/src/foldercertificatecollection.cpp index fa73d175a958a9bfc3d1a59953b0f5bce102ae98..78c09d98b5f2d93cd2fe5948ec7748f320384be6 100644 --- a/src/foldercertificatecollection.cpp +++ b/src/foldercertificatecollection.cpp @@ -28,26 +28,7 @@ //Ring #include "certificate.h" #include "certificatemodel.h" - -/* - -QUrl KDECertificateSerializationDelegate::saveCertificate(const QByteArray& id, const QByteArray& content) -{ - -} - -bool KDECertificateSerializationDelegate::deleteCertificate(const QByteArray& id) -{ - Q_UNUSED(id) - QMutexLocker(&this->m_Mutex); - return false; -} - -QList<QByteArray> KDECertificateSerializationDelegate::listCertificates() -{ - -} - * */ +#include "delegates/pixmapmanipulationdelegate.h" class FallbackLocalCertificateEditor : public CollectionEditor<Certificate> { @@ -60,7 +41,7 @@ public: virtual bool addExisting( const Certificate* item ) override; QVector<Certificate*> m_lItems; - QString m_Path ; + QString m_Path ; QHash<const Certificate*,QString> m_hPaths; private: @@ -74,10 +55,9 @@ public: BackgroundLoader(FolderCertificateCollection* parent); //Attributes - QList<QByteArray> m_lIdList ; QMutex m_LoaderMutex; - QList<QByteArray> m_lQueue ; - FolderCertificateCollection* m_pFallbackCollection; + FolderCertificateCollection* m_pCurrentFolder; + QList<FolderCertificateCollection*> m_lFolderQueue; //Helpers QByteArray loadCertificate(const QByteArray& id); @@ -93,18 +73,53 @@ class FolderCertificateCollectionPrivate { public: + //Attributes + FlagPack<FolderCertificateCollection::Options> m_Flags; + QString m_Path ; + QString m_Name ; + bool m_IsValid ; + FolderCertificateCollection* m_pParent ; + static bool m_sHasFallbackStore; + FolderCertificateCollection* q_ptr ; + static BackgroundLoader* m_spLoader ; + //Helper QList<CollectionInterface::Element> getCertificateList(); }; -FolderCertificateCollection::FolderCertificateCollection(CollectionMediator<Certificate>* mediator, - const QString& path , - const FlagPack<Options>& options , - const QString& name +bool FolderCertificateCollectionPrivate::m_sHasFallbackStore = false; +BackgroundLoader* FolderCertificateCollectionPrivate::m_spLoader = nullptr; + +FolderCertificateCollection::FolderCertificateCollection(CollectionMediator<Certificate>* mediator, + const QString& path , + const FlagPack<Options>& options , + const QString& name , + FolderCertificateCollection* p ) : -CollectionInterface(new FallbackLocalCertificateEditor(mediator,path)),d_ptr(new FolderCertificateCollectionPrivate()) +CollectionInterface(new FallbackLocalCertificateEditor(mediator,path),p),d_ptr(new FolderCertificateCollectionPrivate()) { + d_ptr->q_ptr = this ; + d_ptr->m_Flags = options; + d_ptr->m_Path = path ; + d_ptr->m_Name = name ; + d_ptr->m_pParent = p ; + d_ptr->m_IsValid = true ; + if (path.isEmpty()) { + d_ptr->m_Path = QStandardPaths::writableLocation(QStandardPaths::DataLocation)+"/certs/"; + + d_ptr->m_IsValid = !FolderCertificateCollectionPrivate::m_sHasFallbackStore; + + if (!d_ptr->m_IsValid) { + qWarning() << "A fallback certificat store already exist, doing nothing"; + } + + FolderCertificateCollectionPrivate::m_sHasFallbackStore = true; + } + + if (name.isEmpty()) { + d_ptr->m_Name = d_ptr->m_Path; + } } FolderCertificateCollection::~FolderCertificateCollection() @@ -115,7 +130,7 @@ FolderCertificateCollection::~FolderCertificateCollection() QByteArray BackgroundLoader::loadCertificate(const QByteArray& id) { // QMutexLocker(&this->m_Mutex); - QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation)+"/certs/" + id + ".pem"); + QFile file(id); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Error opening certificate: " << id; return QByteArray(); @@ -126,17 +141,24 @@ QByteArray BackgroundLoader::loadCertificate(const QByteArray& id) bool FolderCertificateCollection::load() { - //Load the stored certificates - BackgroundLoader* loader = new BackgroundLoader(this); - QObject::connect(loader, SIGNAL(finished()), loader, SLOT(deleteLater())); - - /*if (!loader->isFinished()) - connect(loader,&BackgroundLoader::finished,[loader](){ - delete loader; - });*/ - - loader->start(); - return true; + if (d_ptr->m_IsValid) { + //Load the stored certificates + if (!d_ptr->m_spLoader) { + d_ptr->m_spLoader = new BackgroundLoader(this); + QObject::connect(d_ptr->m_spLoader, SIGNAL(finished()), d_ptr->m_spLoader, SLOT(deleteLater())); + } + + /*if (!loader->isFinished()) + connect(loader,&BackgroundLoader::finished,[loader](){ + delete loader; + });*/ + + d_ptr->m_spLoader->m_lFolderQueue << this; + + if (!d_ptr->m_spLoader->isRunning()) + d_ptr->m_spLoader->start(); + return true; + } return false; } @@ -157,7 +179,7 @@ bool FolderCertificateCollection::clear() QString FolderCertificateCollection::name() const { - return QObject::tr("Local certificate store"); + return d_ptr->m_Name; } QString FolderCertificateCollection::category() const @@ -167,7 +189,7 @@ QString FolderCertificateCollection::category() const QVariant FolderCertificateCollection::icon() const { - return QVariant(); + return PixmapManipulationDelegate::instance()->collectionIcon(this,PixmapManipulationDelegate::CollectionIconHint::CERTIFICATE); } bool FolderCertificateCollection::isEnabled() const @@ -207,7 +229,7 @@ bool FallbackLocalCertificateEditor::save( const Certificate* item) { Q_UNUSED(item) /*QMutexLocker(&this->m_Mutex); - QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); + QDir dir(m_Path); dir.mkdir("certs/"); @@ -269,7 +291,7 @@ QVector<Certificate*> FallbackLocalCertificateEditor::items() const ******************************************************************************/ BackgroundLoader::BackgroundLoader(FolderCertificateCollection* parent) : QThread(nullptr), -m_pFallbackCollection(parent) +m_pCurrentFolder(parent) { } @@ -277,14 +299,28 @@ m_pFallbackCollection(parent) QList<CollectionInterface::Element> FolderCertificateCollectionPrivate::getCertificateList() { // QMutexLocker(&this->m_Mutex); - QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)+"/certs/"); + QDir dir(m_Path); if (!dir.exists()) return QList<QByteArray>(); QList<QByteArray> ret; - for (const QString& str : dir.entryList({"*.pem"}) ) { - ret << str.left(str.size()-4).toLatin1(); + for (const QString& str : dir.entryList({"*.pem","*.crt"}) ) { + ret << (m_Path + "/" + str).toLatin1(); + } + + if (m_Flags & FolderCertificateCollection::Options::RECURSIVE) { + for (const QString& d : dir.entryList(QDir::AllDirs)) { + if (d != QString('.') && d != "..") { + CertificateModel::instance()->addCollection<FolderCertificateCollection,QString,FlagPack<FolderCertificateCollection::Options>,QString,FolderCertificateCollection*>( + m_Path+'/'+d , + m_Flags , + d , + q_ptr , + LoadOptions::FORCE_ENABLED + ); + } + } } return ret; @@ -292,14 +328,16 @@ QList<CollectionInterface::Element> FolderCertificateCollectionPrivate::getCerti void BackgroundLoader::run() { - if (m_lIdList.isEmpty()) //WARNING potential race - m_lIdList = m_pFallbackCollection->listId(); - - QMutexLocker(&this->m_LoaderMutex); - for(const QByteArray& id : m_lIdList) { - Certificate* cert = CertificateModel::instance()->getCertificateFromContent(loadCertificate(id),nullptr,false); - m_pFallbackCollection->editor<Certificate>()->addExisting(cert); + while (m_lFolderQueue.size()) { + m_pCurrentFolder = m_lFolderQueue.takeFirst(); + + QMutexLocker(&this->m_LoaderMutex); + for(const QByteArray& id : m_pCurrentFolder->listId()) { + Certificate* cert = CertificateModel::instance()->getCertificateFromContent(loadCertificate(id),m_pCurrentFolder->name(),false); + m_pCurrentFolder->editor<Certificate>()->addExisting(cert); + } } + FolderCertificateCollectionPrivate::m_spLoader = nullptr; QThread::exit(0); } diff --git a/src/foldercertificatecollection.h b/src/foldercertificatecollection.h index b001a571c784b95cc216c8aae12e92d49f856098..20928fe1153a108e35f2975fcff7676e8577d324 100644 --- a/src/foldercertificatecollection.h +++ b/src/foldercertificatecollection.h @@ -33,20 +33,25 @@ template<typename T> class CollectionMediator; */ class LIB_EXPORT FolderCertificateCollection : public CollectionInterface { + friend class BackgroundLoader; + public: ///@enum Options load and behavior parameters for a FolderCertificateCollection enum class Options { - READ_WRITE = 0 << 0, /*!< Try to add certificates to that store (default) */ - READ_ONLY = 1 << 0, /*!< Do not try to add certificate to that store */ - RECURSIVE = 1 << 1, /*!< Read all sub-folders recursively */ - TOP_LEVEL = 1 << 2, /*!< Consider those certificates as top-level entities */ + READ_WRITE = 0 << 0, /*!< Try to add certificates to that store (default) */ + READ_ONLY = 1 << 0, /*!< Do not try to add certificate to that store */ + RECURSIVE = 1 << 1, /*!< Read all sub-folders recursively */ + ROOT = 1 << 2, /*!< Consider those certificates as top-level entities */ + FALLBACK = 1 << 3, /*!< Consider this folder the default destination for volatile certificates */ }; explicit FolderCertificateCollection(CollectionMediator<Certificate>* mediator, - const QString& path = QString(), - const FlagPack<Options>& options = Options::READ_WRITE, - const QString& name = QString() + const QString& path = QString(), + const FlagPack<Options>& options = Options::READ_WRITE, + const QString& name = QString(), + FolderCertificateCollection* parent = nullptr ); + virtual ~FolderCertificateCollection(); virtual bool load () override; diff --git a/src/typedefs.h b/src/typedefs.h index 09ca00d574d485a95c6c96b1d384b38b608f4db5..778e59c95b6cb18c7a7a092532d77b79583aa142 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -73,7 +73,9 @@ template<class T> class LIB_EXPORT FlagPack { public: + FlagPack() : m_Flags(0) {} FlagPack(const T& base) : m_Flags(static_cast<int>(base)) {} + FlagPack(const FlagPack<T>& other) : m_Flags(other.m_Flags) {} //Operator FlagPack<T>& operator|(const T& other) { @@ -94,6 +96,11 @@ public: return FlagPack<T>(m_Flags & other.m_Flags); } + FlagPack<T>&operator=(const FlagPack<T>& other) { + m_Flags = other.m_Flags; + return *this; + } + bool operator!=(const T& other) { return m_Flags != static_cast<int>(other); }