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.