contrib: Add helper to build Android dependencies.
[libpwmd.git] / doc / tutorial.html
blobeb46a7b5d433d2378b3e85eba2d410f7c6ea90ab
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
2 <HTML
3 ><HEAD
4 ><TITLE
5 >Libpwmd Tutorial</TITLE
6 ><META
7 NAME="GENERATOR"
8 CONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD
9 ><BODY
10 CLASS="ARTICLE"
11 ><DIV
12 CLASS="ARTICLE"
13 ><DIV
14 CLASS="TITLEPAGE"
15 ><H1
16 CLASS="TITLE"
17 ><A
18 NAME="AEN2"
19 >Libpwmd Tutorial</A
20 ></H1
21 ><H3
22 CLASS="AUTHOR"
23 ><A
24 NAME="AEN5"
25 ></A
26 ></H3
27 ><HR></DIV
28 ><DIV
29 CLASS="SECT1"
30 ><H2
31 CLASS="SECT1"
32 ><A
33 NAME="AEN9"
34 >Introduction</A
35 ></H2
36 ><P
37 >This is a tutorial showing the basic usage of libpwmd<A
38 NAME="AEN12"
39 HREF="#FTN.AEN12"
40 ><SPAN
41 CLASS="footnote"
42 >[2]</SPAN
43 ></A
44 >. Libpwmd<SPAN
45 CLASS="emphasis"
46 ><I
47 CLASS="EMPHASIS"
48 > </I
49 ></SPAN
50 >is a library making it easy for applications to use pwmd<A
51 NAME="AEN15"
52 HREF="#FTN.AEN15"
53 ><SPAN
54 CLASS="footnote"
55 >[4]</SPAN
56 ></A
57 > (<SPAN
58 CLASS="emphasis"
59 ><I
60 CLASS="EMPHASIS"
61 >Password Manager Daemon). Password Manager Daemon</I
62 ></SPAN
63 > is a universal data server. It began as a way to keep track of passwords for accounts like email and websites but has evolved to store anything you want. There are other password management tools but pwmd has a couple of distinguishing features:</P
64 ><P
65 ></P
66 ><UL
67 ><LI
68 ><P
69 >It does not depend on a desktop environment but has the ability for applications to connect to it like a desktop solution provides.</P
70 ></LI
71 ><LI
72 ><P
73 >Some portion of a stored data can be shared with another portion in the same data file. This feature behaves a lot like a symbolic link on a file system, XML entities, or HTML targets if you're familiar with those, but implemented in a different way. This means less duplication of content. See <A
74 HREF="#SEC.LINKING-ELEMENTS-0"
75 >the Section called <I
76 >Linking elements</I
77 ></A
78 > for details.</P
79 ></LI
80 ><LI
81 ><P
82 >The XML document is OpenPGP encrypted and signed using an existing or newly generated key pair. Symmetric encryption is also supported as well as smartcards. All crypto operations are done using GpgME which in turn uses gnupg.</P
83 ></LI
84 ></UL
85 ><P
86 >Other features include:</P
87 ><P
88 ></P
89 ><UL
90 ><LI
91 ><P
92 >Multi-threaded. More than one client may access the same data file while optionally locking out other clients.</P
93 ></LI
94 ><LI
95 ><P
96 >Secure memory management. Pwmd will zero out memory before freeing it and the contents of the cached document are encrypted.</P
97 ></LI
98 ><LI
99 ><P
100 >Remote connections over TLS with client certificates used as authentication.</P
101 ></LI
102 ><LI
104 >Remote connections over SSH (some configuration needed).</P
105 ></LI
106 ><LI
108 >ACL's for each element in an element path, listening socket and filename.</P
109 ></LI
110 ></UL
111 ></DIV
112 ><DIV
113 CLASS="SECT1"
114 ><HR><H2
115 CLASS="SECT1"
117 NAME="AEN38"
118 >File Format and Element Paths</A
119 ></H2
121 >The document is in XML format and is manipulated by commands sent from a client. Commands that access previously stored data take what is called an <SPAN
122 CLASS="emphasis"
124 CLASS="EMPHASIS"
125 >element path</I
126 ></SPAN
127 > as an argument. An element path is a character string containing element names representing branches of an element tree. The branches are separated with a TAB (ASCII 0x09) character. Why a TAB? So other characters can be used in the element name. If for example a '/' were used as the separator, then a URL (i.e., http://sf.net/) could not be used as an element name since it would be an XML syntax error. For the rest of this tutorial, when you see &lt;TAB&gt;, replace it with a real TAB character.</P
129 >For example, the element path "root&lt;TAB&gt;child&lt;TAB&gt;last" has the following element tree structure:</P
130 ><TABLE
131 BORDER="0"
132 BGCOLOR="#E0E0E0"
133 WIDTH="100%"
134 ><TR
135 ><TD
136 ><PRE
137 CLASS="SCREEN"
138 >&#60;root&#62;
139 &#60;child&#62;
140 &#60;last&#62;
141 Content or XML CDATA of the "last" element.
142 &#60;/last&#62;
143 &#60;/child&#62;
144 &#60;/root&#62;</PRE
145 ></TD
146 ></TR
147 ></TABLE
149 >I should say that the XML structure that pwmd uses is a little more complicated. It really looks like the following internally, but we will use the above format in this tutorial for simplicity:</P
150 ><TABLE
151 BORDER="0"
152 BGCOLOR="#E0E0E0"
153 WIDTH="100%"
154 ><TR
155 ><TD
156 ><PRE
157 CLASS="SCREEN"
158 >&#60;element _name="root"&#62;
159 &#60;element _name="child"&#62;
160 &#60;element _name="last"&#62;
161 Content or CDATA of the "last" element.
162 &#60;/element&#62;
163 &#60;/element&#62;
164 &#60;/element&#62;</PRE
165 ></TD
166 ></TR
167 ></TABLE
169 >Every element created has an element named <SPAN
170 CLASS="emphasis"
172 CLASS="EMPHASIS"
173 >element</I
174 ></SPAN
175 > with an attribute <SPAN
176 CLASS="emphasis"
178 CLASS="EMPHASIS"
179 >_name</I
180 ></SPAN
181 > associated with it. The value of the <SPAN
182 CLASS="emphasis"
184 CLASS="EMPHASIS"
185 >_name</I
186 ></SPAN
187 > attribute is what an element in an element path refers to. It is done this way so that a wider range of characters can be used in an element name while maintaining valid XML. In fact the only restriction of an element name is that it not contain whitespace characters.</P
189 >There is one other difference from your normal XML document in that only the first match of an element is considered for the current element tree depth. When an element of the current depth of an element tree is found, the next element in the element path is searched for beginning at the child node of the found element. From the example above:</P
190 ><TABLE
191 BORDER="0"
192 BGCOLOR="#E0E0E0"
193 WIDTH="100%"
194 ><TR
195 ><TD
196 ><PRE
197 CLASS="SCREEN"
198 >&#60;root&#62;
199 &#60;child&#62;
200 &#60;last&#62;
201 Content or XML CDATA of the "last" element.
202 &#60;/last&#62;
203 &#60;/child&#62;
204 &#60;child&#62;
205 This element will never be reached.
206 &#60;/child&#62;
207 &#60;/root&#62;</PRE
208 ></TD
209 ></TR
210 ></TABLE
212 >The second "&lt;child&gt;" element is never reached because it has the same name as its sibling element &ldquo;above&rdquo; it.</P
213 ></DIV
214 ><DIV
215 CLASS="SECT1"
216 ><HR><H2
217 CLASS="SECT1"
219 NAME="AEN53"
220 >Connecting to PWMD</A
221 ></H2
223 >You will need a <SPAN
224 CLASS="emphasis"
226 CLASS="EMPHASIS"
227 >pwmd</I
228 ></SPAN
229 > client to send commands to the pwmd server. <SPAN
230 CLASS="emphasis"
232 CLASS="EMPHASIS"
233 >libpwmd</I
234 ></SPAN
235 > includes a client named <SPAN
236 CLASS="emphasis"
238 CLASS="EMPHASIS"
239 >pwmc</I
240 ></SPAN
241 >. It is command-line based and there are not any fancy graphics, but it is good for understanding how <SPAN
242 CLASS="emphasis"
244 CLASS="EMPHASIS"
245 >pwmd</I
246 ></SPAN
247 > commands are processed. If you want a more user friendly client that resembles a file manager and has a point and click interface, try QPwmc <A
248 NAME="AEN60"
249 HREF="#FTN.AEN60"
250 ><SPAN
251 CLASS="footnote"
252 >[6]</SPAN
253 ></A
254 > which uses the Qt4 or Qt5 toolkit and is also a full featured client.</P
256 >In this tutorial we will use the <SPAN
257 CLASS="emphasis"
259 CLASS="EMPHASIS"
260 >pwmc</I
261 ></SPAN
262 > client included with libpwmd. <SPAN
263 CLASS="emphasis"
265 CLASS="EMPHASIS"
266 >pwmc</I
267 ></SPAN
268 > has two modes that commands are read from: interactive and stdin. The interactive mode uses the readline library and has command history, while reading from standard input (stdin) makes shell scripting and automation easy. For the examples, we will be connecting to the default local unix domain socket (UDS) that pwmd waits for connections on and use interactive mode. Remote connections are also possible over TLS or an SSH channel but those are not covered here. Read the pwmc(1) manual page for details about how to do that.</P
270 >The example filename we will use is "datafile". It is initially a non-existent file but it will be created once we have saved to it. Now let us connect to the server in interactive mode and open the data file:</P
271 ><TABLE
272 BORDER="0"
273 BGCOLOR="#E0E0E0"
274 WIDTH="100%"
275 ><TR
276 ><TD
277 ><PRE
278 CLASS="SCREEN"
279 >$ pwmc datafile
280 Connected.
281 pwmc:datafile&#62;</PRE
282 ></TD
283 ></TR
284 ></TABLE
286 >The "pwmc&gt;" prompt is a readline prompt that has command history and can also do filename completion when doing a dot command that requires a filename on the local filesystem.</P
287 ></DIV
288 ><DIV
289 CLASS="SECT1"
290 ><HR><H2
291 CLASS="SECT1"
293 NAME="AEN68"
294 >Commands</A
295 ></H2
297 >There are two different types of commands: client commands and protocol commands. The client commands are <SPAN
298 CLASS="emphasis"
300 CLASS="EMPHASIS"
301 >pwmc</I
302 ></SPAN
303 > specific and only available to the <SPAN
304 CLASS="emphasis"
306 CLASS="EMPHASIS"
307 >pwmc</I
308 ></SPAN
309 > client. Protocol commands are commands sent from any client and to the <SPAN
310 CLASS="emphasis"
312 CLASS="EMPHASIS"
313 >pwmd</I
314 ></SPAN
315 > server. All pwmc client commands are prefixed with a dot '.' followed by the command name. Protocol commands are sent without any dot prefix. To see the available pwmc and protocol commands, send the .help or HELP commands:</P
316 ><TABLE
317 BORDER="0"
318 BGCOLOR="#E0E0E0"
319 WIDTH="100%"
320 ><TR
321 ><TD
322 ><PRE
323 CLASS="SCREEN"
324 >pwmc:datafile&#62; .help</PRE
325 ></TD
326 ></TR
327 ></TABLE
329 >or</P
330 ><TABLE
331 BORDER="0"
332 BGCOLOR="#E0E0E0"
333 WIDTH="100%"
334 ><TR
335 ><TD
336 ><PRE
337 CLASS="SCREEN"
338 >pwmc:datafile&#62; help</PRE
339 ></TD
340 ></TR
341 ></TABLE
343 >To store some data in an element path or to create an element path, you will need to know what element path to create. It is up to you how you want your data organized. If for example you will be storing account information it may be good to categorize what the account is for: email, instant messaging, blogging, etc. An application that uses libpwmd may require that a certain element path exists. Refer to that applications documentation to determine what element paths need to be created.</P
345 >In the following example we will setup mail server element paths which can be used for other applications requiring a mail server configuration. First, lets create the hostname element path:</P
346 ><TABLE
347 BORDER="0"
348 BGCOLOR="#E0E0E0"
349 WIDTH="100%"
350 ><TR
351 ><TD
352 ><PRE
353 CLASS="SCREEN"
354 >pwmc:datafile&#62; STORE
355 Press CTRL-D to send the current line. Press twice to end. DATA:</PRE
356 ></TD
357 ></TR
358 ></TABLE
360 >The STORE command is a <SPAN
361 CLASS="emphasis"
363 CLASS="EMPHASIS"
364 >pwmd</I
365 ></SPAN
366 > protocol command. This, and a few other commands, use what is called a <SPAN
367 CLASS="emphasis"
369 CLASS="EMPHASIS"
370 >server inquire</I
371 ></SPAN
372 > to retrieve additional command parameters from the client while other commands require only the command itself with its command arguments. The server inquire will wait for the client to finish sending its' data before completing the command. When responding to a server inquire in pwmc, pwmc will show a message informing you that it is waiting for data to be sent. Enter the element path and its content, then press &lt;CTRL-D&gt; twice to finish sending the data and to let <SPAN
373 CLASS="emphasis"
375 CLASS="EMPHASIS"
376 >pwmd</I
377 ></SPAN
378 > complete the command:</P
379 ><TABLE
380 BORDER="0"
381 BGCOLOR="#E0E0E0"
382 WIDTH="100%"
383 ><TR
384 ><TD
385 ><PRE
386 CLASS="SCREEN"
387 >email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;hostname&#60;TAB&#62;imap.server.com&#60;CTRL-D&#62;&#60;CTRL-D&#62;</PRE
388 ></TD
389 ></TR
390 ></TABLE
392 >Remember that you should replace &lt;TAB&gt; in the examples with a real TAB character. After pressing the first &lt;CTRL-D&gt;, the characters that were entered are sent to <SPAN
393 CLASS="emphasis"
395 CLASS="EMPHASIS"
396 >pwmd</I
397 ></SPAN
398 > and the inquire continues. To terminate the inquire and finish sending data for the command press &lt;CTRL-D&gt; a second time.</P
400 >If you were to have pressed &lt;RETURN&gt; before any &lt;CTRL-D&gt; then the inquired line would have been sent in full including a newline character. Since in this example a newline character in a hostname is not a valid hostname, this is not what we want.</P
402 >We have just created an element path whose XML structure looks like the following:</P
403 ><TABLE
404 BORDER="0"
405 BGCOLOR="#E0E0E0"
406 WIDTH="100%"
407 ><TR
408 ><TD
409 ><PRE
410 CLASS="SCREEN"
411 >&#60;email&#62;
412 &#60;isp&#62;
413 &#60;IMAP&#62;
414 &#60;hostname&#62;imap.server.com&#60;/hostname&#62;
415 &#60;/IMAP&#62;
416 &#60;/isp&#62;
417 &#60;/email&#62;</PRE
418 ></TD
419 ></TR
420 ></TABLE
422 >The GET protocol command returns the value, or content, of the last element of an element path. To retrieve the hostname of the element path we just created, do:</P
423 ><TABLE
424 BORDER="0"
425 BGCOLOR="#E0E0E0"
426 WIDTH="100%"
427 ><TR
428 ><TD
429 ><PRE
430 CLASS="SCREEN"
431 >pwmc:datafile&#62; GET email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;hostname
432 imap.server.com
433 pwmc:datafile&#62;</PRE
434 ></TD
435 ></TR
436 ></TABLE
438 >Let us create the rest of the needed elements:</P
439 ><TABLE
440 BORDER="0"
441 BGCOLOR="#E0E0E0"
442 WIDTH="100%"
443 ><TR
444 ><TD
445 ><PRE
446 CLASS="SCREEN"
447 >pwmc:datafile&#62; STORE
448 email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;port&#60;TAB&#62;993&#60;CTRL-D&#62;&#60;CTRL-D&#62;
450 pwmc:datafile&#62; STORE
451 email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;ssl&#60;TAB&#62;1&#60;CTRL-D&#62;&#60;CTRL-D&#62;
453 pwmc:datafile&#62; STORE
454 email&#60;TAB&#62;isp&#60;TAB&#62;username&#60;TAB&#62;myusername&#60;CTRL-D&#62;&#60;CTRL-D&#62;
456 pwmc:datafile&#62; STORE
457 email&#60;TAB&#62;isp&#60;TAB&#62;password&#60;TAB&#62;mypassword&#60;CTRL-D&#62;&#60;CTRL-D&#62;</PRE
458 ></TD
459 ></TR
460 ></TABLE
462 >Now the element structure for the "email" element looks like this:</P
463 ><TABLE
464 BORDER="0"
465 BGCOLOR="#E0E0E0"
466 WIDTH="100%"
467 ><TR
468 ><TD
469 ><PRE
470 CLASS="SCREEN"
471 >&#60;email&#62;
472 &#60;isp&#62;
473 &#60;IMAP&#62;
474 &#60;hostname&#62;imap.server.com&#60;/hostname&#62;
475 &#60;port&#62;993&#60;/port&#62;
476 &#60;ssl&#62;1&#60;/ssl&#62;
477 &#60;/IMAP&#62;
478 &#60;username&#62;myusername&#60;/username&#62;
479 &#60;password&#62;mypassword&#60;/password&#62;
480 &#60;/isp&#62;
481 &#60;/email&#62;</PRE
482 ></TD
483 ></TR
484 ></TABLE
486 >If you wanted to change your password (after changing it on the mail server, of course) just do as you did when initially creating the password element path. The new content will overwrite the existing content:</P
487 ><TABLE
488 BORDER="0"
489 BGCOLOR="#E0E0E0"
490 WIDTH="100%"
491 ><TR
492 ><TD
493 ><PRE
494 CLASS="SCREEN"
495 >pwmc:datafile&#62; STORE
496 email&#60;TAB&#62;isp&#60;TAB&#62;password&#60;TAB&#62;newpassword&#60;CTRL-D&#62;&#60;CTRL-D&#62;
497 pwmc:datafile&#62;</PRE
498 ></TD
499 ></TR
500 ></TABLE
502 >An application using libpwmd that requires mail server information now has the basic information it needs. It may require more elements and they can be created just as these elements have been. The only thing left to do now is to save the changes:</P
503 ><TABLE
504 BORDER="0"
505 BGCOLOR="#E0E0E0"
506 WIDTH="100%"
507 ><TR
508 ><TD
509 ><PRE
510 CLASS="SCREEN"
511 >pwmc:datafile&#62; &#60;CTRL-D&#62;</PRE
512 ></TD
513 ></TR
514 ></TABLE
516 >After pressing &lt;CTRL-D&gt; a prompt will be shown asking what to do next. Press &ldquo;s&rdquo; to save what we have created. This will generate a new encryption and signing key pair by default. If you would rather use an existing encryption and signing key or use symmetric encryption, you will need to use the .save pwmc command along with the required SAVE protocol command options. The .save command lets libpwmd set some things that may be needed for the current connection such as pinentry settings. Type:</P
517 ><TABLE
518 BORDER="0"
519 BGCOLOR="#E0E0E0"
520 WIDTH="100%"
521 ><TR
522 ><TD
523 ><PRE
524 CLASS="SCREEN"
525 >pwmc:datafile&#62; help save</PRE
526 ></TD
527 ></TR
528 ></TABLE
530 >to see SAVE syntax and options.</P
532 >When the save has completed the encrypted data file has been written to disk and is also stored in pwmd's file cache. A cached document is the same document on disc that is stored in memory. This means that the next time the document is opened a passphrase won't be required until pwmd's cache timer removes it from the cache. By default, the cache timeout for each data file is 600 seconds, or 10 minutes. This setting can be changed in pwmd's configuration and set independently for each file and can also be set to not cache the file at all or to cache it indefinately.</P
533 ></DIV
534 ><DIV
535 CLASS="SECT1"
536 ><HR><H2
537 CLASS="SECT1"
539 NAME="SEC.LINKING-ELEMENTS-0"
540 >Linking elements</A
541 ></H2
543 >One distinguishing feature of pwmd is the ability to share data of one element path with another. If for example your ISP lets you host a blog on their server and you use a blogging client that can use libpwmd for authentication details, you can share authentication information with the email example above when the account details are the same. When element linking is used, this avoids the need to change the content for both the blogging and email password elements.</P
545 >This is done by setting a special &ldquo;_target&rdquo; attribute for an element. It behaves similarly to the HTML &ldquo;target&rdquo; attribute or XML entities or a symbolic link on a filesystem. </P
547 >Let's create an example blogging element path:</P
548 ><TABLE
549 BORDER="0"
550 BGCOLOR="#E0E0E0"
551 WIDTH="100%"
552 ><TR
553 ><TD
554 ><PRE
555 CLASS="SCREEN"
556 >pwmc:datafile&#62; STORE
557 blog&#60;TAB&#62;isp&#60;TAB&#62;hostname&#60;TAB&#62;blog.myisp.com&#60;CTRL-D&#62;&#60;CTRL-D&#62;
559 pwmc:datafile&#62; ATTR SET _target blog&#60;TAB&#62;isp&#60;TAB&#62;username email&#60;TAB&#62;isp&#60;TAB&#62;username
560 pwmc:datafile&#62; ATTR SET _target blog&#60;TAB&#62;isp&#60;TAB&#62;password email&#60;TAB&#62;isp&#60;TAB&#62;password</PRE
561 ></TD
562 ></TR
563 ></TABLE
565 >Now each access of the "blog/isp/username" and "blog/isp/password" element paths, which were created if they did not already exist, will point to "email/isp/username" and "email/isp/password", respectively. To retrieve the value or content of an element that contains a "_target" attribute, just use the GET command as you would for any other element:</P
566 ><TABLE
567 BORDER="0"
568 BGCOLOR="#E0E0E0"
569 WIDTH="100%"
570 ><TR
571 ><TD
572 ><PRE
573 CLASS="SCREEN"
574 >pwmc:datafile&#62; GET blog&#60;TAB&#62;isp&#60;TAB&#62;password
575 mypassword
576 pwmc:datafile&#62;</PRE
577 ></TD
578 ></TR
579 ></TABLE
581 >A "_target" attribute may also refer to another element with a "_target" attribute. Every "_target" attribute will be followed until there are no others to resolve. To get the real element path and resolve all "_target" attributes, use the REALPATH protocol command:</P
582 ><TABLE
583 BORDER="0"
584 BGCOLOR="#E0E0E0"
585 WIDTH="100%"
586 ><TR
587 ><TD
588 ><PRE
589 CLASS="SCREEN"
590 >pwmc:datafile&#62; REALPATH blog&#60;TAB&#62;isp&#60;TAB&#62;password
591 email&#60;TAB&#62;isp&#60;TAB&#62;password
592 pwmc:datafile&#62;</PRE
593 ></TD
594 ></TR
595 ></TABLE
597 >Using the LIST command is useful to show the element structure of a document:</P
598 ><TABLE
599 BORDER="0"
600 BGCOLOR="#E0E0E0"
601 WIDTH="100%"
602 ><TR
603 ><TD
604 ><PRE
605 CLASS="SCREEN"
606 >pwmc:datafile&#62; LIST
607 email
608 blog
609 pwmc:datafile&#62; LIST email
610 email
611 email&#60;TAB&#62;isp
612 email&#60;TAB&#62;isp&#60;TAB&#62;username
613 email&#60;TAB&#62;isp&#60;TAB&#62;password
614 email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;hostname
615 email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;port
616 email&#60;TAB&#62;isp&#60;TAB&#62;IMAP&#60;TAB&#62;ssl
617 pwmc:datafile&#62; LIST blog
618 blog
619 blog&#60;TAB&#62;isp
620 blog&#60;TAB&#62;isp&#60;TAB&#62;hostname
621 blog&#60;TAB&#62;isp&#60;TAB&#62;username
622 blog&#60;TAB&#62;isp&#60;TAB&#62;password
623 pwmc:datafile&#62;</PRE
624 ></TD
625 ></TR
626 ></TABLE
627 ></DIV
628 ></DIV
629 ><H3
630 CLASS="FOOTNOTES"
631 >Notes</H3
632 ><TABLE
633 BORDER="0"
634 CLASS="FOOTNOTES"
635 WIDTH="100%"
636 ><TR
637 ><TD
638 ALIGN="LEFT"
639 VALIGN="TOP"
640 WIDTH="5%"
642 NAME="FTN.AEN6"
643 HREF="#AEN6"
644 ><SPAN
645 CLASS="footnote"
646 >[1]</SPAN
647 ></A
648 ></TD
649 ><TD
650 ALIGN="LEFT"
651 VALIGN="TOP"
652 WIDTH="95%"
653 ><FONT
654 COLOR="RED"
655 >bjk@luxsci.net</FONT
656 ></TD
657 ></TR
658 ><TR
659 ><TD
660 ALIGN="LEFT"
661 VALIGN="TOP"
662 WIDTH="5%"
664 NAME="FTN.AEN12"
665 HREF="#AEN12"
666 ><SPAN
667 CLASS="footnote"
668 >[2]</SPAN
669 ></A
670 ></TD
671 ><TD
672 ALIGN="LEFT"
673 VALIGN="TOP"
674 WIDTH="95%"
675 ><TR
676 ><TD
677 ALIGN="LEFT"
678 VALIGN="TOP"
679 WIDTH="5%"
681 NAME="FTN.AEN13"
682 HREF="#AEN13"
683 ><SPAN
684 CLASS="footnote"
685 >[3]</SPAN
686 ></A
687 ></TD
688 ><TD
689 ALIGN="LEFT"
690 VALIGN="TOP"
691 WIDTH="95%"
692 >https://gitlab.com/bjk/libpwmd/wikis</TD
693 ></TR
694 ></TD
695 ></TR
696 ><TR
697 ><TD
698 ALIGN="LEFT"
699 VALIGN="TOP"
700 WIDTH="5%"
702 NAME="FTN.AEN13"
703 HREF="#AEN13"
704 ><SPAN
705 CLASS="footnote"
706 >[3]</SPAN
707 ></A
708 ></TD
709 ><TD
710 ALIGN="LEFT"
711 VALIGN="TOP"
712 WIDTH="95%"
713 >https://gitlab.com/bjk/libpwmd/wikis</TD
714 ></TR
715 ><TR
716 ><TD
717 ALIGN="LEFT"
718 VALIGN="TOP"
719 WIDTH="5%"
721 NAME="FTN.AEN15"
722 HREF="#AEN15"
723 ><SPAN
724 CLASS="footnote"
725 >[4]</SPAN
726 ></A
727 ></TD
728 ><TD
729 ALIGN="LEFT"
730 VALIGN="TOP"
731 WIDTH="95%"
732 ><TR
733 ><TD
734 ALIGN="LEFT"
735 VALIGN="TOP"
736 WIDTH="5%"
738 NAME="FTN.AEN16"
739 HREF="#AEN16"
740 ><SPAN
741 CLASS="footnote"
742 >[5]</SPAN
743 ></A
744 ></TD
745 ><TD
746 ALIGN="LEFT"
747 VALIGN="TOP"
748 WIDTH="95%"
749 >https://gitlab.com/bjk/pwmd/wikis</TD
750 ></TR
751 ></TD
752 ></TR
753 ><TR
754 ><TD
755 ALIGN="LEFT"
756 VALIGN="TOP"
757 WIDTH="5%"
759 NAME="FTN.AEN16"
760 HREF="#AEN16"
761 ><SPAN
762 CLASS="footnote"
763 >[5]</SPAN
764 ></A
765 ></TD
766 ><TD
767 ALIGN="LEFT"
768 VALIGN="TOP"
769 WIDTH="95%"
770 >https://gitlab.com/bjk/pwmd/wikis</TD
771 ></TR
772 ><TR
773 ><TD
774 ALIGN="LEFT"
775 VALIGN="TOP"
776 WIDTH="5%"
778 NAME="FTN.AEN60"
779 HREF="#AEN60"
780 ><SPAN
781 CLASS="footnote"
782 >[6]</SPAN
783 ></A
784 ></TD
785 ><TD
786 ALIGN="LEFT"
787 VALIGN="TOP"
788 WIDTH="95%"
789 ><TR
790 ><TD
791 ALIGN="LEFT"
792 VALIGN="TOP"
793 WIDTH="5%"
795 NAME="FTN.AEN61"
796 HREF="#AEN61"
797 ><SPAN
798 CLASS="footnote"
799 >[7]</SPAN
800 ></A
801 ></TD
802 ><TD
803 ALIGN="LEFT"
804 VALIGN="TOP"
805 WIDTH="95%"
806 >https://gitlab.com/bjk/qpwmc/wikis</TD
807 ></TR
808 ></TD
809 ></TR
810 ><TR
811 ><TD
812 ALIGN="LEFT"
813 VALIGN="TOP"
814 WIDTH="5%"
816 NAME="FTN.AEN61"
817 HREF="#AEN61"
818 ><SPAN
819 CLASS="footnote"
820 >[7]</SPAN
821 ></A
822 ></TD
823 ><TD
824 ALIGN="LEFT"
825 VALIGN="TOP"
826 WIDTH="95%"
827 >https://gitlab.com/bjk/qpwmc/wikis</TD
828 ></TR
829 ></TABLE
830 ></BODY
831 ></HTML