CGI-MxScreen

 view release on metacpan or  search on metacpan

MxScreen.pm  view on Meta::CPAN

	my $log = $self->log;
	$log->debug(\&log_inc_times, $self, "outside CGI::MxScreen");

	#
	# Compute target screen, trap all errors.
	#
	# Since we might be using CGI::Carp, we must cancel any trap hook by
	# localizing the __DIE__ and __WARN__ special handlers.
	#

	my ($screen, $args);
	eval {
		local $SIG{__DIE__};
		local $SIG{__WARN__};

		($screen, $args) = $self->compute_screen;
	};
	$log->debug(\&log_inc_times, $self, "screen computation");
	$self->internal_error($@) if chomp $@;

	#
	# Emit CGI headers
	# From now on, output is safe and will not get us a server error.
	#

	untie *main::STDOUT;			# Restore original STDOUT stream

	#
	# If they configured us to buffer all STDOUT until context is ready
	# to be emitted, then create object, print headers and mark the
	# output of headers as done: further output to STDOUT will be buffered
	# and printed only after the context.
	#
	# The reason for this is to have the context emitted before any other
	# form widget.  That way, pressing a submit button before the whole form
	# is loaded in the browser won't matter as much, since we'll have at
	# least the context to propagate in the POST parameters.
	#

	my $stdout;
	if ($CGI::MxScreen::cf::mx_buffer_stdout) {
		require CGI::MxScreen::Tie::Buffered_Output;
		$stdout = tie *main::STDOUT, "CGI::MxScreen::Tie::Buffered_Output";
	}

	#
	# Display screen, with proper "bounce" exception support.
	# Returns screen that was finally displayed.
	#

	$screen = $self->display($screen, $args, $stdout);
	$log->debug(\&log_inc_times, $self, "\"%s\" display", $screen->name);

	#
	# Snapshot current time and last modification date of the
	# scriptright before saving context.  That fields can be used to
	# check for session validity.
	#

    $self->ctx->{'time'} = time;
    $self->ctx->{'script_date'} = (stat($0))[9]; 

	#
	# Cleanup context to avoid saving transient data
	#

    &{$coderef}() if defined $coderef; # TBR

    for my $f (@{$self->context_root->[SCREEN_FIELD]}) {
        DASSERT $f->isa('CGI::MxScreen::Form::Field');
        $f->cleanup();
    }
    for my $b (@{$self->context_root->[SCREEN_BUTTON]}) {
        DASSERT $b->isa('CGI::MxScreen::Form::Button');
        $b->cleanup();
    }

	#
	# If STDOUT was bufferd, the context must be emitted explicitely
	# between the header of the form and the remaining data.
	#

	if (defined $stdout) {
		my $context = $self->session->save;
		$stdout->print_all($context);
		untie_stdout();
	} else {
		print $self->session->save;
	}

	$log->debug(\&log_inc_times, $self, "context save");

	#
	# Emit CGI trailers.
	#

	print CGI::endform;

	my $layout = $self->layout;
	$layout->postamble;
	$layout->end_HTML;

    return DVOID;
}

#
# ->compute_screen
#
# Compute target screen, and run and enter/leave hooks if we change screens.
# This routine does not display anything, but runs all the action callbacks.
#
# Returns new screen object, and a ref to the argument list.
#
sub compute_screen {
	DFEATURE my $f_;
	my $self = shift;
    my ($current_state, $previous_state, $new_state);
    my ($origin_name, $target_name, @arg_list);
    my $screen;
	my $errors = 0;
    my $ctx = $self->ctx;

MxScreen.pm  view on Meta::CPAN

		#

		if (ref $@ || chomp $@) {
			my $msg = $@;
			$msg =~ s/^\(.*?\)\s+//;	# Remove already added session tag
			$self->log->critical("display error for screen \"%s\": %s",
					$screen->name, $msg);

			#
			# If they buffered STDOUT, it's nice, because the screen will not
			# mix regular output and the error message.  And since we discard
			# even the form header, the Content-Type printed by CGI::Carp will
			# not even show!
			#

			untie_stdout(1) if defined $stdout;
			logdie $msg;
		}

		return DVAL $screen;		# Successfully displayed the screen
	}

	$self->log->critical("too many screen bounces");
	logdie "possible infinite loop detected, aborting";
}

#
# ->check_validity
#
# Check context validity: proper version, no timeout.
#
sub check_validity {
    DFEATURE my $f_;
    my $self = shift;

	unless (defined $self->context_root) {
		logerr "mangled context from %s", CGI::remote_host();
		$self->internal_error("cannot retrieve application context");
	}

    my $ctx = $self->ctx;
	return DVOID unless exists $ctx->{'cgi_version'};	# Empty context

	#
	# Ensure binary version (which traces variations in the way session
	# context are represented) is compatible.
	#

	my $bin = $ctx->{'bin_version'};
    if ($bin > $BIN_VERSION) {
        $self->internal_error(<<EOS);
Script session used a format (v$bin) more recent than I am (v$BIN_VERSION).
Please restart a new session.
EOS
	}

    #
    # check that the script file has not been modified (compare the
    # last modification time on the file system)
    #
    if ($ctx->{'script_date'} != (stat($0))[9]) {
        $self->internal_error(<<EOS);
Script file has been modified since the last display, 
please restart a new session.
EOS
    }

    #
    # check whether the cgi version is still the same
    #
    if (defined $ctx->{'cgi_version'}) {
        my $version = $ctx->{'cgi_version'};

        if ($version ne $self->cgi_version) {
            $self->internal_error(<<EOS);
Script version has evolved since the last display, please restart a new session.
EOS
        }
    }

    #
    # check whether the timeout is not exhausted
    #
    if (defined $self->valid_time && defined $ctx->{'time'}) {
        my $last_time = $ctx->{'time'};

        if ((time - $last_time) > $self->valid_time) {
            $self->internal_error(<<EOS);
Session timeout since the last display, please restart a new session.
EOS
        }
    }

    return DVOID;
}

#
# ->internal_error
#
#
sub internal_error {
    DFEATURE my $f_;
    my $self = shift;
    my ($message) = @_;

	my $logmsg = $message;
	$logmsg =~ s/\s+/ /sg;
	logerr "internal error: $logmsg";

	untie_stdout(1);		# Restore original STDOUT stream, discard all

	my $layout = $self->layout;

	$layout->init(undef);
	$layout->start_HTML("Internal Script Error");
	$layout->preamble;

    print CGI::h1("Internal Script Error");
    print CGI::p(CGI::tt(ucfirst($message)));
    print CGI::p(CGI::a({-href => CGI::url()}, "Restart a new session"));



( run in 1.637 second using v1.01-cache-2.11-cpan-39bf76dae61 )