use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64);
use Encode qw( encode is_utf8 );
use Fcntl qw/O_RDONLY/; # O_RDONLY is used in generate_salt
+use List::MoreUtils qw/ any /;
+use String::Random qw( random_string );
+
+use C4::Context;
use base 'Exporter';
-our @EXPORT_OK = qw(hash_password);
+our @EXPORT_OK = qw(hash_password get_script_name);
=head1 NAME
For general password salting a C<$strength> of C<weak> is recommend,
For generating a server-salt a C<$strength> of C<strong> is recommended
-'strong' uses /dev/random which may block until sufficient entropy is acheived.
+'strong' uses /dev/random which may block until sufficient entropy is achieved.
'weak' uses /dev/urandom and is non-blocking.
=item length
close SOURCE;
return $string;
}
+
+=head2 is_password_valid
+
+my ( $is_valid, $error ) = is_password_valid( $password );
+
+return $is_valid == 1 if the password match minPasswordLength and RequireStrongPassword conditions
+otherwise return $is_valid == 0 and $error will contain the error ('too_short' or 'too_weak')
+
+=cut
+
+sub is_password_valid {
+ my ($password) = @_;
+ my $minPasswordLength = C4::Context->preference('minPasswordLength');
+ $minPasswordLength = 3 if not $minPasswordLength or $minPasswordLength < 3;
+ if ( length($password) < $minPasswordLength ) {
+ return ( 0, 'too_short' );
+ }
+ elsif ( C4::Context->preference('RequireStrongPassword') ) {
+ return ( 0, 'too_weak' )
+ if $password !~ m|(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{$minPasswordLength,}|;
+ }
+ return ( 0, 'has_whitespaces' ) if $password =~ m[^\s|\s$];
+ return ( 1, undef );
+}
+
+=head2 generate_password
+
+my password = generate_password();
+
+Generate a password according to the minPasswordLength and RequireStrongPassword.
+
+=cut
+
+sub generate_password {
+ my $minPasswordLength = C4::Context->preference('minPasswordLength');
+ $minPasswordLength = 8 if not $minPasswordLength or $minPasswordLength < 8;
+
+ my ( $password, $is_valid );
+ do {
+ $password = random_string('.' x $minPasswordLength );
+ ( $is_valid, undef ) = is_password_valid( $password );
+ } while not $is_valid;
+ return $password;
+}
+
+
+=head2 get_script_name
+
+This returns the correct script name, for use in redirecting back to the correct page after showing
+the login screen. It depends on details of the package Plack configuration, and should not be used
+outside this context.
+
+=cut
+
+sub get_script_name {
+ # This is the method about.pl uses to detect Plack; now that two places use it, it MUST be
+ # right.
+ if ( ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) && $ENV{SCRIPT_NAME} =~ m,^/(intranet|opac)(.*), ) {
+ return '/cgi-bin/koha' . $2;
+ } else {
+ return $ENV{SCRIPT_NAME};
+ }
+}
+
1;
__END__