File Coverage

blib/lib/CGI/Application/Plugin/Authentication/Display/Classic.pm
Criterion Covered Total %
statement 87 87 100.0
branch 54 54 100.0
condition 14 14 100.0
subroutine 8 8 100.0
pod 2 2 100.0
total 165 165 100.0


line stmt bran cond sub pod time code
1             package CGI::Application::Plugin::Authentication::Display::Classic;
2 16     16   944 use base qw(CGI::Application::Plugin::Authentication::Display);
  16         32  
  16         11670  
3              
4 16     16   291 use 5.006;
  16         57  
  16         662  
5 16     16   100 use strict;
  16         35  
  16         475  
6 16     16   83 use warnings;
  16         34  
  16         399  
7 16     16   85 use Carp;
  16         32  
  16         28256  
8             our $VERSION = '0.20';
9              
10             sub new {
11 91     91 1 200 my $class = shift;
12 91         156 my $cgiapp = shift;
13 91         699 my $self = CGI::Application::Plugin::Authentication::Display->new($cgiapp);
14 91         315 bless $self, $class;
15 91         565 return $self;
16             }
17              
18             sub login_box {
19 103     103 1 234 my $self = shift;
20 103         471 my $credentials = $self->_cgiapp->authen->credentials;
21 103         559 my $runmode = $self->_cgiapp->get_current_runmode;
22 103   100     806 my $destination = $self->_cgiapp->authen->_detaint_destination || $self->_cgiapp->authen->_detaint_selfurl;
23 103         625 my $action = $self->_cgiapp->authen->_detaint_url;
24 103         396 my $username = $credentials->[0];
25 103         230 my $password = $credentials->[1];
26 103   100     463 my $login_form = $self->_cgiapp->authen->_config->{LOGIN_FORM} || {};
27 103         1942 my %options = (
28             TITLE => 'Sign In',
29             USERNAME_LABEL => 'User Name',
30             PASSWORD_LABEL => 'Password',
31             SUBMIT_LABEL => 'Sign In',
32             COMMENT => 'Please enter your username and password in the fields below.',
33             REMEMBERUSER_OPTION => 1,
34             REMEMBERUSER_LABEL => 'Remember User Name',
35             REMEMBERUSER_COOKIENAME => 'CAPAUTHTOKEN',
36             REGISTER_URL => '',
37             REGISTER_LABEL => 'Register Now!',
38             FORGOTPASSWORD_URL => '',
39             FORGOTPASSWORD_LABEL => 'Forgot Password?',
40             INVALIDPASSWORD_MESSAGE => 'Invalid username or password
(login attempt %d)',
41             INCLUDE_STYLESHEET => 1,
42             FORM_SUBMIT_METHOD => 'post',
43             %$login_form,
44             );
45              
46 103         234 my $messages = '';
47 103 100       624 if ( my $attempts = $self->_cgiapp->authen->login_attempts ) {
    100          
48 83         781 $messages .= '
  • ' . sprintf($options{INVALIDPASSWORD_MESSAGE}, $attempts) . '
  • ';
    49             } elsif ($options{COMMENT}) {
    50 19         177 $messages .= "
  • $options{COMMENT}
  • ";
    51             }
    52              
    53 103         409 my $tabindex = 3;
    54 103         395 my ($rememberuser, $username_value, $register, $forgotpassword, $javascript, $style) = ('','','','','','');
    55 103 100       539 if ($options{FOCUS_FORM_ONLOAD}) {
    56 1         4 $javascript .= "document.loginform.${username}.focus();\n";
    57             }
    58 103 100       716 if ($options{REMEMBERUSER_OPTION}) {
    59 102         375 $rememberuser = qq[$options{REMEMBERUSER_LABEL}
    ];
    60 102         201 $tabindex++;
    61 102         6399 $username_value = $self->_cgiapp->authen->_detaint_username($username, $options{REMEMBERUSER_COOKIENAME});
    62 102 100       575 $javascript .= "document.loginform.${username}.select();\n" if $username_value;
    63             }
    64 103         244 my $submit_tabindex = $tabindex++;
    65 103 100       526 if ($options{REGISTER_URL}) {
    66 1         5 $register = qq[$options{REGISTER_LABEL}];
    67 1         2 $tabindex++;
    68             }
    69 103 100       370 if ($options{FORGOTPASSWORD_URL}) {
    70 1         4 $forgotpassword = qq[$options{FORGOTPASSWORD_LABEL}];
    71 1         2 $tabindex++;
    72             }
    73 103 100       358 if ($options{INCLUDE_STYLESHEET}) {
    74 100         412 my $login_styles = $self->_login_styles;
    75 100         972 $style = <
    76            
    81             EOS
    82             }
    83 103 100       496 if ($javascript) {
    84 61         261 $javascript = qq[];
    85             }
    86              
    87 103         2228 my $html .= <
    88             $style
    89            
    90            
    91            
    92             $options{TITLE}
    93            
    94            
    95            
    96             ${messages}
    97            
    98            
    99            
    100            
    101            
    102            
    103             ${rememberuser}
    104            
    105            
    106            
    107            
    108            
    109             ${register}
    110             ${forgotpassword}
    111            
    112            
    113            
    114            
    115            
    116            
    117             $javascript
    118             END
    119              
    120 103         4228 return $html;
    121             }
    122              
    123             sub _login_styles {
    124 100     100   351 my $self = shift;
    125 100   100     404 my $login_form = $self->_cgiapp->authen->_config->{LOGIN_FORM} || {};
    126 100         281 my %colour = ();
    127              
    128 100   100     638 $colour{base} = $login_form->{BASE_COLOUR} || '#445588';
    129 100 100       384 $colour{lighter} = $login_form->{LIGHTER_COLOUR} if $login_form->{LIGHTER_COLOUR};
    130 100 100       374 $colour{light} = $login_form->{LIGHT_COLOUR} if $login_form->{LIGHT_COLOUR};
    131 100 100       299 $colour{dark} = $login_form->{DARK_COLOUR} if $login_form->{DARK_COLOUR};
    132 100 100       296 $colour{darker} = $login_form->{DARKER_COLOUR} if $login_form->{DARKER_COLOUR};
    133 100 100       414 $colour{grey} = $login_form->{GREY_COLOUR} if $login_form->{GREY_COLOUR};
    134            
    135 100 100       277 my @undefined_colours = grep { ! defined $colour{$_} || index($colour{$_}, '%') >= 0 } qw(lighter light dark darker);
      400         1592  
    136 100 100       338 if (@undefined_colours) {
    137 99         187 eval { require Color::Calc };
      99         18811  
    138 99 100 100     826054 if ($@ && $login_form->{BASE_COLOUR}) {
    139 1         13 warn "Color::Calc is required when specifying a custom BASE_COLOUR, and leaving LIGHTER_COLOUR, LIGHT_COLOUR, DARK_COLOUR or DARKER_COLOUR blank or when providing percentage based colour";
    140             }
    141 99 100       420 if ($@) {
    142 2         5 $colour{base} = '#445588';
    143 2         7 $colour{lighter} = '#d0d5e1';
    144 2         5 $colour{light} = '#a2aac4';
    145 2         5 $colour{dark} = '#303c5f';
    146 2         5 $colour{darker} = '#1b2236';
    147 2         6 $colour{grey} = '#565656';
    148             } else {
    149 97 100       898 $colour{lighter} = !$colour{lighter}
        100          
    150             ? Color::Calc::light_html($colour{base}, 0.75)
    151             : $colour{lighter} =~ m#(\d{2})%#
    152             ? Color::Calc::light_html($colour{base}, $1 / 100)
    153             : $colour{lighter};
    154 97 100       33665 $colour{light} = !$colour{light}
        100          
    155             ? Color::Calc::light_html($colour{base}, 0.5)
    156             : $colour{light} =~ m#(\d{2})%#
    157             ? Color::Calc::light_html($colour{base}, $1 / 100)
    158             : $colour{light};
    159 97 100       22237 $colour{dark} = !$colour{dark}
        100          
    160             ? Color::Calc::dark_html($colour{base}, 0.3)
    161             : $colour{dark} =~ m#(\d{2})%#
    162             ? Color::Calc::dark_html($colour{base}, $1 / 100)
    163             : $colour{dark};
    164 97 100       21925 $colour{darker} = !$colour{darker}
        100          
    165             ? Color::Calc::dark_html($colour{base}, 0.6)
    166             : $colour{darker} =~ m#(\d{2})%#
    167             ? Color::Calc::dark_html($colour{base}, $1 / 100)
    168             : $colour{darker};
    169             #$colour{grey} ||= Color::Calc::bw_html($colour{base});
    170 97 100       14959 if (!$colour{grey}) {
    171 92         461 $colour{grey} = Color::Calc::bw_html($colour{base});
    172             }
    173             }
    174             }
    175 100   100     7228 $colour{grey} ||= '#565656';
    176 100         3568 return <
    177             div.login {
    178             width: 25em;
    179             margin: auto;
    180             padding: 3px;
    181             font-weight: bold;
    182             border: 2px solid $colour{base};
    183             color: $colour{dark};
    184             font-family: sans-serif;
    185             }
    186             div.login div {
    187             margin: 0;
    188             padding: 0;
    189             border: none;
    190             }
    191             div.login .login_header {
    192             background: $colour{base};
    193             border-bottom: 1px solid $colour{darker};
    194             height: 1.5em;
    195             padding: 0.45em;
    196             text-align: left;
    197             color: #fff;
    198             font-size: 100%;
    199             font-weight: bold;
    200             }
    201             div.login .login_content {
    202             background: $colour{lighter};
    203             padding: 0.8em;
    204             border-top: 1px solid white;
    205             border-bottom: 1px solid $colour{grey};
    206             font-size: 80%;
    207             }
    208             div.login .login_footer {
    209             background: $colour{light};
    210             border-top: 1px solid white;
    211             border-bottom: 1px solid white;
    212             text-align: left;
    213             padding: 0;
    214             margin: 0;
    215             min-height: 2.8em;
    216             }
    217             div.login fieldset {
    218             margin: 0;
    219             padding: 0;
    220             border: none;
    221             width: 100%;
    222             }
    223             div.login label {
    224             clear: left;
    225             float: left;
    226             padding: 0.6em 1em 0.6em 0;
    227             width: 8em;
    228             text-align: right;
    229             }
    230             /* image courtesy of http://www.famfamfam.com/lab/icons/silk/ */
    231             #authen_loginfield {
    232             background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAG5SURBVHjaYvz//z8DJQAggFiIVfh0twHn9w8KD9+/ZBT+9/cfExfvwwc87GxWAAFEtAFf3yl++/9XikHXL56BkYmJ4dKmcoUPT99PBQggRmK8ALT9v4BUBQMLrxxQMztY7N+PjwyXtk76BxBATMRoFjGewsDCx8jw9Oxyht9vboIxCDAxs/wCCCC8LoBrZv/A8PPpVoZ/39gZ7p57xcDLJ8Xw5tkdBrO8DYwAAcRElOYXaxn+/73DwC4vzyAmzsLw58kJsGaQOoAAYiJK868nDGwSXgxvjp1n+Hz7HoNawRFGmFqAAMIw4MBEDaI1gwBAAKEYsKtL/b9x2HSiNYMAQACBA3FmiqKCohrbfQ2nLobn97Yz6Br/JEozCAAEEDgh/eb6d98yYhEDBxsnw5VNZxnOffjLIKltw/D52B6GH89fMVjUnGbEFdgAAQRPiexMzAyfDk9gMJbmYbh17irDueMrGbjExBi8Oy8z4ksnAAEENuDY1S8MjjsnMSgaezJ8Z2Bm+P95PgPX6ycENYMAQACBwyDSUeQ/GzB926kLMEjwsjOwifKvcy05EkxMHgEIIEZKszNAgAEA+j3MEVmacXUAAAAASUVORK5CYII=') no-repeat 0 1px;
    233             background-color: #fff;
    234             border-top: solid 1px $colour{grey};
    235             border-left: solid 1px $colour{grey};
    236             border-bottom: solid 1px $colour{light};
    237             border-right: solid 1px $colour{light};
    238             padding: 2px 0 2px 18px;
    239             margin: 0.3em 0;
    240             width: 12em;
    241             }
    242             /* image courtesy of http://www.famfamfam.com/lab/icons/silk/ */
    243             #authen_passwordfield {
    244             background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKbSURBVHjaYvz//z8DPvBko+s0IJUJ5U6X8d+dhSwPEEAMIANw4ccbXKYB8f8/P+6BMYgNEkNWAxBAhDV/Pff/5+t5/39/2gcU/gc25P5qpzkwdQABxIjNCzBnS7p2Mfz5tJ+BkVWE4dWRxWA5oBcYHiyyYnj5heGAedYxR4AAwmXAf0mPWQx/3q9n+P/3I9AAMaCoBsPr4x0MDH/+MUgHrGG4P8eF4fVf9gMAAcSEK/D+/3oA1gxm/3kLJG8wSDhWMAjoeTJ8fxjNoJDQzyD0+7sDQACx4DKAkVWcgZGZG2jIV6AJfxn+/37F8OfPO6BhRxl+f/nIwC7xluHPm58MAAHEhMX5ILHp787OYvj/7zvDr7f7Gf59vw804DUwPM4x/P3+loFb0ZfhVlc1wxMu7psAAcSCEd9MjAzswoYMAppmDD9e9DKwcIkwMHFyMPx+dZnh7+9vDDxqwQx3Ji1jeMrJc9W1/JQOQAAheyFT2mctw9+vpxh+fz7A8O1JDQMrEz/QK2YMb47uZpD0SmEAmsRwu7eJ4QUX1wWXklOGIE0AAcQIim9YShOzSmf49W4xw5+PdxlYeIUYWLh9GS6vXPH+3U/Gd3K/vikzcTAzvOTkOmNXeNIUZitAALFAbF4D9N8Bhl+vJjP8/vCUgY1fkoGZ24PhysoV7178Y9vmW3M8FqZBHS3MAAIIZMDnP59P835/3Mnw98t7Bg5xNQZGNnOgzSvfv2ZgX+dbfiwVX14BCCCQAbyMrNwMDKxcDOxi/Az/WU0YLi1b8/E9K8cqr6JjGQwEAEAAMf378+/cn+//GFi5bRiYuMOBzt7w4RMH50IPIjSDAEAAsbz8+Gfdh9VFEr9//WX7//s/009uzlmuWUcqGYgEAAEGAIZWUhP4bjW1AAAAAElFTkSuQmCC') no-repeat 0 1px;
    245             background-color: #fff;
    246             border-top: solid 1px $colour{grey};
    247             border-left: solid 1px $colour{grey};
    248             border-bottom: solid 1px $colour{light};
    249             border-right: solid 1px $colour{light};
    250             padding: 2px 0 2px 18px;
    251             margin: 0.3em 0;
    252             width: 12em;
    253             }
    254             #authen_rememberuserfield {
    255             clear: left;
    256             margin-left: 8em;
    257             }
    258             #authen_loginfield:focus {
    259             background-color: #ffc;
    260             color: #000;
    261             }
    262             #authen_passwordfield:focus {
    263             background-color: #ffc;
    264             color: #000;
    265             }
    266             div.login a {
    267             font-size: 80%;
    268             color: $colour{dark};
    269             }
    270             div.login div.buttons input {
    271             border-top: solid 2px $colour{light};
    272             border-left: solid 2px $colour{light};
    273             border-bottom: solid 2px $colour{grey};
    274             border-right: solid 2px $colour{grey};
    275             background-color: $colour{lighter};
    276             padding: .2em 1em ;
    277             font-size: 80%;
    278             font-weight: bold;
    279             color: $colour{dark};
    280             }
    281             div.login div.buttons {
    282             display: block;
    283             margin: 8px 4px;
    284             width: 100%;
    285             }
    286             #authen_loginbutton {
    287             float: right;
    288             margin-right: 1em;
    289             }
    290             #authen_registerlink {
    291             display: block;
    292             }
    293             #authen_forgotpasswordlink {
    294             display: block;
    295             }
    296             ul.message {
    297             margin-top: 0;
    298             margin-bottom: 0;
    299             list-style: none;
    300             }
    301             ul.message li {
    302             text-indent: -2em;
    303             padding: 0px;
    304             margin: 0px;
    305             font-style: italic;
    306             }
    307             ul.message li.warning {
    308             color: red;
    309             }
    310             END
    311             }
    312              
    313             =head1 NAME
    314              
    315             CGI::Application::Plugin::Authentication::Display::Classic - login box that works out of the box
    316              
    317             =head1 VERSION
    318              
    319             This document describes CGI::Application::Plugin::Authentication::Display::Classic version 0.20
    320              
    321             =head1 DESCRIPTION
    322              
    323             This module provides a login box that works out of the box but which can be
    324             configured to modify the styling.
    325              
    326             =head1 METHODS
    327              
    328             =head2 new
    329              
    330             The constructor must be passed the L object as the first
    331             non-object argument.
    332              
    333             =head2 login_box
    334              
    335             This method will return the HTML for a login box that can be
    336             embedded into another page. This is the same login box that is used
    337             in the default authen_login runmode that the plugin provides.
    338              
    339             You can set this option to customize the login form that is created when a user
    340             needs to be authenticated. If you wish to replace the entire login form with a
    341             completely custom version, then just set LOGIN_RUNMODE to point to your custom
    342             runmode.
    343              
    344             All of the parameters listed below are optional, and a reasonable default will
    345             be used if left blank:
    346              
    347             =over 4
    348              
    349             =item TITLE (default: Sign In)
    350              
    351             the heading at the top of the login box
    352              
    353             =item USERNAME_LABEL (default: User Name)
    354              
    355             the label for the user name input
    356              
    357             =item PASSWORD_LABEL (default: Password)
    358              
    359             the label for the password input
    360              
    361             =item SUBMIT_LABEL (default: Sign In)
    362              
    363             the label for the submit button
    364              
    365             =item COMMENT (default: Please enter your username and password in the fields below.)
    366              
    367             a message provided on the first login attempt
    368              
    369             =item REMEMBERUSER_OPTION (default: 1)
    370              
    371             provide a checkbox to offer to remember the users name in a cookie so that
    372             their user name will be pre-filled the next time they log in
    373              
    374             =item REMEMBERUSER_LABEL (default: Remember User Name)
    375              
    376             the label for the remember user name checkbox
    377              
    378             =item REMEMBERUSER_COOKIENAME (default: CAPAUTHTOKEN)
    379              
    380             the name of the cookie where the user name will be saved
    381              
    382             =item REGISTER_URL (default: )
    383              
    384             the URL for the register new account link
    385              
    386             =item REGISTER_LABEL (default: Register Now!)
    387              
    388             the label for the register new account link
    389              
    390             =item FORGOTPASSWORD_URL (default: )
    391              
    392             the URL for the forgot password link
    393              
    394             =item FORGOTPASSWORD_LABEL (default: Forgot Password?)
    395              
    396             the label for the forgot password link
    397              
    398             =item INVALIDPASSWORD_MESSAGE (default: Invalid username or password
    (login attempt %d)
    399              
    400             a message given when a login failed
    401              
    402             =item INCLUDE_STYLESHEET (default: 1)
    403              
    404             use this to disable the built in style-sheet for the login box so you can provide your own custom styles
    405              
    406             =item FORM_SUBMIT_METHOD (default: post)
    407              
    408             use this to get the form to submit using 'get' instead of 'post'
    409              
    410             =item FOCUS_FORM_ONLOAD (default: 1)
    411              
    412             use this to automatically focus the login form when the page loads so a user can start typing right away.
    413              
    414             =item BASE_COLOUR (default: #445588)
    415              
    416             This is the base colour that will be used in the included login box. All other
    417             colours are automatically calculated based on this colour (unless you hardcode
    418             the colour values). In order to calculate other colours, you will need the
    419             Color::Calc module. If you do not have the Color::Calc module, then you will
    420             need to use fixed values for all of the colour options. All colour values
    421             besides the BASE_COLOUR can be simple percentage values (including the % sign).
    422             For example if you set the LIGHTER_COLOUR option to 80%, then the calculated
    423             colour will be 80% lighter than the BASE_COLOUR.
    424              
    425             =item LIGHT_COLOUR (default: 50% or #a2aac4)
    426              
    427             A colour that is lighter than the base colour.
    428              
    429             =item LIGHTER_COLOUR (default: 75% or #d0d5e1)
    430              
    431             A colour that is another step lighter than the light colour.
    432              
    433             =item DARK_COLOUR (default: 30% or #303c5f)
    434              
    435             A colour that is darker than the base colour.
    436              
    437             =item DARKER_COLOUR (default: 60% or #1b2236)
    438              
    439             A colour that is another step darker than the dark colour.
    440              
    441             =item GREY_COLOUR (default: #565656)
    442              
    443             A grey colour that is calculated by desaturating the base colour.
    444              
    445              
    446             =back
    447              
    448             LOGIN_FORM => {
    449             TITLE => 'Login',
    450             SUBMIT_LABEL => 'Login',
    451             REMEMBERUSER_LABEL => 1,
    452             BASE_COLOUR => '#0099FF',
    453             LIGHTER_COLOUR => '#AAFFFF',
    454             DARK_COLOUR => '50%',
    455             }
    456              
    457             =head1 BUGS
    458              
    459             This is alpha software and as such, the features and interface
    460             are subject to change. So please check the Changes file when upgrading.
    461              
    462             =head1 SEE ALSO
    463              
    464             L, perl(1)
    465              
    466             =head1 AUTHOR
    467              
    468             Author: Cees Hek ; Co-maintainer: Nicholas Bamber .
    469              
    470             =head1 CREDITS
    471              
    472             Thanks to SiteSuite (http://www.sitesuite.com.au) for funding the
    473             development of this plugin and for releasing it to the world.
    474              
    475             Thanks to Christian Walde for suggesting changes to fix the incompatibility with
    476             L and for help with github.
    477              
    478             =head1 LICENCE AND COPYRIGHT
    479              
    480             Copyright (c) 2005, SiteSuite. All rights reserved.
    481             Copyright (c) 2010, Nicholas Bamber. All rights reserved.
    482              
    483             This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
    484              
    485             =head1 DISCLAIMER OF WARRANTY
    486              
    487             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
    488              
    489             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
    490              
    491             =cut
    492              
    493             1;