CGI-Framework

 view release on metacpan or  search on metacpan

lib/CGI/Framework.pm  view on Meta::CPAN

#
# Takes a scalar key and a scalar value
# Adds them to the html que
#
sub html {
	my $self  = _getself(\@_);
	my $key   = shift || croak "key not supplied";
	my $value = shift;
	$self->{_html}->{$key} = $value;
	return 1;
}

#
# Takes a scalar key and a scalar value
# Pushes the value into the html element as an array
#
sub html_push {
	my $self           = _getself(\@_);
	my $key            = shift || croak "key not supplied";
	my $value          = shift;
	my $existing_value = $self->{_html}->{$key} || [];
	if (ref($existing_value) ne "ARRAY") {
		croak "Key $key already exists as non-array. Cannot push into it.";
	}
	push(@{$existing_value}, $value);
	$self->{_html}->{$key} = $existing_value;
	return 1;
}

#
# Takes a scalar key and a scalar value
# Unshifts the value into the html element as an array
#
sub html_unshift {
	my $self           = _getself(\@_);
	my $key            = shift || croak "key not supplied";
	my $value          = shift;
	my $existing_value = $self->{_html}->{$key} || [];
	if (ref($existing_value) ne "ARRAY") {
		croak "Key $key already exists as non-array. Cannot unshift into it.";
	}
	unshift(@{$existing_value}, $value);
	$self->{_html}->{$key} = $existing_value;
	return 1;
}

#
# Re-sets initial_template
#
sub initial_template {
	my $self = _getself(\@_);
	my $initial_template = shift || croak "initial template not supplied";
	$self->{initial_template} = $initial_template;
}

#
# An alias to new(), to be used in nooop mode
#
sub initialize_cgi_framework {
	my %para = ref($_[0]) eq "HASH" ? %{ $_[0] } : @_;
	$para{callbacks_namespace} ||= (caller)[0] || "main";
	return new("CGI::Framework", \%para);
}

#
# The constructor.  Initializes pretty much everything, returns a new bless()ed instance
#
sub new {
	my $class = shift || "CGI::Framework";
	my %para = ref($_[0]) eq "HASH" ? %{ $_[0] } : @_;
	my $self = {};
	my $cookie_value;
	my $temp;
	my $expire;
	my $sessions_driver;
	my $sessions_serializer;
	local (*FH);

	$self = bless($self, ref($class) || $class);

	#
	# Paranoia: It should be clear anyways... but
	#
	if ($LASTINSTANCE) {
		$LASTINSTANCE->finalize();
	}

	#
	# Backwards compatability support
	#
	foreach (qw(callbacks_namespace cookie_name import_form initial_template sessions_dir templates_dir valid_languages)) {
		$temp = $_;
		$temp =~ s/_//g;
		if (!exists $para{$_} && exists $para{$temp}) {
			$para{$_} = $para{$temp};
			delete $para{$temp};
		}
	}

	#
	# Custom fatal error handling
	#
	$para{fatal_error_email} && !$para{smtp_host} && !$para{sendmail} && croak "You must supply smtp_host and/or sendmail when supplying fatal_error_email";
	if ($para{"fatal_error_template"} || $para{"fatal_error_email"}) {
		set_message(
			sub {
				my $error     = shift;
				my $emailsent = 0;
				my $errorsent = 0;
				my $index;
				my @callerparts;
				my @stack;
				local (*SMH);

				#
				# Hold your horses - some errors should just be ignored
				#
				if (exists $ENV{"HTTPS"} && $ENV{"HTTPS"} && $error =~ /^((103:)?Software caused connection abort)|((104:)?Connection reset by peer)/i) {

					#
					# This is generated by some braindead web browsers that do not properly terminate an SSL session

lib/CGI/Framework.pm  view on Meta::CPAN

					elsif ($@ =~ /mod_?perl/i && $@ =~ /exit/i) {

						#
						# Under mod_perl, an exit() (deep in finalize()) called inside an eval (above) gets thrown and therefore caught above
						# so we treat it as success
						#
						$errorsent = 1;
					}
				}
				if (!$errorsent) {
					print "Content-type: text/html\n\n<h1>The following fatal error occurred:</h1><p><pre>$error</pre>\n";
				}

				#
				# Now try to send the fatal error email
				#
				if (!$emailsent && $para{"fatal_error_email"} && $para{"sendmail"}) {
					eval {
						open(SMH, "| $para{sendmail} -t -i") || die "Failed to open pipe to sendmail: $!\n";
						print SMH "From: " . ($para{"smtp_from"} || 'cgiframework@localhost') . "\n";
						print SMH "To: ", (ref($para{"fatal_error_email"}) eq "ARRAY" ? join(",", @{ $para{"fatal_error_email"} }) : $para{"fatal_error_email"}), "\n";
						print SMH "Subject: Fatal Error\n";
						print SMH "X-CGI-Framework-Method: sendmail $para{sendmail}\n";
						print SMH "X-CGI-Framework-REMOTE-ADDR: $ENV{REMOTE_ADDR}\n";
						print SMH "X-CGI-Framework-PID: $$\n";
						print SMH "\n";
						print SMH "The following fatal error occurred:\n\n$error\n";
						close(SMH);
					};
					$emailsent = 1 if !$@;
				}
				if (!$emailsent && $para{"fatal_error_email"} && $para{"smtp_host"}) {
					eval {
						require Net::SMTP;
						my $smtp = Net::SMTP->new($para{"smtp_host"}) || die "Could not create Net::SMTP object: $@\n";
						$smtp->mail($para{"smtp_from"} || 'cgiframework@localhost') || die "Could not send MAIL command: $@\n";
						$smtp->recipient(ref($para{"fatal_error_email"}) eq "ARRAY" ? @{ $para{"fatal_error_email"} } : $para{"fatal_error_email"}) || die "Could not send RECIPIENT command: $@\n";
						$smtp->data("X-CGI-Framework-Method: Net::SMTP $para{smtp_host}\nX-CGI-Framework-REMOTE-ADDR: $ENV{REMOTE_ADDR}\nX-CGI-Framework-PID: $$\n\nThe following fatal error occurred:\n\n$error") || die "Could not send DATA command: $@\n";
						$smtp->quit();
					};
					$emailsent = 1 if !$@;
				}

				#
				# Finally cleanup cruft:
				#
				$self->finalize();
			}
		);
	}

	#
	# Some initial setup
	#
	$para{_html} = {};

	#
	# We set some defaults if unsupplied
	#
	$para{valid_languages} ||= [];
	$para{callbacks_namespace} ||= (caller)[0] || "main";
	if (!$para{cookie_name}) {
		$para{cookie_name} = "sessionid_$ENV{SCRIPT_NAME}";
		$para{cookie_name} =~ s/[^0-9a-z]//gi;
	}
	if (!$para{sessions_mysql_dbh} && !$para{sessions_dir}) {

		#
		# They didn't supply any sessions stuff, so let's take a guess at some directories for file-based storage:
		#
		foreach (qw(/tmp /var/tmp c:/tmp c:/temp c:/windows/temp)) {
			if (-d $_) {
				$para{sessions_dir} = $_;
				last;
			}
		}
	}
	if (!$para{templates_dir}) {
		foreach (qw(./templates ../templates)) {
			if (-d $_) {
				$para{templates_dir} = $_;
				last;
			}
		}
	}
	if (!$para{sessions_serializer_default} && !$para{sessions_serializer_storable} && !$para{sessions_serializer_freezethaw}) {
		$para{sessions_serializer_default} = 1;
	}

	#
	# Now we do sanity checking
	#
	ref $para{valid_languages} eq "ARRAY" || croak "valid_languages must be an array ref";
	if ($para{"maketext_class_name"}) {
		@{ $para{valid_languages} } || croak "valid_languages must be set to at least one language to specify the maketext_class_name key";
	}
	$para{sessions_dir} && $para{sessions_mysql_dbh} && croak "Only one of sessions_dir and sessions_mysql_dbh may be supplied";
	if ($para{sessions_dir}) {

		#
		# Supplied (or determined) file-based sessions storage
		#
		-e $para{sessions_dir} && !-d $para{sessions_dir} && croak "$para{sessions_dir} exists but is not a directory";
		-d $para{sessions_dir} || mkdir($para{sessions_dir}, 0700) || croak "Failed to create $para{sessions_dir}: $!";
		-w $para{sessions_dir} || croak "$para{sessions_dir} is not writable by me";
	}
	elsif ($para{sessions_mysql_dbh}) {

		#
		# Supplied mysql-based sessions storage
		# Should be a reference to mysql object - but I'll just make sure it's *a* reference to something
		#
		ref($para{sessions_mysql_dbh}) || croak "Invalid sessions_mysql_dbh supplied";
	}
	else {
		croak "Neither sessions_dir or sessions_mysql_dbh were supplied, and could not automatically determine a suitable sessions_dir";
	}
	if ((grep { $para{$_} } qw(sessions_serializer_default sessions_serializer_storable sessions_serializer_freezethaw)) > 1) {
		croak "Only one of sessions_serializer_default, sessions_serializer_storable and sessions_serializer_freezethaw may be supplied";
	}
	$para{templates_dir}                  || croak "templates_dir must be supplied";



( run in 1.165 second using v1.01-cache-2.11-cpan-6de40a662fe )