X-Git-Url: https://vaikene.ee/gitweb/gitweb.cgi?p=evaf;a=blobdiff_plain;f=www%2Fpswgen04.html;fp=www%2Fpswgen04.html;h=df82cb0b946a970ac9d1335fee64c395576e05c1;hp=0000000000000000000000000000000000000000;hb=368818c22af812ac35f5ff69423522dbd54d37ed;hpb=3352f7acc232104985807b9f470cb12bcb2b47c2 diff --git a/www/pswgen04.html b/www/pswgen04.html new file mode 100644 index 0000000..df82cb0 --- /dev/null +++ b/www/pswgen04.html @@ -0,0 +1,306 @@ + + + +
+ +Now we are going to implement all the classes declared in the module.h. Create the module.cpp file + in the src/apps/PswGen/Generator directory. We obviously include the module.h header file, but also + the QtCore header file for any non-GUI Qt classes.
+ +/** + * @file src/apps/PswGen/Generator/module.cpp + */ + +#include "module.h" + +#include <QtCore>+ +
All the eVaf modules need to include version information. This is common for all the modules and we can simply + copy existing version info files from another eVaf module:
+ +evaf/src/apps/PswGen/Generator $ cp ../../../plugins/SdiWindow/version.{h,rc} .
+
+ The version.h file contains version information for the module. The version.rc is for Windows + builds only and embeds the same version information into the dll or exe file. Modify the copied version.h + file for our new module. The version.rc file uses the values from the version.h and does not + need to be touched.
+ +/** + * @file src/apps/PswGen/Generator/version.h + */ +#ifndef __PSWGEN_GENERATOR_VERSION_H +#define __PSWGEN_GENERATOR_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 "PswGen\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 "PswGen.dll\0" + +/** + * Description of the module/library (shall end with \0) + */ +#define VER_FILE_DESCRIPTION_STR "Module that generates strong passwords using MD5 hashes.\0" + +#endif // version.h+ +
Then include the version info file in the module.cpp file and use the VER_EXPORT_VERSION_INFO() macro + to export version information from the module. This macro defines a public function that all the eVaf modules export and + is used to collect version information from them. In your modules you only need to modify the version.h file and then + use the VER_EXPORT_VERSION_INFO() macro once somewhere in your code.
+ +#include "version.h" + +VER_EXPORT_VERSION_INFO()+ +
We make our life easier with several using namespace keywords:
+ +using namespace eVaf; +using namespace eVaf::PswGen; +using namespace eVaf::PswGen::Generator;+ +
The Module class needs to instantiate the iGenerator interface in the constructor. We also need to set + the QObject's name property to the name of the plugin by combining the name of the module with the name of the class. + While the application would work without the name property, it makes our life much easier if the name property is set.
+ +Finally, we output an info message telling that the object was created. Every eVaf module and class is expected to + output info messages when they are created, destroyed, initialized or destroyed.
+ +Module::Module() + : Plugins::iPlugin() +{ + setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__)); + + mGenerator = new Internal::GeneratorImpl; + + EVAF_INFO("%s created", qPrintable(objectName())); +}+ +
The EVAF_INFO macro comes from the Common/iLogger header file ane we need to include it:
+ +#include <Common/iLogger>
+
+ The destructor should delete the iGenerator interface object, which we created in the constructor. The common + rule is that any resources allocated in the constructor shall be released in the destructor, preferrably in the opposite + order, ie. the first resource allocated in the constructor is released last in the destructor. + +
Module::~Module() +{ + delete mGenerator; + + EVAF_INFO("%s destroyed", qPrintable(objectName())); +}+ +
We also need to implement init() and done() functions, which are used to initialize and finalize modules. + They are similar to the constructor and destructor with two major differences:
+The rule for init() and done() functions is the same than for constructors and destructors -- any resource + allocated in the init() function shall be released in the done() function and preferrably in the opposite + order.
+ +This simple module needs no extra resources to be allocated and our init() and done() functions can be + the following:
+ +bool Module::init(QString const & args) +{ + Q_UNUSED(args); + + EVAF_INFO("%s initialized", qPrintable(objectName())); + + return true; +} + +void Module::done() +{ + EVAF_INFO("%s finalized", qPrintable(objectName())); +}+ +
We continue by implementing the iGenerator interface. There are no resources to be allocated in the constructor + and we just set the QObject's name property and output the info message.
+ +We also register the iGenerator interface in the global registry so that other modules can query for it and + use our interface. This is done by using the Common::iRegistry interface, which we need to include:
+ +#include <Common/iRegistry>
+
+ The GeneratorImpl class was declared in the eVaf::PswGen::Generator::Internal namespace, so we need + another using namespace keyword before the implementation of the class:
+ +using namespace eVaf::PswGen::Generator::Internal; + +GeneratorImpl::GeneratorImpl() + : iGenerator() +{ + setObjectName(QString("%1.iGenerator").arg(VER_MODULE_NAME_STR)); + + Common::iRegistry::instance()->registerInterface("iGenerator", this); + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +GeneratorImpl::~GeneratorImpl() +{ + EVAF_INFO("%s destroyed", qPrintable(objectName())); +}+ +
Finally, we write the generatePassword function that does the actual job of the module.
+ +We use the MD5 cryptographic hash function to calculate a hash value over the name and masterPassword values. + The result, which is a binary blob, needs to be convert into something that can be used as a password and we use base 64 encoding + for this and cut the result to the requested length:
+ +QString GeneratorImpl::generatePassword(QString const & name, QString const & masterPassword, int length, uint flags) const +{ + Q_UNUSED(flags); + + QByteArray inputString = QString("%1%2").arg(name).arg(masterPassword).toLatin1(); + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData(inputString); + QByteArray result = hash.result().toBase64(); + if (length > 0) + return result.left(length); + else + return result; +}+ +
We also know now the maximum length of the generated password, which is 24. Go back to the module.h header file and + modify the GeneratorImpl::maxLength() function:
+ +virtual int maxLength() const { return 24; }+ +
Here is the final module.cpp file:
+ +/** + * @file src/apps/PswGen/Generator/module.cpp + */ + +#include "module.h" +#include "version.h" + +#include <Common/iLogger> +#include <Common/iRegistry> + +#include <QtCore> + +VER_EXPORT_VERSION_INFO() +Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::PswGen::Generator::Module) + +using namespace eVaf; +using namespace eVaf::PswGen; +using namespace eVaf::PswGen::Generator; + +Module::Module() + : Plugins::iPlugin() +{ + setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__)); + + mGenerator = new Internal::GeneratorImpl; + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +Module::~Module() +{ + delete mGenerator; + + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +bool Module::init(QString const & args) +{ + Q_UNUSED(args); + + EVAF_INFO("%s initialized", qPrintable(objectName())); + + return true; +} + +void Module::done() +{ + EVAF_INFO("%s finalized", qPrintable(objectName())); +} + +using namespace eVaf::PswGen::Generator::Internal; + +GeneratorImpl::GeneratorImpl() + : iGenerator() +{ + setObjectName(QString("%1.iGenerator").arg(VER_MODULE_NAME_STR)); + + Common::iRegistry::instance()->registerInterface("iGenerator", this); + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +GeneratorImpl::~GeneratorImpl() +{ + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +QString GeneratorImpl::generatePassword(QString const & name, QString const & masterPassword, int length, uint flags) const +{ + Q_UNUSED(flags); + + QByteArray inputString = QString("%1%2").arg(name).arg(masterPassword).toLatin1(); + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData(inputString); + QByteArray result = hash.result().toBase64(); + if (length > 0) + return result.left(length); + else + return result; +}+ +
Next -- 05 - Building Generator Module.
+ + +