use
base XAO::Objects->load(
objname
=>
'Web::Page'
);
our
$VERSION
=
'2.029'
;
sub
setup ($%);
sub
field_desc ($$;$);
sub
field_names ($);
sub
display ($;%);
sub
form_ok ($%);
sub
form_phase ($);
sub
check_form ($%);
sub
pre_check_form ($%);
sub
countries_list ();
sub
us_continental_states_list ();
sub
us_states_list ();
sub
cc_list ($);
sub
cc_validate ($%);
sub
calculate_year ($$);
sub
new ($%) {
my
$proto
=
shift
;
my
$class
=
ref
(
$proto
) ||
$proto
;
my
$args
=get_args(\
@_
);
my
$self
=
$proto
->SUPER::new(
$args
);
$self
->setup_fields(
fields
=>
$args
->{
'fields'
},
values
=>
$args
->{
'values'
})
if
$args
->{
'fields'
};
$self
;
}
sub
setup ($%) {
my
$self
=
shift
;
my
$args
=get_args(\
@_
);
$self
->setup_fields(
fields
=>
$args
->{
'fields'
},
values
=>
$args
->{
'values'
},
);
my
@names
=
qw(extra_data submit_name form_ok pre_check_form check_form keep_form dont_sanitize)
;
@{
$self
}{
@names
}=@{
$args
}{
@names
};
my
$values
=
$args
->{
'values'
} || {};
foreach
my
$fdata
(@{
$self
->{
'fields'
}}) {
$fdata
->{
'value'
}=
$values
->{
$fdata
->{
'name'
}};
}
}
sub
setup_fields ($%) {
my
$self
=
shift
;
my
$args
=get_args(\
@_
);
my
$fields
=
$args
->{
'fields'
};
return
unless
$fields
&&
ref
(
$fields
);
my
$values
=
$args
->{
'values'
};
my
@copy
;
foreach
my
$fdata
(
ref
(
$fields
) eq
'ARRAY'
? @{
$fields
}
:
keys
%{
$fields
}) {
my
$name
;
if
(!
ref
(
$fdata
)) {
$name
=
$fdata
;
$fdata
=
$fields
->{
$name
};
$fdata
->{
'name'
}=
$name
;
}
else
{
$name
=
$fdata
->{
'name'
};
}
my
%cd
;
@cd
{
keys
%{
$fdata
}}=
values
%{
$fdata
};
$cd
{
'value'
}=
$values
->{
$name
}
if
$values
&&
$values
->{
$name
};
push
(
@copy
,\
%cd
);
}
$self
->{
'fields'
}=\
@copy
;
}
sub
display ($;%) {
my
$self
=
shift
;
my
$args
=get_args(\
@_
);
my
$cgi
=
$self
->cgi;
my
$fields
=
$self
->{
'fields'
};
$fields
|| throw XAO::E::DO::Web::FilloutForm
"display - has not set fields for FilloutForm"
;
my
$phase
=
$self
->{
'phase'
}=
$args
->{
'phase'
};
$self
->{
'submit_name'
}=
$args
->{
'submit_name'
}
if
$args
->{
'submit_name'
};
if
(
ref
(
$fields
) eq
'HASH'
) {
my
@newf
;
foreach
my
$name
(
keys
%{
$fields
}) {
$fields
->{
$name
}->{
'name'
}=
$name
;
push
@newf
,
$fields
->{
$name
};
}
$self
->{
'fields'
}=
$fields
=\
@newf
;
}
$self
->pre_check_form(
$args
);
my
$obj
=
$self
->object;
my
$have_cgivalues
=0;
my
$have_submit
=1;
if
(
$self
->{
'submit_name'
}) {
$have_submit
=(
$cgi
->param(
$self
->{
'submit_name'
}) ||
$cgi
->param(
$self
->{
'submit_name'
}.
'.x'
) ||
$cgi
->param(
$self
->{
'submit_name'
}.
'.y'
)
) ? 1 : 0;
$have_cgivalues
=
$have_submit
;
}
my
$errstr
;
my
%formparams
;
my
$dont_sanitize
=
$self
->{
'dont_sanitize'
} ||
$args
->{
'dont_sanitize'
};
foreach
my
$fdata
(@{
$fields
}) {
my
$name
=
$fdata
->{
'name'
};
my
$param
=
$fdata
->{
'param'
} ||
uc
(
$name
);
my
$cgivalue
=
$cgi
->param(
$name
);
$have_cgivalues
++
if
defined
(
$cgivalue
);
if
(
defined
$cgivalue
&& !
$dont_sanitize
) {
$cgivalue
=~s/[<>]/ /sg;
}
next
if
defined
(
$fdata
->{
'phase'
}) &&
$phase
<
$fdata
->{
'phase'
};
my
$value
=
$fdata
->{
'newvalue'
};
$value
=
$cgivalue
unless
defined
(
$value
);
if
(!
$have_cgivalues
) {
$value
=
$fdata
->{
'value'
}
unless
defined
(
$value
);
$value
=
$fdata
->{
'default'
}
unless
defined
(
$value
);
}
$value
=
""
unless
defined
$value
;
$value
=~s/^\s*(.*?)\s*$/$1/g;
my
$newerr
;
my
$style
=
$fdata
->{
'style'
} ||
$fdata
->{
'type'
} ||
throw
$self
"display - no style or type in field '$name'"
;
if
(!
length
(
$value
) &&
$fdata
->{
'required'
}) {
$newerr
=
$self
->Tx(
'Required field!'
);
}
elsif
(
$fdata
->{
'maxlength'
} &&
length
(
$value
) >
$fdata
->{
'maxlength'
}) {
$newerr
=
$self
->Tx(
'Value is too long!'
);
}
elsif
(
$fdata
->{
'minlength'
} &&
length
(
$value
) &&
length
(
$value
) <
$fdata
->{
'minlength'
}) {
$newerr
=
$self
->Tx(
"Value is too short!"
);
}
elsif
(
$style
eq
'text'
) {
}
elsif
(
$style
eq
'textarea'
) {
}
elsif
(
$style
eq
'file'
) {
if
(!
$value
) {
$newerr
=
$self
->Tx(
"No filename given"
);
}
}
elsif
(
$style
eq
'email'
) {
if
(
length
(
$value
) &&
$value
!~ /^[\w\.\+\/\$\%\&\`{}'=-]+\@([a-z0-9-]+\.)+[a-z]+$/i) {
$newerr
=
$self
->Tx(
"Value is not in the form of user\@host.domain!"
);
}
}
elsif
(
$style
eq
'usphone'
) {
$fdata
->{
'maxlength'
}=15
unless
$fdata
->{
'maxlength'
};
if
(
length
(
$value
)) {
$value
=~ s/\D//g;
if
(
length
(
$value
) == 7) {
$newerr
=
$self
->Tx(
"Needs area code!"
);
}
elsif
(
length
(
$value
) == 11) {
if
(
substr
(
$value
,0,1) ne
'1'
) {
$newerr
=
$self
->Tx(
"Must be a US phone!"
);
}
}
elsif
(
length
(
$value
) != 10) {
$newerr
=
$self
->Tx(
"Does not look like a right phone!"
);
}
else
{
$value
=~s/^.?(...)(...)(....)/($1) $2-$3/;
}
}
}
elsif
(
$style
eq
'phone'
) {
$fdata
->{
'maxlength'
}=30
unless
$fdata
->{
'maxlength'
};
if
(
length
(
$value
)) {
my
(
$p
,
$e
)=
split
(/[a-zA-Z]+/,
$value
);
$p
=~s/\D//g;
$e
||=
''
;
$e
=~s/\D//g;
if
(
length
(
$p
)<10) {
$newerr
=
$self
->Tx(
"Needs area code!"
);
}
elsif
(
length
(
$p
)==10) {
$p
=
'1'
.
$p
;
}
elsif
(
length
(
$p
)>13) {
$newerr
=
$self
->Tx(
"Too many digits!"
);
}
if
(!
$newerr
) {
(
$value
=
$p
)=~s/^(.+)(...)(...)(....)$/+$1 ($2) $3-$4/;
$value
.=
" ext. $e"
if
$e
;
}
}
}
elsif
(
$style
eq
'int'
||
$style
eq
'integer'
||
$style
eq
'number'
) {
if
(
length
(
$value
)) {
if
(
$value
=~ /^-?[\d,']+$/) {
$value
=~s/[,']+//g;
if
(
defined
(
$fdata
->{
'minvalue'
}) &&
$value
<
$fdata
->{
'minvalue'
}) {
$newerr
=
$self
->Tx(
"Value is less than {{min}}"
,
{
min
=>
$fdata
->{
'minvalue'
} });
}
if
(
defined
(
$fdata
->{
'maxvalue'
}) &&
$value
>
$fdata
->{
'maxvalue'
}) {
$newerr
=
$self
->Tx(
"Value is greater than {{max}}"
,
{
max
=>
$fdata
->{
'maxvalue'
} });
}
}
else
{
$newerr
=
$self
->Tx(
"Is not an integer!"
);
}
}
}
elsif
(
$style
eq
'real'
) {
if
(
length
(
$value
)) {
if
(
$value
=~ /^-?[\d,'\.]+$/) {
$value
=~s/[,']+//g;
if
(
defined
(
$fdata
->{
'minvalue'
}) &&
$value
<
$fdata
->{
'minvalue'
}) {
$newerr
=
$self
->Tx(
"Value is less than {{min}}"
,
{
min
=>
$fdata
->{
'minvalue'
} });
}
if
(
defined
(
$fdata
->{
'maxvalue'
}) &&
$value
>
$fdata
->{
'maxvalue'
}) {
$newerr
=
$self
->Tx(
"Value is greater than {{max}}"
,
{
max
=>
$fdata
->{
'maxvalue'
} });
}
}
else
{
$newerr
=
$self
->Tx(
"Is not a number!"
);
}
}
}
elsif
(
$style
eq
'password'
) {
if
(
length
(
$value
) &&
$fdata
->{
'pair'
} &&
$value
ne
$cgi
->param(
$fdata
->{
'pair'
})) {
$newerr
=
$self
->Tx(
"Does not match the copy!"
);
}
}
elsif
(
$style
eq
'country'
) {
my
@cl
=
$self
->countries_list();
my
$match
=0;
foreach
my
$c
(
@cl
) {
$match
=
lc
(
$c
) eq
lc
(
$value
);
last
if
$match
;
}
if
(
length
(
$value
) && !
$match
) {
$newerr
=
$self
->Tx(
"Unknown country"
);
}
}
elsif
(
$style
eq
'usstate'
||
$style
eq
'uscontst'
) {
my
@cl
=
$style
eq
'usstate'
?
$self
->us_states_list()
:
$self
->us_continental_states_list();
my
$match
=0;
my
$sv
=
substr
(
$value
||
''
,0,2);
foreach
my
$c
(
@cl
) {
$match
=
lc
(
substr
(
$c
,0,2)) eq
lc
(
$sv
);
last
if
$match
;
}
if
(
length
(
$value
) && !
$match
) {
$newerr
=
$self
->Tx(
"Unknown state"
);
}
}
elsif
(
$style
eq
'cctype'
) {
my
@cl
=
$self
->cc_list();
my
$match
=0;
foreach
my
$c
(
@cl
) {
$match
=
lc
(
$c
) eq
lc
(
$value
);
last
if
$match
;
}
if
(
length
(
$value
) && !
$match
) {
$newerr
=
$self
->Tx(
"Unknown credit card type"
);
}
}
elsif
(
$style
eq
'ccnum'
) {
if
(
length
(
$value
)) {
my
$type
=
$fdata
->{
'pair'
} ?
$cgi
->param(
$fdata
->{
'pair'
}) :
''
;
$newerr
=
$self
->cc_validate(
type
=>
$type
,
number
=>
$value
,
validated
=> \
$value
);
}
}
elsif
(
$style
eq
'month'
) {
if
(
length
(
$value
)) {
$value
=
int
(
$value
);
if
(
$value
<1 ||
$value
>12) {
$newerr
=
$self
->Tx(
'Invalid month!'
);
}
}
}
elsif
(
$style
eq
'year'
) {
if
(
$fdata
->{
'minyear'
} &&
$fdata
->{
'maxyear'
}) {
my
$minyear
=
$self
->calculate_year(
$fdata
->{
'minyear'
});
my
$maxyear
=
$self
->calculate_year(
$fdata
->{
'maxyear'
});
if
(
length
(
$value
)) {
$value
=
$self
->calculate_year(
$value
);
if
(
$value
<
$minyear
) {
$newerr
=
$self
->Tx(
"Must be after {{year}}"
,
{
year
=>
$minyear
});
}
elsif
(
$value
>
$maxyear
) {
$newerr
=
$self
->Tx(
"Must be before {{year}}"
,
{
year
=>
$maxyear
});
}
}
}
elsif
(
length
(
$value
)) {
$value
=
$self
->calculate_year(
$value
);
if
(
$value
<1900 ||
$value
>2099) {
$newerr
=
$self
->Tx(
'Invalid year!'
);
}
}
}
elsif
(
$style
eq
'checkbox'
) {
if
(
$have_cgivalues
) {
$value
=(
defined
$fdata
->{
'newvalue'
} ?
$fdata
->{
'newvalue'
} :
$cgivalue
) ? 1 : 0;
}
else
{
$value
=(
defined
(
$fdata
->{
'value'
}) ?
$fdata
->{
'value'
} :
$fdata
->{
'default'
}) ? 1 : 0;
}
}
elsif
(
$style
eq
'selection'
) {
if
(
length
(
$value
)) {
my
$opt
=
$fdata
->{
'options'
};
if
(
ref
(
$opt
) eq
'HASH'
) {
if
(!
defined
$opt
->{
$value
}) {
$newerr
=
$self
->Tx(
'Bad option value!'
);
}
}
elsif
(
ref
(
$opt
) eq
'ARRAY'
) {
my
$found
;
for
(
my
$i
=0;
$i
<
@$opt
;
$i
+=2) {
next
unless
defined
(
$opt
->[
$i
+1]);
if
(
$opt
->[
$i
] eq
$value
) {
$found
=1;
last
;
}
}
if
(!
$found
) {
$newerr
=
$self
->Tx(
'Bad option value!'
);
}
}
else
{
$newerr
=
$self
->Tx(
'Unknown data in options!'
);
}
}
}
else
{
$self
->throw(
"display - unknown style '$style'"
);
}
if
(
$newerr
&& (!
$have_submit
|| !
$have_cgivalues
)) {
$newerr
=
''
;
}
if
(
$newerr
) {
$errstr
.=(
$fdata
->{
'text'
} ||
$name
) .
": "
.
$newerr
.
"<br />\n"
;
$fdata
->{
'errstr'
}=
$newerr
;
}
else
{
$fdata
->{
'value'
}=
$value
;
}
$fdata
->{
'rawvalue'
}=
$value
;
$formparams
{
"$param.VALUE"
}=
defined
(
$value
) ?
$value
:
""
;
$formparams
{
"$param.TEXT"
}=
$fdata
->{
'text'
} ||
$name
;
$formparams
{
"$param.NAME"
}=
$name
;
$formparams
{
"$param.REQUIRED"
}=
$fdata
->{
'required'
} ? 1 : 0;
$formparams
{
"$param.SIZE"
}=
$fdata
->{
'size'
} || 30;
$formparams
{
"$param.ROWS"
}=
$fdata
->{
'rows'
} || 1;
$formparams
{
"$param.MAXLENGTH"
}=
$fdata
->{
'maxlength'
} || 100;
$formparams
{
"$param.MINLENGTH"
}=
$fdata
->{
'minlength'
} || 0;
$formparams
{
"$param.ERRSTR"
}=
$fdata
->{
'errstr'
} ||
''
;
}
if
(
$have_submit
&&
$have_cgivalues
&& !
$errstr
) {
my
@rc
=
$self
->check_form(merge_refs(
$args
,\
%formparams
));
if
(
@rc
<2) {
$formparams
{
"ERRSTR.CHECK_FORM"
}=
$errstr
=(
$rc
[0] ||
''
);
}
elsif
(
scalar
(
@rc
)%2 == 0) {
for
(
my
$i
=0;
$i
<
@rc
;
$i
+=2) {
my
$e
=(
$rc
[
$i
] ||
''
);
next
unless
$e
;
my
$fname
=
$rc
[
$i
+1];
if
(
$fname
) {
my
$fdata
=
$self
->field_desc(
$fname
);
my
$param
=
$fdata
->{
'param'
} ||
uc
(
$fdata
->{
'name'
});
if
(
$fdata
->{
'errstr'
}) {
$fdata
->{
'errstr'
}.=(
$fdata
->{
'errstr'
} =~ /\.\s*$/ ?
' '
:
'; '
) .
$e
;
$formparams
{
"$param.ERRSTR"
}=
$fdata
->{
'errstr'
};
}
else
{
$fdata
->{
'errstr'
}=
$formparams
{
"$param.ERRSTR"
}=
$e
;
}
$errstr
.=
"\n<br />"
if
$errstr
;
$errstr
.=
$e
;
}
else
{
$errstr
.=
"\n<br />"
if
$errstr
;
$formparams
{
'ERRSTR.CHECK_FORM'
}.=
"\n<br />"
if
$errstr
;
$errstr
.=
$e
;
$formparams
{
'ERRSTR.CHECK_FORM'
}.=
$e
;
}
}
}
else
{
throw
$self
"display - wrong number of results ("
.
join
(
'|'
,
@rc
).
")"
;
}
}
$formparams
{
"ERRSTR.CHECK_FORM"
}||=
''
;
if
(!
$have_submit
|| !
$have_cgivalues
) {
$errstr
=
''
;
foreach
my
$fdata
(@{
$fields
}) {
my
$param
=
$fdata
->{
'param'
} ||
uc
(
$fdata
->{
'name'
});
$formparams
{
"$param.ERRSTR"
}=
''
;
}
}
foreach
my
$fdata
(@{
$fields
}) {
my
$name
=
$fdata
->{
'name'
};
my
$param
=
$fdata
->{
'param'
} ||
uc
(
$name
);
my
$value
=
$fdata
->{
'rawvalue'
};
my
$style
=
$fdata
->{
'style'
} ||
$fdata
->{
'type'
} ||
throw
$self
"- no style or type in field '$name'"
;
my
$seloptions
;
my
$selcompare
;
if
(
$style
eq
'country'
) {
my
@cl
=
$self
->countries_list();
$seloptions
=[
''
=>
'Select Country'
,
(
map
{
$_
=>
$_
}
@cl
),
];
$selcompare
=
sub
{
return
uc
(
$_
[0]) eq
uc
(
$_
[1]) };
}
elsif
(
$style
eq
'usstate'
||
$style
eq
'uscontst'
) {
my
@cl
=
$style
eq
'usstate'
?
$self
->us_states_list()
:
$self
->us_continental_states_list();
$seloptions
=[
''
=>
'Select State'
,
(
map
{
uc
(
substr
(
$_
,0,2)) =>
$_
}
@cl
),
];
$selcompare
=
sub
{
return
uc
(
$_
[0]) eq
uc
(
$_
[1]) };
}
elsif
(
$style
eq
'cctype'
) {
my
@cl
=
$self
->cc_list();
$seloptions
=[
''
=>
'Select Card Type'
,
(
map
{
$_
=>
$_
}
@cl
),
];
$selcompare
=
sub
{
return
uc
(
$_
[0]) eq
uc
(
$_
[1]) };
}
elsif
(
$style
eq
'month'
) {
my
@cl
=
qw(January February March April May June July
August September October November December)
;
$seloptions
=[
''
=>
'Select Month'
,
(
map
{
sprintf
(
'%02u'
,
$_
) =>
sprintf
(
'%02u - %s'
,
$_
,
$cl
[
$_
-1]) } (1..12)),
];
$selcompare
=
sub
{
return
defined
$_
[0] &&
length
$_
[0] &&
length
$_
[1] &&
$_
[0] ==
$_
[1] };
}
elsif
(
$style
eq
'year'
&& !
$fdata
->{
'maxlength'
} &&
$fdata
->{
'minyear'
} &&
$fdata
->{
'maxyear'
}) {
my
$minyear
=
$self
->calculate_year(
$fdata
->{
'minyear'
});
my
$maxyear
=
$self
->calculate_year(
$fdata
->{
'maxyear'
});
$seloptions
=[
''
=>
'Select Year'
,
(
map
{
sprintf
(
'%04u'
,
$_
) =>
sprintf
(
'%04u'
,
$_
) } (
$minyear
..
$maxyear
)),
];
$selcompare
=
sub
{
return
defined
$_
[0] &&
length
$_
[0] &&
length
$_
[1] &&
$_
[0] ==
$_
[1] };
}
elsif
(
$style
eq
'checkbox'
) {
$fdata
->{
'html'
}=
$obj
->expand(
path
=>
'/bits/fillout-form/html-checkbox'
,
NAME
=>
$name
,
VALUE
=>
$fdata
->{
'value'
} ||
''
,
CHECKED
=>
$value
?
' checked '
:
''
,
HTMLID
=>
$fdata
->{
'htmlid'
} ||
$name
,
ERRSTR
=>
$fdata
->{
'errstr'
} //
''
,
);
}
elsif
(
$style
eq
'selection'
) {
$seloptions
=
$fdata
->{
'options'
} ||
$self
->throw(
"display - no 'options' for '$name' selection"
);
}
elsif
(
$style
eq
'text'
||
$style
eq
'phone'
||
$style
eq
'usphone'
||
$style
eq
'ccnum'
||
$style
eq
'email'
||
$style
eq
'year'
||
$style
eq
'number'
||
$style
eq
'int'
||
$style
eq
'integer'
||
$style
eq
'real'
) {
$fdata
->{
'html'
}=
$obj
->expand(
path
=>
'/bits/fillout-form/html-text'
,
NAME
=>
$name
,
VALUE
=>
$value
//
''
,
MAXLENGTH
=>
$fdata
->{
'maxlength'
} || 100,
SIZE
=>
$fdata
->{
'size'
} || 30,
ERRSTR
=>
$fdata
->{
'errstr'
} //
''
,
);
}
elsif
(
$style
eq
'textarea'
) {
$fdata
->{
'html'
}=
$obj
->expand(
path
=>
'/bits/fillout-form/html-textarea'
,
NAME
=>
$name
,
VALUE
=>
$value
//
''
,
SIZE
=>
$fdata
->{
'size'
} || 30,
ROWS
=>
$fdata
->{
'rows'
} || 8,
ERRSTR
=>
$fdata
->{
'errstr'
} //
''
,
);
}
elsif
(
$style
eq
'file'
) {
$fdata
->{
'html'
}=
$obj
->expand(
path
=>
'/bits/fillout-form/html-file'
,
NAME
=>
$name
,
SIZE
=>
$fdata
->{
'size'
} || 30,
ERRSTR
=>
$fdata
->{
'errstr'
} //
''
,
);
}
elsif
(
$style
eq
'password'
) {
$fdata
->{
'html'
}=
$obj
->expand(
path
=>
'/bits/fillout-form/html-password'
,
NAME
=>
$name
,
VALUE
=>
$value
//
''
,
MAXLENGTH
=>
$fdata
->{
'maxlength'
} || 100,
SIZE
=>
$fdata
->{
'size'
} || 30,
ERRSTR
=>
$fdata
->{
'errstr'
} //
''
,
);
}
if
(
$seloptions
) {
my
$has_empty
;
my
$used_selected
;
my
$html
=
''
;
my
$html_sub
=
sub
{
my
(
$v
,
$t
)=
@_
;
$has_empty
=1
if
!
defined
(
$v
) || !
length
(
$v
);
return
unless
defined
(
$t
);
my
$sel
=
''
;
if
(!
$used_selected
) {
my
$equal
=
$selcompare
?
$selcompare
->(
$v
,
$value
) : (
$v
eq
$value
);
if
(
$equal
) {
$sel
=
' selected'
;
$used_selected
=1;
}
}
$html
.=
$obj
->expand(
path
=>
'/bits/fillout-form/html-select-option'
,
NAME
=>
$name
,
VALUE
=>
$v
,
TEXT
=>
$t
,
SELECTED
=>
$sel
,
);
$formparams
{
"$param.RV_CURRENT_$v"
}=
$sel
? 1 : 0;
$formparams
{
"$param.RV_VALUE_$v"
}=
$v
;
$formparams
{
"$param.RV_TEXT_$v"
}=
$t
;
};
if
(
ref
(
$seloptions
) eq
'HASH'
) {
foreach
my
$v
(
sort
{
$seloptions
->{
$a
} cmp
$seloptions
->{
$b
} }
keys
%$seloptions
) {
&{
$html_sub
}(
$v
,
$seloptions
->{
$v
});
}
}
elsif
(
ref
(
$seloptions
) eq
'ARRAY'
) {
for
(
my
$i
=0;
$i
<
@$seloptions
;
$i
+=2) {
&{
$html_sub
}(
$seloptions
->[
$i
],
$seloptions
->[
$i
+1]);
}
}
else
{
throw
$self
"Unknown data type in 'options' name=$name"
;
};
$formparams
{
"$param.HTML_OPTIONS"
}=
$html
;
if
(!
$has_empty
) {
$html
=
'<option value="">'
.
t2ht(
$self
->Tx(
'Please select'
)) .
'</option>'
.
$html
;
}
$fdata
->{
'html'
}=
$obj
->expand(
path
=>
'/bits/fillout-form/html-select'
,
NAME
=>
$name
,
VALUE
=>
$value
//
''
,
OPTIONS
=>
$html
,
ERRSTR
=>
$fdata
->{
'errstr'
},
);
}
$formparams
{
"$param.HTML"
}=
$fdata
->{
'html'
} ||
""
;
}
my
$keep_form
=
$self
->{
'keep_form'
};
if
(!
$have_submit
|| !
$have_cgivalues
||
$errstr
||
$keep_form
) {
my
$eh
;
my
$et
;
if
(
$errstr
&&
$have_cgivalues
) {
$eh
=
$obj
->expand(
path
=>
'/bits/fillout-form/errstr'
,
ERRSTR
=>
$errstr
,
'ERRSTR.CHECK_FORM'
=>
$formparams
{
"ERRSTR.CHECK_FORM"
},
);
$et
=
$errstr
;
}
$obj
->display(
$args
,\
%formparams
,{
path
=>
$args
->{
'form.path'
},
template
=>
$args
->{
'form.template'
},
ERRSTR
=>
$et
||
''
,
'ERRSTR.HTML'
=>
$eh
||
''
,
});
return
unless
$keep_form
&& !
$errstr
&&
$have_cgivalues
&&
$have_submit
;
}
$self
->form_ok(merge_refs(
$args
,\
%formparams
));
}
sub
field_desc ($$;$) {
my
(
$self
,
$name
,
$soft_failure
)=
@_
;
my
$fields
=
$self
->{
'fields'
} ||
throw
$self
"field_desc - has not set fields for FilloutForm"
;
if
(
ref
(
$fields
) eq
'ARRAY'
) {
foreach
my
$fdata
(@{
$fields
}) {
return
$fdata
if
$fdata
->{
'name'
} eq
$name
;
}
}
else
{
return
$fields
->{
$name
}
if
$fields
->{
$name
};
}
return
undef
if
$soft_failure
;
throw
$self
"field_desc - unknown field '$name' referred"
;
}
sub
field_names ($) {
my
$self
=
shift
;
my
$fields
=
$self
->{
'fields'
} ||
throw
$self
"field_names - has not set fields for FilloutForm"
;
if
(
ref
(
$fields
) eq
'ARRAY'
) {
return
map
{
$_
->{
'name'
} }
@$fields
;
}
else
{
return
map
{
$_
->{
'name'
} }
keys
%$fields
;
}
}
sub
form_ok ($%) {
my
$self
=
shift
;
if
(
$self
->{
'form_ok'
}) {
my
$na
=merge_refs(get_args(\
@_
),{
extra_data
=>
$self
->{
'extra_data'
},
});
return
&{
$self
->{
'form_ok'
}}(
$self
,
$na
);
}
throw
$self
'form_ok - must be overriden in derived class or using form_ok parameter'
;
}
sub
check_form ($%) {
my
$self
=
shift
;
if
(
$self
->{
'check_form'
}) {
my
%na
=%{get_args(\
@_
)};
$na
{
'extra_data'
}=
$self
->{
'extra_data'
};
return
&{
$self
->{
'check_form'
}}(
$self
,\
%na
);
}
''
;
}
sub
pre_check_form ($%) {
my
$self
=
shift
;
if
(
$self
->{
'pre_check_form'
}) {
my
$na
=get_args(\
@_
);
$na
->{
'extra_data'
}=
$self
->{
'extra_data'
};
return
&{
$self
->{
'pre_check_form'
}}(
$self
,
$na
);
}
}
sub
countries_list () {
split
(/\n/,
<<'END_OF_LIST');
United States
Afghanistan
Albania
Algeria
American Samoa
Andorra
Angola
Anguilla
Antarctica
Antigua
Antilles
Arab Emirates
Argentina
Armenia
Aruba
Australia
Austria
Azerbaidjan
Bahamas
Bahrain
Bangladesh
Barbados
Barbuda
Belarus
Belgium
Belize
Benin
Bermuda
Bhutan
Bolivia
Bosnia Herz.
Botswana
Bouvet Isl.
Brazil
Brunei Dar.
Bulgaria
Burkina Faso
Burundi
C. African Rep.
Cambodia
Cameroon
Cambodia
Cameroon
Canada
Cape Verde
Cayman Islands
Chad
Chile
China
Christmas Isl.
Cocos Islands
Colombia
Comoros
Congo
Cook Islands
Costa Rica
Croatia
Cuba
Cyprus
Czech Republic
Denmark
Djibouti
Dominica
Dominican Rep.
East Timor
Ecuador
Egypt
England
El Salvador
Equat. Guinea
Eritrea
Estonia
Ethiopia
Falkland Isl.
Faroe Islands
Fiji
Finland
Former Czech.
Former USSR
France
French Guyana
French S. Terr.
Gabon
Gambia
Georgia
Germany
Ghana
Gibraltar
Great Britain
Greece
Greenland
Grenada
Guadeloupe
Grenada
Guadeloupe
Guam (USA)
Guatemala
Guinea
Guinea Bissau
Guyana
Haiti
Heard/McDonald
Honduras
Hong Kong
Hungary
Iceland
India
Indonesia
Iran
Iraq
Ireland
Israel
Italy
Ivory Coast
Jamaica
Japan
Jordan
Kazakhstan
Kenya
Kiribati
Kuwait
Kyrgyzstan
Laos
Latvia
Lebanon
Lesotho
Liberia
Libya
Liechtenstein
Lithuania
Luxembourg
Macau
Macedonia
Madagascar
Malawi
Malaysia
Maldives
Mali
Malta
Marshall Isl.
Martinique
Mauritania
Mauritius
Mayotte
Mexico
Mayotte
Mexico
Micronesia
Moldavia
Monaco
Mongolia
Montserrat
Morocco
Mozambique
Myanmar
N. Mariana Isl.
Namibia
Nauru
Nepal
Netherlands
Neutral Zone
New Caledonia
New Zealand
Nicaragua
Niger
Nigeria
Niue
Norfolk Island
Northern Ireland
North Korea
Norway
Oman
Pakistan
Palau
Panama
Papua New Guinea
Paraguay
Peru
Philippines
Pitcairn Isl.
Poland
Polynesia
Portugal
Puerto Rico
Qatar
Reunion
Romania
Russia
Rwanda
Samoa
San Marino
Saudi Arabia
Scotland
Senegal
Seychelles
Sierra Leone
Singapore
Sierra Leone
Singapore
Slovak Rep.
Slovenia
Solomon Isl.
Somalia
South Africa
South Korea
Spain
Sri Lanka
St Helena
St Lucia
St Pierre
St Tome
St Vincent
Sudan
Suriname
Swaziland
Sweden
Switzerland
Syrian Arab Republic
Tadjikistan
Taiwan
Tanzania
Thailand
Tobago
Togo
Tokelau
Tonga
Trinidad & Tobago
Tunisia
Turopaque
Turkmenistan
Turks/Caicos Isl.
Tuvalu
Uganda
Ukraine
Uruguay
Uzbekistan
Vanuatu
Vatican City
Venezuela
Vietnam
Virg.Isl. (UK)
Virg.Isl. (US)
Wales
Western Sahara
Yemen
Yugoslavia
Zaire
Zambia
Zimbabwe
END_OF_LIST
}
sub
us_continental_states_list () {
my
$self
=
shift
;
my
@list
;
foreach
my
$st
(
$self
->us_states_list) {
next
if
$st
=~ /^AK/;
next
if
$st
=~ /^AS/;
next
if
$st
=~ /^FM/;
next
if
$st
=~ /^GU/;
next
if
$st
=~ /^HI/;
next
if
$st
=~ /^MH/;
next
if
$st
=~ /^MP/;
next
if
$st
=~ /^VI/;
push
(
@list
,
$st
);
}
@list
;
}
sub
us_states_list () {
split
(/\n/,
<<'END_OF_LIST');
AL - Alabama
AK - Alaska
AS - American Samoa
AZ - Arizona
AR - Arkansas
CA - California
CO - Colorado
CT - Connecticut
DE - Delaware
DC - District Of Columbia
FM - Federated States Of Micronesia
FL - Florida
GA - Georgia
GU - Guam
HI - Hawaii
ID - Idaho
IL - Illinois
IN - Indiana
IA - Iowa
KS - Kansas
KY - Kentucky
LA - Louisiana
ME - Maine
MH - Marshall Islands
MD - Maryland
MA - Massachusetts
MI - Michigan
MN - Minnesota
MS - Mississippi
MO - Missouri
MT - Montana
NE - Nebraska
NV - Nevada
NH - New Hampshire
NJ - New Jersey
NM - New Mexico
NY - New York
NC - North Carolina
ND - North Dakota
MP - Northern Mariana Islands
OH - Ohio
OK - Oklahoma
OR - Oregon
PW - Palau
PA - Pennsylvania
PR - Puerto Rico
RI - Rhode Island
SC - South Carolina
SD - South Dakota
TN - Tennessee
TX - Texas
UT - Utah
VT - Vermont
VI - Virgin Islands
VA - Virginia
WA - Washington
WV - West Virginia
WI - Wisconsin
WY - Wyoming
END_OF_LIST
}
sub
cc_list ($) {
split
(/\n/,
<<'END_OF_LIST');
Visa
American Express
MasterCard
Discover
Diner's Club
END_OF_LIST
}
sub
cc_validate ($%) {
my
$self
=
shift
;
my
$args
=get_args(\
@_
);
my
$number
=
$args
->{
'number'
};
my
$type
=
$args
->{
'type'
};
$number
=~s/\D//g;
if
(
length
(
$number
)<13) {
return
$self
->Tx(
'Number is too short!'
);
}
my
$sum
=0;
for
(
my
$i
=0;
$i
!=
length
(
$number
)-1;
$i
++) {
my
$weight
=
substr
(
$number
, -1 * (
$i
+ 2), 1) * (2 - (
$i
% 2));
$sum
+= ((
$weight
< 10) ?
$weight
: (
$weight
- 9));
}
if
(
substr
(
$number
,-1) ne (10-
$sum
%10)%10) {
return
$self
->Tx(
'Invalid number!'
);
}
my
$typecode
;
my
$realtype
=
''
;
my
$reqlen
;
if
(
$number
=~ /^(?:34|37)/) {
$realtype
=
'american express'
;
$typecode
=
'AE'
;
$reqlen
=[15];
}
elsif
(
$number
=~ /^4/) {
$realtype
=
'visa'
;
$typecode
=
'VI'
;
$reqlen
=[13,16];
}
elsif
(
$number
=~ /^5/) {
$realtype
=
'master\s?card'
;
$typecode
=
'MC'
;
$reqlen
=[16];
}
elsif
(
$number
=~ /^6/) {
$realtype
=
'discover'
;
$typecode
=
'DC'
;
$reqlen
=[16];
}
else
{
return
$self
->Tx(
'Unknown card type!'
);
}
if
(
$reqlen
) {
scalar
(
grep
{
length
(
$number
)==
$_
}
@$reqlen
) ||
return
$self
->Tx(
'Invalid number length!'
);
}
if
(
$type
&&
lc
(
$type
) !~
$realtype
) {
return
$self
->Tx(
'Number does not match card type!'
);
}
${
$args
->{
'validated'
}}=
$number
if
$args
->{
'validated'
};
${
$args
->{
'typecode'
}}=
$typecode
if
$args
->{
'typecode'
};
return
''
;
}
sub
calculate_year ($$) {
my
$self
=
shift
;
my
$year
=
shift
;
if
(
substr
(
$year
,0,1) eq
'+'
) {
$year
=(
localtime
)[5]+1900+
substr
(
$year
,1);
}
elsif
(
substr
(
$year
,0,1) eq
'-'
) {
$year
=(
localtime
)[5]+1900-
substr
(
$year
,1);
}
elsif
(
$year
< 20) {
$year
+=2000;
}
elsif
(
$year
< 100) {
$year
+=1900;
}
$year
;
}
sub
form_phase ($) {
my
$self
=
shift
;
return
$self
->{
'phase'
} || 1;
}
sub
Tx ($$;$) {
my
$self
=
shift
;
my
$text
=
shift
;
my
$values
=
shift
|| { };
if
(
$self
->can(
'Tx_translate'
)) {
$text
=
$self
->Tx_translate(
$text
,
$values
);
}
$text
=~s/
\{\{(\w+)\}\}
/
exists
$values
->{$1} ?
$values
->{$1} :
'<UNDEF>'
/xesg;
return
$text
;
}
1;