ASP4

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

  - Documentation overhaul.

2011-03-23    v1.042
  - Fixed sporadic error in master pages that looks like this:
    Can't call method "Write" on an undefined value at /tmp/PAGE_CACHE/BStat/_masters_global_asp.pm line 1.
  - Apparently $s->init_asp_objects($context) was not getting called before the 
    master page's run() method was called, resulting in a call to $Response->Write(...)
    before $Response had been initialized.

2010-11-11    v1.041
  - ASP4::UserAgent calls all cleanup handlers registered via $Server->RegisterCleanup(sub { }, @args)
    at the end of each request, not when the ASP4::Mock::Pool object's DESTROY method is called.
    This fixes a condition which caused conflict when a Class::DBI::Lite ORM is
    used and the ASP4 application is executed via the `asp4` helper script.

2010-10-25    v1.040
  - 1.039 introduced a bug that could cause session-id conflicts in the asp_sessions table.
  - This release fixes that bug.

2010-10-25    v1.039
  - Session expiration now happens exclusively on the server, not as the 

README.markdown  view on Meta::CPAN

    <body>
      <p>This is an html email.</p>
      <p>You can see that <b>this text is bold</b>.</p>
    </body>
    </html>
    HTML
    );

Please see [Mail::Sendmail](http://search.cpan.org/perldoc?Mail::Sendmail) for further details and examples.

### $Server->RegisterCleanup( sub { ... }, \@args )

After the final response has been sent to the client, the server will execute
your subref and provide it the `\@args` passed in.

This is useful for long-running or asynchronous processes that don't require the
client to wait for a response.

## $Request

An instance of [ASP4::Request](http://search.cpan.org/perldoc?ASP4::Request), the `$Request` object contains specialized methods

README.markdown  view on Meta::CPAN

    

    __PACKAGE__->has_many(
      messages_out  =>
        'App::db::message'  =>
          'from_user_id'
    );
    

    # Hash the password before storing it in the database:
    __PACKAGE__->add_trigger( before_create => sub {
      my ($self) = @_;
      

      # Sign the password instead of storing it as plaintext:
      unless( $self->{password} =~ m{^([a-f0-9]{32})$}i ) {
        $self->{password} = $self->hash_password( $self->password );
      }
    });
    

    # Hash the new password before storing it in the database:
    __PACKAGE__->add_trigger( before_update_password => sub {
      my ($self, $old, $new) = @_;
      

      unless( $new =~ m{^([a-f0-9]{32})$}i ) {
        $self->{password} = $self->hash_password( $new );
      }
    });
    

    # Verify an email/password combination and return the user if a match is found:
    sub check_credentials {
      my ($self, %args) = @_;
      

    my ($result) = $self->search(
      email     => $args{email},
      password  => $self->hash_password( $args{password} ),
    );
    

      $result ? return $result : return;
    }
    

    # Convert a password string into its hashed value:
    sub hash_password {
      my ($self, $str) = @_;
      

      my $key = ASP4::ConfigLoader->load->system->settings->signing_key;
      return md5_hex( $str . $key );
    }
    

    1;# return true:

README.markdown  view on Meta::CPAN

    <asp:Content PlaceHolderID="main_content">
    <%
      # Sticky forms work like this:
      if( my $args = $Session->{__lastArgs} ) {
        map { $Form->{$_} = $args->{$_} } keys %$args;
      }
      

      # Our validation errors:
      my $errors = $Session->{validation_errors} || { };
      $::err = sub {
        my $field = shift;
        my $error = $errors->{$field} or return;
        %><span class="field_error"><%= $Server->HTMLEncode( $error ) %></span><%
      };
    %>
    <form id="register_form" method="post" action="/handlers/myapp.register">
      <p>
        <label>Email:</label>
        <input type="text" name="email" value="<%= $Server->HTMLEncode( $Form->{email} ) %>" />
        <% $::err->("email"); %>

README.markdown  view on Meta::CPAN

    package app::register;
    

    use strict;
    use warnings 'all';
    use base 'ASP4::FormHandler';
    use vars __PACKAGE__->VARS; # Import $Response, $Form, $Session, etc
    use App::db::user;
    

    sub run {
      my ($self, $context) = @_;
      

    # If there is an error, return the user to the registration page:
    if( my $errors = $self->validate() ) {
      $Session->{validation_errors} = $errors;
      $Session->{__lastArgs} = $Form;
      $Session->save;
      return $Response->Redirect( $ENV{HTTP_REFERER} );
    }
    

    # Create the user:
    my $user = eval {
      App::db::user->do_transaction(sub {
        return App::db::user->create(
          email     => $Form->{email},
          password  => $Form->{password},
        );
      });
    };
    

    if( $@ ) {
      # There was an error:

README.markdown  view on Meta::CPAN

      $Session->{msg} = "Thank you for registering!";
      $Session->save;
      

        # Redirect to /profile.asp:
      return $Response->Redirect("/profile.asp");
      }# end if()
    }
    

    sub validate {
      my ($self) = @_;
      

    $self->trim_form;
    

    my $errors = { };
    no warnings 'uninitialized';
    

README.markdown  view on Meta::CPAN

    

    use strict;
    use warnings 'all';
    use base 'ASP4::FormHandler';
    use vars __PACKAGE__->VARS;
    use App::db::user;
    use App::db::message;
    

    sub run {
      my ($self, $context) = @_;
      

    # Create the message:
    my $msg = eval {
      App::db::message->do_transaction(sub {
        my $msg = App::db::message->create(
          from_user_id  => $Session->{user_id},
          to_user_id    => $Form->{to_user_id},
          subject       => $Form->{subject},
          body          => $Form->{body},
        );
        

        # Send an email to the recipient:
        $Server->Mail(

inc/Module/Install.pm  view on Meta::CPAN






use Cwd        ();
use File::Find ();
use File::Path ();
use FindBin;

sub autoload {
	my $self = shift;
	my $who  = $self->_caller;
	my $cwd  = Cwd::cwd();
	my $sym  = "${who}::AUTOLOAD";
	$sym->{$cwd} = sub {
		my $pwd = Cwd::cwd();
		if ( my $code = $sym->{$pwd} ) {
			# delegate back to parent dirs
			goto &$code unless $cwd eq $pwd;
		}
		$$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
		unless ( uc($1) eq $1 ) {
			unshift @_, ( $self, $1 );
			goto &{$self->can('call')};
		}
	};
}

sub import {
	my $class = shift;
	my $self  = $class->new(@_);
	my $who   = $self->_caller;

	unless ( -f $self->{file} ) {
		require "$self->{path}/$self->{dispatch}.pm";
		File::Path::mkpath("$self->{prefix}/$self->{author}");
		$self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
		$self->{admin}->init;
		@_ = ($class, _self => $self);

inc/Module/Install.pm  view on Meta::CPAN

	*{"${who}::AUTOLOAD"} = $self->autoload;
	$self->preload;

	# Unregister loader and worker packages so subdirs can use them again
	delete $INC{"$self->{file}"};
	delete $INC{"$self->{path}.pm"};

	return 1;
}

sub preload {
	my $self = shift;
	unless ( $self->{extensions} ) {
		$self->load_extensions(
			"$self->{prefix}/$self->{path}", $self
		);
	}

	my @exts = @{$self->{extensions}};
	unless ( @exts ) {
		my $admin = $self->{admin};

inc/Module/Install.pm  view on Meta::CPAN

		while (my ($method, $glob) = each %{ref($obj) . '::'}) {
			next unless $obj->can($method);
			next if $method =~ /^_/;
			next if $method eq uc($method);
			$seen{$method}++;
		}
	}

	my $who = $self->_caller;
	foreach my $name ( sort keys %seen ) {
		*{"${who}::$name"} = sub {
			${"${who}::AUTOLOAD"} = "${who}::$name";
			goto &{"${who}::AUTOLOAD"};
		};
	}
}

sub new {
	my ($class, %args) = @_;

	# ignore the prefix on extension modules built from top level.
	my $base_path = Cwd::abs_path($FindBin::Bin);
	unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
		delete $args{prefix};
	}

	return $args{_self} if $args{_self};

inc/Module/Install.pm  view on Meta::CPAN

	unless ( $args{path} ) {
		$args{path}  = $args{name};
		$args{path}  =~ s!::!/!g;
	}
	$args{file}     ||= "$args{base}/$args{prefix}/$args{path}.pm";
	$args{wrote}      = 0;

	bless( \%args, $class );
}

sub call {
	my ($self, $method) = @_;
	my $obj = $self->load($method) or return;
        splice(@_, 0, 2, $obj);
	goto &{$obj->can($method)};
}

sub load {
	my ($self, $method) = @_;

	$self->load_extensions(
		"$self->{prefix}/$self->{path}", $self
	) unless $self->{extensions};

	foreach my $obj (@{$self->{extensions}}) {
		return $obj if $obj->can($method);
	}

inc/Module/Install.pm  view on Meta::CPAN

The '$method' method does not exist in the '$self->{prefix}' path!
Please remove the '$self->{prefix}' directory and run $0 again to load it.
END_DIE

	my $obj = $admin->load($method, 1);
	push @{$self->{extensions}}, $obj;

	$obj;
}

sub load_extensions {
	my ($self, $path, $top) = @_;

	unless ( grep { !ref $_ and lc $_ eq lc $self->{prefix} } @INC ) {
		unshift @INC, $self->{prefix};
	}

	foreach my $rv ( $self->find_extensions($path) ) {
		my ($file, $pkg) = @{$rv};
		next if $self->{pathnames}{$pkg};

inc/Module/Install.pm  view on Meta::CPAN

			warn $@ if $@;
			next;
		}
		$self->{pathnames}{$pkg} = delete $INC{$file};
		push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
	}

	$self->{extensions} ||= [];
}

sub find_extensions {
	my ($self, $path) = @_;

	my @found;
	File::Find::find( sub {
		my $file = $File::Find::name;
		return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
		my $subpath = $1;
		return if lc($subpath) eq lc($self->{dispatch});

		$file = "$self->{path}/$subpath.pm";
		my $pkg = "$self->{name}::$subpath";
		$pkg =~ s!/!::!g;

		# If we have a mixed-case package name, assume case has been preserved

inc/Module/Install.pm  view on Meta::CPAN

	@found;
}





#####################################################################
# Utility Functions

sub _caller {
	my $depth = 0;
	my $call  = caller($depth);
	while ( $call eq __PACKAGE__ ) {
		$depth++;
		$call = caller($depth);
	}
	return $call;
}

sub _read {
	local *FH;
	open FH, "< $_[0]" or die "open($_[0]): $!";
	my $str = do { local $/; <FH> };
	close FH or die "close($_[0]): $!";
	return $str;
}

sub _write {
	local *FH;
	open FH, "> $_[0]" or die "open($_[0]): $!";
	foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!" }
	close FH or die "close($_[0]): $!";
}

# _version is for processing module versions (eg, 1.03_05) not
# Perl versions (eg, 5.8.1).

sub _version ($) {
	my $s = shift || 0;
	   $s =~ s/^(\d+)\.?//;
	my $l = $1 || 0;
	my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g;
	   $l = $l . '.' . join '', @v if @v;
	return $l + 0;
}

# Cloned from Params::Util::_CLASS
sub _CLASS ($) {
	(
		defined $_[0]
		and
		! ref $_[0]
		and
		$_[0] =~ m/^[^\W\d]\w*(?:::\w+)*$/s
	) ? $_[0] : undef;
}

1;

inc/Module/Install/Base.pm  view on Meta::CPAN

#line 1
package Module::Install::Base;

$VERSION = '0.79';

# Suspend handler for "redefined" warnings
BEGIN {
	my $w = $SIG{__WARN__};
	$SIG{__WARN__} = sub { $w };
}

### This is the ONLY module that shouldn't have strict on
# use strict;

#line 41

sub new {
    my ($class, %args) = @_;

    foreach my $method ( qw(call load) ) {
        *{"$class\::$method"} = sub {
            shift()->_top->$method(@_);
        } unless defined &{"$class\::$method"};
    }

    bless( \%args, $class );
}

#line 61

sub AUTOLOAD {
    my $self = shift;
    local $@;
    my $autoload = eval { $self->_top->autoload } or return;
    goto &$autoload;
}

#line 76

sub _top { $_[0]->{_top} }

#line 89

sub admin {
    $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new;
}

#line 101

sub is_admin {
    $_[0]->admin->VERSION;
}

sub DESTROY {}

package Module::Install::Base::FakeAdmin;

my $Fake;
sub new { $Fake ||= bless(\@_, $_[0]) }

sub AUTOLOAD {}

sub DESTROY {}

# Restore warning handler
BEGIN {
	$SIG{__WARN__} = $SIG{__WARN__}->();
}

1;

#line 146

inc/Module/Install/Can.pm  view on Meta::CPAN


use vars qw{$VERSION $ISCORE @ISA};
BEGIN {
	$VERSION = '0.79';
	$ISCORE  = 1;
	@ISA     = qw{Module::Install::Base};
}

# check if we can load some module
### Upgrade this to not have to load the module if possible
sub can_use {
	my ($self, $mod, $ver) = @_;
	$mod =~ s{::|\\}{/}g;
	$mod .= '.pm' unless $mod =~ /\.pm$/i;

	my $pkg = $mod;
	$pkg =~ s{/}{::}g;
	$pkg =~ s{\.pm$}{}i;

	local $@;
	eval { require $mod; $pkg->VERSION($ver || 0); 1 };
}

# check if we can run some command
sub can_run {
	my ($self, $cmd) = @_;

	my $_cmd = $cmd;
	return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));

	for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') {
		next if $dir eq '';
		my $abs = File::Spec->catfile($dir, $_[1]);
		return $abs if (-x $abs or $abs = MM->maybe_command($abs));
	}

	return;
}

# can we locate a (the) C compiler
sub can_cc {
	my $self   = shift;
	my @chunks = split(/ /, $Config::Config{cc}) or return;

	# $Config{cc} may contain args; try to find out the program part
	while (@chunks) {
		return $self->can_run("@chunks") || (pop(@chunks), next);
	}

	return;
}

# Fix Cygwin bug on maybe_command();
if ( $^O eq 'cygwin' ) {
	require ExtUtils::MM_Cygwin;
	require ExtUtils::MM_Win32;
	if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) {
		*ExtUtils::MM_Cygwin::maybe_command = sub {
			my ($self, $file) = @_;
			if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) {
				ExtUtils::MM_Win32->maybe_command($file);
			} else {
				ExtUtils::MM_Unix->maybe_command($file);
			}
		}
	}
}

inc/Module/Install/Fetch.pm  view on Meta::CPAN

use strict;
use Module::Install::Base;

use vars qw{$VERSION $ISCORE @ISA};
BEGIN {
	$VERSION = '0.79';
	$ISCORE  = 1;
	@ISA     = qw{Module::Install::Base};
}

sub get_file {
    my ($self, %args) = @_;
    my ($scheme, $host, $path, $file) =
        $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;

    if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) {
        $args{url} = $args{ftp_url}
            or (warn("LWP support unavailable!\n"), return);
        ($scheme, $host, $path, $file) =
            $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
    }

inc/Module/Install/Makefile.pm  view on Meta::CPAN

use Module::Install::Base;
use ExtUtils::MakeMaker ();

use vars qw{$VERSION $ISCORE @ISA};
BEGIN {
	$VERSION = '0.79';
	$ISCORE  = 1;
	@ISA     = qw{Module::Install::Base};
}

sub Makefile { $_[0] }

my %seen = ();

sub prompt {
	shift;

	# Infinite loop protection
	my @c = caller();
	if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
	}

	# In automated testing, always use defaults
	if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
		local $ENV{PERL_MM_USE_DEFAULT} = 1;
		goto &ExtUtils::MakeMaker::prompt;
	} else {
		goto &ExtUtils::MakeMaker::prompt;
	}
}

sub makemaker_args {
	my $self = shift;
	my $args = ( $self->{makemaker_args} ||= {} );
	%$args = ( %$args, @_ );
	return $args;
}

# For mm args that take multiple space-seperated args,
# append an argument to the current list.
sub makemaker_append {
	my $self = sShift;
	my $name = shift;
	my $args = $self->makemaker_args;
	$args->{name} = defined $args->{$name}
		? join( ' ', $args->{name}, @_ )
		: join( ' ', @_ );
}

sub build_subdirs {
	my $self    = shift;
	my $subdirs = $self->makemaker_args->{DIR} ||= [];
	for my $subdir (@_) {
		push @$subdirs, $subdir;
	}
}

sub clean_files {
	my $self  = shift;
	my $clean = $self->makemaker_args->{clean} ||= {};
	  %$clean = (
		%$clean,
		FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_),
	);
}

sub realclean_files {
	my $self      = shift;
	my $realclean = $self->makemaker_args->{realclean} ||= {};
	  %$realclean = (
		%$realclean,
		FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_),
	);
}

sub libs {
	my $self = shift;
	my $libs = ref $_[0] ? shift : [ shift ];
	$self->makemaker_args( LIBS => $libs );
}

sub inc {
	my $self = shift;
	$self->makemaker_args( INC => shift );
}

my %test_dir = ();

sub _wanted_t {
	/\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1;
}

sub tests_recursive {
	my $self = shift;
	if ( $self->tests ) {
		die "tests_recursive will not work if tests are already defined";
	}
	my $dir = shift || 't';
	unless ( -d $dir ) {
		die "tests_recursive dir '$dir' does not exist";
	}
	%test_dir = ();
	require File::Find;
	File::Find::find( \&_wanted_t, $dir );
	$self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir );
}

sub write {
	my $self = shift;
	die "&Makefile->write() takes no arguments\n" if @_;

	# Make sure we have a new enough
	require ExtUtils::MakeMaker;

	# MakeMaker can complain about module versions that include
	# an underscore, even though its own version may contain one!
	# Hence the funny regexp to get rid of it.  See RT #35800
	# for details.

inc/Module/Install/Makefile.pm  view on Meta::CPAN

	if (my $preop = $self->admin->preop($user_preop)) {
		foreach my $key ( keys %$preop ) {
			$args{dist}->{$key} = $preop->{$key};
		}
	}

	my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
	$self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
}

sub fix_up_makefile {
	my $self          = shift;
	my $makefile_name = shift;
	my $top_class     = ref($self->_top) || '';
	my $top_version   = $self->_top->VERSION || '';

	my $preamble = $self->preamble
		? "# Preamble by $top_class $top_version\n"
			. $self->preamble
		: '';
	my $postamble = "# Postamble by $top_class $top_version\n"

inc/Module/Install/Makefile.pm  view on Meta::CPAN

	# XXX - This is currently unused; not sure if it breaks other MM-users
	# $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;

	open  MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
	print MAKEFILE  "$preamble$makefile$postamble" or die $!;
	close MAKEFILE  or die $!;

	1;
}

sub preamble {
	my ($self, $text) = @_;
	$self->{preamble} = $text . $self->{preamble} if defined $text;
	$self->{preamble};
}

sub postamble {
	my ($self, $text) = @_;
	$self->{postamble} ||= $self->admin->postamble;
	$self->{postamble} .= $text if defined $text;
	$self->{postamble}
}

1;

__END__

inc/Module/Install/Metadata.pm  view on Meta::CPAN

	bundles
	resources
};

my @resource_keys = qw{
	homepage
	bugtracker
	repository
};

sub Meta              { shift          }
sub Meta_ScalarKeys   { @scalar_keys   }
sub Meta_TupleKeys    { @tuple_keys    }
sub Meta_ResourceKeys { @resource_keys }

foreach my $key ( @scalar_keys ) {
	*$key = sub {
		my $self = shift;
		return $self->{values}{$key} if defined wantarray and !@_;
		$self->{values}{$key} = shift;
		return $self;
	};
}

foreach my $key ( @resource_keys ) {
	*$key = sub {
		my $self = shift;
		unless ( @_ ) {
			return () unless $self->{values}{resources};
			return map  { $_->[1] }
			       grep { $_->[0] eq $key }
			       @{ $self->{values}{resources} };
		}
		return $self->{values}{resources}{$key} unless @_;
		my $uri = shift or die(
			"Did not provide a value to $key()"
		);
		$self->resources( $key => $uri );
		return 1;
	};
}

sub requires {
	my $self = shift;
	while ( @_ ) {
		my $module  = shift or last;
		my $version = shift || 0;
		push @{ $self->{values}{requires} }, [ $module, $version ];
	}
	$self->{values}{requires};
}

sub build_requires {
	my $self = shift;
	while ( @_ ) {
		my $module  = shift or last;
		my $version = shift || 0;
		push @{ $self->{values}{build_requires} }, [ $module, $version ];
	}
	$self->{values}{build_requires};
}

sub configure_requires {
	my $self = shift;
	while ( @_ ) {
		my $module  = shift or last;
		my $version = shift || 0;
		push @{ $self->{values}{configure_requires} }, [ $module, $version ];
	}
	$self->{values}{configure_requires};
}

sub recommends {
	my $self = shift;
	while ( @_ ) {
		my $module  = shift or last;
		my $version = shift || 0;
		push @{ $self->{values}{recommends} }, [ $module, $version ];
	}
	$self->{values}{recommends};
}

sub bundles {
	my $self = shift;
	while ( @_ ) {
		my $module  = shift or last;
		my $version = shift || 0;
		push @{ $self->{values}{bundles} }, [ $module, $version ];
	}
	$self->{values}{bundles};
}

# Resource handling
my %lc_resource = map { $_ => 1 } qw{
	homepage
	license
	bugtracker
	repository
};

sub resources {
	my $self = shift;
	while ( @_ ) {
		my $name  = shift or last;
		my $value = shift or next;
		if ( $name eq lc $name and ! $lc_resource{$name} ) {
			die("Unsupported reserved lowercase resource '$name'");
		}
		$self->{values}{resources} ||= [];
		push @{ $self->{values}{resources} }, [ $name, $value ];
	}
	$self->{values}{resources};
}

# Aliases for build_requires that will have alternative
# meanings in some future version of META.yml.
sub test_requires      { shift->build_requires(@_) }
sub install_requires   { shift->build_requires(@_) }

# Aliases for installdirs options
sub install_as_core    { $_[0]->installdirs('perl')   }
sub install_as_cpan    { $_[0]->installdirs('site')   }
sub install_as_site    { $_[0]->installdirs('site')   }
sub install_as_vendor  { $_[0]->installdirs('vendor') }

sub sign {
	my $self = shift;
	return $self->{values}{sign} if defined wantarray and ! @_;
	$self->{values}{sign} = ( @_ ? $_[0] : 1 );
	return $self;
}

sub dynamic_config {
	my $self = shift;
	unless ( @_ ) {
		warn "You MUST provide an explicit true/false value to dynamic_config\n";
		return $self;
	}
	$self->{values}{dynamic_config} = $_[0] ? 1 : 0;
	return 1;
}

sub perl_version {
	my $self = shift;
	return $self->{values}{perl_version} unless @_;
	my $version = shift or die(
		"Did not provide a value to perl_version()"
	);

	# Normalize the version
	$version = $self->_perl_version($version);

	# We don't support the reall old versions
	unless ( $version >= 5.005 ) {
		die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n";
	}

	$self->{values}{perl_version} = $version;
}

sub license {
	my $self = shift;
	return $self->{values}{license} unless @_;
	my $license = shift or die(
		'Did not provide a value to license()'
	);
	$self->{values}{license} = $license;

	# Automatically fill in license URLs
	if ( $license eq 'perl' ) {
		$self->resources( license => 'http://dev.perl.org/licenses/' );
	}

	return 1;
}

sub all_from {
	my ( $self, $file ) = @_;

	unless ( defined($file) ) {
		my $name = $self->name or die(
			"all_from called with no args without setting name() first"
		);
		$file = join('/', 'lib', split(/-/, $name)) . '.pm';
		$file =~ s{.*/}{} unless -e $file;
		unless ( -e $file ) {
			die("all_from cannot find $file from $name");

inc/Module/Install/Metadata.pm  view on Meta::CPAN

	$self->name_from($file)         unless $self->name;
	$self->version_from($file)      unless $self->version;
	$self->perl_version_from($file) unless $self->perl_version;
	$self->author_from($pod)        unless $self->author;
	$self->license_from($pod)       unless $self->license;
	$self->abstract_from($pod)      unless $self->abstract;

	return 1;
}

sub provides {
	my $self     = shift;
	my $provides = ( $self->{values}{provides} ||= {} );
	%$provides = (%$provides, @_) if @_;
	return $provides;
}

sub auto_provides {
	my $self = shift;
	return $self unless $self->is_admin;
	unless (-e 'MANIFEST') {
		warn "Cannot deduce auto_provides without a MANIFEST, skipping\n";
		return $self;
	}
	# Avoid spurious warnings as we are not checking manifest here.
	local $SIG{__WARN__} = sub {1};
	require ExtUtils::Manifest;
	local *ExtUtils::Manifest::manicheck = sub { return };

	require Module::Build;
	my $build = Module::Build->new(
		dist_name    => $self->name,
		dist_version => $self->version,
		license      => $self->license,
	);
	$self->provides( %{ $build->find_dist_packages || {} } );
}

sub feature {
	my $self     = shift;
	my $name     = shift;
	my $features = ( $self->{values}{features} ||= [] );
	my $mods;

	if ( @_ == 1 and ref( $_[0] ) ) {
		# The user used ->feature like ->features by passing in the second
		# argument as a reference.  Accomodate for that.
		$mods = $_[0];
	} else {

inc/Module/Install/Metadata.pm  view on Meta::CPAN

		$name => [
			map {
				ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_
			} @$mods
		]
	);

	return @$features;
}

sub features {
	my $self = shift;
	while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) {
		$self->feature( $name, @$mods );
	}
	return $self->{values}{features}
		? @{ $self->{values}{features} }
		: ();
}

sub no_index {
	my $self = shift;
	my $type = shift;
	push @{ $self->{values}{no_index}{$type} }, @_ if $type;
	return $self->{values}{no_index};
}

sub read {
	my $self = shift;
	$self->include_deps( 'YAML::Tiny', 0 );

	require YAML::Tiny;
	my $data = YAML::Tiny::LoadFile('META.yml');

	# Call methods explicitly in case user has already set some values.
	while ( my ( $key, $value ) = each %$data ) {
		next unless $self->can($key);
		if ( ref $value eq 'HASH' ) {
			while ( my ( $module, $version ) = each %$value ) {
				$self->can($key)->($self, $module => $version );
			}
		} else {
			$self->can($key)->($self, $value);
		}
	}
	return $self;
}

sub write {
	my $self = shift;
	return $self unless $self->is_admin;
	$self->admin->write_meta;
	return $self;
}

sub version_from {
	require ExtUtils::MM_Unix;
	my ( $self, $file ) = @_;
	$self->version( ExtUtils::MM_Unix->parse_version($file) );
}

sub abstract_from {
	require ExtUtils::MM_Unix;
	my ( $self, $file ) = @_;
	$self->abstract(
		bless(
			{ DISTNAME => $self->name },
			'ExtUtils::MM_Unix'
		)->parse_abstract($file)
	 );
}

# Add both distribution and module name
sub name_from {
	my ($self, $file) = @_;
	if (
		Module::Install::_read($file) =~ m/
		^ \s*
		package \s*
		([\w:]+)
		\s* ;
		/ixms
	) {
		my ($name, $module_name) = ($1, $1);
		$name =~ s{::}{-}g;
		$self->name($name);
		unless ( $self->module_name ) {
			$self->module_name($module_name);
		}
	} else {
		die("Cannot determine name from $file\n");
	}
}

sub perl_version_from {
	my $self = shift;
	if (
		Module::Install::_read($_[0]) =~ m/
		^
		(?:use|require) \s*
		v?
		([\d_\.]+)
		\s* ;
		/ixms
	) {
		my $perl_version = $1;
		$perl_version =~ s{_}{}g;
		$self->perl_version($perl_version);
	} else {
		warn "Cannot determine perl version info from $_[0]\n";
		return;
	}
}

sub author_from {
	my $self    = shift;
	my $content = Module::Install::_read($_[0]);
	if ($content =~ m/
		=head \d \s+ (?:authors?)\b \s*
		([^\n]*)
		|
		=head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s*
		.*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s*
		([^\n]*)
	/ixms) {
		my $author = $1 || $2;
		$author =~ s{E<lt>}{<}g;
		$author =~ s{E<gt>}{>}g;
		$self->author($author);
	} else {
		warn "Cannot determine author info from $_[0]\n";
	}
}

sub license_from {
	my $self = shift;
	if (
		Module::Install::_read($_[0]) =~ m/
		(
			=head \d \s+
			(?:licen[cs]e|licensing|copyright|legal)\b
			.*?
		)
		(=head\\d.*|=cut.*|)
		\z

inc/Module/Install/Metadata.pm  view on Meta::CPAN

				$self->license($license);
				return 1;
			}
		}
	}

	warn "Cannot determine license info from $_[0]\n";
	return 'unknown';
}

sub bugtracker_from {
	my $self    = shift;
	my $content = Module::Install::_read($_[0]);
	my @links   = $content =~ m/L\<(http\:\/\/rt\.cpan\.org\/[^>]+)\>/g;
	unless ( @links ) {
		warn "Cannot determine bugtracker info from $_[0]\n";
		return 0;
	}
	if ( @links > 1 ) {
		warn "Found more than on rt.cpan.org link in $_[0]\n";
		return 0;
	}

	# Set the bugtracker
	bugtracker( $links[0] );
	return 1;
}

# Convert triple-part versions (eg, 5.6.1 or 5.8.9) to
# numbers (eg, 5.006001 or 5.008009).
# Also, convert double-part versions (eg, 5.8)
sub _perl_version {
	my $v = $_[-1];
	$v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e;	
	$v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e;
	$v =~ s/(\.\d\d\d)000$/$1/;
	$v =~ s/_.+$//;
	if ( ref($v) ) {
		$v = $v + 0; # Numify
	}
	return $v;
}





######################################################################
# MYMETA.yml Support

sub WriteMyMeta {
	$_[0]->write_mymeta;
}

sub write_mymeta {
	my $self = shift;
	
	# If there's no existing META.yml there is nothing we can do
	return unless -f 'META.yml';

	# Merge the perl version into the dependencies
	my $val  = $self->Meta->{values};
	my $perl = delete $val->{perl_version};
	if ( $perl ) {
		$val->{requires} ||= [];

inc/Module/Install/Scripts.pm  view on Meta::CPAN

use strict 'vars';
use Module::Install::Base;

use vars qw{$VERSION $ISCORE @ISA};
BEGIN {
	$VERSION = '0.80';
	$ISCORE  = 1;
	@ISA     = qw{Module::Install::Base};
}

sub install_script {
	my $self = shift;
	my $args = $self->makemaker_args;
	my $exe  = $args->{EXE_FILES} ||= [];
        foreach ( @_ ) {
		if ( -f $_ ) {
			push @$exe, $_;
		} elsif ( -d 'script' and -f "script/$_" ) {
			push @$exe, "script/$_";
		} else {
			die("Cannot find script '$_'");

inc/Module/Install/Win32.pm  view on Meta::CPAN

use Module::Install::Base;

use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
	$VERSION = '0.79';
	@ISA     = qw{Module::Install::Base};
	$ISCORE  = 1;
}

# determine if the user needs nmake, and download it if needed
sub check_nmake {
	my $self = shift;
	$self->load('can_run');
	$self->load('get_file');

	require Config;
	return unless (
		$^O eq 'MSWin32'                     and
		$Config::Config{make}                and
		$Config::Config{make} =~ /^nmake\b/i and
		! $self->can_run('nmake')

inc/Module/Install/WriteAll.pm  view on Meta::CPAN

use strict;
use Module::Install::Base;

use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
	$VERSION = '0.79';
	@ISA     = qw{Module::Install::Base};
	$ISCORE  = 1;
}

sub WriteAll {
	my $self = shift;
	my %args = (
		meta        => 1,
		sign        => 0,
		inline      => 0,
		check_nmake => 1,
		@_,
	);

	$self->sign(1)                if $args{sign};

lib/ASP4.pm  view on Meta::CPAN

  <body>
    <p>This is an html email.</p>
    <p>You can see that <b>this text is bold</b>.</p>
  </body>
  </html>
  HTML
  );

Please see L<Mail::Sendmail> for further details and examples.

=head3 $Server->RegisterCleanup( sub { ... }, \@args )

After the final response has been sent to the client, the server will execute
your subref and provide it the C<\@args> passed in.

This is useful for long-running or asynchronous processes that don't require the
client to wait for a response.

=head2 $Request

An instance of L<ASP4::Request>, the C<$Request> object contains specialized methods

lib/ASP4.pm  view on Meta::CPAN

        'to_user_id'
  );
  
  __PACKAGE__->has_many(
    messages_out  =>
      'App::db::message'  =>
        'from_user_id'
  );
  
  # Hash the password before storing it in the database:
  __PACKAGE__->add_trigger( before_create => sub {
    my ($self) = @_;
    
    # Sign the password instead of storing it as plaintext:
    unless( $self->{password} =~ m{^([a-f0-9]{32})$}i ) {
      $self->{password} = $self->hash_password( $self->password );
    }
  });
  
  # Hash the new password before storing it in the database:
  __PACKAGE__->add_trigger( before_update_password => sub {
    my ($self, $old, $new) = @_;
    
    unless( $new =~ m{^([a-f0-9]{32})$}i ) {
      $self->{password} = $self->hash_password( $new );
    }
  });
  
  # Verify an email/password combination and return the user if a match is found:
  sub check_credentials {
    my ($self, %args) = @_;
    
    my ($result) = $self->search(
      email     => $args{email},
      password  => $self->hash_password( $args{password} ),
    );
    
    $result ? return $result : return;
  }
  
  # Convert a password string into its hashed value:
  sub hash_password {
    my ($self, $str) = @_;
    
    my $key = ASP4::ConfigLoader->load->system->settings->signing_key;
    return md5_hex( $str . $key );
  }
  
  1;# return true:

C<lib/App/db/message.pm>

lib/ASP4.pm  view on Meta::CPAN

  
  <asp:Content PlaceHolderID="main_content">
  <%
    # Sticky forms work like this:
    if( my $args = $Session->{__lastArgs} ) {
      map { $Form->{$_} = $args->{$_} } keys %$args;
    }
    
    # Our validation errors:
    my $errors = $Session->{validation_errors} || { };
    $::err = sub {
      my $field = shift;
      my $error = $errors->{$field} or return;
      %><span class="field_error"><%= $Server->HTMLEncode( $error ) %></span><%
    };
  %>
  <form id="register_form" method="post" action="/handlers/myapp.register">
    <p>
      <label>Email:</label>
      <input type="text" name="email" value="<%= $Server->HTMLEncode( $Form->{email} ) %>" />
      <% $::err->("email"); %>

lib/ASP4.pm  view on Meta::CPAN

File: C<handlers/app/register.pm>

  package app::register;
  
  use strict;
  use warnings 'all';
  use base 'ASP4::FormHandler';
  use vars __PACKAGE__->VARS; # Import $Response, $Form, $Session, etc
  use App::db::user;
  
  sub run {
    my ($self, $context) = @_;
    
    # If there is an error, return the user to the registration page:
    if( my $errors = $self->validate() ) {
      $Session->{validation_errors} = $errors;
      $Session->{__lastArgs} = $Form;
      $Session->save;
      return $Response->Redirect( $ENV{HTTP_REFERER} );
    }
    
    # Create the user:
    my $user = eval {
      App::db::user->do_transaction(sub {
        return App::db::user->create(
          email     => $Form->{email},
          password  => $Form->{password},
        );
      });
    };
    
    if( $@ ) {
      # There was an error:
      $Session->{validation_errors} = {email => "Server error.  Sorry!"};

lib/ASP4.pm  view on Meta::CPAN

      # No error - Sign them in:
      $Session->{user_id} = $user->id;
      $Session->{msg} = "Thank you for registering!";
      $Session->save;
      
      # Redirect to /profile.asp:
    return $Response->Redirect("/profile.asp");
    }# end if()
  }
  
  sub validate {
    my ($self) = @_;
    
    $self->trim_form;
    
    my $errors = { };
    no warnings 'uninitialized';
    
    # email:
    if( length($Form->{email}) ) {
      # Basic email validation:

lib/ASP4.pm  view on Meta::CPAN


  package app::send;
  
  use strict;
  use warnings 'all';
  use base 'ASP4::FormHandler';
  use vars __PACKAGE__->VARS;
  use App::db::user;
  use App::db::message;
  
  sub run {
    my ($self, $context) = @_;
    
    # Create the message:
    my $msg = eval {
      App::db::message->do_transaction(sub {
        my $msg = App::db::message->create(
          from_user_id  => $Session->{user_id},
          to_user_id    => $Form->{to_user_id},
          subject       => $Form->{subject},
          body          => $Form->{body},
        );
        
        # Send an email to the recipient:
        $Server->Mail(
          from        => 'root@localhost',

lib/ASP4/API.pm  view on Meta::CPAN

package ASP4::API;

use strict;
use warnings 'all';
use ASP4::ConfigLoader;
use ASP4::HTTPContext;
use ASP4::UserAgent;
use ASP4::Test::Fixtures;
BEGIN { ASP4::ConfigLoader->load }

sub new
{
  my ($class) = @_;;
  
  my $config = ASP4::ConfigLoader->load;
  
  # Our test fixtures:
  my $test_data;
  if( -f $config->web->application_root . '/etc/test_fixtures.json' )
  {
    eval { require Data::Properties::JSON };

lib/ASP4/API.pm  view on Meta::CPAN

  return bless {
    test_fixtures => $test_data,
    properties    => $properties,
    ua            => ASP4::UserAgent->new(),
    config        => $config,
  }, $class;
}# end new()

*init = \&new;

sub test_fixtures   { shift->{test_fixtures} }
sub properties  { shift->{properties} }
sub ua          { shift->{ua} }
sub context     { ASP4::HTTPContext->current }
sub config      { shift->{config} }
sub data        { shift->test_fixtures }    # XXX: Deprecated! - for Apache2::ASP compat only.
sub test_data   { shift->test_fixtures }    # XXX: Deprecated!

sub DESTROY
{
  my $s = shift;
  undef(%$s);
}# end DESTROY()

1;# return true:

=pod

=head1 NAME

lib/ASP4/Config.pm  view on Meta::CPAN


package ASP4::Config;

use strict;
use warnings 'all';
use Carp 'confess';
use base 'ASP4::ConfigNode';


sub new
{
  my ($class, $ref, $root) = @_;
  
  my $s = $class->SUPER::new( $ref );
  
  $s->init_server_root( $root );
  
  $s->_init_inc();
  
  my $vars = $s->system->env_vars;

lib/ASP4/Config.pm  view on Meta::CPAN

  {
    $ENV{$var} = $vars->{$var};
  }# end foreach()
  
  map { $s->load_class( $_ ) } $s->system->load_modules;
  
  return $s;
}# end new()


sub _init_inc
{
  my $s = shift;
  
  my %saw = map { $_ => 1 } @INC;
  my $web = $s->web;
  push @INC, grep { ! $saw{$_}++ } ( $s->system->libs, $web->handler_root, $web->page_cache_root );
}# end _init_inc()


sub init_server_root
{
  my ($s, $root) = @_;
  
  my $project_root = (sub{
    my @parts = split /\//, $root;
    pop(@parts);
    join '/', @parts;
  })->();
  $s->{web}->{project_root} = $project_root;
  no warnings 'uninitialized';

lib/ASP4/Config.pm  view on Meta::CPAN

    }# end unless()
    confess "Folder '$folder' does not exist and cannot be created"
      unless -d $folder;
  }# end foreach()
  
  confess "Folder '$folder' exists but cannot be written to"
    unless -w $folder;
}# end init_server_root()


sub load_class
{
  my ($s, $class) = @_;
  
  (my $file = "$class.pm") =~ s/::/\//g;
  eval { require $file; }
    or confess "Cannot load $class: $@";
}# end load_class()


sub DESTROY
{
  my $s = shift;
  undef(%$s);
}


1;# return true:

=pod

lib/ASP4/ConfigFinder.pm  view on Meta::CPAN

package
ASP4::ConfigFinder;

use strict;
use warnings 'all';
use Cwd 'fastcwd';

our $CONFIGFILE = 'asp4-config.json';


sub config_path
{
  my $path = $CONFIGFILE;
  
  my $root = do { ($ENV{REMOTE_ADDR} || '') eq '' ? fastcwd() : $ENV{DOCUMENT_ROOT} || fastcwd() };
  
  # Try test dir:
  if( -f "$root/t/conf/$CONFIGFILE" )
  {
    return "$root/t/conf/$CONFIGFILE";
  }# end if()

lib/ASP4/ConfigLoader.pm  view on Meta::CPAN

use warnings 'all';
use Carp 'confess';
use ASP4::ConfigFinder;
use ASP4::ConfigParser;
use JSON::XS;

our $Configs = { };


#==============================================================================
sub load
{
  my ($s) = @_;
  
  my $path = ASP4::ConfigFinder->config_path;
  my $file_time = (stat($path))[7];
  if( exists($Configs->{$path}) && ( $file_time <= $Configs->{$path}->{timestamp} ) )
  {
    return $Configs->{$path}->{data};
  }# end if()
  

lib/ASP4/ConfigNode.pm  view on Meta::CPAN


package
ASP4::ConfigNode;

use strict;
use warnings 'all';
use Carp 'confess';


sub new
{
  my ($class, $ref) = @_;
  local $SIG{__DIE__} = \&Carp::confess;
  my $s = bless $ref, $class;
  $s->init_keys();
  $s;
}# end new()


sub init_keys
{
  my $s = shift;
  
  foreach my $key ( grep { ref($s->{$_}) eq 'HASH' } keys(%$s) )
  {
    if( $key eq 'web' )
    {
      require ASP4::ConfigNode::Web;
      $s->{$key} = ASP4::ConfigNode::Web->new( $s->{$key} );
    }

lib/ASP4/ConfigNode.pm  view on Meta::CPAN

      $s->{$key} = ASP4::ConfigNode::System->new( $s->{$key} );
    }
    else
    {
      $s->{$key} = __PACKAGE__->new( $s->{$key} );
    }# end if()
  }# end foreach()
}# end init_keys()


sub AUTOLOAD
{
  my $s = shift;
  our $AUTOLOAD;
  my ($name) = $AUTOLOAD =~ m/([^:]+)$/;
  
  confess "Unknown method or property '$name'" unless exists($s->{$name});
  
  # Read-only:
  $s->{$name};
}# end AUTOLOAD()


sub DESTROY
{
  my $s = shift;
  undef(%$s);
}# end DESTROY()

1;# return true:

lib/ASP4/ConfigNode/System.pm  view on Meta::CPAN


package ASP4::ConfigNode::System;

use strict;
use warnings 'all';
use base 'ASP4::ConfigNode';


sub new
{
  my $class = shift;
  
  my $s = $class->SUPER::new( @_ );
  
  return $s;
}# end new()


sub libs
{
  my $s = shift;
  
  @{ $s->{libs} || [ ] };
}# end libs()


sub load_modules
{
  my $s = shift;
  
  @{ $s->{load_modules} || [ ] };
}# end load_modules()


sub env_vars
{
  my $s = shift;
  
  $s->{env_vars} || { };
}# end env_vars()


sub post_processors
{
  my $s = shift;
  
  @{ $s->{post_processors} || [ ] };
}# end post_processors()


sub settings
{
  my $s = shift;
  
  return $s->{settings} || { };
}# end settings()

1;# return true:

=pod

lib/ASP4/ConfigNode/Web.pm  view on Meta::CPAN


package ASP4::ConfigNode::Web;

use strict;
use warnings 'all';
use base 'ASP4::ConfigNode';
use Carp 'confess';
use JSON::XS;


sub new
{
  my $class = shift;
  
  my $s = $class->SUPER::new( @_ );
  $s->{handler_resolver}  ||= 'ASP4::HTTPContext::HandlerResolver';
  $s->{handler_runner}    ||= 'ASP4::HTTPContext::HandlerRunner';
  $s->{filter_resolver}   ||= 'ASP4::HTTPContext::FilterResolver';
  
  map {
    $_->{uri_match} = undef unless defined($_->{uri_match});

lib/ASP4/ConfigNode/Web.pm  view on Meta::CPAN

  } $s->disable_persistence;
  
  # Do we have "routes"?:
  eval { require Router::Generic };
  $s->{__has_router} = ! $@;
  
  return $s;
}# end new()


sub request_filters
{
  my $s = shift;
  
  @{ $s->{request_filters} };
}# end request_filters()


sub disable_persistence
{
  my $s = shift;
  
  @{ $s->{disable_persistence} };
}# end disable_persistence()


sub router
{
  my $s = shift;
  $s->_parse_routes() unless $s->{__parsed_routes}++;
  $s->{router};
}

sub routes
{
  my $s = shift;
  return unless $s->{__has_router};
  $s->_parse_routes() unless $s->{__parsed_routes}++;
  $s->{routes};
}# end routes()


sub _parse_routes
{
  my $s = shift;
  
  my @original = @{ $s->{routes} };
  my $app_root = $s->application_root;
  @{ $s->{routes} } = map {
    $_->{include_routes} ? do {
      my $item = $_;
      $item->{include_routes} =~ s/\@ServerRoot\@/$app_root/sg;
      $item->{include_routes} =~ s{\\\\}{\\}g;

lib/ASP4/ConfigParser.pm  view on Meta::CPAN


package
ASP4::ConfigParser;

use strict;
use warnings 'all';
use ASP4::Config;


sub new
{
  my ($class) = @_;
  
  return bless { }, $class;
}# end new()


sub parse
{
  my ($s, $doc, $root) = @_;
  
  my $config = ASP4::Config->new( $doc, $root );
  
  # Now do any post-processing:
  foreach my $class ( $config->system->post_processors )
  {
    (my $file = "$class.pm") =~ s/::/\//;
    require $file unless $INC{$file};

lib/ASP4/ConfigPostProcessor.pm  view on Meta::CPAN


package
ASP4::ConfigPostProcessor;

use strict;
use warnings 'all';


sub new
{
  my ($class, %args) = @_;
  
  return bless \%args, $class;
}# end new()


sub post_process($$);

1;# return true:

lib/ASP4/Error.pm  view on Meta::CPAN


package ASP4::Error;

use strict;
use warnings 'all';
use ASP4::HTTPContext;
use JSON::XS;


sub new
{
  my $class = shift;
  my ($err_str, %args);
  if( @_ )
  {
    if( @_ == 1 )
    {
      $err_str = shift;
    }
    else

lib/ASP4/Error.pm  view on Meta::CPAN

    http_code     => ($Response->Status =~ m{^(\d+)})[0],
    remote_addr   => $ENV{REMOTE_ADDR} || '127.0.0.1',
    # Allow overrides:
    %args
  );
  
  return bless \%info, $class;
}# end new()


sub domain        { $_[0]->{domain} }
sub request_uri   { $_[0]->{request_uri} }
sub file          { $_[0]->{file} }
sub line          { $_[0]->{line} }
sub message       { $_[0]->{message} }
sub stacktrace    { $_[0]->{stacktrace} }
sub code          { $_[0]->{code} }
sub form_data     { $_[0]->{form_data} }
sub session_data  { $_[0]->{session_data} }
sub http_referer  { $_[0]->{http_referer} }
sub user_agent    { $_[0]->{user_agent} }
sub http_code     { $_[0]->{http_code} }
sub remote_addr   { $_[0]->{remote_addr} }


# Find the numbers within a given range, but not less than 1 and not greater than max.
sub _number_range
{
  my ($s, $number, $max, $padding) = @_;
  
  my $low = $number - $padding > 0 ? $number - $padding : 1;
  my $high = $number + $padding <= $max ? $number + $padding : $max;
  return ($low, $high);
}# end _number_range()

1;# return true:

lib/ASP4/ErrorHandler.pm  view on Meta::CPAN

package ASP4::ErrorHandler;

use strict;
use warnings 'all';
use base 'ASP4::HTTPHandler';
use vars __PACKAGE__->VARS;
use MIME::Base64;
use Data::Dumper;


sub run
{
  my ($s, $context) = @_;
  
  my $error = $Stash->{error};
  $s->print_error( $error );
  $s->send_error( $error );
}# end run()


sub print_error
{
  my ($s, $error) = @_;
  
  $Response->ContentType('text/html');

  if( $ENV{HTTP_HOST} eq 'localhost' )
  {
    $Response->Write( Dumper(\%$error) );
  }
  else
  {
    $Response->Write( $s->error_html( $error ) );
  }# end if()
  
  $Response->Flush;
}# end print_error()


sub send_error
{
  my ($s, $error) = @_;
  
  $Server->Mail(
    To                          => $Config->errors->mail_errors_to,
    From                        => $Config->errors->mail_errors_from,
    Subject                     => "ASP4: Error in @{[ $ENV{HTTP_HOST} ]}@{[ $ENV{REQUEST_URI} ]}",
    'content-type'              => 'text/html',
    'content-transfer-encoding' => 'base64',
    Message                     => encode_base64( $s->error_html($error) ),
    smtp                        => $Config->errors->smtp_server,
  );
}# end send_error()


sub error_html
{
  my ($s, $error) = @_;
  
  my $msg = <<"ERROR";
<!DOCTYPE html>
<html>
<head><title>500 Server Error</title>
<meta charset="utf-8" />
<style type="text/css">
HTML,BODY {

lib/ASP4/ErrorHandler.pm  view on Meta::CPAN


To subclass C<ASP4::ErrorHandler> you must do the following:

  package My::ErrorHandler;
  
  use strict;
  use warnings 'all';
  use base 'ASP4::ErrorHandler';
  use vars __PACKAGE__->VARS;
  
  sub run {
    my ($s, $context) = @_;
    
    my $error = $Stash->{error};
    
    # $error is an ASP4::Error object.
  
    # Do something here about the error.
    $s->print_error( $error );
    $s->send_error( $error );
  }

lib/ASP4/ErrorHandler/Remote.pm  view on Meta::CPAN

use vars __PACKAGE__->VARS;
use LWP::UserAgent;
use HTTP::Request::Common;
use HTTP::Date 'time2iso';
use JSON::XS;
use Data::Dumper;
require ASP4;

our $ua;

sub run
{
  my ($s, $context) = @_;
  
  my $error = $Stash->{error};
  
  $s->print_error( $error );
  $s->send_error($error);
}# end run()


sub send_error
{
  my ($s, $error) = @_;
  
  $ua ||= LWP::UserAgent->new();
  $ua->agent( ref($s) . " $ASP4::VERSION" );
  my %clone = %$error;
  my $req = POST $Config->errors->post_errors_to, \%clone;
  $ua->request( $req );
}# end send_error()

lib/ASP4/FileUpload.pm  view on Meta::CPAN


package ASP4::FileUpload;

use strict;
use warnings 'all';
use Carp 'confess';


sub new
{
  my ($class, %args) = @_;
  
  foreach(qw( ContentType FileHandle FileName ))
  {
    confess "Required param '$_' was not provided"
      unless $args{$_};
  }# end foreach()
  
  $args{UploadedFileName} = $args{FileName};
  ($args{FileName})       = $args{FileName} =~ m{[/\\]?([^/\\]+)$};
  ($args{FileExtension})  = $args{FileName} =~ m/([^\.]+)$/;
  $args{FileSize}         = (stat($args{FileHandle}))[7];
  
  return bless \%args, $class;
}# end new()


# Public readonly properties:
sub ContentType       { shift->{ContentType} }
sub FileName          { shift->{FileName} }
sub UploadedFileName  { shift->{UploadedFileName} }
sub FileExtension     { shift->{FileExtension} }
sub FileSize          { shift->{FileSize} }

sub FileContents
{
  my $s = shift;
  local $/;
  my $ifh = $s->FileHandle;
  return scalar(<$ifh>);
}# end FileContents()

sub FileHandle
{
  my $s = shift;
  my $ifh = $s->{FileHandle}; 
  seek($ifh,0,0)
    or confess "Cannot seek to the beginning of filehandle '$ifh': $!";
  return $ifh;
}# end FileHandle()


# Public methods:
sub SaveAs
{
  my ($s, $path) = @_;
  
  # Create the file path if it doesn't yet exist:
  my $folder = "";
  my @parts = grep { $_ } split /\//, $path;
  pop(@parts);
  for( @parts )
  {
    $folder .= "/$_";

lib/ASP4/FileUpload.pm  view on Meta::CPAN

  while( my $line = <$ifh> )
  {
    print $ofh $line;
  }# end while()
  close($ofh);
  
  return 1;
}# end SaveAs()


sub DESTROY
{
  my $s = shift;
  my $ifh = $s->FileHandle;
  close($ifh);
  undef(%$s);
}# end DESTROY()

1;# return true:

=pod

=head1 NAME

ASP4::FileUpload - Simple interface for handling File Uploads

=head1 SYNOPSIS

  # In your handler:
  sub run {
    my ($s, $context) = @_;
    
    if( my $file = $Request->FileUpload('fieldname') ) {
    
      # Save the file:
      $file->SaveAs('/var/media/uploads/budget.csv');
      
      # Some info about it:
      warn $file->UploadedFileName; # C:\Users\billg\budget.csv
      warn $file->FileName;         # budget.csv

lib/ASP4/FilterResolver.pm  view on Meta::CPAN


package
ASP4::FilterResolver;

use strict;
use warnings 'all';
my %FilterCache = ( );


sub new
{
  my ($class, %args) = @_;
  
  return bless \%args, $class;
}# end new()


sub context { ASP4::HTTPContext->current }


sub resolve_request_filters
{
  my ($s, $uri) = @_;
  
  ($uri) = split /\?/, $uri;
  my $key = "$ENV{DOCUMENT_ROOT}:$uri";
  return @{$FilterCache{$key}} if $FilterCache{$key};
  $FilterCache{$key} = [
    grep {
      if( my $pattern = $_->uri_match )
      {

lib/ASP4/FormHandler.pm  view on Meta::CPAN


  package my::handler;
  
  use strict;
  use warnings 'all';
  use base 'ASP4::FormHandler';
  
  # Import $Request, $Response, $Session, $Server, $Form, $Config, $Stash
  use vars __PACKAGE__->VARS;
  
  sub run {
    my ($self, $context) = @_;
    
    $Response->Write("Hello, World!");
  }
  
  1;# return true:

=head1 DESCRIPTION

All ASP4 *.asp scripts and C</handlers/*> classes should inherit from C<ASP4::FormHandler>.

lib/ASP4/HTTPContext.pm  view on Meta::CPAN

use ASP4::ConfigLoader;
use ASP4::Request;
use ASP4::Response;
use ASP4::Server;
use ASP4::OutBuffer;
use ASP4::SessionStateManager::NonPersisted;
use Carp 'confess';

use vars '$_instance';

sub new
{
  my ($class, %args) = @_;
  
  my $s = bless {
    config => ASP4::ConfigLoader->load,
    buffer => [ ASP4::OutBuffer->new ],
    stash  => { },
    headers_out => HTTP::Headers->new(),
    is_subrequest => $args{is_subrequest},
  }, $class;

lib/ASP4/HTTPContext.pm  view on Meta::CPAN

  my $web = $s->config->web;
  $s->config->load_class( $web->handler_resolver );
  $s->config->load_class( $web->handler_runner );
  $s->config->load_class( $s->config->data_connections->session->manager );
  $s->config->load_class( $web->filter_resolver );
  
  return $s->is_subrequest ? $s : $_instance = $s;
}# end new()


sub setup_request
{
  my ($s, $r, $cgi) = @_;
  
  $ENV{DOCUMENT_ROOT} = $r->document_root;
  $s->{r} = $r;
  $s->{cgi} = $cgi;
  
  # Must instantiate $_instance before creating the other objects:
  $s->{request}   ||= ASP4::Request->new();
  $s->{response}  ||= ASP4::Response->new();

lib/ASP4/HTTPContext.pm  view on Meta::CPAN

  else
  {
    $s->{session} ||= $s->config->data_connections->session->manager->new( $s->r );
  }# end if()
  
  return $_instance;
}# end setup_request()


# Intrinsics:
sub current   { $_instance || shift->new }
sub request   { shift->{request} }
sub response  { shift->{response} }
sub server    { shift->{server} }
sub session   { shift->{session} }
sub config    { shift->{config} }
sub stash     { shift->{stash} }

# More advanced:
sub is_subrequest { shift->{is_subrequest} }
sub cgi         { shift->{cgi} }
sub r           { shift->{r} }
sub handler     { shift->{handler} }
sub headers_out { shift->{headers_out} }
sub content_type  { my $s = shift; $s->r->content_type( @_ ) }
sub status        { my $s = shift; $s->r->status( @_ ) }
sub did_send_headers  { shift->{did_send_headers} }
sub did_end {
  my $s = shift;
  @_ ? $s->{did_end} = shift : $s->{did_end};
}

sub rprint {
  my ($s,$str) = @_;
  $s->buffer->add( $str );
}

sub rflush {
  my $s = shift;
  $s->send_headers;
  $s->r->print( $s->buffer->data );
  $s->r->rflush;
  $s->rclear;
}

sub rclear {
  my $s = shift;
  $s->buffer->clear;
}

sub send_headers
{
  my $s = shift;
  return if $s->{did_send_headers};
  
  my $headers = $s->headers_out;
  while( my ($k,$v) = each(%$headers) )
  {
    $s->r->err_headers_out->{$k} = $v;
  }# end while()

  $s->r->rflush;
  $s->{did_send_headers} = 1;
}# end send_headers()

# Here be dragons:
sub buffer        { shift->{buffer}->[-1] }
sub add_buffer    {
  my $s = shift;
  $s->rflush;
  push @{$s->{buffer}}, ASP4::OutBuffer->new;
}
sub purge_buffer  { shift( @{shift->{buffer}} ) }


sub execute
{
  my ($s, $args, $is_include) = @_;
  
  unless( $is_include )
  {
    # Set up and execute any matching request filters:
    my $resolver = $s->config->web->filter_resolver;
    foreach my $filter ( $resolver->new()->resolve_request_filters( $s->r->uri ) )
    {
      $s->config->load_class( $filter->class );

lib/ASP4/HTTPContext.pm  view on Meta::CPAN

  }# end if()
  
  $s->response->Flush;
  my $res = $s->end_request();
  
  $res = 0 if $res =~ m/^200/;
  return $res;
}# end execute()


sub handle_phase
{
  my ($s, $ref, $is_filter) = @_;
  
  my $res = eval { $ref->( ) };
  if( $@ )
  {
    $s->handle_error;
  }# end if()
  
  # Undef on success:

lib/ASP4/HTTPContext.pm  view on Meta::CPAN

    }# end if()
  }
  else
  {
    return if (! defined($res)) || $res == -1;
    return $s->response->Status =~ m/^200/ ? undef : $s->response->Status;
  }# end if()
}# end handle_phase()


sub handle_error
{
  my $s = shift;
  
  $s->response->Status( 500 );
  $s->response->Clear();
  my $err_str = $@;
  my $error = $s->server->Error( $@ );
  warn "[Error: @{[ HTTP::Date::time2iso() ]}] $err_str\n";
  
  return $s->end_request;
}# end handle_error()


sub end_request
{
  my $s = shift;
  
  $s->response->End;
  my $res = $s->response->Status =~ m/^200/ ? 0 : $s->response->Status;
  
  return $res;
}# end end_request()


sub do_disable_session_state
{
  my ($s) = @_;
  
#  my ($uri) = split /\?/, $s->r->uri;
  my ($uri) = split /\?/, $ENV{REQUEST_URI} || $s->r->uri;
  my ($yes) = grep { $_->disable_session } grep {
    if( my $pattern = $_->uri_match )
    {
      $uri =~ m/^$pattern$/
    }
    else
    {
      $uri eq $_->uri_equals;
    }# end if()
  } $s->config->web->disable_persistence;
  
  return $yes;
}# end do_disable_session_state()


sub DESTROY
{
  my $s = shift;
  $s->session->save if $s->session && ! $s->session->is_read_only;
  $s = { };
  undef(%$s);
}# end DESTROY()

1;# return true:

=pod

lib/ASP4/HTTPHandler.pm  view on Meta::CPAN


package
ASP4::HTTPHandler;

use strict;
use warnings 'all';
use Data::Properties::YAML;

BEGIN {
  sub VARS {
    qw(
      $Request      $Response
      $Session      $Server
      $Config       $Form
      $Stash
    )
  }
  use vars __PACKAGE__->VARS;
}


sub new {
  my ($class, %args) = @_;
  return bless \%args, $class;
}


sub before_run  { 1; }
sub after_run   { }
sub request     { $Request }
sub response    { $Response }
sub session     { $Session }
sub stash       { $Stash }
sub server      { $Server }
sub form        { $Form }
sub config      { $Config }


sub init_asp_objects
{
  my ($s, $context) = @_;
  
  $Request  = $context->request;
  $Response = $context->response;
  $Session  = $context->session;
  $Server   = $context->server;
  $Form     = $context->request->Form;
  $Config   = $context->config;
  $Stash    = $context->stash;

lib/ASP4/HTTPHandler.pm  view on Meta::CPAN

    ${"$_\::Server"}    = $Server;
    ${"$_\::Form"}      = $Form;
    ${"$_\::Config"}    = $Config;
    ${"$_\::Stash"}     = $Stash;
  } grep { ! $saw{$_}++ } @classes;
  
  return 1;
}# end init_asp_objects()


sub properties
{
  my ($s, $file) = @_;
  
  $file ||= $Config->web->application_root . '/etc/properties.yaml';
  return Data::Properties::YAML->new( properties_file => $file );
}# end properties()

sub trim_form
{
  no warnings 'uninitialized';
  
  map {
    $Form->{$_} =~ s/^\s+//;
    $Form->{$_} =~ s/\s+$//;
  } keys %$Form;
}# end trim_form()


sub _parents
{
  my ($s, $class ) = @_;
  
  no strict 'refs';
  
  ${"$class\::__PARENTS_TIME"} ||= 0;
  my $diff = time() - ${"$class\::__PARENTS_TIME"};
  my $max_age = 5;
  if( @{"$class\::__PARENTS"} && $diff < $max_age )
  {

lib/ASP4/HTTPHandler.pm  view on Meta::CPAN

  my %saw = ( );
  push @classes, map { $s->_parents( $_ ) }
                   grep { ( ! $saw{$_}++ ) && $_->isa($pkg) }
                     @{"$class\::ISA"};
  
  ${"$class\::__PARENTS_TIME"} = time();
  return @{"$class\::__PARENTS"} = @classes;
}# end _parents()


sub DESTROY
{
  my $s = shift;
  undef(%$s);
}# end DESTROY()

1;# return true:

lib/ASP4/HandlerResolver.pm  view on Meta::CPAN

ASP4::HandlerResolver;

use strict;
use warnings 'all';
use ASP4::PageLoader;
use File::stat;
my %HandlerCache = ( );
my %FileTimes = ( );


sub new
{
  my ($class, %args) = @_;
  
  return bless \%args, $class;
}# end new()


sub context { ASP4::HTTPContext->current }


sub resolve_request_handler
{
  my ($s, $uri) = @_;
  
  ($uri) = split /\?/, $uri;
  $s->check_reload( $uri );
  return $HandlerCache{"$ENV{DOCUMENT_ROOT}:$uri"} if $HandlerCache{"$ENV{DOCUMENT_ROOT}:$uri"};
  
  if( $uri =~ m/^\/handlers\// )
  {
    (my $handler = $uri) =~ s/^\/handlers\///;

lib/ASP4/HandlerResolver.pm  view on Meta::CPAN

      return $HandlerCache{"$ENV{DOCUMENT_ROOT}:$uri"} = $page->package;
    }
    else
    {
      return;
    }# end if()
  }# end if()
}# end resolve_request_handler()


sub check_reload
{
  my ($s, $uri) = @_;

  if( $uri =~ m/^\/handlers\// )
  {
    (my $handler = $uri) =~ s/^\/handlers\///;
    $handler =~ s/[^a-z0-9_]/::/gi;
    (my $path = "$handler.pm") =~ s/::/\//g;
    my $filepath = $s->context->config->web->handler_root . "/$path";
    (my $inc_entry = "$handler.pm") =~ s/::/\//g;

lib/ASP4/HandlerResolver.pm  view on Meta::CPAN

      $FileTimes{ "$ENV{DOCUMENT_ROOT}:$info->{filename}" } = stat($info->{filename})->mtime;
      $s->_forget_package(
        $info->{compiled_as}, $info->{package}
      );
      delete( $HandlerCache{"$ENV{DOCUMENT_ROOT}:$uri"} );
    }# end if()
  }# end if()
}# end check_reload()


sub _forget_package
{
  my ($s, $inc, $package) = @_;
  
  # Forcibly forget all about the handler we are going to reload:
  no strict 'refs';
  delete( $INC{ $inc } );
  if( *{"$package\::run"} )
  {
    no warnings;
    *{"$package\::run"} = undef;



( run in 0.591 second using v1.01-cache-2.11-cpan-4d50c553e7e )