[interchange] captcha refresh
Mark Johnson <[email protected]>
| Newsgroups | gmane.comp.web.interchange.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit 5a1ba34afdfb5623c83aacd1e4ed116421a4bd54 Author: Mark Johnson <[email protected]> Date: Mon Dec 10 14:12:31 2012 -0500 captcha refresh Optional global config to pull in that creates the [captcha-refresh] tag to ask for a new captcha image if it can't be read. code/SystemTag/captcha.coretag | 3 + eg/captcha_refresh.cfg | 171 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 0 deletions(-) --- diff --git a/code/SystemTag/captcha.coretag b/code/SystemTag/captcha.coretag index 8d7f459..47807fb 100644 --- a/code/SystemTag/captcha.coretag +++ b/code/SystemTag/captcha.coretag @@ -96,6 +96,9 @@ sub { } } else { + # Used for [captcha-refresh] if requested + $::Instance->{last_captcha_build_opt} = { %$opt }; + my $save_u = umask($::Variable->{CAPTCHA_UMASK} || 2); if($opt->{reset}) { diff --git a/eg/captcha_refresh.cfg b/eg/captcha_refresh.cfg new file mode 100644 index 0000000..f3cb318 --- /dev/null +++ b/eg/captcha_refresh.cfg @@ -0,0 +1,171 @@ +# captcha refresh: Provide a refresh feature to use in conjunction with the +# stock [captcha] tag by Mark Johnson <mark(at)endpoint(dot)com> +# +# To use: +# +# 1. Put this in, or include from, interchange.cfg and restart. +# +# 2. Place call to [captcha-refresh] where you would like to see the +# refresh link appear. See documentation within usertag defintion below. +# +# 3. The captcha-refresh process couples tag and actionmap definitions. +# Ensure there is no conflict with the actionmap name and any existing +# custom maps for your implementation. + +UserTag captcha-refresh addAttr +UserTag captcha-refresh Routine <<EOR +use 5.10.0; +sub { + my $opt = shift; + my %cache = %{ + delete ($opt->{use_last}) && $::Instance->{last_captcha_build_opt} || {} + }; + + my $anc = delete ($opt->{anchor}) || 'refresh image'; + my $img_id = delete $opt->{img_id}; + my $js_func_name = delete ($opt->{js_func_name}) || 'captcha_refresh'; + + my @uri = (delete ($opt->{am}) || 'captcha-refresh'); + + my %unq_keys; + @unq_keys{ keys %cache, keys %$opt } = (); + push (@uri, + join ( + '=', + ($_, $::Tag->filter(urlencode => ($opt->{$_} // $cache{$_} // ''))) + ) + ) + for keys %unq_keys; + + my $url = $::Tag->area({ href => join ('/', @uri) }); + + my $script = qq{ + <a href="#captcha" onclick="$js_func_name()">$anc</a> + <script> + function $js_func_name() { + var ajax = new XMLHttpRequest(); + + ajax.onreadystatechange = function() { + if (ajax.readyState == 4 && ajax.status == 200) { + document.getElementById('$img_id').src = ajax.responseText; + } + } + + ajax.open('GET','$url',true); + ajax.send(); + return; + } + </script> + }; + + return $script; +} +EOR + +CodeDef captcha-refresh ActionMap +CodeDef captcha-refresh Routine <<EOR +sub { + my (undef, %opt) = split (m{[/=]+}, shift); + $_ = $::Tag->filter(urldecode => $_) + for values %opt; + + # Always name_only since we're updating the img's src param + $opt{name_only} = 1; + + my $doc = Vend::Document->new; + $doc->hot(1); + $doc->write($::Tag->captcha(\%opt)); + return 0; +} +EOR + +UserTag captcha-refresh Documentation <<EOD +=head1 NAME + +Captcha refresh + +=head1 DESCRIPTION + +Given a call to [captcha] to generate a check image, place a subsequent call +to [captcha-refresh] where you would like to insert a hyperlink to refresh the +image. The call will bundle the necessary parameters to duplicate the +appropriate call to [captcha] into an AJAX GET back to the complementary +captcha-refresh actionmap. The actionmap will build the new image and return +the new URL to the image, to which the original <img> tag's src field will be +set. + +As long as the [captcha-refresh] call is processed after the most recent call +to [captcha] itself, the calling parameters for the latter call can be easily +tied to the refresh request and not need to be duplicated. The calling order +can always be enforced via the use of [output] or, if simpler, using scratch +to store the [captcha] results and display later in the page. + +=over 4 + +=item B<img_id> (required) + +The refresh code needs to be able to reference the original image so that the +newly formed captcha image can overwrite the previous, discarded one. Thus, +your captcha image must include an "id" attribute in the <img> tag, and that +value must be included in this param. + +=item B<use_last> + +When true, the code will pull in the attribute list of the last non-check call +to [captcha]. In order to refresh the image under the same terms as the +original, the code needs access to the calling params used. These can either +be duplicated in the call to [captcha-refresh] or referenced via B<use_last> + +=item B<anchor> + +Value to use for the link itself. Defaults to 'refresh image'. To use an +image, supply the entire <img> tag. + +=item B<am> + +Alternate actionmap name to use to refresh the captcha image. Default is +'captcha-refresh' and is included in the .cfg build file for this tag. + +=item B<js_func_name> + +Name of javascript function built from this tag to handle the refresh request +and image update. Default is 'captcha_refresh'. Should only need to change if +there is a conflict with an existing JS function. + +=back + +You can also provide any of the options defined for [captcha] itself, which +will be necessary without use of the B<use_last> option. If B<use_last> and +explicit [captcha] options are combined, options set in [captcha-refresh] will +override those derived from the B<use_last> call. + +=head1 EXAMPLE + + <form action="[area @@MV_PAGE@@]" method="post"> + ... + <input name="mv_captcha_guess" size="6" autocomplete="off" /> + <img + id="captcha_image" + style="vertical-align: middle" + src="[captcha + function=image + length=6 + image_location=captcha + image_path=/images/captcha + name_only=1 + ]" + /> + + [captcha-refresh + img_id=captcha_image + use_last=1 + ] + ... + <input type="submit" value="Submit" /> + +=head1 AUTHOR + +Mark Johnson <mark(at)endpoint(dot)com> + +=cut +EOD