File Coverage

blib/lib/App/ZofCMS/Plugin/Captcha.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package App::ZofCMS::Plugin::Captcha;
2              
3 1     1   30403 use warnings;
  1         4  
  1         42  
4 1     1   8 use strict;
  1         2  
  1         56  
5              
6             our $VERSION = '1.001002'; # VERSION
7              
8 1     1   4 use base 'App::ZofCMS::Plugin::Base';
  1         2  
  1         1119  
9             use GD::SecurityImage;
10              
11             sub _key { 'plug_captcha' }
12             sub _defaults {
13             string => undef,
14             file => undef,
15             width => 80,
16             height => 20,
17             lines => 5,
18             particle => 0,
19             no_exit => 1,
20             style => 'rect',
21             format => 'gif',
22             tcolor => '#895533',
23             lcolor => '#000000',
24             }
25             sub _do {
26             my ( $self, $conf, $t, $q, $config ) = @_;
27              
28             my $image = GD::SecurityImage->new(
29             width => $conf->{width},
30             height => $conf->{height},
31             lines => $conf->{lines},
32             gd_font => 'giant'
33             );
34              
35             $image->random( $conf->{string} );
36             $image->create('normal', @$conf{qw/style tcolor lcolor/} );
37              
38             if ( $conf->{particle} ) {
39             $image->particle( ref $conf->{particle} ? @{ $conf->{particle} } : () );
40             }
41              
42             my ( $image_data, $mime_type, $random_number ) = $image->out( force => $conf->{format} );
43             $t->{d}{session}{captcha} = $random_number;
44              
45             if ( defined $conf->{file} and length $conf->{file} ) {
46             if ( open my $fh, '>', $conf->{file} ) {
47             binmode $fh;
48             print $fh $image_data;
49             close $fh;
50             }
51             else {
52             $t->{t}{plug_captcha_error} = $!;
53             return;
54             }
55             }
56             else {
57             binmode STDOUT;
58             print "Content-Type: image/$mime_type\n\n";
59             print $image_data;
60             exit
61             unless $conf->{no_exit};
62             }
63             }
64              
65             1;
66             __END__
67              
68             =encoding utf8
69              
70             =for stopwords RGB bots captcha captchas crypto cryptocrap runcycle runlevel subref
71              
72             =head1 NAME
73              
74             App::ZofCMS::Plugin::Captcha - plugin to utilize security images (captchas)
75              
76             =head1 SYNOPSIS
77              
78             plugins => [
79             { Session => 1000 },
80             { Captcha => 2000 },
81             ],
82             plugins2 => [
83             qw/Session/
84             ],
85              
86             plug_captcha => {},
87              
88             # Session plugin configuration (i.e. database connection is left out for brevity)
89              
90             =head1 DESCRIPTION
91              
92             The module is a plugin for L<App::ZofCMS> that provides means to generate and display
93             security images, known as "captchas" (i.e. protecting forms from bots).
94              
95             The plugin was coded with idea that you will be using L<App::ZofCMS::Plugin::Session>
96             along with it to store the generated random string; however, it's not painfully
97             necessary to use Session plugin (just easier with it).
98              
99             This documentation assumes you've read L<App::ZofCMS>, L<App::ZofCMS::Config> and L<App::ZofCMS::Template>
100              
101             =head1 FIRST-LEVEL ZofCMS TEMPLATE AND MAIN CONFIG FILE KEYS
102              
103             =head2 C<plugins>
104              
105             plugins => [
106             { Session => 1000 },
107             { Captcha => 2000 },
108             ],
109             plugins2 => [
110             qw/Session/
111             ],
112              
113             B<Mandatory>. You need to include the plugin in the list of plugins to execute. I'm using
114             Session plugin here to first load existing session and after Captcha is ran, to save
115             the session.
116              
117             =head2 C<plug_captcha>
118              
119             # all defaults
120             plug_captcha => {},
121              
122             # set all arguments
123             plug_captcha => {
124             string => 'Zoffix Znet Roxors',
125             file => 'captcha.gif',
126             width => 80,
127             height => 20,
128             lines => 5,
129             particle => 0,
130             no_exit => 1,
131             style => 'rect',
132             format => 'gif',
133             tcolor => '#895533',
134             lcolor => '#000000',
135             },
136              
137             # or set some via a subref
138             plug_captcha => sub {
139             my ( $t, $q, $config ) = @_;
140             return {
141             string => 'Zoffix Znet Roxors',
142             file => 'captcha.gif',
143             }
144             },
145              
146             B<Mandatory>. Takes either a hashref or a subref as a value. If subref is specified,
147             its return value will be assigned to C<plug_captcha> as if it was already there. If
148             sub returns an C<undef>, then plugin will stop further processing.
149             The C<@_> of the subref will
150             contain (in that order): ZofCMS Template hashref, query parameters hashref and
151             L<App::ZofCMS::Config> object. To run the plugin with all the defaults,
152             use an empty hashref. Possible keys/values for the hashref
153             are as follows:
154              
155             =head3 C<string>
156              
157             plug_captcha => {
158             string => 'Zoffix Znet Roxors',
159             },
160              
161             B<Optional>. Specifies the captcha string. Takes either a scalar string or C<undef>.
162             If set to C<undef>, the plugin will generate a random numeric string. B<Defaults to:>
163             C<undef>.
164              
165             =head3 C<file>
166              
167             plug_captcha => {
168             file => 'captcha.gif',
169             },
170              
171             B<Optional>. Takes either a scalar string or C<undef> as a value. If set to a string,
172             it represents the name of the file into which to save the captcha image (relative to
173             C<index.pl>). If set to C<undef>, plugin will output correct HTTP headers and the image
174             directly into the browser. B<Defaults to:> C<undef>.
175              
176             =head3 C<no_exit>
177              
178             plug_captcha => {
179             no_exit => 1,
180             },
181              
182             B<Optional>. This one is relevant only when C<file> (see above) is set to C<undef>.
183             Takes either true or false values. If set to a B<false value>, plugin will call
184             C<exit()> as soon as it finishes outputting the image to the browser. You'd use it
185             if you're generating your own string and are able to store it with the Session plugin
186             before Captcha plugin runs. If set to a B<true value>, plugin will not call C<exit()> and
187             the runcycle will continue; this way the Captcha plugin generated random string can
188             be stored by Session plugin later in the runlevel. B<Note:> that in this case, after the
189             image is printed the browser will also send some garbage (and by that I mean the
190             standard HTTP Content-type headers that ZofCMS prints along with whatever may be in
191             your template); even though I haven't noticed that causing any problems with the image,
192             if it does cause broken image for you, simply use L<App::ZofCMS::Plugin::Sub> and call
193             C<exit()> within it. B<Defaults to:> C<1>
194              
195             =head3 C<width>
196              
197             plug_captcha => {
198             width => 80,
199             },
200              
201             B<Optional>. Takes a positive integer as a value. Specifies captcha image's width in pixels.
202             B<Defaults to:> C<80>
203              
204             =head3 C<height>
205              
206             plug_captcha => {
207             height => 20,
208             },
209              
210             B<Optional>. Takes a positive integer as a value. Specifies captcha image's height in
211             pixels.B<Defaults to:> C<20>
212              
213             =head3 C<lines>
214              
215             plug_captcha => {
216             lines => 5,
217             },
218              
219             B<Optional>. Specifies the number of crypto-lines to generate. See L<GD::SecurityImage> for
220             more details. B<Defaults to:> C<5>
221              
222             =head3 C<particle>
223              
224             plug_captcha => {
225             particle => 0, # disable particles
226             },
227              
228             plug_captcha => {
229             particle => 1, # let plugin decide the right amount
230             },
231              
232             plug_captcha => {
233             particle => [40, 50], # set amount yourself
234             },
235              
236             B<Optional>. Takes either false values, true values or an arrayref as a value. When set to an
237             arrayref, the first element of it is density and the second one is maximum
238             number of dots to generate - these dots will add more cryptocrap to your captcha. See
239             C<particle()> method in L<GD::SecurityImage> for more details. When set to a true value
240             that is not an arrayref, L<GD::SecurityImage> will try to determine optimal number of
241             particles. When set to a false value, no extra particles will be created.
242             B<Defaults to:> C<0>
243              
244             =head3 C<style>
245              
246             plug_captcha => {
247             style => 'rect',
248             },
249              
250             B<Optional>. Specifies the cryptocrap style of captcha.
251             See L<GD::SecurityImage> C<create()> method for possible styles.
252             B<Defaults to:> C<rect>
253              
254             =head3 C<format>
255              
256             plug_captcha => {
257             format => 'gif',
258             },
259              
260             B<Optional>. Takes string C<gif>, C<jpeg> or C<png> as a value. Specifies the format
261             of the captcha image. Some formats may be unavailable depending on your L<GD> version.
262             B<Defaults to:> C<gif>
263              
264             =head3 C<tcolor>
265              
266             plug_captcha => {
267             tcolor => '#895533',
268             lcolor => '#000000',
269             },
270              
271             B<Optional>. Takes 6-digit hex RGB notation as a value. Specifies the color
272             of the text (and particles if they are on). B<Defaults to:> C<#895533>
273              
274             =head3 C<lcolor>
275              
276             plug_captcha => {
277             lcolor => '#000000',
278             },
279              
280             B<Optional>. Takes 6-digit hex RGB notation as a value. Specifies the color
281             of cryptocrap lines. B<Defaults to:> C<#000000>
282              
283             =head1 OUTPUT
284              
285             $t->{d}{session}{captcha} = 'random_number';
286              
287             $t->{t}{plug_captcha_error} = 'error message';
288              
289             Plugin will put the captcha string into C<< $t->{d}{session}{captcha} >> where
290             C<$t> is ZofCMS Template hashref. Currently there is no way to change that.
291              
292             If you're saving captcha to a file, possible I/O error message will be put into
293             C<< $t->{t}{plug_captcha_error} >> where C<$t> is ZofCMS Template hashref.
294              
295             =head1 REPOSITORY
296              
297             Fork this module on GitHub:
298             L<https://github.com/zoffixznet/App-ZofCMS-PluginBundle-Naughty>
299              
300             =head1 BUGS
301              
302             To report bugs or request features, please use
303             L<https://github.com/zoffixznet/App-ZofCMS-PluginBundle-Naughty/issues>
304              
305             If you can't access GitHub, you can email your request
306             to C<bug-App-ZofCMS-PluginBundle-Naughty at rt.cpan.org>
307              
308             =head1 AUTHOR
309              
310             Zoffix Znet <zoffix at cpan.org>
311             (L<http://zoffix.com/>, L<http://haslayout.net/>)
312              
313             =head1 LICENSE
314              
315             You can use and distribute this module under the same terms as Perl itself.
316             See the C<LICENSE> file included in this distribution for complete
317             details.
318              
319             =cut