]> vaikene.ee Git - evaf/blob - www/pswgen04.html
df82cb0b946a970ac9d1335fee64c395576e05c1
[evaf] / www / pswgen04.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et">
3
4 <head>
5 <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
6 <title>eVaf Tutorial - 04 - Generator Module</title>
7 <meta name="Author" content="Enar Väikene" />
8 <meta name="description" content="eVaf Tutorial" />
9 <meta name="keywords" content="evaf c++ application development framework tutorial password generator" />
10 <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" />
11 <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" />
12 </head>
13
14 <body>
15
16 <h1>eVaf Tutorial</h1>
17
18 <h2>04 - Generator Module</h2>
19
20 <p>Now we are going to implement all the classes declared in the <tt>module.h</tt>. Create the <tt>module.cpp</tt> file
21 in the <tt>src/apps/PswGen/Generator</tt> directory. We obviously include the <tt>module.h</tt> header file, but also
22 the <tt>QtCore</tt> header file for any non-GUI Qt classes.</p>
23
24 <pre class="hl"><span class="hl com">/**</span>
25 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/module.cpp</span>
26 <span class="hl com"> */</span>
27
28 <span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
29
30 <span class="hl ppc">#include &lt;QtCore&gt;</span></pre>
31
32 <p>All the eVaf modules need to include version information. This is common for all the modules and we can simply
33 copy existing version info files from another eVaf module:</p>
34
35 <pre>evaf/src/apps/PswGen/Generator $ <code>cp ../../../plugins/SdiWindow/version.{h,rc} .</code></pre>
36
37 <p>The <tt>version.h</tt> file contains version information for the module. The <tt>version.rc</tt> is for Windows
38 builds only and embeds the same version information into the dll or exe file. Modify the copied <tt>version.h</tt>
39 file for our new module. The <tt>version.rc</tt> file uses the values from the <tt>version.h</tt> and does not
40 need to be touched.</p>
41
42 <pre class="hl"><span class="hl com">/**</span>
43 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/version.h</span>
44 <span class="hl com"> */</span>
45 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_VERSION_H</span>
46 <span class="hl ppc">#define __PSWGEN_GENERATOR_VERSION_H</span>
47
48 <span class="hl ppc">#include &lt;version_rc.h&gt;</span>
49
50 <span class="hl com">/**</span>
51 <span class="hl com"> * Module/library version number in the form major,minor,release,build</span>
52 <span class="hl com"> */</span>
53 <span class="hl ppc">#define VER_FILE_VERSION 0,1,1,1</span>
54
55 <span class="hl com">/**</span>
56 <span class="hl com"> * Module/library version number in the string format (shall end with \0)</span>
57 <span class="hl com"> */</span>
58 <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>
59
60 <span class="hl com">/**</span>
61 <span class="hl com"> * Module/library name (shall end with \0)</span>
62 <span class="hl com"> */</span>
63 <span class="hl ppc">#define VER_MODULE_NAME_STR</span> <span class="hl pps">&quot;PswGen\0&quot;</span><span class="hl ppc"></span>
64
65 <span class="hl com">/**</span>
66 <span class="hl com"> * Module type (see version_rc.h for all the types)</span>
67 <span class="hl com"> */</span>
68 <span class="hl ppc">#define VER_MODULE_TYPE MT_GENERIC</span>
69
70 <span class="hl com">/**</span>
71 <span class="hl com"> * Module type in the string format (see version_rc for all the types)</span>
72 <span class="hl com"> */</span>
73 <span class="hl ppc">#define VER_MODULE_TYPE_STR MT_GENERIC</span>
74
75 <span class="hl com">/**</span>
76 <span class="hl com"> * Original file name for windows (shall end with \0)</span>
77 <span class="hl com"> */</span>
78 <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>
79
80 <span class="hl com">/**</span>
81 <span class="hl com"> * Description of the module/library (shall end with \0)</span>
82 <span class="hl com"> */</span>
83 <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>
84
85 <span class="hl ppc">#endif</span> <span class="hl slc">// version.h</span><span class="hl ppc"></span></pre>
86
87 <p>Then include the version info file in the <tt>module.cpp</tt> file and use the <tt>VER_EXPORT_VERSION_INFO()</tt> macro
88 to export version information from the module. This macro defines a public function that all the eVaf modules export and
89 is used to collect version information from them. In your modules you only need to modify the <tt>version.h</tt> file and then
90 use the <tt>VER_EXPORT_VERSION_INFO()</tt> macro once somewhere in your code.</p>
91
92 <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
93
94 <span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span></pre>
95
96 <p>We make our life easier with several <tt>using namespace</tt> keywords:</p>
97
98 <pre class="hl"><span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span>
99 <span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span>
100 <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>
101
102 <p>The Module class needs to instantiate the <tt>iGenerator</tt> interface in the constructor. We also need to set
103 the QObject's name property to the name of the plugin by combining the name of the module with the name of the class.
104 While the application would work without the name property, it makes our life much easier if the name property is set.</p>
105
106 <p>Finally, we output an info message telling that the object was created. Every eVaf module and class is expected to
107 output info messages when they are created, destroyed, initialized or destroyed.</p>
108
109 <pre class="hl">Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
110 <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span>
111 <span class="hl opt">{</span>
112 <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>
113
114 mGenerator <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>GeneratorImpl<span class="hl opt">;</span>
115
116 <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>
117 <span class="hl opt">}</span></pre>
118
119 <p>The <tt>EVAF_INFO</tt> macro comes from the <tt>Common/iLogger</tt> header file ane we need to include it:</p>
120
121 <pre class="hl"><span class="hl ppc">#include &lt;Common/iLogger&gt;</span></pre>
122
123 <p>The destructor should delete the <tt>iGenerator</tt> interface object, which we created in the constructor. The common
124 rule is that any resources allocated in the constructor shall be released in the destructor, preferrably in the opposite
125 order, ie. the first resource allocated in the constructor is released last in the destructor.</tt>
126
127 <pre class="hl">Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
128 <span class="hl opt">{</span>
129 <span class="hl kwa">delete</span> mGenerator<span class="hl opt">;</span>
130
131 <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>
132 <span class="hl opt">}</span></pre>
133
134 <p>We also need to implement <tt>init()</tt> and <tt>done()</tt> functions, which are used to initialize and finalize modules.
135 They are similar to the constructor and destructor with two major differences:</p>
136 <ol>
137 <li>The <tt>init()</tt> function can fail and return <tt>false</tt> to indicate a failure. eVaf does not use exceptions and
138 this is the only way for a module to fail without terminating the whole application. A failed module will be disabled
139 and the rest of the application can still run if it can.</li>
140 <li>eVaf modules are loaded in two steps. At first, all the modules are created, which means that all the objects
141 are constructed. Only then will eVaf call <tt>init()</tt> functions meaning that when the <tt>init()</tt> function is
142 called, all the modules are already loaded and instantiated. Interfaces and resources from other modules that might be not
143 available when the object is created, are available when the <tt>init()</tt> function is called.</li>
144 </ol>
145
146 <p>The rule for <tt>init()</tt> and <tt>done()</tt> functions is the same than for constructors and destructors -- any resource
147 allocated in the <tt>init()</tt> function shall be released in the <tt>done()</tt> function and preferrably in the opposite
148 order.</p>
149
150 <p>This simple module needs no extra resources to be allocated and our <tt>init()</tt> and <tt>done()</tt> functions can be
151 the following:</p>
152
153 <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>
154 <span class="hl opt">{</span>
155 <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span>
156
157 <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>
158
159 <span class="hl kwa">return true</span><span class="hl opt">;</span>
160 <span class="hl opt">}</span>
161
162 <span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
163 <span class="hl opt">{</span>
164 <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>
165 <span class="hl opt">}</span></pre>
166
167 <p>We continue by implementing the <tt>iGenerator</tt> interface. There are no resources to be allocated in the constructor
168 and we just set the QObject's name property and output the info message.</p>
169
170 <p>We also register the <tt>iGenerator</tt> interface in the global registry so that other modules can query for it and
171 use our interface. This is done by using the <tt>Common::iRegistry</tt> interface, which we need to include:</p>
172
173 <pre class="hl"><span class="hl ppc">#include &lt;Common/iRegistry&gt;</span></pre>
174
175 <p>The <tt>GeneratorImpl</tt> class was declared in the <tt>eVaf::PswGen::Generator::Internal</tt> namespace, so we need
176 another <tt>using namespace</tt> keyword before the implementation of the class:</p>
177
178 <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>
179
180 GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
181 <span class="hl opt">:</span> <span class="hl kwd">iGenerator</span><span class="hl opt">()</span>
182 <span class="hl opt">{</span>
183 <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>
184
185 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>
186
187 <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>
188 <span class="hl opt">}</span>
189
190 GeneratorImpl<span class="hl opt">::~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
191 <span class="hl opt">{</span>
192 <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>
193 <span class="hl opt">}</span></pre>
194
195 <p>Finally, we write the <tt>generatePassword</tt> function that does the actual job of the module.</p>
196
197 <p>We use the MD5 cryptographic hash function to calculate a hash value over the <tt>name</tt> and <tt>masterPassword</tt> values.
198 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
199 for this and cut the result to the requested length:</p>
200
201 <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>
202 <span class="hl opt">{</span>
203 <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>flags<span class="hl opt">);</span>
204
205 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>
206 QCryptographicHash <span class="hl kwd">hash</span><span class="hl opt">(</span>QCryptographicHash<span class="hl opt">::</span>Md5<span class="hl opt">);</span>
207 hash<span class="hl opt">.</span><span class="hl kwd">addData</span><span class="hl opt">(</span>inputString<span class="hl opt">);</span>
208 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>
209 <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>
210 <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>
211 <span class="hl kwa">else</span>
212 <span class="hl kwa">return</span> result<span class="hl opt">;</span>
213 <span class="hl opt">}</span></pre>
214
215 <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
216 modify the <tt>GeneratorImpl::maxLength()</tt> function:</p>
217
218 <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>
219
220 <p>Here is the final <tt>module.cpp</tt> file:</p>
221
222 <pre class="hl"><span class="hl com">/**</span>
223 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/module.cpp</span>
224 <span class="hl com"> */</span>
225
226 <span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
227 <span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
228
229 <span class="hl ppc">#include &lt;Common/iLogger&gt;</span>
230 <span class="hl ppc">#include &lt;Common/iRegistry&gt;</span>
231
232 <span class="hl ppc">#include &lt;QtCore&gt;</span>
233
234 <span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span>
235 <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>
236
237 <span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span>
238 <span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span>
239 <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>
240
241 Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
242 <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span>
243 <span class="hl opt">{</span>
244 <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>
245
246 mGenerator <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>GeneratorImpl<span class="hl opt">;</span>
247
248 <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>
249 <span class="hl opt">}</span>
250
251 Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
252 <span class="hl opt">{</span>
253 <span class="hl kwa">delete</span> mGenerator<span class="hl opt">;</span>
254
255 <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>
256 <span class="hl opt">}</span>
257
258 <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>
259 <span class="hl opt">{</span>
260 <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span>
261
262 <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>
263
264 <span class="hl kwa">return true</span><span class="hl opt">;</span>
265 <span class="hl opt">}</span>
266
267 <span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
268 <span class="hl opt">{</span>
269 <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>
270 <span class="hl opt">}</span>
271
272 <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>
273
274 GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
275 <span class="hl opt">:</span> <span class="hl kwd">iGenerator</span><span class="hl opt">()</span>
276 <span class="hl opt">{</span>
277 <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>
278
279 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>
280
281 <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>
282 <span class="hl opt">}</span>
283
284 GeneratorImpl<span class="hl opt">::~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
285 <span class="hl opt">{</span>
286 <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>
287 <span class="hl opt">}</span>
288
289 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>
290 <span class="hl opt">{</span>
291 <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>flags<span class="hl opt">);</span>
292
293 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>
294 QCryptographicHash <span class="hl kwd">hash</span><span class="hl opt">(</span>QCryptographicHash<span class="hl opt">::</span>Md5<span class="hl opt">);</span>
295 hash<span class="hl opt">.</span><span class="hl kwd">addData</span><span class="hl opt">(</span>inputString<span class="hl opt">);</span>
296 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>
297 <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>
298 <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>
299 <span class="hl kwa">else</span>
300 <span class="hl kwa">return</span> result<span class="hl opt">;</span>
301 <span class="hl opt">}</span></pre>
302
303 <p>Next -- <a href="pswgen05.html">05 - Building Generator Module</a>.</p>
304
305 </body>
306 </html>