[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
+    ]"
+ />
+ &nbsp;
+ [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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.