]> vaikene.ee Git - evaf/blob - www/pswgen03.html
Fixed typo in the tutorial.
[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 and 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>We need to include some Qt header files -- <tt>QObject</tt> is almost always needed and <tt>QString</tt> we need for input data and generated
38 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>. For pure abstract classes I personally prefer using the <tt>struct</tt> keyword, but
53 <tt>class</tt> works as well if you remember to add the <tt>public</tt> keyword to make methods in the class public.</p>
54
55 <pre class="hl"><span class="hl kwc">struct</span> iGenerator
56 <span class="hl opt">{</span>
57
58 <span class="hl opt">};</span></pre>
59
60 <p>We add functionality to the interface and according to the specification we need two functions -- one that
61 generates passwords and another that returns the maximum length of the password:</p>
62
63 <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>
64
65 <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>
66
67 <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>
68
69 <p>We use the <tt>Q_DECLARE_INTERFACE</tt> macro to add Qt meta-data to the interface. eVaf interfaces are type-casted using the <tt>qobject_cast&lt;&gt;()</tt> template function and it requires meta-data to verify type and version of the interface. The <tt>Q_DECLARE_INTERFACE</tt> macro has to be
70 outside of any namespaces and we add it to the end of the file:</p>
71
72 <pre class="hl"><span class="hl kwd">Q_DECLARE_INTERFACE</span><span class="hl opt">(</span>eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>iGenerator<span class="hl opt">,</span> <span class="hl str">&quot;eVaf.PswGen.iGenerator/1.0&quot;</span><span class="hl opt">)</span></pre>
73
74 <p>This is pretty much all we need to add to the <tt>iGenerator</tt> interface and here is the final file:</p>
75
76 <pre class="hl"><span class="hl com">/**</span>
77 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/igenerator.h</span>
78 <span class="hl com"> */</span>
79
80 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span>
81 <span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span>
82
83 <span class="hl ppc">#include &lt;QObject&gt;</span>
84 <span class="hl ppc">#include &lt;QString&gt;</span>
85
86 <span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
87 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
88
89 <span class="hl com">/// Password generator interface.</span>
90 <span class="hl kwb">struct</span> iGenerator
91 <span class="hl opt">{</span>
92 <span class="hl com">/// Generates a strong password</span>
93 <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>
94
95 <span class="hl com">/// Returns the maximum length of generated passwords</span>
96 <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>
97
98 <span class="hl opt">};</span>
99
100 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
101 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span>
102
103 <span class="hl kwd">Q_DECLARE_INTERFACE</span><span class="hl opt">(</span>eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>iGenerator<span class="hl opt">,</span> <span class="hl str">&quot;eVaf.PswGen.iGenerator/1.0&quot;</span><span class="hl opt">)</span>
104
105 <span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span></pre>
106
107 <p>As a final touch, we create a file called <tt>iGenerator</tt> with the following content:</p>
108 <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">&quot;igenerator.h&quot;</span><span class="hl ppc"></span></pre>
109
110 <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>
111
112 <h3>Generator module</h3>
113
114 <p>Now we write the Generator module itself. The module class has to be derived from the <tt>Plugins::iPlugin</tt> interface class
115 with or without the <tt>Plugins::iPluginFactory</tt> factory class.</p>
116
117 <p>The <tt>Plugins::iPluginFactory</tt> factory class should be used when more than one plugins are implemented by the same
118 module. The factory class takes care of creating individual plugins whenever they are instantiated. This module implements only
119 one plugin and we opt to the implementation without the factory class.</p>
120
121 <p>Create the <tt>module.h</tt> header file in the <tt>src/apps/PswGen/Generator</tt> directory:</p>
122
123 <pre class="hl"><span class="hl com">/**</span>
124 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/module.h</span>
125 <span class="hl com"> */</span>
126 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span>
127 <span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span>
128
129 <span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre>
130
131 <p>As this is a simple module, we define all our class in this single header file. This includes the implementation
132 of the <tt>iGenerator</tt> interface and also the plugin itself. Se we need to include header files for the
133 <tt>iGenerator</tt> and <tt>iPlugin</tt> interfaces:</p>
134
135 <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">&quot;igenerator.h&quot;</span><span class="hl ppc"></span>
136 <span class="hl ppc">#include &lt;Plugins/iPlugin&gt;</span></pre>
137
138 <p>We are going to put every public class in this module into the <tt>eVaf::PswGen::Generator</tt> namespace and private
139 classes into the <tt>eVaf::PswGen::Generator::Private</tt> namespace:</p>
140
141 <pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
142 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
143
144 <span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span>
145 <span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span>
146
147 <span class="hl slc">/// Internal implementation of the Generator module</span>
148 <span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
149
150 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
151 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span>
152 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
153 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre>
154
155 <p>We call the class that implements the module simply <tt>Module</tt>. This is a public class and goes into the
156 <tt>eVaf::PswGen::Generator</tt> namespace</tt>.</p>
157
158 <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
159 <span class="hl opt">{</span>
160 Q_OBJECT
161
162 <span class="hl kwc">public</span><span class="hl opt">:</span>
163
164 <span class="hl kwd">Module</span><span class="hl opt">();</span>
165
166 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span>
167
168 }</span></pre>
169
170 <p>The <tt>iPlugin</tt> interface has three pure virtual methods that we need to implement in our class -- <tt>init()</tt>,
171 <tt>done()</tt> and <tt>isReady()</tt>. Since this simple module is always ready, we can return always <tt>true</tt> in the
172 <tt>isReady()</tt> function. More complex modules can use a private <tt>mReady</tt> variable, which they set to <tt>true</tt>
173 once all the initialization is done.</tt>
174
175 <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>
176
177 <span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span>
178
179 <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>
180
181 <p>We need the <tt>iGenerator</tt> interface object in this module and add it to the private members section:</tt>
182
183 <pre class="hl"><span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span>
184
185 <span class="hl slc">/// iGenerator interface instance</span>
186 Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span></pre>
187
188 <p>As the <tt>Internal::GeneratorImpl</tt> class is not declared yet, we need to add this forward declaration before the
189 <tt>Module</tt> class:</p>
190
191 <pre class="hl"><span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
192 <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span>
193 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span></pre>
194
195 <p>Then we can move forward and implement the <tt>iGenerator</tt> interface, which we already happened to call
196 <tt>GeneratorImpl</tt>. This class goes into the <tt>eVaf::PswGen::Generator::Internal</tt> namespace.</p>
197
198 <p>The <tt>GeneratorImpl</tt> class needs to be derived both from <tt>QObject</tt> and from <tt>iGenerator</tt>. We also have to use the
199 <tt>Q_INTERFACES</tt> macro to include Qt meta-data for the <tt>iGenerator</tt> interface:</p>
200
201 <pre class="hl"><span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject<span class="hl opt">,</span> <span class="hl kwc">public</span> iGenerator
202 <span class="hl opt">{</span>
203 <span class="hl kwd">Q_OBJECT</span>
204 <span class="hl kwd">Q_INTERFACES</span><span class="hl opt">(</span>eVaf::PswGen::iGenerator<span class="hl opt">)</span>
205
206 <span class="hl kwc">public</span><span class="hl opt">:</span>
207
208 <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
209
210 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
211
212 <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>
213
214 <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>
215 <span class="hl opt">};</span></pre>
216
217 <p>Here is the final <tt>module.h</tt> file:</p>
218
219 <pre class="hl"><span class="hl com">/**</span>
220 <span class="hl com"> * &#64;file src/apps/PswGen/Generator/module.h</span>
221 <span class="hl com"> */</span>
222
223 <span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span>
224 <span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span>
225
226 <span class="hl ppc">#include</span> <span class="hl pps">&quot;igenerator.h&quot;</span><span class="hl ppc"></span>
227
228 <span class="hl ppc">#include &lt;Plugins/iPlugin&gt;</span>
229
230 <span class="hl ppc">#include &lt;QObject&gt;</span>
231 <span class="hl ppc">#include &lt;QString&gt;</span>
232
233 <span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
234 <span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
235
236 <span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span>
237 <span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span>
238
239 <span class="hl slc">/// Internal implementation of the Generator module</span>
240 <span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
241 <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span>
242 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
243
244 <span class="hl com">/// Plugins::iPlugin interface implementation.</span>
245 <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
246 <span class="hl opt">{</span>
247 <span class="hl kwd">Q_OBJECT</span>
248
249 <span class="hl kwc">public</span><span class="hl opt">:</span>
250
251 <span class="hl kwd">Module</span><span class="hl opt">();</span>
252
253 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span>
254
255 <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>
256
257 <span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span>
258
259 <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>
260
261 <span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span>
262
263 <span class="hl slc">/// iGenerator interface instance</span>
264 Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span>
265 <span class="hl opt">};</span>
266
267 <span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
268
269 <span class="hl com">/// iGenerator interface implementation.</span>
270 <span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject<span class="hl opt">,</span> <span class="hl kwc">public</span> iGenerator
271 <span class="hl opt">{</span>
272 <span class="hl kwd">Q_OBJECT</span>
273 <span class="hl kwd">Q_INTERFACES</span><span class="hl opt">(</span>eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>iGenerator<span class="hl opt">)</span>
274
275 <span class="hl kwc">public</span><span class="hl opt">:</span>
276
277 <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
278
279 <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
280
281 <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>
282
283 <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>
284 <span class="hl opt">};</span>
285
286 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
287
288 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span>
289 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
290 <span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span>
291
292 <span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre>
293
294 <p>Continue implementing the <a href="pswgen04.html">Generator Module</a>.</p>
295
296 </body>
297
298 </html>