summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rt/Makefile31
-rwxr-xr-xrt/README46
-rwxr-xr-xrt/bin/mason_handler.fcgi24
-rwxr-xr-xrt/bin/mason_handler.scgi8
-rwxr-xr-xrt/bin/rt-mailgate109
-rwxr-xr-xrt/bin/webmux.pl29
-rw-r--r--rt/etc/acl.Oracle12
-rwxr-xr-xrt/etc/schema.Pg16
-rwxr-xr-xrt/etc/schema.mysql10
-rw-r--r--rt/lib/RT.pm33
-rwxr-xr-xrt/lib/RT/Action/Autoreply.pm16
-rwxr-xr-xrt/lib/RT/Action/SendEmail.pm4
-rwxr-xr-xrt/lib/RT/CurrentUser.pm34
-rw-r--r--rt/lib/RT/Handle.pm9
-rw-r--r--rt/lib/RT/Interface/CLI.pm2
-rwxr-xr-xrt/lib/RT/Interface/Email.pm294
-rw-r--r--rt/lib/RT/Interface/Web.pm150
-rwxr-xr-xrt/lib/RT/Record.pm5
18 files changed, 594 insertions, 238 deletions
diff --git a/rt/Makefile b/rt/Makefile
index 6447221..0895874 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -1,20 +1,19 @@
# BEGIN LICENSE BLOCK
#
-# Copyright (c) 1996-2002 Jesse Vincent <jesse@bestpractical.com>
+# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
#
# (Except where explictly superceded by other copyright notices)
#
# 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
+# 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.
#
-#
# 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
@@ -22,8 +21,6 @@
#
#
# END LICENSE BLOCK
-
-
#
# DO NOT HAND-EDIT the file named 'Makefile'. This file is autogenerated.
# Have a look at "configure" and "Makefile.in" instead
@@ -39,7 +36,7 @@ SITE_CONFIG_FILE = $(CONFIG_FILE_PATH)/RT_SiteConfig.pm
RT_VERSION_MAJOR = 3
RT_VERSION_MINOR = 0
-RT_VERSION_PATCH = 4
+RT_VERSION_PATCH = 9
RT_VERSION = $(RT_VERSION_MAJOR).$(RT_VERSION_MINOR).$(RT_VERSION_PATCH)
TAG = rt-$(RT_VERSION_MAJOR)-$(RT_VERSION_MINOR)-$(RT_VERSION_PATCH)
@@ -101,8 +98,8 @@ RT_MODPERL_HANDLER = $(RT_BIN_PATH)/webmux.pl
RT_FASTCGI_HANDLER = $(RT_BIN_PATH)/mason_handler.fcgi
# RT_WIN32_FASTCGI_HANDLER is the mason handler script for FastCGI
RT_WIN32_FASTCGI_HANDLER = $(RT_BIN_PATH)/mason_handler.svc
-# RT's admin CLI
-RT_CLI_ADMIN_BIN = $(RT_BIN_PATH)/rtadmin
+# RT's CLI
+RT_CLI_BIN = $(RT_BIN_PATH)/rt
# RT's mail gateway
RT_MAILGATE_BIN = $(RT_BIN_PATH)/rt-mailgate
# RT's cron tool
@@ -115,6 +112,7 @@ SETGID_BINARIES = $(DESTDIR)/$(RT_FASTCGI_HANDLER) \
BINARIES = $(DESTDIR)/$(RT_MODPERL_HANDLER) \
$(DESTDIR)/$(RT_MAILGATE_BIN) \
+ $(DESTDIR)/$(RT_CLI_BIN) \
$(DESTDIR)/$(RT_CRON_BIN) \
$(SETGID_BINARIES)
SYSTEM_BINARIES = $(DESTDIR)/$(RT_SBIN_PATH)/
@@ -128,6 +126,7 @@ SYSTEM_BINARIES = $(DESTDIR)/$(RT_SBIN_PATH)/
# DB_TYPE defines what sort of database RT trys to talk to
# "mysql" is known to work.
# "Pg" is known to work
+# "Informix" is known to work
DB_TYPE = mysql
@@ -138,7 +137,8 @@ DB_TYPE = mysql
# For mysql, you probably want 'root'
# For Pg, you probably want 'postgres'
-# For oracle, you want 'system'
+# For Oracle, you want 'system'
+# For Informix, you want 'informix'
DB_DBA = root
@@ -211,7 +211,7 @@ upgrade-instruct:
@echo " $(RT_SBIN_PATH)/rt-setup-database --action insert --datafile etc/upgrade/<version>"
-upgrade: dirs upgrade-noclobber upgrade-instruct
+upgrade: config-install dirs files-install fixperms upgrade-instruct
upgrade-noclobber: config-install libs-install html-install bin-install local-install doc-install fixperms
@@ -312,13 +312,16 @@ config-install:
test:
$(PERL) -Ilib lib/t/00smoke.t
-regression-nosetgid-quiet: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
+regression-install: config-install
+ $(PERL) -pi -e 's/Set\(\$$DatabaseName.*\);/Set\(\$$DatabaseName, "rt3regression"\);/' $(DESTDIR)/$(CONFIG_FILE)
+
+regression-nosetgid-quiet: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
$(PERL) sbin/regression_harness
-regression-nosetgid: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
+regression-nosetgid: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
$(PERL) lib/t/02regression.t
-regression: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods apachectl
+regression: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms apachectl
$(PERL) lib/t/02regression.t
regression-quiet:
@@ -397,7 +400,9 @@ bin-install:
-cp -rp \
bin/rt-mailgate \
bin/mason_handler.fcgi \
+ bin/mason_handler.scgi \
bin/mason_handler.svc \
+ bin/rt \
bin/webmux.pl \
bin/rt-crontool \
$(DESTDIR)/$(RT_BIN_PATH)
diff --git a/rt/README b/rt/README
index 7c5e4d4..7188f09 100755
--- a/rt/README
+++ b/rt/README
@@ -21,6 +21,7 @@
#
#
# END LICENSE BLOCK
+
RT is an enterprise-grade issue tracking system. It allows
organizations to keep track of their to-do lists, who is working
on which tasks, what's already been done, and when tasks were
@@ -36,22 +37,22 @@ up and use.
REQUIRED PACKAGES:
------------------
-o Perl 5.8.0 or later (http://www.perl.com).
+o Perl 5.8.3 or later (http://www.perl.com).
(If you intend to use the FastCGI or SpeedyCGI support, you
need to make sure that perl has been built with support for
setgid perl scripts.)`
+ Perl versions prior to 5.8.3 contain bugs that could result in data
+ corruption. We recommend strongly that you use 5.8.3 or newer.
+
Perl 5.6.1 is currently deprecated and will be officially desupported
in a future release
o A DB backend; MySQL is recommended ( http://www.mysql.com )
Currently supported: Mysql 4.0.13 or later.
Postgres 7.2 or later.
-
- Mysql 3.23.46 or newer with support for InnoDB
- is currently deprecated and will be officially
- desupported in a future release.
+ Oracle 9iR2.
o Apache version 1.3.x or 2.x (http://httpd.apache.org)
with mod_perl -- (http://perl.apache.org )
@@ -119,7 +120,7 @@ http://www.bestpractical.com/rt
perl sbin/rt-test-dependencies \
--with-<databasename> --with-<web-environment>
- databasename is one of: mysql, postgres
+ databasename is one of: mysql, postgres, oracle
web-environment is one of: fastcgi, modperl1, modperl2
3.2 If there are unsatisfied dependencies, install them by hand or run:
@@ -151,6 +152,10 @@ http://www.bestpractical.com/rt
5b FOR UPGRADING: (Within the RT 3.0.x series)
+
+ Read through the UPGRADING document included in this distribution.
+ It may contain important instructions for updating your database
+
As root, type:
make upgrade (replace "make" with the local name for
Make, if you need to)
@@ -160,6 +165,14 @@ http://www.bestpractical.com/rt
It may then instruct you to update your RT system database objects
+5c FOR UPGRADING: (From RT 2.0.x)
+
+ Download the RT2 to RT3 migration tools from:
+
+ http://bestpractical.com/pub/rt/devel/rt2-to-rt3.tar.gz
+
+ Follow the included instructions.
+
6 Edit etc/RT_SiteConfig.pm in your RT installation directory, by specifying
any values you need to change from the defaults in etc/RT_Config.pm
@@ -192,31 +205,20 @@ Apache
DocumentRoot /opt/rt3/share/html
AddDefaultCharset UTF-8
- # this line applies to Apache2+mod_perl2 only
+ # these four lines apply to Apache2+mod_perl2 only: {{{
+ PerlSetVar MasonArgsMethod CGI
PerlModule Apache2 Apache::compat
+ RewriteEngine On
+ RewriteRule ^(.*)/$ $1/index.html
+ # }}}
PerlModule Apache::DBI
PerlRequire /opt/rt3/bin/webmux.pl
- # this section applies to Apache 1 only
<Location />
SetHandler perl-script
PerlHandler RT::Mason
</Location>
-
- # this section applies to Apache2+mod_perl2 only
- <FilesMatch "\.html$">
- SetHandler perl-script
- PerlHandler RT::Mason
- </FilesMatch>
- <LocationMatch "/Attachment/">
- SetHandler perl-script
- PerlHandler RT::Mason
- </LocationMatch>
- <LocationMatch "/REST/">
- SetHandler perl-script
- PerlHandler RT::Mason
- </LocationMatch>
</VirtualHost>
diff --git a/rt/bin/mason_handler.fcgi b/rt/bin/mason_handler.fcgi
index 431eccb..93d1f88 100755
--- a/rt/bin/mason_handler.fcgi
+++ b/rt/bin/mason_handler.fcgi
@@ -27,7 +27,7 @@ use strict;
use File::Basename;
require ('/opt/rt3/bin/webmux.pl');
-my $h = &RT::Interface::Web::NewCGIHandler();
+my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters);
# Enter CGI::Fast mode, which should also work as a vanilla CGI script.
require CGI::Fast;
@@ -44,11 +44,25 @@ while ( my $cgi = CGI::Fast->new ) {
$ENV{'ENV'} = '' if defined $ENV{'ENV'};
$ENV{'IFS'} = '' if defined $ENV{'IFS'};
- unless ($h->interp->comp_exists($cgi->path_info)) {
- $cgi->path_info($cgi->path_info . "/index.html");
+ RT::ConnectToDatabase();
+
+ if ( ( !$h->interp->comp_exists( $cgi->path_info ) )
+ && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) {
+ $cgi->path_info( $cgi->path_info . "/index.html" );
+ }
+
+ eval { $h->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") ;
}
- $h->handle_cgi_object($cgi);
- # _should_ always be tied
+
+
}
1;
diff --git a/rt/bin/mason_handler.scgi b/rt/bin/mason_handler.scgi
index 8e1135c..7774189 100755
--- a/rt/bin/mason_handler.scgi
+++ b/rt/bin/mason_handler.scgi
@@ -26,16 +26,18 @@
use strict;
require ('/opt/rt3/bin/webmux.pl');
-my $h = &RT::Interface::Web::NewCGIHandler();
+my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters);
require CGI;
RT::Init();
my $cgi = CGI->new;
-unless ($h->interp->comp_exists($cgi->path_info)) {
- $cgi->path_info($cgi->path_info . "/index.html");
+if ( ( !$h->interp->comp_exists( $cgi->path_info ) )
+ && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) {
+ $cgi->path_info( $cgi->path_info . "/index.html" );
}
+
$h->handle_cgi_object($cgi);
1;
diff --git a/rt/bin/rt-mailgate b/rt/bin/rt-mailgate
index b304436..8af8002 100755
--- a/rt/bin/rt-mailgate
+++ b/rt/bin/rt-mailgate
@@ -1,26 +1,26 @@
#!/usr/bin/perl -w
# BEGIN LICENSE BLOCK
-#
+#
# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-#
+#
# (Except where explictly superceded by other copyright notices)
-#
+#
# 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.
-#
+#
# 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.
-#
-#
+#
+#
# END LICENSE BLOCK
=head1 NAME
@@ -31,10 +31,25 @@ rt-mailgate - Mail interface to RT3.
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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -45,6 +60,9 @@ 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');
@@ -59,7 +77,7 @@ ok ($tick->Subject eq 'This is a test of new ticket creation', "Created the tick
# {{{This is a test of new ticket creation as an unknown user
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -69,6 +87,8 @@ 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');
@@ -94,7 +114,7 @@ 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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -104,6 +124,8 @@ Blah!
Foob!
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$tickets = RT::Tickets->new($RT::SystemUser);
@@ -126,7 +148,7 @@ ok( $u->Id != 0, " user does not exist and was created by ticket submission");
#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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -136,6 +158,8 @@ 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');
@@ -148,7 +172,7 @@ ok( $u->Id == 0, " user does not exist and was not created by ticket corresponde
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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -158,6 +182,8 @@ Blah!
Foob!
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$u = RT::User->new($RT::SystemUser);
@@ -173,7 +199,7 @@ ok( $u->Id != 0, " user exists and was created by ticket correspondence submissi
#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/ --queue general --action comment"), "Opened the mailgate - $@");
+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
@@ -184,6 +210,9 @@ 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");
@@ -196,7 +225,7 @@ ok( $u->Id == 0, " user does not exist and was not created by ticket comment sub
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/ --queue general --action comment"), "Opened the mailgate - $@");
+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
@@ -207,6 +236,8 @@ 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');
@@ -227,17 +258,20 @@ my $entity = MIME::Entity->build( From => 'root@localhost',
Data => ['This is a test of a binary attachment']);
# currently in lib/t/autogen
-$entity->attach(Path => '../../../html/NoAuth/images/spacer.gif',
+$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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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');
@@ -273,7 +307,7 @@ use LWP::UserAgent;
# Grab the binary attachment via the web ui
my $ua = LWP::UserAgent->new();
-my $full_url = "http://localhost/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password";
+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);
@@ -286,7 +320,7 @@ 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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -301,6 +335,9 @@ 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');
@@ -317,7 +354,7 @@ is ($unitick->Transactions->First->Content, $unitick->Transactions->First->Attac
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/ --queue general --action correspond"), "Opened the mailgate - $@");
+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
@@ -332,6 +369,9 @@ 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');
@@ -367,7 +407,7 @@ use LWP::UserAgent;
use constant EX_TEMPFAIL => 75;
my %opts;
-GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s" );
+GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s", "timeout=i" );
if ( $opts{help} ) {
require Pod::Usage;
@@ -381,17 +421,18 @@ for (qw(url)) {
}
undef $/;
-my $message = <>;
my $ua = LWP::UserAgent->new();
$ua->cookie_jar( { file => $opts{jar} } );
my %args = (
queue => $opts{queue},
action => $opts{action},
- message => $message,
SessionType => 'REST', # Surpress login box
);
+# Read the message in from STDIN
+$args{'message'} = <>;
+
if ($opts{'extension'}) {
$args{$opts{'extension'}} = $ENV{'EXTENSION'};
@@ -404,6 +445,7 @@ warn "Connecting to $full_url" if $opts{'debug'};
+$ua->timeout(exists($opts{'timeout'}) ? $opts{'timeout'} : 180);
my $r = $ua->post( $full_url, {%args} );
check_failure($r);
@@ -414,7 +456,7 @@ if ( $content !~ /^(ok|not ok)/ ) {
# It's not the server's fault if the mail is bogus. We just want to know that
# *something* came out of the server.
- die <<EOF
+ warn <<EOF;
RT server error.
The RT server which handled your email did not behave as expected. It
@@ -423,8 +465,13 @@ said:
$content
EOF
+exit EX_TEMPFAIL;
+
}
+exit;
+
+
sub check_failure {
my $r = shift;
return if $r->is_success();
@@ -455,7 +502,11 @@ Usual invocation (from MTA):
rt-mailgate --action (correspond|comment) --queue queuename
--url http://your.rt.server/
- [ --extension (queue|action|ticket)
+ [ --debug ]
+ [ --extension (queue|action|ticket) ]
+ [ --timeout seconds ]
+
+
See C<man rt-mailgate> for more.
@@ -486,6 +537,16 @@ submitted to will be set to the value of $EXTENSION. By specifying
is related to. "action" will allow the user to specify either "comment" or
"correspond" in the address extension.
+=item C<--debug> OPTIONAL
+
+Print debugging output to standard error
+
+
+=item C<--timeout> OPTIONAL
+
+Configure the timeout for posting the message to the web server. The
+default timeout is 3 minutes (180 seconds).
+
=head1 DESCRIPTION
diff --git a/rt/bin/webmux.pl b/rt/bin/webmux.pl
index 21cb83f..96e7ebf 100755
--- a/rt/bin/webmux.pl
+++ b/rt/bin/webmux.pl
@@ -31,6 +31,7 @@ BEGIN {
$ENV{'SHELL'} = '/bin/sh' if defined $ENV{'SHELL'};
$ENV{'ENV'} = '' if defined $ENV{'ENV'};
$ENV{'IFS'} = '' if defined $ENV{'IFS'};
+
}
use lib ("/opt/rt3/local/lib", "/opt/rt3/lib");
@@ -42,6 +43,17 @@ use CGI qw(-private_tempfiles); #bring this in before mason, to make sure we
#set private_tempfiles
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;
}
@@ -104,21 +116,32 @@ if ( $CGI::MOD_PERL) {
unless ( ( -d _ ) and ( -r _ ) and ( -w _ ) );
}
-my $ah = &RT::Interface::Web::NewApacheHandler() if $CGI::MOD_PERL;
+my $ah = &RT::Interface::Web::NewApacheHandler(@RT::MasonParameters) if $CGI::MOD_PERL;
sub handler {
($r) = @_;
+ local $SIG{__WARN__};
+ local $SIG{__DIE__};
+
RT::Init();
# We don't need to handle non-text items
return -1 if defined( $r->content_type ) && $r->content_type !~ m|^text/|io;
my %session;
- my $status = $ah->handle_request($r);
+ my $status;
+ eval { $status = $ah->handle_request($r) };
+ if ($@) {
+ $RT::Logger->crit($@);
+ }
+
undef (%session);
- $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") if $RT::Handle->TransactionDepth;
+ 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/etc/acl.Oracle b/rt/etc/acl.Oracle
index c8667c0..ac29215 100644
--- a/rt/etc/acl.Oracle
+++ b/rt/etc/acl.Oracle
@@ -1,10 +1,10 @@
sub acl {
return (
-"CREATE USER ${RT::DatabaseUser} identified by ${RT::DatabasePassword}".
-"temporary tablespace TEMP" .
-"default tablespace USERS" .
-"quota unlimited on USERS;" ,
-"grant connect, resource to ${RT::DatabaseUser};",
-"exit;");
+"CREATE USER ${RT::DatabaseUser} identified by ${RT::DatabasePassword} ".
+"default tablespace USERS " .
+"temporary tablespace TEMP " .
+"quota unlimited on USERS" ,
+"grant connect, resource to ${RT::DatabaseUser}"
+);
}
1;
diff --git a/rt/etc/schema.Pg b/rt/etc/schema.Pg
index ba0d6fc..085c615 100755
--- a/rt/etc/schema.Pg
+++ b/rt/etc/schema.Pg
@@ -3,9 +3,6 @@
--
------------------------------------------------------------------
-BEGIN;
-
-
--
@@ -93,6 +90,7 @@ CREATE TABLE Links (
);
CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ;
+CREATE INDEX Links4 ON Links(Type,LocalBase);
-- }}}
@@ -136,7 +134,7 @@ CREATE TABLE Groups (
Description varchar(255) NULL ,
Domain varchar(64),
Type varchar(64),
- Instance varchar(64),
+ Instance integer,
PRIMARY KEY (id)
);
@@ -192,7 +190,7 @@ CREATE TABLE Transactions (
Field varchar(40) NULL ,
OldValue varchar(255) NULL ,
NewValue varchar(255) NULL ,
- Data varchar(100) NULL ,
+ Data varchar(255) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created TIMESTAMP NULL ,
@@ -500,6 +498,9 @@ CREATE TABLE TicketCustomFieldValues (
);
+CREATE INDEX TicketCustomFieldValues1 ON TicketCustomFieldValues (CustomField,Ticket,Content);
+CREATE INDEX TicketCustomFieldValues2 ON TicketCustomFieldValues (CustomField,Ticket);
+
-- }}}
-- {{{ CustomFields
@@ -556,6 +557,8 @@ CREATE TABLE CustomFieldValues (
);
+CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField);
+
-- }}}
-- {{{ Sessions
@@ -573,6 +576,3 @@ CREATE TABLE sessions (
-- }}}
-
-
-COMMIT;
diff --git a/rt/etc/schema.mysql b/rt/etc/schema.mysql
index 46f8ec5..14e9223 100755
--- a/rt/etc/schema.mysql
+++ b/rt/etc/schema.mysql
@@ -62,6 +62,7 @@ CREATE TABLE Links (
CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ;
CREATE INDEX Links2 ON Links (Base, Type) ;
CREATE INDEX Links3 ON Links (Target, Type) ;
+CREATE INDEX Links4 ON Links(Type,LocalBase);
# }}}
@@ -87,7 +88,7 @@ CREATE TABLE Groups (
Description varchar(255) NULL ,
Domain varchar(64),
Type varchar(64),
- Instance varchar(64),
+ Instance integer,
PRIMARY KEY (id)
) TYPE=InnoDB;
@@ -125,7 +126,7 @@ CREATE TABLE Transactions (
Field varchar(40) NULL ,
OldValue varchar(255) NULL ,
NewValue varchar(255) NULL ,
- Data varchar(100) NULL ,
+ Data varchar(255) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created DATETIME NULL ,
@@ -358,6 +359,9 @@ CREATE TABLE TicketCustomFieldValues (
PRIMARY KEY (id)
) TYPE=InnoDB;
+CREATE INDEX TicketCustomFieldValues1 ON TicketCustomFieldValues (CustomField,Ticket,Content);
+CREATE INDEX TicketCustomFieldValues2 ON TicketCustomFieldValues (CustomField,Ticket);
+
# }}}
# {{{ CustomFields
@@ -399,6 +403,8 @@ CREATE TABLE CustomFieldValues (
PRIMARY KEY (id)
) TYPE=InnoDB;
+CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField);
+
# }}}
# {{{ Sessions
diff --git a/rt/lib/RT.pm b/rt/lib/RT.pm
index 90c332b..7e941a2 100644
--- a/rt/lib/RT.pm
+++ b/rt/lib/RT.pm
@@ -47,7 +47,7 @@ use vars qw($VERSION $System $SystemUser $Nobody $Handle $Logger
$MasonSessionDir
);
-$VERSION = '3.0.4';
+$VERSION = '3.0.9';
$CORE_CONFIG_FILE = "/opt/rt3/etc/RT_Config.pm";
$SITE_CONFIG_FILE = "/opt/rt3/etc/RT_SiteConfig.pm";
@@ -117,13 +117,10 @@ sub LoadConfig {
=cut
sub Init {
- require RT::Handle;
+
#Get a database connection
- unless ($Handle && $Handle->dbh->ping) {
- $Handle = RT::Handle->new();
- }
- $Handle->Connect();
-
+ ConnectToDatabase();
+
#RT's system user is a genuine database user. its id lives here
$SystemUser = new RT::CurrentUser();
$SystemUser->LoadByName('RT_System');
@@ -137,6 +134,21 @@ sub Init {
InitLogging();
}
+
+=head2 ConnectToDatabase
+
+Get a database connection
+
+=cut
+
+sub ConnectToDatabase {
+ require RT::Handle;
+ unless ($Handle && $Handle->dbh && $Handle->dbh->ping) {
+ $Handle = RT::Handle->new();
+ }
+ $Handle->Connect();
+}
+
=head2 InitLogging
Create the RT::Logger object.
@@ -282,8 +294,15 @@ sub DropSetGIDPermissions {
=head1 BUGS
+Please report them to rt-3.0-bugs@fsck.com, if you know what's broken and have at least some idea of what needs to be fixed.
+If you're not sure what's going on, report them rt-devel@lists.fsck.com.
+
=head1 SEE ALSO
+L<RT::StyleGuide>
+L<DBIx::SearchBuilder>
+
+
=begin testing
diff --git a/rt/lib/RT/Action/Autoreply.pm b/rt/lib/RT/Action/Autoreply.pm
index 81f7bdd..f58b8f2 100755
--- a/rt/lib/RT/Action/Autoreply.pm
+++ b/rt/lib/RT/Action/Autoreply.pm
@@ -74,10 +74,18 @@ sub SetReturnAddress {
}
unless ($self->TemplateObj->MIMEObj->head->get('From')) {
- my $friendly_name = $self->TicketObj->QueueObj->Description ||
- $self->TicketObj->QueueObj->Name;
- $friendly_name =~ s/"/\\"/g;
- $self->SetHeader('From', "\"$friendly_name\" <$replyto>");
+ if ($RT::UseFriendlyFromLine) {
+ my $friendly_name = $self->TicketObj->QueueObj->Description ||
+ $self->TicketObj->QueueObj->Name;
+ $friendly_name =~ s/"/\\"/g;
+ $self->SetHeader( 'From',
+ sprintf($RT::FriendlyFromLineFormat,
+ $self->MIMEEncodeString( $friendly_name, $RT::EmailOutputEncoding ), $replyto),
+ );
+ }
+ else {
+ $self->SetHeader( 'From', $replyto );
+ }
}
unless ($self->TemplateObj->MIMEObj->head->get('Reply-To')) {
diff --git a/rt/lib/RT/Action/SendEmail.pm b/rt/lib/RT/Action/SendEmail.pm
index dac8fc8..6592380 100755
--- a/rt/lib/RT/Action/SendEmail.pm
+++ b/rt/lib/RT/Action/SendEmail.pm
@@ -129,7 +129,7 @@ sub Commit {
$self->SetHeader( 'Cc', join ( ',', @{ $self->{'Cc'} } ) )
if ( $self->{'Cc'} && @{ $self->{'Cc'} } );
$self->SetHeader( 'Bcc', join ( ',', @{ $self->{'Bcc'} } ) )
- if ( $self->{'Cc'} && @{ $self->{'Bcc'} } );
+ if ( $self->{'Bcc'} && @{ $self->{'Bcc'} } );
$self->SetHeader('MIME-Version', '1.0');
@@ -266,7 +266,7 @@ sub SendMessage {
and ( !$MIMEObj->head->get('To') ) );
if ( $RT::MailCommand eq 'sendmailpipe' ) {
eval {
- open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" );
+ open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" ) || die $!;
print MAIL $MIMEObj->as_string;
close(MAIL);
};
diff --git a/rt/lib/RT/CurrentUser.pm b/rt/lib/RT/CurrentUser.pm
index 4ca2f98..7fcc65c 100755
--- a/rt/lib/RT/CurrentUser.pm
+++ b/rt/lib/RT/CurrentUser.pm
@@ -70,7 +70,7 @@ sub _Init {
$self->Load($Name);
}
- $self->CurrentUser($self);
+ # $self->CurrentUser($self);
}
# }}}
@@ -104,15 +104,13 @@ sub Delete {
sub UserObj {
my $self = shift;
- unless ($self->{'UserObj'}) {
use RT::User;
- $self->{'UserObj'} = RT::User->new($self);
- unless ($self->{'UserObj'}->Load($self->Id)) {
+ my $user = RT::User->new($self);
+
+ unless ($user->Load($self->Id)) {
$RT::Logger->err($self->loc("Couldn't load [_1] from the users database.\n", $self->Id));
}
-
- }
- return ($self->{'UserObj'});
+ return ($user);
}
# }}}
@@ -160,6 +158,7 @@ sub _Accessible {
Gecos => 'read',
RealName => 'read',
Password => 'neither',
+ Lang => 'read',
EmailAddress => 'read',
Privileged => 'read',
IsAdministrator => 'read'
@@ -241,6 +240,11 @@ sub Load {
if ($identifier !~ /\D/) {
$self->SUPER::LoadById($identifier);
}
+
+ elsif (UNIVERSAL::isa($identifier,"RT::User")) {
+ # DWIM if they pass a user in
+ $self->SUPER::LoadById($identifier->Id);
+ }
else {
# This is a bit dangerous, we might get false authen if somebody
# uses ambigous userids or real names:
@@ -329,6 +333,9 @@ sub LanguageHandle {
if ((!defined $self->{'LangHandle'}) ||
(!UNIVERSAL::can($self->{'LangHandle'}, 'maketext')) ||
(@_)) {
+ if ( $self->Lang) {
+ push @_, $self->Lang;
+ }
$self->{'LangHandle'} = RT::I18N->get_handle(@_);
}
# Fall back to english.
@@ -365,6 +372,19 @@ sub loc_fuzzy {
}
# }}}
+
+=head2 CurrentUser
+
+Return the current currentuser object
+
+=cut
+
+sub CurrentUser {
+ my $self = shift;
+ return($self);
+
+}
+
eval "require RT::CurrentUser_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/CurrentUser_Vendor.pm});
eval "require RT::CurrentUser_Local";
diff --git a/rt/lib/RT/Handle.pm b/rt/lib/RT/Handle.pm
index 5cdb65e..9b611b9 100644
--- a/rt/lib/RT/Handle.pm
+++ b/rt/lib/RT/Handle.pm
@@ -60,9 +60,12 @@ Takes nothing. Calls SUPER::Connect with the needed args
sub Connect {
my $self=shift;
-# Unless the database port is a positive integer, we really don't want to pass it.
-$self->SUPER::Connect(
+ if ($RT::DatabaseType eq 'Oracle') {
+ $ENV{'NLS_LANG'} = ".UTF8";
+ }
+
+ $self->SUPER::Connect(
User => $RT::DatabaseUser,
Password => $RT::DatabasePassword,
);
@@ -79,9 +82,11 @@ from the config file.
sub BuildDSN {
my $self = shift;
+# Unless the database port is a positive integer, we really don't want to pass it.
$RT::DatabasePort = undef unless (defined $RT::DatabasePort && $RT::DatabasePort =~ /^(\d+)$/);
$RT::DatabaseHost = undef unless (defined $RT::DatabaseHost && $RT::DatabaseHost ne '');
+
$self->SUPER::BuildDSN(Host => $RT::DatabaseHost,
Database => $RT::DatabaseName,
Port => $RT::DatabasePort,
diff --git a/rt/lib/RT/Interface/CLI.pm b/rt/lib/RT/Interface/CLI.pm
index ec0e877..a3c840a 100644
--- a/rt/lib/RT/Interface/CLI.pm
+++ b/rt/lib/RT/Interface/CLI.pm
@@ -33,7 +33,7 @@ BEGIN {
use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# set the version for version checking
- $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
+ $VERSION = do { my @r = (q$Revision: 1.1.1.1 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
@ISA = qw(Exporter);
diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm
index 7eec050..241f5f3 100755
--- a/rt/lib/RT/Interface/Email.pm
+++ b/rt/lib/RT/Interface/Email.pm
@@ -27,14 +27,14 @@ use strict;
use Mail::Address;
use MIME::Entity;
use RT::EmailParser;
-
+use File::Temp;
BEGIN {
use Exporter ();
use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# set the version for version checking
- $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
+ $VERSION = do { my @r = (q$Revision: 1.1.1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
@ISA = qw(Exporter);
@@ -153,6 +153,7 @@ sub MailError {
Subject => 'There has been an error',
Explanation => 'Unexplained error',
MIMEObj => undef,
+ Attach => undef,
LogLevel => 'crit',
@_);
@@ -175,7 +176,13 @@ sub MailError {
$mimeobj->sync_headers();
$entity->add_part($mimeobj);
}
-
+
+ if ($args{'Attach'}) {
+ $entity->attach(Data => $args{'Attach'}, Type => 'message/rfc822');
+
+ }
+
+
if ($RT::MailCommand eq 'sendmailpipe') {
open (MAIL, "|$RT::SendmailPath $RT::SendmailArguments") || return(0);
print MAIL $entity->as_string;
@@ -194,12 +201,6 @@ sub CreateUser {
my ($Username, $Address, $Name, $ErrorsTo, $entity) = @_;
my $NewUser = RT::User->new($RT::SystemUser);
- # This data is tainted by some Very Broken mailers.
- # (Sometimes they send raw ISO 8859-1 data here. fear that.
- require Encode;
- $Username = Encode::encode(utf8 => $Username, Encode::FB_PERLQQ()) if defined $Username;
- $Name = Encode::encode(utf8 => $Name, Encode::FB_PERLQQ()) if defined $Name;
-
my ($Val, $Message) =
$NewUser->Create(Name => ($Username || $Address),
EmailAddress => $Address,
@@ -361,36 +362,108 @@ sub ParseAddressFromHeader{
-=head2 Gateway
+=head2 Gateway ARGSREF
+
+
+Takes parameters:
+
+ action
+ queue
+ message
+
This performs all the "guts" of the mail rt-mailgate program, and is
designed to be called from the web interface with a message, user
object, and so on.
+Returns:
+
+ An array of:
+
+ (status code, message, optional ticket object)
+
+ status code is a numeric value.
+
+ for temporary failures, status code should be -75
+
+ for permanent failures which are handled by RT, status code should be 0
+
+ for succces, the status code should be 1
+
+
+
=cut
sub Gateway {
- my %args = ( message => undef,
- queue => 1,
- action => 'correspond',
- ticket => undef,
- @_ );
+ my $argsref = shift;
+
+ my %args = %$argsref;
+
+ # Set some reasonable defaults
+ $args{'action'} = 'correspond' unless ( $args{'action'} );
+ $args{'queue'} = '1' unless ( $args{'queue'} );
# Validate the action
unless ( $args{'action'} =~ /^(comment|correspond|action)$/ ) {
# Can't safely loc this. What object do we loc around?
- return ( 0, "Invalid 'action' parameter", undef );
+ $RT::Logger->crit("Mail gateway called with an invalid action paramenter '".$args{'action'}."' for queue '".$args{'queue'}."'");
+
+ return ( -75, "Invalid 'action' parameter", undef );
}
my $parser = RT::EmailParser->new();
- $parser->ParseMIMEEntityFromScalar( $args{'message'} );
+ my ( $fh, $temp_file );
+ for ( 1 .. 10 ) {
+
+ # on NFS and NTFS, it is possible that tempfile() conflicts
+ # with other processes, causing a race condition. we try to
+ # accommodate this by pausing and retrying.
+ last if ( $fh, $temp_file ) = eval { File::Temp::tempfile(undef, UNLINK => 0) };
+ sleep 1;
+ }
+ if ($fh) {
+ binmode $fh; #thank you, windows
+ $fh->autoflush(1);
+ print $fh $args{'message'};
+ close($fh);
+
+ if ( -f $temp_file ) {
+ $parser->ParseMIMEEntityFromFile($temp_file);
+ File::Temp::unlink0( $fh, $temp_file );
+ if ($parser->Entity) {
+ delete $args{'message'};
+ }
+ }
+
+ }
+
+ #If for some reason we weren't able to parse the message using a temp file
+ # try it with a scalar
+ if ($args{'message'}) {
+ $parser->ParseMIMEEntityFromScalar($args{'message'});
+
+ }
+
+ if (!$parser->Entity()) {
+ MailError(
+ To => $RT::OwnerEmail,
+ Subject => "RT Bounce: Unparseable message",
+ Explanation => "RT couldn't process the message below",
+ Attach => $args{'message'}
+ );
+
+ return(0,"Failed to parse this message. Something is likely badly wrong with the message");
+ }
my $Message = $parser->Entity();
- my $head = $Message->head;
+ my $head = $Message->head;
my ( $CurrentUser, $AuthStat, $status, $error );
+ # Initalize AuthStat so comparisons work correctly
+ $AuthStat = -9999999;
+
my $ErrorsTo = ParseErrorsToAddressFromHead($head);
my $MessageId = $head->get('Message-Id')
@@ -400,37 +473,31 @@ sub Gateway {
my $Subject = $head->get('Subject') || '';
chomp $Subject;
-
$args{'ticket'} ||= $parser->ParseTicketId($Subject);
my $SystemTicket;
- if ($args{'ticket'} ) {
+ if ( $args{'ticket'} ) {
$SystemTicket = RT::Ticket->new($RT::SystemUser);
- $SystemTicket->Load($args{'ticket'});
+ $SystemTicket->Load( $args{'ticket'} );
}
#Set up a queue object
my $SystemQueueObj = RT::Queue->new($RT::SystemUser);
$SystemQueueObj->Load( $args{'queue'} );
-
# We can safely have no queue of we have a known-good ticket
unless ( $args{'ticket'} || $SystemQueueObj->id ) {
- MailError(
- To => $RT::OwnerEmail,
- Subject => "RT Bounce: $Subject",
- Explanation => "RT couldn't find the queue: " . $args{'queue'},
- MIMEObj => $Message );
- return ( 0, "RT couldn't find the queue: " . $args{'queue'}, undef );
+ return ( -75, "RT couldn't find the queue: " . $args{'queue'}, undef );
}
# Authentication Level
- # -1 - Get out. this user has been explicitly declined
+ # -1 - Get out. this user has been explicitly declined
# 0 - User may not do anything (Not used at the moment)
# 1 - Normal user
# 2 - User is allowed to specify status updates etc. a la enhanced-mailgate
- push @RT::MailPlugins, "Auth::MailFrom" unless @RT::MailPlugins;
+ push @RT::MailPlugins, "Auth::MailFrom" unless @RT::MailPlugins;
+
# Since this needs loading, no matter what
for (@RT::MailPlugins) {
@@ -453,35 +520,59 @@ sub Gateway {
}
}
- ( $CurrentUser, $NewAuthStat ) = $Code->( Message => $Message,
- CurrentUser => $CurrentUser,
- AuthLevel => $AuthStat,
- Action => $args{'action'},
- Ticket => $SystemTicket,
- Queue => $SystemQueueObj );
+ ( $CurrentUser, $NewAuthStat ) = $Code->(
+ Message => $Message,
+ CurrentUser => $CurrentUser,
+ AuthLevel => $AuthStat,
+ Action => $args{'action'},
+ Ticket => $SystemTicket,
+ Queue => $SystemQueueObj
+ );
+
+ # If a module returns a "-1" then we discard the ticket, so.
+ $AuthStat = -1 if $NewAuthStat == -1;
# You get the highest level of authentication you were assigned.
- last if $AuthStat == -1;
$AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
+ last if $AuthStat == -1;
}
# {{{ If authentication fails and no new user was created, get out.
if ( !$CurrentUser or !$CurrentUser->Id or $AuthStat == -1 ) {
# If the plugins refused to create one, they lose.
- MailError(
- Subject => "Could not load a valid user",
- Explanation => <<EOT,
+ unless ( $AuthStat == -1 ) {
+
+ # Notify the RT Admin of the failure.
+ # XXX Should this be configurable?
+ MailError(
+ To => $RT::OwnerEmail,
+ Subject => "Could not load a valid user",
+ Explanation => <<EOT,
RT could not load a valid user, and RT's configuration does not allow
-for the creation of a new user for your email.
+for the creation of a new user for this email ($ErrorsTo).
-Your RT administrator needs to grant 'Everyone' the right 'CreateTicket'
-for this queue.
+You might need to grant 'Everyone' the right 'CreateTicket' for the
+queue @{[$args{'queue'}]}.
EOT
- MIMEObj => $Message,
- LogLevel => 'error' )
- unless $AuthStat == -1;
+ MIMEObj => $Message,
+ LogLevel => 'error'
+ );
+
+ # Also notify the requestor that his request has been dropped.
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Could not load a valid user",
+ Explanation => <<EOT,
+RT could not load a valid user, and RT's configuration does not allow
+for the creation of a new user for your email.
+
+EOT
+ MIMEObj => $Message,
+ LogLevel => 'error'
+ );
+ }
return ( 0, "Could not load a valid user", undef );
}
@@ -508,10 +599,11 @@ EOT
# {{{ Drop it if it's disallowed
if ( $AuthStat == 0 ) {
MailError(
- To => $ErrorsTo,
- Subject => "Permission Denied",
- Explanation => "You do not have permission to communicate with RT",
- MIMEObj => $Message );
+ To => $ErrorsTo,
+ Subject => "Permission Denied",
+ Explanation => "You do not have permission to communicate with RT",
+ MIMEObj => $Message
+ );
}
# }}}
@@ -523,10 +615,12 @@ EOT
#Should we mail it to RTOwner?
if ($RT::LoopsToRTOwner) {
- MailError( To => $RT::OwnerEmail,
- Subject => "RT Bounce: $Subject",
- Explanation => "RT thinks this message may be a bounce",
- MIMEObj => $Message );
+ MailError(
+ To => $RT::OwnerEmail,
+ Subject => "RT Bounce: $Subject",
+ Explanation => "RT thinks this message may be a bounce",
+ MIMEObj => $Message
+ );
#Do we actually want to store it?
return ( 0, "Message Bounced", undef ) unless ($RT::StoreLoops);
@@ -538,8 +632,10 @@ EOT
# {{{ Squelch replies if necessary
# Don't let the user stuff the RT-Squelch-Replies-To header.
if ( $head->get('RT-Squelch-Replies-To') ) {
- $head->add( 'RT-Relocated-Squelch-Replies-To',
- $head->get('RT-Squelch-Replies-To') );
+ $head->add(
+ 'RT-Relocated-Squelch-Replies-To',
+ $head->get('RT-Squelch-Replies-To')
+ );
$head->delete('RT-Squelch-Replies-To');
}
@@ -564,22 +660,27 @@ EOT
my @Requestors = ( $CurrentUser->id );
if ($RT::ParseNewMessageForTicketCcs) {
- @Cc = ParseCcAddressesFromHead( Head => $head,
- CurrentUser => $CurrentUser,
- QueueObj => $SystemQueueObj );
+ @Cc = ParseCcAddressesFromHead(
+ Head => $head,
+ CurrentUser => $CurrentUser,
+ QueueObj => $SystemQueueObj
+ );
}
my ( $id, $Transaction, $ErrStr ) = $Ticket->Create(
- Queue => $SystemQueueObj->Id,
- Subject => $Subject,
- Requestor => \@Requestors,
- Cc => \@Cc,
- MIMEObj => $Message );
+ Queue => $SystemQueueObj->Id,
+ Subject => $Subject,
+ Requestor => \@Requestors,
+ Cc => \@Cc,
+ MIMEObj => $Message
+ );
if ( $id == 0 ) {
- MailError( To => $ErrorsTo,
- Subject => "Ticket creation failed",
- Explanation => $ErrStr,
- MIMEObj => $Message );
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Ticket creation failed",
+ Explanation => $ErrStr,
+ MIMEObj => $Message
+ );
$RT::Logger->error("Create failed: $id / $Transaction / $ErrStr ");
return ( 0, "Ticket creation failed", $Ticket );
}
@@ -591,15 +692,17 @@ EOT
# If the action is comment, add a comment.
elsif ( $args{'action'} =~ /^(comment|correspond)$/i ) {
- $Ticket->Load($args{'ticket'});
+ $Ticket->Load( $args{'ticket'} );
unless ( $Ticket->Id ) {
- my $message = "Could not find a ticket with id ".$args{'ticket'};
- MailError( To => $ErrorsTo,
- Subject => "Message not recorded",
- Explanation => $message,
- MIMEObj => $Message );
-
- return ( 0, $message);
+ my $message = "Could not find a ticket with id " . $args{'ticket'};
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Message not recorded",
+ Explanation => $message,
+ MIMEObj => $Message
+ );
+
+ return ( 0, $message );
}
my ( $status, $msg );
@@ -612,10 +715,12 @@ EOT
unless ($status) {
#Warn the sender that we couldn't actually submit the comment.
- MailError( To => $ErrorsTo,
- Subject => "Message not recorded",
- Explanation => $msg,
- MIMEObj => $Message );
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Message not recorded",
+ Explanation => $msg,
+ MIMEObj => $Message
+ );
return ( 0, "Message not recorded", $Ticket );
}
}
@@ -623,21 +728,28 @@ EOT
else {
#Return mail to the sender with an error
- MailError( To => $ErrorsTo,
- Subject => "RT Configuration error",
- Explanation => "'"
- . $args{'action'}
- . "' not a recognized action."
- . " Your RT administrator has misconfigured "
- . "the mail aliases which invoke RT",
- MIMEObj => $Message );
+ MailError(
+ To => $ErrorsTo,
+ Subject => "RT Configuration error",
+ Explanation => "'"
+ . $args{'action'}
+ . "' not a recognized action."
+ . " Your RT administrator has misconfigured "
+ . "the mail aliases which invoke RT",
+ MIMEObj => $Message
+ );
$RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
- return ( 0, "Configuration error: " . $args{'action'} . " not a recognized action", $Ticket );
+ return (
+ -75,
+ "Configuration error: "
+ . $args{'action'}
+ . " not a recognized action",
+ $Ticket
+ );
}
-
-return ( 1, "Success", $Ticket );
+ return ( 1, "Success", $Ticket );
}
eval "require RT::Interface::Email_Vendor";
diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm
index 5097f54..8d66239 100644
--- a/rt/lib/RT/Interface/Web.pm
+++ b/rt/lib/RT/Interface/Web.pm
@@ -68,6 +68,7 @@ sub NewApacheHandler {
default_escape_flags => 'h',
allow_globals => [qw(%session)],
data_dir => "$RT::MasonDataDir",
+ autoflush => 1,
@_
);
@@ -98,7 +99,8 @@ sub NewCGIHandler {
],
data_dir => "$RT::MasonDataDir",
default_escape_flags => 'h',
- allow_globals => [qw(%session)]
+ allow_globals => [qw(%session)],
+ autoflush => 1,
);
@@ -137,6 +139,60 @@ sub EscapeUTF8 {
# }}}
+# {{{ WebCanonicalizeInfo
+
+=head2 WebCanonicalizeInfo();
+
+Different web servers set different environmental varibles. This
+function must return something suitable for REMOTE_USER. By default,
+just downcase $ENV{'REMOTE_USER'}
+
+=cut
+
+sub WebCanonicalizeInfo {
+ my $user;
+
+ if ( defined $ENV{'REMOTE_USER'} ) {
+ $user = lc ( $ENV{'REMOTE_USER'} ) if( length($ENV{'REMOTE_USER'}) );
+ }
+
+ return $user;
+}
+
+# }}}
+
+# {{{ WebExternalAutoInfo
+
+=head2 WebExternalAutoInfo($user);
+
+Returns a hash of user attributes, used when WebExternalAuto is set.
+
+=cut
+
+sub WebExternalAutoInfo {
+ my $user = shift;
+
+ my %user_info;
+
+ $user_info{'Privileged'} = 1;
+
+ if ($^O !~ /^(?:riscos|MacOS|MSWin32|dos|os2)$/) {
+ # Populate fields with information from Unix /etc/passwd
+
+ my ($comments, $realname) = (getpwnam($user))[5, 6];
+ $user_info{'Comments'} = $comments if defined $comments;
+ $user_info{'RealName'} = $realname if defined $realname;
+ }
+ elsif ($^O eq 'MSWin32' and eval 'use Net::AdminMisc; 1') {
+ # Populate fields with information from NT domain controller
+ }
+
+ # and return the wad of stuff
+ return {%user_info};
+}
+
+# }}}
+
package HTML::Mason::Commands;
use strict;
@@ -160,10 +216,13 @@ sub loc {
UNIVERSAL::can($session{'CurrentUser'}, 'loc')){
return($session{'CurrentUser'}->loc(@_));
}
- else {
- my $u = RT::CurrentUser->new($RT::SystemUser);
+ elsif ( my $u = eval { RT::CurrentUser->new($RT::SystemUser->Id) } ) {
return ($u->loc(@_));
}
+ else {
+ # pathetic case -- SystemUser is gone.
+ return $_[0];
+ }
}
# }}}
@@ -189,7 +248,7 @@ sub loc_fuzzy {
return($session{'CurrentUser'}->loc_fuzzy($msg));
}
else {
- my $u = RT::CurrentUser->new($RT::SystemUser);
+ my $u = RT::CurrentUser->new($RT::SystemUser->Id);
return ($u->loc_fuzzy($msg));
}
}
@@ -365,7 +424,8 @@ sub ProcessUpdateMessage {
);
#Make the update content have no 'weird' newlines in it
- if ( $args{ARGSRef}->{'UpdateContent'} ) {
+ if ( $args{ARGSRef}->{'UpdateContent'} ||
+ $args{ARGSRef}->{'UpdateAttachments'}) {
if (
$args{ARGSRef}->{'UpdateSubject'} eq $args{'TicketObj'}->Subject() )
@@ -433,7 +493,8 @@ sub MakeMIMEEntity {
Cc => undef,
Body => undef,
AttachmentFieldName => undef,
- map Encode::encode_utf8($_), @_,
+# map Encode::encode_utf8($_), @_,
+ @_,
);
#Make the update content have no 'weird' newlines in it
@@ -449,6 +510,7 @@ sub MakeMIMEEntity {
Subject => $args{'Subject'} || "",
From => $args{'From'},
Cc => $args{'Cc'},
+ Charset => 'utf8',
Data => [ $args{'Body'} ]
);
}
@@ -463,7 +525,14 @@ sub MakeMIMEEntity {
#foreach my $filehandle (@filenames) {
- my ( $fh, $temp_file ) = tempfile();
+ my ( $fh, $temp_file );
+ for ( 1 .. 10 ) {
+ # on NFS and NTFS, it is possible that tempfile() conflicts
+ # with other processes, causing a race condition. we try to
+ # accommodate this by pausing and retrying.
+ last if ($fh, $temp_file) = eval { tempfile() };
+ sleep 1;
+ }
binmode $fh; #thank you, windows
my ($buffer);
@@ -481,7 +550,7 @@ sub MakeMIMEEntity {
$Message->attach(
Path => $temp_file,
- Filename => $filename,
+ Filename => Encode::decode_utf8($filename),
Type => $uploadinfo->{'Content-Type'},
);
close($fh);
@@ -594,13 +663,13 @@ sub ProcessSearchQuery {
# }}}
# {{{ Limit requestor email
+ if ( $args{ARGS}->{'ValueOfWatcherRole'} ne '' ) {
+ $session{'tickets'}->LimitWatcher(
+ TYPE => $args{ARGS}->{'WatcherRole'},
+ VALUE => $args{ARGS}->{'ValueOfWatcherRole'},
+ OPERATOR => $args{ARGS}->{'WatcherRoleOp'},
- if ( $args{ARGS}->{'ValueOfRequestor'} ne '' ) {
- my $alias = $session{'tickets'}->LimitRequestor(
- VALUE => $args{ARGS}->{'ValueOfRequestor'},
- OPERATOR => $args{ARGS}->{'RequestorOp'},
);
-
}
# }}}
@@ -780,17 +849,13 @@ sub ProcessACLChanges {
my $obj;
- if ($object_type eq 'RT::Queue') {
- $obj = RT::Queue->new($session{'CurrentUser'});
- $obj->Load($object_id);
- } elsif ($object_type eq 'RT::Group') {
- $obj = RT::Group->new($session{'CurrentUser'});
- $obj->Load($object_id);
-
- } elsif ($object_type eq 'RT::System') {
+ if ($object_type eq 'RT::System') {
$obj = $RT::System;
+ } elsif ($RT::ACE::OBJECT_TYPES{$object_type}) {
+ $obj = $object_type->new($session{'CurrentUser'});
+ $obj->Load($object_id);
} else {
- push (@results, loc("System Error").
+ push (@results, loc("System Error"). ': '.
loc("Rights could not be granted for [_1]", $object_type));
next;
}
@@ -813,17 +878,14 @@ sub ProcessACLChanges {
next unless ($right);
my $obj;
- if ($object_type eq 'RT::Queue') {
- $obj = RT::Queue->new($session{'CurrentUser'});
- $obj->Load($object_id);
- } elsif ($object_type eq 'RT::Group') {
- $obj = RT::Group->new($session{'CurrentUser'});
- $obj->Load($object_id);
-
- } elsif ($object_type eq 'RT::System') {
+ if ($object_type eq 'RT::System') {
$obj = $RT::System;
+ } elsif ($RT::ACE::OBJECT_TYPES{$object_type}) {
+ $obj = $object_type->new($session{'CurrentUser'});
+ $obj->Load($object_id);
} else {
- push (@results, loc("System Error").
+ die;
+ push (@results, loc("System Error"). ': '.
loc("Rights could not be revoked for [_1]", $object_type));
next;
}
@@ -953,6 +1015,17 @@ sub ProcessCustomFieldUpdates {
my ( $err, $msg ) = $Object->DeleteValue($id);
push ( @results, $msg );
}
+
+ my $vals = $Object->Values();
+ while (my $cfv = $vals->Next()) {
+ if (my $so = $ARGSRef->{ 'CustomField-' . $Object->Id . '-SortOrder' . $cfv->Id }) {
+ if ($cfv->SortOrder != $so) {
+ my ( $err, $msg ) = $cfv->SetSortOrder($so);
+ push ( @results, $msg );
+ }
+ }
+ }
+
return (@results);
}
@@ -1050,8 +1123,11 @@ sub ProcessTicketCustomFieldUpdates {
# For each of those tickets
foreach my $tick ( keys %custom_fields_to_mod ) {
- my $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
- $Ticket->Load($tick);
+ my $Ticket = $args{'TicketObj'};
+ if (!$Ticket or $Ticket->id != $tick) {
+ $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
+ $Ticket->Load($tick);
+ }
# For each custom field
foreach my $cf ( keys %{ $custom_fields_to_mod{$tick} } ) {
@@ -1074,10 +1150,10 @@ sub ProcessTicketCustomFieldUpdates {
my @values =
( ref( $ARGSRef->{$arg} ) eq 'ARRAY' )
? @{ $ARGSRef->{$arg} }
- : ( $ARGSRef->{$arg} );
+ : split /\n/, $ARGSRef->{$arg} ;
if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) {
foreach my $value (@values) {
- next unless ($value);
+ next unless length($value);
my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
Field => $cf,
Value => $value
@@ -1087,7 +1163,7 @@ sub ProcessTicketCustomFieldUpdates {
}
elsif ( $arg =~ /-DeleteValues$/ ) {
foreach my $value (@values) {
- next unless ($value);
+ next unless length($value);
my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue(
Field => $cf,
Value => $value
@@ -1100,7 +1176,7 @@ sub ProcessTicketCustomFieldUpdates {
my %values_hash;
foreach my $value (@values) {
- next unless ($value);
+ next unless length($value);
# build up a hash of values that the new set has
$values_hash{$value} = 1;
diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm
index 6962221..7a86906 100755
--- a/rt/lib/RT/Record.pm
+++ b/rt/lib/RT/Record.pm
@@ -211,7 +211,10 @@ sub LoadByCols {
$newhash{$key} = $hash{$key};
}
else {
- $newhash{ "lower(" . $key . ")" } = lc( $hash{$key} );
+ my ($op, $val);
+ ($key, $op, $val) = $self->_Handle->_MakeClauseCaseInsensitive($key, '=', $hash{$key});
+ $newhash{$key}->{operator} = $op;
+ $newhash{$key}->{value} = $val;
}
}