From ceef63652cf84acbcd0870f155475fa423ee4004 Mon Sep 17 00:00:00 2001 From: "ian%hixie.ch" Date: Fri, 14 Mar 2003 13:08:43 +0000 Subject: [PATCH] Improve the Exception class so it can work out what 'eval' numbers map to; remove the 'properties' stuff since it was taking a good 4% of the overall time of PLIF applications. THIS WILL CAUSE HUGE PROBLEMS WITH PLIF CONSUMERS. I REPEAT, THIS **WILL** BREAK YOUR CODE. DO NOT UPDATE TO THIS CODE IF YOU DON'T WANT TO SPEND A LOT OF TIME UPDATING YOUR CODE\!\!\! --- webtools/PLIF/PLIF.pm | 49 ++------ webtools/PLIF/PLIF/Controller.pm | 40 +++---- webtools/PLIF/PLIF/DataSource.pm | 4 +- webtools/PLIF/PLIF/DataSource/Strings.pm | 30 ++--- .../PLIF/PLIF/Database/ConfigurationFile.pm | 13 +-- webtools/PLIF/PLIF/Database/DBI.pm | 60 +++++----- .../PLIF/PLIF/Database/ResultsFrame/DBI.pm | 28 ++--- webtools/PLIF/PLIF/DatabaseHelper.pm | 2 + webtools/PLIF/PLIF/Exception.pm | 45 +++++++- webtools/PLIF/PLIF/Input.pm | 2 +- webtools/PLIF/PLIF/Input/Arguments.pm | 13 ++- webtools/PLIF/PLIF/Input/CGI.pm | 16 +-- webtools/PLIF/PLIF/Input/CGI/Head.pm | 2 +- webtools/PLIF/PLIF/Input/CGI/PostMultipart.pm | 8 +- webtools/PLIF/PLIF/Input/CGI/PostXMLRPC.pm | 6 +- webtools/PLIF/PLIF/Input/CommandLine.pm | 4 +- webtools/PLIF/PLIF/Output.pm | 18 +-- webtools/PLIF/PLIF/Output/Generic.pm | 34 +++--- webtools/PLIF/PLIF/Output/Generic/AIM.pm | 30 ++--- webtools/PLIF/PLIF/Output/Generic/Email.pm | 36 +++--- webtools/PLIF/PLIF/Program.pm | 39 ++++--- .../PLIF/PLIF/ProtocolHelper/Logout/HTTP.pm | 4 +- .../PLIF/PLIF/Service/Components/Login.pm | 6 +- .../PLIF/PLIF/Service/Components/UserPrefs.pm | 2 +- webtools/PLIF/PLIF/Service/Session.pm | 2 +- webtools/PLIF/PLIF/Service/User.pm | 106 +++++++++--------- webtools/PLIF/PLIF/Service/UserField.pm | 30 ++--- webtools/PLIF/PLIF/Service/WWW.pm | 10 +- webtools/PLIF/PLIF/Service/XMLRPC.pm | 10 +- webtools/PLIF/TODO | 5 + 30 files changed, 337 insertions(+), 317 deletions(-) diff --git a/webtools/PLIF/PLIF.pm b/webtools/PLIF/PLIF.pm index 298958d45dd6..2f65da44becc 100644 --- a/webtools/PLIF/PLIF.pm +++ b/webtools/PLIF/PLIF.pm @@ -40,7 +40,7 @@ my %MODULES = ('PLIF' => 1); # Levels are assumed to be something along the following: # 0 = debugging remarks for the section currently under test # 1 = -# 2 = +# 2 = perl warnings # 3 = # 4 = important warnings (e.g. unexpected but possibly legitimate lack of data) # 5 = important events (e.g. application started) @@ -124,9 +124,9 @@ sub load { } $MODULES{$package} = 1; local $/ = undef; - my $data = "package $package;\nuse strict;\n" . eval "<$package\::DATA>"; + my $data = "package $package;use strict;" . eval "<$package\::DATA>"; #print STDERR "================================================================================\n$data\n================================================================================\n"; - eval $data; + evalString $data, "${package}::DATA block"; if ($@) { $self->error(1, "Error while loading '$package': $@"); } @@ -138,18 +138,9 @@ sub AUTOLOAD { my $name = $AUTOLOAD; syntaxError "Use of inherited AUTOLOAD for non-method $name is deprecated" if not defined($self); $name =~ s/^.*://o; # strip fully-qualified portion - if ($self->propertyImpliedAccessAllowed($name)) { - if (scalar(@_) == 1) { - return $self->propertySet($name, @_); - } elsif (scalar(@_) == 0) { - if ($self->propertyExists($name)) { - return $self->propertyGet($name); - } else { - return $self->propertyGetUndefined($name); - } - } - } - $self->methodMissing($name, @_); + my $method = $self->can('implyMethod'); # get a function pointer + @_ = ($self, $name, @_); # set the arguments + goto &$method; # invoke the method using deep magic } sub propertySet { @@ -159,22 +150,6 @@ sub propertySet { return $self->{$name} = $value; } -sub propertyExists { - # this is not a class method - my $self = shift; - my($name) = @_; - $self->assert($name, 0, 'propertyExists() cannot be called without arguments'); - return exists($self->{$name}); -} - -sub propertyImpliedAccessAllowed { - # this is not (supposed to be) a class method - # my $self = shift; - # my($name) = @_; - # $self->assert($name, 0, 'propertyImpliedAccessAllowed() cannot be called without arguments'); - return 1; -} - sub propertyGet { # this is not a class method my $self = shift; @@ -182,11 +157,7 @@ sub propertyGet { return $self->{$name}; } -sub propertyGetUndefined { - return undef; -} - -sub methodMissing { +sub implyMethod { my $self = shift; my($method) = @_; syntaxError "Tried to access non-existent method '$method' in object '$self'"; @@ -225,9 +196,9 @@ sub error { # the next three lines are a highly magical incantation to remove # this call from the stack so that the stack trace looks like the # previous function raised the exception itself - my $raise = PLIF::Exception->can('raise'); - @_ = ('PLIF::Exception', 'message', join("\n", @data)); - goto &$raise; + my $raise = PLIF::Exception->can('raise'); # get a function pointer + @_ = ('PLIF::Exception', 'message', join("\n", @data)); # set the arguments + goto &$raise; # and invoke the call using deep call stack magic } # this should not be called with the @data containing a trailing dot diff --git a/webtools/PLIF/PLIF/Controller.pm b/webtools/PLIF/PLIF/Controller.pm index 7f17dc48de59..dab487f72a1f 100644 --- a/webtools/PLIF/PLIF/Controller.pm +++ b/webtools/PLIF/PLIF/Controller.pm @@ -43,9 +43,9 @@ sub init { my $self = shift; $self->SUPER::init(@_); # prepare the services array for the registration system - $self->services([]); - $self->objects([]); - $self->servicesHash({}); + $self->{services} = []; + $self->{objects} = []; + $self->{servicesHash} = {}; # perform the registration $self->registerServices(); } @@ -56,7 +56,7 @@ sub init { sub register { my $self = shift; foreach my $service (@_) { - push(@{$self->services}, $service); + push(@{$self->{services}}, $service); my $file = $service; # XXX THIS IS PLATFORM SPECIFIC CODE XXX if ($^O eq 'linux') { @@ -87,7 +87,7 @@ sub addObject { my $self = shift; foreach my $object (@_) { $self->assert(defined($object), 1, 'Internal error: Tried to add undefined object to object list.'); - push(@{$self->objects}, $object); + push(@{$self->{objects}}, $object); } } @@ -95,15 +95,15 @@ sub removeObject { my $self = shift; # XXX for 5.6.1, use this: # foreach my $object (@_) { - # foreach my $index (0..$#{$self->objects}) { - # if ($self->objects->[$index] == $object) { - # delete($self->objects->[$index]); + # foreach my $index (0..$#{$self->{objects}}) { + # if ($self->{objects}->[$index] == $object) { + # delete($self->{objects}->[$index]); # } # } # } # won't work in early perls though, so instead: my $objects = []; - object: foreach my $object (@{$self->objects}) { + object: foreach my $object (@{$self->{objects}}) { foreach my $removee (@_) { if ($object == $removee) { next object; @@ -111,16 +111,16 @@ sub removeObject { } push(@$objects, $objects); } - $self->objects($objects); + $self->{objects} = $objects; } sub getService { my $self = shift; my($name) = @_; - if (defined($self->servicesHash->{$name})) { - return $self->servicesHash->{$name}; + if (defined($self->{servicesHash}->{$name})) { + return $self->{servicesHash}->{$name}; } - foreach my $service (@{$self->services}) { + foreach my $service (@{$self->{services}}) { if ($service->provides($name)) { # Create the service. If it is already created, this will # just return the object reference, so no harm done. @@ -129,7 +129,7 @@ sub getService { # Doing so would create a circular dependency, resulting # in a memory leak. $service = $service->create($self); - $self->servicesHash->{$name} = $service; + $self->{servicesHash}->{$name} = $service; return $service; } } @@ -141,7 +141,7 @@ sub getObject { # constructor call my $self = shift; my($name) = @_; - foreach my $object (@{$self->objects}) { + foreach my $object (@{$self->{objects}}) { if ($object->objectProvides($name)) { return $object; } @@ -153,7 +153,7 @@ sub getServiceList { my $self = shift; my($name) = @_; my @services = (); - foreach my $service (@{$self->services}) { + foreach my $service (@{$self->{services}}) { if ($service->provides($name)) { # Create the service. If it is already created, this will # just return the object reference, so no harm done. @@ -174,7 +174,7 @@ sub getObjectList { my $self = shift; my($name) = @_; my @objects = (); - foreach my $object (@{$self->objects}) { + foreach my $object (@{$self->{objects}}) { if ($object->objectProvides($name)) { push(@objects, $object); } @@ -215,7 +215,7 @@ sub getSelectingObjectList { sub getServiceInstance { my $self = shift; my($name, @data) = @_; - foreach my $service (@{$self->services}) { + foreach my $service (@{$self->{services}}) { if ($service->provides($name)) { # Create and return the service instance, without storing # a copy. @@ -258,9 +258,9 @@ sub DESTROY { my $self = shift; $self->dump(10, 'At controller shutdown, there were ' . # I assume there will always be > 1 and so haven't bothered to special case the singular grammar - scalar(@{$self->services}) . + scalar(@{$self->{services}}) . ' services registered, of which ' . - scalar(keys(%{$self->servicesHash})) . + scalar(keys(%{$self->{servicesHash}})) . ' had been placed in the services hash.'); $self->SUPER::DESTROY(@_); } diff --git a/webtools/PLIF/PLIF/DataSource.pm b/webtools/PLIF/PLIF/DataSource.pm index c1718ccdd035..6f95877a1d2e 100644 --- a/webtools/PLIF/PLIF/DataSource.pm +++ b/webtools/PLIF/PLIF/DataSource.pm @@ -63,7 +63,7 @@ sub database { } } } - $self->error(1, 'There is no suitable \''.$self->databaseName.'\' database installed.'); + $self->error(1, 'There is no suitable \''.$self->databaseName.'\' database installed'); } sub helper { @@ -86,5 +86,5 @@ sub helper { } } } - $self->error(1, 'Configuration Error: There is no database helper suitable for the \''.$self->databaseName.'\' database installed.'); + $self->error(1, 'Configuration Error: There is no database helper suitable for the \''.$self->databaseName.'\' database installed'); } diff --git a/webtools/PLIF/PLIF/DataSource/Strings.pm b/webtools/PLIF/PLIF/DataSource/Strings.pm index 3ae981f789b7..6c622bf8a347 100644 --- a/webtools/PLIF/PLIF/DataSource/Strings.pm +++ b/webtools/PLIF/PLIF/DataSource/Strings.pm @@ -59,9 +59,9 @@ sub init { $self->SUPER::init(@_); require HTTP::Negotiate; import HTTP::Negotiate; # DEPENDENCY require HTTP::Headers; import HTTP::Headers; # DEPENDENCY - $self->variantsCache({}); - $self->stringsCache({}); - $self->enabled(1); + $self->{variantsCache} = {}; + $self->{stringsCache} = {}; + $self->{enabled} = 1; } # returns ($type, $version, $string) @@ -69,7 +69,7 @@ sub getCustomisedString { my $self = shift; my($app, $session, $protocol, $string) = @_; # error handling makes code ugly :-) - if ($self->enabled) { + if ($self->{enabled}) { my $variant; if (defined($session)) { $variant = $session->selectVariant($protocol); @@ -79,10 +79,10 @@ sub getCustomisedString { # $app->input instead $variant = $self->selectVariant($app, $protocol); } - if (not defined($self->stringsCache->{$variant})) { - $self->stringsCache->{$variant} = {}; + if (not defined($self->{stringsCache}->{$variant})) { + $self->{stringsCache}->{$variant} = {}; } - if (not defined($self->stringsCache->{$variant}->{$string})) { + if (not defined($self->{stringsCache}->{$variant}->{$string})) { my @results; try { @results = $self->getString($app, $variant, $string); @@ -92,13 +92,13 @@ sub getCustomisedString { $self->warn(4, "While I was looking for the string '$string' in protocol '$protocol' using variant '$variant', I failed with: @_"); }; if (@results) { - $self->stringsCache->{$variant}->{$string} = \@results; + $self->{stringsCache}->{$variant}->{$string} = \@results; return @results; } else { return; } } else { - return @{$self->stringsCache->{$variant}->{$string}}; + return @{$self->{stringsCache}->{$variant}->{$string}}; } } else { $self->dump(9, "String datasource is disabled, skipping"); @@ -144,31 +144,31 @@ sub selectVariant { sub variants { my $self = shift; my($app, $protocol) = @_; - if (not defined($self->variantsCache->{$protocol})) { + if (not defined($self->{variantsCache}->{$protocol})) { try { - $self->variantsCache->{$protocol} = $self->getVariants($app, $protocol); + $self->{variantsCache}->{$protocol} = $self->getVariants($app, $protocol); } except { # ok, so, er, it seems that didn't go to well # XXX do we want to do an error here or something? $self->warn(4, "While I was looking for the variants, I failed with: @_"); - $self->variantsCache->{$protocol} = []; # no variants here, no sir! + $self->{variantsCache}->{$protocol} = []; # no variants here, no sir! }; } - return $self->variantsCache->{$protocol}; + return $self->{variantsCache}->{$protocol}; } # setup.events.start sub setupStarting { my $self = shift; my($app) = @_; - $self->enabled(0); + $self->{enabled} = 0; } # setup.events.end sub setupEnding { my $self = shift; my($app) = @_; - $self->enabled(1); + $self->{enabled} = 1; } # setup.install diff --git a/webtools/PLIF/PLIF/Database/ConfigurationFile.pm b/webtools/PLIF/PLIF/Database/ConfigurationFile.pm index 127fe0f88dc9..1a4fba20941d 100644 --- a/webtools/PLIF/PLIF/Database/ConfigurationFile.pm +++ b/webtools/PLIF/PLIF/Database/ConfigurationFile.pm @@ -118,22 +118,17 @@ sub write { sub propertySet { my $self = shift; + my($name, $value) = @_; $self->ensureRead(); - my $result = $self->SUPER::propertySet(@_); $self->{'_DIRTY'} = 1; - return $result; -} - -sub propertyExists { - my $self = shift; - $self->ensureRead(); - return $self->SUPER::propertyExists(@_); + return $self->{$name} = $value; } sub propertyGet { my $self = shift; + my($name) = @_; $self->ensureRead(); - return $self->SUPER::propertyGet(@_); + return $self->{$name}; } sub DESTROY { diff --git a/webtools/PLIF/PLIF/Database/DBI.pm b/webtools/PLIF/PLIF/Database/DBI.pm index fe2d0ff70696..c2840a084dc4 100644 --- a/webtools/PLIF/PLIF/Database/DBI.pm +++ b/webtools/PLIF/PLIF/Database/DBI.pm @@ -57,34 +57,40 @@ sub init { $self->openDB(@_); } +sub type { + my $self = shift; + syntaxError "type() called with arguments" if @_; + return $self->{type}; +} + sub openDB { my $self = shift; my($app) = @_; try { $self->getConfig($app); } except { - $self->handle(undef); - $self->errstr(@_); + $self->{handle} = undef; + $self->{errstr} = @_; $self->dump(9, "failed to get the database configuration, not going to bother to connect: @_"); } otherwise { try { - $self->handle(DBI->connect($self->connectString, $self->username, $self->password, - {RaiseError => 0, PrintError => 0, AutoCommit => 1, Taint => 1})); - $self->errstr($DBI::errstr); + $self->{handle} = DBI->connect($self->connectString, $self->{username}, $self->{password}, + {RaiseError => 0, PrintError => 0, AutoCommit => 1, Taint => 1}); + $self->{errstr} = $DBI::errstr; $self->dump(9, 'created a database object without raising an exception'); } except { - $self->handle(undef); - $self->errstr(@_); - $self->error(1, "failed to connect to the database because of @_"); + $self->{handle} = undef; + $self->{errstr} = @_; + $self->error(1, "failed to connect to the database: @_"); } } } sub closeDB { my $self = shift; - if ($self->handle) { - $self->handle->disconnect(); - $self->handle(undef); + if ($self->{handle}) { + $self->{handle}->disconnect(); + $self->{handle} = undef; } } @@ -92,14 +98,14 @@ sub connectString { my $self = shift; my($name) = @_; if (not defined($name)) { - $name = $self->name; + $name = $self->{name}; } - return 'DBI:'.($self->type).':'.($name).':'.($self->host).':'.($self->port); + return 'DBI:'.($self->{type}).':'.($name).':'.($self->{host}).':'.($self->{port}); } sub lastError { my $self = shift; - return $self->handle->err; + return $self->{handle}->err; } sub prepare { @@ -123,9 +129,9 @@ sub attempt { sub createResultsFrame { my $self = shift; my($statement, $execute, @values) = @_; - $self->assert($self->handle, 1, 'No database handle: '.(defined($self->errstr) ? $self->errstr : 'unknown error')); + $self->assert($self->{handle}, 1, 'No database handle: '.(defined($self->{errstr}) ? $self->{errstr} : 'unknown error')); $statement =~ /^(.*)$/os; # untaint # (XXX?) - my $handle = $self->handle->prepare($1); + my $handle = $self->{handle}->prepare($1); if ($handle) { return PLIF::Database::ResultsFrame::DBI->create($handle, $self, $execute, @values); } else { @@ -204,7 +210,7 @@ sub setupConfigure { my $return; $app->output->setupProgress("$prefix.admin.checking"); try { - DBI->connect($self->connectString, $self->username, $self->password, + DBI->connect($self->connectString, $self->{username}, $self->{password}, {RaiseError => 1, PrintError => 0, AutoCommit => 1, Taint => 1})->disconnect(); } except { $return = $self->setupConfigureDatabase($app, $prefix); @@ -273,31 +279,31 @@ sub setupConfigureDatabase { my @helpers = $app->getServiceList('database.helper'); helper: foreach my $helperInstance (@helpers) { foreach my $helperType ($helperInstance->databaseType) { - if ($helperType eq $self->type) { + if ($helperType eq $self->{type}) { $helper = $helperInstance; last helper; } } } - $self->assert(defined($helper), 1, 'No database helper installed for database type \''.$self->type.'\''); + $self->assert(defined($helper), 1, 'No database helper installed for database type \''.$self->{type}.'\''); # connect eval { - $self->handle(DBI->connect($self->connectString($helper->setupDatabaseName), $adminUsername, $adminPassword, - {RaiseError => 0, PrintError => 1, AutoCommit => 1, Taint => 1})); + $self->{handle} = DBI->connect($self->connectString($helper->setupDatabaseName), $adminUsername, $adminPassword, + {RaiseError => 0, PrintError => 1, AutoCommit => 1, Taint => 1}); }; $self->assert((not $@), 1, "Could not connect to database: $@"); - $self->assert($self->handle, 1, 'Failed to connect to database: '.(defined($DBI::errstr) ? $DBI::errstr : 'unknown error')); + $self->assert($self->{handle}, 1, 'Failed to connect to database: '.(defined($DBI::errstr) ? $DBI::errstr : 'unknown error')); # get the helper to do its stuff $helper->setupVerifyVersion($app, $self); - $helper->setupCreateUser($app, $self, $self->username, $self->password, $localHostname, $self->name); - $helper->setupCreateDatabase($app, $self, $self->name); - $helper->setupSetRights($app, $self, $self->username, $self->password, $localHostname, $self->name); + $helper->setupCreateUser($app, $self, $self->{username}, $self->{password}, $localHostname, $self->{name}); + $helper->setupCreateDatabase($app, $self, $self->{name}); + $helper->setupSetRights($app, $self, $self->{username}, $self->{password}, $localHostname, $self->{name}); # disconnect - $self->handle->disconnect(); - $self->handle(undef); + $self->{handle}->disconnect(); + $self->{handle} = undef; } sub DESTROY { diff --git a/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm b/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm index 5a45713b3e2d..a56a7b1936dc 100644 --- a/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm +++ b/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm @@ -41,8 +41,8 @@ sub init { my $self = shift; $self->SUPER::init(@_); my($handle, $database, $execute, @values) = @_; - $self->handle($handle); - $self->database($database); + $self->{handle} = $handle; + $self->{database} = $database; if (defined($execute)) { $self->execute($execute, @values); } @@ -52,23 +52,23 @@ __DATA__ sub lastError { my $self = shift; - return $self->handle->err; + return $self->{handle}->err; } sub rowsAffected { my $self = shift; - return $self->handle->rows; + return $self->{handle}->rows; } sub row { my $self = shift; - $self->assert($self->executed, 1, 'Tried to fetch data from an unexecuted statement'); + $self->assert($self->{executed}, 1, 'Tried to fetch data from an unexecuted statement'); my $wantarray = wantarray; # to propagate it into the try block below my @result = try { if ($wantarray) { - return $self->handle->fetchrow_array(); + return $self->{handle}->fetchrow_array(); } else { - my $array = $self->handle->fetchrow_arrayref(); + my $array = $self->{handle}->fetchrow_arrayref(); if ((not defined($array)) or @$array == 0) { # no data return undef; @@ -94,9 +94,9 @@ sub row { sub rows { my $self = shift; - $self->assert($self->executed, 1, 'Tried to fetch data from an unexecuted statement'); + $self->assert($self->{executed}, 1, 'Tried to fetch data from an unexecuted statement'); my $result = try { - $self->handle->fetchall_arrayref(); + $self->{handle}->fetchall_arrayref(); } except { my($exception) = @_; if (my $error = $self->lastError) { @@ -128,14 +128,14 @@ sub execute { } } my $result = try { - $self->handle->execute(@values); + $self->{handle}->execute(@values); } except { raise PLIF::Exception::Database ( 'message' => $_[0], ); }; if ($result) { - $self->executed(1); + $self->{executed} = 1; return $self; } elsif (not $raise) { return $self; @@ -154,12 +154,12 @@ sub raiseError { # This should only be used by MySQL-specific DBI data sources raise PLIF::Exception::Database::Duplicate ( 'code' => $self->lastError, - 'message' => $self->handle->errstr, + 'message' => $self->{handle}->errstr, ); } else { raise PLIF::Exception::Database ( 'code' => $self->lastError, - 'message' => $self->handle->errstr, + 'message' => $self->{handle}->errstr, ); } } @@ -167,7 +167,7 @@ sub raiseError { # This should only be used by MySQL-specific DBI data sources sub MySQLID { my $self = shift; - return $self->handle->{'mysql_insertid'}; + return $self->{handle}->{'mysql_insertid'}; } # other possible APIs: diff --git a/webtools/PLIF/PLIF/DatabaseHelper.pm b/webtools/PLIF/PLIF/DatabaseHelper.pm index 2ff3f5c04654..ca4d07eb463e 100644 --- a/webtools/PLIF/PLIF/DatabaseHelper.pm +++ b/webtools/PLIF/PLIF/DatabaseHelper.pm @@ -43,3 +43,5 @@ sub databaseType { my $self = shift; $self->notImplemented(); } + +__DATA__ diff --git a/webtools/PLIF/PLIF/Exception.pm b/webtools/PLIF/PLIF/Exception.pm index 4455f9788524..4b0f3413c481 100644 --- a/webtools/PLIF/PLIF/Exception.pm +++ b/webtools/PLIF/PLIF/Exception.pm @@ -32,7 +32,17 @@ use vars qw(@ISA @EXPORT); use overload '""' => 'stringify', 'cmp' => 'comparison'; require Exporter; @ISA = qw(Exporter); -@EXPORT = qw(try catch with fallthrough except otherwise finally syntaxError); +@EXPORT = qw(try catch with fallthrough except otherwise finally syntaxError evalString); +my %EVALS = (); + +# Make warnings +$SIG{__WARN__} = sub { + my $message = shift; + $message =~ s/\(eval ([0-9]+)\)/ exists $EVALS{$1} ? $EVALS{$1} : $1 /gose; + $message =~ s/, line [0-9]+//gos; # clean up irrelevant useless junk... + warn $message; # reraise the updated message +}; + # To use this package, you first have to define your own exceptions: # @@ -70,6 +80,23 @@ require Exporter; # # The report method also returns a valid exception, should you wish to # later raise it for real. +# +# If you want to evaluate a string, call evalString($string, +# $filename). This will take a note of the eval number for stack +# traces and warnings. All warnings in blocks evaluated by this will +# be updated automatically. + +sub evalString($$) { + my($string, $filename) = @_; + my $evalID; + my $test = eval "sub { (undef eq 0) }"; + local $^W = 1; + local $SIG{__WARN__} = sub { $_[0] =~ m/^Use of uninitialized value in string eq at \(eval ([0-9]+)\) line 1/os; $evalID = $1; }; + &$test(); + $EVALS{++$evalID} = $filename; + # print STDERR "evaluating eval $evalID = $EVALS{$evalID}\n"; + eval $string; +} # constants for stringifying exceptions sub seMaxLength() { 80 } @@ -90,6 +117,9 @@ sub getFrames() { my @frames; my $index = 0; while (my @data = caller($index++)) { + # expand knows eval numbers + $data[1] =~ s/\(eval ([0-9]+)\)/ exists $EVALS{$1} ? $EVALS{$1} : $1 /ose; + # push frame onto stack push(@frames, { 'package' => $data[0], 'filename' => $data[1], @@ -142,6 +172,10 @@ sub init { $exception->{'line'} = $line; $exception->{'stacktrace'} = $stacktrace; } + if (defined($exception->{'message'})) { + $exception->{'message'} =~ s/\(eval ([0-9]+)\)/ exists $EVALS{$1} ? $EVALS{$1} : $1 /ose; + $exception->{'message'} =~ s/\.?\n$/, reraised/os; + } return $exception; } @@ -156,6 +190,7 @@ sub report { my($exception, @data) = @_; syntaxError "Syntax error in \"report\": \"$exception\" is not a PLIF::Exception class", 1 unless UNIVERSAL::isa($exception, __PACKAGE__); $exception = $exception->init(@data); + local $SIG{__WARN__} = undef; # don't want this warning going through our processor warn $exception; return $exception; } @@ -273,8 +308,8 @@ sub stringify { $value .= "\nStack Trace:\n"; foreach my $frame (@{$self->{'stacktrace'}}) { my $where; - if ($frame->{'filename'} =~ m/^\(eval [0-9]+\)$/os) { - $where = "line $frame->{'line'} of eval '...' created in $frame->{'package'} context"; + if ($frame->{'filename'} =~ m/^\(eval ([0-9]+)\)$/os) { + $where = "line $frame->{'line'} of eval '...' $1 created in $frame->{'package'} context"; } else { $where = "$frame->{'filename'} line $frame->{'line'}"; } @@ -308,7 +343,6 @@ sub stringify { foreach my $key (sort keys %ENV) { $value .= " $key = $ENV{$key}\n"; } - $value .= "\n"; return $value; } @@ -392,6 +426,9 @@ sub wrap($) { if (not ref($exception) or not $exception->isa('PLIF::Exception')) { # an unexpected exception + $exception =~ s/\(eval ([0-9]+)\)/ exists $EVALS{$1} ? $EVALS{$1} : $1 /gose; + $exception =~ s/, line [0-9]+//gos; # clean up irrelevant useless junk... + $exception =~ s/\.?\n$/, reraised/os; $exception = PLIF::Exception->create('message' => $exception); } if (not exists $exception->{'stacktrace'}) { diff --git a/webtools/PLIF/PLIF/Input.pm b/webtools/PLIF/PLIF/Input.pm index 72952fa42211..72d5a14c716e 100644 --- a/webtools/PLIF/PLIF/Input.pm +++ b/webtools/PLIF/PLIF/Input.pm @@ -56,7 +56,7 @@ sub init { my $self = shift; my($app) = @_; $self->SUPER::init(@_); - $self->app($app); # only safe because input services are created as service instances not pure services!!! + $self->{app} = $app; # only safe because input services are created as service instances not pure services!!! $self->fetchArguments(); } diff --git a/webtools/PLIF/PLIF/Input/Arguments.pm b/webtools/PLIF/PLIF/Input/Arguments.pm index a87b63af14d2..e65538b92e5e 100644 --- a/webtools/PLIF/PLIF/Input/Arguments.pm +++ b/webtools/PLIF/PLIF/Input/Arguments.pm @@ -163,8 +163,17 @@ sub createArgument { $self->{"argument $argument"} = []; } -sub propertyExists { - return 1; +sub implyMethod { + my $self = shift; + my($name, @data) = @_; + if (@data > 1) { + return $self->SUPER::implyMethod(@_); + } + if (@data) { + return $self->propertySet($name, @data); + } else { + return $self->propertyGet($name); + } } sub propertyGet { diff --git a/webtools/PLIF/PLIF/Input/CGI.pm b/webtools/PLIF/PLIF/Input/CGI.pm index 59b291367e7e..b0bea6038948 100644 --- a/webtools/PLIF/PLIF/Input/CGI.pm +++ b/webtools/PLIF/PLIF/Input/CGI.pm @@ -80,22 +80,22 @@ sub splitArguments { if ($self->HTTP_AUTHORIZATION =~ /^Basic +(.*)$/os) { # HTTP Basic Authentication my($username, $password) = split(/:/, decode_base64($1), 2); - $self->username($username); - $self->password($password); + $self->{username} = $username; + $self->{password} = $password; } else { # Some other authentication scheme } } # hook in cookies - $self->cookies({}); # empty the list of cookies first + $self->{cookies} = {}; # empty the list of cookies first if (defined($ENV{'HTTP_COOKIE'})) { foreach my $cookie (split(/; /os, $ENV{'HTTP_COOKIE'})) { my($field, $value) = split(/=/os, $cookie); - $self->cookies->{$field} = $value; + $self->{cookies}->{$field} = $value; } } # decode the arguments - $self->decodeHTTPArguments; + $self->decodeHTTPArguments(); } sub decodeHTTPArguments { @@ -150,7 +150,7 @@ sub setCommandArgument { sub getMetaData { my $self = shift; my($field) = @_; - return $self->metaData->{$field}; + return $self->{metaData}->{$field}; } sub registerPropertyAsMetaData { @@ -159,7 +159,7 @@ sub registerPropertyAsMetaData { foreach my $property (@propertys) { my $value = $self->propertyGet($property); if (defined($value)) { - $self->metaData->{$field} = $value; + $self->{metaData}->{$field} = $value; last; } } @@ -169,5 +169,5 @@ sub registerPropertyAsMetaData { sub getSessionData { my $self = shift; my($field) = @_; - return $self->cookies->{$field}; + return $self->{cookies}->{$field}; } diff --git a/webtools/PLIF/PLIF/Input/CGI/Head.pm b/webtools/PLIF/PLIF/Input/CGI/Head.pm index 4b87cb4fc6f8..862384e32f54 100644 --- a/webtools/PLIF/PLIF/Input/CGI/Head.pm +++ b/webtools/PLIF/PLIF/Input/CGI/Head.pm @@ -50,7 +50,7 @@ sub decodeHTTPArguments { } else { $self->dump(9, 'HTTP HEAD. No input.'); } - $self->app->addObject($self); + $self->{app}->addObject($self); } sub objectProvides { diff --git a/webtools/PLIF/PLIF/Input/CGI/PostMultipart.pm b/webtools/PLIF/PLIF/Input/CGI/PostMultipart.pm index b2b83f1f933f..980ec64b571c 100644 --- a/webtools/PLIF/PLIF/Input/CGI/PostMultipart.pm +++ b/webtools/PLIF/PLIF/Input/CGI/PostMultipart.pm @@ -70,8 +70,8 @@ sub decodeHTTPArguments { # parse the MIME body local $/ = undef; - my $data = 'Content-Type: ' . $self->CONTENT_TYPE . "\n" . - 'Content-Length: ' . $self->CONTENT_LENGTH . "\n" . + my $data = 'Content-Type: ' . $self->{CONTENT_TYPE} . "\n" . + 'Content-Length: ' . $self->{CONTENT_LENGTH} . "\n" . "\n" . ; $self->dump(9, "Data was:\n==============================\n$data\n=============================="); my $entity = $parser->parse_data($data); @@ -111,11 +111,11 @@ sub decodeHTTPArguments { } # store the entity so that we can purge the files later - $self->entity($entity); + $self->{entity} = $entity; } sub DESTROY { my $self = shift; - $self->entity->purge(); + $self->{entity}->purge(); $self->SUPER::destroy(); } diff --git a/webtools/PLIF/PLIF/Input/CGI/PostXMLRPC.pm b/webtools/PLIF/PLIF/Input/CGI/PostXMLRPC.pm index 4fc9072cfcab..b71bd358fa60 100644 --- a/webtools/PLIF/PLIF/Input/CGI/PostXMLRPC.pm +++ b/webtools/PLIF/PLIF/Input/CGI/PostXMLRPC.pm @@ -54,15 +54,15 @@ sub decodeHTTPArguments { $self->dump(9, 'XML-RPC call. Input was:', '=' x 72 . "\n$input", '=' x 72); # find someone who understands XML RPC - my $service = $self->app->getService('service.xmlrpc'); + my $service = $self->{app}->getService('service.xmlrpc'); # decode the XML stream and stuff the arguments from it - my($method, $arguments) = $service->decodeXMLRPC($self->app, $input); + my($method, $arguments) = $service->decodeXMLRPC($self->{app}, $input); $self->addArgument('command', $method); foreach my $argument (keys(%$arguments)) { $self->addArgument($argument, $arguments->{$argument}); } # tell the XML RPC expert to that our input is being used - $service->registerHook($self->app); + $service->registerHook($self->{app}); } diff --git a/webtools/PLIF/PLIF/Input/CommandLine.pm b/webtools/PLIF/PLIF/Input/CommandLine.pm index d0e87f4e0d2f..a5d24d0975f7 100644 --- a/webtools/PLIF/PLIF/Input/CommandLine.pm +++ b/webtools/PLIF/PLIF/Input/CommandLine.pm @@ -102,7 +102,7 @@ sub createArgument { # defer to superclass $self->SUPER::createArgument(@_); } else { - $self->app->output->request(@_); + $self->{app}->output->request(@_); # get input from user my $term = $self->term(); my $value = $term->readline(''); # (the parameter passed is the prompt, if any) @@ -127,7 +127,7 @@ sub createArgument { sub term { my $self = shift; if (not defined($self->{'term'})) { - $self->{'term'} = Term::ReadLine->new($self->app->name); + $self->{'term'} = Term::ReadLine->new($self->{app}->name); } return $self->{'term'}; } diff --git a/webtools/PLIF/PLIF/Output.pm b/webtools/PLIF/PLIF/Output.pm index 1dcaee152592..e57cb826d70f 100644 --- a/webtools/PLIF/PLIF/Output.pm +++ b/webtools/PLIF/PLIF/Output.pm @@ -50,25 +50,17 @@ sub serviceInstanceInit { my $self = shift; my($app) = @_; $self->SUPER::init(@_); - $self->propertySet('app', $app); + $self->{app} = $app; # output classes disable implied property creation, so we use - # propertySet() here instead of just $self->app($app). -} - -# disable implied property access so that calls to unimplemented -# output methods will always be caught and can be handled by generic -# output handlers. -sub propertyImpliedAccessAllowed { - my $self = shift; - return $self->propertyExists(@_); + # propertySet() here instead of just $self->{app} = $app. } # if we don't implement the output handler directly, let's see if some # output dispatcher service for this protocol does -sub methodMissing { +sub implyMethod { my $self = shift; my($method, @arguments) = @_; - if (not $self->app->dispatchMethod('dispatcher.output.'.$self->protocol, 'output', $method, $self, @arguments)) { - $self->SUPER::methodMissing(@_); + if (not $self->{app}->dispatchMethod('dispatcher.output.'.$self->protocol, 'output', $method, $self, @arguments)) { + $self->SUPER::implyMethod(@_); } } diff --git a/webtools/PLIF/PLIF/Output/Generic.pm b/webtools/PLIF/PLIF/Output/Generic.pm index 0aa7dcd70559..bcad0dcd99c6 100644 --- a/webtools/PLIF/PLIF/Output/Generic.pm +++ b/webtools/PLIF/PLIF/Output/Generic.pm @@ -55,10 +55,10 @@ use PLIF::Output; # # It calls the generic output module's 'HelloWorld' method, which in # this case doesn't exist and ends up going through core PLIF and then -# back to methodMissing implemented in this module and the ancestor +# back to implyMethod implemented in this module and the ancestor # Output module. # -# The methodMissing methods first call every output dispatcher service +# The implyMethod methods first call every output dispatcher service # for the actual protocol (HTTP in this case) and then every output # dispatcher service for the generic protocol until one of them # handles the HelloWorld method. @@ -122,7 +122,7 @@ sub serviceInstanceInit { my($app, $session, $protocol) = @_; $self->propertySet('actualSession', $session); $self->propertySet('actualProtocol', $protocol); - $self->propertySet('outputter', $self->app->getService("output.generic.$protocol")); + $self->propertySet('outputter', $self->{app}->getService("output.generic.$protocol")); } # output.generic service instance method @@ -130,18 +130,18 @@ sub output { my $self = shift; my($string, $data, $session) = @_; if (not defined($session)) { - $session = $self->actualSession; + $session = $self->{actualSession}; } - $self->dump(9, "outputting string '$string' on protocol '". ($self->actualProtocol) .'\''); + $self->dump(9, "outputting string '$string' on protocol '". ($self->{actualProtocol}) .'\''); $self->fillData($data); # it's not that anyone would override dataSource.strings, it's just that # people might call it without calling output(), so the right thing here # is also to call it through getService(): - $string = $self->app->getService('dataSource.strings')->getExpandedString($self->app, $session, $self->actualProtocol, $string, $data); - foreach my $filter ($self->app->getObjectList('output.filter')) { - $string = $filter->filterOutput($self->app, $session, $string); + $string = $self->{app}->getService('dataSource.strings')->getExpandedString($self->{app}, $session, $self->{actualProtocol}, $string, $data); + foreach my $filter ($self->{app}->getObjectList('output.filter')) { + $string = $filter->filterOutput($self->{app}, $session, $string); } - $self->outputter->output($self->app, $session, $string); + $self->{outputter}->output($self->{app}, $session, $string); } # output.generic service instance method @@ -151,12 +151,12 @@ sub output { # even though this is actually the generic output handler, because # there _is_ no 'output object for this protocol' since if there was # the generic output module wouldn't get called! -sub methodMissing { +sub implyMethod { my $self = shift; my($method, @arguments) = @_; - if (not $self->app->dispatchMethod('dispatcher.output.'.$self->actualProtocol, 'output', $method, $self, @arguments)) { + if (not $self->{app}->dispatchMethod('dispatcher.output.'.$self->{actualProtocol}, 'output', $method, $self, @arguments)) { # ok, no generic output dispatcher for the actual protocol, let's try the generic protocol - if (not $self->app->dispatchMethod('dispatcher.output.'.$self->protocol, 'output', $method, $self, @arguments)) { + if (not $self->{app}->dispatchMethod('dispatcher.output.'.$self->protocol, 'output', $method, $self, @arguments)) { # nope, so let's do our own. # this assumes the string will be the same as the output # method and that the arguments will be all in 'data'. @@ -169,12 +169,12 @@ sub methodMissing { sub fillData { my $self = shift; my($data) = @_; - $data->{'app'} = $self->app->hash; - if (defined($self->actualSession)) { - $data->{'session'} = $self->actualSession->hash; + $data->{'app'} = $self->{app}->hash; + if (defined($self->{actualSession})) { + $data->{'session'} = $self->{actualSession}->hash; } - $data->{'input'} = $self->app->input->hash; - $data->{'output'} = $self->outputter->hash; + $data->{'input'} = $self->{app}->input->hash; + $data->{'output'} = $self->{outputter}->hash; } # dataSource.strings default implementation diff --git a/webtools/PLIF/PLIF/Output/Generic/AIM.pm b/webtools/PLIF/PLIF/Output/Generic/AIM.pm index ee1a84b05694..d568333ca14b 100644 --- a/webtools/PLIF/PLIF/Output/Generic/AIM.pm +++ b/webtools/PLIF/PLIF/Output/Generic/AIM.pm @@ -68,7 +68,7 @@ sub init { $app->getService('dataSource.configuration')->getSettings($app, $self, 'protocol.aim'); } except { $self->dump(9, "failed to get the AIM configuration, not going to bother to connect: @_"); - $self->handle(undef); + $self->{handle} = undef; } otherwise { $self->open(); } @@ -78,19 +78,19 @@ sub open { my $self = shift; # try to connect $self->dump(9, 'opening AIM connection'); - $self->handle(undef); + $self->{handle} = undef; eval { # The Net::AIM code sprouts warning like there's no tomorrow # Let's mute them. :-) local $^W = 0; my $aim = Net::AIM->new(); # $aim->debug(${$self->getDebugLevel} > 4); - if ($aim->newconn('Screenname' => $self->address, - 'Password' => $self->password, + if ($aim->newconn('Screenname' => $self->{address}, + 'Password' => $self->{password}, 'AutoReconnect' => 1)) { # wow, we did it # add a buddy first of all (seem to need this, not sure why) - $aim->add_buddy(0, 'Buddies', $self->address); + $aim->add_buddy(0, 'Buddies', $self->{address}); # this is dodgy; protocol specs don't guarentee that this # message will arrive @@ -98,7 +98,7 @@ sub open { my $conn = shift; my($evt, $from, $to) = @_; my $nick = $evt->args()->[0]; - $self->handle($aim); + $self->{handle} = $aim; $self->dump(9, "opened AIM connection to $from as $nick"); }); @@ -112,11 +112,11 @@ sub open { $self->warn(4, "error occured while opening AIM connection: $errstr"); }); - while (not defined($self->handle) and $aim->do_one_loop()) { } + while (not defined($self->{handle}) and $aim->do_one_loop()) { } } }; - if (not defined($self->handle)) { + if (not defined($self->{handle})) { if ($@) { $self->warn(4, "Could not create the AIM handle: $@"); } else { @@ -127,8 +127,8 @@ sub open { sub close { my $self = shift; - if (defined($self->handle)) { - my $conn = $self->handle->getconn; + if (defined($self->{handle})) { + my $conn = $self->{handle}->getconn; if (defined($conn)) { $conn->disconnect(); } @@ -139,16 +139,16 @@ sub close { sub output { my $self = shift; my($app, $session, $string) = @_; - $self->assert(defined($self->handle), 1, 'No AIM handle, can\'t send IM'); - $self->handle->send_im($session->getAddress('aim'), $string); + $self->assert(defined($self->{handle}), 1, 'No AIM handle, can\'t send IM'); + $self->{handle}->send_im($session->getAddress('aim'), $string); } # protocol.aim sub checkAddress { my $self = shift; my($app, $username) = @_; - $self->assert(defined($self->handle), 1, 'No AIM handle, can\'t check address'); - # my $result = $self->handle->XXX; + $self->assert(defined($self->{handle}), 1, 'No AIM handle, can\'t check address'); + # my $result = $self->{handle}->XXX; # return $result; return 1; } @@ -196,6 +196,6 @@ sub setupConfigure { sub hash { my $self = shift; return { - 'address' => $self->address, + 'address' => $self->{address}, }; } diff --git a/webtools/PLIF/PLIF/Output/Generic/Email.pm b/webtools/PLIF/PLIF/Output/Generic/Email.pm index 4680524e67df..70b1f0c2e411 100644 --- a/webtools/PLIF/PLIF/Output/Generic/Email.pm +++ b/webtools/PLIF/PLIF/Output/Generic/Email.pm @@ -55,7 +55,7 @@ sub init { $app->getService('dataSource.configuration')->getSettings($app, $self, 'protocol.email'); } except { $self->dump(9, "failed to get the SMTP configuration, not going to bother to connect: $@"); - $self->handle(undef); + $self->{handle} = undef; } otherwise { $self->open(); } @@ -67,20 +67,20 @@ sub open { try { local $SIG{ALRM} = sub { raise PLIF::Exception::Alarm }; local $^W = 0; # XXX shut up warnings in Net::SMTP - $self->handle(Net::SMTP->new($self->host, 'Timeout' => $self->timeout)); + $self->{handle} = Net::SMTP->new($self->{host}, 'Timeout' => $self->{timeout}); alarm(0); } catch PLIF::Exception::Alarm with { # timed out -- ignore }; - if (not defined($self->handle)) { + if (not defined($self->{handle})) { $self->warn(4, 'Could not create the SMTP handle'); } } sub close { my $self = shift; - if (defined($self->handle)) { - $self->handle->quit(); + if (defined($self->{handle})) { + $self->{handle}->quit(); } } @@ -88,12 +88,12 @@ sub close { sub output { my $self = shift; my($app, $session, $string) = @_; - $self->assert(defined($self->handle), 1, 'No SMTP handle, can\'t send mail'); + $self->assert(defined($self->{handle}), 1, 'No SMTP handle, can\'t send mail'); try { local $SIG{ALRM} = sub { raise PLIF::Exception::Alarm }; - $self->assert($self->handle->mail($self->from), 1, 'Could not start sending mail'); - $self->assert($self->handle->to($session->getAddress('email')), 1, 'Could not set mail recipient (was going to send to '.($session->getAddress('email')).')'); - $self->assert($self->handle->data($string), 1, 'Could not send mail body'); + $self->assert($self->{handle}->mail($self->from), 1, 'Could not start sending mail'); + $self->assert($self->{handle}->to($session->getAddress('email')), 1, 'Could not set mail recipient (was going to send to '.($session->getAddress('email')).')'); + $self->assert($self->{handle}->data($string), 1, 'Could not send mail body'); alarm(0); } catch PLIF::Exception::Alarm with { $self->error(1, 'Timed out while trying to send e-mail'); @@ -106,9 +106,9 @@ sub checkAddress { my($app, $username) = @_; return (defined($username) and $username =~ m/^[^@\s]+@[^@\s]+\.[^@.\s]+$/os); # XXX this doesn't seem to be working: - # $self->assert(defined($self->handle), 1, 'No SMTP handle, can\'t check address'); + # $self->assert(defined($self->{handle}), 1, 'No SMTP handle, can\'t check address'); # $self->assert(defined($username), 1, 'Internal error: no username passed to checkAddress'); - # my $result = $self->handle->verify($username); + # my $result = $self->{handle}->verify($username); # return $result; } @@ -133,7 +133,7 @@ sub setupConfigure { my $value; - $value = $self->host; + $value = $self->{host}; if (not defined($value)) { $value = 'localhost'; } @@ -141,9 +141,9 @@ sub setupConfigure { if (not defined($value)) { return 'protocol.email.host'; } - $self->host($value); + $self->{host} = $value; - $value = $self->address; + $value = $self->{address}; if (defined($value)) { # default to existing value $value = $app->input->getArgument('protocol.email.address', $value); @@ -155,9 +155,9 @@ sub setupConfigure { if (not defined($value)) { return 'protocol.email.address'; } - $self->address($value); + $self->{address} = $value; - $value = $self->timeout; + $value = $self->{timeout}; if (not defined($value)) { $value = 5; } @@ -165,7 +165,7 @@ sub setupConfigure { if (not defined($value)) { return 'protocol.email.timeout'; } - $self->timeout($value); + $self->{timeout} = $value; $self->open(); $app->getService('dataSource.configuration')->setSettings($app, $self, 'protocol.email'); @@ -176,7 +176,7 @@ sub setupConfigure { sub hash { my $self = shift; return { - 'address' => $self->address, + 'address' => $self->{address}, # XXX RFC822 date -- need to provide this WITHOUT duplicating code in StdOut outputter }; } diff --git a/webtools/PLIF/PLIF/Program.pm b/webtools/PLIF/PLIF/Program.pm index da2967e39be0..e28fd2d09833 100644 --- a/webtools/PLIF/PLIF/Program.pm +++ b/webtools/PLIF/PLIF/Program.pm @@ -63,11 +63,11 @@ sub run { if ($self->verifyInput()) { if ($self->input->command) { $self->dump(8, 'Command: ' . ($self->input->command)); - $self->command($self->input->command); + $self->{command} = $self->input->command; $self->dispatch($self->input->command); } else { $self->dump(8, 'Command: (none)'); - $self->command(''); + $self->{command} = ''; $self->noCommand(); } } # verifyInput should deal with the errors @@ -76,20 +76,20 @@ sub run { $self->output->reportFatalError(@_); }; # command has been completed, reset it - $self->command(undef); + $self->{command} = undef; # In case we used a progressive output device, let it shut # down. It's important to do this, because it holds a # reference to us and we wouldn't want a memory leak... - $self->defaultOutput(undef); + $self->{defaultOutput} = undef; # empty the session objects list - $self->objects([]); + $self->{objects} = []; } while ($self->input->next()); # clear the objects hash here, so that objects are removed before # us, otherwise they can't refer back to us during shutdown. # don't need to do the same to services as services should never # use the application object during shutdown. (They shouldn't be # able to. If they can, there is a circular reference.) - $self->objects([]); + $self->{objects} = []; $self->input(undef); # shutdown the input service instance $self->dump(5, 'PLIF application completed normally.'); } @@ -106,6 +106,15 @@ sub initInput { } } +sub input { + my $self = shift; + if (@_) { + return $self->{'_input'} = shift; + } else { + return $self->{'_input'}; + } +} + # Returns an applicable output method. If you need a particular # protocol, pass it as a parameter. To get the default output class # given the current objects, do not pass any parameters. The output @@ -121,8 +130,8 @@ sub output { my($protocol, $session) = @_; my $default = 0; if (not defined($protocol)) { - if (defined($self->defaultOutput)) { - return $self->defaultOutput; + if (defined($self->{defaultOutput})) { + return $self->{defaultOutput}; } if ($session) { $self->warn(3, 'Tried to use default output method for a specific session object'); @@ -161,11 +170,7 @@ sub output { # which returns a reference which will be treated just as a # normal output service. In particular, this means that any # method could be called. So most output hooks should use - # methodMissing much like PLIF::Output::Generic. (Don't - # forget to implement a strict propertyImpliedAccessAllowed - # method -- see the PLIF::Output module for an example. If - # you don't, then outputs with zero or just one arguments - # will be treated as properties, not methods.) + # implyMethod much like PLIF::Output::Generic. # * passthrough hooks should then call the original method # again on the argument of the getOutputHook method (which # is the next object). Override hooks (like the XML RPC one) @@ -177,7 +182,7 @@ sub output { foreach my $hook (@hooks) { $output = $hook->getOutputHook($output); } - $self->defaultOutput($output); + $self->{defaultOutput} = $output; } return $output; } @@ -205,6 +210,12 @@ sub hash { return { 'name' => $self->name }; } +sub command { + my $self = shift; + syntaxError 'command() called with arguments' if @_; + return $self->{command}; +} + # Implementation Specific Methods # At least some of these should be overriden by real applications diff --git a/webtools/PLIF/PLIF/ProtocolHelper/Logout/HTTP.pm b/webtools/PLIF/PLIF/ProtocolHelper/Logout/HTTP.pm index 94b6ee2c2b43..284d23f01fb1 100644 --- a/webtools/PLIF/PLIF/ProtocolHelper/Logout/HTTP.pm +++ b/webtools/PLIF/PLIF/ProtocolHelper/Logout/HTTP.pm @@ -56,7 +56,7 @@ sub objectInit { my $self = shift; my($app, $user) = @_; $self->SUPER::objectInit(@_); - $self->user($user); + $self->{user} = $user; } # user.login.canLogin. @@ -77,7 +77,7 @@ sub loginRequired { my($app) = @_; my $userHandle = $app->getObject('user.login.loggedOutUserHandle.http'); if (defined($userHandle)) { - my $state = $userHandle->user->hasField('state', 'http.logout'); + my $state = $userHandle->{user}->hasField('state', 'http.logout'); if (defined($state)) { my $value = $state->data - 1; if ($value > 0) { diff --git a/webtools/PLIF/PLIF/Service/Components/Login.pm b/webtools/PLIF/PLIF/Service/Components/Login.pm index 9c2ff537d8c1..ab924a7db0b5 100644 --- a/webtools/PLIF/PLIF/Service/Components/Login.pm +++ b/webtools/PLIF/PLIF/Service/Components/Login.pm @@ -60,7 +60,7 @@ sub verifyInput { my $self = shift; my($app) = @_; # clear internal flags - $self->userAdminMessage(''); + $self->{userAdminMessage} = ''; # let's see if there are any protocol-specific user authenticators my @result = $app->getSelectingServiceList('input.verify.user.'.$app->input->defaultOutputProtocol)->authenticateUser($app); if (not @result) { @@ -84,7 +84,7 @@ sub verifyInput { } else { # hmm, so apparently user is not allowed to log in $self->dump(2, 'user '.($result[0]->userID).' tried logging in but their account is disabled'); - $self->userAdminMessage($result[0]->adminMessage); + $self->{userAdminMessage} = $result[0]->{adminMessage}; return $self; # supports user.login (reportInputVerificationError) } } @@ -108,7 +108,7 @@ sub authenticateUser { sub reportInputVerificationError { my $self = shift; my($app) = @_; - $app->output->loginFailed(1, $self->userAdminMessage); # 1 means 'unknown username/password' + $app->output->loginFailed(1, $self->{userAdminMessage}); # 1 means 'unknown username/password' } # dispatcher.commands diff --git a/webtools/PLIF/PLIF/Service/Components/UserPrefs.pm b/webtools/PLIF/PLIF/Service/Components/UserPrefs.pm index 436d910cc2dd..b5fdccf6e1ff 100644 --- a/webtools/PLIF/PLIF/Service/Components/UserPrefs.pm +++ b/webtools/PLIF/PLIF/Service/Components/UserPrefs.pm @@ -81,7 +81,7 @@ sub cmdUserPrefs { foreach my $userID (@userIDs) { my $targetUser = $userFactory->getUserByID($app, $userID); if (defined($targetUser)) { - $userData->{$userID} = $self->populateUserPrefsHash($app, $userDataSource, $user, $targetUser, $userID, $userID == $user->userID, @rights); + $userData->{$userID} = $self->populateUserPrefsHash($app, $userDataSource, $user, $targetUser, $userID, $userID == $user->{userID}, @rights); } else { $self->warn(2, "someone tried to get the details of invalid user $userID"); push(@notifications, [$userID, '', 'user.noSuchUser']); diff --git a/webtools/PLIF/PLIF/Service/Session.pm b/webtools/PLIF/PLIF/Service/Session.pm index 77f0e700647c..82729df10fe5 100644 --- a/webtools/PLIF/PLIF/Service/Session.pm +++ b/webtools/PLIF/PLIF/Service/Session.pm @@ -45,7 +45,7 @@ sub objectInit { my $self = shift; my($app) = @_; $self->SUPER::objectInit(@_); - $self->app($app); + $self->{app} = $app; } # expected by dataSource.strings diff --git a/webtools/PLIF/PLIF/Service/User.pm b/webtools/PLIF/PLIF/Service/User.pm index ddccea958188..b744f954366e 100644 --- a/webtools/PLIF/PLIF/Service/User.pm +++ b/webtools/PLIF/PLIF/Service/User.pm @@ -113,7 +113,7 @@ sub objectProvides { my $self = shift; my($service) = @_; return ($service eq 'user' or - $service eq 'user.'.($self->userID) or + $service eq 'user.'.($self->{userID}) or $self->SUPER::objectProvides($service)); } @@ -139,12 +139,12 @@ sub objectInit { my($app, $userID, $mode, $password, $adminMessage, $fields, $groups, $rights) = @_; $self->{'_DIRTY'} = {}; # make sure propertySet is happy $self->SUPER::objectInit(@_); - $self->userID($userID); - $self->mode($mode); # 0=active, 1=disabled XXX need a way to make this extensible - $self->password($password); - $self->adminMessage($adminMessage); - $self->fields({}); - $self->fieldsByID({}); + $self->{userID} = $userID; + $self->{mode} = $mode; # 0=active, 1=disabled XXX need a way to make this extensible + $self->{password} = $password; + $self->{adminMessage} = $adminMessage; + $self->{fields} = {}; + $self->{fieldsByID} = {}; # don't forget to update the 'hash' function if you add more properties/field whatever you want to call them my $fieldFactory = $app->getService('user.fieldFactory'); foreach my $fieldID (keys(%$fields)) { @@ -157,25 +157,25 @@ sub objectInit { $groupsByID->{$group->[0]} = {'name' => $group->[1], 'level' => $group->[2], }; # id => name, level $groupsByName->{$group->[1]} = {'groupID' => $group->[0], 'level' => $group->[2], }; # name => id, level } - $self->groupsByID($groupsByID); # authoritative version - $self->originalGroupsByID({%{$groupsByID}}); # a backup used to make a comparison when saving the groups - $self->groupsByName($groupsByName); # helpful version for output purposes only + $self->{groupsByID} = $groupsByID; # authoritative version + $self->{originalGroupsByID} = {%{$groupsByID}}; # a backup used to make a comparison when saving the groups + $self->{groupsByName} = $groupsByName; # helpful version for output purposes only # rights - $self->rights({ map {$_ => 1} @$rights }); # map a list of strings into a hash for easy access + $self->{rights} = { map {$_ => 1} @$rights }; # map a list of strings into a hash for easy access $self->{'_DIRTY'}->{'properties'} = not(defined($userID)); } sub hasRight { my $self = shift; my($right) = @_; - return (defined($self->rights->{$right}) or $self->levelInGroup(1)); # group 1 is a magical group + return (defined($self->{rights}->{$right}) or $self->levelInGroup(1)); # group 1 is a magical group } sub hasField { my $self = shift; my($category, $name) = @_; - if (defined($self->fields->{$category})) { - return $self->fields->{$category}->{$name}; + if (defined($self->{fields}->{$category})) { + return $self->{fields}->{$category}->{$name}; } return undef; } @@ -188,7 +188,7 @@ sub getField { my($category, $name) = @_; my $field = $self->hasField($category, $name); if (not defined($field)) { - $field = $self->insertField($self->app->getService('user.fieldFactory')->createFieldByName($self->app, $self, $category, $name)); + $field = $self->insertField($self->{app}->getService('user.fieldFactory')->createFieldByName($self->{app}, $self, $category, $name)); } return $field; } @@ -199,9 +199,9 @@ sub getField { sub getFieldByID { my $self = shift; my($ID) = @_; - my $field = $self->fieldsByID->{$ID}; + my $field = $self->{fieldsByID}->{$ID}; if (not defined($field)) { - $field = $self->insertField($self->app->getService('user.fieldFactory')->createFieldByID($self->app, $self, $ID)); + $field = $self->insertField($self->{app}->getService('user.fieldFactory')->createFieldByID($self->{app}, $self, $ID)); } return $field; } @@ -211,7 +211,7 @@ sub getAddress { my($protocol) = @_; my $field = $self->hasField('contact', $protocol); if (defined($field)) { - return $field->address; + return $field->{address}; } else { return undef; } @@ -221,18 +221,18 @@ sub addFieldChange { my $self = shift; my($field, $newData, $password, $type) = @_; $field->prepareChange($newData); - return $self->app->getService('dataSource.user')->setUserFieldChange($self->app, $self->userID, $field->fieldID, $newData, $password, $type); + return $self->{app}->getService('dataSource.user')->setUserFieldChange($self->{app}, $self->{userID}, $field->{fieldID}, $newData, $password, $type); } sub performFieldChange { my $self = shift; my($changeID, $candidatePassword, $minTime) = @_; - my $dataSource = $self->app->getService('dataSource.user'); - my($userID, $fieldID, $newData, $password, $createTime, $type) = $dataSource->getUserFieldChangeFromChangeID($self->app, $changeID); + my $dataSource = $self->{app}->getService('dataSource.user'); + my($userID, $fieldID, $newData, $password, $createTime, $type) = $dataSource->getUserFieldChangeFromChangeID($self->{app}, $changeID); # check for valid change if ((not defined($userID)) or # invalid change ID - ($userID != $self->userID) or # wrong change ID - (not $self->app->getService('service.password')->checkPassword($candidatePassword, $password)) or # wrong password + ($userID != $self->{userID}) or # wrong change ID + (not $self->{app}->getService('service.password')->checkPassword($candidatePassword, $password)) or # wrong password ($createTime < $minTime)) { # expired change return 0; } @@ -242,11 +242,11 @@ sub performFieldChange { if ($type == 1) { # XXX HARDCODED CONSTANT ALERT # this is an override change # remove all pending changes for this field (including this one) - $dataSource->removeUserFieldChangesByUserIDAndFieldID($self->app, $userID, $fieldID); + $dataSource->removeUserFieldChangesByUserIDAndFieldID($self->{app}, $userID, $fieldID); } else { # this is a normal change # remove just this change - $dataSource->removeUserFieldChangesByChangeID($self->app, $changeID); + $dataSource->removeUserFieldChangesByChangeID($self->{app}, $changeID); } return 1; } @@ -262,7 +262,7 @@ sub setting { } else { my $field = $self->hasField('settings', $setting); if (defined($field)) { - $$variable = $field->data; + $$variable = $field->{data}; } } } @@ -270,26 +270,26 @@ sub setting { sub hash { my $self = shift; my $result = $self->SUPER::hash(); - $result->{'userID'} = $self->userID, - $result->{'mode'} = $self->mode, - $result->{'adminMessage'} = $self->adminMessage, - $result->{'groupsByID'} = $self->groupsByID; - $result->{'groupsByName'} = $self->groupsByName; - $result->{'rights'} = [keys(%{$self->rights})]; + $result->{'userID'} = $self->{userID}, + $result->{'mode'} = $self->{mode}, + $result->{'adminMessage'} = $self->{adminMessage}, + $result->{'groupsByID'} = $self->{groupsByID}; + $result->{'groupsByName'} = $self->{groupsByName}; + $result->{'rights'} = [keys(%{$self->{rights}})]; if ($self->levelInGroup(1)) { # has all rights $result->{'right'} = {}; - foreach my $right (@{$self->app->getService('dataSource.user')->getAllRights($self->app)}) { + foreach my $right (@{$self->{app}->getService('dataSource.user')->getAllRights($self->{app})}) { $result->{'right'}->{$right} = 1; } } else { - $result->{'right'} = $self->rights; + $result->{'right'} = $self->{rights}; } $result->{'fields'} = {}; - foreach my $field (values(%{$self->fieldsByID})) { + foreach my $field (values(%{$self->{fieldsByID}})) { # XXX should we also pass the field metadata on? (e.g. typeData) - $result->{'fields'}->{$field->fieldID} = $field->hash; # (not an array btw: could have holes) - $result->{'fields'}->{$field->category.'.'.$field->name} = $field->hash; + $result->{'fields'}->{$field->{fieldID}} = $field->hash; # (not an array btw: could have holes) + $result->{'fields'}->{$field->{category} . '.' . $field->{name}} = $field->hash; } return $result; } @@ -297,19 +297,19 @@ sub hash { sub checkPassword { my $self = shift; my($password) = @_; - return $self->app->getService('service.passwords')->checkPassword($self->password, $password); + return $self->{app}->getService('service.passwords')->checkPassword($self->{password}, $password); } sub checkLogin { my $self = shift; - return ($self->mode == 0); + return ($self->{mode} == 0); } sub joinGroup { my $self = shift; my($groupID, $level) = @_; if ($level > 0) { - my $groupName = $self->app->getService('dataSource.user')->getGroupName($self->app, $groupID); + my $groupName = $self->{app}->getService('dataSource.user')->getGroupName($self->{app}, $groupID); $self->{'groupsByID'}->{$groupID} = {'name' => $groupName, 'level' => $level, }; $self->{'groupsByName'}->{$groupName} = {'groupID' => $groupID, 'level' => $level, }; $self->invalidateRights(); @@ -347,14 +347,14 @@ sub insertField { my $self = shift; my($field) = @_; $self->assert(ref($field) and $field->provides('user.field'), 1, 'Tried to insert something that wasn\'t a field object into a user\'s field hash'); - $self->fields->{$field->category}->{$field->name} = $field; - $self->fieldsByID->{$field->fieldID} = $field; + $self->{fields}->{$field->{category}}->{$field->{name}} = $field; + $self->{fieldsByID}->{$field->{fieldID}} = $field; return $field; } sub invalidateRights { my $self = shift; - my $rights = $self->app->getService('dataSource.user')->getRightsForGroups($self->app, keys(%{$self->{'groupsByID'}})); + my $rights = $self->{app}->getService('dataSource.user')->getRightsForGroups($self->{app}, keys(%{$self->{'groupsByID'}})); $self->rights({ map {$_ => 1} @$rights }); # map a list of strings into a hash for easy access # don't set a dirty flag, because rights are merely a convenient # cached expansion of the rights data. Changing this externally @@ -373,8 +373,8 @@ sub propertySet { my $result = $self->SUPER::propertySet(@_); if (($hadUndefinedID) and (defined($value))) { # we've just aquired an ID, so propagate the change to all fields - foreach my $field (values(%{$self->fieldsByID})) { - $field->userID($value); + foreach my $field (values(%{$self->{fieldsByID}})) { + $field->{userID} = $value; } # and mark the groups as dirty too $self->{'_DIRTY'}->{'groups'} = 1; @@ -391,10 +391,10 @@ sub propertyGet { # Create new hash so that they can't edit ours. This ensures # that they can't inadvertently bypass the DIRTY flagging by # propertySet(), above. This does mean that internally we have - # to access $self->{'groupsByID'} instead of $self->groupsByID. + # to access $self->{'groupsByID'} instead of $self->{groupsByID}. } else { # we don't bother looking at $self->rights or - # $self->groupsByName, but any changes made to those won't be + # $self->{groupsByName}, but any changes made to those won't be # saved anyway. return $self->SUPER::propertyGet(@_); } @@ -413,24 +413,24 @@ sub DESTROY { sub writeProperties { my $self = shift; - $self->userID($self->app->getService('dataSource.user')->setUser($self->app, $self->userID, $self->mode, - $self->password, $self->adminMessage, - $self->newFieldID, $self->newFieldValue, $self->newFieldKey)); + $self->{userID} = $self->{app}->getService('dataSource.user')->setUser($self->{app}, $self->{userID}, $self->{mode}, + $self->{password}, $self->{adminMessage}, + $self->newFieldID, $self->{newFieldValue}, $self->{newFieldKey}); } sub writeGroups { my $self = shift; # compare the group lists before and after and see which got added or changed and which got removed - my $dataSource = $self->app->getService('dataSource.user'); + my $dataSource = $self->{app}->getService('dataSource.user'); foreach my $group (keys(%{$self->{'groupsByID'}})) { if ((not defined($self->{'originalGroupsByID'}->{$group})) or ($self->{'groupsByID'}->{$group}->{'level'} != $self->{'originalGroupsByID'}->{$group}->{'level'})) { - $dataSource->addUserGroup($self->app, $self->userID, $group, $self->{'groupsByID'}->{$group}->{'level'}); + $dataSource->addUserGroup($self->{app}, $self->{userID}, $group, $self->{'groupsByID'}->{$group}->{'level'}); } } foreach my $group (keys(%{$self->{'originalGroupsByID'}})) { if (not defined($self->{'groupsByID'}->{$group})) { - $dataSource->removeUserGroup($self->app, $self->userID, $group); + $dataSource->removeUserGroup($self->{app}, $self->{userID}, $group); } } } diff --git a/webtools/PLIF/PLIF/Service/UserField.pm b/webtools/PLIF/PLIF/Service/UserField.pm index 3c07d52f7bf6..fdb073a76f13 100644 --- a/webtools/PLIF/PLIF/Service/UserField.pm +++ b/webtools/PLIF/PLIF/Service/UserField.pm @@ -67,13 +67,13 @@ sub init { my($app, $user, $fieldID, $fieldCategory, $fieldName, $fieldTypeData, $fieldMode, $fieldData) = @_; $self->SUPER::init($app); # do not hold on to $user! - $self->app($app); - $self->userID($user->userID); # only change this if it started as undef - $self->fieldID($fieldID); # change this at your peril - $self->category($fieldCategory); # change this at your peril - $self->name($fieldName); # change this at your peril - $self->typeData($fieldTypeData); # change this at your peril - $self->mode($fieldMode); # change this at your peril + $self->{app} = $app; + $self->{userID} = $user->{userID}; # only change this if it started as undef + $self->{fieldID} = $fieldID; # change this at your peril + $self->{category} = $fieldCategory; # change this at your peril + $self->{name} = $fieldName; # change this at your peril + $self->{typeData} = $fieldTypeData; # change this at your peril + $self->{mode} = $fieldMode; # change this at your peril $self->{'data'} = $fieldData; # read this via $field->data and write via $field->data($foo) # don't forget to update the 'hash' function if you add more member variables here $self->{'_DATAFIELD'} = 'data'; @@ -111,7 +111,7 @@ sub data { sub hash { my $self = shift; - return $self->data; + return $self->{data}; } # Methods specifically for 'contact' category fields @@ -120,21 +120,21 @@ sub hash { # followed by the field data itself sub username { my $self = shift; - $self->assert($self->category eq 'contact', 0, 'Tried to get the username from the non-contact field \''.($self->fieldID).'\''); - return $self->typeData.$self->data; + $self->assert($self->{category} eq 'contact', 0, 'Tried to get the username from the non-contact field \''.($self->{fieldID}).'\''); + return $self->{typeData} . $self->{data}; } sub address { my $self = shift; - $self->assert($self->category eq 'contact', 0, 'Tried to get the address of the non-contact field \''.($self->fieldID).'\''); - return $self->data; + $self->assert($self->{category} eq 'contact', 0, 'Tried to get the address of the non-contact field \''.($self->{fieldID}).'\''); + return $self->{data}; } sub prepareChange { my $self = shift; my($newData) = @_; $self->assert($self->validate($newData), 0, 'tried to prepare change to invalid value'); # XXX might want to provide more debugging data - $self->newData($newData); + $self->{newData} = $newData; } # sets a flag so that calls to ->data and ->address will return the @@ -168,8 +168,8 @@ sub DESTROY { sub write { my $self = shift; if ($self->{'_DELETE'}) { - $self->app->getService('dataSource.user')->removeUserField($self->app, $self->userID, $self->fieldID); + $self->{app}->getService('dataSource.user')->removeUserField($self->{app}, $self->{userID}, $self->{fieldID}); } else { - $self->app->getService('dataSource.user')->setUserField($self->app, $self->userID, $self->fieldID, $self->data); + $self->{app}->getService('dataSource.user')->setUserField($self->{app}, $self->{userID}, $self->{fieldID}, $self->{data}); } } diff --git a/webtools/PLIF/PLIF/Service/WWW.pm b/webtools/PLIF/PLIF/Service/WWW.pm index cb5717b2886a..9dade22603c7 100644 --- a/webtools/PLIF/PLIF/Service/WWW.pm +++ b/webtools/PLIF/PLIF/Service/WWW.pm @@ -55,19 +55,19 @@ sub get { if (defined($referrer)) { $request->referer($referrer); } - if (not exists $self->{'ua'}) { + if (not exists $self->{ua}) { require LWP::UserAgent; import LWP::UserAgent; # DEPENDENCY my $ua = LWP::UserAgent->new(); $ua->agent($ua->agent . ' (' . $app->name . ')'); $ua->timeout(5); # XXX HARDCODED CONSTANT ALERT $ua->env_proxy(); - $self->ua($ua); + $self->{ua} = $ua; } - my $response = $self->ua->request($request); + my $response = $self->{ua}->request($request); if (wantarray) { - return ($response->content, $response); + return ($response->{content}, $response); } else { - return $response->content; + return $response->{content}; } } diff --git a/webtools/PLIF/PLIF/Service/XMLRPC.pm b/webtools/PLIF/PLIF/Service/XMLRPC.pm index 388cdcc77e49..7f05b51abc5f 100644 --- a/webtools/PLIF/PLIF/Service/XMLRPC.pm +++ b/webtools/PLIF/PLIF/Service/XMLRPC.pm @@ -104,7 +104,7 @@ sub reportFatalError { } # output.hook -sub methodMissing { +sub implyMethod { my $self = shift; my($method, @arguments) = @_; # We drop 'method' on the floor, since it is assumed that an XML @@ -125,14 +125,6 @@ sub methodMissing { $self->output->XMLRPC($response->as_string); } -# disable implied property access so that all method calls are routed -# through methodMissing() above. -sub propertyImpliedAccessAllowed { - my $self = shift; - my($name) = @_; - return ($name eq 'output'); -} - # This is commented out because the default generic output module # defaults to this behaviour anyway, and we don't really want this # module being probed for output.generic.dispatcher stuff since it has diff --git a/webtools/PLIF/TODO b/webtools/PLIF/TODO index 6a6484f9b38c..4d7530bab80e 100644 --- a/webtools/PLIF/TODO +++ b/webtools/PLIF/TODO @@ -15,3 +15,8 @@ Make getSettings return a boolean instead of raising an exception. Stylesheet should be a template + + + +refactor the |die|, |warn|, |PLIF::warn|, |PLIF::error|, |PLIF::dump| +call sites and functions so that they all go through the same system.