File: fb.html

package info (click to toggle)
libapache2-mod-rivet 3.2.2-1
  • links: PTS
  • area: main
  • in suites: bookworm
  • size: 6,296 kB
  • sloc: xml: 8,554; tcl: 7,568; ansic: 7,094; sh: 5,017; makefile: 195; sql: 91; lisp: 78
file content (263 lines) | stat: -rw-r--r-- 19,930 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>FormBroker</title><link rel="stylesheet" type="text/css" href="rivet.css"><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot"><link rel="home" href="index.html" title="Apache Rivet 3.2"><link rel="up" href="formbroker.html" title="The Form Broker"><link rel="prev" href="formbroker.html" title="The Form Broker"><link rel="next" href="help.html" title="Resources - How to Get Help"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">FormBroker</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="formbroker.html"><img src="images/prev.png" alt="Prev"></a> </td><th width="60%" align="center">The Form Broker</th><td width="20%" align="right"> <a accesskey="n" href="help.html"><img src="images/next.png" alt="Next"></a></td></tr></table></div><div class="refentry"><a name="fb"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>FormBroker — 
               Form broker object creator
            </p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis" style="width:80%"><div style="border: 1px solid #282; margin:1ex ; padding:.4ex; padding-left: 0.8ex;   word-spacing:1ex "><span style="font-weight:bold ; font-family:monospace">::FormBroker</span>   <span style="font-family:monospace; font-weight: bold;">create</span>  ?<span style="font-family:monospace; font-weight: bold;">-quoting quoting_procedure</span>? ?<span style="font-family:monospace; font-weight: bold;">variable1 descriptor</span>? ?<span style="font-family:monospace; font-weight: bold;">variable2 descriptor</span>? ?<span style="font-family:monospace; font-weight: bold;">...</span>?</div></div></div><div class="refsect1"><a name="idm4273"></a><h2>Description</h2><p style="width:90%">
               The command returns a reference to a form broker object by creating
               a representation of the form data using the list of variable 
               descriptors passed to method <span style="font-family:monospace"><span class="command"><strong>create</strong></span></span>. Each descriptor
               is a list of parameter or parameter-value pairs that must
               begin with the <span style="font-family:monospace"><span class="command"><strong>{variable_name variable_type}</strong></span></span> pair as only
               requirement. A formbroker object provide native support for
               integer, unsigned integer, string, boolean and email data types.
               The programmer can defined new data types and provide in the descriptor a
               reference to a validation procedure for that type.
            </p><p style="width:90%">
               The optional  ?<span style="font-family:monospace; font-weight: bold;">-quoting quoting_procedure</span>? switch defines an
               external procedure to quote or reformat the response values. 
               The quoting procedure is any procedure accepting a single string argument
               and returning its quoted value. A most basic example is the FormBroker default quoting procedure
            </p><pre class="programlisting">proc force_quote {str} {
    return "'$str'"
}</pre><p style="width:90%">
               Other parameters of a descriptors are
            </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>type</strong></span></span>: the data type of the variable</li><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>bounds</strong></span></span>: limits of a variable value. The
                  meanining of bounds depends on the variable type. For an integer is the
                  maximum absolute value for that variable (for an unsigned the lower 
                  limit is invariably 0), for a string is the maximum length of the string. The
                  parameter bounds has no effect on an email data type
               </li><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>constrain</strong></span></span>: boolean value telling the variable has to be
               forced to fulfill the constrain imposed by <span style="font-family:monospace"><span class="command"><strong>bounds</strong></span></span>. This field
               is bidirectional in that it can be used by the validator to force the
               variable value rewriting</li><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>validator</strong></span></span>: name of the specialized validator for this variable</li><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>default</strong></span></span>: default value of the variable if not set in a response array. 
               When a variable is given a default value the form validation will not fail on the fact that
               this variable may be missing from the form response array</li><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>quote</strong></span></span>: the variable value has to be quoted when written back in
               the response array</li><li class="listitem"><span style="font-family:monospace"><span class="command"><strong>validator</strong></span></span>: name of the validator procedure. The procedure
                  can be any Tcl procedure accepting as argument the name of a dictionary
                  holding the variable	internal representation. 
               </li></ul></div><p style="width:90%">
               An example of a form accepting four variable, one for each native type of a form broker object
            </p><pre class="programlisting"> % set fbroker [::FormBroker create {var1 integer} {var2 unsigned} {var3 string} {var4 integer bounds {-10 100}}]
::FormBroker::form0</pre></div><div class="refsect1"><a name="idm4300"></a><h2>Form broker object methods</h2><p style="width:90%">
               The central method of a form broker object is <span style="font-family:monospace"><span class="command"><strong>validate</strong></span></span> 
            </p><div class="variablelist"><dl class="variablelist"><dt></dt><dd><div style="padding:4 ; margin-top:3 ; margin-bottom:3 ; width:75%"><div class="cmdsynopsis" style="width:80%"><div style="border: 1px solid #282; margin:1ex ; padding:.4ex; padding-left: 0.8ex;   word-spacing:1ex "> <span style="font-family:monospace; font-weight: bold;"><em class="replaceable"><code>formBroker_object</code></em></span>   <span style="font-family:monospace; font-weight: bold;">validate</span>  ?<span style="font-family:monospace; font-weight: bold;">-forcequote</span>?  <span style="font-family:monospace; font-weight: bold;">response</span>  ?<span style="font-family:monospace; font-weight: bold;"><em class="replaceable"><code>response copy</code></em></span>?</div></div><div style="margin-bottom:1.5ex ; padding .5ex">
                        The method <span style="font-family:monospace"><span class="command"><strong>validate</strong></span></span> takes as argument the name of an array of variables
                        in the way this is produced by command <a class="xref" href="load_response.html" title="load_response">load_response</a>
                        returning a form response. The optional argument <em class="replaceable"><code>-forcequote</code></em> causes the
                        variable values to be rewritten and quoted. If the optional argument <em class="replaceable"><code>response copy</code></em>
                        is present the validated response is copied in this array instead of the input   <span style="font-family:monospace; font-weight: bold;">response</span> 
                        array.
                     </div><div style="margin-bottom:1.5ex ; padding .5ex">
                        If the form data have been validated the method <span style="font-family:monospace"><span class="command"><strong>validate</strong></span></span> returns <span class="emphasis"><em>true</em></span>
                     </div><div style="margin-bottom:1.5ex ; padding .5ex">
                        Example of form data validation (assuming ::rivet::load_response is loading the array <span class="emphasis"><em>response</em></span>
                        with data taken from a form non displayed here)
                     </div><pre class="programlisting">% package require formbroker
% set fbroker [::FormBroker create {var1 integer} {var2 unsigned} {var3 string} {var4 integer bounds {-10 100}}]
::FormBroker::form0

% ::rivet::load_response
% parray response
response(var1) = -10
response(var2) = 20
response(var3) = a string
response(var4) = 50

# let's keep a copy of the response

% array set response_copy [array get response]

# form data validation

% $fbroker validate response
true
% $fbroker validate -forcequote response
% parray response
response(var1) = '-10'
response(var2) = '20'
response(var3) = 'a string'
response(var4) = '50'

# restore response original value

% array set response [array get response_copy]
% $fbroker validate -forcequote response response_copy
true
% parray response
response(var1) = -10
response(var2) = 20
response(var3) = a string
response(var4) = 50
% parray response_copy 
response_copy(var1) = '-10'
response_copy(var2) = '20'
response_copy(var3) = 'a string'
response_copy(var4) = '50'

# a form object has to be destroyed if it's not needed anymore

% $fbroker destroy</pre></div></dd><dt></dt><dd><div style="padding:4 ; margin-top:3 ; margin-bottom:3 ; width:75%"><div class="cmdsynopsis" style="width:80%"><div style="border: 1px solid #282; margin:1ex ; padding:.4ex; padding-left: 0.8ex;   word-spacing:1ex "> <span style="font-family:monospace; font-weight: bold;"><em class="replaceable"><code>formBroker_object</code></em></span>   <span style="font-family:monospace; font-weight: bold;">failing</span> </div></div><div style="margin-bottom:1.5ex ; padding .5ex">
                        In case the validation fails method <span style="font-family:monospace"><span class="command"><strong>failing</strong></span></span> returns a list
                        of <span class="emphasis"><em>variable_name - error_condition</em></span> pairs for each 
                        variable whose value failed to validate and was impossible to fix. This list
                        is suitable to populate an array or used directly as a dictionary
                     </div><pre class="programlisting">% package require formbroker
1.0
% set fbroker [::FormBroker create {var1 integer} \
         {var2 unsigned} \
         {var3 string} \
         {var4 integer}]
::FormBroker::form0
% ::rivet::load_response

# let's suppose we have an incomplete response
% parray response
response(var1) = '100'
response(var2) = '20'
response(var3) = 'a string'
% $fbroker validate response
false
$fbroker failing
var4 MISSING_VAR

# this can be prevented by assigning a variable a default value

% set fbroker [::FormBroker create {var1 integer} \
                                   {var2 unsigned} \
                                   {var3 string} \
                                   {var4 integer default 0}]						
::FormBroker::form1
% $fbroker validate response
true
% parray response
response(var1) = 100
response(var2) = 20
response(var3) = a string
response(var4) = 0

% set fbroker [::FormBroker create {var1 integer} \
                                   {var2 unsigned} \
                                   {var3 string length 10 constrain} \
                                   {var4 integer bounds {-10 100}}]
::FormBroker::form2
% ::rivet::load_response

# this time the response has invalid data

% parray response
response(var1) = 'aaaaa'
response(var2) = '-20'
response(var3) = 'a longer string that breaks the 10 chars max limit imposed'
response(var4) = '150'
% $fbroker validate response
false
% $fbroker failing
var1 NOT_INTEGER var2 FB_OUT_OF_BOUNDS var4 FB_OUT_OF_BOUNDS</pre><div style="margin-bottom:1.5ex ; padding .5ex">
                        Notice that even though $response(var3) exceeds the 10 characters max length imposed to variable <span class="emphasis"><em>var3</em></span>
                        this variable is not in the list returned by <span style="font-family:monospace"><span class="command"><strong>failing</strong></span></span> because
                        the 'constrain' attribute forced the truncation of the string. 
                        In fact this applies also to the integer and unsigned values 
                     </div><pre class="programlisting">% package require formbroker
% set fbroker [::FormBroker create {var1 integer bounds 10 constrain} \
                                   {var2 unsigned constrain} \
                                   {var3 string length 10 constrain} \
                                   {var4 integer bounds {-10 100} constrain}]
::FormBroker::form0
% ::rivet::load_response
% parray response
response(var1) = abcdef
response(var2) = -20
response(var3) = a longer string that breaks the 10 chars max limit imposed
response(var4) = 150
% $fbroker validate response response_copy
false
% $fbroker failing
var1 NOT_INTEGER
% parray response_copy 
response_copy(var2) = 0
response_copy(var3) = a longer s
response_copy(var4) = 100</pre><div style="margin-bottom:1.5ex ; padding .5ex">
                     The variable <span class="emphasis"><em>var1</em></span> could not be constrained because the input
                     value "abcdef" is fundamentally incompatible
                  </div></div></dd><dt></dt><dd><div style="padding:4 ; margin-top:3 ; margin-bottom:3 ; width:75%"><div class="cmdsynopsis" style="width:80%"><div style="border: 1px solid #282; margin:1ex ; padding:.4ex; padding-left: 0.8ex;   word-spacing:1ex "> <span style="font-family:monospace; font-weight: bold;"><em class="replaceable"><code>formBroker_object</code></em></span>   <span style="font-family:monospace; font-weight: bold;">response</span>  ?<span style="font-family:monospace; font-weight: bold;">response_array_name</span>?</div></div><div style="margin-bottom:1.5ex ; padding .5ex">
                        The <span style="font-family:monospace"><span class="command"><strong>response</strong></span></span> method fills 
                        the array whose name is passed as optional argument
                        with the last response processing. If this argument is omitted
                        the method creates an array named <span class="emphasis"><em>response</em></span>.
                     </div><div style="margin-bottom:1.5ex ; padding .5ex">
                        This method can be called also if no form response validation has taken place: it
                        simply populates the array with the default values assigned to the form variables. As
                        such is a way to create form default arrays to initialize forms created with
                        the <a class="xref" href="form_package.html" title="form">form</a> package.
                     </div><pre class="programlisting">
set fbroker [::FormBroker create {var1 integer default 0} \
                                 {var2 unsigned default 1} \
                                 {var3 string} \
                                 {var4 integer default 0}]
% $fbroker response a
% parray a
a(var1) = 0
a(var2) = 1
a(var4) = 0</pre></div></dd><dt></dt><dd><div style="padding:4 ; margin-top:3 ; margin-bottom:3 ; width:75%"><div class="cmdsynopsis" style="width:80%"><div style="border: 1px solid #282; margin:1ex ; padding:.4ex; padding-left: 0.8ex;   word-spacing:1ex "> <span style="font-family:monospace; font-weight: bold;"><em class="replaceable"><code>formBroker_object</code></em></span>   <span style="font-family:monospace; font-weight: bold;">reset</span> </div></div><div style="margin-bottom:1.5ex ; padding .5ex">
                     	The method resets the object to its initial defaults
                     </div></div></dd></dl></div></div><div class="refsect1"><a name="idm4365"></a><h2>Writing a custom variable validator</h2><p style="width:90%">
            	The form broker is by no means restricted to work only with its native
            	data types: you may define your own form variable types and have
            	them validated with their own variable validator. 
            </p><p style="width:90%">
            	A validator is a function accepting a dictionary as single argument and
            	must return either FB_OK, if the variable value is valid, 
            	or any other used defined error code. The dictionary argument stores
            	the variable descriptor used internally by the form broker. 
				</p><p style="width:90%">
            	Suppose you're writing a form text entry that demands as input a network 
            	interface MAC address. 
            	A MAC address is represented by 6 hexadecimal octets separated by 
            	either a <span class="quote">“<span class="quote">-</span>”</span> (Windows convention) or <span class="quote">“<span class="quote">:</span>”</span> 
            	(Unix, Mac convention). The procedure <span style="font-family:monospace"><span class="command"><strong>validate_mac</strong></span></span>
            	checks the validity of the mac address and if validation is successful it
            	transforms its representation into the Unix form. 
            	By setting the key <span class="quote">“<span class="quote">constrain</span>”</span>
            	in the dictionary <span class="emphasis"><em>mac_address_d</em></span> the procedure
            	is telling the form broker to copy the transformed value back
            	in the input response array
            </p><pre class="programlisting">proc validate_mac {_mac_address_d} {
    upvar $_mac_address_d mac_address_d

    dict with mac_address_d {
		  
        set var [string trim $var]
        if {[regexp {^[[:xdigit:]]{2}([:-][[:xdigit:]]{2}){5}$} $var]} {

            set var [string tolower $var]

            # we normalize the mac address to the Unix form.
            # The dash '-' characters in the windows representation 
            # are replaced by columns ':'

            set var [regsub -all -- {-} $var :]

            # the 'constrain' field is bidirectional:
            # it tells the validator to curb/change the value
            # within bonds/forms/representation. By setting it the
            # validator tells the FormBroker to copy the value
            # back in the response array

            set constrain 1
            return FB_OK

         } else {

            return FB_WRONG_MAC

         }

    }

}
% set fbroker [::FormBroker create {mac mac_address validator validate_mac}]
% ::rivet::load_response r
% parray r
r(mac) = 00-A1-B2-C3-D4-C5
% $fbroker validate r
true
% parray r
r(mac) = 00:a1:b2:c3:d4:c5</pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="formbroker.html"><img src="images/prev.png" alt="Prev"></a> </td><td width="20%" align="center"><a accesskey="u" href="formbroker.html"><img src="images/up.png" alt="Up"></a></td><td width="40%" align="right"> <a accesskey="n" href="help.html"><img src="images/next.png" alt="Next"></a></td></tr><tr><td width="40%" align="left" valign="top">The Form Broker </td><td width="20%" align="center"><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a></td><td width="40%" align="right" valign="top"> Resources - How to Get Help</td></tr></table></div></body></html>