]> vaikene.ee Git - evaf/blobdiff - www/pswgen04.html
Written more tutorial files.
[evaf] / www / pswgen04.html
diff --git a/www/pswgen04.html b/www/pswgen04.html
new file mode 100644 (file)
index 0000000..df82cb0
--- /dev/null
@@ -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"> * &#64;file src/apps/PswGen/Generator/module.cpp</span>
+<span class="hl com"> */</span>
+
+<span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include &lt;QtCore&gt;</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"> * &#64;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 &lt;version_rc.h&gt;</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">&quot;0.1.1.1\0&quot;</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">&quot;PswGen\0&quot;</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">&quot;PswGen.dll\0&quot;</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">&quot;Module that generates strong passwords using MD5 hashes.\0&quot;</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">&quot;version.h&quot;</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">&quot;%1.%2&quot;</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">&quot;%s created&quot;</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 &lt;Common/iLogger&gt;</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">&quot;%s destroyed&quot;</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">&amp;</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">&quot;%s initialized&quot;</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">&quot;%s finalized&quot;</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 &lt;Common/iRegistry&gt;</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">&quot;%1.iGenerator&quot;</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">()-&gt;</span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">&quot;iGenerator&quot;</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">&quot;%s created&quot;</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">&quot;%s destroyed&quot;</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">&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 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">&quot;%1%2&quot;</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">&gt;</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"> * &#64;file src/apps/PswGen/Generator/module.cpp</span>
+<span class="hl com"> */</span>
+
+<span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
+<span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include &lt;Common/iLogger&gt;</span>
+<span class="hl ppc">#include &lt;Common/iRegistry&gt;</span>
+
+<span class="hl ppc">#include &lt;QtCore&gt;</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">&quot;%1.%2&quot;</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">&quot;%s created&quot;</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">&quot;%s destroyed&quot;</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">&amp;</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">&quot;%s initialized&quot;</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">&quot;%s finalized&quot;</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">&quot;%1.iGenerator&quot;</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">()-&gt;</span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">&quot;iGenerator&quot;</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">&quot;%s created&quot;</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">&quot;%s destroyed&quot;</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">&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 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">&quot;%1%2&quot;</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">&gt;</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>