]> vaikene.ee Git - evaf/commitdiff
Added the PswStorage module.
authorEnar Väikene <enar@vaikene.net>
Tue, 26 Jul 2011 12:08:02 +0000 (15:08 +0300)
committerEnar Väikene <enar@vaikene.net>
Tue, 26 Jul 2011 12:08:02 +0000 (15:08 +0300)
This module stores data for password generation and allows lookups using the name of the password.
The module also acts as an item model for auto-completion of the name field.

src/apps/PswGen/CMakeLists.txt
src/apps/PswGen/Storage/CMakeLists.txt [new file with mode: 0644]
src/apps/PswGen/Storage/iStorage [new file with mode: 0644]
src/apps/PswGen/Storage/istorage.h [new file with mode: 0644]
src/apps/PswGen/Storage/lib.h [new file with mode: 0644]
src/apps/PswGen/Storage/module.cpp [new file with mode: 0644]
src/apps/PswGen/Storage/module.h [new file with mode: 0644]
src/apps/PswGen/Storage/version.h [new file with mode: 0644]
src/apps/PswGen/Storage/version.rc [new file with mode: 0644]

index 64a26c54fb3c91643c202c6d213cb5c8660c62a0..c7c1db54fe73b80b5ab74fb9732e561805d52f0c 100644 (file)
@@ -2,4 +2,4 @@ set(eVaf_INCLUDE ${eVaf_INCLUDE} ${CMAKE_SOURCE_DIR}/src/apps/PswGen)
 
 add_subdirectory(GUI)
 add_subdirectory(Generator)
-#add_subdirectory(Storage)
+add_subdirectory(Storage)
diff --git a/src/apps/PswGen/Storage/CMakeLists.txt b/src/apps/PswGen/Storage/CMakeLists.txt
new file mode 100644 (file)
index 0000000..13722c3
--- /dev/null
@@ -0,0 +1,39 @@
+# Name of the target
+set(TARGET PswStorage)
+
+# Qt modules
+set(QT_USE_QTSQL TRUE)
+set(QT_DONT_USE_QTGUI TRUE)
+include(${QT_USE_FILE})
+
+# Needed for exporting symbols
+add_definitions(-DPSWGEN_STORAGE_LIBRARY)
+
+# Include files
+include_directories(${eVaf_INCLUDE})
+
+# Required eVaf libraries
+set(eVaf_LIBRARIES CommonLib PluginsLib)
+
+# Source files
+set(SRCS
+    module.cpp
+)
+
+# Header files for the meta-object compiler
+set(MOC_HDRS
+    module.h
+)
+
+# Version info resource file for Windows builds
+if(WIN32)
+    set(SRCS ${SRCS} version.rc)
+endif(WIN32)
+
+qt4_wrap_cpp(MOC_SRCS ${MOC_HDRS})
+
+add_library(${TARGET} SHARED ${SRCS} ${MOC_SRCS})
+
+target_link_libraries(${TARGET} ${QT_LIBRARIES} ${eVaf_LIBRARIES})
+
+install(TARGETS ${TARGET} DESTINATION bin)
diff --git a/src/apps/PswGen/Storage/iStorage b/src/apps/PswGen/Storage/iStorage
new file mode 100644 (file)
index 0000000..2e4711c
--- /dev/null
@@ -0,0 +1 @@
+#include "istorage.h"
diff --git a/src/apps/PswGen/Storage/istorage.h b/src/apps/PswGen/Storage/istorage.h
new file mode 100644 (file)
index 0000000..6560553
--- /dev/null
@@ -0,0 +1,133 @@
+/**
+ * @file PswGen/Storage/istorage.h
+ * @brief Interface for password storage modules
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#ifndef __PSWGEN_STORAGE_ISTORAGE_H
+#  define __PSWGEN_STORAGE_ISTORAGE_H
+
+#include "lib.h"
+
+#include <QObject>
+#include <QString>
+#include <QSharedData>
+#include <QExplicitlySharedDataPointer>
+
+class QAbstractItemModel;
+
+namespace eVaf {
+namespace PswGen {
+
+namespace Storage {
+
+/**
+ * Data stored for every password.
+ */
+class PSWGEN_STORAGE_EXPORT Data : public QSharedData
+{
+public:
+
+    Data()
+        : QSharedData()
+        , mModified(false)
+        , mLength(0)
+        , mFlags(0)
+    {}
+
+    Data(int l, uint f = 0)
+        : QSharedData()
+        , mModified(false)
+        , mLength(l)
+        , mFlags(f)
+    {}
+
+    /// Length of the generated password
+    inline int length() const { return mLength; }
+    inline void setLength(int value)
+    {
+        if (mLength != value) {
+            mLength = value;
+            mModified = true;
+        }
+    }
+
+    /// Optional flags for the password generator
+    inline uint flags() const { return mFlags; }
+    inline void setFlags(uint value)
+    {
+        if (mFlags != value) {
+            mFlags = value;
+            mModified = true;
+        }
+    }
+
+    /// Flag indicating that some fields are modified
+    bool modified() const { return mModified; }
+
+    /// Resets the modified flag
+    void reset() { mModified = false; }
+
+
+private:
+
+    bool mModified;
+    int mLength;
+    uint mFlags;
+
+};
+
+} // eVaf::PswGen::Storage
+
+/**
+ * Password storage interface.
+ *
+ * This interface is used to store options that were used to generate strong passwords.
+ */
+struct iStorage
+{
+
+    /**
+     * Saves the data record
+     * @param name Name of the password
+     * @param data Data for the password
+     * @return True if ok; false if failed
+     */
+    virtual bool save(QString const & name, QExplicitlySharedDataPointer<Storage::Data> data) = 0;
+
+    /**
+     * Returns a data record by the name
+     * @param name Name of the password
+     * @return Shared data pointer of the stored data record or invalid if not found
+     */
+    virtual QExplicitlySharedDataPointer<Storage::Data> query(QString const & name) const = 0;
+
+    /**
+     * Returns an item model with the names of all the stored passwords
+     *
+     * This function returns an item model with the names of all the stored passwords. Use the item
+     * model for auto completion.
+     */
+    virtual QAbstractItemModel * autoCompletionModel() = 0;
+
+};
+
+} // namespace eVaf::PswGen
+} // namespace eVaf
+
+Q_DECLARE_INTERFACE(eVaf::PswGen::iStorage, "eVaf.PswGen.iStorage/1.0")
+
+#endif // istorage.h
diff --git a/src/apps/PswGen/Storage/lib.h b/src/apps/PswGen/Storage/lib.h
new file mode 100644 (file)
index 0000000..2dbfa67
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * @file PswGen/Storage/lib.h
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#ifndef __PSWGEN_STORAGE_LIB_H
+#  define __PSWGEN_STORAGE_LIB_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(PSWGEN_STORAGE_LIBRARY)
+#  define PSWGEN_STORAGE_EXPORT Q_DECL_EXPORT
+#else
+#  define PSWGEN_STORAGE_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // libgen.h
diff --git a/src/apps/PswGen/Storage/module.cpp b/src/apps/PswGen/Storage/module.cpp
new file mode 100644 (file)
index 0000000..b0fd6af
--- /dev/null
@@ -0,0 +1,241 @@
+/**
+ * @file PswGen/Storage/module.cpp
+ * @brief Implementation of the iStorage interface
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#include "module.h"
+#include "version.h"
+
+#include <Common/Globals>
+#include <Common/iLogger>
+#include <Common/iRegistry>
+#include <Common/iEnv>
+
+#include <QtCore>
+#include <QtSql/QtSql>
+
+VER_EXPORT_VERSION_INFO()
+Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::PswGen::Storage::Module)
+
+using namespace eVaf;
+using namespace eVaf::PswGen;
+using namespace eVaf::PswGen::Storage;
+
+//-------------------------------------------------------------------
+
+Module::Module()
+    : Plugins::iPlugin()
+    , mReady(false)
+{
+    setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
+
+    mStorage = new Internal::StorageImpl;
+
+    EVAF_INFO("%s created", qPrintable(objectName()));
+}
+
+Module::~Module()
+{
+    delete mStorage;
+
+    EVAF_INFO("%s destroyed", qPrintable(objectName()));
+}
+
+bool Module::init(QString const & args)
+{
+    Q_UNUSED(args);
+
+    if (!mStorage->init())
+        return false;
+
+    mReady = true;
+
+    EVAF_INFO("%s initialized", qPrintable(objectName()));
+
+    return true;
+}
+
+void Module::done()
+{
+    mReady = false;
+
+    mStorage->done();
+
+    EVAF_INFO("%s finalized", qPrintable(objectName()));
+}
+
+
+//-------------------------------------------------------------------
+
+using namespace eVaf::PswGen::Storage::Internal;
+
+char const * const StorageImpl::DbConnectionName = "PswGenDB";
+
+char const * const StorageImpl::DbName = "PswGen.sqlite";
+
+StorageImpl::StorageImpl()
+    : QAbstractListModel()
+{
+    setObjectName(QString("%1.iGenerator").arg(VER_MODULE_NAME_STR));
+
+    EVAF_INFO("%s created", qPrintable(objectName()));
+}
+
+StorageImpl::~StorageImpl()
+{
+    EVAF_INFO("%s destroyed", qPrintable(objectName()));
+}
+
+bool StorageImpl::init()
+{
+    EVAF_INFO("%s initialized", qPrintable(objectName()));
+
+    // Open the database
+    if (!QSqlDatabase::contains(DbConnectionName)) {
+        // No database connection yet
+        mDb = QSqlDatabase::addDatabase("QSQLITE", DbConnectionName);
+        mDb.setDatabaseName(Common::iEnv::instance()->dataRootDir() + DbName);
+        if (!mDb.open()) {
+            QSqlError err = mDb.lastError();
+            EVAF_ERROR("Failed to open database : %s", qPrintable(err.text()));
+            return false;
+        }
+    }
+    else {
+        // Database connection already exists
+        mDb = QSqlDatabase::database(DbConnectionName);
+    }
+
+    // Create tables if necessary
+    if (!createTables())
+        return false;
+
+    // Load data
+    if (!loadData())
+        return false;
+
+    /// Register our interface
+    Common::iRegistry::instance()->registerInterface("iStorage", this);
+
+    return true;
+}
+
+void StorageImpl::done()
+{
+    mData.clear();
+    EVAF_INFO("%s finalized", qPrintable(objectName()));
+}
+
+bool StorageImpl::save(QString const & name, QExplicitlySharedDataPointer<Storage::Data> data)
+{
+    EVAF_TEST_X(data, "Data cannot be null");
+    EVAF_TEST_X(!name.isEmpty(), "Name cannot be empty");
+
+    // Is it an update or a new data record?
+    if (mData.constFind(name) != mData.constEnd()) {
+        // This is an update
+        if (data->modified()) {
+            QSqlQuery q(mDb);
+            if (!q.exec(QString("UPDATE data SET length = \'%1\', flags = \'%2\' WHERE name = \'%3\';").arg(data->length()).arg(data->flags()).arg(name))) {
+                QSqlError err = mDb.lastError();
+                EVAF_ERROR("Failed to update \'%s\' : %s", qPrintable(name), qPrintable(err.text()));
+                return false;
+            }
+        }
+    }
+    else {
+        // Store to the database
+        QSqlQuery q(mDb);
+        if (!q.exec(QString("INSERT INTO data (name, length, flags) VALUES ('\%1\', %2, %3);").arg(name).arg(data->length()).arg(int(data->flags())))) {
+            QSqlError err = mDb.lastError();
+            EVAF_ERROR("Failed to insert \'%s\' : %s", qPrintable(name), qPrintable(err.text()));
+            return false;
+        }
+
+        // Store also into the local hash
+        mData.insert(name, data);
+
+        // Reset the model
+        reset();
+    }
+
+    data->reset();
+
+    return true;
+}
+
+QExplicitlySharedDataPointer<Storage::Data> StorageImpl::query(QString const & name) const
+{
+    QMap<QString, QExplicitlySharedDataPointer<Storage::Data> >::const_iterator it = mData.constFind(name);
+    if (it != mData.constEnd())
+        return it.value();
+    else
+        return QExplicitlySharedDataPointer<Storage::Data>();
+}
+
+QVariant StorageImpl::data(QModelIndex const & index, int role) const
+{
+    if (!index.isValid() || index.row() < 0 || index.row() >= mData.size() || index.column() != 0)
+        return QVariant();
+
+    if (role == Qt::EditRole || role == Qt::DisplayRole)
+        return mData.keys().at(index.row());
+
+    return QVariant();
+}
+
+bool StorageImpl::createTables()
+{
+    QSqlQuery q(mDb);
+    if (!q.exec("SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'data\';")) {
+        QSqlError err = mDb.lastError();
+        EVAF_ERROR("Failed to query database : %s", qPrintable(err.text()));
+        return false;
+    }
+
+    if (q.isActive() && q.isSelect() && q.first())
+        return true; // We already have a table called 'data'
+
+    // Create the 'data' table
+    if (!q.exec("CREATE TABLE data (name text primary key not null, length integer, flags integer);")) {
+        QSqlError err = mDb.lastError();
+        EVAF_ERROR("Failed to create table \'data\' : %s", qPrintable(err.text()));
+        return false;
+    }
+
+    return true;
+}
+
+bool StorageImpl::loadData()
+{
+    QSqlQuery q(mDb);
+    if (!q.exec("SELECT name, length, flags FROM data;")) {
+        QSqlError err = mDb.lastError();
+        EVAF_ERROR("Failed to query database : %s", qPrintable(err.text()));
+        return false;
+    }
+
+    while (q.next()) {
+        QString name = q.value(0).toString();
+        QExplicitlySharedDataPointer<Storage::Data> data(new Storage::Data(q.value(1).toInt(), uint(q.value(2).toInt())));
+        mData.insert(name, data);
+    }
+
+    reset();
+
+    return true;
+}
diff --git a/src/apps/PswGen/Storage/module.h b/src/apps/PswGen/Storage/module.h
new file mode 100644 (file)
index 0000000..ae784e9
--- /dev/null
@@ -0,0 +1,156 @@
+/**
+ * @file PswGen/Storage/module.h
+ * @brief Implementation of the iStorage interface
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#ifndef __PSWGEN_STORAGE_MODULE_H
+#  define __PSWGEN_STORAGE_MODULE_H
+
+#include "istorage.h"
+
+#include <Plugins/iPlugin>
+
+#include <QObject>
+#include <QString>
+#include <QAbstractListModel>
+#include <QMap>
+#include <QtSql/QSqlDatabase>
+
+
+namespace eVaf {
+namespace PswGen {
+
+/// Module that stores options for strong passwords
+namespace Storage {
+
+/// Internal implementation of the Storage module
+namespace Internal {
+    class StorageImpl;
+} // namespace eVaf::PswGen::Storage::Internal
+
+/**
+ * Module implementing the iStorage interface.
+ */
+class Module : public Plugins::iPlugin
+{
+    Q_OBJECT
+
+public:
+
+    Module();
+
+    virtual ~Module();
+
+    virtual bool init(QString const & args);
+
+    virtual void done();
+
+    virtual bool isReady() const { return mReady; }
+
+
+private: // Members
+
+    /// Flag indicating that the module is ready
+    bool mReady;
+
+    /// iStorage interface instance
+    Internal::StorageImpl * mStorage;
+
+};
+
+
+namespace Internal {
+
+/**
+ * iStorage interface implementation.
+ *
+ * Implements the iStorage interface using a simple file storage.
+ */
+
+class StorageImpl : public QAbstractListModel, public iStorage
+{
+    Q_OBJECT
+    Q_INTERFACES(eVaf::PswGen::iStorage)
+
+public:
+
+    StorageImpl();
+
+    virtual ~StorageImpl();
+
+    bool init();
+
+    void done();
+
+    /*
+        iStorage interface
+    */
+
+    virtual bool save(QString const & name, QExplicitlySharedDataPointer<Storage::Data> data);
+
+    virtual QExplicitlySharedDataPointer<Storage::Data> query(QString const & name) const;
+
+    virtual QAbstractItemModel * autoCompletionModel() { return this; }
+
+    /*
+        QAbstractListModel methods
+    */
+
+    virtual int rowCount(QModelIndex const & parent) const { return mData.count(); }
+
+    virtual QVariant data(QModelIndex const & index, int role = Qt::DisplayRole) const;
+
+
+private: // Members
+
+    /// Name of the database connection
+    static char const * const DbConnectionName;
+
+    /// Name of the database file without path
+    static char const * const DbName;
+
+    /// Database connection
+    QSqlDatabase mDb;
+
+    /// List of name/data pairs
+    QMap<QString, QExplicitlySharedDataPointer<Storage::Data> > mData;
+
+
+private: // Methods
+
+    /**
+     * Creates database tables if necessary
+     * @return True if ok; false if failed
+     */
+    bool createTables();
+
+    /**
+     * Loads data from the database
+     * @return True if ok; false if failed
+     */
+    bool loadData();
+
+};
+
+} // namespace eVaf::PswGen::Storage::Internal
+
+
+} // namespace eVaf::PswGen::Storage
+} // namespace eVaf::PswGen
+} // namespace eVaf
+
+#endif // module.h
diff --git a/src/apps/PswGen/Storage/version.h b/src/apps/PswGen/Storage/version.h
new file mode 100644 (file)
index 0000000..33eaa3d
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * @file PswGen/Storage/version.h
+ * @brief Version information for eVaf modules
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#ifndef __PSWGEN_STORAGE_VERSION_H
+#define __PSWGEN_STORAGE_VERSION_H
+
+#include <version_rc.h>
+
+/**
+ * Module/library version number in the form major,minor,release,build
+ */
+#define VER_FILE_VERSION                0,1,1,1
+
+/**
+ * Module/library version number in the string format (shall end with \0)
+ */
+#define VER_FILE_VERSION_STR            "0.1.1.1\0"
+
+/**
+ * Module/library name (shall end with \0)
+ */
+#define VER_MODULE_NAME_STR             "PswStorage\0"
+
+/**
+ * Module type (see version_rc.h for all the types)
+ */
+#define VER_MODULE_TYPE                 MT_GENERIC
+
+/**
+ * Module type in the string format (see version_rc for all the types)
+ */
+#define VER_MODULE_TYPE_STR             MT_GENERIC
+
+/**
+ * Original file name for windows (shall end with \0)
+ */
+#define VER_ORIGINAL_FILE_NAME_STR      "PswStorage.dll\0"
+
+/**
+ * Description of the module/library (shall end with \0)
+ */
+#define VER_FILE_DESCRIPTION_STR         "Module that stores data for generating strong passwords.\0"
+
+#endif // version.h
diff --git a/src/apps/PswGen/Storage/version.rc b/src/apps/PswGen/Storage/version.rc
new file mode 100644 (file)
index 0000000..33672fb
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * @file PswGen/Generator/version.rc
+ * @brief Windows resource file with module/library version information.
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#include "version.h"
+#include <version_rc.h>
+#include <winver.h>
+
+
+VS_VERSION_INFO VERSIONINFO
+        FILEVERSION VER_FILE_VERSION
+        PRODUCTVERSION VER_PRODUCT_VERSION
+        FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+        FILEFLAGS VS_FF_DEBUG
+#else
+        FILEFLAGS 0x0L
+#endif
+        FILEOS VOS__WINDOWS32
+        FILETYPE VFT_DLL
+        FILESUBTYPE 0x0L
+        BEGIN
+                BLOCK "StringFileInfo"
+                BEGIN
+                        BLOCK "040904B0"
+                        BEGIN
+                                VALUE "CompanyName", VER_COMPANY_NAME_STR
+                                VALUE "FileDescription", VER_FILE_DESCRIPTION_STR
+                                VALUE "FileVersion", VER_FILE_VERSION_STR
+                                VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT_STR
+                                VALUE "OriginalFilename", VER_ORIGINAL_FILE_NAME_STR
+                                VALUE "ProductName", VER_PRODUCT_NAME_STR
+                                VALUE "ProductVersion", VER_PRODUCT_VERSION_STR
+                                VALUE "Build Date", VER_PRODUCT_DATE_STR
+                                VALUE "Module Name", VER_MODULE_NAME_STR
+                                VALUE "Module Type", VER_MODULE_TYPE_STR
+                        END
+                END
+        END