This file is indexed.

/usr/share/perl5/CGI/Application/Plugin/CAPTCHA.pm is in libcgi-application-plugin-captcha-perl 0.04-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
package CGI::Application::Plugin::CAPTCHA;

use strict;

use GD::SecurityImage;
use Digest::SHA;
use vars qw($VERSION @EXPORT);

require Exporter;

@EXPORT = qw(
    captcha_config
    captcha_create
    captcha_verify
);

sub import { goto &Exporter::import }

=head1 NAME

CGI::Application::Plugin::CAPTCHA - Easily create, use, and verify CAPTCHAs in
CGI::Application-based web applications.

=head1 VERSION

Version 0.04

=cut

$VERSION = '0.04';

=head1 SYNOPSIS

    # In your CGI::Application-based web application module. . .
    use CGI::Application::Plugin::CAPTCHA;

    sub setup
    {
        my $self = shift;

        $self->run_modes([ qw/
            create
            # Your other run modes go here
        /]);

        $self->captcha_config(
            IMAGE_OPTIONS    => {
                width    => 150,
                height   => 40,
                lines    => 10,
                font     => "/Library/Fonts/Arial",
                ptsize   => 18,
                bgcolor  => "#FFFF00",
            },
            CREATE_OPTIONS   => [ 'ttf', 'rect' ],
            PARTICLE_OPTIONS => [ 300 ],
        );
    }

    # Create a run mode that calls the CAPTCHA creation method...
    sub create 
    {
        my $self = shift;
        return $self->captcha_create;
    }
    
    # In a template far, far away. . . 
    <img src="/delight/Ident/create"> (to generate a CAPTCHA image)

    # Back in your application, to verify the CAPTCHA...
    sub some_other_runmode
    {
        my $self    = shift;
        my $request = $self->query;
        
        return unless $self->captcha_verify($request->cookie("hash"), $request->param("verify"));
    }

=head1 DESCRIPTION

C<CGI::Application::Plugin::CAPTCHA> allows programmers to easily add and 
verify CAPTCHAs in their CGI::Application-derived web applications.

A CAPTCHA (or Completely Automated Public Turing Test to Tell Computers 
and Humans Apart) is an image with a random string of characters.  A user must 
successfully enter the random string in order to submit a form.  This is a 
simple (yet annoying) procedure for humans to complete, but one that is 
significantly more difficult for a form-stuffing script to complete without 
having to integrate some sort of OCR.

CAPTCHAs are not a perfect solution.  Any skilled, diligent cracker will 
eventually be able to bypass a CAPTCHA, but it should be able to shut down
your average script-kiddie.

C<CGI::Application::Plugin::CAPTCHA> is a wrapper for L<GD::SecurityImage>.  It
makes it more convenient to access L<GD::SecurityImage> functionality, and 
gives a more L<CGI::Application>-like way of doing it.

When a CAPTCHA is created with this module, raw image data is transmitted from
your web application to the client browser.  A cookie containing a checksum is
also transmitted with the image.  When the client submits their form for
processing (along with their verification of the random string),
C<captcha_verify()> generates a checksum of the verification string the user
entered.  If the newly generated checksum matches the checksum found in the
cookie, we trust that the CAPTCHA has been successfully entered, and we allow
the user to continue processing their form.

The checksum is generated by taking the string in question, and joining it with
a SECRET. We then generate an SHA1 hex digest of the resulting string.  The
end user will not be able to generate their own checksums to bypass the CAPTCHA
check, because they do not know the value of our SECRET.  This means it is
important to choose a good value for your SECRET.

An easy way to generate a relatively good secret is to run the following perl
snippet:

  perl -MDigest::SHA=sha1_base64 -le 'print sha1_base64($$,time(),rand(9999))'

The author recognizes that the transmission of a cookie with the CAPTCHA image
may not be a popular decision, and welcomes any patches from those who can
provide an equally easy-to-implement solution.

=head1 FUNCTIONS

=head2 captcha_config()

This method is used to customize how new CAPTCHA images will be created.  
Values specified here are passed along to the appropriate functions in 
L<GD::SecurityImage> when a new CAPTCHA is created.

It is recommended that you call C<captcha_config()> in the C<cgiapp_init()>
method of your CGI::Application base class, and in the C<setup()> method of
any derived applications.

The following parameters are currently accepted:

=head3 IMAGE_OPTIONS

This specifies what options will be passed to the constructor of 
L<GD::SecurityImage>.  Please see the documentation for L<GD::SecurityImage>
for more information.

=head3 CREATE_OPTIONS

This specifies what options will be passed to the C<create()> method of 
L<GD::SecurityImage>.  Please see the documentation for L<GD::SecurityImage>
for more information.

=head3 PARTICLE_OPTIONS

This specifies what options will be passed to the C<particle()> method of
L<GD::SecurityImage>.  Please see the documentation for L<GD::SecurityImage>
for more information.

=head3 SECRET

This specifies the secret that will be used when generating the checksum hash.

=cut

sub captcha_config
{
    my $self = shift;

    if (@_) 
    {
        my $props;
        if (ref($_[0]) eq 'HASH') 
        {
            my $rthash = %{$_[0]};
            $props = $self->_cap_hash($_[0]);
        } 
        else 
        {
            $props = $self->_cap_hash({ @_ });
        }

        # Check for IMAGE_OPTIONS
        if ($props->{IMAGE_OPTIONS}) 
        {
            die "captcha_config() error:  parameter IMAGE_OPTIONS is not a hash reference" if ref $props->{IMAGE_OPTIONS} ne 'HASH';
            $self->{__CAP__CAPTCHA_CONFIG}->{IMAGE_OPTIONS} = delete $props->{IMAGE_OPTIONS};
        }

        # Check for CREATE_OPTIONS
        if ($props->{CREATE_OPTIONS}) 
        {
            die "captcha_config() error:  parameter CREATE_OPTIONS is not an array reference" if ref $props->{CREATE_OPTIONS} ne 'ARRAY';
            $self->{__CAP__CAPTCHA_CONFIG}->{CREATE_OPTIONS} = delete $props->{CREATE_OPTIONS};
        }

        # Check for PARTICLE_OPTIONS
        if ($props->{PARTICLE_OPTIONS}) 
        {
            die "captcha_config() error:  parameter PARTICLE_OPTIONS is not an array reference" if ref $props->{PARTICLE_OPTIONS} ne 'ARRAY';
            $self->{__CAP__CAPTCHA_CONFIG}->{PARTICLE_OPTIONS} = delete $props->{PARTICLE_OPTIONS};
        }

        # Check for SECRET
        if ($props->{SECRET}) 
        {
            die "captcha_config() error:  parameter SECRET is not a string" if ref $props->{SECRET};
            $self->{__CAP__CAPTCHA_CONFIG}->{SECRET} = delete $props->{SECRET};
        }

        # Check for DEBUG
        if ($props->{DEBUG}) 
        {
            $self->{__CAP__CAPTCHA_CONFIG}->{DEBUG} = delete $props->{DEBUG};
        }

        # If there are still entries left in $props then they are invalid
        die "Invalid option(s) (".join(', ', keys %$props).") passed to captcha_config" if %$props;
    }

    $self->{__CAP__CAPTCHA_CONFIG};
}

=head2 captcha_create()

Creates the CAPTCHA image, and return a cookie with the encrypted hash of the
random string.  Takes no arguments.  

The cookie created in this method is named C<hash>, and contains only the 
encrypted hash.  Future versions of this module will allow you to specify
cookie options in greater detail.

=cut

sub captcha_create
{
    my $self             = shift;
    my %image_options    = %{ $self->{__CAP__CAPTCHA_CONFIG}->{ IMAGE_OPTIONS    } }; 
    my @create_options   = @{ $self->{__CAP__CAPTCHA_CONFIG}->{ CREATE_OPTIONS   } }; 
    my @particle_options = @{ $self->{__CAP__CAPTCHA_CONFIG}->{ PARTICLE_OPTIONS } }; 
    my $secret           = $self->{__CAP__CAPTCHA_CONFIG}->{ SECRET } ;
    my $debug            = $self->{__CAP__CAPTCHA_CONFIG}->{ DEBUG  } ;

    # Create the CAPTCHA image
    my $image = GD::SecurityImage->new( %image_options );
    $debug == 1 ? $image->random("ABC123") : $image->random;
    $image->create  ( @create_options   );
    $image->particle( @particle_options );
    my ( $image_data, $mime_type, $random_string ) = $image->out;

    # check the secret
    if (!$secret) {
        $secret = Digest::SHA::sha1_base64( ref $self );
        warn "using default SECRET!  Please provide a proper SECRET when using the CGI::Application::Plugin::CAPTCHA plugin";
    }

    # Create the verification hash
    my $hash = Digest::SHA::sha1_base64(join("\0", $secret, $random_string));
    
    # Stuff the verification hash in a cookie and push it out to the 
    # client.
    my $cookie = $self->query->cookie("hash" => $hash);
    $self->header_type ( 'header' );
    $self->header_props( -type => $mime_type, -cookie => [ $cookie ], -expires => '-1d', '-cache-control' => 'no-cache', -pragma => 'no-cache' );
    return $image_data;
}

=head2 captcha_verify()

Verifies that the value entered by the user matches what was in the CAPTCHA
image.  Argument 1 is the encrypted hash from the cookie sent by 
C<captcha_create()>, and argument 2 is the value the user entered to verify
the CAPTCHA image.  Returns true if the CAPTCHA was successfully verified, else
returns false.

=cut

sub captcha_verify
{
    my ($self, $hash, $verify) = @_;
    my $secret = $self->{__CAP__CAPTCHA_CONFIG}->{ SECRET } ;

    # check the secret
    if (!$secret) {
        $secret = Digest::SHA::sha1_base64( ref $self );
        warn "using default SECRET!  Please provide a proper SECRET when using the CGI::Application::Plugin::CAPTCHA plugin";
    }

    return 1 if Digest::SHA::sha1_base64(join("\0", $secret, $verify)) eq $hash;
    return 0;
}

=head1 AUTHOR

Jason A. Crome, C<< <cromedome@cpan.org> >>

=head1 TODO

=over 4

=item *

Allow C<captcha_config()> to take cookie configuration arguments.

=item *

Allow the plugin to actually create a run mode in your CGI::Application-based
webapp without the developer having to manually create one.

=back

=head1 BUGS

Please report any bugs or feature requests to
C<bug-cgi-application-plugin-captcha@rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Application-Plugin-CAPTCHA>.
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.

=head1 CONTRIBUTING

Patches, questions, and feedback are welcome.

=head1 ACKNOWLEDGEMENTS

A big thanks to Cees Hek for providing a great module for me to borrow code 
from (L<CGI::Application::Plugin::Session>), to Michael Peters and Tony Fraser
for all of their valuable input, and to the rest who contributed ideas and
criticisms on the CGI::Application mailing list.  

Additional thanks to chorny and Cees for the various bug fixes and patches
they have submitted.

=head1 SEE ALSO

L<CGI::Application>
L<GD::SecurityImage>
Wikipedia entry for CAPTCHA - L<http://en.wikipedia.org/wiki/Captcha>

=head1 COPYRIGHT & LICENSE

Copyright 2005-2011 Jason A. Crome, all rights reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut

1; # End of CGI::Application::Plugin::CAPTCHA