blib/lib/XAO/DO/Web/FilloutForm.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 54 | 433 | 12.4 |
branch | 15 | 332 | 4.5 |
condition | 4 | 270 | 1.4 |
subroutine | 7 | 27 | 25.9 |
pod | 11 | 17 | 64.7 |
total | 91 | 1079 | 8.4 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | =head1 NAME | ||||||
2 | |||||||
3 | XAO::DO::Web::FilloutForm - support for HTML forms | ||||||
4 | |||||||
5 | =head1 DESCRIPTION | ||||||
6 | |||||||
7 | Fill out form object. Helps to create fill-out forms for registration | ||||||
8 | and so on. Checks that parameters are Ok and then displays either form | ||||||
9 | or thanks. | ||||||
10 | |||||||
11 | Must be overriden with something which will put 'fields' parameter | ||||||
12 | into $self. Format is as array of hash references reference of the | ||||||
13 | following structure: | ||||||
14 | |||||||
15 | [ { name => field name, | ||||||
16 | required => 0 || 1, | ||||||
17 | style => selection || text || textarea || email || phone || | ||||||
18 | integer || dollars || real, | ||||||
19 | maxlength => maximum length, | ||||||
20 | minlength => minimum length, | ||||||
21 | param => name of parameter for form substitution, | ||||||
22 | text => description of parameter, | ||||||
23 | }, | ||||||
24 | { ... } | ||||||
25 | ] | ||||||
26 | |||||||
27 | If you do not care in what order fields are checked you can also | ||||||
28 | supply 'fields' as a hash reference: | ||||||
29 | |||||||
30 | { name => { | ||||||
31 | required => 0 || 1, | ||||||
32 | style => selection || text || textarea || email || phone || | ||||||
33 | integer || dollars || real, | ||||||
34 | maxlength => maximum length, | ||||||
35 | minlength => minimum length, | ||||||
36 | param => name of parameter for form substitution, | ||||||
37 | text => description of parameter, | ||||||
38 | }, | ||||||
39 | name1 => { ... } | ||||||
40 | } | ||||||
41 | |||||||
42 | When form filled out "form_ok" method is called, which must be | ||||||
43 | overridden in inherited object to do something good with | ||||||
44 | results. Alternatively reference to subroutine can be given through | ||||||
45 | 'setup' method. This is suitable for using FilloutForm object without | ||||||
46 | overriding it. | ||||||
47 | |||||||
48 | Displays form with PARAM.VALUE set to value, PARAM.NAME - to name, | ||||||
49 | PARAM.TEXT - to text, PARAM.REQUIRED to the 0/1 required flag, and | ||||||
50 | PARAM.HTML - to piece of HTML code if applicable (Country selection for | ||||||
51 | example). | ||||||
52 | |||||||
53 | =head1 METHODS | ||||||
54 | |||||||
55 | =over | ||||||
56 | |||||||
57 | =cut | ||||||
58 | |||||||
59 | ############################################################################### | ||||||
60 | package XAO::DO::Web::FilloutForm; | ||||||
61 | 1 | 1 | 870 | use strict; | |||
1 | 3 | ||||||
1 | 35 | ||||||
62 | 1 | 1 | 5 | use XAO::Utils qw(:args :debug :html); | |||
1 | 2 | ||||||
1 | 252 | ||||||
63 | 1 | 1 | 9 | use XAO::Errors qw(XAO::DO::Web::FilloutForm); | |||
1 | 2 | ||||||
1 | 7 | ||||||
64 | 1 | 1 | 398 | use base XAO::Objects->load(objname => 'Web::Page'); | |||
1 | 2 | ||||||
1 | 5 | ||||||
65 | |||||||
66 | our $VERSION='2.029'; | ||||||
67 | |||||||
68 | sub setup ($%); | ||||||
69 | sub field_desc ($$;$); | ||||||
70 | sub field_names ($); | ||||||
71 | sub display ($;%); | ||||||
72 | sub form_ok ($%); | ||||||
73 | sub form_phase ($); | ||||||
74 | sub check_form ($%); | ||||||
75 | sub pre_check_form ($%); | ||||||
76 | sub countries_list (); | ||||||
77 | sub us_continental_states_list (); | ||||||
78 | sub us_states_list (); | ||||||
79 | sub cc_list ($); | ||||||
80 | sub cc_validate ($%); | ||||||
81 | sub calculate_year ($$); | ||||||
82 | |||||||
83 | ############################################################################### | ||||||
84 | |||||||
85 | =item new (%) | ||||||
86 | |||||||
87 | Overrided new method for those who prefer to use inheritance style. | ||||||
88 | |||||||
89 | =cut | ||||||
90 | |||||||
91 | sub new ($%) { | ||||||
92 | 1 | 1 | 1 | 25 | my $proto=shift; | ||
93 | 1 | 33 | 7 | my $class=ref($proto) || $proto; | |||
94 | 1 | 6 | my $args=get_args(\@_); | ||||
95 | 1 | 23 | my $self=$proto->SUPER::new($args); | ||||
96 | |||||||
97 | # Setting up fields if required | ||||||
98 | # | ||||||
99 | $self->setup_fields(fields => $args->{'fields'}, | ||||||
100 | 1 | 50 | 36 | values => $args->{'values'}) if $args->{'fields'}; | |||
101 | |||||||
102 | # Done | ||||||
103 | # | ||||||
104 | 1 | 3 | $self; | ||||
105 | } | ||||||
106 | |||||||
107 | |||||||
108 | ############################################################################### | ||||||
109 | |||||||
110 | # Setting object up for use as embedded form checker from other | ||||||
111 | # non-derived objects. | ||||||
112 | # | ||||||
113 | # Arguments are: | ||||||
114 | # fields => fields descriptions | ||||||
115 | # values => values for fields, unless this is set all values | ||||||
116 | # are cleaned | ||||||
117 | # extra_data => reference to any data, subroutines will then be | ||||||
118 | # able to access it. | ||||||
119 | # form_ok => form_ok subroutine reference (mandatory) | ||||||
120 | # pre_check_form => pre_check_form subroutine reference | ||||||
121 | # check_form => check_form subroutine reference | ||||||
122 | # submit_name => name of the submit button | ||||||
123 | # keep_form => display form template even when the form is complete | ||||||
124 | # | ||||||
125 | # Call to this subroutine is not required from derived objects, use | ||||||
126 | # method overriding instead when possible! | ||||||
127 | # | ||||||
128 | |||||||
129 | sub setup ($%) { | ||||||
130 | 0 | 0 | 0 | 0 | my $self=shift; | ||
131 | 0 | 0 | my $args=get_args(\@_); | ||||
132 | |||||||
133 | # Fields and values | ||||||
134 | # | ||||||
135 | $self->setup_fields( | ||||||
136 | fields => $args->{'fields'}, | ||||||
137 | 0 | 0 | values => $args->{'values'}, | ||||
138 | ); | ||||||
139 | |||||||
140 | # Handlers and special data: | ||||||
141 | # extra_data - passed to handlers as is. | ||||||
142 | # submit_name - name of submit button for pre-filled forms (change form). | ||||||
143 | # dont_sanitize - don't remove <> from CGI input | ||||||
144 | # | ||||||
145 | 0 | 0 | my @names=qw(extra_data submit_name form_ok pre_check_form check_form keep_form dont_sanitize); | ||||
146 | 0 | 0 | @{$self}{@names}=@{$args}{@names}; | ||||
0 | 0 | ||||||
0 | 0 | ||||||
147 | |||||||
148 | 0 | 0 | 0 | my $values=$args->{'values'} || {}; | |||
149 | 0 | 0 | foreach my $fdata (@{$self->{'fields'}}) { | ||||
0 | 0 | ||||||
150 | 0 | 0 | $fdata->{'value'}=$values->{$fdata->{'name'}}; | ||||
151 | } | ||||||
152 | } | ||||||
153 | |||||||
154 | ############################################################################### | ||||||
155 | |||||||
156 | =item setup_fields (%) | ||||||
157 | |||||||
158 | Copying fields descriptions. We copy entire structure here because it | ||||||
159 | could be persistent and we do not want original data to be modified. | ||||||
160 | |||||||
161 | =cut | ||||||
162 | |||||||
163 | sub setup_fields ($%) { | ||||||
164 | 0 | 0 | 1 | 0 | my $self=shift; | ||
165 | 0 | 0 | my $args=get_args(\@_); | ||||
166 | 0 | 0 | my $fields=$args->{'fields'}; | ||||
167 | 0 | 0 | 0 | 0 | return unless $fields && ref($fields); | ||
168 | |||||||
169 | 0 | 0 | my $values=$args->{'values'}; | ||||
170 | 0 | 0 | my @copy; | ||||
171 | 0 | 0 | 0 | foreach my $fdata (ref($fields) eq 'ARRAY' ? @{$fields} | |||
0 | 0 | ||||||
172 | 0 | 0 | : keys %{$fields}) { | ||||
173 | 0 | 0 | my $name; | ||||
174 | 0 | 0 | 0 | if(! ref($fdata)) { | |||
175 | 0 | 0 | $name=$fdata; | ||||
176 | 0 | 0 | $fdata=$fields->{$name}; | ||||
177 | 0 | 0 | $fdata->{'name'}=$name; | ||||
178 | } | ||||||
179 | else { | ||||||
180 | 0 | 0 | $name=$fdata->{'name'}; | ||||
181 | } | ||||||
182 | |||||||
183 | 0 | 0 | my %cd; | ||||
184 | 0 | 0 | @cd{keys %{$fdata}}=values %{$fdata}; | ||||
0 | 0 | ||||||
0 | 0 | ||||||
185 | 0 | 0 | 0 | 0 | $cd{'value'}=$values->{$name} if $values && $values->{$name}; | ||
186 | 0 | 0 | push(@copy,\%cd); | ||||
187 | } | ||||||
188 | |||||||
189 | 0 | 0 | $self->{'fields'}=\@copy; | ||||
190 | } | ||||||
191 | |||||||
192 | ############################################################################### | ||||||
193 | |||||||
194 | =item display (%) | ||||||
195 | |||||||
196 | Displaying the form. | ||||||
197 | |||||||
198 | =cut | ||||||
199 | |||||||
200 | sub display ($;%) { | ||||||
201 | 0 | 0 | 1 | 0 | my $self=shift; | ||
202 | 0 | 0 | my $args=get_args(\@_); | ||||
203 | 0 | 0 | my $cgi=$self->cgi; | ||||
204 | 0 | 0 | my $fields=$self->{'fields'}; | ||||
205 | 0 | 0 | 0 | $fields || throw XAO::E::DO::Web::FilloutForm | |||
206 | "display - has not set fields for FilloutForm"; | ||||||
207 | 0 | 0 | my $phase=$self->{'phase'}=$args->{'phase'}; | ||||
208 | 0 | 0 | 0 | $self->{'submit_name'}=$args->{'submit_name'} if $args->{'submit_name'}; | |||
209 | |||||||
210 | # Checking the type of fields argument we have - hash or | ||||||
211 | # array? Converting to array if it is a hash. | ||||||
212 | # | ||||||
213 | 0 | 0 | 0 | if(ref($fields) eq 'HASH') { | |||
214 | 0 | 0 | my @newf; | ||||
215 | 0 | 0 | foreach my $name (keys %{$fields}) { | ||||
0 | 0 | ||||||
216 | 0 | 0 | $fields->{$name}->{'name'}=$name; | ||||
217 | 0 | 0 | push @newf,$fields->{$name}; | ||||
218 | } | ||||||
219 | 0 | 0 | $self->{'fields'}=$fields=\@newf; | ||||
220 | } | ||||||
221 | |||||||
222 | # Pre-checking form with external overridable function. | ||||||
223 | # | ||||||
224 | 0 | 0 | $self->pre_check_form($args); | ||||
225 | |||||||
226 | # Displayable object | ||||||
227 | # | ||||||
228 | 0 | 0 | my $obj=$self->object; | ||||
229 | |||||||
230 | # Special parameter named 'submit_name' contains submit button name | ||||||
231 | # and used for pre-filled forms - these forms usually already have | ||||||
232 | # valid data and we need some way to know when the form was really | ||||||
233 | # checked and corrected by user. | ||||||
234 | # | ||||||
235 | 0 | 0 | my $have_cgivalues=0; | ||||
236 | 0 | 0 | my $have_submit=1; | ||||
237 | 0 | 0 | 0 | if($self->{'submit_name'}) { | |||
238 | $have_submit=($cgi->param($self->{'submit_name'}) || | ||||||
239 | $cgi->param($self->{'submit_name'}.'.x') || | ||||||
240 | 0 | 0 | 0 | 0 | $cgi->param($self->{'submit_name'}.'.y') | ||
241 | ) ? 1 : 0; | ||||||
242 | 0 | 0 | $have_cgivalues=$have_submit; | ||||
243 | } | ||||||
244 | |||||||
245 | # First checking all parameters and collecting mistakes into errstr. | ||||||
246 | # | ||||||
247 | # Also creating hash with parameters for form diplaying while we are | ||||||
248 | # going through fields anyway. | ||||||
249 | # | ||||||
250 | 0 | 0 | my $errstr; | ||||
251 | my %formparams; | ||||||
252 | |||||||
253 | 0 | 0 | 0 | my $dont_sanitize=$self->{'dont_sanitize'} || $args->{'dont_sanitize'}; | |||
254 | |||||||
255 | 0 | 0 | foreach my $fdata (@{$fields}) { | ||||
0 | 0 | ||||||
256 | 0 | 0 | my $name=$fdata->{'name'}; | ||||
257 | 0 | 0 | 0 | my $param=$fdata->{'param'} || uc($name); | |||
258 | |||||||
259 | 0 | 0 | my $cgivalue=$cgi->param($name); | ||||
260 | 0 | 0 | 0 | $have_cgivalues++ if defined($cgivalue); | |||
261 | |||||||
262 | # Unless we have a 'dont_sanitize' argument we remove angle | ||||||
263 | # brackets to prevent XSS attacks. | ||||||
264 | # | ||||||
265 | 0 | 0 | 0 | 0 | if(defined $cgivalue && !$dont_sanitize) { | ||
266 | 0 | 0 | $cgivalue=~s/[<>]/ /sg; | ||||
267 | } | ||||||
268 | |||||||
269 | # Checking form phase for multi-phased forms if required. | ||||||
270 | # | ||||||
271 | 0 | 0 | 0 | 0 | next if defined($fdata->{'phase'}) && $phase<$fdata->{'phase'}; | ||
272 | |||||||
273 | 0 | 0 | my $value=$fdata->{'newvalue'}; | ||||
274 | 0 | 0 | 0 | $value=$cgivalue unless defined($value); | |||
275 | 0 | 0 | 0 | if(!$have_cgivalues) { | |||
276 | 0 | 0 | 0 | $value=$fdata->{'value'} unless defined($value); | |||
277 | 0 | 0 | 0 | $value=$fdata->{'default'} unless defined($value); | |||
278 | } | ||||||
279 | |||||||
280 | # Empty value is the same as undefined. Spaces are trimmed from the | ||||||
281 | # beginning and the end of the string. | ||||||
282 | # | ||||||
283 | 0 | 0 | 0 | $value="" unless defined $value; | |||
284 | 0 | 0 | $value=~s/^\s*(.*?)\s*$/$1/g; | ||||
285 | |||||||
286 | # Various checks depending on field style. | ||||||
287 | # | ||||||
288 | 0 | 0 | my $newerr; | ||||
289 | 0 | 0 | 0 | my $style=$fdata->{'style'} || $fdata->{'type'} || | |||
290 | throw $self "display - no style or type in field '$name'"; | ||||||
291 | 0 | 0 | 0 | 0 | if(!length($value) && $fdata->{'required'}) { | ||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
292 | 0 | 0 | $newerr=$self->Tx('Required field!'); | ||||
293 | } | ||||||
294 | elsif($fdata->{'maxlength'} && length($value) > $fdata->{'maxlength'}) { | ||||||
295 | 0 | 0 | $newerr=$self->Tx('Value is too long!'); | ||||
296 | } | ||||||
297 | elsif($fdata->{'minlength'} && length($value) && | ||||||
298 | length($value) < $fdata->{'minlength'}) { | ||||||
299 | 0 | 0 | $newerr=$self->Tx("Value is too short!"); | ||||
300 | } | ||||||
301 | elsif($style eq 'text') { | ||||||
302 | # No checks for text | ||||||
303 | } | ||||||
304 | elsif($style eq 'textarea') { | ||||||
305 | # No checks for textarea | ||||||
306 | } | ||||||
307 | elsif($style eq 'file') { | ||||||
308 | 0 | 0 | 0 | if(!$value) { | |||
309 | 0 | 0 | $newerr=$self->Tx("No filename given"); | ||||
310 | } | ||||||
311 | } | ||||||
312 | elsif($style eq 'email') { | ||||||
313 | 0 | 0 | 0 | 0 | if(length($value) && $value !~ /^[\w\.\+\/\$\%\&\`{}'=-]+\@([a-z0-9-]+\.)+[a-z]+$/i) { | ||
314 | 0 | 0 | $newerr=$self->Tx("Value is not in the form of user\@host.domain!"); | ||||
315 | } | ||||||
316 | } | ||||||
317 | elsif($style eq 'usphone') { | ||||||
318 | 0 | 0 | 0 | $fdata->{'maxlength'}=15 unless $fdata->{'maxlength'}; | |||
319 | 0 | 0 | 0 | if(length($value)) { | |||
320 | 0 | 0 | $value =~ s/\D//g; | ||||
321 | 0 | 0 | 0 | if(length($value) == 7) { | |||
0 | |||||||
0 | |||||||
322 | 0 | 0 | $newerr=$self->Tx("Needs area code!"); | ||||
323 | } | ||||||
324 | elsif(length($value) == 11) { | ||||||
325 | 0 | 0 | 0 | if(substr($value,0,1) ne '1') { | |||
326 | 0 | 0 | $newerr=$self->Tx("Must be a US phone!"); | ||||
327 | } | ||||||
328 | } | ||||||
329 | elsif(length($value) != 10) { | ||||||
330 | 0 | 0 | $newerr=$self->Tx("Does not look like a right phone!"); | ||||
331 | } | ||||||
332 | else { | ||||||
333 | 0 | 0 | $value=~s/^.?(...)(...)(....)/($1) $2-$3/; | ||||
334 | } | ||||||
335 | } | ||||||
336 | } | ||||||
337 | elsif($style eq 'phone') { # +99 (123) 456-78-90 x 123 | ||||||
338 | 0 | 0 | 0 | $fdata->{'maxlength'}=30 unless $fdata->{'maxlength'}; | |||
339 | 0 | 0 | 0 | if(length($value)) { | |||
340 | 0 | 0 | my ($p,$e)=split(/[a-zA-Z]+/,$value); | ||||
341 | |||||||
342 | 0 | 0 | $p=~s/\D//g; | ||||
343 | 0 | 0 | 0 | $e||=''; | |||
344 | 0 | 0 | $e=~s/\D//g; | ||||
345 | |||||||
346 | 0 | 0 | 0 | if(length($p)<10) { | |||
0 | |||||||
0 | |||||||
347 | 0 | 0 | $newerr=$self->Tx("Needs area code!"); | ||||
348 | } | ||||||
349 | elsif(length($p)==10) { | ||||||
350 | 0 | 0 | $p='1' . $p; | ||||
351 | } | ||||||
352 | elsif(length($p)>13) { | ||||||
353 | 0 | 0 | $newerr=$self->Tx("Too many digits!"); | ||||
354 | } | ||||||
355 | |||||||
356 | 0 | 0 | 0 | if(!$newerr) { | |||
357 | 0 | 0 | ($value=$p)=~s/^(.+)(...)(...)(....)$/+$1 ($2) $3-$4/; | ||||
358 | 0 | 0 | 0 | $value.=" ext. $e" if $e; | |||
359 | } | ||||||
360 | } | ||||||
361 | } | ||||||
362 | elsif($style eq 'int' || $style eq 'integer' || $style eq 'number') { | ||||||
363 | 0 | 0 | 0 | if(length($value)) { | |||
364 | 0 | 0 | 0 | if($value =~ /^-?[\d,']+$/) { | |||
365 | 0 | 0 | $value=~s/[,']+//g; | ||||
366 | 0 | 0 | 0 | 0 | if(defined($fdata->{'minvalue'}) && $value<$fdata->{'minvalue'}) { | ||
367 | $newerr=$self->Tx("Value is less than {{min}}", | ||||||
368 | 0 | 0 | { min => $fdata->{'minvalue'} }); | ||||
369 | } | ||||||
370 | 0 | 0 | 0 | 0 | if(defined($fdata->{'maxvalue'}) && $value>$fdata->{'maxvalue'}) { | ||
371 | $newerr=$self->Tx("Value is greater than {{max}}", | ||||||
372 | 0 | 0 | { max => $fdata->{'maxvalue'} }); | ||||
373 | } | ||||||
374 | } | ||||||
375 | else { | ||||||
376 | 0 | 0 | $newerr=$self->Tx("Is not an integer!"); | ||||
377 | } | ||||||
378 | } | ||||||
379 | } | ||||||
380 | elsif($style eq 'real') { | ||||||
381 | 0 | 0 | 0 | if(length($value)) { | |||
382 | 0 | 0 | 0 | if($value =~ /^-?[\d,'\.]+$/) { | |||
383 | 0 | 0 | $value=~s/[,']+//g; | ||||
384 | 0 | 0 | 0 | 0 | if(defined($fdata->{'minvalue'}) && $value<$fdata->{'minvalue'}) { | ||
385 | $newerr=$self->Tx("Value is less than {{min}}", | ||||||
386 | 0 | 0 | { min => $fdata->{'minvalue'} }); | ||||
387 | } | ||||||
388 | 0 | 0 | 0 | 0 | if(defined($fdata->{'maxvalue'}) && $value>$fdata->{'maxvalue'}) { | ||
389 | $newerr=$self->Tx("Value is greater than {{max}}", | ||||||
390 | 0 | 0 | { max => $fdata->{'maxvalue'} }); | ||||
391 | } | ||||||
392 | } | ||||||
393 | else { | ||||||
394 | 0 | 0 | $newerr=$self->Tx("Is not a number!"); | ||||
395 | } | ||||||
396 | } | ||||||
397 | } | ||||||
398 | elsif($style eq 'password') { | ||||||
399 | 0 | 0 | 0 | 0 | if(length($value) && $fdata->{'pair'} && | ||
0 | |||||||
400 | $value ne $cgi->param($fdata->{'pair'})) { | ||||||
401 | 0 | 0 | $newerr=$self->Tx("Does not match the copy!"); | ||||
402 | } | ||||||
403 | } | ||||||
404 | elsif($style eq 'country') { | ||||||
405 | 0 | 0 | my @cl=$self->countries_list(); | ||||
406 | 0 | 0 | my $match=0; | ||||
407 | 0 | 0 | foreach my $c (@cl) { | ||||
408 | 0 | 0 | $match=lc($c) eq lc($value); | ||||
409 | 0 | 0 | 0 | last if $match; | |||
410 | } | ||||||
411 | 0 | 0 | 0 | 0 | if(length($value) && !$match) { | ||
412 | 0 | 0 | $newerr=$self->Tx("Unknown country"); | ||||
413 | } | ||||||
414 | } | ||||||
415 | elsif($style eq 'usstate' || $style eq 'uscontst') { | ||||||
416 | 0 | 0 | 0 | my @cl=$style eq 'usstate' ? $self->us_states_list() | |||
417 | : $self->us_continental_states_list(); | ||||||
418 | 0 | 0 | my $match=0; | ||||
419 | 0 | 0 | 0 | my $sv=substr($value || '',0,2); | |||
420 | 0 | 0 | foreach my $c (@cl) { | ||||
421 | 0 | 0 | $match=lc(substr($c,0,2)) eq lc($sv); | ||||
422 | 0 | 0 | 0 | last if $match; | |||
423 | } | ||||||
424 | 0 | 0 | 0 | 0 | if(length($value) && !$match) { | ||
425 | 0 | 0 | $newerr=$self->Tx("Unknown state"); | ||||
426 | } | ||||||
427 | } | ||||||
428 | elsif($style eq 'cctype') { | ||||||
429 | 0 | 0 | my @cl=$self->cc_list(); | ||||
430 | 0 | 0 | my $match=0; | ||||
431 | 0 | 0 | foreach my $c (@cl) { | ||||
432 | 0 | 0 | $match=lc($c) eq lc($value); | ||||
433 | 0 | 0 | 0 | last if $match; | |||
434 | } | ||||||
435 | 0 | 0 | 0 | 0 | if(length($value) && !$match) { | ||
436 | 0 | 0 | $newerr=$self->Tx("Unknown credit card type"); | ||||
437 | } | ||||||
438 | } | ||||||
439 | elsif($style eq 'ccnum') { | ||||||
440 | 0 | 0 | 0 | if(length($value)) { | |||
441 | 0 | 0 | 0 | my $type=$fdata->{'pair'} ? $cgi->param($fdata->{'pair'}) : ''; | |||
442 | 0 | 0 | $newerr=$self->cc_validate(type => $type, number => $value, validated => \$value); | ||||
443 | } | ||||||
444 | } | ||||||
445 | elsif($style eq 'month') { | ||||||
446 | 0 | 0 | 0 | if(length($value)) { | |||
447 | 0 | 0 | $value=int($value); | ||||
448 | 0 | 0 | 0 | 0 | if($value<1 || $value>12) { | ||
449 | 0 | 0 | $newerr=$self->Tx('Invalid month!'); | ||||
450 | } | ||||||
451 | } | ||||||
452 | } | ||||||
453 | elsif($style eq 'year') { | ||||||
454 | 0 | 0 | 0 | 0 | if($fdata->{'minyear'} && $fdata->{'maxyear'}) { | ||
0 | |||||||
455 | 0 | 0 | my $minyear=$self->calculate_year($fdata->{'minyear'}); | ||||
456 | 0 | 0 | my $maxyear=$self->calculate_year($fdata->{'maxyear'}); | ||||
457 | 0 | 0 | 0 | if(length($value)) { | |||
458 | 0 | 0 | $value=$self->calculate_year($value); | ||||
459 | 0 | 0 | 0 | if($value<$minyear) { | |||
0 | |||||||
460 | 0 | 0 | $newerr=$self->Tx("Must be after {{year}}", | ||||
461 | { year => $minyear }); | ||||||
462 | } | ||||||
463 | elsif($value>$maxyear) { | ||||||
464 | 0 | 0 | $newerr=$self->Tx("Must be before {{year}}", | ||||
465 | { year => $maxyear }); | ||||||
466 | } | ||||||
467 | } | ||||||
468 | } | ||||||
469 | elsif(length($value)) { | ||||||
470 | 0 | 0 | $value=$self->calculate_year($value); | ||||
471 | 0 | 0 | 0 | 0 | if($value<1900 || $value>2099) { | ||
472 | 0 | 0 | $newerr=$self->Tx('Invalid year!'); | ||||
473 | } | ||||||
474 | } | ||||||
475 | } | ||||||
476 | elsif($style eq 'checkbox') { | ||||||
477 | |||||||
478 | # If checkbox is not checked we don't get any info about it | ||||||
479 | # in the cgi parameters. So we have to take a guess if the | ||||||
480 | # form was generally filled in, but we have an unchecked | ||||||
481 | # checkbox or this is the first display and form was not | ||||||
482 | # submitted yet. | ||||||
483 | # | ||||||
484 | 0 | 0 | 0 | if($have_cgivalues) { | |||
485 | 0 | 0 | 0 | $value=(defined $fdata->{'newvalue'} ? $fdata->{'newvalue'} : $cgivalue) ? 1 : 0; | |||
0 | |||||||
486 | } | ||||||
487 | else { | ||||||
488 | 0 | 0 | 0 | $value=(defined($fdata->{'value'}) ? $fdata->{'value'} : $fdata->{'default'}) ? 1 : 0; | |||
0 | |||||||
489 | } | ||||||
490 | } | ||||||
491 | elsif($style eq 'selection') { | ||||||
492 | 0 | 0 | 0 | if(length($value)) { | |||
493 | 0 | 0 | my $opt=$fdata->{'options'}; | ||||
494 | 0 | 0 | 0 | if(ref($opt) eq 'HASH') { | |||
0 | |||||||
495 | 0 | 0 | 0 | if(!defined $opt->{$value}) { | |||
496 | 0 | 0 | $newerr=$self->Tx('Bad option value!'); | ||||
497 | } | ||||||
498 | } | ||||||
499 | elsif(ref($opt) eq 'ARRAY') { | ||||||
500 | 0 | 0 | my $found; | ||||
501 | 0 | 0 | for(my $i=0; $i<@$opt; $i+=2) { | ||||
502 | 0 | 0 | 0 | next unless defined($opt->[$i+1]); | |||
503 | 0 | 0 | 0 | if($opt->[$i] eq $value) { | |||
504 | 0 | 0 | $found=1; | ||||
505 | 0 | 0 | last; | ||||
506 | } | ||||||
507 | } | ||||||
508 | 0 | 0 | 0 | if(!$found) { | |||
509 | 0 | 0 | $newerr=$self->Tx('Bad option value!'); | ||||
510 | } | ||||||
511 | } | ||||||
512 | else { | ||||||
513 | 0 | 0 | $newerr=$self->Tx('Unknown data in options!'); | ||||
514 | } | ||||||
515 | } | ||||||
516 | } | ||||||
517 | else { | ||||||
518 | 0 | 0 | $self->throw("display - unknown style '$style'"); | ||||
519 | } | ||||||
520 | |||||||
521 | # If the form is not filled at all we empty the errstr | ||||||
522 | # | ||||||
523 | 0 | 0 | 0 | 0 | if($newerr && (!$have_submit || !$have_cgivalues)) { | ||
0 | |||||||
524 | 0 | 0 | $newerr = ''; | ||||
525 | } | ||||||
526 | |||||||
527 | # Adding error description to the list if there was an | ||||||
528 | # error. Storing value otherwise. | ||||||
529 | # | ||||||
530 | 0 | 0 | 0 | if($newerr) { | |||
531 | 0 | 0 | 0 | $errstr.=($fdata->{'text'} || $name) . ": " . $newerr . " \n"; |
|||
532 | 0 | 0 | $fdata->{'errstr'}=$newerr; | ||||
533 | } | ||||||
534 | else { | ||||||
535 | 0 | 0 | $fdata->{'value'}=$value; | ||||
536 | } | ||||||
537 | |||||||
538 | 0 | 0 | $fdata->{'rawvalue'}=$value; | ||||
539 | |||||||
540 | # Filling formparams hash | ||||||
541 | # | ||||||
542 | 0 | 0 | 0 | $formparams{"$param.VALUE"}=defined($value) ? $value : ""; | |||
543 | 0 | 0 | 0 | $formparams{"$param.TEXT"}=$fdata->{'text'} || $name; | |||
544 | 0 | 0 | $formparams{"$param.NAME"}=$name; | ||||
545 | 0 | 0 | 0 | $formparams{"$param.REQUIRED"}=$fdata->{'required'} ? 1 : 0; | |||
546 | 0 | 0 | 0 | $formparams{"$param.SIZE"}=$fdata->{'size'} || 30; | |||
547 | 0 | 0 | 0 | $formparams{"$param.ROWS"}=$fdata->{'rows'} || 1; | |||
548 | 0 | 0 | 0 | $formparams{"$param.MAXLENGTH"}=$fdata->{'maxlength'} || 100; | |||
549 | 0 | 0 | 0 | $formparams{"$param.MINLENGTH"}=$fdata->{'minlength'} || 0; | |||
550 | 0 | 0 | 0 | $formparams{"$param.ERRSTR"}=$fdata->{'errstr'} || ''; | |||
551 | } | ||||||
552 | |||||||
553 | # Checking content for general compatibility by overriden | ||||||
554 | # method. Called only if data are basicly good. | ||||||
555 | # | ||||||
556 | 0 | 0 | 0 | 0 | if($have_submit && $have_cgivalues && !$errstr) { | ||
0 | |||||||
557 | 0 | 0 | my @rc=$self->check_form(merge_refs($args,\%formparams)); | ||||
558 | 0 | 0 | 0 | if(@rc<2) { | |||
0 | |||||||
559 | 0 | 0 | 0 | $formparams{"ERRSTR.CHECK_FORM"}=$errstr=($rc[0] || ''); | |||
560 | } | ||||||
561 | elsif(scalar(@rc)%2 == 0) { | ||||||
562 | 0 | 0 | for(my $i=0; $i<@rc; $i+=2) { | ||||
563 | 0 | 0 | 0 | my $e=($rc[$i] || ''); | |||
564 | 0 | 0 | 0 | next unless $e; | |||
565 | 0 | 0 | my $fname=$rc[$i+1]; | ||||
566 | 0 | 0 | 0 | if($fname) { | |||
567 | 0 | 0 | my $fdata=$self->field_desc($fname); | ||||
568 | 0 | 0 | 0 | my $param=$fdata->{'param'} || uc($fdata->{'name'}); | |||
569 | |||||||
570 | 0 | 0 | 0 | if($fdata->{'errstr'}) { | |||
571 | 0 | 0 | 0 | $fdata->{'errstr'}.=($fdata->{'errstr'} =~ /\.\s*$/ ? ' ' : '; ') . $e; | |||
572 | 0 | 0 | $formparams{"$param.ERRSTR"}=$fdata->{'errstr'}; | ||||
573 | } | ||||||
574 | else { | ||||||
575 | 0 | 0 | $fdata->{'errstr'}=$formparams{"$param.ERRSTR"}=$e; | ||||
576 | } | ||||||
577 | |||||||
578 | 0 | 0 | 0 | $errstr.="\n " if $errstr; |
|||
579 | 0 | 0 | $errstr.=$e; | ||||
580 | } | ||||||
581 | else { | ||||||
582 | 0 | 0 | 0 | $errstr.="\n " if $errstr; |
|||
583 | 0 | 0 | 0 | $formparams{'ERRSTR.CHECK_FORM'}.="\n " if $errstr; |
|||
584 | 0 | 0 | $errstr.=$e; | ||||
585 | 0 | 0 | $formparams{'ERRSTR.CHECK_FORM'}.=$e; | ||||
586 | } | ||||||
587 | } | ||||||
588 | } | ||||||
589 | else { | ||||||
590 | 0 | 0 | throw $self "display - wrong number of results (".join('|',@rc).")"; | ||||
591 | } | ||||||
592 | } | ||||||
593 | 0 | 0 | 0 | $formparams{"ERRSTR.CHECK_FORM"}||=''; | |||
594 | |||||||
595 | # If the form is not filled at all we remove errstr's from | ||||||
596 | # individual fields. | ||||||
597 | # | ||||||
598 | 0 | 0 | 0 | 0 | if(!$have_submit || !$have_cgivalues) { | ||
599 | 0 | 0 | $errstr=''; | ||||
600 | 0 | 0 | foreach my $fdata (@{$fields}) { | ||||
0 | 0 | ||||||
601 | 0 | 0 | 0 | my $param=$fdata->{'param'} || uc($fdata->{'name'}); | |||
602 | 0 | 0 | $formparams{"$param.ERRSTR"}=''; | ||||
603 | } | ||||||
604 | } | ||||||
605 | |||||||
606 | # Building form element HTML values. Need to do this after error | ||||||
607 | # checking, because the element HTML might be reliant on error | ||||||
608 | # checking status. | ||||||
609 | # | ||||||
610 | 0 | 0 | foreach my $fdata (@{$fields}) { | ||||
0 | 0 | ||||||
611 | 0 | 0 | my $name=$fdata->{'name'}; | ||||
612 | 0 | 0 | 0 | my $param=$fdata->{'param'} || uc($name); | |||
613 | |||||||
614 | 0 | 0 | my $value=$fdata->{'rawvalue'}; | ||||
615 | |||||||
616 | 0 | 0 | 0 | my $style=$fdata->{'style'} || $fdata->{'type'} || | |||
617 | throw $self "- no style or type in field '$name'"; | ||||||
618 | |||||||
619 | 0 | 0 | my $seloptions; | ||||
620 | my $selcompare; | ||||||
621 | 0 | 0 | 0 | 0 | if($style eq 'country') { | ||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | 0 | ||||||
0 | |||||||
0 | |||||||
622 | 0 | 0 | my @cl=$self->countries_list(); | ||||
623 | $seloptions=[ | ||||||
624 | '' => 'Select Country', | ||||||
625 | 0 | 0 | (map { $_ => $_ } @cl), | ||||
0 | 0 | ||||||
626 | ]; | ||||||
627 | 0 | 0 | 0 | $selcompare=sub { return uc($_[0]) eq uc($_[1]) }; | |||
0 | 0 | ||||||
628 | } | ||||||
629 | elsif($style eq 'usstate' || $style eq 'uscontst') { | ||||||
630 | 0 | 0 | 0 | my @cl=$style eq 'usstate' ? $self->us_states_list() | |||
631 | : $self->us_continental_states_list(); | ||||||
632 | $seloptions=[ | ||||||
633 | '' => 'Select State', | ||||||
634 | 0 | 0 | (map { uc(substr($_,0,2)) => $_ } @cl), | ||||
0 | 0 | ||||||
635 | ]; | ||||||
636 | 0 | 0 | 0 | $selcompare=sub { return uc($_[0]) eq uc($_[1]) }; | |||
0 | 0 | ||||||
637 | } | ||||||
638 | elsif($style eq 'cctype') { | ||||||
639 | 0 | 0 | my @cl=$self->cc_list(); | ||||
640 | $seloptions=[ | ||||||
641 | '' => 'Select Card Type', | ||||||
642 | 0 | 0 | (map { $_ => $_ } @cl), | ||||
0 | 0 | ||||||
643 | ]; | ||||||
644 | 0 | 0 | 0 | $selcompare=sub { return uc($_[0]) eq uc($_[1]) }; | |||
0 | 0 | ||||||
645 | } | ||||||
646 | elsif($style eq 'month') { | ||||||
647 | 0 | 0 | my @cl=qw(January February March April May June July | ||||
648 | August September October November December); | ||||||
649 | $seloptions=[ | ||||||
650 | '' => 'Select Month', | ||||||
651 | 0 | 0 | (map { sprintf('%02u',$_) => sprintf('%02u - %s',$_,$cl[$_-1]) } (1..12)), | ||||
0 | 0 | ||||||
652 | ]; | ||||||
653 | 0 | 0 | 0 | 0 | $selcompare=sub { return defined $_[0] && length $_[0] && length $_[1] && $_[0] == $_[1] }; | ||
0 | 0 | ||||||
654 | } | ||||||
655 | elsif($style eq 'year' && !$fdata->{'maxlength'} && $fdata->{'minyear'} && $fdata->{'maxyear'}) { | ||||||
656 | 0 | 0 | my $minyear=$self->calculate_year($fdata->{'minyear'}); | ||||
657 | 0 | 0 | my $maxyear=$self->calculate_year($fdata->{'maxyear'}); | ||||
658 | $seloptions=[ | ||||||
659 | '' => 'Select Year', | ||||||
660 | 0 | 0 | (map { sprintf('%04u',$_) => sprintf('%04u',$_) } ($minyear..$maxyear)), | ||||
0 | 0 | ||||||
661 | ]; | ||||||
662 | 0 | 0 | 0 | 0 | $selcompare=sub { return defined $_[0] && length $_[0] && length $_[1] && $_[0] == $_[1] }; | ||
0 | 0 | ||||||
663 | } | ||||||
664 | elsif($style eq 'checkbox') { | ||||||
665 | $fdata->{'html'}=$obj->expand( | ||||||
666 | path => '/bits/fillout-form/html-checkbox', | ||||||
667 | NAME => $name, | ||||||
668 | VALUE => $fdata->{'value'} || '', | ||||||
669 | CHECKED => $value ? ' checked ' : '', | ||||||
670 | HTMLID => $fdata->{'htmlid'} || $name, | ||||||
671 | 0 | 0 | 0 | 0 | ERRSTR => $fdata->{'errstr'} // '', | ||
0 | |||||||
0 | |||||||
672 | ); | ||||||
673 | } | ||||||
674 | elsif($style eq 'selection') { | ||||||
675 | 0 | 0 | 0 | $seloptions=$fdata->{'options'} || | |||
676 | $self->throw("display - no 'options' for '$name' selection"); | ||||||
677 | } | ||||||
678 | elsif($style eq 'text' || $style eq 'phone' || $style eq 'usphone' || | ||||||
679 | $style eq 'ccnum' || $style eq 'email' || $style eq 'year' || | ||||||
680 | $style eq 'number' || $style eq 'int' || $style eq 'integer' || | ||||||
681 | $style eq 'real' ) { | ||||||
682 | $fdata->{'html'}=$obj->expand( | ||||||
683 | path => '/bits/fillout-form/html-text', | ||||||
684 | NAME => $name, | ||||||
685 | VALUE => $value // '', | ||||||
686 | MAXLENGTH => $fdata->{'maxlength'} || 100, | ||||||
687 | SIZE => $fdata->{'size'} || 30, | ||||||
688 | 0 | 0 | 0 | ERRSTR => $fdata->{'errstr'} // '', | |||
0 | |||||||
0 | |||||||
0 | |||||||
689 | ); | ||||||
690 | } | ||||||
691 | elsif($style eq 'textarea') { | ||||||
692 | $fdata->{'html'}=$obj->expand( | ||||||
693 | path => '/bits/fillout-form/html-textarea', | ||||||
694 | NAME => $name, | ||||||
695 | VALUE => $value // '', | ||||||
696 | SIZE => $fdata->{'size'} || 30, | ||||||
697 | ROWS => $fdata->{'rows'} || 8, | ||||||
698 | 0 | 0 | 0 | ERRSTR => $fdata->{'errstr'} // '', | |||
0 | |||||||
0 | |||||||
0 | |||||||
699 | ); | ||||||
700 | } | ||||||
701 | elsif($style eq 'file') { | ||||||
702 | $fdata->{'html'}=$obj->expand( | ||||||
703 | path => '/bits/fillout-form/html-file', | ||||||
704 | NAME => $name, | ||||||
705 | SIZE => $fdata->{'size'} || 30, | ||||||
706 | 0 | 0 | 0 | ERRSTR => $fdata->{'errstr'} // '', | |||
0 | |||||||
707 | ); | ||||||
708 | } | ||||||
709 | elsif($style eq 'password') { | ||||||
710 | $fdata->{'html'}=$obj->expand( | ||||||
711 | path => '/bits/fillout-form/html-password', | ||||||
712 | NAME => $name, | ||||||
713 | VALUE => $value // '', | ||||||
714 | MAXLENGTH => $fdata->{'maxlength'} || 100, | ||||||
715 | SIZE => $fdata->{'size'} || 30, | ||||||
716 | 0 | 0 | 0 | ERRSTR => $fdata->{'errstr'} // '', | |||
0 | |||||||
0 | |||||||
0 | |||||||
717 | ); | ||||||
718 | } | ||||||
719 | |||||||
720 | # Various selection fields above just set seloptions for uniform build. | ||||||
721 | # | ||||||
722 | 0 | 0 | 0 | if($seloptions) { | |||
723 | 0 | 0 | my $has_empty; | ||||
724 | my $used_selected; | ||||||
725 | 0 | 0 | my $html=''; | ||||
726 | my $html_sub=sub { | ||||||
727 | 0 | 0 | 0 | my ($v,$t)=@_; | |||
728 | 0 | 0 | 0 | 0 | $has_empty=1 if !defined($v) || !length($v); | ||
729 | 0 | 0 | 0 | return unless defined($t); | |||
730 | 0 | 0 | my $sel=''; | ||||
731 | 0 | 0 | 0 | if(!$used_selected) { | |||
732 | 0 | 0 | 0 | my $equal=$selcompare ? $selcompare->($v,$value) : ($v eq $value); | |||
733 | 0 | 0 | 0 | if($equal) { | |||
734 | 0 | 0 | $sel=' selected'; | ||||
735 | 0 | 0 | $used_selected=1; | ||||
736 | } | ||||||
737 | } | ||||||
738 | 0 | 0 | $html.=$obj->expand( | ||||
739 | path => '/bits/fillout-form/html-select-option', | ||||||
740 | NAME => $name, | ||||||
741 | VALUE => $v, | ||||||
742 | TEXT => $t, | ||||||
743 | SELECTED=> $sel, | ||||||
744 | ); | ||||||
745 | 0 | 0 | 0 | $formparams{"$param.RV_CURRENT_$v"}=$sel ? 1 : 0; | |||
746 | 0 | 0 | $formparams{"$param.RV_VALUE_$v"}=$v; | ||||
747 | 0 | 0 | $formparams{"$param.RV_TEXT_$v"}=$t; | ||||
748 | 0 | 0 | }; | ||||
749 | |||||||
750 | 0 | 0 | 0 | if(ref($seloptions) eq 'HASH') { | |||
0 | |||||||
751 | 0 | 0 | foreach my $v (sort { $seloptions->{$a} cmp $seloptions->{$b} } keys %$seloptions) { | ||||
0 | 0 | ||||||
752 | 0 | 0 | &{$html_sub}($v,$seloptions->{$v}); | ||||
0 | 0 | ||||||
753 | } | ||||||
754 | } | ||||||
755 | elsif(ref($seloptions) eq 'ARRAY') { | ||||||
756 | 0 | 0 | for(my $i=0; $i<@$seloptions; $i+=2) { | ||||
757 | 0 | 0 | &{$html_sub}($seloptions->[$i],$seloptions->[$i+1]); | ||||
0 | 0 | ||||||
758 | } | ||||||
759 | } | ||||||
760 | else { | ||||||
761 | 0 | 0 | throw $self "Unknown data type in 'options' name=$name"; | ||||
762 | }; | ||||||
763 | |||||||
764 | # We do not display 'Please select' if there is an empty | ||||||
765 | # value in the list, we assume that that empty value is a | ||||||
766 | # prompt of some sort. | ||||||
767 | # | ||||||
768 | # If there is no need for empty value and no need for a | ||||||
769 | # prompt -- use ('' => undef) as an indicator of that. | ||||||
770 | # | ||||||
771 | 0 | 0 | $formparams{"$param.HTML_OPTIONS"}=$html; | ||||
772 | |||||||
773 | # For compatibility with older code this is not included in | ||||||
774 | # HTML_OPTIONS | ||||||
775 | # | ||||||
776 | 0 | 0 | 0 | if(!$has_empty) { | |||
777 | 0 | 0 | $html=' | ||||
778 | t2ht($self->Tx('Please select')) . | ||||||
779 | ''.$html; | ||||||
780 | } | ||||||
781 | |||||||
782 | # Final code | ||||||
783 | # | ||||||
784 | $fdata->{'html'}=$obj->expand( | ||||||
785 | path => '/bits/fillout-form/html-select', | ||||||
786 | NAME => $name, | ||||||
787 | VALUE => $value // '', | ||||||
788 | OPTIONS => $html, | ||||||
789 | 0 | 0 | 0 | ERRSTR => $fdata->{'errstr'}, | |||
790 | ); | ||||||
791 | } | ||||||
792 | |||||||
793 | 0 | 0 | 0 | $formparams{"$param.HTML"}=$fdata->{'html'} || ""; | |||
794 | } | ||||||
795 | |||||||
796 | # If there were errors then displaying the form. We also display | ||||||
797 | # the form here if it is not yet filled out and if it is, but we we | ||||||
798 | # asked to keep displaying it using 'keep_form' setup parameter. | ||||||
799 | # | ||||||
800 | 0 | 0 | my $keep_form=$self->{'keep_form'}; | ||||
801 | 0 | 0 | 0 | 0 | if(!$have_submit || !$have_cgivalues || $errstr || $keep_form) { | ||
0 | |||||||
0 | |||||||
802 | 0 | 0 | my $eh; | ||||
803 | my $et; | ||||||
804 | 0 | 0 | 0 | 0 | if($errstr && $have_cgivalues) { | ||
805 | $eh=$obj->expand( | ||||||
806 | path => '/bits/fillout-form/errstr', | ||||||
807 | ERRSTR => $errstr, | ||||||
808 | 0 | 0 | 'ERRSTR.CHECK_FORM' => $formparams{"ERRSTR.CHECK_FORM"}, | ||||
809 | ); | ||||||
810 | 0 | 0 | $et=$errstr; | ||||
811 | |||||||
812 | } | ||||||
813 | $obj->display($args,\%formparams,{ | ||||||
814 | path => $args->{'form.path'}, | ||||||
815 | 0 | 0 | 0 | template => $args->{'form.template'}, | |||
0 | |||||||
816 | ERRSTR => $et || '', | ||||||
817 | 'ERRSTR.HTML' => $eh || '', | ||||||
818 | }); | ||||||
819 | 0 | 0 | 0 | 0 | return unless $keep_form && !$errstr && $have_cgivalues && $have_submit; | ||
0 | |||||||
0 | |||||||
820 | } | ||||||
821 | |||||||
822 | # Our form is correct! | ||||||
823 | # | ||||||
824 | 0 | 0 | $self->form_ok(merge_refs($args,\%formparams)); | ||||
825 | } | ||||||
826 | |||||||
827 | ############################################################################### | ||||||
828 | |||||||
829 | =item field_desc ($) | ||||||
830 | |||||||
831 | Returns field description by name. This is the correct way to get to the | ||||||
832 | value of a field from check_form() or form_ok() methods. | ||||||
833 | |||||||
834 | If the optional second parameter set to true then on failure to find the | ||||||
835 | field the method will return undef instead of throwing an error. | ||||||
836 | |||||||
837 | =cut | ||||||
838 | |||||||
839 | sub field_desc ($$;$) { | ||||||
840 | 0 | 0 | 1 | 0 | my ($self,$name,$soft_failure)=@_; | ||
841 | |||||||
842 | 0 | 0 | 0 | my $fields=$self->{'fields'} || | |||
843 | throw $self "field_desc - has not set fields for FilloutForm"; | ||||||
844 | |||||||
845 | 0 | 0 | 0 | if(ref($fields) eq 'ARRAY') { | |||
846 | 0 | 0 | foreach my $fdata (@{$fields}) { | ||||
0 | 0 | ||||||
847 | 0 | 0 | 0 | return $fdata if $fdata->{'name'} eq $name; | |||
848 | } | ||||||
849 | } | ||||||
850 | else { | ||||||
851 | 0 | 0 | 0 | return $fields->{$name} if $fields->{$name}; | |||
852 | } | ||||||
853 | |||||||
854 | 0 | 0 | 0 | return undef if $soft_failure; | |||
855 | |||||||
856 | 0 | 0 | throw $self "field_desc - unknown field '$name' referred"; | ||||
857 | } | ||||||
858 | |||||||
859 | ############################################################################### | ||||||
860 | |||||||
861 | =item field_names ($) | ||||||
862 | |||||||
863 | Returns field a list of all field names in the current form. | ||||||
864 | |||||||
865 | =cut | ||||||
866 | |||||||
867 | sub field_names ($) { | ||||||
868 | 0 | 0 | 1 | 0 | my $self=shift; | ||
869 | |||||||
870 | 0 | 0 | 0 | my $fields=$self->{'fields'} || | |||
871 | throw $self "field_names - has not set fields for FilloutForm"; | ||||||
872 | |||||||
873 | 0 | 0 | 0 | if(ref($fields) eq 'ARRAY') { | |||
874 | 0 | 0 | return map { $_->{'name'} } @$fields; | ||||
0 | 0 | ||||||
875 | } | ||||||
876 | else { | ||||||
877 | 0 | 0 | return map { $_->{'name'} } keys %$fields; | ||||
0 | 0 | ||||||
878 | } | ||||||
879 | } | ||||||
880 | |||||||
881 | ############################################################################### | ||||||
882 | |||||||
883 | =item form_ok | ||||||
884 | |||||||
885 | Default handler for filled out form. Must be overriden! | ||||||
886 | |||||||
887 | =cut | ||||||
888 | |||||||
889 | sub form_ok ($%) { | ||||||
890 | 0 | 0 | 1 | 0 | my $self=shift; | ||
891 | 0 | 0 | 0 | if($self->{'form_ok'}) { | |||
892 | my $na=merge_refs(get_args(\@_),{ | ||||||
893 | 0 | 0 | extra_data => $self->{'extra_data'}, | ||||
894 | }); | ||||||
895 | 0 | 0 | return &{$self->{'form_ok'}}($self,$na); | ||||
0 | 0 | ||||||
896 | } | ||||||
897 | 0 | 0 | throw $self 'form_ok - must be overriden in derived class or using form_ok parameter'; | ||||
898 | } | ||||||
899 | |||||||
900 | ## | ||||||
901 | # High-level form content check. Should be overriden for real checks. | ||||||
902 | # Returns '' if there were no error or error text otherwise. | ||||||
903 | # | ||||||
904 | sub check_form ($%) { | ||||||
905 | 0 | 0 | 0 | 0 | my $self=shift; | ||
906 | 0 | 0 | 0 | if($self->{'check_form'}) { | |||
907 | 0 | 0 | my %na=%{get_args(\@_)}; | ||||
0 | 0 | ||||||
908 | 0 | 0 | $na{'extra_data'}=$self->{'extra_data'}; | ||||
909 | 0 | 0 | return &{$self->{'check_form'}}($self,\%na); | ||||
0 | 0 | ||||||
910 | } | ||||||
911 | 0 | 0 | ''; | ||||
912 | } | ||||||
913 | |||||||
914 | ############################################################################### | ||||||
915 | |||||||
916 | =item pre_check_form (%) | ||||||
917 | |||||||
918 | Pre-checking form. May be used if some values are calculated or copied | ||||||
919 | from another and should be checked later. | ||||||
920 | |||||||
921 | Should stuff generated values into {'newvalue'} parameter. | ||||||
922 | |||||||
923 | =cut | ||||||
924 | |||||||
925 | sub pre_check_form ($%) { | ||||||
926 | 0 | 0 | 1 | 0 | my $self=shift; | ||
927 | 0 | 0 | 0 | if($self->{'pre_check_form'}) { | |||
928 | 0 | 0 | my $na=get_args(\@_); | ||||
929 | 0 | 0 | $na->{'extra_data'}=$self->{'extra_data'}; | ||||
930 | 0 | 0 | return &{$self->{'pre_check_form'}}($self,$na); | ||||
0 | 0 | ||||||
931 | } | ||||||
932 | } | ||||||
933 | |||||||
934 | ############################################################################### | ||||||
935 | |||||||
936 | =item countries_list () | ||||||
937 | |||||||
938 | Returns list of countries for selection. May be overriden if site | ||||||
939 | needs only a fraction of that. | ||||||
940 | |||||||
941 | =cut | ||||||
942 | |||||||
943 | sub countries_list () { | ||||||
944 | 0 | 0 | 1 | 0 | split(/\n/,<<'END_OF_LIST'); | ||
945 | United States | ||||||
946 | Afghanistan | ||||||
947 | Albania | ||||||
948 | Algeria | ||||||
949 | American Samoa | ||||||
950 | Andorra | ||||||
951 | Angola | ||||||
952 | Anguilla | ||||||
953 | Antarctica | ||||||
954 | Antigua | ||||||
955 | Antilles | ||||||
956 | Arab Emirates | ||||||
957 | Argentina | ||||||
958 | Armenia | ||||||
959 | Aruba | ||||||
960 | Australia | ||||||
961 | Austria | ||||||
962 | Azerbaidjan | ||||||
963 | Bahamas | ||||||
964 | Bahrain | ||||||
965 | Bangladesh | ||||||
966 | Barbados | ||||||
967 | Barbuda | ||||||
968 | Belarus | ||||||
969 | Belgium | ||||||
970 | Belize | ||||||
971 | Benin | ||||||
972 | Bermuda | ||||||
973 | Bhutan | ||||||
974 | Bolivia | ||||||
975 | Bosnia Herz. | ||||||
976 | Botswana | ||||||
977 | Bouvet Isl. | ||||||
978 | Brazil | ||||||
979 | Brunei Dar. | ||||||
980 | Bulgaria | ||||||
981 | Burkina Faso | ||||||
982 | Burundi | ||||||
983 | C. African Rep. | ||||||
984 | Cambodia | ||||||
985 | Cameroon | ||||||
986 | Cambodia | ||||||
987 | Cameroon | ||||||
988 | Canada | ||||||
989 | Cape Verde | ||||||
990 | Cayman Islands | ||||||
991 | Chad | ||||||
992 | Chile | ||||||
993 | China | ||||||
994 | Christmas Isl. | ||||||
995 | Cocos Islands | ||||||
996 | Colombia | ||||||
997 | Comoros | ||||||
998 | Congo | ||||||
999 | Cook Islands | ||||||
1000 | Costa Rica | ||||||
1001 | Croatia | ||||||
1002 | Cuba | ||||||
1003 | Cyprus | ||||||
1004 | Czech Republic | ||||||
1005 | Denmark | ||||||
1006 | Djibouti | ||||||
1007 | Dominica | ||||||
1008 | Dominican Rep. | ||||||
1009 | East Timor | ||||||
1010 | Ecuador | ||||||
1011 | Egypt | ||||||
1012 | England | ||||||
1013 | El Salvador | ||||||
1014 | Equat. Guinea | ||||||
1015 | Eritrea | ||||||
1016 | Estonia | ||||||
1017 | Ethiopia | ||||||
1018 | Falkland Isl. | ||||||
1019 | Faroe Islands | ||||||
1020 | Fiji | ||||||
1021 | Finland | ||||||
1022 | Former Czech. | ||||||
1023 | Former USSR | ||||||
1024 | France | ||||||
1025 | French Guyana | ||||||
1026 | French S. Terr. | ||||||
1027 | Gabon | ||||||
1028 | Gambia | ||||||
1029 | Georgia | ||||||
1030 | Germany | ||||||
1031 | Ghana | ||||||
1032 | Gibraltar | ||||||
1033 | Great Britain | ||||||
1034 | Greece | ||||||
1035 | Greenland | ||||||
1036 | Grenada | ||||||
1037 | Guadeloupe | ||||||
1038 | Grenada | ||||||
1039 | Guadeloupe | ||||||
1040 | Guam (USA) | ||||||
1041 | Guatemala | ||||||
1042 | Guinea | ||||||
1043 | Guinea Bissau | ||||||
1044 | Guyana | ||||||
1045 | Haiti | ||||||
1046 | Heard/McDonald | ||||||
1047 | Honduras | ||||||
1048 | Hong Kong | ||||||
1049 | Hungary | ||||||
1050 | Iceland | ||||||
1051 | India | ||||||
1052 | Indonesia | ||||||
1053 | Iran | ||||||
1054 | Iraq | ||||||
1055 | Ireland | ||||||
1056 | Israel | ||||||
1057 | Italy | ||||||
1058 | Ivory Coast | ||||||
1059 | Jamaica | ||||||
1060 | Japan | ||||||
1061 | Jordan | ||||||
1062 | Kazakhstan | ||||||
1063 | Kenya | ||||||
1064 | Kiribati | ||||||
1065 | Kuwait | ||||||
1066 | Kyrgyzstan | ||||||
1067 | Laos | ||||||
1068 | Latvia | ||||||
1069 | Lebanon | ||||||
1070 | Lesotho | ||||||
1071 | Liberia | ||||||
1072 | Libya | ||||||
1073 | Liechtenstein | ||||||
1074 | Lithuania | ||||||
1075 | Luxembourg | ||||||
1076 | Macau | ||||||
1077 | Macedonia | ||||||
1078 | Madagascar | ||||||
1079 | Malawi | ||||||
1080 | Malaysia | ||||||
1081 | Maldives | ||||||
1082 | Mali | ||||||
1083 | Malta | ||||||
1084 | Marshall Isl. | ||||||
1085 | Martinique | ||||||
1086 | Mauritania | ||||||
1087 | Mauritius | ||||||
1088 | Mayotte | ||||||
1089 | Mexico | ||||||
1090 | Mayotte | ||||||
1091 | Mexico | ||||||
1092 | Micronesia | ||||||
1093 | Moldavia | ||||||
1094 | Monaco | ||||||
1095 | Mongolia | ||||||
1096 | Montserrat | ||||||
1097 | Morocco | ||||||
1098 | Mozambique | ||||||
1099 | Myanmar | ||||||
1100 | N. Mariana Isl. | ||||||
1101 | Namibia | ||||||
1102 | Nauru | ||||||
1103 | Nepal | ||||||
1104 | Netherlands | ||||||
1105 | Neutral Zone | ||||||
1106 | New Caledonia | ||||||
1107 | New Zealand | ||||||
1108 | Nicaragua | ||||||
1109 | Niger | ||||||
1110 | Nigeria | ||||||
1111 | Niue | ||||||
1112 | Norfolk Island | ||||||
1113 | Northern Ireland | ||||||
1114 | North Korea | ||||||
1115 | Norway | ||||||
1116 | Oman | ||||||
1117 | Pakistan | ||||||
1118 | Palau | ||||||
1119 | Panama | ||||||
1120 | Papua New Guinea | ||||||
1121 | Paraguay | ||||||
1122 | Peru | ||||||
1123 | Philippines | ||||||
1124 | Pitcairn Isl. | ||||||
1125 | Poland | ||||||
1126 | Polynesia | ||||||
1127 | Portugal | ||||||
1128 | Puerto Rico | ||||||
1129 | Qatar | ||||||
1130 | Reunion | ||||||
1131 | Romania | ||||||
1132 | Russia | ||||||
1133 | Rwanda | ||||||
1134 | Samoa | ||||||
1135 | San Marino | ||||||
1136 | Saudi Arabia | ||||||
1137 | Scotland | ||||||
1138 | Senegal | ||||||
1139 | Seychelles | ||||||
1140 | Sierra Leone | ||||||
1141 | Singapore | ||||||
1142 | Sierra Leone | ||||||
1143 | Singapore | ||||||
1144 | Slovak Rep. | ||||||
1145 | Slovenia | ||||||
1146 | Solomon Isl. | ||||||
1147 | Somalia | ||||||
1148 | South Africa | ||||||
1149 | South Korea | ||||||
1150 | Spain | ||||||
1151 | Sri Lanka | ||||||
1152 | St Helena | ||||||
1153 | St Lucia | ||||||
1154 | St Pierre | ||||||
1155 | St Tome | ||||||
1156 | St Vincent | ||||||
1157 | Sudan | ||||||
1158 | Suriname | ||||||
1159 | Swaziland | ||||||
1160 | Sweden | ||||||
1161 | Switzerland | ||||||
1162 | Syrian Arab Republic | ||||||
1163 | Tadjikistan | ||||||
1164 | Taiwan | ||||||
1165 | Tanzania | ||||||
1166 | Thailand | ||||||
1167 | Tobago | ||||||
1168 | Togo | ||||||
1169 | Tokelau | ||||||
1170 | Tonga | ||||||
1171 | Trinidad & Tobago | ||||||
1172 | Tunisia | ||||||
1173 | Turopaque | ||||||
1174 | Turkmenistan | ||||||
1175 | Turks/Caicos Isl. | ||||||
1176 | Tuvalu | ||||||
1177 | Uganda | ||||||
1178 | Ukraine | ||||||
1179 | Uruguay | ||||||
1180 | Uzbekistan | ||||||
1181 | Vanuatu | ||||||
1182 | Vatican City | ||||||
1183 | Venezuela | ||||||
1184 | Vietnam | ||||||
1185 | Virg.Isl. (UK) | ||||||
1186 | Virg.Isl. (US) | ||||||
1187 | Wales | ||||||
1188 | Western Sahara | ||||||
1189 | Yemen | ||||||
1190 | Yugoslavia | ||||||
1191 | Zaire | ||||||
1192 | Zambia | ||||||
1193 | Zimbabwe | ||||||
1194 | END_OF_LIST | ||||||
1195 | } | ||||||
1196 | |||||||
1197 | ############################################################################### | ||||||
1198 | |||||||
1199 | =item us_continental_states_list () | ||||||
1200 | |||||||
1201 | Returns list of US continental states for selection. May be overriden | ||||||
1202 | if site needs only a fraction of that. | ||||||
1203 | |||||||
1204 | =cut | ||||||
1205 | |||||||
1206 | sub us_continental_states_list () { | ||||||
1207 | 0 | 0 | 1 | 0 | my $self=shift; | ||
1208 | 0 | 0 | my @list; | ||||
1209 | 0 | 0 | foreach my $st ($self->us_states_list) { | ||||
1210 | 0 | 0 | 0 | next if $st =~ /^AK/; | |||
1211 | 0 | 0 | 0 | next if $st =~ /^AS/; | |||
1212 | 0 | 0 | 0 | next if $st =~ /^FM/; | |||
1213 | 0 | 0 | 0 | next if $st =~ /^GU/; | |||
1214 | 0 | 0 | 0 | next if $st =~ /^HI/; | |||
1215 | 0 | 0 | 0 | next if $st =~ /^MH/; | |||
1216 | 0 | 0 | 0 | next if $st =~ /^MP/; | |||
1217 | 0 | 0 | 0 | next if $st =~ /^VI/; | |||
1218 | 0 | 0 | push(@list,$st); | ||||
1219 | } | ||||||
1220 | 0 | 0 | @list; | ||||
1221 | } | ||||||
1222 | |||||||
1223 | ############################################################################### | ||||||
1224 | |||||||
1225 | =item us_states_list () | ||||||
1226 | |||||||
1227 | Returns list of US states for selection. May be overriden if site | ||||||
1228 | needs only a fraction of that. | ||||||
1229 | |||||||
1230 | =cut | ||||||
1231 | |||||||
1232 | sub us_states_list () { | ||||||
1233 | 0 | 0 | 1 | 0 | split(/\n/,<<'END_OF_LIST'); | ||
1234 | AL - Alabama | ||||||
1235 | AK - Alaska | ||||||
1236 | AS - American Samoa | ||||||
1237 | AZ - Arizona | ||||||
1238 | AR - Arkansas | ||||||
1239 | CA - California | ||||||
1240 | CO - Colorado | ||||||
1241 | CT - Connecticut | ||||||
1242 | DE - Delaware | ||||||
1243 | DC - District Of Columbia | ||||||
1244 | FM - Federated States Of Micronesia | ||||||
1245 | FL - Florida | ||||||
1246 | GA - Georgia | ||||||
1247 | GU - Guam | ||||||
1248 | HI - Hawaii | ||||||
1249 | ID - Idaho | ||||||
1250 | IL - Illinois | ||||||
1251 | IN - Indiana | ||||||
1252 | IA - Iowa | ||||||
1253 | KS - Kansas | ||||||
1254 | KY - Kentucky | ||||||
1255 | LA - Louisiana | ||||||
1256 | ME - Maine | ||||||
1257 | MH - Marshall Islands | ||||||
1258 | MD - Maryland | ||||||
1259 | MA - Massachusetts | ||||||
1260 | MI - Michigan | ||||||
1261 | MN - Minnesota | ||||||
1262 | MS - Mississippi | ||||||
1263 | MO - Missouri | ||||||
1264 | MT - Montana | ||||||
1265 | NE - Nebraska | ||||||
1266 | NV - Nevada | ||||||
1267 | NH - New Hampshire | ||||||
1268 | NJ - New Jersey | ||||||
1269 | NM - New Mexico | ||||||
1270 | NY - New York | ||||||
1271 | NC - North Carolina | ||||||
1272 | ND - North Dakota | ||||||
1273 | MP - Northern Mariana Islands | ||||||
1274 | OH - Ohio | ||||||
1275 | OK - Oklahoma | ||||||
1276 | OR - Oregon | ||||||
1277 | PW - Palau | ||||||
1278 | PA - Pennsylvania | ||||||
1279 | PR - Puerto Rico | ||||||
1280 | RI - Rhode Island | ||||||
1281 | SC - South Carolina | ||||||
1282 | SD - South Dakota | ||||||
1283 | TN - Tennessee | ||||||
1284 | TX - Texas | ||||||
1285 | UT - Utah | ||||||
1286 | VT - Vermont | ||||||
1287 | VI - Virgin Islands | ||||||
1288 | VA - Virginia | ||||||
1289 | WA - Washington | ||||||
1290 | WV - West Virginia | ||||||
1291 | WI - Wisconsin | ||||||
1292 | WY - Wyoming | ||||||
1293 | END_OF_LIST | ||||||
1294 | } | ||||||
1295 | |||||||
1296 | ## | ||||||
1297 | # Returns a list of known Credit Card types. May be overriden. Should be | ||||||
1298 | # consistent with cc_validate. | ||||||
1299 | # | ||||||
1300 | sub cc_list ($) { | ||||||
1301 | 0 | 0 | 0 | 0 | split(/\n/,<<'END_OF_LIST'); | ||
1302 | Visa | ||||||
1303 | American Express | ||||||
1304 | MasterCard | ||||||
1305 | Discover | ||||||
1306 | Diner's Club | ||||||
1307 | END_OF_LIST | ||||||
1308 | } | ||||||
1309 | |||||||
1310 | ############################################################################### | ||||||
1311 | |||||||
1312 | =item cc_validate (%) | ||||||
1313 | |||||||
1314 | Returns error text if card number is invalid. Only checksum and | ||||||
1315 | consistence with card type is checked. | ||||||
1316 | |||||||
1317 | Card number is taken from 'number' argument and card type from 'type' | ||||||
1318 | argument (optionally). | ||||||
1319 | |||||||
1320 | Will store card number into a scalar reference given by 'validated' | ||||||
1321 | argument, if it exists and the card validates. Will store card type code | ||||||
1322 | into scalar reference given by 'typecode' argument if it exists and the | ||||||
1323 | card validates. Codes are: | ||||||
1324 | |||||||
1325 | VI -- Visa | ||||||
1326 | AE -- American Express | ||||||
1327 | MC -- Mastercard | ||||||
1328 | DC -- Discover | ||||||
1329 | |||||||
1330 | =cut | ||||||
1331 | |||||||
1332 | sub cc_validate ($%) { | ||||||
1333 | 4 | 4 | 1 | 253 | my $self=shift; | ||
1334 | 4 | 13 | my $args=get_args(\@_); | ||||
1335 | |||||||
1336 | 4 | 50 | my $number=$args->{'number'}; | ||||
1337 | 4 | 6 | my $type=$args->{'type'}; | ||||
1338 | |||||||
1339 | # General corrections and checks first. | ||||||
1340 | # | ||||||
1341 | 4 | 23 | $number=~s/\D//g; | ||||
1342 | 4 | 50 | 14 | if(length($number)<13) { | |||
1343 | 0 | 0 | return $self->Tx('Number is too short!'); | ||||
1344 | } | ||||||
1345 | |||||||
1346 | # Checksum first | ||||||
1347 | # | ||||||
1348 | 4 | 6 | my $sum=0; | ||||
1349 | 4 | 10 | for(my $i=0; $i!=length($number)-1; $i++) { | ||||
1350 | 60 | 103 | my $weight = substr($number, -1 * ($i + 2), 1) * (2 - ($i % 2)); | ||||
1351 | 60 | 100 | 118 | $sum += (($weight < 10) ? $weight : ($weight - 9)); | |||
1352 | } | ||||||
1353 | 4 | 50 | 13 | if(substr($number,-1) ne (10-$sum%10)%10) { | |||
1354 | ### dprint "have ".substr($number,-1)." want ".(10-$sum%10)%10; | ||||||
1355 | 0 | 0 | return $self->Tx('Invalid number!'); | ||||
1356 | } | ||||||
1357 | |||||||
1358 | # Guessing card type. | ||||||
1359 | # | ||||||
1360 | 4 | 6 | my $typecode; | ||||
1361 | 4 | 5 | my $realtype=''; | ||||
1362 | 4 | 7 | my $reqlen; | ||||
1363 | 4 | 100 | 18 | if($number =~ /^(?:34|37)/) { | |||
50 | |||||||
0 | |||||||
0 | |||||||
1364 | 1 | 3 | $realtype='american express'; | ||||
1365 | 1 | 2 | $typecode='AE'; | ||||
1366 | 1 | 3 | $reqlen=[15]; | ||||
1367 | } | ||||||
1368 | elsif($number =~ /^4/) { | ||||||
1369 | 3 | 5 | $realtype='visa'; | ||||
1370 | 3 | 4 | $typecode='VI'; | ||||
1371 | 3 | 6 | $reqlen=[13,16]; | ||||
1372 | } | ||||||
1373 | elsif($number =~ /^5/) { | ||||||
1374 | 0 | 0 | $realtype='master\s?card'; | ||||
1375 | 0 | 0 | $typecode='MC'; | ||||
1376 | 0 | 0 | $reqlen=[16]; | ||||
1377 | } | ||||||
1378 | elsif($number =~ /^6/) { | ||||||
1379 | 0 | 0 | $realtype='discover'; | ||||
1380 | 0 | 0 | $typecode='DC'; | ||||
1381 | 0 | 0 | $reqlen=[16]; | ||||
1382 | } | ||||||
1383 | else { | ||||||
1384 | 0 | 0 | return $self->Tx('Unknown card type!'); | ||||
1385 | } | ||||||
1386 | 4 | 50 | 10 | if($reqlen) { | |||
1387 | 4 | 100 | 6 | scalar(grep { length($number)==$_ } @$reqlen) || | |||
7 | 34 | ||||||
1388 | return $self->Tx('Invalid number length!'); | ||||||
1389 | } | ||||||
1390 | |||||||
1391 | # Checking guessed type against the given type. | ||||||
1392 | # | ||||||
1393 | 3 | 50 | 66 | 28 | if($type && lc($type) !~ $realtype) { | ||
1394 | 0 | 0 | return $self->Tx('Number does not match card type!'); | ||||
1395 | } | ||||||
1396 | |||||||
1397 | # Storing values if we were given these references. | ||||||
1398 | # | ||||||
1399 | 3 | 50 | 9 | ${$args->{'validated'}}=$number if $args->{'validated'}; | |||
3 | 7 | ||||||
1400 | 3 | 50 | 8 | ${$args->{'typecode'}}=$typecode if $args->{'typecode'}; | |||
3 | 4 | ||||||
1401 | |||||||
1402 | 3 | 13 | return ''; | ||||
1403 | } | ||||||
1404 | |||||||
1405 | ## | ||||||
1406 | # Calculates year - accepts value, +N, -N. | ||||||
1407 | # | ||||||
1408 | sub calculate_year ($$) { | ||||||
1409 | 0 | 0 | 0 | 0 | my $self=shift; | ||
1410 | 0 | 0 | my $year=shift; | ||||
1411 | 0 | 0 | 0 | if(substr($year,0,1) eq '+') { | |||
0 | |||||||
0 | |||||||
0 | |||||||
1412 | 0 | 0 | $year=(localtime)[5]+1900+substr($year,1); | ||||
1413 | } | ||||||
1414 | elsif(substr($year,0,1) eq '-') { | ||||||
1415 | 0 | 0 | $year=(localtime)[5]+1900-substr($year,1); | ||||
1416 | } | ||||||
1417 | elsif($year < 20) { | ||||||
1418 | 0 | 0 | $year+=2000; | ||||
1419 | } | ||||||
1420 | elsif($year < 100) { | ||||||
1421 | 0 | 0 | $year+=1900; | ||||
1422 | } | ||||||
1423 | 0 | 0 | $year; | ||||
1424 | } | ||||||
1425 | |||||||
1426 | ## | ||||||
1427 | # Returns form phase for multi-page forms. Taken from 'phase' argument | ||||||
1428 | # to 'display' method. | ||||||
1429 | # | ||||||
1430 | sub form_phase ($) { | ||||||
1431 | 0 | 0 | 0 | 0 | my $self=shift; | ||
1432 | 0 | 0 | 0 | return $self->{'phase'} || 1; | |||
1433 | } | ||||||
1434 | |||||||
1435 | ############################################################################### | ||||||
1436 | |||||||
1437 | sub Tx ($$;$) { | ||||||
1438 | 1 | 1 | 0 | 4 | my $self=shift; | ||
1439 | 1 | 2 | my $text=shift; | ||||
1440 | 1 | 50 | 8 | my $values=shift || { }; | |||
1441 | |||||||
1442 | 1 | 50 | 10 | if($self->can('Tx_translate')) { | |||
1443 | 0 | 0 | $text=$self->Tx_translate($text,$values); | ||||
1444 | } | ||||||
1445 | |||||||
1446 | 1 | 3 | $text=~s/ | ||||
1447 | \{\{(\w+)\}\} | ||||||
1448 | / | ||||||
1449 | 0 | 0 | 0 | exists $values->{$1} ? $values->{$1} : ' |
|||
1450 | /xesg; | ||||||
1451 | |||||||
1452 | 1 | 6 | return $text; | ||||
1453 | } | ||||||
1454 | |||||||
1455 | ############################################################################### | ||||||
1456 | 1; | ||||||
1457 | __END__ |