]> vaikene.ee Git - evaf/blob - www/pswgen03.html
056da8e42145a4b3c1f15656e206c67b8cb92497
[evaf] / www / pswgen03.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 - 03 - 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>03 - Generator Module</h2>
19
20 <p>In this section we write the Generator module. According to the specification, the Generator module has to
21 generate strong passwords in such a way that by feeding the module with the same input data we always get the
22 same password.</p>
23
24 <h3>iGenerator interface</h3>
25
26 <p>We start by defining the interface for the module. For this create the file <tt>igenerator.h</tt> in the
27 <tt>src/apps/pswGen/Generator</tt> directory:</p>
28
29 <pre class="hl"><span class="hl com">/**</span>
30 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/igenerator.h</span>
31 <span class="hl com"> */</span>
32 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span>
33 <span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span>
34
35 <span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span></pre>
36
37 <p>The interface class needs to be derived from <tt>QObject</tt> and we also need <tt>QString</tt> for input
38 data and generated passwords:</p>
39
40 <pre class="hl"><span class="hl ppc">#include &lt;QObject&gt;</span>
41 <span class="hl ppc">#include &lt;QString&gt;</span></pre>
42
43 <p>To avoid potential name collisions with other existing or future modules, we use the <tt>eVaf::PswGen</tt>
44 namespace for this application:</p>
45
46 <pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
47 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
48
49 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
50 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre>
51
52 <p>We call the interface class <tt>iGenerator</tt>:
53
54 <pre class="hl"><span class="hl kwc">class</span> iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject
55 <span class="hl opt">{</span>
56 Q_OBJECT
57 <span class="hl kwc">public</span><span class="hl opt">:</span>
58 <span class="hl opt">};</span></pre>
59
60 <p>All the interface classes need a default constructor and an empty virtual destructor. Do not perform any actions
61 in these constructors and destructors. Instead, leave it up to the class that implements the interface.</p>
62 <pre class="hl"><span class="hl slc">/// Interface constructor</span>
63 <span class="hl kwd">iGenerator</span><span class="hl opt">() :</span> <span class="hl kwd">QObject</span><span class="hl opt">() {}</span>
64
65 <span class="hl slc">/// Empty virtual destructor</span>
66 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">iGenerator</span><span class="hl opt">() {}</span></pre>
67
68 <p>Now we add the functionality to the interface and according to the specification we need two functions -- one that
69 generates passwords and another that returns the maximum length of the password:</p>
70
71 <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>
72
73 <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>
74
75 <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>
76
77 <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>
78 <pre class="hl"><span class="hl com">/**</span>
79 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/lib.h</span>
80 <span class="hl com"> */</span>
81 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_LIB_H</span>
82 <span class="hl ppc"># define __PSWGEN_GENERATOR_LIB_H</span>
83
84 <span class="hl ppc">#include &lt;QtCore/qglobal.h&gt;</span>
85
86 <span class="hl ppc">#if defined(PSWGEN_GENERATOR_LIBRARY)</span>
87 <span class="hl ppc"># define PSWGEN_GENERATOR_EXPORT Q_DECL_EXPORT</span>
88 <span class="hl ppc">#else</span>
89 <span class="hl ppc"># define PSWGEN_GENERATOR_EXPORT Q_DECL_IMPORT</span>
90 <span class="hl ppc">#endif</span>
91 <span class="hl ppc">#endif</span> <span class="hl slc">// libgen.h</span><span class="hl ppc"></span></pre>
92
93 <p>Then we include this new header file in our interface header file and modify the <tt>iGenerator</tt> class definition by adding
94 the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro to it:</p>
95 <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">&quot;lib.h&quot;</span><span class="hl ppc"></span>
96
97 /// ...
98
99 <span class="hl kwc">class</span> PSWGEN_GENERATOR_EXPORT iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject</pre>
100
101 <p>This is pretty much all we need to add to the <tt>iGenerator</tt> interface and here is the final file:</p>
102
103 <pre class="hl"><span class="hl com">/**</span>
104 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/igenerator.h</span>
105 <span class="hl com"> */</span>
106
107 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span>
108 <span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span>
109
110 <span class="hl ppc">#include</span> <span class="hl pps">&quot;lib.h&quot;</span><span class="hl ppc"></span>
111
112 <span class="hl ppc">#include &lt;QObject&gt;</span>
113 <span class="hl ppc">#include &lt;QString&gt;</span>
114
115 <span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
116 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
117
118 <span class="hl com">/// Password generator interface.</span>
119 <span class="hl kwc">class</span> PSWGEN_GENERATOR_EXPORT iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject
120 <span class="hl opt">{</span>
121 Q_OBJECT
122
123 <span class="hl kwc">public</span><span class="hl opt">:</span>
124
125 <span class="hl slc">/// Interface constructor</span>
126 <span class="hl kwd">iGenerator</span><span class="hl opt">() :</span> <span class="hl kwd">QObject</span><span class="hl opt">() {}</span>
127
128 <span class="hl slc">/// Empty virtual destructor</span>
129 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">iGenerator</span><span class="hl opt">() {}</span>
130
131 <span class="hl com">/// Generates a strong password</span>
132 <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>
133
134 <span class="hl com">/// Returns the maximum length of generated passwords</span>
135 <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>
136
137 <span class="hl opt">};</span>
138
139 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
140 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span>
141
142 <span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span>
143 </pre>
144
145 <p>As a final touch, we create a file called <tt>iGenerator</tt> with the following content:</p>
146 <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">&quot;igenerator.h&quot;</span><span class="hl ppc"></span></pre>
147
148 <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>
149
150 <h3>Generator module</h3>
151
152 <p>Now we write the Generator module itself. The module class has to be derived from the <tt>Plugins::iPlugin</tt> interface class
153 with or without the <tt>Plugins::iPluginFactory</tt> factory class.</p>
154
155 <p>The <tt>Plugins::iPluginFactory</tt> factory class should be used when more than one plugins are implemented by the same
156 module. The factory class takes care of creating individual plugins whenever they are instantiated. This module implements only
157 one plugin and we opt to the implementation without the factory class.</p>
158
159 <p>Create the <tt>module.h</tt> header file in the <tt>src/apps/PswGen/Generator</tt> directory:</p>
160
161 <pre class="hl"><span class="hl com">/**</span>
162 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/module.h</span>
163 <span class="hl com"> */</span>
164 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span>
165 <span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span>
166
167 <span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre>
168
169 <p>As this is a simple module, we define all our class in this single header file. This includes the implementation
170 of the <tt>iGenerator</tt> interface and also the plugin itself. Se we need to include header files for the
171 <tt>iGenerator</tt> and <tt>iPlugin</tt> interfaces:</p>
172
173 <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">&quot;igenerator.h&quot;</span><span class="hl ppc"></span>
174 <span class="hl ppc">#include &lt;Plugins/iPlugin&gt;</span></pre>
175
176 <p>We are going to put every public class in this module into the <tt>eVaf::PswGen::Generator</tt> namespace and private
177 classes into the <tt>eVaf::PswGen::Generator::Private</tt> namespace:</p>
178
179 <pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
180 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
181
182 <span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span>
183 <span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span>
184
185 <span class="hl slc">/// Internal implementation of the Generator module</span>
186 <span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
187
188 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
189 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span>
190 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
191 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre>
192
193 <p>We call the class that implements the module simply <tt>Module</tt>. This is a public class and goes into the
194 <tt>eVaf::PswGen::Generator</tt> namespace</tt>. We however, do not need to export it as we did with the <tt>iGenerator</tt>
195 interface class, as this will be done by Qt.</p>
196
197 <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
198 <span class="hl opt">{</span>
199 Q_OBJECT
200
201 <span class="hl kwc">public</span><span class="hl opt">:</span>
202
203 <span class="hl kwd">Module</span><span class="hl opt">();</span>
204
205 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span>
206
207 }</span></pre>
208
209 <p>The <tt>iPlugin</tt> interface has three abstract methods that we need to implement in our class -- <tt>init()</tt>,
210 <tt>done()</tt> and <tt>isReady()</tt>. Since this simple module is always ready, we can return <tt>true</tt> in the
211 <tt>isReady()</tt> function. More complex modules can use a private <tt>mReady</tt> variable, which they set to <tt>true</tt>
212 once all the initialization is done.</tt>
213
214 <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>
215
216 <span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span>
217
218 <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>
219
220 <p>We need the <tt>iGenerator</tt> interface object in this module and add it to the private members section:</tt>
221
222 <pre class="hl"><span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span>
223
224 <span class="hl slc">/// iGenerator interface instance</span>
225 Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span></pre>
226
227 <p>As the <tt>Internal::GeneratorImpl</tt> class is not declared yet, we need to add this forward declaration before the
228 <tt>Module</tt> class:</p>
229
230 <pre class="hl"><span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
231 <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span>
232 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span></pre>
233
234 <p>Then we can move forward and implement the <tt>iGenerator</tt> interface, which we already happened to call
235 <tt>GeneratorImpl</tt>. This class goes into the <tt>eVaf::PswGen::Generator::Internal</tt> namespace:</p>
236
237 <pre class="hl"><span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator
238 <span class="hl opt">{</span>
239 Q_OBJECT
240
241 <span class="hl kwc">public</span><span class="hl opt">:</span>
242
243 <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
244
245 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
246
247 <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>
248
249 <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>
250 <span class="hl opt">};</span></pre>
251
252 <p>Here is the final <tt>module.h</tt> file:</p>
253
254 <pre class="hl"><span class="hl com">/**</span>
255 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/module.h</span>
256 <span class="hl com"> */</span>
257
258 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span>
259 <span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span>
260
261 <span class="hl ppc">#include</span> <span class="hl pps">&quot;igenerator.h&quot;</span><span class="hl ppc"></span>
262
263 <span class="hl ppc">#include &lt;Plugins/iPlugin&gt;</span>
264
265 <span class="hl ppc">#include &lt;QObject&gt;</span>
266 <span class="hl ppc">#include &lt;QString&gt;</span>
267
268 <span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
269 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
270
271 <span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span>
272 <span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span>
273
274 <span class="hl slc">/// Internal implementation of the Generator module</span>
275 <span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
276 <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span>
277 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
278
279 <span class="hl com">/// Plugins/iPlugin interface implementation.</span>
280 <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
281 <span class="hl opt">{</span>
282 Q_OBJECT
283
284 <span class="hl kwc">public</span><span class="hl opt">:</span>
285
286 <span class="hl kwd">Module</span><span class="hl opt">();</span>
287
288 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span>
289
290 <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>
291
292 <span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span>
293
294 <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>
295
296
297 <span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span>
298
299 <span class="hl slc">/// iGenerator interface instance</span>
300 Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span>
301
302 <span class="hl opt">};</span>
303
304 <span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
305
306 <span class="hl com"> /// iGenerator interface implementation.</span>
307 <span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator
308 <span class="hl opt">{</span>
309 Q_OBJECT
310
311 <span class="hl kwc">public</span><span class="hl opt">:</span>
312
313 <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
314
315 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
316
317 <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>
318
319 <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>
320
321 <span class="hl opt">};</span>
322
323 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
324 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span>
325 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
326 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span>
327
328 <span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre>
329
330 <p>Continue implementing the <a href="pswgen04.html">Generator Module</a>.</p>
331
332 </body>
333
334 </html>