X-Git-Url: https://vaikene.ee/gitweb/gitweb.cgi?p=evaf;a=blobdiff_plain;f=www%2Fpswgen03.html;fp=www%2Fpswgen03.html;h=056da8e42145a4b3c1f15656e206c67b8cb92497;hp=0000000000000000000000000000000000000000;hb=368818c22af812ac35f5ff69423522dbd54d37ed;hpb=3352f7acc232104985807b9f470cb12bcb2b47c2 diff --git a/www/pswgen03.html b/www/pswgen03.html new file mode 100644 index 0000000..056da8e --- /dev/null +++ b/www/pswgen03.html @@ -0,0 +1,334 @@ + + + + + + eVaf Tutorial - 03 - Generator Module + + + + + + + + + +

eVaf Tutorial

+ +

03 - Generator Module

+ +

In this section we write the Generator module. According to the specification, the Generator module has to + generate strong passwords in such a way that by feeding the module with the same input data we always get the + same password.

+ +

iGenerator interface

+ +

We start by defining the interface for the module. For this create the file igenerator.h in the + src/apps/pswGen/Generator directory:

+ +
/**
+ * @file src/apps/PswGen/Generator/igenerator.h
+ */
+#ifndef __PSWGEN_GENERATOR_IGENERATOR_H
+#  define __PSWGEN_GENERATOR_IGENERATOR_H
+
+#endif // igenerator.h
+ +

The interface class needs to be derived from QObject and we also need QString for input + data and generated passwords:

+ +
#include <QObject>
+#include <QString>
+ +

To avoid potential name collisions with other existing or future modules, we use the eVaf::PswGen + namespace for this application:

+ +
namespace eVaf {
+namespace PswGen {
+
+} // namespace eVaf::PswGen
+} // namespace eVaf
+ +

We call the interface class iGenerator: + +

class iGenerator : public QObject
+{
+    Q_OBJECT
+public:
+};
+ +

All the interface classes need a default constructor and an empty virtual destructor. Do not perform any actions + in these constructors and destructors. Instead, leave it up to the class that implements the interface.

+
/// Interface constructor
+iGenerator() : QObject() {}
+
+/// Empty virtual destructor
+virtual ~iGenerator() {}
+ +

Now we add the functionality to the interface and according to the specification we need two functions -- one that + generates passwords and another that returns the maximum length of the password:

+ +
virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const = 0;
+
+virtual int maxLength() const = 0;
+ +

I am training myself to use the style of writing declarations like "QString const &", which refers to a non-mutable QString object similar to "int maxLength() const", which is a function that does not modify the object's data members. Feel free to use the traditional way of writing "const QString &" if this looks weird to you.

+ +

The iGenerator interface needs to be visible for other modules and marked for export. We do this by creating the src/apps/PswGen/Generator/lib.h file, which defines the PSWGEN_GENERATOR_EXPORT macro:

+
/**
+ * @file src/apps/PswGen/Generator/lib.h
+ */
+#ifndef __PSWGEN_GENERATOR_LIB_H
+#  define __PSWGEN_GENERATOR_LIB_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(PSWGEN_GENERATOR_LIBRARY)
+#  define PSWGEN_GENERATOR_EXPORT Q_DECL_EXPORT
+#else
+#  define PSWGEN_GENERATOR_EXPORT Q_DECL_IMPORT
+#endif
+#endif // libgen.h
+ +

Then we include this new header file in our interface header file and modify the iGenerator class definition by adding + the PSWGEN_GENERATOR_EXPORT macro to it:

+
#include "lib.h"
+
+/// ...
+
+class PSWGEN_GENERATOR_EXPORT iGenerator : public QObject
+ +

This is pretty much all we need to add to the iGenerator interface and here is the final file:

+ +
/**
+ * @file src/apps/PswGen/Generator/igenerator.h
+ */
+
+#ifndef __PSWGEN_GENERATOR_IGENERATOR_H
+#  define __PSWGEN_GENERATOR_IGENERATOR_H
+
+#include "lib.h"
+
+#include <QObject>
+#include <QString>
+
+namespace eVaf {
+namespace PswGen {
+
+/// Password generator interface.
+class PSWGEN_GENERATOR_EXPORT iGenerator : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    /// Interface constructor
+    iGenerator() : QObject() {}
+
+    /// Empty virtual destructor
+    virtual ~iGenerator() {}
+
+    /// Generates a strong password
+    virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const = 0;
+
+    /// Returns the maximum length of generated passwords
+    virtual int maxLength() const = 0;
+
+};
+
+} // namespace eVaf::PswGen
+} // namespace eVaf
+
+#endif // igenerator.h
+
+ +

As a final touch, we create a file called iGenerator with the following content:

+
#include "igenerator.h"
+ +

With this file in place other modules can use #include "Generator/iGenerator" instead of #include "Generator/igenerator.h" similar to other eVaf and Qt include files.

+ +

Generator module

+ +

Now we write the Generator module itself. The module class has to be derived from the Plugins::iPlugin interface class + with or without the Plugins::iPluginFactory factory class.

+ +

The Plugins::iPluginFactory factory class should be used when more than one plugins are implemented by the same + module. The factory class takes care of creating individual plugins whenever they are instantiated. This module implements only + one plugin and we opt to the implementation without the factory class.

+ +

Create the module.h header file in the src/apps/PswGen/Generator directory:

+ +
/**
+ * @file src/apps/PswGen/Generator/module.h
+ */
+#ifndef __PSWGEN_GENERATOR_MODULE_H
+#  define __PSWGEN_GENERATOR_MODULE_H
+
+#endif // module.h
+ +

As this is a simple module, we define all our class in this single header file. This includes the implementation + of the iGenerator interface and also the plugin itself. Se we need to include header files for the + iGenerator and iPlugin interfaces:

+ +
#include "igenerator.h"
+#include <Plugins/iPlugin>
+ +

We are going to put every public class in this module into the eVaf::PswGen::Generator namespace and private + classes into the eVaf::PswGen::Generator::Private namespace:

+ +
namespace eVaf {
+namespace PswGen {
+
+/// Module that generates strong passwords using cryptographic methods
+namespace Generator {
+
+/// Internal implementation of the Generator module
+namespace Internal {
+
+} // namespace eVaf::PswGen::Generator::Internal
+} // namespace eVaf::PswGen::Generator
+} // namespace eVaf::PswGen
+} // namespace eVaf
+ +

We call the class that implements the module simply Module. This is a public class and goes into the + eVaf::PswGen::Generator namespace. We however, do not need to export it as we did with the iGenerator + interface class, as this will be done by Qt.

+ +
class Module : public Plugins::iPlugin
+{
+    Q_OBJECT
+
+public:
+
+    Module();
+
+    virtual ~Module();
+
+}
+ +

The iPlugin interface has three abstract methods that we need to implement in our class -- init(), + done() and isReady(). Since this simple module is always ready, we can return true in the + isReady() function. More complex modules can use a private mReady variable, which they set to true + once all the initialization is done. + +

virtual bool init(QString const & args);
+
+virtual void done();
+
+virtual bool isReady() const { return true; }
+ +

We need the iGenerator interface object in this module and add it to the private members section: + +

private: // Members
+
+    /// iGenerator interface instance
+    Internal::GeneratorImpl * mGenerator;
+ +

As the Internal::GeneratorImpl class is not declared yet, we need to add this forward declaration before the + Module class:

+ +
namespace Internal {
+    class GeneratorImpl;
+} // namespace eVaf::PswGen::Generator::Internal
+ +

Then we can move forward and implement the iGenerator interface, which we already happened to call + GeneratorImpl. This class goes into the eVaf::PswGen::Generator::Internal namespace:

+ +
class GeneratorImpl : public iGenerator
+{
+    Q_OBJECT
+
+public:
+
+    GeneratorImpl();
+
+    virtual ~GeneratorImpl();
+
+    virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const;
+
+    virtual int maxLength() const;
+};
+ +

Here is the final module.h file:

+ +
/**
+ * @file src/apps/PswGen/Generator/module.h
+ */
+
+#ifndef __PSWGEN_GENERATOR_MODULE_H
+#  define __PSWGEN_GENERATOR_MODULE_H
+
+#include "igenerator.h"
+
+#include <Plugins/iPlugin>
+
+#include <QObject>
+#include <QString>
+
+namespace eVaf {
+namespace PswGen {
+
+/// Module that generates strong passwords using cryptographic methods
+namespace Generator {
+
+/// Internal implementation of the Generator module
+namespace Internal {
+    class GeneratorImpl;
+} // namespace eVaf::PswGen::Generator::Internal
+
+/// Plugins/iPlugin interface implementation.
+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 true; }
+
+
+private: // Members
+
+    /// iGenerator interface instance
+    Internal::GeneratorImpl * mGenerator;
+
+};
+
+namespace Internal {
+
+ /// iGenerator interface implementation.
+class GeneratorImpl : public iGenerator
+{
+    Q_OBJECT
+
+public:
+
+    GeneratorImpl();
+
+    virtual ~GeneratorImpl();
+
+    virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const;
+
+    virtual int maxLength() const;
+
+};
+
+} // namespace eVaf::PswGen::Generator::Internal
+} // namespace eVaf::PswGen::Generator
+} // namespace eVaf::PswGen
+} // namespace eVaf
+
+#endif // module.h
+ +

Continue implementing the Generator Module.

+ + + +