From 377070f12059e6fcb1bd595d6245f6dea00fe571 Mon Sep 17 00:00:00 2001 From: George Clark Date: Wed, 31 Aug 2016 10:10:52 -0400 Subject: [PATCH 1/6] Item14150: Recompute validation keys on cached pages Fix provided by MichaelDaum. Cached pages were keeping their original cached validation keys. Once they expired, it was impossible to submit forms on cached pages without refreshing the cache. --- core/lib/Foswiki/PageCache.pm | 8 ++++++++ core/lib/Foswiki/Validation.pm | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/core/lib/Foswiki/PageCache.pm b/core/lib/Foswiki/PageCache.pm index 5770a18e20..9c00fa9b86 100644 --- a/core/lib/Foswiki/PageCache.pm +++ b/core/lib/Foswiki/PageCache.pm @@ -681,6 +681,14 @@ sub _handleDirtyArea { $prefs->popTopicContext(); }; + my $request = $session->{request}; + my $context = $request->url( -full => 1, -path => 1, -query => 1 ) . time(); + my $cgis = $session->{users}->getCGISession(); + my $usingStrikeOne = $Foswiki::cfg{Validation}{Method} eq 'strikeone'; + + $text =~ +s//Foswiki::Validation::updateValidationKey($cgis, $context, $usingStrikeOne, $1)/gei; + #Foswiki::Func::writeDebug("out text='$text'") if TRACE; return $text; } diff --git a/core/lib/Foswiki/Validation.pm b/core/lib/Foswiki/Validation.pm index 5441c3278d..c4ae7c4591 100644 --- a/core/lib/Foswiki/Validation.pm +++ b/core/lib/Foswiki/Validation.pm @@ -92,6 +92,15 @@ sub addValidationKey { return ""; } +sub updateValidationKey { + my ( $cgis, $context, $strikeone, $oldKey ) = @_; + + # expire old key + expireValidationKeys( $cgis, $oldKey ); + + return addValidationKey( $cgis, $context, $strikeone ); +} + =begin TML ---++ StaticMethod generateValidationKey( $cgis, $context, $strikeone ) -> $nonce From e9fecba1251580b6604c03e21ad6cbea892654ee Mon Sep 17 00:00:00 2001 From: Vadim Belman Date: Thu, 1 Sep 2016 16:37:15 -0400 Subject: [PATCH 2/6] Item13897: Fixed a problem with @ARGV being emptied. - Merge from Item14152: Foswiki::Class imports 5.14 feature set into a module. No need to always `use v5.14;' or a kind of. - Removed @_newParameters from Foswiki::Exception. - Merge from Item14152 of getNS() and fetchGlobal() function of Foswiki.pm. --- core/lib/Foswiki.pm | 79 ++++++++++++++++++++++++++++++++++- core/lib/Foswiki/AppObject.pm | 1 - core/lib/Foswiki/Attach.pm | 4 +- core/lib/Foswiki/Class.pm | 24 +++++++---- core/lib/Foswiki/Engine.pm | 4 +- core/lib/Foswiki/Exception.pm | 12 ------ core/lib/Foswiki/Object.pm | 3 +- core/tools/configure | 2 +- 8 files changed, 99 insertions(+), 30 deletions(-) diff --git a/core/lib/Foswiki.pm b/core/lib/Foswiki.pm index 8402124c29..04b4bce5ca 100644 --- a/core/lib/Foswiki.pm +++ b/core/lib/Foswiki.pm @@ -1,3 +1,4 @@ +# See bottom of file for license and copyright information package Foswiki; use v5.14; # First version to accept v-numbers. @@ -34,8 +35,6 @@ our $UNICODE = 1; # flag that extensions can use to test if the core is unicode our $TRUE = 1; our $FALSE = 0; our $TranslationToken = "\0"; # Do not deprecate - used in many plugins -our $system_message; # Important broadcast message from the system -my $bootstrap_message = ''; # Bootstrap message. # Note: the following marker is used in text to mark RENDERZONE # macros that have been hoisted from the source text of a page. It is @@ -904,6 +903,82 @@ sub saveFile { close($FILE); } +=begin TML + +---++ StaticMethod getNS( $module ) => $globRef + +Returns GLOB pointing to namespace of a module. Returns undef if module isn't +loaded. + +=cut + +sub getNS { + my ($module) = @_; + + my @keys = split /::/, $module; + + my $ref = \%::; + while (@keys) { + my $key = shift @keys; + my $sym = "$key\:\:"; + return undef unless defined $ref->{$sym}; + $ref = $ref->{$sym}; + } + return $ref; +} + +=begin TML + +---++ StaticMethod fetchGlobal($fullName) => $value + +Fetches a variable value by it's full name. 'Full' means it includes type of +variable data ($, %, @, or &) and package name. For & a coderef will be +returned. + +The purpose of this function is to avoid use of =no strict 'refs'= in the code. + +*Example:* fetchGlobal('$Foswiki::Extension::Sample::API_VERSION'); + +=cut + +sub fetchGlobal { + my ($fullName) = @_; + + $fullName =~ s/^([\$%@&])// + or Foswiki::Exception::Fatal->throw( + text => "Foswiki::fetchGlobal(): Invalid sigil in `$fullName'" ); + my $sigil = $1; + + my @keys = split /::/, $fullName; + my $symbol = pop @keys; + my $module = join( '::', @keys ); + + my $ns = getNS($module); + + Foswiki::Exception::Fatal->throw( text => "Module $module not found" ) + unless defined $ns; + + state $sigilSub = { + '$' => sub { return ${ $_[0] } }, + '%' => sub { return %{ $_[0] } }, + '@' => sub { return @{ $_[0] } }, + '&' => sub { return *{ $_[0] }{CODE} }, + }; + state $sigilKey = { + '$' => 'SCALAR', + '%' => 'HASH', + '@' => 'ARRAY', + '&' => 'CODE', + }; + + Foswiki::Exception::Fatal->throw( + text => "$sigil$symbol not declared in " . $ns ) + unless defined $ns->{$symbol} + && *{ $ns->{$symbol} }{ $sigilKey->{$sigil} }; + + return $sigilSub->{$sigil}->( $ns->{$symbol} ); +} + 1; __END__ Foswiki - The Free and Open Source Wiki, http://foswiki.org/ diff --git a/core/lib/Foswiki/AppObject.pm b/core/lib/Foswiki/AppObject.pm index 7daa678d54..421ffcc5d0 100644 --- a/core/lib/Foswiki/AppObject.pm +++ b/core/lib/Foswiki/AppObject.pm @@ -17,7 +17,6 @@ Method create() is imported from Foswiki::App class. =cut use Assert; -use Foswiki::Exception; require Foswiki::Object; diff --git a/core/lib/Foswiki/Attach.pm b/core/lib/Foswiki/Attach.pm index 97411e83ca..ff10ab6129 100644 --- a/core/lib/Foswiki/Attach.pm +++ b/core/lib/Foswiki/Attach.pm @@ -15,10 +15,8 @@ use Assert; use Unicode::Normalize; use Foswiki qw(expandStandardEscapes); -use Moo; -use namespace::clean; +use Foswiki::Class qw(app); extends qw(Foswiki::Object); -with qw(Foswiki::AppObject); BEGIN { if ( $Foswiki::cfg{UseLocale} ) { diff --git a/core/lib/Foswiki/Class.pm b/core/lib/Foswiki/Class.pm index 3a880b9db4..aa2b82603b 100644 --- a/core/lib/Foswiki/Class.pm +++ b/core/lib/Foswiki/Class.pm @@ -78,11 +78,14 @@ manually by the class using =with=. use Carp; +require Foswiki; require Moo::Role; require Moo; require namespace::clean; use B::Hooks::EndOfScope 'on_scope_end'; +use constant DEFAULT_FEATURESET => ':5.14'; + our @ISA = qw(Moo); my %_assignedRoles; @@ -103,9 +106,14 @@ sub import { ); my @p; - my @noNsClean = qw(meta); + my @noNsClean = qw(meta); + my $featureSet = DEFAULT_FEATURESET; while (@_) { my $param = shift; + if ( $param =~ /^:/ ) { + $featureSet = $param; + next; + } if ( exists $options{$param} ) { my $opt = $options{$param}; $opt->{use} = 1; @@ -127,6 +135,8 @@ sub import { $class->_apply_roles; }; + feature->import($featureSet); + namespace::clean->import( -cleanee => $target, -except => \@noNsClean, @@ -139,11 +149,9 @@ sub import { # Actually we're duplicating Moo::_install_coderef here in a way. But we better # avoid using a module's internalls. sub _inject_code { - my ( $name, $code ) = @_; + my ( $target, $name, $code ) = @_; - no strict "refs"; - *{$name} = $code; - use strict "refs"; + Foswiki::getNS($target)->{$name} = $code; } sub _apply_roles { @@ -164,17 +172,19 @@ sub _assign_role { sub _install_callbacks { my ( $class, $target ) = @_; + Foswiki::load_package('Foswiki::Aux::Callbacks'); _assign_role( $target, 'Foswiki::Aux::Callbacks' ); - _inject_code( "${target}::callback_names", \&_handler_callbacks ); + _inject_code( $target, "callback_names", \&_handler_callbacks ); } -sub _handler_callbacks { +sub _handler_callbacks (@) { my $target = caller; Foswiki::Aux::Callbacks::registerCallbackNames( $target, @_ ); } sub _install_app { my ( $class, $target ) = @_; + Foswiki::load_package('Foswiki::AppObject'); _assign_role( $target, 'Foswiki::AppObject' ); } diff --git a/core/lib/Foswiki/Engine.pm b/core/lib/Foswiki/Engine.pm index 6d121f3b72..033a77d3f7 100644 --- a/core/lib/Foswiki/Engine.pm +++ b/core/lib/Foswiki/Engine.pm @@ -20,10 +20,8 @@ use Assert; use Scalar::Util (); use Unicode::Normalize; -use Moo; -use namespace::clean; +use Foswiki::Class qw(app); extends qw(Foswiki::Object); -with qw(Foswiki::AppObject); use constant HTTP_COMPLIANT => undef; # This is a generic class. diff --git a/core/lib/Foswiki/Exception.pm b/core/lib/Foswiki/Exception.pm index acf805854a..e8da538600 100644 --- a/core/lib/Foswiki/Exception.pm +++ b/core/lib/Foswiki/Exception.pm @@ -54,19 +54,11 @@ use Carp (); use Scalar::Util (); use Foswiki::Class; -use namespace::clean; extends qw(Foswiki::Object); with 'Throwable'; our $EXCEPTION_TRACE = 0; -BEGIN { - if ( $Foswiki::cfg{UseLocale} ) { - require locale; - import locale(); - } -} - =begin TML ---++ ObjectAttribute file @@ -509,11 +501,8 @@ Attributes: package Foswiki::Exception::HTTPResponse; use Foswiki::Class; -use namespace::clean; extends qw(Foswiki::Exception); -our @_newParameters = qw(status reason response); - has status => ( is => 'ro', lazy => 1, default => sub { $_[0]->response->status, }, ); has response => ( @@ -562,7 +551,6 @@ use CGI (); use Assert; use Foswiki::Class; -use namespace::clean; extends qw(Foswiki::Exception::HTTPResponse); has header => ( is => 'rw', default => '' ); diff --git a/core/lib/Foswiki/Object.pm b/core/lib/Foswiki/Object.pm index c8bfbe19d1..890ff72ac2 100644 --- a/core/lib/Foswiki/Object.pm +++ b/core/lib/Foswiki/Object.pm @@ -87,7 +87,7 @@ has __id => ( has __clone_heap => ( is => 'rw', clearer => 1, lazy => 1, default => sub { {} }, ); -around BUILDARGS { +around BUILDARGS => sub { my $orig = shift; my ( $class, @params ) = @_; @@ -101,6 +101,7 @@ around BUILDARGS { my $paramHash; + Carp::confess("Undefined \$class") unless defined $class; no strict 'refs'; if ( defined *{ $class . '::_newParameters' }{ARRAY} ) { my @newParameters = @{ $class . '::_newParameters' }; diff --git a/core/tools/configure b/core/tools/configure index 5584f0f811..8ac86c30d0 100755 --- a/core/tools/configure +++ b/core/tools/configure @@ -45,8 +45,8 @@ binmode( STDIN, ':crlf' ); use Assert; use Foswiki; -use Foswiki::App; use Foswiki::Configure::Query; +use Foswiki::App; { From cfb5a2716a2d6d7540562abad03019e467c1e6b2 Mon Sep 17 00:00:00 2001 From: Vadim Belman Date: Thu, 1 Sep 2016 16:44:31 -0400 Subject: [PATCH 3/6] Item13897: Merge of Foswiki::Exception.pm from Item14152 Foswiki::Exception::transmute doesn't enforce an exception into destination class if the exception's class is a subclass of destination. --- core/lib/Foswiki/Exception.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/lib/Foswiki/Exception.pm b/core/lib/Foswiki/Exception.pm index e8da538600..699c5d0a58 100644 --- a/core/lib/Foswiki/Exception.pm +++ b/core/lib/Foswiki/Exception.pm @@ -289,7 +289,7 @@ sub transmute { if DEBUG; if ( ref($e) ) { if ( $e->isa('Foswiki::Exception') ) { - if ( !$enforce || ( ref($e) eq $class ) ) { + if ( !$enforce || $e->isa($class) ) { return $e; } return $class->new( %$e, @_ ); @@ -390,13 +390,14 @@ extends qw(Foswiki::Exception); # For informational exceptions. package Foswiki::Exception::Fatal; +use Assert; use Foswiki::Class; extends qw(Foswiki::Exception); sub BUILD { my $this = shift; - say STDERR $this->stringify, $this->stacktrace; + say STDERR $this->stringify, $this->stacktrace if DEBUG; } # To cover perl/system errors. From 0753fd2d07d32b2915cc478975f2cf5b1cd902ad Mon Sep 17 00:00:00 2001 From: Vadim Belman Date: Fri, 2 Sep 2016 14:50:29 -0400 Subject: [PATCH 4/6] Item13897: Fixed feature :5.14 not been applied sometimes. --- core/lib/Foswiki/Class.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/core/lib/Foswiki/Class.pm b/core/lib/Foswiki/Class.pm index aa2b82603b..969ef2af44 100644 --- a/core/lib/Foswiki/Class.pm +++ b/core/lib/Foswiki/Class.pm @@ -135,6 +135,7 @@ sub import { $class->_apply_roles; }; + require feature; feature->import($featureSet); namespace::clean->import( From f9504fd59fc0801eec9f993472736d38f5f9b56c Mon Sep 17 00:00:00 2001 From: Vadim Belman Date: Fri, 2 Sep 2016 20:49:48 -0400 Subject: [PATCH 5/6] Item13897: Fixed Foswiki::Class incompatibility with perl 5.20 and lower. Some bootstrap fixed. --- core/lib/Foswiki/Class.pm | 16 +++++++++------- core/lib/Foswiki/Configure/Auth.pm | 15 +++++++++++---- core/lib/Foswiki/UI/Configure.pm | 4 ++-- core/lib/Foswiki/Users.pm | 9 ++++----- core/tools/configure | 25 ++++++++++++++++++++++--- 5 files changed, 48 insertions(+), 21 deletions(-) diff --git a/core/lib/Foswiki/Class.pm b/core/lib/Foswiki/Class.pm index 969ef2af44..decbcd824b 100644 --- a/core/lib/Foswiki/Class.pm +++ b/core/lib/Foswiki/Class.pm @@ -117,7 +117,8 @@ sub import { if ( exists $options{$param} ) { my $opt = $options{$param}; $opt->{use} = 1; - push @noNsClean, @{ $opt->{keywords} } if defined $opt->{keywords}; + + #push @noNsClean, @{ $opt->{keywords} } if defined $opt->{keywords}; } else { push @p, $param; @@ -138,6 +139,7 @@ sub import { require feature; feature->import($featureSet); + require namespace::clean; namespace::clean->import( -cleanee => $target, -except => \@noNsClean, @@ -170,17 +172,17 @@ sub _assign_role { push @{ $_assignedRoles{$class} }, $role; } +sub _handler_callbacks { + my $target = caller; + Foswiki::Aux::Callbacks::registerCallbackNames( $target, @_ ); +} + sub _install_callbacks { my ( $class, $target ) = @_; Foswiki::load_package('Foswiki::Aux::Callbacks'); _assign_role( $target, 'Foswiki::Aux::Callbacks' ); - _inject_code( $target, "callback_names", \&_handler_callbacks ); -} - -sub _handler_callbacks (@) { - my $target = caller; - Foswiki::Aux::Callbacks::registerCallbackNames( $target, @_ ); + _inject_code( $target, "callback_names", *_handler_callbacks ); } sub _install_app { diff --git a/core/lib/Foswiki/Configure/Auth.pm b/core/lib/Foswiki/Configure/Auth.pm index 18bd24f90b..9ca302355e 100644 --- a/core/lib/Foswiki/Configure/Auth.pm +++ b/core/lib/Foswiki/Configure/Auth.pm @@ -2,9 +2,11 @@ package Foswiki::Configure::Auth; +use strict; +use warnings; + use Foswiki::Func; use Foswiki::AccessControlException; -use Foswiki::Contrib::JsonRpcContrib::Error; =begin TML @@ -14,9 +16,6 @@ Implements authorization checking for access to configure. =cut -use strict; -use warnings; - =begin TML ---++ StaticMethod checkAccess( $app, $die ) @@ -53,6 +52,12 @@ sub checkAccess { } unless ($authorized) { if ($json) { + + # NOTE Don't pre-load this module because it'll break + # tools/configure when JsonRpcContrib isn't installed + # (yet). + Foswiki::load_package( + "Foswiki::Contrib::JsonRpcContrib::Error"); throw Foswiki::Contrib::JsonRpcContrib::Error( -32600, 'Access to configure denied by {FeatureAccess}{Configure} Setting' ); @@ -71,6 +76,8 @@ sub checkAccess { else { unless ( Foswiki::Func::isAnAdmin() ) { if ($json) { + Foswiki::load_package( + "Foswiki::Contrib::JsonRpcContrib::Error"); throw Foswiki::Contrib::JsonRpcContrib::Error( -32600, 'Access to configure denied for non-admin users' ); } diff --git a/core/lib/Foswiki/UI/Configure.pm b/core/lib/Foswiki/UI/Configure.pm index ebe9e9edc5..9fbca81575 100644 --- a/core/lib/Foswiki/UI/Configure.pm +++ b/core/lib/Foswiki/UI/Configure.pm @@ -13,8 +13,8 @@ use v5.14; use Assert; -use Foswiki (); -use Foswiki::Configure::Auth (); +use Foswiki (); +require Foswiki::Configure::Auth; use Moo; use namespace::clean; diff --git a/core/lib/Foswiki/Users.pm b/core/lib/Foswiki/Users.pm index eb9424748b..1beaa87745 100644 --- a/core/lib/Foswiki/Users.pm +++ b/core/lib/Foswiki/Users.pm @@ -60,10 +60,8 @@ to a user. use Foswiki::AggregateIterator (); use Foswiki::LoginManager (); -use Moo; -use namespace::clean; +use Foswiki::Class qw(app); extends qw(Foswiki::Object); -with qw(Foswiki::AppObject); use Assert; @@ -135,7 +133,7 @@ sub BUILD { my $app = $this->app; # making basemapping - my $implBaseUserMappingManager = $Foswiki::cfg{BaseUserMappingManager} + my $implBaseUserMappingManager = $app->cfg->data->{BaseUserMappingManager} || 'Foswiki::Users::BaseUserMapping'; Foswiki::load_package($implBaseUserMappingManager); @@ -143,7 +141,8 @@ sub BUILD { #Foswiki::Exception::Fatal->throw( text => $@ ) if $@; $this->basemapping( $this->create($implBaseUserMappingManager) ); - my $implUserMappingManager = $Foswiki::cfg{UserMappingManager} || 'none'; + my $implUserMappingManager = $app->cfg->data->{UserMappingManager} + || 'none'; $implUserMappingManager = 'Foswiki::Users::TopicUserMapping' if ( $implUserMappingManager eq 'none' ); diff --git a/core/tools/configure b/core/tools/configure index 8ac86c30d0..638d8a3052 100755 --- a/core/tools/configure +++ b/core/tools/configure @@ -31,6 +31,7 @@ use Getopt::Long; use Storable qw(dclone); use Pod::Usage (); use Data::Dumper (); +use Try::Tiny; # Assume we are in the tools dir, and we can find bin and lib from there use FindBin; @@ -45,8 +46,9 @@ binmode( STDIN, ':crlf' ); use Assert; use Foswiki; -use Foswiki::Configure::Query; use Foswiki::App; +use Foswiki::Exception; +require Foswiki::Configure::Query; { @@ -97,7 +99,7 @@ use Foswiki::App; $orig->( $this, $k ); print Encode::encode_utf8( - "\$Foswiki::cfg$k = " . $this->changes->{$k} . ";\n"); + "\$Foswiki::cfg$k = " . $this->changes->{$k} . ";\n" ); }; around WIZARD => sub { @@ -258,7 +260,24 @@ sub _prompt { #$Foswiki::Configure::LoadSpec::RAW_VALS = 1; # Initialise -my $app = Foswiki::App->new( env => dclone( \%ENV ), ); + +$SIG{__DIE__} = sub { + + # Somehow overriding of __DIE__ clashes with remote perl debugger in + # Komodo unless we die again instantly. + die $_[0] if (caller)[0] =~ /^DB::/; + Foswiki::Exception::Fatal->rethrow( $_[0] ); +}; + +my $app; +try { + $app = Foswiki::App->new( env => dclone( \%ENV ), ); +} +catch { + my $e = $_; + say STDERR "App creation failed:", Foswiki::Exception::errorStr($e); + exit 1; +}; # Force config re-read to be independant of any possible variations in config # constructor. From 5fcac85155551731f8a04fdd8c667cb93d558497 Mon Sep 17 00:00:00 2001 From: Vadim Belman Date: Mon, 5 Sep 2016 20:05:39 -0400 Subject: [PATCH 6/6] Item13897: OopsException backward compatibility and bug fixes. - Foswiki::OopsException must now support both calling formats: the old-style mixed positional/param and Moo-style fully parametrized. Unchecked. - Accidentally there was _two_ BUILDARGS methods declared for Foswiki::OopsException. Perhaps this why it is called 'oops'? ;) - Fixed tests broken after introduction of Unit::FoswikiTestRole. - Foswiki::Response::ouputHasStarted is now set only by CGI engine and only when engine's write() method is called. For PSGI/Plack it is totally meaningless. - Fixed Unit::TestApp not registering callbacks if created with cloned cfg attribute. - Minor style fixes. --- UnitTestContrib/lib/Unit/TestApp.pm | 2 +- .../test/unit/FoswikiFnTestCase.pm | 3 +- UnitTestContrib/test/unit/ManageDotPmTests.pm | 16 +- UnitTestContrib/test/unit/RegisterTests.pm | 217 +++++++++--------- core/lib/Foswiki/App.pm | 1 - core/lib/Foswiki/Class.pm | 4 +- core/lib/Foswiki/Engine/CGI.pm | 3 + core/lib/Foswiki/Engine/PSGI.pm | 3 +- core/lib/Foswiki/Net.pm | 55 +++-- core/lib/Foswiki/OopsException.pm | 26 +-- core/lib/Foswiki/Response.pm | 55 +++-- 11 files changed, 212 insertions(+), 173 deletions(-) diff --git a/UnitTestContrib/lib/Unit/TestApp.pm b/UnitTestContrib/lib/Unit/TestApp.pm index 34e45e5fd9..84628b3347 100644 --- a/UnitTestContrib/lib/Unit/TestApp.pm +++ b/UnitTestContrib/lib/Unit/TestApp.pm @@ -113,7 +113,7 @@ sub registerCallbacks { $this->_cbRegistered(1); } -before _prepareConfig => sub { +before BUILD => sub { my $this = shift; $this->registerCallbacks; diff --git a/UnitTestContrib/test/unit/FoswikiFnTestCase.pm b/UnitTestContrib/test/unit/FoswikiFnTestCase.pm index 28cce9e07e..d68b2abf5e 100644 --- a/UnitTestContrib/test/unit/FoswikiFnTestCase.pm +++ b/UnitTestContrib/test/unit/FoswikiFnTestCase.pm @@ -31,8 +31,7 @@ use Foswiki::UI::Register(); use Try::Tiny; use Carp qw(cluck); -use Moo; -use namespace::clean; +use Foswiki::Class; extends qw(FoswikiTestCase); has test_user_forename => ( is => 'rw', ); diff --git a/UnitTestContrib/test/unit/ManageDotPmTests.pm b/UnitTestContrib/test/unit/ManageDotPmTests.pm index 1963ecd85a..cd3f611a84 100644 --- a/UnitTestContrib/test/unit/ManageDotPmTests.pm +++ b/UnitTestContrib/test/unit/ManageDotPmTests.pm @@ -225,7 +225,7 @@ sub _registerUserException { }, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); my $exception; try { $this->captureWithKey( @@ -252,7 +252,7 @@ sub _registerUserException { # Reload caches $this->createNewFoswikiApp; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); return $exception; } @@ -814,7 +814,7 @@ sub verify_resetEmailOkay { callbacks => { handleRequestException => \&_cbHRE, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( manage => sub { @@ -923,7 +923,7 @@ EOM callbacks => { handleRequestException => \&_cbHRE, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); # SMELL We've set path_info, web and topic must be set from it. #$req->topic($regTopic); @@ -1071,7 +1071,7 @@ EOM callbacks => { handleRequestException => \&_cbHRE, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { my ($text) = $this->captureWithKey( @@ -1133,7 +1133,7 @@ sub verify_deleteUser { callbacks => { handleRequestException => \&_cbHRE, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1454,7 +1454,7 @@ sub test_createDefaultWeb { callbacks => { handleRequestException => \&_cbHRE, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { my ( $stdout, $stderr, $result ) = @@ -1837,7 +1837,7 @@ sub test_createEmptyWeb { callbacks => { handleRequestException => \&_cbHRE, }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { my ( $stdout, $stderr, $result ) = diff --git a/UnitTestContrib/test/unit/RegisterTests.pm b/UnitTestContrib/test/unit/RegisterTests.pm index 2b25a2a705..884cfae8d5 100644 --- a/UnitTestContrib/test/unit/RegisterTests.pm +++ b/UnitTestContrib/test/unit/RegisterTests.pm @@ -3,7 +3,7 @@ use v5.14; package Foswiki::Exception::RTInfo; -use Moo; +use Foswiki::Class; extends qw(Foswiki::Exception); has template => ( is => 'rw', ); @@ -20,7 +20,6 @@ use diagnostics; #Uncomment to isolate #our @TESTS = qw(notest_registerVerifyOk); #notest_UnregisteredUser); -use Foswiki::UI::Register(); use Data::Dumper; use FileHandle(); use File::Copy(); @@ -32,8 +31,7 @@ use Try::Tiny; # Note that the FoswikiFnTestCase needs to use the registration code to work, # so this is a bit arse before tit. However we need some pre-registered users # for this to work sensibly, so we just have to bite the bullet. -use Moo; -use namespace::clean; +use Foswiki::Class; extends qw( FoswikiFnTestCase ); has regUI => ( @@ -189,7 +187,7 @@ EOF Foswiki::Exception::Fatal->rethrow($_); }; - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); return; }; @@ -262,7 +260,7 @@ sub registerAccount { ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->regUI->_action_verify; @@ -274,9 +272,10 @@ sub registerAccount { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "thanks", $e->def, $e->stringify() ); - $this->assert_equals( 2, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 2, + scalar(@Unit::FoswikiTestRole::mails) ); my $done = ''; - foreach my $mail (@FoswikiFnTestCase::mails) { + foreach my $mail (@Unit::FoswikiTestRole::mails) { if ( $mail->header('Subject') =~ m/Registration for/m ) { my $new_user_email = $this->new_user_email; if ( $mail->header('To') =~ m/\b$new_user_email\b/m ) { @@ -295,7 +294,7 @@ qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, } } $this->assert($done); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->rethrow; @@ -707,7 +706,7 @@ sub registerVerifyOk { callbacks => { handleRequestException => \&_cbHRE }, ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -751,7 +750,7 @@ sub registerVerifyOk { $cfgData = $this->app->cfg->data; $this->app->heap->{DebugVerificationCode} = $code; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); $code = $this->app->request->param('code'); my $data = $this->regUI->_loadPendingRegistration($code); @@ -759,9 +758,9 @@ sub registerVerifyOk { $this->assert_equals( $data->{VerificationCode}, $code ); $this->assert( $data->{Email} ); - $this->assert_equals( 1, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 1, scalar(@Unit::FoswikiTestRole::mails) ); my $done = ''; - foreach my $mail (@FoswikiFnTestCase::mails) { + foreach my $mail (@Unit::FoswikiTestRole::mails) { my $body = $mail->body(); if ( $body =~ m/Your verification code is /m ) { $this->assert( !$done, $done . "\n---------\n" . $body ); @@ -773,7 +772,7 @@ sub registerVerifyOk { #} } $this->assert($done); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); # We're sitting with a valid verification code waiting for the next step # i.e. need to _verify @@ -830,7 +829,7 @@ sub _registerBadVerify { ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( register => sub { return $this->app->handleRequest; }, ); @@ -869,7 +868,7 @@ sub _registerBadVerify { ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->regUI->_action_verify; @@ -892,8 +891,8 @@ sub _registerBadVerify { text => "Expected a redirect but received: " . $e ); } }; - $this->assert_equals( 1, scalar(@FoswikiFnTestCase::mails) ); - my $mess = $FoswikiFnTestCase::mails[0]; + $this->assert_equals( 1, scalar(@Unit::FoswikiTestRole::mails) ); + my $mess = $Unit::FoswikiTestRole::mails[0]; $this->assert_matches( qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, $mess->header('From') ); @@ -960,7 +959,7 @@ sub _registerNoVerifyOk { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -972,9 +971,9 @@ sub _registerNoVerifyOk { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "thanks", $e->def, $e->stringify() ); - $this->assert_equals( 2, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 2, scalar(@Unit::FoswikiTestRole::mails) ); my $done = ''; - foreach my $mail (@FoswikiFnTestCase::mails) { + foreach my $mail (@Unit::FoswikiTestRole::mails) { if ( $mail->header('Subject') =~ m/^.*Registration for/m ) { my $new_user_email = $this->new_user_email; if ( $mail->header('To') =~ m/^.*\b$new_user_email\b/m ) { @@ -994,7 +993,7 @@ qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, } } $this->assert($done); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1043,7 +1042,7 @@ sub verify_rejectShortPassword { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1056,8 +1055,8 @@ sub verify_rejectShortPassword { $e->stringify() ); $this->assert_str_equals( "bad_password", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); - @FoswikiFnTestCase::mails = (); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1107,7 +1106,7 @@ sub verify_userTopictemplate { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1120,8 +1119,8 @@ sub verify_userTopictemplate { $e->stringify() ); $this->assert_str_equals( "bad_templatetopic", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); - @FoswikiFnTestCase::mails = (); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1157,7 +1156,7 @@ sub verify_userTopictemplate { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1236,7 +1235,7 @@ sub verify_rejectDuplicateEmail { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1248,9 +1247,9 @@ sub verify_rejectDuplicateEmail { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "thanks", $e->def, $e->stringify() ); - $this->assert_equals( 2, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 2, scalar(@Unit::FoswikiTestRole::mails) ); my $done = ''; - foreach my $mail (@FoswikiFnTestCase::mails) { + foreach my $mail (@Unit::FoswikiTestRole::mails) { if ( $mail->header('Subject') =~ m/^.*Registration for/m ) { if ( $mail->header('To') =~ m/^.*\bjoe\@gooddomain.net\b/m ) { @@ -1270,7 +1269,7 @@ qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, } } $this->assert($done); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1305,7 +1304,7 @@ qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1317,8 +1316,8 @@ qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "dup_email", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); - @FoswikiFnTestCase::mails = (); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1368,7 +1367,7 @@ sub verify_rejectDuplicatePendingEmail { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1382,7 +1381,7 @@ sub verify_rejectDuplicatePendingEmail { $this->assert_str_equals( "confirm", $e->def, $e->stringify() ); $this->assert_matches( 'joe@dupdomain.net', $e->params->[0], $e->stringify() ); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1409,7 +1408,7 @@ sub verify_rejectDuplicatePendingEmail { # #$query->path_info( "/" . $this->users_web . "/UserRegistration" ); #$this->createNewFoswikiSession( $cfgData->{DefaultUserLogin}, $query ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); $cfgData->{Register}{NeedVerification} = 1; $cfgData->{Register}{UniqueEmail} = 1; @@ -1427,8 +1426,8 @@ sub verify_rejectDuplicatePendingEmail { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "dup_email", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); - @FoswikiFnTestCase::mails = (); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1480,7 +1479,7 @@ sub verify_rejectFilteredEmail { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1492,8 +1491,8 @@ sub verify_rejectFilteredEmail { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "rej_email", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); - @FoswikiFnTestCase::mails = (); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1528,7 +1527,7 @@ sub verify_rejectFilteredEmail { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1540,9 +1539,9 @@ sub verify_rejectFilteredEmail { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "thanks", $e->def, $e->stringify() ); - $this->assert_equals( 2, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 2, scalar(@Unit::FoswikiTestRole::mails) ); my $done = ''; - foreach my $mail (@FoswikiFnTestCase::mails) { + foreach my $mail (@Unit::FoswikiTestRole::mails) { if ( $mail->header('Subject') =~ m/^.*Registration for/m ) { if ( $mail->header('To') =~ m/^.*\bjoe\@gooddomain.net\b/m ) { @@ -1562,7 +1561,7 @@ qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, } } $this->assert($done); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1611,7 +1610,7 @@ sub verify_rejectEvilContent { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1624,7 +1623,7 @@ sub verify_rejectEvilContent { $this->assert_matches( qr/.*Comment: <blah>.*Organization: <script>Bad stuff<\/script>/ms, - $FoswikiFnTestCase::mails[0]->body() + $Unit::FoswikiTestRole::mails[0]->body() ); my ($meta) = Foswiki::Func::readTopic( $cfgData->{UsersWebName}, @@ -1681,7 +1680,7 @@ sub verify_shortPassword { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1699,10 +1698,10 @@ sub verify_shortPassword { $e->stringify() ); $this->assert_str_equals( "bad_password", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); -# don't check the FoswikiFnTestCase::mails in this test case - this is done elsewhere - @FoswikiFnTestCase::mails = (); +# don't check the Unit::FoswikiTestRole::mails in this test case - this is done elsewhere + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1748,7 +1747,7 @@ sub verify_duplicateActivation { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( register => sub { return $this->app->handleRequest; }, ); @@ -1793,7 +1792,7 @@ sub verify_duplicateActivation { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1814,7 +1813,7 @@ sub verify_duplicateActivation { }; # and now for something completely different: Do it all over again - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); $this->createNewFoswikiApp( requestParams => { @@ -1833,7 +1832,7 @@ sub verify_duplicateActivation { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1846,7 +1845,7 @@ sub verify_duplicateActivation { $e->stringify() ); $this->assert_str_equals( "duplicate_activation", $e->def, $e->stringify() ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); } else { $e->_set_text( "expected an oops redirect but received: " @@ -1854,7 +1853,7 @@ sub verify_duplicateActivation { $e->rethrow; } }; - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); return; } @@ -1899,7 +1898,7 @@ sub verify_resetPasswordOkay { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1918,8 +1917,8 @@ sub verify_resetPasswordOkay { $e->rethrow; } }; - $this->assert_equals( 1, scalar(@FoswikiFnTestCase::mails) ); - my $mess = $FoswikiFnTestCase::mails[0]; + $this->assert_equals( 1, scalar(@Unit::FoswikiTestRole::mails) ); + my $mess = $Unit::FoswikiTestRole::mails[0]; $this->assert_matches( qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, $mess->header('From') ); @@ -1958,7 +1957,7 @@ sub verify_resetPasswordNoSuchUser { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -1977,7 +1976,7 @@ sub verify_resetPasswordNoSuchUser { $e->rethrow; } }; - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); return; } @@ -2007,7 +2006,7 @@ sub verify_resetPasswordNeedPrivilegeForMultipleReset { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2027,7 +2026,7 @@ sub verify_resetPasswordNeedPrivilegeForMultipleReset { $e->rethrow; } }; - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); return; } @@ -2063,7 +2062,7 @@ sub verify_resetPasswordNoPassword { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2084,8 +2083,8 @@ sub verify_resetPasswordNoPassword { }; # If the user is not in htpasswd, there's can't be an email - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); - @FoswikiFnTestCase::mails = (); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); + @Unit::FoswikiTestRole::mails = (); return; } @@ -2131,7 +2130,7 @@ sub verify_UnregisteredUser { }; # $this->assert_null( UnregisteredUser::reloadUserContext($code)); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); return; } @@ -2208,7 +2207,7 @@ sub verify_buildRegistrationEmail { $this->createNewFoswikiApp( engineParams => { initialAttributes => { user => $cfgData->{DefaultUserLogin}, }, } ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); my $actual = $this->regUI->_buildConfirmationEmail( \%data, @@ -2234,7 +2233,7 @@ sub verify_buildRegistrationEmail { $this->assert( $actual =~ m/^\s*\*\s*Name:\s*$new_user_fullname$/, $actual ); - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); return; } @@ -2290,7 +2289,7 @@ sub verify_disabled_registration { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2349,7 +2348,7 @@ sub test_PendingRegistrationManualCleanup { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2422,7 +2421,7 @@ sub test_PendingRegistrationAutoCleanup { ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2452,12 +2451,12 @@ sub test_PendingRegistrationAutoCleanup { utime( $mtime, $mtime, $file ) || $this->assert( 0, "couldn't touch $file: $!" ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { - no strict 'refs'; $this->captureWithKey( register => sub { return $this->app->handleRequest; }, ); + $this->reCreateFoswikiApp; $this->captureWithKey( register => sub { return $this->app->handleRequest; }, ); } @@ -2514,7 +2513,7 @@ sub test_Item12205 { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2584,7 +2583,7 @@ sub test_3951 { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2648,7 +2647,7 @@ sub test_4061 { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); $this->assert( open( my $fh, "<:encoding(utf-8)", $cfgData->{Htpasswd}{FileName} ) ); @@ -2768,7 +2767,7 @@ sub verify_resetPassword_NoWikiUsersEntry { callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->captureWithKey( @@ -2787,8 +2786,8 @@ sub verify_resetPassword_NoWikiUsersEntry { $e->rethrow; } }; - $this->assert_equals( 1, scalar(@FoswikiFnTestCase::mails) ); - my $mess = $FoswikiFnTestCase::mails[0]; + $this->assert_equals( 1, scalar(@Unit::FoswikiTestRole::mails) ); + my $mess = $Unit::FoswikiTestRole::mails[0]; $this->assert_matches( qr/$cfgData->{WebMasterName} <$cfgData->{WebMasterEmail}>/, $mess->header('From') ); @@ -2832,7 +2831,7 @@ sub registerUserException { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); my $exception; try { $this->captureWithKey( @@ -2867,7 +2866,7 @@ sub registerUserException { # Reload caches $this->reCreateFoswikiApp; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); return $exception; } @@ -3085,7 +3084,7 @@ sub verify_registerVerifyOKApproved { # setting was established, and will always have a LoginName $this->registerUserException( 'asdf', 'Rego', 'Approver', 'approve@example.com' ); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); $cfgData->{Register}{NeedVerification} = 1; @@ -3111,7 +3110,7 @@ sub verify_registerVerifyOKApproved { ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); $cfgData->{Register}{NeedApproval} = 1; $cfgData->{Register}{Approvers} = 'RegoApprover'; @@ -3124,8 +3123,8 @@ sub verify_registerVerifyOKApproved { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "approve", $e->def ); - $this->assert_equals( 1, scalar(@FoswikiFnTestCase::mails) ); - foreach my $mail (@FoswikiFnTestCase::mails) { + $this->assert_equals( 1, scalar(@Unit::FoswikiTestRole::mails) ); + foreach my $mail (@Unit::FoswikiTestRole::mails) { $this->assert_matches( qr/registration approval required/m, $mail->header('Subject') ); $this->assert_matches( qr/RegoApprover /m, @@ -3141,7 +3140,7 @@ sub verify_registerVerifyOKApproved { $this->assert_equals( $this->app->heap->{DebugVerificationCode}, $1 ); } - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -3166,8 +3165,11 @@ sub verify_registerVerifyOKApproved { }, callbacks => { handleRequestException => \&_cbHRE }, - # Preserve the heap data. - heap => $this->_cloneData( $this->app->heap, 'heap' ), + # Preserve the heap data Debug.* keys. + heap => { + map { $_ => $this->app->heap->{$_} } + grep { /^Debug/ } keys %{ $this->app->heap } + }, ); # Make sure we get bounced unless we are logged in @@ -3195,9 +3197,14 @@ sub verify_registerVerifyOKApproved { }, }, callbacks => { handleRequestException => \&_cbHRE }, - heap => $this->_cloneData( $this->app->heap, 'heap' ), + + # Preserve the heap data Debug.* keys. + heap => { + map { $_ => $this->app->heap->{$_} } + grep { /^Debug/ } keys %{ $this->app->heap } + }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->regUI->_action_approve; @@ -3212,8 +3219,8 @@ sub verify_registerVerifyOKApproved { $this->assert_str_equals( "rego_approved", $e->def ); # Make sure the confirmations are sent; one to the user, one to the admin - $this->assert_equals( 2, scalar(@FoswikiFnTestCase::mails) ); - foreach my $mail (@FoswikiFnTestCase::mails) { + $this->assert_equals( 2, scalar(@Unit::FoswikiTestRole::mails) ); + foreach my $mail (@Unit::FoswikiTestRole::mails) { if ( $mail->header('To') =~ m/^Wiki/m ) { $this->assert_matches( qr/^Wiki Administrator/m, $mail->header('To') ); @@ -3226,7 +3233,7 @@ sub verify_registerVerifyOKApproved { qr/^Foswiki - Registration for WalterPigeon/m, $mail->header('Subject') ); } - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -3255,7 +3262,7 @@ sub verify_registerVerifyOKDisapproved { # setting was established, and will always have a LoginName $this->registerUserException( 'asdf', 'Rego', 'Approver', 'approve@example.com' ); - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); $cfgData->{Register}{NeedVerification} = 1; @@ -3281,7 +3288,7 @@ sub verify_registerVerifyOKDisapproved { ); $cfgData = $this->app->cfg->data; - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); $cfgData->{Register}{NeedApproval} = 1; $cfgData->{Register}{Approvers} = 'RegoApprover'; @@ -3294,8 +3301,8 @@ sub verify_registerVerifyOKDisapproved { $this->assert_str_equals( $REG_TMPL, $e->template, $e->stringify() ); $this->assert_str_equals( "approve", $e->def ); - $this->assert_equals( 1, scalar(@FoswikiFnTestCase::mails) ); - foreach my $mail (@FoswikiFnTestCase::mails) { + $this->assert_equals( 1, scalar(@Unit::FoswikiTestRole::mails) ); + foreach my $mail (@Unit::FoswikiTestRole::mails) { $this->assert_matches( qr/^.* registration approval required/m, $mail->header('Subject') ); $this->assert_matches( @@ -3312,7 +3319,7 @@ sub verify_registerVerifyOKDisapproved { $this->assert_equals( $this->app->heap->{DebugVerificationCode}, $1 ); } - @FoswikiFnTestCase::mails = (); + @Unit::FoswikiTestRole::mails = (); } else { $e->_set_text( "expected an oops redirect but received: " @@ -3338,7 +3345,7 @@ sub verify_registerVerifyOKDisapproved { }, callbacks => { handleRequestException => \&_cbHRE }, ); - $this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail ); + $this->app->net->setMailHandler( $this->can('sentMail') ); try { $this->regUI->_action_disapprove; @@ -3353,7 +3360,7 @@ sub verify_registerVerifyOKDisapproved { $this->assert_str_equals( "rego_denied", $e->def ); # Make sure no mails are sent (yet) - $this->assert_equals( 0, scalar(@FoswikiFnTestCase::mails) ); + $this->assert_equals( 0, scalar(@Unit::FoswikiTestRole::mails) ); } else { $e->_set_text( "expected an oops redirect but received: " diff --git a/core/lib/Foswiki/App.pm b/core/lib/Foswiki/App.pm index 0e24342cc2..2f93f7d75f 100644 --- a/core/lib/Foswiki/App.pm +++ b/core/lib/Foswiki/App.pm @@ -577,7 +577,6 @@ sub handleRequest { }; my $return = $res->as_array; - $res->outputHasStarted(1); $rc = $this->engine->finalizeReturn($return); # Clean up sessions before we finish. diff --git a/core/lib/Foswiki/Class.pm b/core/lib/Foswiki/Class.pm index decbcd824b..ae725e335c 100644 --- a/core/lib/Foswiki/Class.pm +++ b/core/lib/Foswiki/Class.pm @@ -172,7 +172,7 @@ sub _assign_role { push @{ $_assignedRoles{$class} }, $role; } -sub _handler_callbacks { +sub _handler_callback_names { my $target = caller; Foswiki::Aux::Callbacks::registerCallbackNames( $target, @_ ); } @@ -182,7 +182,7 @@ sub _install_callbacks { Foswiki::load_package('Foswiki::Aux::Callbacks'); _assign_role( $target, 'Foswiki::Aux::Callbacks' ); - _inject_code( $target, "callback_names", *_handler_callbacks ); + _inject_code( $target, "callback_names", *_handler_callback_names ); } sub _install_app { diff --git a/core/lib/Foswiki/Engine/CGI.pm b/core/lib/Foswiki/Engine/CGI.pm index e76bb60598..b960ca5031 100644 --- a/core/lib/Foswiki/Engine/CGI.pm +++ b/core/lib/Foswiki/Engine/CGI.pm @@ -384,6 +384,9 @@ around stringifyHeaders => sub { around write => sub { my $orig = shift; my ( $this, $buffer ) = @_; + + # This is the only location where we know EXACTLY that output has started. + $this->response->outputHasStarted(1); print $buffer; }; diff --git a/core/lib/Foswiki/Engine/PSGI.pm b/core/lib/Foswiki/Engine/PSGI.pm index 13538fd396..cca9c3a1b3 100644 --- a/core/lib/Foswiki/Engine/PSGI.pm +++ b/core/lib/Foswiki/Engine/PSGI.pm @@ -17,8 +17,7 @@ use Assert; use Plack::Request; use Unicode::Normalize; -use Moo; -use namespace::clean; +use Foswiki::Class; extends qw(Foswiki::Engine); use constant HTTP_COMPLIANT => 1; diff --git a/core/lib/Foswiki/Net.pm b/core/lib/Foswiki/Net.pm index 4b5fe40333..ffa0bee803 100644 --- a/core/lib/Foswiki/Net.pm +++ b/core/lib/Foswiki/Net.pm @@ -21,10 +21,8 @@ use URI; use Foswiki::IP qw/:regexp :info $IPv6Avail/; -use Moo; -use namespace::clean; +use Foswiki::Class qw(app); extends qw(Foswiki::Object); -with qw(Foswiki::AppObject); BEGIN { if ( $Foswiki::cfg{UseLocale} ) { @@ -302,7 +300,7 @@ sub getExternalResource { } } catch { - my $message = ref($_) ? $_->stringify : $_; + my $message = Foswiki::Exception::errorStr($_); $response = $this->create( 'Foswiki::Net::HTTPResponse', message => $message ); }; @@ -350,6 +348,8 @@ sub _logMailError { my $this = shift; my $level = shift; + my $cfgData = $this->app->cfg->data; + my $msg = join( '', @_ ); chomp $msg; @@ -361,7 +361,7 @@ sub _logMailError { $die = 1; } - if ( $Foswiki::cfg{SMTP}{Debug} ) { + if ( $cfgData->{SMTP}{Debug} ) { _throwMsg( $level, $msg ) if ($die); chomp $msg; $msg =~ s,\n,\n -- ,g; @@ -374,7 +374,7 @@ sub _logMailError { $logger = $this->app->logger; } else { - $logger = $Foswiki::cfg{Log}{Implementation}; + $logger = $cfgData->{Log}{Implementation}; if ($logger) { eval "require $logger;"; die "Can't load $logger: $!\n" if ($@); @@ -462,7 +462,7 @@ sub _installMailHandler { } } - if ( !$handler && $Foswiki::cfg{MailProgram} ) { + if ( !$handler && $this->app->cfg->data->{MailProgram} ) { $handler = \&_sendEmailBySendmail; #_logMailError('debug', "Set EMAIL HANDLER to $this->{MAIL_METHOD} $Foswiki::cfg{MailProgram}" ); @@ -486,6 +486,7 @@ alternative mail handling method. sub setMailHandler { my ( $this, $fnref ) = @_; + ASSERT( $fnref, "Mail handler code ref must not be undef" ) if DEBUG; $this->mailHandler($fnref); } @@ -507,7 +508,7 @@ sub sendEmail { #_logMailError('debug', "sendEmail Entered"); - unless ( $Foswiki::cfg{EnableEmail} ) { + unless ( $this->app->cfg->data->{EnableEmail} ) { return 'Cannot send mail: Foswiki email is disabled'; } @@ -614,14 +615,16 @@ sub _slurpFile( $$ ) { sub _smimeSignMessage { my $this = shift; + my $cfgData = $this->app->cfg->data; + my ( $certFile, $keyFile ) = ( - $Foswiki::cfg{Email}{SmimeCertificateFile}, - $Foswiki::cfg{Email}{SmimeKeyFile} + $cfgData->{Email}{SmimeCertificateFile}, + $cfgData->{Email}{SmimeKeyFile} ); unless ( $certFile && $keyFile ) { ( $certFile, $keyFile ) = ( - "$Foswiki::cfg{DataDir}/SmimeCertificate.pem", - "$Foswiki::cfg{DataDir}/SmimePrivateKey.pem" + $cfgData->{DataDir} . "/SmimeCertificate.pem", + $cfgData->{DataDir} . "/SmimePrivateKey.pem" ); unless ( $certFile && $keyFile && -r $certFile && -r $keyFile ) { @@ -645,8 +648,8 @@ sub _smimeSignMessage { # Decrypt key if password specified and file has encryption header. - if ( exists $Foswiki::cfg{Email}{SmimeKeyPassword} - && length $Foswiki::cfg{Email}{SmimeKeyPassword} + if ( exists $cfgData->{Email}{SmimeKeyPassword} + && length $cfgData->{Email}{SmimeKeyPassword} && $key =~ m/^-----BEGIN RSA PRIVATE KEY-----\n(?:(.*?\n)\n)?/s ) { my %h; @@ -670,12 +673,12 @@ sub _smimeSignMessage { #>>> $key = $pem->decode( Content => $key, - Password => $Foswiki::cfg{Email}{SmimeKeyPassword} + Password => $cfgData->{Email}{SmimeKeyPassword} ); unless ($key) { $this->_logMailError( 'die', "Unable to decrypt " - . $Foswiki::cfg{Email}{SmimeKeyFile} . ": " + . $cfgData->{Email}{SmimeKeyFile} . ": " . $pem->errstr . ". Mail will not be sent." ); return; @@ -731,10 +734,12 @@ sub _fixEmail { require POSIX; POSIX->import(qw(locale_h)); + my $cfgData = $this->app->cfg->data; + my $old_locale = POSIX::setlocale( LC_TIME() ); POSIX::setlocale( LC_TIME(), 'C' ); my $dateStr; - if ( $Foswiki::cfg{Email}{Servertime} ) { + if ( $cfgData->{Email}{Servertime} ) { $dateStr = POSIX::strftime( '%a, %d %b %Y %T %z', localtime(time) ); } else { @@ -749,7 +754,7 @@ sub _fixEmail { $email->header_str_set( $header, $email->header($header) ); } - if ( $Foswiki::cfg{Email}{EnableSMIME} ) { + if ( $cfgData->{Email}{EnableSMIME} ) { # TODO That would be much better to teach _smimeSignMessage to work # with pre-parsed email object. So far – this hack will do the job. @@ -764,14 +769,16 @@ sub _fixEmail { sub _sendEmailBySendmail { my ( $this, $email ) = @_; + my $cfgData = $this->app->cfg->data; + # With feedback, unsaved values are tainted. # We don't have special priveleges (or shouldn't), and # MailProgram allows specifying an arbitrary command - e.g. rm. # So there's not much point in trying to be defensive here. - my $mailer = $Foswiki::cfg{MailProgram} || ''; - $mailer .= ' ' . ( $Foswiki::cfg{SMTP}{DebugFlags} || '' ) - if ( $Foswiki::cfg{SMTP}{Debug} && $Foswiki::cfg{SMTP}{DebugFlags} ); + my $mailer = $cfgData->{MailProgram} || ''; + $mailer .= ' ' . ( $cfgData->{SMTP}{DebugFlags} || '' ) + if ( $cfgData->{SMTP}{Debug} && $cfgData->{SMTP}{DebugFlags} ); $mailer =~ m/^(.*)$/; $mailer = $1; @@ -808,7 +815,9 @@ sub _sendEmailByNetSMTP { # XXX Check if our'ing of this has any impact on the functionality. my ( $this, $email ) = @_; - my $debug = $Foswiki::cfg{SMTP}{Debug} || 0; + my $cfgData = $this->app->cfg->data; + + my $debug = $cfgData->{SMTP}{Debug} || 0; my $from = ''; my @to = (); @@ -934,7 +943,7 @@ sub _sendEmailByNetSMTP { $smtp->startTLS( $this, $host ) if ($starttls); my ( $username, $password ) = - ( $Foswiki::cfg{SMTP}{Username}, $Foswiki::cfg{SMTP}{Password} ); + ( $cfgData->{SMTP}{Username}, $cfgData->{SMTP}{Password} ); $username = '' unless ( defined $username ); $password = '' unless ( defined $password ); diff --git a/core/lib/Foswiki/OopsException.pm b/core/lib/Foswiki/OopsException.pm index a6bb47062a..0cf6baf157 100644 --- a/core/lib/Foswiki/OopsException.pm +++ b/core/lib/Foswiki/OopsException.pm @@ -154,6 +154,19 @@ around BUILDARGS => sub { my $orig = shift; my $class = shift; + if ( ( @_ % 2 == 1 ) && ( scalar(@_) > 1 || ref( $_[0] ) ne 'HASH' ) ) { + + # Add 'template' key to make arguments a valid key/value list. + # I.e. we suppose that the old calling format has been used with + # template name as the first positional argument. + # The old calling format also means that there is no `app' key. We + # add it manually. Sorry if won't always work as excepted, but + # there is no valid solution for this situation. `app' is added to + # the start of the list so that user provided key will override our + # default. + unshift @_, app => $Foswiki::app, 'template'; + } + my %params = @_; if ( defined $params{params} && !( ref( $params{params} ) eq 'ARRAY' ) ) { @@ -176,19 +189,6 @@ sub BUILD { $this->_set_text( $this->stringify ); } -around BUILDARGS => sub { - my $orig = shift; - my $class = shift; - - # Check if we have received a valid key/value pair parameters including - # template => 'tmpl'. - if ( ( @_ % 2 == 1 ) && ( scalar(@_) > 1 || ref( $_[0] ) ne 'HASH' ) ) { - my $template = shift; - return $orig->( $class, template => $template, @_ ); - } - return $orig->( $class, @_ ); -}; - =begin TML ---++ ObjectMethod stringify( [$wihtTemplate] ) -> $string diff --git a/core/lib/Foswiki/Response.pm b/core/lib/Foswiki/Response.pm index ea0e9f4a9a..2d9152b063 100644 --- a/core/lib/Foswiki/Response.pm +++ b/core/lib/Foswiki/Response.pm @@ -15,15 +15,13 @@ Fields: =cut package Foswiki::Response; -use v5.14; -use Assert; +use Assert; use CGI::Util (); +use Carp (); -use Moo; -use namespace::clean; +use Foswiki::Class qw(app); extends qw(Foswiki::Object); -with qw(Foswiki::AppObject); BEGIN { if ( $Foswiki::cfg{UseLocale} ) { @@ -75,7 +73,15 @@ cannot be changed (though the body can be modified) =cut -has outputHasStarted => ( is => 'rw', lazy => 1, default => 0, ); +has _outputStartedAt => ( is => 'rw', lazy => 1, default => '', ); +has outputHasStarted => ( + is => 'rw', + lazy => 1, + default => 0, + trigger => sub { + $_[0]->_outputStartedAt( Carp::longmess('') ) if DEBUG; + }, +); =begin TML @@ -105,8 +111,7 @@ has status => ( is => 'rw', default => 200, trigger => sub { - ASSERT( !$_[0]->outputHasStarted, 'Too late to change status' ) - if DEBUG; + $_[0]->_checkStartedOutput('Too late to change status'); }, coerce => sub { $_[0] =~ m/^(\d{3})/ ? int($1) : undef; @@ -118,8 +123,7 @@ has headers => ( default => sub { {} }, trigger => sub { my $this = shift; - ASSERT( !$this->outputHasStarted, 'Too late to change headers' ) - if DEBUG; + $this->_checkStartedOutput('Too late to change headers'); my $headers = $this->headers; if ( defined $headers->{'Set-Cookie'} ) { my @cookies = @@ -169,7 +173,7 @@ sub header { my ( $this, @p ) = @_; my (@header); - ASSERT( !$this->outputHasStarted, 'Too late to change headers' ) if DEBUG; + $this->_checkStartedOutput('Too late to change headers'); # Ugly hack to avoid html escape in CGI::Util::rearrange local $CGI::Q = { escape => 0 }; @@ -390,7 +394,7 @@ Deletes headers whose names are passed. sub deleteHeader { my $this = shift; - ASSERT( !$this->outputHasStarted, 'Too late to change headers' ) if DEBUG; + $this->_checkStartedOutput('Too late to change headers'); foreach (@_) { ( my $hdr = $_ ) =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g; @@ -409,7 +413,7 @@ Adds $value to list of values associated with header $name. sub pushHeader { my ( $this, $hdr, $value ) = @_; - ASSERT( !$this->outputHasStarted, 'Too late to change headers' ) if DEBUG; + $this->_checkStartedOutput('Too late to change headers'); $hdr =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g; my $cur = $this->headers->{$hdr}; @@ -430,8 +434,7 @@ sub pushHeader { sub cookies { my $this = shift; if (@_) { - ASSERT( !$this->outputHasStarted, 'Too late to change cookies' ) - if DEBUG; + $this->_checkStartedOutput('Too late to change cookies'); $this->setCookies(@_) if @_; } return @{ $this->getCookies }; @@ -454,7 +457,7 @@ CGI Compatibility Note: It doesn't support -target or -nph sub redirect { my ( $this, @p ) = @_; - ASSERT( !$this->outputHasStarted, 'Too late to redirect' ) if DEBUG; + $this->_checkStartedOutput('Too late to redirect'); my ( $url, $status, $cookies ) = CGI::Util::rearrange( [ [qw(LOCATION URL URI)], 'STATUS', [qw(COOKIE COOKIES)], ], @p ); @@ -573,6 +576,26 @@ sub as_array { return \@rc; } +# See if output has already been started and fail in DEBUG mode. +sub _checkStartedOutput { + my $this = shift; + my ($msg) = @_; + + if (DEBUG) { + ASSERT( + !$this->outputHasStarted, + $msg + . ( + $this->_outputStartedAt + ? "\n---<<_outputStartedAt + . ">>>---" + : '' + ) + ); + } +} + 1; __END__ Foswiki - The Free and Open Source Wiki, http://foswiki.org/