diff options
author | ivan <ivan> | 2009-12-18 00:41:34 +0000 |
---|---|---|
committer | ivan <ivan> | 2009-12-18 00:41:34 +0000 |
commit | 2dfda73eeb3eae2d4f894099754794ef07d060dd (patch) | |
tree | 5486a76d4557f05ed1420da42ec4edbe5b748f04 /rt/bin | |
parent | 8103c1fc1b2c27a6855feadf26f91b980a54bc52 (diff) |
import rt 3.6.10
Diffstat (limited to 'rt/bin')
-rwxr-xr-x | rt/bin/mason_handler.fcgi | 60 | ||||
-rw-r--r-- | rt/bin/mason_handler.fcgi.in | 4 | ||||
-rwxr-xr-x | rt/bin/mason_handler.scgi | 52 | ||||
-rw-r--r-- | rt/bin/mason_handler.scgi.in | 4 | ||||
-rw-r--r-- | rt/bin/mason_handler.svc | 48 | ||||
-rw-r--r-- | rt/bin/mason_handler.svc.in | 4 | ||||
-rwxr-xr-x | rt/bin/rt | 392 | ||||
-rw-r--r-- | rt/bin/rt-crontool | 166 | ||||
-rw-r--r-- | rt/bin/rt-crontool.in | 4 | ||||
-rwxr-xr-x | rt/bin/rt-mailgate | 451 | ||||
-rw-r--r-- | rt/bin/rt-mailgate.in | 4 | ||||
-rw-r--r-- | rt/bin/rt.in | 4 | ||||
-rwxr-xr-x | rt/bin/standalone_httpd | 67 | ||||
-rwxr-xr-x | rt/bin/standalone_httpd.in | 4 | ||||
-rwxr-xr-x | rt/bin/webmux.pl | 165 | ||||
-rw-r--r-- | rt/bin/webmux.pl.in | 4 |
16 files changed, 777 insertions, 656 deletions
diff --git a/rt/bin/mason_handler.fcgi b/rt/bin/mason_handler.fcgi index 93d1f8855..9bef9a89f 100755 --- a/rt/bin/mason_handler.fcgi +++ b/rt/bin/mason_handler.fcgi @@ -1,9 +1,15 @@ #!/usr/bin/perl -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,26 +21,43 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# 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 LICENSE BLOCK +# END BPS TAGGED BLOCK }}} +package RT::Mason; use strict; +use vars '$Handler'; use File::Basename; require ('/opt/rt3/bin/webmux.pl'); -my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters); - # Enter CGI::Fast mode, which should also work as a vanilla CGI script. require CGI::Fast; RT::Init(); -# Response loop while ( my $cgi = CGI::Fast->new ) { # the whole point of fastcgi requires the env to get reset here.. # So we must squash it again @@ -44,24 +67,19 @@ while ( my $cgi = CGI::Fast->new ) { $ENV{'ENV'} = '' if defined $ENV{'ENV'}; $ENV{'IFS'} = '' if defined $ENV{'IFS'}; + Module::Refresh->refresh if $RT::DevelMode; RT::ConnectToDatabase(); - if ( ( !$h->interp->comp_exists( $cgi->path_info ) ) - && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) { + if ( ( !$Handler->interp->comp_exists( $cgi->path_info ) ) + && ( $Handler->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) { $cgi->path_info( $cgi->path_info . "/index.html" ); } - eval { $h->handle_cgi_object($cgi); }; + eval { $Handler->handle_cgi_object($cgi); }; if ($@) { $RT::Logger->crit($@); } - - - if ($RT::Handle->TransactionDepth) { - $RT::Handle->ForceRollback; - $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") ; - } - + RT::Interface::Web::Handler->CleanupRequest(); } diff --git a/rt/bin/mason_handler.fcgi.in b/rt/bin/mason_handler.fcgi.in index aefe6d881..26842d31e 100644 --- a/rt/bin/mason_handler.fcgi.in +++ b/rt/bin/mason_handler.fcgi.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: diff --git a/rt/bin/mason_handler.scgi b/rt/bin/mason_handler.scgi index 7774189ee..6a3404ea5 100755 --- a/rt/bin/mason_handler.scgi +++ b/rt/bin/mason_handler.scgi @@ -1,9 +1,15 @@ #!/usr/local/bin/speedy -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,29 +21,47 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# 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.) # -# END LICENSE BLOCK +# 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::Mason; use strict; +use vars '$Handler'; require ('/opt/rt3/bin/webmux.pl'); -my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters); - require CGI; RT::Init(); my $cgi = CGI->new; -if ( ( !$h->interp->comp_exists( $cgi->path_info ) ) - && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) { +if ( ( !$Handler->interp->comp_exists( $cgi->path_info ) ) + && ( $Handler->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) { $cgi->path_info( $cgi->path_info . "/index.html" ); } -$h->handle_cgi_object($cgi); - +$Handler->handle_cgi_object($cgi); +RT::Interface::Web::Handler->CleanupRequest(); 1; diff --git a/rt/bin/mason_handler.scgi.in b/rt/bin/mason_handler.scgi.in index 0af0ccd94..2d77e8f82 100644 --- a/rt/bin/mason_handler.scgi.in +++ b/rt/bin/mason_handler.scgi.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: diff --git a/rt/bin/mason_handler.svc b/rt/bin/mason_handler.svc index c05d21e69..86adfae28 100644 --- a/rt/bin/mason_handler.svc +++ b/rt/bin/mason_handler.svc @@ -1,9 +1,15 @@ #!/usr/bin/perl -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,14 +21,31 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # -# END LICENSE BLOCK - +# 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 }}} =head1 NAME mason_handler.svc - Win32 IIS Service handler for RT @@ -55,8 +78,11 @@ registry setting will also be automatically populated. =cut +package RT::Mason; + use strict; use File::Basename; +use vars '$Handler'; require (dirname(__FILE__) . '/webmux.pl'); use Cwd; @@ -197,7 +223,6 @@ BEGIN { warn "Begin listening on $ENV{'FCGI_SOCKET_PATH'}\n"; require CGI::Fast; -my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters); RT::Init(); @@ -212,7 +237,8 @@ while( my $cgi = CGI::Fast->new ) { warn "Serving $comp\n"; - $h->handle_cgi($comp); + $Handler->handle_cgi($comp); + RT::Interface::Web::Handler->CleanupRequest(); # _should_ always be tied } diff --git a/rt/bin/mason_handler.svc.in b/rt/bin/mason_handler.svc.in index bda998aa5..3bf851c7a 100644 --- a/rt/bin/mason_handler.svc.in +++ b/rt/bin/mason_handler.svc.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: @@ -1,9 +1,15 @@ #!/usr/bin/perl -w -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,13 +21,33 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# # +# CONTRIBUTION SUBMISSION POLICY: # -# END LICENSE BLOCK +# (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 }}} +# Designed and implemented for Best Practical Solutions, LLC by +# Abhijit Menon-Sen <ams@wiw.org> use strict; @@ -30,7 +56,9 @@ use strict; use Cwd; use LWP; +use Text::ParseWords; use HTTP::Request::Common; +use Term::ReadLine; # We derive configuration information from hardwired defaults, dotfiles, # and the RT* environment variables (in increasing order of precedence). @@ -45,7 +73,9 @@ my %config = ( debug => 0, user => eval{(getpwuid($<))[0]} || $ENV{USER} || $ENV{USERNAME}, passwd => undef, - server => 'http://localhost/rt/', + server => 'http://localhost/', + query => undef, + orderby => undef, ), config_from_file($ENV{RTCONFIG} || ".rtrc"), config_from_env() @@ -53,6 +83,8 @@ my %config = ( my $session = new Session("$HOME/.rt_sessions"); my $REST = "$config{server}/REST/1.0"; +my $prompt = 'rt> '; + sub whine; sub DEBUG { warn @_ if $config{debug} >= shift } @@ -60,7 +92,7 @@ sub DEBUG { warn @_ if $config{debug} >= shift } # (XXX: Ask Autrijus how i18n changes these definitions.) my $name = '[\w.-]+'; -my $field = '[a-zA-Z][a-zA-Z0-9_-]*'; +my $field = '(?:[a-zA-Z](?:[a-zA-Z0-9_-]|\s+)*)'; my $label = '[a-zA-Z0-9@_.+-]+'; my $labels = "(?:$label,)*$label"; my $idlist = '(?:(?:\d+-)?\d+,)*(?:\d+-)?\d+'; @@ -75,6 +107,7 @@ my $idlist = '(?:(?:\d+-)?\d+,)*(?:\d+-)?\d+'; my %handlers = ( # handler => [ ...aliases... ], version => ["version", "ver"], + shell => ["shell"], logout => ["logout"], help => ["help", "man"], show => ["show", "cat"], @@ -84,20 +117,35 @@ my %handlers = ( link => ["link", "ln"], merge => ["merge"], grant => ["grant", "revoke"], + take => ["take", "steal", "untake"], + quit => ["quit", "exit"], ); -# Once we find and call an appropriate handler, we're done. - -my (%actions, $action); +my %actions; foreach my $fn (keys %handlers) { foreach my $alias (@{ $handlers{$fn} }) { $actions{$alias} = \&{"$fn"}; } } -if (@ARGV && exists $actions{$ARGV[0]}) { - $action = shift @ARGV; + +# Once we find and call an appropriate handler, we're done. + +sub handler { + my $action; + + push @ARGV, 'shell' if (!@ARGV); # default to shell mode + shift @ARGV if ($ARGV[0] eq 'rt'); # ignore a leading 'rt' + if (@ARGV && exists $actions{$ARGV[0]}) { + $action = shift @ARGV; + $actions{$action}->($action); + } + else { + print STDERR "rt: Unknown command '@ARGV'.\n"; + print STDERR "rt: For help, run 'rt help'.\n"; + } } -$actions{$action || "help"}->($action || ()); + +handler(); exit; # Handler functions. @@ -105,6 +153,17 @@ exit; # # The following subs are handlers for each entry in %actions. +sub shell { + $|=1; + my $term = new Term::ReadLine 'RT CLI'; + while ( defined ($_ = $term->readline($prompt)) ) { + next if /^#/ || /^\s*$/; + + @ARGV = shellwords($_); + handler(); + } +} + sub version { print "rt $VERSION\n"; } @@ -113,18 +172,26 @@ sub logout { submit("$REST/logout") if defined $session->cookie; } +sub quit { + logout(); + exit; +} + +my %help; sub help { my ($action, $type) = @_; - my (%help, $key); + my $key; # What help topics do we know about? - local $/ = undef; - foreach my $item (@{ Form::parse(<DATA>) }) { - my $title = $item->[2]{Title}; - my @titles = ref $title eq 'ARRAY' ? @$title : $title; + if (!%help) { + local $/ = undef; + foreach my $item (@{ Form::parse(<DATA>) }) { + my $title = $item->[2]{Title}; + my @titles = ref $title eq 'ARRAY' ? @$title : $title; - foreach $title (grep $_, @titles) { - $help{$title} = $item->[2]{Text}; + foreach $title (grep $_, @titles) { + $help{$title} = $item->[2]{Text}; + } } } @@ -166,7 +233,12 @@ sub help { # Displays a list of objects that match some specified condition. sub list { - my ($q, $type, %data, $orderby); + my ($q, $type, %data); + my $orderby = $config{orderby}; + + if ($config{orderby}) { + $data{orderby} = $config{orderby}; + } my $bad = 0; while (@ARGV) { @@ -179,7 +251,7 @@ sub list { $bad = 1, last unless get_var_argument(\%data); } elsif (/^-o$/) { - $orderby = shift @ARGV; + $data{'orderby'} = shift @ARGV; } elsif (/^-([isl])$/) { $data{format} = $1; @@ -200,16 +272,20 @@ sub list { $bad = 1; last; } } - + if (!defined $q) { + $q = $config{query}; + } + $type ||= "ticket"; unless ($type && defined $q) { my $item = $type ? "query string" : "object type"; whine "No $item specified."; $bad = 1; } - return help("list", $type) if $bad; + #return help("list", $type) if $bad; + return suggest_help("list", $type) if $bad; - my $r = submit("$REST/search/$type", { query => $q, %data, orderby => $orderby || "" }); + my $r = submit("$REST/search/$type", { query => $q, %data }); print $r->content; } @@ -264,10 +340,18 @@ sub show { whine "No objects specified."; $bad = 1; } - return help("show", $type) if $bad; + #return help("show", $type) if $bad; + return suggest_help("show", $type) if $bad; my $r = submit("$REST/show", { id => \@objects, %data }); - print $r->content; + my $c = $r->content; + # if this isn't a text reply, remove the trailing newline so we + # don't corrupt things like tarballs when people do + # show ticket/id/attachments/id/content > foo.tar.gz + if ($r->content_type !~ /^text\//) { + chomp($c); + } + print $c; } # To create a new object, we ask the server for a form with the defaults @@ -371,18 +455,23 @@ sub edit { } @objects = ("$type/new"); } - return help($action, $type) if $bad; + #return help($action, $type) if $bad; + return suggest_help($action, $type) if $bad; # We need a form to make changes to. We usually ask the server for # one, but we can avoid that if we are fed one on STDIN, or if the # user doesn't want to edit the form by hand, and the command line - # specifies only simple variable assignments. + # specifies only simple variable assignments. We *should* get a + # form if we're creating a new ticket, so that the default values + # get filled in properly. + + my @new_objects = grep /\/new$/, @objects; if ($input) { local $/ = undef; $text = <STDIN>; } - elsif ($edit || %add || %del || !$cl) { + elsif ($edit || %add || %del || !$cl || @new_objects) { my $r = submit("$REST/show", { id => \@objects, format => 'l' }); $text = $r->content; } @@ -451,7 +540,7 @@ sub edit { if ($output) { print $text; - exit; + return; } my $synerr = 0; @@ -477,7 +566,7 @@ EDIT: } else { print $r->content; - exit -1; + return; } } print $r->content; @@ -506,7 +595,7 @@ sub comment { if (/-a/) { unless (-f $ARGV[0] && -r $ARGV[0]) { whine "Cannot read attachment: '$ARGV[0]'."; - exit -1; + return; } push @files, shift @ARGV; } @@ -514,7 +603,14 @@ sub comment { my $a = $_ eq "-b" ? \@bcc : \@cc; @$a = split /\s*,\s*/, shift @ARGV; } - elsif (/-m/) { $msg = shift @ARGV } + elsif (/-m/) { + $msg = shift @ARGV; + if ( $msg =~ /^-$/ ) { + undef $msg; + while (<STDIN>) { $msg .= $_ } + } + } + elsif (/-w/) { $wtime = shift @ARGV } } elsif (!$id && m|^(?:ticket/)?($idlist)$|) { @@ -531,7 +627,8 @@ sub comment { whine "No object specified."; $bad = 1; } - return help($action, "ticket") if $bad; + #return help($action, "ticket") if $bad; + return suggest_help($action, "ticket") if $bad; my $form = [ "", @@ -544,6 +641,7 @@ sub comment { Attachment => [ @files ], TimeWorked => $wtime || '', Text => $msg || '', + Status => '' } ]; @@ -555,7 +653,7 @@ sub comment { do { my $ntext = vi($text); - exit if ($error && $ntext eq $text); + return if ($error && $ntext eq $text); $text = $ntext; $form = Form::parse($text); $error = 0; @@ -567,7 +665,7 @@ sub comment { goto NEXT; } elsif (!@$o) { - exit; + return; } @files = @{ vsplit($k->{Attachment}) }; @@ -583,7 +681,7 @@ sub comment { } $data{content} = $text; - my $r = submit("$REST/ticket/comment/$id", \%data); + my $r = submit("$REST/ticket/$id/comment", \%data); print $r->content; } @@ -610,9 +708,10 @@ sub merge { whine "Too $evil arguments specified."; $bad = 1; } - return help("merge", "ticket") if $bad; + #return help("merge", "ticket") if $bad; + return suggest_help("merge", "ticket") if $bad; - my $r = submit("$REST/ticket/merge/$id[0]", {into => $id[1]}); + my $r = submit("$REST/ticket/$id[0]/merge/$id[1]"); print $r->content; } @@ -643,7 +742,7 @@ sub link { $bad = 1; } unless (exists $ltypes{lc $rel}) { - whine "Invalid relationship '$rel' specified."; + whine "Invalid link '$rel' specified."; $bad = 1; } %data = (id => $from, rel => $rel, to => $to, del => $del); @@ -653,12 +752,51 @@ sub link { whine "Too $bad arguments specified."; $bad = 1; } - return help("link", "ticket") if $bad; + #return help("link", "ticket") if $bad; + return suggest_help("link", "ticket") if $bad; my $r = submit("$REST/ticket/link", \%data); print $r->content; } +# Take/steal a ticket +sub take { + my ($cmd) = @_; + my ($bad, %data) = (0, ()); + + my $id; + + # get the ticket id + if (@ARGV == 1) { + ($id) = @ARGV; + unless ($id =~ /^\d+$/) { + whine "Invalid ticket ID $id specified."; + $bad = 1; + } + my $form = [ + "", + [ "Ticket", "Action" ], + { + Ticket => $id, + Action => $cmd, + Status => '', + } + ]; + + my $text = Form::compose([ $form ]); + $data{content} = $text; + } + else { + $bad = @ARGV < 1 ? "few" : "many"; + whine "Too $bad arguments specified."; + $bad = 1; + } + return suggest_help("take", "ticket") if $bad; + + my $r = submit("$REST/ticket/$id/take", \%data); + print $r->content; +} + # Grant/revoke a user's rights. sub grant { @@ -733,10 +871,10 @@ sub submit { my ($head, $text) = split /\n\n/, $res->content, 2; my ($status, @headers) = split /\n/, $head; - $text =~ s/\n*$/\n/; + $text =~ s/\n*$/\n/ if ($text); # "RT/3.0.1 401 Credentials required" - if ($status !~ m#^RT/\d+(?:\.\d+)+(?:-?\w+)? (\d+) ([\w\s]+)$#) { + if ($status !~ m#^RT/\d+(?:\S+) (\d+) ([\w\s]+)$#) { warn "rt: Malformed RT response from $config{server}.\n"; warn "(Rerun with RTDEBUG=3 for details.)\n" if $config{debug} < 3; exit -1; @@ -770,7 +908,7 @@ sub submit { # For anything else, we just die. elsif ($res->code != 409) { warn "rt: ", $res->content; - exit; + #exit; } } } @@ -812,7 +950,7 @@ sub submit { sub cookie { my ($self) = @_; my $cookie = $self->{sids}{$s}{$u}; - return defined $cookie ? "RT_SID=$cookie" : undef; + return defined $cookie ? "RT_SID_$cookie" : undef; } # Deletes the current session cookie. @@ -835,7 +973,7 @@ sub submit { my ($self, $response) = @_; my $cookie = $response->header("Set-Cookie"); - if (defined $cookie && $cookie =~ /^RT_SID=([0-9A-Fa-f]+);/) { + if (defined $cookie && $cookie =~ /^RT_SID_(.[^;,\s]+=[0-9A-Fa-f]+);/) { $self->{sids}{$s}{$u} = $1; } } @@ -852,7 +990,7 @@ sub submit { while (<F>) { chomp; next if /^$/ || /^#/; - next unless m#^https?://[^ ]+ \w+ [0-9A-Fa-f]+$#; + next unless m#^https?://[^ ]+ \w+ [^;,\s]+=[0-9A-Fa-f]+$#; my ($server, $user, $cookie) = split / /, $_; $sids->{$server}{$user} = $cookie; } @@ -1061,7 +1199,7 @@ sub Form::compose { sub config_from_env { my %env; - foreach my $k ("DEBUG", "USER", "PASSWD", "SERVER") { + foreach my $k ("DEBUG", "USER", "PASSWD", "SERVER", "QUERY", "ORDERBY") { if (exists $ENV{"RT$k"}) { $env{lc $k} = $ENV{"RT$k"}; } @@ -1106,13 +1244,14 @@ sub config_from_file { sub parse_config_file { my %cfg; my ($file) = @_; + local $_; # $_ may be aliased to a constant, from line 1163 open(CFG, $file) && do { while (<CFG>) { chomp; next if (/^#/ || /^\s*$/); - if (/^(user|passwd|server)\s+([^ ]+)$/) { + if (/^(user|passwd|server|query|orderby)\s+(.*)\s?$/) { $cfg{$1} = $2; } else { @@ -1189,7 +1328,7 @@ sub vsplit { my @values = ref $val eq 'ARRAY' ? @$val : $val; foreach my $line (map {split /\n/} @values) { - # XXX: This should become a real parser, à la Text::ParseWords. + # XXX: This should become a real parser, Ã la Text::ParseWords. $line =~ s/^\s+//; $line =~ s/\s+$//; push @words, split /\s*,\s*/, $line; @@ -1198,17 +1337,29 @@ sub vsplit { return \@words; } +# WARN: this code is duplicated in lib/RT/Interface/REST.pm +# change both functions at once sub expand_list { my ($list) = @_; - my ($elt, @elts, %elts); - foreach $elt (split /,/, $list) { - if ($elt =~ /^(\d+)-(\d+)$/) { push @elts, ($1..$2) } - else { push @elts, $elt } + my @elts; + foreach (split /,/, $list) { + push @elts, /^(\d+)-(\d+)$/? ($1..$2): $_; } - @elts{@elts}=(); - return sort {$a<=>$b} keys %elts; + return map $_->[0], # schwartzian transform + sort { + defined $a->[1] && defined $b->[1]? + # both numbers + $a->[1] <=> $b->[1] + :!defined $a->[1] && !defined $b->[1]? + # both letters + $a->[2] cmp $b->[2] + # mix, number must be first + :defined $a->[1]? -1: 1 + } + map [ $_, (defined( /^(\d+)$/ )? $1: undef), lc($_) ], + @elts; } sub get_type_argument { @@ -1258,16 +1409,23 @@ sub is_object_spec { return; } +sub suggest_help { + my ($action, $type) = @_; + + print STDERR "rt: For help, run 'rt help $action'.\n" if defined $action; + print STDERR "rt: For help, run 'rt help $type'.\n" if defined $type; +} + __DATA__ Title: intro Title: introduction Text: - ** THIS IS AN UNSUPPORTED PREVIEW RELEASE ** - ** PLEASE REPORT BUGS TO rt-bugs@fsck.com ** + ** THIS IS AN UNSUPPORTED PREVIEW RELEASE ** + ** PLEASE REPORT BUGS TO rt-bugs@bestpractical.com ** - This is a command-line interface to RT 3. + This is a command-line interface to RT 3.0 or newer It allows you to interact with an RT server over HTTP, and offers an interface to RT's functionality that is better-suited to automation @@ -1279,9 +1437,10 @@ Text: For more information: - - rt help actions (a list of possible actions) - - rt help objects (how to specify objects) - rt help usage (syntax information) + - rt help objects (how to specify objects) + - rt help actions (a list of possible actions) + - rt help types (a list of object types) - rt help config (configuration details) - rt help examples (a few useful examples) @@ -1296,6 +1455,8 @@ Text: Syntax: rt <action> [options] [arguments] + or + rt shell Each invocation of this program must specify an action (e.g. "edit", "create"), options to modify behaviour, and other arguments required @@ -1306,6 +1467,10 @@ Text: "rt help <action>". Some actions may be referred to by more than one name ("create" is the same as "new", for example). + You may also call "rt shell", which will give you an 'rt>' prompt at + which you can issue commands of the form "<action> [options] + [arguments]". See "rt help shell" for details. + Objects are identified by a type and an ID (which can be a name or a number, depending on the type). For some actions, the object type is implied (you can only comment on tickets); for others, the user must @@ -1320,6 +1485,7 @@ Text: - rt help objects (how to specify objects) - rt help actions (a list of actions) - rt help types (a list of object types) + - rt help shell (how to use the shell) -- @@ -1343,6 +1509,8 @@ Text: - server <URL> URL to RT server. - user <username> RT username. - passwd <passwd> RT user's password. + - query <RT Query> Default RT Query for list action + - orderby <order> Default RT order for list action Blank and #-commented lines are ignored. @@ -1357,6 +1525,8 @@ Text: - RTDEBUG Numeric debug level. (Set to 3 for full logs.) - RTCONFIG Specifies a name other than ".rtrc" for the configuration file. + - RTQUERY Default RT Query for rt list + - RTORDERBY Default order for rt list -- @@ -1380,7 +1550,7 @@ Text: be used to specify more than one object of the same type. Note that the list must be a single argument (i.e., no spaces). For example, "user/root,1-3,5,7-10,ams" is a list of ten users; the same list - can also be written as "user/ams,root,1,2,3,5,7,8-20". + can also be written as "user/ams,root,1,2,3,5,7,8-10". Examples: @@ -1599,13 +1769,15 @@ Text: -t type Specifies object type. -f a,b,c Restrict the display to the specified fields. -S var=val Submits the specified variable with the request. - + -v Verbose display Examples: rt show -t ticket -f id,subject,status 1-3 rt show ticket/3/attachments/29 rt show ticket/3/attachments/29/content rt show ticket/1-3/links + rt show ticket/3/history + rt show -v ticket/3/history rt show -t user 2 -- @@ -1666,7 +1838,7 @@ Text: rt ls -t tickets -i 'Priority > 5' | rt edit - set status=resolved rt edit ticket/4 set priority=3 owner=bar@example.com \ add cc=foo@example.com bcc=quux@example.net - rt create -t ticket subject='new ticket' priority=10 \ + rt create -t ticket set subject='new ticket' priority=10 \ add cc=foo@example.com -- @@ -1701,7 +1873,7 @@ Text: Examples: - rt comment -t 'Not worth fixing.' -a stddisclaimer.h 23 + rt comment -m 'Not worth fixing.' -a stddisclaimer.h 23 -- @@ -1712,7 +1884,7 @@ Text: rt merge <from-id> <to-id> - Merges the two specified tickets. + Merges the first ticket specified into the second ticket specified. -- @@ -1721,16 +1893,16 @@ Text: Syntax: - rt link [-d] <id-A> <relationship> <id-B> + rt link [-d] <id-A> <link> <id-B> Creates (or, with -d, deletes) a link between the specified tickets. - The relationship can (irrespective of case) be any of: + The link can (irrespective of case) be any of: DependsOn/DependedOnBy: A depends upon B (or vice versa). RefersTo/ReferredToBy: A refers to B (or vice versa). MemberOf/HasMember: A is a member of B (or vice versa). - To view a ticket's relationships, use "rt show ticket/3/links". (See + To view a ticket's links, use "rt show ticket/3/links". (See "rt help ticket" and "rt help show".) Options: @@ -1787,7 +1959,11 @@ Text: Title: topics Text: - Use "rt help <topic>" for help on any of the following subjects: + Syntax: + + rt help <topic> + + Get help on any of the following subjects: - tickets, users, groups, queues. - show, edit, ls/list/search, new/create. @@ -1814,3 +1990,71 @@ Text: For the moment, please consult examples provided with each action. -- + +Title: shell +Text: + + Syntax: + + rt shell + + Opens an interactive shell, at which you can issue commands of + the form "<action> [options] [arguments]". + + To exit the shell, type "quit" or "exit". + + Commands can be given at the shell in the same form as they would + be given at the command line without the leading 'rt' invocation. + + Example: + $ rt shell + rt> create -t ticket set subject='new' add cc=foo@example.com + # Ticket 8 created. + rt> quit + $ + +-- + +Title: take +Title: untake +Title: steal +Text: + + Syntax: + + rt <take|untake|steal> <ticket-id> + + Sets the owner of the specified ticket to the current user, + assuming said user has the bits to do so, or releases the + ticket. + + 'Take' is used on tickets which are not currently owned + (Owner: Nobody), 'steal' is used on tickets which *are* + currently owned, and 'untake' is used to "release" a ticket + (reset its Owner to Nobody). 'Take' cannot be used on + tickets which are currently owned. + + Example: + alice$ rt create -t ticket set subject="New ticket" + # Ticket 7 created. + alice$ rt take 7 + # Owner changed from Nobody to alice + alice$ su bob + bob$ rt steal 7 + # Owner changed from alice to bob + bob$ rt untake 7 + # Owner changed from bob to Nobody + +-- + +Title: quit +Title: exit +Text: + + Use "quit" or "exit" to leave the shell. Only valid within shell + mode. + + Example: + $ rt shell + rt> quit + $ diff --git a/rt/bin/rt-crontool b/rt/bin/rt-crontool index cdbc3cbc9..3171d115c 100644 --- a/rt/bin/rt-crontool +++ b/rt/bin/rt-crontool @@ -1,9 +1,15 @@ #!/usr/bin/perl -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,18 +21,35 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # -# END LICENSE BLOCK - +# 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 }}} use strict; use Carp; -use lib ("/opt/rt3/lib", "/opt/rt3/local/lib"); +use lib ("/opt/rt3/local/lib", "/opt/rt3/lib"); package RT; @@ -45,9 +68,6 @@ RT::LoadConfig(); #Connect to the database and get RT::SystemUser and RT::Nobody loaded RT::Init(); -#Drop setgid permissions -RT::DropSetGIDPermissions(); - #Get the current user all loaded my $CurrentUser = GetCurrentUser(); @@ -57,18 +77,27 @@ unless ( $CurrentUser->Id ) { } my ( $search, $condition, $action, $search_arg, $condition_arg, $action_arg, - $template_id, $help, $verbose ); -GetOptions( "search=s" => \$search, - "search-arg=s" => \$search_arg, - "condition=s" => \$condition, - "condition-arg=s" => \$condition_arg, - "action-arg=s" => \$action_arg, - "action=s" => \$action, - "template-id=s" => \$template_id, - "help" => \$help, - "verbose|v" => \$verbose ); - -help() if $help; + $template_id, $transaction, $transaction_type, $help, $verbose ); +GetOptions( "search=s" => \$search, + "search-arg=s" => \$search_arg, + "condition=s" => \$condition, + "condition-arg=s" => \$condition_arg, + "action-arg=s" => \$action_arg, + "action=s" => \$action, + "template-id=s" => \$template_id, + "transaction=s" => \$transaction, + "transaction-type=s" => \$transaction_type, + "help" => \$help, + "verbose|v" => \$verbose ); + +help() if $help or not $search or not $action; + +$transaction ||= 'first'; +unless ( $transaction =~ /^(first|last)$/i ) { + print STDERR loc("--transaction argument could be only 'first' or 'last'"); + exit 1; +} +$transaction = lc($transaction) eq 'first'? 'ASC': 'DESC'; # We _must_ have a search object load_module($search); @@ -78,15 +107,21 @@ load_module($condition) if ($condition); # load template if specified my $template_obj; if ($template_id) { - $template_obj = RT::Template->new($RT::Nobody); - $template_obj->LoadById($template_id); + $template_obj = RT::Template->new($CurrentUser); + $template_obj->Load($template_id); } +my $void_scrip = RT::Scrip->new( $CurrentUser ); +my $void_scrip_action = RT::ScripAction->new( $CurrentUser ); #At the appointed time: #find a bunch of tickets my $tickets = RT::Tickets->new($CurrentUser); -my $search = $search->new( TicketsObj => $tickets, Argument => $search_arg ); +my $search = $search->new( + TicketsObj => $tickets, + Argument => $search_arg, + CurrentUser => $CurrentUser +); $search->Prepare(); @@ -95,12 +130,22 @@ my $tickets = $search->TicketsObj; #for each ticket we've found while ( my $ticket = $tickets->Next() ) { - print "\n" . $ticket->Id() . ": " if ($verbose); + print $ticket->Id() . ": " if ($verbose); + + my $transaction = get_transaction($ticket); + print loc("Using transaction #[_1]...", $transaction->id) + if $verbose && $transaction; # perform some more advanced check if ($condition) { - my $condition_obj = $condition->new( TicketObj => $ticket, - Argument => $condition_arg ); + my $condition_obj = $condition->new( + TransactionObj => $transaction, + TicketObj => $ticket, + ScripObj => $void_scrip, + TemplateObj => $template_obj, + Argument => $condition_arg, + CurrentUser => $CurrentUser, + ); # if the condition doesn't apply, get out of here @@ -109,9 +154,15 @@ while ( my $ticket = $tickets->Next() ) { } #prepare our action - my $action_obj = $action->new( TicketObj => $ticket, - TemplateObj => $template_obj, - Argument => $action_arg ); + my $action_obj = $action->new( + TicketObj => $ticket, + TransactionObj => $transaction, + TemplateObj => $template_obj, + Argument => $action_arg, + ScripObj => $void_scrip, + ScripActionObj => $void_scrip_action, + CurrentUser => $CurrentUser, + ); #if our preparation, move onto the next ticket next unless ( $action_obj->Prepare ); @@ -119,7 +170,27 @@ while ( my $ticket = $tickets->Next() ) { #commit our action. next unless ( $action_obj->Commit ); - print loc("Action committed.") if ($verbose); + print loc("Action committed.\n") if ($verbose); +} + +=head2 get_transaction + +Takes ticket and returns its transaction acording to command +line arguments C<--transaction> and <--transaction-type>. + +=cut + +sub get_transaction { + my $ticket = shift; + my $txns = $ticket->Transactions; + $txns->OrderByCols( + { FIELD => 'Created', ORDER => $transaction }, + { FIELD => 'id', ORDER => $transaction }, + ); + $txns->Limit( FIELD => 'Type', VALUE => $transaction_type ) + if $transaction_type; + $txns->RowsPerPage(1); + return $txns->First; } # {{{ load_module @@ -181,6 +252,15 @@ sub help { . loc( "[_1] - An argument to pass to [_2]", "--action-argument", "--action" ) . "\n"; print " " + . loc( "[_1] - Specify id of the template you want to use", "--template-id" ) + . "\n"; + print " " + . loc( "[_1] - Specify if you want to use either 'first' or 'last' transaction", "--transaction" ) + . "\n"; + print " " + . loc( "[_1] - Specify the type of a transaction you want to use", "--transaction-type" ) + . "\n"; + print " " . loc( "[_1] - Output status updates to STDOUT", "--verbose" ) . "\n"; print "\n"; print "\n"; @@ -197,19 +277,17 @@ sub help { ) . "\n\n"; - print " bin/rt-cron-tool \\\n"; - print - " --search RT::Search::ActiveTicketsInQueue --search-arg general \\\n"; - print - " --condition RT::Condition::UntouchedInHours --condition-arg 4 \\\n"; + print " bin/rt-crontool \\\n"; + print " --search RT::Search::ActiveTicketsInQueue --search-arg general \\\n"; + print " --condition RT::Condition::UntouchedInHours --condition-arg 4 \\\n"; print " --action RT::Action::SetPriority --action-arg 99 \\\n"; print " --verbose\n"; print "\n"; - print loc("Escalate tickets"); - print "rt-crontool \\\n"; - print " --search RT::Search::ActiveTicketsInQueue --search-arg thequeuename \\\n"; - print " --action RT::Action::EscalatePriority \\\n"; + print loc("Escalate tickets"). "\n"; + print " bin/rt-crontool \\\n"; + print " --search RT::Search::ActiveTicketsInQueue --search-arg general \\\n"; + print " --action RT::Action::EscalatePriority\n"; diff --git a/rt/bin/rt-crontool.in b/rt/bin/rt-crontool.in index 9881120fa..07e7a8b52 100644 --- a/rt/bin/rt-crontool.in +++ b/rt/bin/rt-crontool.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: diff --git a/rt/bin/rt-mailgate b/rt/bin/rt-mailgate index 8af800227..a578b4bc6 100755 --- a/rt/bin/rt-mailgate +++ b/rt/bin/rt-mailgate @@ -1,9 +1,15 @@ #!/usr/bin/perl -w -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,392 +21,40 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # -# END LICENSE BLOCK - +# 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 }}} =head1 NAME rt-mailgate - Mail interface to RT3. -=begin testing - -use RT::I18N; - -# Make sure that when we call the mailgate wrong, it tempfails - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://bad.address"), "Opened the mailgate - The error below is expected - $@"); -print MAIL <<EOF; -From: root\@localhost -To: rt\@example.com -Subject: This is a test of new ticket creation - -Foob! -EOF -close (MAIL); - -# Check the return value -is ( $? >> 8, 75, "The error message above is expected The mail gateway exited with a failure. yay"); - - -# {{{ Test new ticket creation by root who is privileged and superuser - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: root\@localhost -To: rt\@example.com -Subject: This is a test of new ticket creation - -Blah! -Foob! -EOF -close (MAIL); - -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -use RT::Tickets; -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok (UNIVERSAL::isa($tick,'RT::Ticket')); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'This is a test of new ticket creation', "Created the ticket"); - -# }}} - - -# {{{This is a test of new ticket creation as an unknown user - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: doesnotexist\@example.com -To: rt\@example.com -Subject: This is a test of new ticket creation as an unknown user - -Blah! -Foob! -EOF -close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -$tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -$tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject ne 'This is a test of new ticket creation as an unknown user', "failed to create the new ticket from an unprivileged account"); -my $u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist@example.com'); -ok( $u->Id == 0, " user does not exist and was not created by failed ticket submission"); - - -# }}} - -# {{{ now everybody can create tickets. can a random unkown user create tickets? - -my $g = RT::Group->new($RT::SystemUser); -$g->LoadSystemInternalGroup('Everyone'); -ok( $g->Id, "Found 'everybody'"); - -my ($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CreateTicket'); -ok ($val, "Granted everybody the right to create tickets - $msg"); - -sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: doesnotexist\@example.com -To: rt\@example.com -Subject: This is a test of new ticket creation as an unknown user - -Blah! -Foob! -EOF -close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - - -$tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -$tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'This is a test of new ticket creation as an unknown user', "failed to create the new ticket from an unprivileged account"); -my $u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist@example.com'); -ok( $u->Id != 0, " user does not exist and was created by ticket submission"); - -# }}} - - -# {{{ can another random reply to a ticket without being granted privs? answer should be no. - - -#($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CreateTicket'); -#ok ($val, "Granted everybody the right to create tickets - $msg"); -#sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: doesnotexist-2\@example.com -To: rt\@example.com -Subject: [example.com #@{[$tick->Id]}] This is a test of a reply as an unknown user - -Blah! -Foob! -EOF -close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-2@example.com'); -ok( $u->Id == 0, " user does not exist and was not created by ticket correspondence submission"); -# }}} -# {{{ can another random reply to a ticket after being granted privs? answer should be yes - - -($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'ReplyToTicket'); -ok ($val, "Granted everybody the right to reply to tickets - $msg"); -sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: doesnotexist-2\@example.com -To: rt\@example.com -Subject: [example.com #@{[$tick->Id]}] This is a test of a reply as an unknown user - -Blah! -Foob! -EOF -close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - - -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-2@example.com'); -ok( $u->Id != 0, " user exists and was created by ticket correspondence submission"); - -# }}} - -# {{{ can another random comment on a ticket without being granted privs? answer should be no. - - -#($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CreateTicket'); -#ok ($val, "Granted everybody the right to create tickets - $msg"); -#sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action comment"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: doesnotexist-3\@example.com -To: rt\@example.com -Subject: [example.com #@{[$tick->Id]}] This is a test of a comment as an unknown user - -Blah! -Foob! -EOF -close (MAIL); - -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-3@example.com'); -ok( $u->Id == 0, " user does not exist and was not created by ticket comment submission"); - -# }}} -# {{{ can another random reply to a ticket after being granted privs? answer should be yes - - -($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CommentOnTicket'); -ok ($val, "Granted everybody the right to reply to tickets - $msg"); -sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action comment"), "Opened the mailgate - $@"); -print MAIL <<EOF; -From: doesnotexist-3\@example.com -To: rt\@example.com -Subject: [example.com #@{[$tick->Id]}] This is a test of a comment as an unknown user - -Blah! -Foob! -EOF -close (MAIL); - -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-3@example.com'); -ok( $u->Id != 0, " user exists and was created by ticket comment submission"); - -# }}} - -# {{{ Testing preservation of binary attachments - -# Get a binary blob (Best Practical logo) - -# Create a mime entity with an attachment - -use MIME::Entity; -my $entity = MIME::Entity->build( From => 'root@localhost', - To => 'rt@localhost', - Subject => 'binary attachment test', - Data => ['This is a test of a binary attachment']); - -# currently in lib/t/autogen -$entity->attach(Path => '/opt/rt3/share/html/NoAuth/images/spacer.gif', - Type => 'image/gif', - Encoding => 'base64'); - -# Create a ticket with a binary attachment -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); - -$entity->print(\*MAIL); - -close (MAIL); - -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); - $tick = $tickets->First(); -ok (UNIVERSAL::isa($tick,'RT::Ticket')); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'binary attachment test', "Created the ticket - ".$tick->Id); - -my $file = `cat ../../../html/NoAuth/images/spacer.gif`; -ok ($file, "Read in the logo image"); - - - use Digest::MD5; -warn "for the raw file the content is ".Digest::MD5::md5_base64($file); - - - -# Verify that the binary attachment is valid in the database -my $attachments = RT::Attachments->new($RT::SystemUser); -$attachments->Limit(FIELD => 'ContentType', VALUE => 'image/gif'); -ok ($attachments->Count == 1, 'Found only one gif in the database'); -my $attachment = $attachments->First; -my $acontent = $attachment->Content; - - warn "coming from the database, the content is ".Digest::MD5::md5_base64($acontent); - -is( $acontent, $file, 'The attachment isn\'t screwed up in the database.'); -# Log in as root -use Getopt::Long; -use LWP::UserAgent; - - -# Grab the binary attachment via the web ui -my $ua = LWP::UserAgent->new(); - -my $full_url = "http://localhost".$RT::WebPath."/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password"; -my $r = $ua->get( $full_url); - - -# Verify that the downloaded attachment is the same as what we uploaded. -is($file, $r->content, 'The attachment isn\'t screwed up in download'); - - - -# }}} - -# {{{ Simple I18N testing - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); - -print MAIL <<EOF; -From: root\@localhost -To: rtemail\@example.com -Subject: This is a test of I18N ticket creation -Content-Type: text/plain; charset="utf-8" - -2 accented lines -\303\242\303\252\303\256\303\264\303\273 -\303\241\303\251\303\255\303\263\303\272 -bye -EOF -close (MAIL); - -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -my $unitickets = RT::Tickets->new($RT::SystemUser); -$unitickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$unitickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); -my $unitick = $unitickets->First(); -ok (UNIVERSAL::isa($unitick,'RT::Ticket')); -ok ($unitick->Id, "found ticket ".$unitick->Id); -ok ($unitick->Subject eq 'This is a test of I18N ticket creation', "Created the ticket - ". $unitick->Subject); - - - -my $unistring = "\303\241\303\251\303\255\303\263\303\272"; -Encode::_utf8_on($unistring); -is ($unitick->Transactions->First->Content, $unitick->Transactions->First->Attachments->First->Content, "Content is ". $unitick->Transactions->First->Attachments->First->Content); -ok($unitick->Transactions->First->Attachments->First->Content =~ /$unistring/i, $unitick->Id." appears to be unicode ". $unitick->Transactions->First->Attachments->First->Id); -# supposedly I18N fails on the second message sent in. - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); - -print MAIL <<EOF; -From: root\@localhost -To: rtemail\@example.com -Subject: This is a test of I18N ticket creation -Content-Type: text/plain; charset="utf-8" - -2 accented lines -\303\242\303\252\303\256\303\264\303\273 -\303\241\303\251\303\255\303\263\303\272 -bye -EOF -close (MAIL); - -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - -my $tickets2 = RT::Tickets->new($RT::SystemUser); -$tickets2->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets2->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); -my $tick2 = $tickets2->First(); -ok (UNIVERSAL::isa($tick2,'RT::Ticket')); -ok ($tick2->Id, "found ticket ".$tick2->Id); -ok ($tick2->Subject eq 'This is a test of I18N ticket creation', "Created the ticket"); - - - -my $unistring = "\303\241\303\251\303\255\303\263\303\272"; -Encode::_utf8_on($unistring); - -ok ($tick2->Transactions->First->Content =~ $unistring, "It appears to be unicode - ".$tick2->Transactions->First->Content); - -# }}} - - -($val,$msg) = $g->PrincipalObj->RevokeRight(Right => 'CreateTicket'); -ok ($val, $msg); - - - -=end testing - =cut use strict; +use warnings; use Getopt::Long; use LWP::UserAgent; @@ -420,19 +74,23 @@ for (qw(url)) { die "$0 invoked improperly\n\nNo $_ provided to mail gateway!\n" unless $opts{$_}; } -undef $/; my $ua = LWP::UserAgent->new(); $ua->cookie_jar( { file => $opts{jar} } ); my %args = ( - queue => $opts{queue}, - action => $opts{action}, - SessionType => 'REST', # Surpress login box + SessionType => 'REST', # Surpress login box ); +foreach ( qw(queue action) ) { + $args{$_} = $opts{$_} if defined $opts{$_}; +}; # Read the message in from STDIN -$args{'message'} = <>; +$args{'message'} = do { local (@ARGV, $/); <> }; +unless ( $args{message} =~ /\S/ ) { + print STDERR "$0: no message passed on STDIN!\n"; + exit 0; +} if ($opts{'extension'}) { $args{$opts{'extension'}} = $ENV{'EXTENSION'}; @@ -500,7 +158,7 @@ sub check_failure { Usual invocation (from MTA): - rt-mailgate --action (correspond|comment) --queue queuename + rt-mailgate --action (correspond|comment|...) --queue queuename --url http://your.rt.server/ [ --debug ] [ --extension (queue|action|ticket) ] @@ -516,15 +174,31 @@ See C<man rt-mailgate> for more. =item C<--action> -Specifies whether this is a correspondence or comment address. +Specifies what happens to email sent to this alias. The avaliable +basic actions are: C<correspond>, C<comment>. + + +If you've set the RT configuration variable B<$RT::UnsafeEmailCommands>, +C<take> and C<resolve> are also available. You can execute two or more +actions on a single message using a C<-> separated list. RT will execute +the actions in the listed order. For example you can use C<take-comment>, +C<correspond-resolve> or C<take-comment-resolve> as actions. + +Note that C<take> and C<resolve> actions ignore message text if used +alone. Include a C<comment> or C<correspond> action if you want RT +to record the incoming message. + +The default action is C<correspond>. =item C<--queue> -Reflects which queue this address handles. +This flag determines which queue this alias should create a ticket in if no ticket identifier +is found. =item C<--url> -The location of the web server for your RT instance. +This flag tells the mail gateway where it can find your RT server. You should +probably use the same URL that users use to log into RT. =item C<--extension> OPTIONAL @@ -615,6 +289,7 @@ several parameters: =item Message A C<MIME::Entity> object representing the email + =item CurrentUser An C<RT::CurrentUser> object diff --git a/rt/bin/rt-mailgate.in b/rt/bin/rt-mailgate.in index 6264d4389..49c4facfe 100644 --- a/rt/bin/rt-mailgate.in +++ b/rt/bin/rt-mailgate.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: diff --git a/rt/bin/rt.in b/rt/bin/rt.in index 09b52ae34..9731acf7d 100644 --- a/rt/bin/rt.in +++ b/rt/bin/rt.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: diff --git a/rt/bin/standalone_httpd b/rt/bin/standalone_httpd new file mode 100755 index 000000000..1057ce0ea --- /dev/null +++ b/rt/bin/standalone_httpd @@ -0,0 +1,67 @@ +#!/usr/bin/perl -w +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# 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 }}} +use warnings; +use strict; + +BEGIN { + use lib( "/opt/rt3/local/lib", "/opt/rt3/lib"); + use RT; + RT::LoadConfig(); + if ($RT::DevelMode) { require Module::Refresh; } +} + +RT::Init(); + +my $port = shift @ARGV || $RT::WebPort || '8080'; +use RT::Interface::Web::Standalone; +my $server = RT::Interface::Web::Standalone->new; +$server->port($port); +$server->run(); + + diff --git a/rt/bin/standalone_httpd.in b/rt/bin/standalone_httpd.in index c26e2a522..8aebdb867 100755 --- a/rt/bin/standalone_httpd.in +++ b/rt/bin/standalone_httpd.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: diff --git a/rt/bin/webmux.pl b/rt/bin/webmux.pl index 96e7ebf8d..02eb84640 100755 --- a/rt/bin/webmux.pl +++ b/rt/bin/webmux.pl @@ -1,9 +1,15 @@ #!/usr/bin/perl -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (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 @@ -15,133 +21,116 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # -# END LICENSE BLOCK - +# 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 }}} use strict; BEGIN { - $ENV{'PATH'} = '/bin:/usr/bin'; # or whatever you need + $ENV{'PATH'} = '/bin:/usr/bin'; # or whatever you need $ENV{'CDPATH'} = '' if defined $ENV{'CDPATH'}; $ENV{'SHELL'} = '/bin/sh' if defined $ENV{'SHELL'}; $ENV{'ENV'} = '' if defined $ENV{'ENV'}; $ENV{'IFS'} = '' if defined $ENV{'IFS'}; - + + use CGI qw(-private_tempfiles); #bring this in before mason, to make sure we + #set private_tempfiles + + die "RT does not support mod_perl 1.99. Please upgrade to mod_perl 2.0" + if $ENV{'MOD_PERL'} + and $ENV{'MOD_PERL'} =~ m{mod_perl/(?:1\.9)}; + } -use lib ("/opt/rt3/local/lib", "/opt/rt3/lib"); +use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" ); use RT; package RT::Mason; -use CGI qw(-private_tempfiles); #bring this in before mason, to make sure we - #set private_tempfiles +use vars qw($Nobody $SystemUser $Handler $r); +#This drags in RT's config.pm BEGIN { - if ($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 ($CGI::MOD_PERL) { - require HTML::Mason::ApacheHandler; - } - else { - require HTML::Mason::CGIHandler; - } + RT::LoadConfig(); + if ($RT::DevelMode) { require Module::Refresh; } } -use HTML::Mason; # brings in subpackages: Parser, Interp, etc. - -use vars qw($Nobody $SystemUser $r); - -#This drags in RT's config.pm -RT::LoadConfig(); - -use Carp; { + package HTML::Mason::Commands; use vars qw(%session); - - use RT::Tickets; - use RT::Transactions; - use RT::Users; - use RT::CurrentUser; - use RT::Templates; - use RT::Queues; - use RT::ScripActions; - use RT::ScripConditions; - use RT::Scrips; - use RT::Groups; - use RT::GroupMembers; - use RT::CustomFields; - use RT::CustomFieldValues; - use RT::TicketCustomFieldValues; - - use RT::Interface::Web; - use MIME::Entity; - use Text::Wrapper; - use CGI::Cookie; - use Time::ParseDate; - use HTML::Entities; } +use RT::Interface::Web; +use RT::Interface::Web::Handler; +$Handler = RT::Interface::Web::Handler->new(@RT::MasonParameters); -# 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)/) { - # Clean up our umask to protect session files - umask(0077); - -if ( $CGI::MOD_PERL) { - chown( Apache->server->uid, Apache->server->gid, [$RT::MasonSessionDir] ) - if Apache->server->can('uid'); - } - # Die if WebSessionDir doesn't exist or we can't write to it - stat($RT::MasonSessionDir); - die "Can't read and write $RT::MasonSessionDir" - unless ( ( -d _ ) and ( -r _ ) and ( -w _ ) ); +if ($ENV{'MOD_PERL'} && !$RT::DevelMode) { + # Under static_source, we need to purge the component cache + # each time we restart, so newer components may be reloaded. + # + # We can't do this in FastCGI or we'll blow away the component root _every_ time a new server starts + # which happens every few hits. + + use File::Path qw( rmtree ); + use File::Glob qw( bsd_glob ); + my @files = bsd_glob("$RT::MasonDataDir/obj/*"); + rmtree([ @files ], 0, 1) if @files; } -my $ah = &RT::Interface::Web::NewApacheHandler(@RT::MasonParameters) if $CGI::MOD_PERL; - sub handler { ($r) = @_; local $SIG{__WARN__}; local $SIG{__DIE__}; - RT::Init(); + if ($r->content_type =~ m/^httpd\b.*\bdirectory/i) { + use File::Spec::Unix; + # Our DirectoryIndex is always index.html, regardless of httpd settings + $r->filename( File::Spec::Unix->catfile( $r->filename, 'index.html' ) ); + } +# elsif (defined( $r->content_type )) { + #$r->content_type !~ m!(^text/|\bxml\b)!i or return -1; +# } - # We don't need to handle non-text items - return -1 if defined( $r->content_type ) && $r->content_type !~ m|^text/|io; + Module::Refresh->refresh if $RT::DevelMode; + + RT::Init(); my %session; my $status; - eval { $status = $ah->handle_request($r) }; + eval { $status = $Handler->handle_request($r) }; if ($@) { - $RT::Logger->crit($@); + $RT::Logger->crit($@); } - undef (%session); + undef(%session); + + RT::Interface::Web::Handler->CleanupRequest(); - if ($RT::Handle->TransactionDepth) { - $RT::Handle->ForceRollback; - $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") ; - } return $status; } diff --git a/rt/bin/webmux.pl.in b/rt/bin/webmux.pl.in index f9b792f88..b21d02673 100644 --- a/rt/bin/webmux.pl.in +++ b/rt/bin/webmux.pl.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -25,7 +25,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/copyleft/gpl.html. +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. # # # CONTRIBUTION SUBMISSION POLICY: |