From 368818c22af812ac35f5ff69423522dbd54d37ed Mon Sep 17 00:00:00 2001 From: =?utf8?q?Enar=20V=C3=A4ikene?= <enar@vaikene.net> Date: Fri, 22 Jul 2011 16:53:40 +0300 Subject: [PATCH] Written more tutorial files. --- www/highlight.css | 20 +++ www/pswgen02.html | 23 ++++ www/pswgen03.html | 334 ++++++++++++++++++++++++++++++++++++++++++++++ www/pswgen04.html | 306 ++++++++++++++++++++++++++++++++++++++++++ www/pswgen05.html | 173 ++++++++++++++++++++++++ 5 files changed, 856 insertions(+) create mode 100644 www/highlight.css create mode 100644 www/pswgen02.html create mode 100644 www/pswgen03.html create mode 100644 www/pswgen04.html create mode 100644 www/pswgen05.html diff --git a/www/highlight.css b/www/highlight.css new file mode 100644 index 0000000..d490944 --- /dev/null +++ b/www/highlight.css @@ -0,0 +1,20 @@ +/* Style definition file generated by highlight 3.3, http://www.andre-simon.de/ */ + +/* Highlighting theme: Kwrite Editor */ + +body.hl { background-color:#e0eaee; } +pre.hl { color:#000000; background-color:#e0eaee; font-size:10pt; font-family:'Courier New';} +.hl.num { color:#b07e00; } +.hl.esc { color:#ff00ff; } +.hl.str { color:#bf0303; } +.hl.pps { color:#818100; } +.hl.slc { color:#838183; font-style:italic; } +.hl.com { color:#838183; font-style:italic; } +.hl.ppc { color:#008200; } +.hl.opt { color:#000000; } +.hl.lin { color:#555555; } +.hl.kwa { color:#000000; font-weight:bold; } +.hl.kwb { color:#0057ae; } +.hl.kwc { color:#000000; font-weight:bold; } +.hl.kwd { color:#010181; } + diff --git a/www/pswgen02.html b/www/pswgen02.html new file mode 100644 index 0000000..021c93e --- /dev/null +++ b/www/pswgen02.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et"> + + <head> + <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" /> + <title>eVaf Tutorial - 02 - Preparations</title> + <meta name="Author" content="Enar Väikene" /> + <meta name="description" content="eVaf Tutorial" /> + <meta name="keywords" content="evaf c++ application development framework tutorial password generator" /> + <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" /> + </head> + + <body> + + <h1>eVaf Tutorial</h1> + + <h2>02 - Preparations</h2> + + <p>In the next section <a href="pswgen03.html">03 - Generator Module</a> we write the Generator module.</p> + + </body> + +</html> 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 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et"> + + <head> + <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" /> + <title>eVaf Tutorial - 03 - Generator Module</title> + <meta name="Author" content="Enar Väikene" /> + <meta name="description" content="eVaf Tutorial" /> + <meta name="keywords" content="evaf c++ application development framework tutorial password generator" /> + <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" /> + <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" /> + </head> + + <body> + + <h1>eVaf Tutorial</h1> + + <h2>03 - Generator Module</h2> + + <p>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.</p> + + <h3>iGenerator interface</h3> + + <p>We start by defining the interface for the module. For this create the file <tt>igenerator.h</tt> in the + <tt>src/apps/pswGen/Generator</tt> directory:</p> + + <pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/igenerator.h</span> +<span class="hl com"> */</span> +<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span> +<span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span> + +<span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span></pre> + + <p>The interface class needs to be derived from <tt>QObject</tt> and we also need <tt>QString</tt> for input + data and generated passwords:</p> + + <pre class="hl"><span class="hl ppc">#include <QObject></span> +<span class="hl ppc">#include <QString></span></pre> + + <p>To avoid potential name collisions with other existing or future modules, we use the <tt>eVaf::PswGen</tt> + namespace for this application:</p> + + <pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span> +<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span> + +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre> + + <p>We call the interface class <tt>iGenerator</tt>: + + <pre class="hl"><span class="hl kwc">class</span> iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject +<span class="hl opt">{</span> + Q_OBJECT +<span class="hl kwc">public</span><span class="hl opt">:</span> +<span class="hl opt">};</span></pre> + + <p>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.</p> + <pre class="hl"><span class="hl slc">/// Interface constructor</span> +<span class="hl kwd">iGenerator</span><span class="hl opt">() :</span> <span class="hl kwd">QObject</span><span class="hl opt">() {}</span> + +<span class="hl slc">/// Empty virtual destructor</span> +<span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">iGenerator</span><span class="hl opt">() {}</span></pre> + + <p>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:</p> + + <pre class="hl"><span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span> + +<span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span></pre> + + <p>I am training myself to use the style of writing declarations like <tt>"QString const &"</tt>, which refers to a non-mutable <tt>QString</tt> object similar to <tt>"int maxLength() const"</tt>, which is a function that does not modify the object's data members. Feel free to use the traditional way of writing <tt>"const QString &"</tt> if this looks weird to you.</p> + + <p>The <tt>iGenerator</tt> interface needs to be visible for other modules and marked for export. We do this by creating the <tt>src/apps/PswGen/Generator/lib.h file, which defines the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro:</p> + <pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/lib.h</span> +<span class="hl com"> */</span> +<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_LIB_H</span> +<span class="hl ppc"># define __PSWGEN_GENERATOR_LIB_H</span> + +<span class="hl ppc">#include <QtCore/qglobal.h></span> + +<span class="hl ppc">#if defined(PSWGEN_GENERATOR_LIBRARY)</span> +<span class="hl ppc"># define PSWGEN_GENERATOR_EXPORT Q_DECL_EXPORT</span> +<span class="hl ppc">#else</span> +<span class="hl ppc"># define PSWGEN_GENERATOR_EXPORT Q_DECL_IMPORT</span> +<span class="hl ppc">#endif</span> +<span class="hl ppc">#endif</span> <span class="hl slc">// libgen.h</span><span class="hl ppc"></span></pre> + + <p>Then we include this new header file in our interface header file and modify the <tt>iGenerator</tt> class definition by adding + the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro to it:</p> + <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"lib.h"</span><span class="hl ppc"></span> + +/// ... + +<span class="hl kwc">class</span> PSWGEN_GENERATOR_EXPORT iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject</pre> + + <p>This is pretty much all we need to add to the <tt>iGenerator</tt> interface and here is the final file:</p> + +<pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/igenerator.h</span> +<span class="hl com"> */</span> + +<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span> +<span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span> + +<span class="hl ppc">#include</span> <span class="hl pps">"lib.h"</span><span class="hl ppc"></span> + +<span class="hl ppc">#include <QObject></span> +<span class="hl ppc">#include <QString></span> + +<span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span> +<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span> + +<span class="hl com">/// Password generator interface.</span> +<span class="hl kwc">class</span> PSWGEN_GENERATOR_EXPORT iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject +<span class="hl opt">{</span> + Q_OBJECT + +<span class="hl kwc">public</span><span class="hl opt">:</span> + + <span class="hl slc">/// Interface constructor</span> + <span class="hl kwd">iGenerator</span><span class="hl opt">() :</span> <span class="hl kwd">QObject</span><span class="hl opt">() {}</span> + + <span class="hl slc">/// Empty virtual destructor</span> + <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">iGenerator</span><span class="hl opt">() {}</span> + + <span class="hl com">/// Generates a strong password</span> + <span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span> + + <span class="hl com">/// Returns the maximum length of generated passwords</span> + <span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span> + +<span class="hl opt">};</span> + +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span> + +<span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span> +</pre> + + <p>As a final touch, we create a file called <tt>iGenerator</tt> with the following content:</p> +<pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"igenerator.h"</span><span class="hl ppc"></span></pre> + + <p>With this file in place other modules can use <tt>#include "Generator/iGenerator"</tt> instead of <tt>#include "Generator/igenerator.h"</tt> similar to other eVaf and Qt include files.</p> + + <h3>Generator module</h3> + + <p>Now we write the Generator module itself. The module class has to be derived from the <tt>Plugins::iPlugin</tt> interface class + with or without the <tt>Plugins::iPluginFactory</tt> factory class.</p> + + <p>The <tt>Plugins::iPluginFactory</tt> 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.</p> + + <p>Create the <tt>module.h</tt> header file in the <tt>src/apps/PswGen/Generator</tt> directory:</p> + + <pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/module.h</span> +<span class="hl com"> */</span> +<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span> +<span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span> + +<span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre> + + <p>As this is a simple module, we define all our class in this single header file. This includes the implementation + of the <tt>iGenerator</tt> interface and also the plugin itself. Se we need to include header files for the + <tt>iGenerator</tt> and <tt>iPlugin</tt> interfaces:</p> + +<pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"igenerator.h"</span><span class="hl ppc"></span> +<span class="hl ppc">#include <Plugins/iPlugin></span></pre> + + <p>We are going to put every public class in this module into the <tt>eVaf::PswGen::Generator</tt> namespace and private + classes into the <tt>eVaf::PswGen::Generator::Private</tt> namespace:</p> + +<pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span> +<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span> + +<span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span> +<span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span> + +<span class="hl slc">/// Internal implementation of the Generator module</span> +<span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span> + +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre> + + <p>We call the class that implements the module simply <tt>Module</tt>. This is a public class and goes into the + <tt>eVaf::PswGen::Generator</tt> namespace</tt>. We however, do not need to export it as we did with the <tt>iGenerator</tt> + interface class, as this will be done by Qt.</p> + +<pre class="hl"><span class="hl kwc">class</span> Module <span class="hl opt">:</span> <span class="hl kwc">public</span> Plugins<span class="hl opt">::</span>iPlugin +<span class="hl opt">{</span> + Q_OBJECT + +<span class="hl kwc">public</span><span class="hl opt">:</span> + + <span class="hl kwd">Module</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span> + +}</span></pre> + + <p>The <tt>iPlugin</tt> interface has three abstract methods that we need to implement in our class -- <tt>init()</tt>, + <tt>done()</tt> and <tt>isReady()</tt>. Since this simple module is always ready, we can return <tt>true</tt> in the + <tt>isReady()</tt> function. More complex modules can use a private <tt>mReady</tt> variable, which they set to <tt>true</tt> + once all the initialization is done.</tt> + +<pre class="hl"><span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">);</span> + +<span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span> + +<span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">isReady</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return true</span><span class="hl opt">; }</pre> + + <p>We need the <tt>iGenerator</tt> interface object in this module and add it to the private members section:</tt> + +<pre class="hl"><span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span> + + <span class="hl slc">/// iGenerator interface instance</span> + Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span></pre> + + <p>As the <tt>Internal::GeneratorImpl</tt> class is not declared yet, we need to add this forward declaration before the + <tt>Module</tt> class:</p> + +<pre class="hl"><span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span> + <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span></pre> + + <p>Then we can move forward and implement the <tt>iGenerator</tt> interface, which we already happened to call + <tt>GeneratorImpl</tt>. This class goes into the <tt>eVaf::PswGen::Generator::Internal</tt> namespace:</p> + +<pre class="hl"><span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator +<span class="hl opt">{</span> + Q_OBJECT + +<span class="hl kwc">public</span><span class="hl opt">:</span> + + <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span><span class="hl opt">;</span> + + <span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const;</span> +<span class="hl opt">};</span></pre> + + <p>Here is the final <tt>module.h</tt> file:</p> + +<pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/module.h</span> +<span class="hl com"> */</span> + +<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span> +<span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span> + +<span class="hl ppc">#include</span> <span class="hl pps">"igenerator.h"</span><span class="hl ppc"></span> + +<span class="hl ppc">#include <Plugins/iPlugin></span> + +<span class="hl ppc">#include <QObject></span> +<span class="hl ppc">#include <QString></span> + +<span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span> +<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span> + +<span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span> +<span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span> + +<span class="hl slc">/// Internal implementation of the Generator module</span> +<span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span> + <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span> + +<span class="hl com">/// Plugins/iPlugin interface implementation.</span> +<span class="hl kwc">class</span> Module <span class="hl opt">:</span> <span class="hl kwc">public</span> Plugins<span class="hl opt">::</span>iPlugin +<span class="hl opt">{</span> + Q_OBJECT + +<span class="hl kwc">public</span><span class="hl opt">:</span> + + <span class="hl kwd">Module</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">);</span> + + <span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">isReady</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return true</span><span class="hl opt">; }</span> + + +<span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span> + + <span class="hl slc">/// iGenerator interface instance</span> + Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span> + +<span class="hl opt">};</span> + +<span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span> + +<span class="hl com"> /// iGenerator interface implementation.</span> +<span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator +<span class="hl opt">{</span> + Q_OBJECT + +<span class="hl kwc">public</span><span class="hl opt">:</span> + + <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span> + + <span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span><span class="hl opt">;</span> + + <span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const;</span> + +<span class="hl opt">};</span> + +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span> +<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span> + +<span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre> + + <p>Continue implementing the <a href="pswgen04.html">Generator Module</a>.</p> + + </body> + +</html> 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 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et"> + + <head> + <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" /> + <title>eVaf Tutorial - 04 - Generator Module</title> + <meta name="Author" content="Enar Väikene" /> + <meta name="description" content="eVaf Tutorial" /> + <meta name="keywords" content="evaf c++ application development framework tutorial password generator" /> + <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" /> + <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" /> + </head> + + <body> + + <h1>eVaf Tutorial</h1> + + <h2>04 - Generator Module</h2> + + <p>Now we are going to implement all the classes declared in the <tt>module.h</tt>. Create the <tt>module.cpp</tt> file + in the <tt>src/apps/PswGen/Generator</tt> directory. We obviously include the <tt>module.h</tt> header file, but also + the <tt>QtCore</tt> header file for any non-GUI Qt classes.</p> + +<pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/module.cpp</span> +<span class="hl com"> */</span> + +<span class="hl ppc">#include</span> <span class="hl pps">"module.h"</span><span class="hl ppc"></span> + +<span class="hl ppc">#include <QtCore></span></pre> + + <p>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:</p> + + <pre>evaf/src/apps/PswGen/Generator $ <code>cp ../../../plugins/SdiWindow/version.{h,rc} .</code></pre> + + <p>The <tt>version.h</tt> file contains version information for the module. The <tt>version.rc</tt> is for Windows + builds only and embeds the same version information into the dll or exe file. Modify the copied <tt>version.h</tt> + file for our new module. The <tt>version.rc</tt> file uses the values from the <tt>version.h</tt> and does not + need to be touched.</p> + +<pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/version.h</span> +<span class="hl com"> */</span> +<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_VERSION_H</span> +<span class="hl ppc">#define __PSWGEN_GENERATOR_VERSION_H</span> + +<span class="hl ppc">#include <version_rc.h></span> + +<span class="hl com">/**</span> +<span class="hl com"> * Module/library version number in the form major,minor,release,build</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_FILE_VERSION 0,1,1,1</span> + +<span class="hl com">/**</span> +<span class="hl com"> * Module/library version number in the string format (shall end with \0)</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_FILE_VERSION_STR</span> <span class="hl pps">"0.1.1.1\0"</span><span class="hl ppc"></span> + +<span class="hl com">/**</span> +<span class="hl com"> * Module/library name (shall end with \0)</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_MODULE_NAME_STR</span> <span class="hl pps">"PswGen\0"</span><span class="hl ppc"></span> + +<span class="hl com">/**</span> +<span class="hl com"> * Module type (see version_rc.h for all the types)</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_MODULE_TYPE MT_GENERIC</span> + +<span class="hl com">/**</span> +<span class="hl com"> * Module type in the string format (see version_rc for all the types)</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_MODULE_TYPE_STR MT_GENERIC</span> + +<span class="hl com">/**</span> +<span class="hl com"> * Original file name for windows (shall end with \0)</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_ORIGINAL_FILE_NAME_STR</span> <span class="hl pps">"PswGen.dll\0"</span><span class="hl ppc"></span> + +<span class="hl com">/**</span> +<span class="hl com"> * Description of the module/library (shall end with \0)</span> +<span class="hl com"> */</span> +<span class="hl ppc">#define VER_FILE_DESCRIPTION_STR</span> <span class="hl pps">"Module that generates strong passwords using MD5 hashes.\0"</span><span class="hl ppc"></span> + +<span class="hl ppc">#endif</span> <span class="hl slc">// version.h</span><span class="hl ppc"></span></pre> + + <p>Then include the version info file in the <tt>module.cpp</tt> file and use the <tt>VER_EXPORT_VERSION_INFO()</tt> 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 <tt>version.h</tt> file and then + use the <tt>VER_EXPORT_VERSION_INFO()</tt> macro once somewhere in your code.</p> + +<pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"version.h"</span><span class="hl ppc"></span> + +<span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span></pre> + + <p>We make our life easier with several <tt>using namespace</tt> keywords:</p> + +<pre class="hl"><span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span> +<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span> +<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">;</span></pre> + + <p>The Module class needs to instantiate the <tt>iGenerator</tt> 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.</p> + + <p>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.</p> + +<pre class="hl">Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span> + <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>__FUNCTION__<span class="hl opt">));</span> + + mGenerator <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>GeneratorImpl<span class="hl opt">;</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span></pre> + + <p>The <tt>EVAF_INFO</tt> macro comes from the <tt>Common/iLogger</tt> header file ane we need to include it:</p> + +<pre class="hl"><span class="hl ppc">#include <Common/iLogger></span></pre> + + <p>The destructor should delete the <tt>iGenerator</tt> 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.</tt> + +<pre class="hl">Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwa">delete</span> mGenerator<span class="hl opt">;</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span></pre> + + <p>We also need to implement <tt>init()</tt> and <tt>done()</tt> functions, which are used to initialize and finalize modules. + They are similar to the constructor and destructor with two major differences:</p> + <ol> + <li>The <tt>init()</tt> function can fail and return <tt>false</tt> to indicate a failure. eVaf does not use exceptions and + this is the only way for a module to fail without terminating the whole application. A failed module will be disabled + and the rest of the application can still run if it can.</li> + <li>eVaf modules are loaded in two steps. At first, all the modules are created, which means that all the objects + are constructed. Only then will eVaf call <tt>init()</tt> functions meaning that when the <tt>init()</tt> function is + called, all the modules are already loaded and instantiated. Interfaces and resources from other modules that might be not + available when the object is created, are available when the <tt>init()</tt> function is called.</li> + </ol> + + <p>The rule for <tt>init()</tt> and <tt>done()</tt> functions is the same than for constructors and destructors -- any resource + allocated in the <tt>init()</tt> function shall be released in the <tt>done()</tt> function and preferrably in the opposite + order.</p> + + <p>This simple module needs no extra resources to be allocated and our <tt>init()</tt> and <tt>done()</tt> functions can be + the following:</p> + +<pre class="hl"><span class="hl kwb">bool</span> Module<span class="hl opt">::</span><span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">)</span> +<span class="hl opt">{</span> + <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s initialized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> + + <span class="hl kwa">return true</span><span class="hl opt">;</span> +<span class="hl opt">}</span> + +<span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s finalized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span></pre> + + <p>We continue by implementing the <tt>iGenerator</tt> 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.</p> + + <p>We also register the <tt>iGenerator</tt> interface in the global registry so that other modules can query for it and + use our interface. This is done by using the <tt>Common::iRegistry</tt> interface, which we need to include:</p> + +<pre class="hl"><span class="hl ppc">#include <Common/iRegistry></span></pre> + + <p>The <tt>GeneratorImpl</tt> class was declared in the <tt>eVaf::PswGen::Generator::Internal</tt> namespace, so we need + another <tt>using namespace</tt> keyword before the implementation of the class:</p> + +<pre class="hl"><span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">::</span>Internal<span class="hl opt">;</span> + +GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span> + <span class="hl opt">:</span> <span class="hl kwd">iGenerator</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.iGenerator"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">));</span> + + Common<span class="hl opt">::</span>iRegistry<span class="hl opt">::</span><span class="hl kwd">instance</span><span class="hl opt">()-></span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">"iGenerator"</span><span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">);</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span> + +GeneratorImpl<span class="hl opt">::~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span></pre> + + <p>Finally, we write the <tt>generatePassword</tt> function that does the actual job of the module.</p> + + <p>We use the MD5 cryptographic hash function to calculate a hash value over the <tt>name</tt> and <tt>masterPassword</tt> 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:</p> + +<pre class="hl">QString GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags<span class="hl opt">)</span> <span class="hl kwb">const</span> +<span class="hl opt">{</span> + <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>flags<span class="hl opt">);</span> + + QByteArray inputString <span class="hl opt">=</span> <span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>name<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>masterPassword<span class="hl opt">).</span><span class="hl kwd">toLatin1</span><span class="hl opt">();</span> + QCryptographicHash <span class="hl kwd">hash</span><span class="hl opt">(</span>QCryptographicHash<span class="hl opt">::</span>Md5<span class="hl opt">);</span> + hash<span class="hl opt">.</span><span class="hl kwd">addData</span><span class="hl opt">(</span>inputString<span class="hl opt">);</span> + QByteArray result <span class="hl opt">=</span> hash<span class="hl opt">.</span><span class="hl kwd">result</span><span class="hl opt">().</span><span class="hl kwd">toBase64</span><span class="hl opt">();</span> + <span class="hl kwa">if</span> <span class="hl opt">(</span>length <span class="hl opt">></span> <span class="hl num">0</span><span class="hl opt">)</span> + <span class="hl kwa">return</span> result<span class="hl opt">.</span><span class="hl kwd">left</span><span class="hl opt">(</span>length<span class="hl opt">);</span> + <span class="hl kwa">else</span> + <span class="hl kwa">return</span> result<span class="hl opt">;</span> +<span class="hl opt">}</span></pre> + + <p>We also know now the maximum length of the generated password, which is 24. Go back to the <tt>module.h</tt> header file and + modify the <tt>GeneratorImpl::maxLength()</tt> function:</p> + +<pre class="hl"><span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return</span> <span class="hl num">24</span><span class="hl opt">; }</span></pre> + + <p>Here is the final <tt>module.cpp</tt> file:</p> + +<pre class="hl"><span class="hl com">/**</span> +<span class="hl com"> * @file src/apps/PswGen/Generator/module.cpp</span> +<span class="hl com"> */</span> + +<span class="hl ppc">#include</span> <span class="hl pps">"module.h"</span><span class="hl ppc"></span> +<span class="hl ppc">#include</span> <span class="hl pps">"version.h"</span><span class="hl ppc"></span> + +<span class="hl ppc">#include <Common/iLogger></span> +<span class="hl ppc">#include <Common/iRegistry></span> + +<span class="hl ppc">#include <QtCore></span> + +<span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span> +<span class="hl kwd">Q_EXPORT_PLUGIN2</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">,</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">::</span>Module<span class="hl opt">)</span> + +<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span> +<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span> +<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">;</span> + +Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span> + <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>__FUNCTION__<span class="hl opt">));</span> + + mGenerator <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>GeneratorImpl<span class="hl opt">;</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span> + +Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwa">delete</span> mGenerator<span class="hl opt">;</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span> + +<span class="hl kwb">bool</span> Module<span class="hl opt">::</span><span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">)</span> +<span class="hl opt">{</span> + <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s initialized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> + + <span class="hl kwa">return true</span><span class="hl opt">;</span> +<span class="hl opt">}</span> + +<span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s finalized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span> + +<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">::</span>Internal<span class="hl opt">;</span> + +GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span> + <span class="hl opt">:</span> <span class="hl kwd">iGenerator</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.iGenerator"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">));</span> + + Common<span class="hl opt">::</span>iRegistry<span class="hl opt">::</span><span class="hl kwd">instance</span><span class="hl opt">()-></span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">"iGenerator"</span><span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">);</span> + + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span> + +GeneratorImpl<span class="hl opt">::~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span> +<span class="hl opt">{</span> + <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span> +<span class="hl opt">}</span> + +QString GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags<span class="hl opt">)</span> <span class="hl kwb">const</span> +<span class="hl opt">{</span> + <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>flags<span class="hl opt">);</span> + + QByteArray inputString <span class="hl opt">=</span> <span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>name<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>masterPassword<span class="hl opt">).</span><span class="hl kwd">toLatin1</span><span class="hl opt">();</span> + QCryptographicHash <span class="hl kwd">hash</span><span class="hl opt">(</span>QCryptographicHash<span class="hl opt">::</span>Md5<span class="hl opt">);</span> + hash<span class="hl opt">.</span><span class="hl kwd">addData</span><span class="hl opt">(</span>inputString<span class="hl opt">);</span> + QByteArray result <span class="hl opt">=</span> hash<span class="hl opt">.</span><span class="hl kwd">result</span><span class="hl opt">().</span><span class="hl kwd">toBase64</span><span class="hl opt">();</span> + <span class="hl kwa">if</span> <span class="hl opt">(</span>length <span class="hl opt">></span> <span class="hl num">0</span><span class="hl opt">)</span> + <span class="hl kwa">return</span> result<span class="hl opt">.</span><span class="hl kwd">left</span><span class="hl opt">(</span>length<span class="hl opt">);</span> + <span class="hl kwa">else</span> + <span class="hl kwa">return</span> result<span class="hl opt">;</span> +<span class="hl opt">}</span></pre> + + <p>Next -- <a href="pswgen05.html">05 - Building Generator Module</a>.</p> + + </body> +</html> diff --git a/www/pswgen05.html b/www/pswgen05.html new file mode 100644 index 0000000..bc6b5d6 --- /dev/null +++ b/www/pswgen05.html @@ -0,0 +1,173 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et"> + + <head> + <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" /> + <title>eVaf Tutorial - 05 - Building Generator Module</title> + <meta name="Author" content="Enar Väikene" /> + <meta name="description" content="eVaf Tutorial" /> + <meta name="keywords" content="evaf c++ application development framework tutorial password generator" /> + <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" /> + <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" /> + </head> + + <body> + + <h1>eVaf Tutorial</h1> + + <h2>05 - Building Generator Module</h2> + + <h3>CMakeLists.txt</h3> + + <p>eVaf uses <a href="http://www.cmake.org">CMake</a> as its build system and needs a file called <tt>CMakeLists.txt</tt> + in the <tt>src/apps/PswGen/Generator</tt> directory. Create the file and start editing it.</p> + + <p>We use the <tt>TARGET</tt> variable to set the name of the module. This makes it easier to re-use the <tt>CMakeLists.txt</tt> + file in other modules and applications.</p> + +<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>TARGET PswGen<span class="hl opt">)</span></pre> + + <p>Then we include Qt include files and libraries. We also specify, that we do not want to include the QtGui module as this + module does not any classes from the QtGui module. By removing the QtGui module, we remove any graphical libraries as + dependencies for this module and it can be used in headless systems.</p> + +<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>QT_DONT_USE_QTGUI TRUE<span class="hl opt">)</span> +<span class="hl kwa">include</span><span class="hl opt">(</span><span class="hl kwd">${QT_USE_FILE}</span><span class="hl opt">)</span></pre> + + <p>The next line adds the <tt>PSWGEN_GENERATOR_LIBRARY</tt> definition to the compiler (remember the <tt>lib.h</tt> file and + the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro in the <tt>igeneraror.h</tt> file?): + +<pre class="hl"><span class="hl kwa">add_definitions</span><span class="hl opt">(</span>-DPSWGEN_GENERATOR_LIBRARY<span class="hl opt">)</span></pre> + + <p>Add all the eVaf include directories to the compiler. The variable <tt>eVaf_INCLUDE</tt> contains all the eVaf include + directories and is already initialized with proper values when this <tt>CMakeLists.txt</tt> file is processed.</p> + +<pre class="hl"><span class="hl kwa">include_directories</span><span class="hl opt">(</span><span class="hl kwd">${eVaf_INCLUDE}<span class="hl opt">)</span></pre> + + <p>Then we initialize a variable with the names of all the eVaf modules that this module needs to be linked with. We only + need to specify the names of libraries without prefixes or suffixes like ".dll" or ".so". These libraries also become dependencies + of this module and will be built whenever we build this module.</p> + +<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>eVaf_LIBRARIES CommonLib PluginsLib<span class="hl opt">)</span></pre> + + <p>Collect all the source files that needs to be compiled:</p> + +<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>SRCS + module.cpp +<span class="hl opt">)</span></pre> + + <p>Collect header files that need to be processed with the Qt meta-object compiler. Any header file that contains + class declarations with the Q_OBJECT keyword and/or signals and slots, needs to be included here. To avoid warnings + during the build, do not include here any other header files.</p> + +<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>MOC_HDRS + igenerator.h + module.h +<span class="hl opt">)</span></pre> + + <p>The following line adds the Windows version info resource file to the list of source files:</p> +<pre class="hl"><span class="hl kwa">if</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span> + <span class="hl kwa">set</span><span class="hl opt">(</span>SRCS <span class="hl kwd">${SRCS}</span> version.rc<span class="hl opt">)</span> +<span class="hl kwa">endif</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span></pre> + + <p>Process specified header files with the Qt meta-object compiler:</p> + +<pre class="hl"><span class="hl kwd">qt4_wrap_cpp</span><span class="hl opt">(</span>MOC_SRCS <span class="hl kwd">${MOC_HDRS}</span><span class="hl opt">)</span></pre> + + <p>Put it all together and compile the module:</p> + +<pre class="hl"><span class="hl kwa">add_library</span><span class="hl opt">(</span><span class="hl kwd">${TARGET}</span> <span class="hl kwb">SHARED</span> <span class="hl kwd">${SRCS} ${MOC_SRCS}</span><span class="hl opt">)</span></pre> + + <p>Finally, link the module:</p> + +<pre class="hl"><span class="hl kwa">target_link_libraries</span><span class="hl opt">(</span><span class="hl kwd">${TARGET} ${QT_LIBRARIES} ${eVaf_LIBRARIES}</span><span class="hl opt">)</span></pre> + + <p>And the final <tt>CMakeLists.txt</tt> file looks the following:</p> + +<pre class="hl"><span class="hl com"># src/apps/PswGen/Generator/CMakeLists.txt</span> + +<span class="hl com"># Name of the target</span> +<span class="hl kwa">set</span><span class="hl opt">(</span>TARGET PswGen<span class="hl opt">)</span> + +<span class="hl com"># Qt modules</span> +<span class="hl kwa">set</span><span class="hl opt">(</span>QT_DONT_USE_QTGUI TRUE<span class="hl opt">)</span> +<span class="hl kwa">include</span><span class="hl opt">(</span><span class="hl kwd">${QT_USE_FILE}</span><span class="hl opt">)</span> + +<span class="hl com"># Needed for exporting symbols from this library</span> +<span class="hl kwa">add_definitions</span><span class="hl opt">(</span>-DPSWGEN_GENERATOR_LIBRARY<span class="hl opt">)</span> + +<span class="hl com"># Include directories</span> +<span class="hl kwa">include_directories</span><span class="hl opt">(</span><span class="hl kwd">${eVaf_INCLUDE}<span class="hl opt">)</span> + +<span class="hl com"># Required eVaf libraries</span> +<span class="hl kwa">set</span><span class="hl opt">(</span>eVaf_LIBRARIES CommonLib PluginsLib<span class="hl opt">)</span> + +<span class="hl com"># Source files</span> +<span class="hl kwa">set</span><span class="hl opt">(</span>MOC_HDRS + igenerator.h + module.h +<span class="hl opt">)</span> + +<span class="hl com"># Header files for the Qt meta-object compiler</span> +<span class="hl kwa">set</span><span class="hl opt">(</span>MOC_HDRS + igenerator.h + module.h +<span class="hl opt">)</span> + +<span class="hl com"># Version info resource file for Windows builds</span> +<span class="hl kwa">if</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span> + <span class="hl kwa">set</span><span class="hl opt">(</span>SRCS <span class="hl kwd">${SRCS}</span> version.rc<span class="hl opt">)</span> +<span class="hl kwa">endif</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span> + +<span class="hl com"># Run the Qt meta-object compiler</span> +<span class="hl kwd">qt4_wrap_cpp</span><span class="hl opt">(</span>MOC_SRCS <span class="hl kwd">${MOC_HDRS}</span><span class="hl opt">)</span> + +<span class="hl com"># Compile the module</span> +<span class="hl kwa">add_library</span><span class="hl opt">(</span><span class="hl kwd">${TARGET}</span> <span class="hl kwb">SHARED</span> <span class="hl kwd">${SRCS} ${MOC_SRCS}</span><span class="hl opt">)</span> + +<span class="hl com"># Link the module</span> +<span class="hl kwa">target_link_libraries</span><span class="hl opt">(</span><span class="hl kwd">${TARGET} ${QT_LIBRARIES} ${eVaf_LIBRARIES}</span><span class="hl opt">)</span></pre> + + <p>We also need <tt>CMakeLists.txt</tt> files in parent directory <tt>src/apps/PswGen</tt>. + In this file we add the <tt>PswGen</tt> directory to the list of include directories, which makes it possible to use + +<pre class="hl"><span class="hl com"># src/apps/PswGen/CMakeLists.txt</span> +<span class="hl kwa">set</span><span class="hl opt">(</span>eVaf_INCLUDE <span class="hl kwd">${eVaf_INCLUDE} ${SMAKE_SOURCE_DIR}</span>/src/apps/PswGen<span class="hl opt">)</span> +<span class="hl kwa">add_subdirectory</span><span class="hl opt">(</span>Generator<span class="hl opt">)</span></pre> + + <p>Modify the <tt>CMakeLists.txt</tt> file in the <tt>src/apps</tt> directory and include the <tt>PswGen</tt> application:</p> + +<pre class="hl"><span class="hl com"># src/apps/CMakeLists.txt</span> +<span class="hl com"># ...</span> +<span class="hl kwa">add_subdirectory</span><span class="hl opt">(</span>PswGen<span class="hl opt">)</span></pre> + + <h3>Building the module</h3> + + <p>Now our module is included in the build system and we can try to compile it. Go to the eVaf root directory and create + a build directory:</p> + +<pre>evaf $ <code>mkdir build</code> +evaf $ <code>cd build</code></pre> + + <p>In the build directory, run <tt>cmake</tt>:</p> + +<pre>evaf/build $ <code>cmake ..</code></pre> + + <p>If <tt>cmake</tt> finishes without errors, build the module with the <tt>make</tt> command:</p> + +<pre>evaf/build $ <code>make PswGen</code></pre> + + <p>If you get compiler errors during the build, fix them. If the build finishes without errors, check the content of the + <tt>bin</tt> directory:</p> + +<pre>evaf/build $ <code>ls bin</code> +libCommonLib.so* libPluginsLib.so* libPswGen.so* +evaf/build $</pre> + + <p>As you can see, there are three libraries now. The <tt>libPswGen.so</tt> is our module and others are eVaf libraries + that our module needs in order to be run.</p> + + <p>In the next section <a href="pswgen06.html">06 - Storage Module</a> we write the Storage module. + + </body> +</html> -- 2.49.0