diff options
author | ivan <ivan> | 2005-10-15 09:11:20 +0000 |
---|---|---|
committer | ivan <ivan> | 2005-10-15 09:11:20 +0000 |
commit | 673b9a458d9138523026963df6fa3b4683e09bae (patch) | |
tree | 42acc524ff5fd53e4fdb2f5b6dac4a42ce8057f6 /rt/lib/RT/Interface | |
parent | 591613cf1c861505335646fff3ffb4a705e011bf (diff) | |
parent | d4d0590bef31071e8809ec046717444b95b3f30a (diff) |
This commit was generated by cvs2svn to compensate for changes in r4407,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'rt/lib/RT/Interface')
-rwxr-xr-x | rt/lib/RT/Interface/Email/Auth/GnuPG.pm | 6 | ||||
-rw-r--r-- | rt/lib/RT/Interface/Email/Auth/MailFrom.pm | 36 | ||||
-rw-r--r-- | rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm | 27 | ||||
-rw-r--r-- | rt/lib/RT/Interface/REST.pm | 8 | ||||
-rw-r--r-- | rt/lib/RT/Interface/Web/Handler.pm | 81 | ||||
-rwxr-xr-x | rt/lib/RT/Interface/Web/QueryBuilder.pm | 56 | ||||
-rwxr-xr-x | rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm | 245 | ||||
-rwxr-xr-x | rt/lib/RT/Interface/Web/Standalone.pm | 37 |
8 files changed, 458 insertions, 38 deletions
diff --git a/rt/lib/RT/Interface/Email/Auth/GnuPG.pm b/rt/lib/RT/Interface/Email/Auth/GnuPG.pm index 724b1b3fc..2dfada755 100755 --- a/rt/lib/RT/Interface/Email/Auth/GnuPG.pm +++ b/rt/lib/RT/Interface/Email/Auth/GnuPG.pm @@ -1,8 +1,8 @@ -# {{{ BEGIN BPS TAGGED BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -42,7 +42,7 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# }}} END BPS TAGGED BLOCK +# END BPS TAGGED BLOCK }}} # package RT::Interface::Email::Auth::GnuPG; use Mail::GnuPG; diff --git a/rt/lib/RT/Interface/Email/Auth/MailFrom.pm b/rt/lib/RT/Interface/Email/Auth/MailFrom.pm index 0efadb1cd..ef315dd53 100644 --- a/rt/lib/RT/Interface/Email/Auth/MailFrom.pm +++ b/rt/lib/RT/Interface/Email/Auth/MailFrom.pm @@ -1,8 +1,8 @@ -# {{{ BEGIN BPS TAGGED BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -42,7 +42,7 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# }}} END BPS TAGGED BLOCK +# END BPS TAGGED BLOCK }}} package RT::Interface::Email::Auth::MailFrom; use RT::Interface::Email qw(ParseSenderAddressFromHead CreateUser); @@ -122,6 +122,36 @@ sub GetCurrentUser { } } + elsif ( $args{'Action'} =~ /^take$/i ) { + + # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets + unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'}, + Right => 'OwnTicket' + ) + || $unpriv->PrincipalObj->HasRight( + Object => $args{'Queue'}, + Right => 'OwnTicket' + ) + ) { + return ( $args{'CurrentUser'}, 0 ); + } + + } + elsif ( $args{'Action'} =~ /^resolve$/i ) { + + # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets + unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'}, + Right => 'ModifyTicket' + ) + || $unpriv->PrincipalObj->HasRight( + Object => $args{'Queue'}, + Right => 'ModifyTicket' + ) + ) { + return ( $args{'CurrentUser'}, 0 ); + } + + } else { return ( $args{'CurrentUser'}, 0 ); } diff --git a/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm b/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm index 8c9eae88c..c552d76e6 100644 --- a/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm +++ b/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm @@ -1,8 +1,8 @@ -# {{{ BEGIN BPS TAGGED BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -42,22 +42,31 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# }}} END BPS TAGGED BLOCK +# END BPS TAGGED BLOCK }}} package RT::Interface::Email::Filter::SpamAssassin; use Mail::SpamAssassin; my $spamtest = Mail::SpamAssassin->new(); sub GetCurrentUser { - my $item = shift; - my $status = $spamtest->check ($item); - return (undef, 0) unless $status->is_spam(); + my %args = ( + Message => undef, + CurrentUser => undef, + AuthLevel => undef, + @_ + ); + my $status = $spamtest->check( $args{'Message'} ); + return ( $args{'CurrentUser'}, $args{'AuthLevel'} ) + unless $status->is_spam(); + eval { $status->rewrite_mail() }; - if ($status->get_hits > $status->get_required_hits()*1.5) { + if ( $status->get_hits > $status->get_required_hits() * 1.5 ) { + # Spammy indeed - return (undef, -1); + return ( $args{'CurrentUser'}, -1 ); } - return (undef, 0); + return ( $args{'CurrentUser'}, $args{'AuthLevel'} ); + } =head1 NAME diff --git a/rt/lib/RT/Interface/REST.pm b/rt/lib/RT/Interface/REST.pm index 8c8baa1e7..279ddf4b3 100644 --- a/rt/lib/RT/Interface/REST.pm +++ b/rt/lib/RT/Interface/REST.pm @@ -1,8 +1,8 @@ -# {{{ BEGIN BPS TAGGED BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -42,7 +42,7 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# }}} END BPS TAGGED BLOCK +# END BPS TAGGED BLOCK }}} # lib/RT/Interface/REST.pm # @@ -54,7 +54,7 @@ BEGIN { use Exporter (); use vars qw($VERSION @ISA @EXPORT); - $VERSION = do { my @r = (q$Revision: 1.1.1.2 $ =~ /\d+/g); sprintf "%d."."%02d"x$#r, @r }; + $VERSION = do { my @r = (q$Revision: 1.1.1.3 $ =~ /\d+/g); sprintf "%d."."%02d"x$#r, @r }; @ISA = qw(Exporter); @EXPORT = qw(expand_list form_parse form_compose vpush vsplit); diff --git a/rt/lib/RT/Interface/Web/Handler.pm b/rt/lib/RT/Interface/Web/Handler.pm index 7ee654e7c..ce9222586 100644 --- a/rt/lib/RT/Interface/Web/Handler.pm +++ b/rt/lib/RT/Interface/Web/Handler.pm @@ -1,8 +1,8 @@ -# {{{ BEGIN BPS TAGGED BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -42,9 +42,24 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# }}} END BPS TAGGED BLOCK +# END BPS TAGGED BLOCK }}} + package RT::Interface::Web::Handler; +use CGI qw/-private_tempfiles/; +use MIME::Entity; +use Text::Wrapper; +use CGI::Cookie; +use Time::ParseDate; +use Time::HiRes; +use HTML::Entities; +use HTML::Scrubber; +use Text::Quoted; +use RT::Interface::Web::Handler; +use File::Path qw( rmtree ); +use File::Glob qw( bsd_glob ); +use File::Spec::Unix; + sub DefaultHandlerArgs { ( comp_root => [ [ local => $RT::MasonLocalComponentRoot ], @@ -53,7 +68,10 @@ sub DefaultHandlerArgs { ( default_escape_flags => 'h', data_dir => "$RT::MasonDataDir", allow_globals => [qw(%session)], - autoflush => 1 + # Turn off static source if we're in developer mode. + static_source => ($RT::DevelMode ? '0' : '1'), + use_object_files => ($RT::DevelMode ? '0' : '1'), + autoflush => 0 ) }; # {{{ sub new @@ -69,19 +87,17 @@ sub new { my $class = shift; $class->InitSessionDir; - if ($MasonX::Apache2Handler::VERSION) { - goto &NewApache2Handler; - } - elsif ($mod_perl::VERSION and $mod_perl::VERSION >= 1.9908) { - require Apache::RequestUtil; - no warnings 'redefine'; - my $sub = *Apache::request{CODE}; - *Apache::request = sub { - my $r; - eval { $r = $sub->('Apache'); }; - # warn $@ if $@; - return $r; - }; + if ( $mod_perl::VERSION && $mod_perl::VERSION >= 1.9908 ) { +# require Apache::RequestUtil; +# no warnings 'redefine'; +# my $sub = *Apache::request{CODE}; +# *Apache::request = sub { +# my $r; +# eval { $r = $sub->('Apache'); }; +# +# # warn $@ if $@; +# return $r; +# }; goto &NewApacheHandler; } elsif ($CGI::MOD_PERL) { @@ -96,14 +112,14 @@ sub InitSessionDir { # Activate the following if running httpd as root (the normal case). # Resets ownership of all files created by Mason at startup. # Note that mysql uses DB for sessions, so there's no need to do this. - unless ( $RT::DatabaseType =~ /(mysql|Pg)/ ) { + unless ( $RT::DatabaseType =~ /(?:mysql|Pg)/ ) { # Clean up our umask to protect session files umask(0077); if ($CGI::MOD_PERL) { chown( Apache->server->uid, Apache->server->gid, - [$RT::MasonSessionDir] ) + $RT::MasonSessionDir ) if Apache->server->can('uid'); } @@ -170,9 +186,36 @@ sub NewHandler { ); $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 ); + $handler->interp->set_escape( u => \&RT::Interface::Web::EscapeURI ); return($handler); } +=head2 CleanupRequest + +Rollback any uncommitted transaction. +Flush the ACL cache +Flush the searchbuilder query cache + +=cut + +sub CleanupRequest { + + if ( $RT::Handle->TransactionDepth ) { + $RT::Handle->ForceRollback; + $RT::Logger->crit( + "Transaction not committed. Usually indicates a software fault." + . "Data loss may have occurred" ); + } + + # Clean out the ACL cache. the performance impact should be marginal. + # Consistency is imprived, too. + RT::Principal->InvalidateACLCache(); + DBIx::SearchBuilder::Record::Cachable->FlushCache + if ( $RT::WebFlushDbCacheEveryRequest + and UNIVERSAL::can( + 'DBIx::SearchBuilder::Record::Cachable' => 'FlushCache' ) ); + +} # }}} 1; diff --git a/rt/lib/RT/Interface/Web/QueryBuilder.pm b/rt/lib/RT/Interface/Web/QueryBuilder.pm new file mode 100755 index 000000000..b7526b30a --- /dev/null +++ b/rt/lib/RT/Interface/Web/QueryBuilder.pm @@ -0,0 +1,56 @@ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +package RT::Interface::Web::QueryBuilder; + +use strict; +use warnings; + +eval "require RT::Interface::Web::QueryBuilder_Vendor"; +die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder_Vendor.pm}); +eval "require RT::Interface::Web::QueryBuilder_Local"; +die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder_Local.pm}); + +1; diff --git a/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm b/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm new file mode 100755 index 000000000..67b728339 --- /dev/null +++ b/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm @@ -0,0 +1,245 @@ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +package RT::Interface::Web::QueryBuilder::Tree; + +use strict; +use warnings; + +use base qw/Tree::Simple/; + +=head1 NAME + + RT::Interface::Web::QueryBuilder::Tree - subclass of Tree::Simple used in Query Builder + +=head1 DESCRIPTION + +This class provides support functionality for the Query Builder (Search/Build.html). +It is a subclass of L<Tree::Simple>. + +=head1 METHODS + +=head2 TraversePrePost PREFUNC POSTFUNC + +Traverses the tree depth-first. Before processing the node's children, +calls PREFUNC with the node as its argument; after processing all of the +children, calls POSTFUNC with the node as its argument. + +(Note that unlike Tree::Simple's C<traverse>, it actually calls its functions +on the root node passed to it.) + +=cut + +sub TraversePrePost { + my ($self, $prefunc, $postfunc) = @_; + + $prefunc->($self); + + foreach my $child ($self->getAllChildren()) { + $child->TraversePrePost($prefunc, $postfunc); + } + + $postfunc->($self); +} + +=head2 GetReferencedQueues + +Returns a hash reference with keys each queue name referenced in a clause in +the key (even if it's "Queue != 'Foo'"), and values all 1. + +=cut + +sub GetReferencedQueues { + my $self = shift; + + my $queues = {}; + + $self->traverse( + sub { + my $node = shift; + + return if $node->isRoot; + + my $clause = $node->getNodeValue(); + + if ( ref($clause) and $clause->{Key} eq 'Queue' ) { + $queues->{ $clause->{Value} } = 1; + }; + } + ); + + return $queues; +} + +=head2 GetQueryAndOptionList SELECTED_NODES + +Given an array reference of tree nodes that have been selected by the user, +traverses the tree and returns the equivalent SQL query and a list of hashes +representing the "clauses" select option list. Each has contains the keys +TEXT, INDEX, SELECTED, and DEPTH. TEXT is the displayed text of the option +(including parentheses, not including indentation); INDEX is the 0-based +index of the option in the list (also used as its CGI parameter); SELECTED +is either 'SELECTED' or '', depending on whether the node corresponding +to the select option was in the SELECTED_NODES list; and DEPTH is the +level of indentation for the option. + +=cut + +sub GetQueryAndOptionList { + my $self = shift; + my $selected_nodes = shift; + + my $optionlist = []; + + my $i = 0; + + $self->TraversePrePost( + sub { # This is called before recursing to the node's children. + my $node = shift; + + return if $node->isRoot or $node->getParent->isRoot; + + my $clause = $node->getNodeValue(); + my $str = ' '; + my $aggregator_context = $node->getParent()->getNodeValue(); + $str = $aggregator_context . " " if $node->getIndex() > 0; + + if ( ref($clause) ) { # ie, it's a leaf + $str .= + $clause->{Key} . " " . $clause->{Op} . " " . $clause->{Value}; + } + + unless ($node->getParent->getParent->isRoot) { + # used to check !ref( $parent->getNodeValue() ) ) + if ( $node->getIndex() == 0 ) { + $str = '( ' . $str; + } + } + + push @$optionlist, { + TEXT => $str, + INDEX => $i, + SELECTED => (grep { $_ == $node } @$selected_nodes) ? 'SELECTED' : '', + DEPTH => $node->getDepth() - 1, + }; + + $i++; + }, sub { + # This is called after recursing to the node's children. + my $node = shift; + + return if $node->isRoot or $node->getParent->isRoot or $node->getParent->getParent->isRoot; + + # Only do this for the rightmost child. + return unless $node->getIndex == $node->getParent->getChildCount - 1; + + $optionlist->[-1]{TEXT} .= ' )'; + } + ); + + return (join ' ', map { $_->{TEXT} } @$optionlist), $optionlist; +} + +=head2 PruneChildLessAggregators + +If tree manipulation has left it in a state where there are ANDs, ORs, +or parenthesizations with no children, get rid of them. + +=cut + +sub PruneChildlessAggregators { + my $self = shift; + + $self->TraversePrePost( + sub { + }, + sub { + my $node = shift; + + return if $node->isRoot or $node->getParent->isRoot; + + # We're only looking for aggregators (AND/OR) + return if ref $node->getNodeValue; + + return if $node->getChildCount != 0; + + # OK, this is a childless aggregator. Remove self. + + $node->getParent->removeChild($node); + + # Deal with circular refs + $node->DESTROY; + } + ); +} + +=head2 GetDisplayedNodes + +This function returns a list of the nodes of the tree in depth-first +order which correspond to options in the "clauses" multi-select box. +In fact, it's all of them but the root and its child. + +=cut + +sub GetDisplayedNodes { + my $self = shift; + my @lines; + + $self->traverse(sub { + my $node = shift; + + push @lines, $node unless $node->isRoot or $node->getParent->isRoot; + }); + + return @lines; +} + + +eval "require RT::Interface::Web::QueryBuilder::Tree_Vendor"; +die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder/Tree_Vendor.pm}); +eval "require RT::Interface::Web::QueryBuilder::Tree_Local"; +die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder/Tree_Local.pm}); + +1; diff --git a/rt/lib/RT/Interface/Web/Standalone.pm b/rt/lib/RT/Interface/Web/Standalone.pm new file mode 100755 index 000000000..bc2423e6d --- /dev/null +++ b/rt/lib/RT/Interface/Web/Standalone.pm @@ -0,0 +1,37 @@ +package RT::Interface::Web::Standalone; + +use strict; +use base 'HTTP::Server::Simple::Mason'; +use RT::Interface::Web::Handler; +use RT::Interface::Web; + +sub handler_class { "RT::Interface::Web::Handler" } + +sub setup_escapes { + my $self = shift; + my $handler = shift; + + # Override HTTP::Server::Simple::Mason's version of this method to do + # nothing. (RT::Interface::Web::Handler does this already for us in + # NewHandler.) +} + +sub default_mason_config { + return @RT::MasonParameters; +} + +sub handle_request { + + my $self = shift; + my $cgi = shift; + + Module::Refresh->refresh if $RT::DevelMode; + + $self->SUPER::handle_request($cgi); + $RT::Logger->crit($@) if ($@); + + RT::Interface::Web::Handler->CleanupRequest(); + +} + +1; |