]> vaikene.ee Git - evaf/blobdiff - www/pswgen03.html
Written more tutorial files.
[evaf] / www / pswgen03.html
diff --git a/www/pswgen03.html b/www/pswgen03.html
new file mode 100644 (file)
index 0000000..056da8e
--- /dev/null
@@ -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"> * &#64;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 &lt;QObject&gt;</span>
+<span class="hl ppc">#include &lt;QString&gt;</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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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 &amp;"</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 &amp;"</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"> * &#64;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 &lt;QtCore/qglobal.h&gt;</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">&quot;lib.h&quot;</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"> * &#64;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">&quot;lib.h&quot;</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include &lt;QObject&gt;</span>
+<span class="hl ppc">#include &lt;QString&gt;</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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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">&quot;igenerator.h&quot;</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"> * &#64;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">&quot;igenerator.h&quot;</span><span class="hl ppc"></span>
+<span class="hl ppc">#include &lt;Plugins/iPlugin&gt;</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">&amp;</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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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"> * &#64;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">&quot;igenerator.h&quot;</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include &lt;Plugins/iPlugin&gt;</span>
+
+<span class="hl ppc">#include &lt;QObject&gt;</span>
+<span class="hl ppc">#include &lt;QString&gt;</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">&amp;</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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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>