Apache-AppSamurai

 view release on metacpan or  search on metacpan

lib/Apache/AppSamurai/Util.pm  view on Meta::CPAN

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

# NOTE - This file includes content directly from CGI::Util

# TODO - Move validation methods into this and provide methods exports

package Apache::AppSamurai::Util;
use strict;
use warnings;

use vars qw($VERSION @EXPORT_OK @ISA $IDLEN);
$VERSION = substr(q$Revision: 1.21 $, 10, -1);

use Digest::SHA qw(sha256_hex hmac_sha256_hex);
use Time::HiRes;

@ISA = qw(Exporter);
@EXPORT_OK = qw(expires CreateSessionAuthKey CheckSidFormat
		HashPass HashAny ComputeSessionId CheckUrlFormat CheckHostName
		CheckHostIP XHalf);

# $IDLEN defines the byte length for all IDs (Session IDs, Keys, etc).
# This should be the byte length of the main digest function used.
# (Provided in case something other than SHA256 is used.)
$IDLEN = 32;

# -- expires() shamelessly taken from CGI::Util
## -- And this expires shamelessly taken from Apache::AuthCookie::Util ;)
sub expires {
    my($time,$format) = @_;
    $format ||= 'http';

    my(@MON) = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
    my(@WDAY) = qw/Sun Mon Tue Wed Thu Fri Sat/;

    # pass through preformatted dates for the sake of expire_calc()
    $time = _expire_calc($time);
    return $time unless $time =~ /^\d+$/;

    # make HTTP/cookie date string from GMT'ed time
    # (cookies use '-' as date separator, HTTP uses ' ')
    my($sc) = ' ';
    $sc = '-' if $format eq "cookie";
    my($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime($time);
    $year += 1900;
    return sprintf("%s, %02d$sc%s$sc%04d %02d:%02d:%02d GMT",
                   $WDAY[$wday],$mday,$MON[$mon],$year,$hour,$min,$sec);
}

# -- expire_calc() shamelessly taken from CGI::Util
# This internal routine creates an expires time exactly some number of
# hours from the current time.  It incorporates modifications from 
# Mark Fisher.
sub _expire_calc {
    my($time) = @_;
    my(%mult) = ('s'=>1,
                 'm'=>60,
                 'h'=>60*60,
                 'd'=>60*60*24,
                 'M'=>60*60*24*30,
                 'y'=>60*60*24*365);
    # format for time can be in any of the forms...
    # "now" -- expire immediately
    # "+180s" -- in 180 seconds
    # "+2m" -- in 2 minutes
    # "+12h" -- in 12 hours
    # "+1d"  -- in 1 day
    # "+3M"  -- in 3 months
    # "+2y"  -- in 2 years
    # "-3m"  -- 3 minutes ago(!)
    # If you don't supply one of these forms, we assume you are
    # specifying the date yourself
    my($offset);
    if (!$time || (lc($time) eq 'now')) {
        $offset = 0;
    } elsif ($time=~/^\d+/) {
        return $time;
    } elsif ($time=~/^([+-]?(?:\d+|\d*\.\d*))([mhdMy]?)/) {
        $offset = ($mult{$2} || 1)*$1;
    } else {
        return $time;
    }
    return (time+$offset);
}


# Create a session authentication key to send back to the user's browser.
# This is the "session key", not the local "session ID".  It will be used
# with the server's ServerKey value to create the local session ID, and 
# to look up a user's session going forward.  This session key is also used
# to encrypt the user's session data.  Do not log the session authentication
# key!  All logging should reference the server side session key/ID.
#
# If no arguments are passed the key is chosen randomly, else it is a digest of
# the concatenated args
sub CreateSessionAuthKey {
    my $key = '';
    my $cycles = 5;
    my $text = '';

    # Pull in and concatenate custom key text
    if (scalar @_) {
	$text = join("", @_);
	($text =~ /^\s*$/) && ($text = '');
    }

    if ($text) {
	$key = sha256_hex($text);
    } else {
	# You only make a new session once in a while, so take the time to pick
	# something hard. (Though, Bruce Schneier might very well laugh at it.)
	for (my $i=0; $i < $cycles; $i++) {
	    $key = sha256_hex(sprintf("%0.6f", Time::HiRes::time()) . $key . $$);
	}
    }

    # One time I put a VERY stupid bug in this code.  End result: It returned
    # the SHA256 digest of '' for everything.  Stupid.  NEVER AGAIN!!!!
    # (FYI: Yes, this method is unit tested now, too, but still...)
    if ($key =~ /^e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855$/i) {
	die "OH MY GOD!!!! That is the SHA256 of nothing, bozo!";



( run in 2.850 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )