summaryrefslogtreecommitdiff
path: root/rt/sbin
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2014-02-25 18:34:25 -0800
committerIvan Kohler <ivan@freeside.biz>2014-02-25 18:34:25 -0800
commit45d35d5739d05e602bc317739485693e0e9ff0b5 (patch)
tree61801368d96662baff145d3271fd887ca104391c /rt/sbin
parent662be3ece2ef8c7f05fcbfaa699d80a6a73ca110 (diff)
RT 4.0.19
Diffstat (limited to 'rt/sbin')
-rw-r--r--rt/sbin/rt-attributes-viewer.in2
-rw-r--r--rt/sbin/rt-clean-sessions.in2
-rw-r--r--rt/sbin/rt-dump-metadata.in191
-rw-r--r--rt/sbin/rt-email-dashboards.in2
-rw-r--r--rt/sbin/rt-email-digest.in8
-rwxr-xr-xrt/sbin/rt-email-group-admin.in36
-rwxr-xr-xrt/sbin/rt-fulltext-indexer465
-rw-r--r--rt/sbin/rt-fulltext-indexer.in6
-rwxr-xr-xrt/sbin/rt-message-catalog2
-rw-r--r--rt/sbin/rt-preferences-viewer.in2
-rw-r--r--rt/sbin/rt-server.fcgi.in4
-rw-r--r--rt/sbin/rt-server.in4
-rwxr-xr-xrt/sbin/rt-session-viewer121
-rw-r--r--rt/sbin/rt-session-viewer.in2
-rw-r--r--rt/sbin/rt-setup-database.in44
-rwxr-xr-xrt/sbin/rt-setup-fulltext-index714
-rw-r--r--rt/sbin/rt-setup-fulltext-index.in2
-rwxr-xr-xrt/sbin/rt-shredder.in8
-rw-r--r--rt/sbin/rt-test-dependencies.in3
-rw-r--r--rt/sbin/rt-validate-aliases.in2
-rw-r--r--rt/sbin/rt-validator.in2
-rwxr-xr-xrt/sbin/standalone_httpd284
-rw-r--r--rt/sbin/standalone_httpd.in4
23 files changed, 236 insertions, 1674 deletions
diff --git a/rt/sbin/rt-attributes-viewer.in b/rt/sbin/rt-attributes-viewer.in
index 59eb423..31bae00 100644
--- a/rt/sbin/rt-attributes-viewer.in
+++ b/rt/sbin/rt-attributes-viewer.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-clean-sessions.in b/rt/sbin/rt-clean-sessions.in
index 1d6e1cf..77730fe 100644
--- a/rt/sbin/rt-clean-sessions.in
+++ b/rt/sbin/rt-clean-sessions.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-dump-metadata.in b/rt/sbin/rt-dump-metadata.in
index 20c2853..5e0e5c3 100644
--- a/rt/sbin/rt-dump-metadata.in
+++ b/rt/sbin/rt-dump-metadata.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -79,7 +79,11 @@ BEGIN {
use Getopt::Long;
my %opt;
-GetOptions( \%opt, "help|h" );
+GetOptions( \%opt, "help|h",
+ "limit-to-privileged|l",
+ "skip-disabled|s",
+ "all|a",
+);
if ( $opt{help} ) {
require Pod::Usage;
@@ -93,8 +97,6 @@ require XML::Simple;
RT::LoadConfig();
RT::Init();
-my $LocalOnly = @ARGV ? shift(@ARGV) : 1;
-
my %RV;
my %Ignore = (
All => [
@@ -117,8 +119,15 @@ my @classes = qw(
foreach my $class (@classes) {
require "RT/$class.pm";
my $objects = "RT::$class"->new( RT->SystemUser );
- $objects->{find_disabled_rows} = 1;
+ $objects->{find_disabled_rows} = 1 unless $opt{'skip-disabled'};
$objects->UnLimit;
+ $objects->LimitToPrivileged if $class eq 'Users'
+ && $opt{'limit-to-privileged'};
+ $objects->Limit(
+ FIELD => 'Domain',
+ OPERATOR => '=',
+ VALUE => 'UserDefined'
+ ) if $class eq 'Groups';
if ( $class eq 'CustomFields' ) {
$objects->OrderByCols(
@@ -130,7 +139,7 @@ foreach my $class (@classes) {
$objects->OrderBy( FIELD => 'Id' );
}
- if ($LocalOnly) {
+ unless ($opt{all}) {
next if $class eq 'ACL'; # XXX - would go into infinite loop - XXX
$objects->Limit(
FIELD => 'LastUpdatedBy',
@@ -142,14 +151,10 @@ foreach my $class (@classes) {
OPERATOR => '!=',
VALUE => $SystemUserId
) if $class eq 'Users';
- $objects->Limit(
- FIELD => 'Domain',
- OPERATOR => '=',
- VALUE => 'UserDefined'
- ) if $class eq 'Groups';
}
my %fields;
+OBJECT:
while ( my $obj = $objects->Next ) {
next
if $obj->can('LastUpdatedBy')
@@ -163,36 +168,116 @@ foreach my $class (@classes) {
my $rv;
- # next if $obj-> # skip default names
- foreach my $field ( sort keys %fields ) {
- my $value = $obj->__Value($field);
- $rv->{$field} = $value if ( defined($value) && length($value) );
- }
- delete $rv->{Disabled} unless $rv->{Disabled};
-
- foreach my $record ( map { /ACL/ ? 'ACE' : substr( $_, 0, -1 ) }
- @classes )
- {
- foreach my $key ( map "$record$_", ( '', 'Id' ) ) {
- next unless exists $rv->{$key};
- my $id = $rv->{$key} or next;
- my $obj = "RT::$record"->new( RT->SystemUser );
- $obj->LoadByCols( Id => $id ) or next;
- $rv->{$key} = $obj->__Value('Name') || 0;
+ if ( $class ne 'ACL' ) {
+ # next if $obj-> # skip default names
+ foreach my $field ( sort keys %fields ) {
+ my $value = $obj->__Value($field);
+ $rv->{$field} = $value if ( defined($value) && length($value) );
+ }
+ delete $rv->{Disabled} unless $rv->{Disabled};
+
+ foreach my $record ( map { /ACL/ ? 'ACE' : substr( $_, 0, -1 ) }
+ @classes )
+ {
+ foreach my $key ( map "$record$_", ( '', 'Id' ) ) {
+ next unless exists $rv->{$key};
+ my $id = $rv->{$key} or next;
+ my $obj = "RT::$record"->new( RT->SystemUser );
+ $obj->LoadByCols( Id => $id ) or next;
+ $rv->{$key} = $obj->__Value('Name') || 0;
+ }
+ }
+
+ if ( $class eq 'Users' and defined $obj->Privileged ) {
+ $rv->{Privileged} = int( $obj->Privileged );
+ } elsif ( $class eq 'CustomFields' ) {
+ my $values = $obj->Values;
+ while ( my $value = $values->Next ) {
+ push @{ $rv->{Values} }, {
+ map { ( $_ => $value->__Value($_) ) }
+ qw(
+ Name Description SortOrder
+ ),
+ };
+ }
+ if ( $obj->LookupType eq 'RT::Queue-RT::Ticket' ) {
+ # XXX-TODO: unused CF's turn into global CF when importing
+ # as the sub InsertData in RT::Handle creates a global CF
+ # when no queue is specified.
+ $rv->{Queue} = [];
+ my $applies = $obj->AppliedTo;
+ while ( my $queue = $applies->Next ) {
+ push @{ $rv->{Queue} }, $queue->Name;
+ }
+ }
}
}
+ else {
+ # 1) pick the right
+ $rv->{Right} = $obj->RightName;
+
+ # 2) Pick a level: Granted on Queue, CF, CF+Queue, or Globally?
+ for ( $obj->ObjectType ) {
+ if ( /^RT::Queue$/ ) {
+ next OBJECT if $opt{'skip-disabled'} && $obj->Object->Disabled;
+ $rv->{Queue} = $obj->Object->Name;
+ }
+ elsif ( /^RT::CustomField$/ ) {
+ next OBJECT if $opt{'skip-disabled'} && $obj->Object->Disabled;
+ $rv->{CF} = $obj->Object->Name;
+ }
+ elsif ( /^RT::Group$/ ) {
+ # No support for RT::Group ACLs in RT::Handle yet.
+ next OBJECT;
+ }
+ elsif ( /^RT::System$/ ) {
+ # skip setting anything on $rv;
+ # "Specifying none of the above will get you a global right."
+ }
+ }
- if ( $class eq 'Users' and defined $obj->Privileged ) {
- $rv->{Privileged} = int( $obj->Privileged );
- } elsif ( $class eq 'CustomFields' ) {
- my $values = $obj->Values;
- while ( my $value = $values->Next ) {
- push @{ $rv->{Values} }, {
- map { ( $_ => $value->__Value($_) ) }
- qw(
- Name Description SortOrder
- ),
- };
+ # 3) Pick a Principal; User or Group or Role
+ if ( $obj->PrincipalType eq 'Group' ) {
+ next OBJECT if $opt{'skip-disabled'} && $obj->PrincipalObj->Disabled;
+ my $group = $obj->PrincipalObj->Object;
+ for ( $group->Domain ) {
+ # An internal user group
+ if ( /^SystemInternal$/ ) {
+ $rv->{GroupDomain} = $group->Domain;
+ $rv->{GroupType} = $group->Type;
+ }
+ # An individual user
+ elsif ( /^ACLEquivalence$/ ) {
+ my $member = $group->MembersObj->Next->MemberObj;
+ next OBJECT if $opt{'skip-disabled'} && $member->Disabled;
+ $rv->{UserId} = $member->Object->Name;
+ }
+ # A group you created
+ elsif ( /^UserDefined$/ ) {
+ $rv->{GroupDomain} = 'UserDefined';
+ $rv->{GroupId} = $group->Name;
+ }
+ }
+ } else {
+ $rv->{GroupType} = $obj->PrincipalType;
+ # A system-level role
+ if ( $obj->ObjectType eq 'RT::System' ) {
+ $rv->{GroupDomain} = 'RT::System-Role';
+ }
+ # A queue-level role
+ elsif ( $obj->ObjectType eq 'RT::Queue' ) {
+ $rv->{GroupDomain} = 'RT::Queue-Role';
+ }
+ }
+ if ( $obj->LookupType eq 'RT::Queue-RT::Ticket' ) {
+ # XXX-TODO: unused CF's turn into global CF when importing
+ # as the sub InsertData in RT::Handle creates a global CF
+ # when no queue is specified.
+ $rv->{Queue} = [];
+ my $applies = $obj->AppliedTo;
+ while ( my $queue = $applies->Next ) {
+ push @{ $rv->{Queue} }, $queue->Name;
+ }
}
}
@@ -200,6 +285,9 @@ foreach my $class (@classes) {
my $attributes = $obj->Attributes;
while ( my $attribute = $attributes->Next ) {
my $content = $attribute->Content;
+ if ( $class eq 'Users' and $attribute->Name eq 'Bookmarks' ) {
+ next;
+ }
$rv->{Attributes}{ $attribute->Name } = $content
if length($content);
}
@@ -232,7 +320,7 @@ rt-dump-metadata - dump configuration metadata from an RT database
=head1 SYNOPSIS
- rt-dump-metdata [ 0 ]
+ rt-dump-metdata [--all]
=head1 DESCRIPTION
@@ -242,11 +330,28 @@ C<rt-setup-database>. To dump and load a full RT database, you should generally
use the native database tools instead, as well as performing any necessary
steps from UPGRADING.
-When run without arguments, the metadata dump will only include 'local'
+This is NOT a tool for backing up an RT database. See also
+L<docs/initialdata> for more straightforward means of importing data.
+
+=head1 OPTIONS
+
+=over
+
+=item C<--all> or C<-a>
+
+When run with C<--all>, the dump will include all configuration
+metadata; otherwise, the metadata dump will only include 'local'
configuration changes, i.e. those done manually in the web interface.
-When run with the argument '0', the dump will include all configuration
-metadata.
+=item C<--limit-to-privileged> or C<-l>
+
+Causes the dumper to only dump privileged users.
+
+=item C<--skip-disabled> or C<-s>
+
+Ignores disabled rows in the database.
+
+=back
-This is NOT a tool for backing up an RT database.
+=cut
diff --git a/rt/sbin/rt-email-dashboards.in b/rt/sbin/rt-email-dashboards.in
index f77ae61..0fcb126 100644
--- a/rt/sbin/rt-email-dashboards.in
+++ b/rt/sbin/rt-email-dashboards.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-email-digest.in b/rt/sbin/rt-email-digest.in
index 68f0b4c..a535e36 100644
--- a/rt/sbin/rt-email-digest.in
+++ b/rt/sbin/rt-email-digest.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -95,6 +95,7 @@ sub usage {
print "\t-p, --print\t"
. loc("Print the resulting digest messages to STDOUT; don't mail them. Do not mark them as sent")
. "\n";
+ print "\t-v, --verbose\t" . loc("Give output even on messages successfully sent") . "\n";
print "\t-h, --help\t" . loc("Print this message") . "\n";
if ( $error eq 'help' ) {
@@ -105,10 +106,11 @@ sub usage {
}
}
-my ( $frequency, $print, $help ) = ( '', '', '' );
+my ( $frequency, $print, $verbose, $help ) = ( '', '', '', '' );
GetOptions(
'mode=s' => \$frequency,
'print' => \$print,
+ 'verbose' => \$verbose,
'help' => \$help,
);
@@ -134,7 +136,7 @@ sub run {
my ( $contents_list, $contents_body ) = build_digest_for_user( $user, $all_digest->{$user} );
# Now we have a content head and a content body. We can send a message.
if ( send_digest( $user, $contents_list, $contents_body ) ) {
- print "Sent message to $user\n";
+ print "Sent message to $user\n" if $verbose;
mark_transactions_sent( $frequency, $user, values %{$sent_transactions->{$user}} ) unless ($print);
} else {
print "Failed to send message to $user\n";
diff --git a/rt/sbin/rt-email-group-admin.in b/rt/sbin/rt-email-group-admin.in
index f626626..3306a38 100755
--- a/rt/sbin/rt-email-group-admin.in
+++ b/rt/sbin/rt-email-group-admin.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -245,10 +245,11 @@ sub _list {
return;
}
-=head2 create NAME [--comment] [--group GNAME] [--user UNAME]
+=head2 create NAME [--comment] [--group GNAME] [--user NAME-OR-EMAIL]
Creates new action with NAME and adds users and/or groups to its
-recipient list. Would be notify as comment if --comment specified.
+recipient list. Would be notify as comment if --comment specified. The
+user, if specified, will be autocreated if necessary.
=cut
@@ -295,8 +296,9 @@ sub __create_empty {
sub _check_groups
{
- return grep { $_ ? 1: do { print STDERR "Group '$_' skipped, doesn't exist\n"; 0; } }
- map { __check_group($_) } @_;
+ return map {$_->[1]}
+ grep { $_->[1] ? 1: do { print STDERR "Group '$_->[0]' skipped, doesn't exist\n"; 0; } }
+ map { [$_, __check_group($_)] } @_;
}
sub __check_group
@@ -310,8 +312,9 @@ sub __check_group
sub _check_users
{
- return grep { $_ ? 1: do { print STDERR "User '$_' skipped, doesn't exist\n"; 0; } }
- map { __check_user($_) } @_;
+ return map {$_->[1]}
+ grep { $_->[1] ? 1: do { print STDERR "User '$_->[0]' skipped, doesn't exist and couldn't autocreate\n"; 0; } }
+ map { [$_, __check_user($_)] } @_;
}
sub __check_user
@@ -320,12 +323,27 @@ sub __check_user
require RT::User;
my $obj = RT::User->new( RT->SystemUser );
$obj->Load( $instance );
+ $obj->LoadByEmail( $instance )
+ if not $obj->id and $instance =~ /@/;
+
+ unless ($obj->id) {
+ my ($ok, $msg) = $obj->Create(
+ Name => $instance,
+ EmailAddress => $instance,
+ Privileged => 0,
+ Comments => 'Autocreated when added to notify action via rt-email-group-admin',
+ );
+ print STDERR "Autocreate of user '$instance' failed: $msg\n"
+ unless $ok;
+ }
+
return $obj->id ? $obj : undef;
}
-=head2 add NAME [--group GNAME] [--user UNAME]
+=head2 add NAME [--group GNAME] [--user NAME-OR-EMAIL]
-Adds groups and/or users to recipients of the action NAME.
+Adds groups and/or users to recipients of the action NAME. The user, if
+specified, will be autocreated if necessary.
=cut
diff --git a/rt/sbin/rt-fulltext-indexer b/rt/sbin/rt-fulltext-indexer
deleted file mode 100755
index 8ac0e9c..0000000
--- a/rt/sbin/rt-fulltext-indexer
+++ /dev/null
@@ -1,465 +0,0 @@
-#!/usr/bin/perl
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
-# <sales@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 strict;
-use warnings;
-no warnings 'once';
-
-# fix lib paths, some may be relative
-BEGIN {
- require File::Spec;
- my @libs = ("/opt/rt3/lib", "/opt/rt3/local/lib");
- my $bin_path;
-
- for my $lib (@libs) {
- unless ( File::Spec->file_name_is_absolute($lib) ) {
- unless ($bin_path) {
- if ( File::Spec->file_name_is_absolute(__FILE__) ) {
- $bin_path = ( File::Spec->splitpath(__FILE__) )[1];
- }
- else {
- require FindBin;
- no warnings "once";
- $bin_path = $FindBin::Bin;
- }
- }
- $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib );
- }
- unshift @INC, $lib;
- }
-}
-
-BEGIN {
- use RT;
- RT::LoadConfig();
- RT::Init();
-};
-use RT::Interface::CLI ();
-
-my %OPT = (
- help => 0,
- debug => 0,
-);
-my @OPT_LIST = qw(help|h! debug!);
-
-my $db_type = RT->Config->Get('DatabaseType');
-if ( $db_type eq 'Pg' ) {
- %OPT = (
- %OPT,
- limit => 0,
- all => 0,
- );
- push @OPT_LIST, 'limit=i', 'all!';
-}
-elsif ( $db_type eq 'mysql' ) {
- %OPT = (
- %OPT,
- limit => 0,
- all => 0,
- xmlpipe2 => 0,
- );
- push @OPT_LIST, 'limit=i', 'all!', 'xmlpipe2!';
-}
-elsif ( $db_type eq 'Oracle' ) {
- %OPT = (
- %OPT,
- memory => '2M',
- );
- push @OPT_LIST, qw(memory=s);
-}
-
-use Getopt::Long qw(GetOptions);
-GetOptions( \%OPT, @OPT_LIST );
-
-if ( $OPT{'help'} ) {
- RT::Interface::CLI->ShowHelp(
- Sections => 'NAME|DESCRIPTION|'. uc($db_type),
- );
-}
-
-my $fts_config = RT->Config->Get('FullTextSearch') || {};
-unless ( $fts_config->{'Enable'} ) {
- print STDERR <<EOT;
-
-Full text search is disabled in your RT configuration. Run
-/opt/rt3/sbin/rt-setup-fulltext-index to configure and enable it.
-
-EOT
- exit 1;
-}
-unless ( $fts_config->{'Indexed'} ) {
- print STDERR <<EOT;
-
-Full text search is enabled in your RT configuration, but not with any
-full-text database indexing -- hence this tool is not required. Read
-the documentation for %FullTextSearch in your RT_Config for more details.
-
-EOT
- exit 1;
-}
-
-if ( $db_type eq 'Oracle' ) {
- my $index = $fts_config->{'IndexName'} || 'rt_fts_index';
- $RT::Handle->dbh->do(
- "begin ctx_ddl.sync_index(?, ?); end;", undef,
- $index, $OPT{'memory'}
- );
- exit;
-} elsif ( $db_type eq 'mysql' ) {
- unless ($OPT{'xmlpipe2'}) {
- print STDERR <<EOT;
-
-Updates to the external Sphinx index are done via running the sphinx
-`indexer` tool:
-
- indexer rt
-
-EOT
- exit 1;
- }
-}
-
-my @types = qw(text html);
-foreach my $type ( @types ) {
- REDO:
- my $attachments = attachments($type);
- $attachments->Limit(
- FIELD => 'id',
- OPERATOR => '>',
- VALUE => last_indexed($type)
- );
- $attachments->OrderBy( FIELD => 'id', ORDER => 'asc' );
- $attachments->RowsPerPage( $OPT{'limit'} || 100 );
-
- my $found = 0;
- while ( my $a = $attachments->Next ) {
- next if filter( $type, $a );
- debug("Found attachment #". $a->id );
- my $txt = extract($type, $a) or next;
- $found++;
- process( $type, $a, $txt );
- debug("Processed attachment #". $a->id );
- }
- finalize( $type, $attachments ) if $found;
- clean( $type );
- goto REDO if $OPT{'all'} and $attachments->Count == ($OPT{'limit'} || 100)
-}
-
-sub attachments {
- my $type = shift;
- my $res = RT::Attachments->new( RT->SystemUser );
- my $txn_alias = $res->Join(
- ALIAS1 => 'main',
- FIELD1 => 'TransactionId',
- TABLE2 => 'Transactions',
- FIELD2 => 'id',
- );
- $res->Limit(
- ALIAS => $txn_alias,
- FIELD => 'ObjectType',
- VALUE => 'RT::Ticket',
- );
- my $ticket_alias = $res->Join(
- ALIAS1 => $txn_alias,
- FIELD1 => 'ObjectId',
- TABLE2 => 'Tickets',
- FIELD2 => 'id',
- );
- $res->Limit(
- ALIAS => $ticket_alias,
- FIELD => 'Status',
- OPERATOR => '!=',
- VALUE => 'deleted'
- );
-
- # On newer DBIx::SearchBuilder's, indicate that making the query DISTINCT
- # is unnecessary because the joins won't produce duplicates. This
- # drastically improves performance when fetching attachments.
- $res->{joins_are_distinct} = 1;
-
- return goto_specific(
- suffix => $type,
- error => "Don't know how to find $type attachments",
- arguments => [$res],
- );
-}
-
-sub last_indexed {
- my ($type) = (@_);
- return goto_specific(
- suffix => $db_type,
- error => "Don't know how to find last indexed $type attachment for $db_type DB",
- arguments => \@_,
- );
-}
-
-sub filter {
- my $type = shift;
- return goto_specific(
- suffix => $type,
- arguments => \@_,
- );
-}
-
-sub extract {
- my $type = shift;
- return goto_specific(
- suffix => $type,
- error => "No way to convert $type attachment into text",
- arguments => \@_,
- );
-}
-
-sub process {
- return goto_specific(
- suffix => $db_type,
- error => "No processer for $db_type DB",
- arguments => \@_,
- );
-}
-
-sub finalize {
- return goto_specific(
- suffix => $db_type,
- arguments => \@_,
- );
-}
-
-sub clean {
- return goto_specific(
- suffix => $db_type,
- arguments => \@_,
- );
-}
-
-{
-sub last_indexed_mysql {
- my $type = shift;
- my $attr = $RT::System->FirstAttribute('LastIndexedAttachments');
- return 0 unless $attr;
- return 0 unless exists $attr->{ $type };
- return $attr->{ $type } || 0;
-}
-
-sub process_mysql {
- my ($type, $attachment, $text) = (@_);
-
- my $doc = sphinx_template();
-
- my $element = $doc->createElement('sphinx:document');
- $element->setAttribute( id => $attachment->id );
- $element->appendTextChild( content => $$text );
-
- $doc->documentElement->appendChild( $element );
-}
-
-my $doc = undef;
-sub sphinx_template {
- return $doc if $doc;
-
- require XML::LibXML;
- $doc = XML::LibXML::Document->new('1.0', 'UTF-8');
- my $root = $doc->createElement('sphinx:docset');
- $doc->setDocumentElement( $root );
-
- my $schema = $doc->createElement('sphinx:schema');
- $root->appendChild( $schema );
- foreach ( qw(content) ) {
- my $field = $doc->createElement('sphinx:field');
- $field->setAttribute( name => $_ );
- $schema->appendChild( $field );
- }
-
- return $doc;
-}
-
-sub finalize_mysql {
- my ($type, $attachments) = @_;
- sphinx_template()->toFH(*STDOUT, 1);
-}
-
-sub clean_mysql {
- $doc = undef;
-}
-
-}
-
-sub last_indexed_pg {
- my $type = shift;
- my $attachments = attachments( $type );
- my $alias = 'main';
- if ( $fts_config->{'Table'} && $fts_config->{'Table'} ne 'Attachments' ) {
- $alias = $attachments->Join(
- TYPE => 'left',
- FIELD1 => 'id',
- TABLE2 => $fts_config->{'Table'},
- FIELD2 => 'id',
- );
- }
- $attachments->Limit(
- ALIAS => $alias,
- FIELD => $fts_config->{'Column'},
- OPERATOR => 'IS NOT',
- VALUE => 'NULL',
- );
- $attachments->OrderBy( FIELD => 'id', ORDER => 'desc' );
- $attachments->RowsPerPage( 1 );
- my $res = $attachments->First;
- return 0 unless $res;
- return $res->id;
-}
-
-sub process_pg {
- my ($type, $attachment, $text) = (@_);
-
- my $dbh = $RT::Handle->dbh;
- my $table = $fts_config->{'Table'};
- my $column = $fts_config->{'Column'};
-
- my $query;
- if ( $table ) {
- if ( my ($id) = $dbh->selectrow_array("SELECT id FROM $table WHERE id = ?", undef, $attachment->id) ) {
- $query = "UPDATE $table SET $column = to_tsvector(?) WHERE id = ?";
- } else {
- $query = "INSERT INTO $table($column, id) VALUES(to_tsvector(?), ?)";
- }
- } else {
- $query = "UPDATE Attachments SET $column = to_tsvector(?) WHERE id = ?";
- }
-
- my $status = eval { $dbh->do( $query, undef, $$text, $attachment->id ) };
- unless ( $status ) {
- if ( $dbh->err == 7 && $dbh->state eq '54000' ) {
- warn "Attachment @{[$attachment->id]} cannot be indexed, as it contains too many unique words";
- } elsif ( $dbh->err == 7 && $dbh->state eq '22021' ) {
- warn "Attachment @{[$attachment->id]} cannot be indexed, as it contains invalid UTF8 bytes";
- } else {
- die "error: ". $dbh->errstr;
- }
-
- # Insert an empty tsvector, so we count this row as "indexed"
- # for purposes of knowing where to pick up
- eval { $dbh->do( $query, undef, "", $attachment->id ) }
- or die "Failed to insert empty tsvector: " . $dbh->errstr;
- }
-}
-
-sub attachments_text {
- my $res = shift;
- $res->Limit( FIELD => 'ContentType', VALUE => 'text/plain' );
- return $res;
-}
-
-sub extract_text {
- my $attachment = shift;
- my $text = $attachment->Content;
- return undef unless defined $text && length($text);
- return \$text;
-}
-
-sub attachments_html {
- my $res = shift;
- $res->Limit( FIELD => 'ContentType', VALUE => 'text/html' );
- return $res;
-}
-
-sub filter_html {
- my $attachment = shift;
- if ( my $parent = $attachment->ParentObj ) {
-# skip html parts that are alternatives
- return 1 if $parent->id
- && $parent->ContentType eq 'mulitpart/alternative';
- }
- return 0;
-}
-
-sub extract_html {
- my $attachment = shift;
- my $text = $attachment->Content;
- return undef unless defined $text && length($text);
-# TODO: html -> text
- return \$text;
-}
-
-sub goto_specific {
- my %args = (@_);
-
- my $func = (caller(1))[3];
- $func =~ s/.*:://;
- my $call = $func ."_". lc $args{'suffix'};
- unless ( defined &$call ) {
- return undef unless $args{'error'};
- require Carp; Carp::croak( $args{'error'} );
- }
- @_ = @{ $args{'arguments'} };
- goto &$call;
-}
-
-
-# helper functions
-sub debug { print @_, "\n" if $OPT{debug}; 1 }
-sub error { $RT::Logger->error(_(@_)); 1 }
-sub warning { $RT::Logger->warn(_(@_)); 1 }
-
-=head1 NAME
-
-rt-fulltext-indexer - Indexer for full text search
-
-=head1 DESCRIPTION
-
-This is a helper script to keep full text indexes in sync with data.
-Read F<docs/full_text_indexing.pod> for complete details on how and when
-to run it.
-
-=head1 AUTHOR
-
-Ruslan Zakirov E<lt>ruz@bestpractical.comE<gt>,
-Alex Vandiver E<lt>alexmv@bestpractical.comE<gt>
-
-=cut
-
diff --git a/rt/sbin/rt-fulltext-indexer.in b/rt/sbin/rt-fulltext-indexer.in
index 9ad6d26..b84ca94 100644
--- a/rt/sbin/rt-fulltext-indexer.in
+++ b/rt/sbin/rt-fulltext-indexer.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -375,9 +375,9 @@ sub process_pg {
my $status = eval { $dbh->do( $query, undef, $$text, $attachment->id ) };
unless ( $status ) {
if ( $dbh->err == 7 && $dbh->state eq '54000' ) {
- warn "Attachment @{[$attachment->id]} cannot be indexed, as it contains too many unique words";
+ warn "Attachment @{[$attachment->id]} cannot be indexed. Most probably it contains too many unique words. Error: ". $dbh->errstr;
} elsif ( $dbh->err == 7 && $dbh->state eq '22021' ) {
- warn "Attachment @{[$attachment->id]} cannot be indexed, as it contains invalid UTF8 bytes";
+ warn "Attachment @{[$attachment->id]} cannot be indexed. Most probably it contains invalid UTF8 bytes. Error: ". $dbh->errstr;
} else {
die "error: ". $dbh->errstr;
}
diff --git a/rt/sbin/rt-message-catalog b/rt/sbin/rt-message-catalog
index b31b58d..b428369 100755
--- a/rt/sbin/rt-message-catalog
+++ b/rt/sbin/rt-message-catalog
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-preferences-viewer.in b/rt/sbin/rt-preferences-viewer.in
index d32588e..8eeb7c9 100644
--- a/rt/sbin/rt-preferences-viewer.in
+++ b/rt/sbin/rt-preferences-viewer.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-server.fcgi.in b/rt/sbin/rt-server.fcgi.in
index 632ba0b..0d11f01 100644
--- a/rt/sbin/rt-server.fcgi.in
+++ b/rt/sbin/rt-server.fcgi.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -127,7 +127,7 @@ EOF
RT->InstallMode(1);
} else {
- RT->Init();
+ RT->Init( Heavy => 1 );
my ($status, $msg) = RT::Handle->CheckCompatibility( $RT::Handle->dbh, 'post');
unless ( $status ) {
diff --git a/rt/sbin/rt-server.in b/rt/sbin/rt-server.in
index 632ba0b..0d11f01 100644
--- a/rt/sbin/rt-server.in
+++ b/rt/sbin/rt-server.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -127,7 +127,7 @@ EOF
RT->InstallMode(1);
} else {
- RT->Init();
+ RT->Init( Heavy => 1 );
my ($status, $msg) = RT::Handle->CheckCompatibility( $RT::Handle->dbh, 'post');
unless ( $status ) {
diff --git a/rt/sbin/rt-session-viewer b/rt/sbin/rt-session-viewer
deleted file mode 100755
index 1a6334d..0000000
--- a/rt/sbin/rt-session-viewer
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/perl
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2013 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 strict;
-use warnings;
-
-# fix lib paths, some may be relative
-BEGIN {
- require File::Spec;
- my @libs = ("/opt/rt3/lib", "/opt/rt3/local/lib");
- my $bin_path;
-
- for my $lib (@libs) {
- unless ( File::Spec->file_name_is_absolute($lib) ) {
- unless ($bin_path) {
- if ( File::Spec->file_name_is_absolute(__FILE__) ) {
- $bin_path = ( File::Spec->splitpath(__FILE__) )[1];
- }
- else {
- require FindBin;
- no warnings "once";
- $bin_path = $FindBin::Bin;
- }
- }
- $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib );
- }
- unshift @INC, $lib;
- }
-}
-
-use Getopt::Long;
-my %opt;
-GetOptions( \%opt, 'help|h', );
-
-my $session_id = shift;
-
-if ( $opt{help} || !$session_id ) {
- require Pod::Usage;
- Pod::Usage::pod2usage({ verbose => 2 });
- exit;
-}
-
-require RT;
-RT::LoadConfig();
-RT::Init();
-
-require RT::Interface::Web::Session;
-my %session;
-
-tie %session, 'RT::Interface::Web::Session', $session_id;
-unless ( $session{'_session_id'} eq $session_id ) {
- print STDERR "Couldn't load session $session_id\n";
- exit 1;
-}
-
-use Data::Dumper;
-print "Content of session $session_id: ". Dumper( \%session);
-
-__END__
-
-=head1 NAME
-
-rt-session-viewer - show the content of a user's session
-
-=head1 SYNOPSIS
-
- # show the content of a session
- rt-session-viewer 2c21c8a2909c14eff12975dd2cc7b9a3
-
-=head1 DESCRIPTION
-
-This script deserializes and print content of a session identified
-by <session id>. May be useful for developers and for troubleshooting
-problems.
-
-=cut
diff --git a/rt/sbin/rt-session-viewer.in b/rt/sbin/rt-session-viewer.in
index cdf7a77..5ace1ae 100644
--- a/rt/sbin/rt-session-viewer.in
+++ b/rt/sbin/rt-session-viewer.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-setup-database.in b/rt/sbin/rt-setup-database.in
index f1e35f5..edf3d46 100644
--- a/rt/sbin/rt-setup-database.in
+++ b/rt/sbin/rt-setup-database.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -83,13 +83,15 @@ $| = 1; # unbuffer all output.
my %args = (
dba => '@DB_DBA@',
+ package => 'RT',
);
GetOptions(
\%args,
'action=s',
'force', 'debug',
- 'dba=s', 'dba-password=s', 'prompt-for-dba-password',
+ 'dba=s', 'dba-password=s', 'prompt-for-dba-password', 'package=s',
'datafile=s', 'datadir=s', 'skip-create', 'root-password-file=s',
+ 'upgrade-from=s', 'upgrade-to=s',
'help|h',
);
@@ -164,6 +166,7 @@ foreach my $key(qw(Type Host Name User Password)) {
my $db_type = RT->Config->Get('DatabaseType') || '';
my $db_host = RT->Config->Get('DatabaseHost') || '';
+my $db_port = RT->Config->Get('DatabasePort') || '';
my $db_name = RT->Config->Get('DatabaseName') || '';
my $db_user = RT->Config->Get('DatabaseUser') || '';
my $db_pass = RT->Config->Get('DatabasePassword') || '';
@@ -191,8 +194,11 @@ if ($args{'skip-create'}) {
}
}
+my $version_word_regex = join '|', RT::Handle->version_words;
+my $version_dir = qr/^\d+\.\d+\.\d+(?:$version_word_regex)?\d*$/;
+
print "Working with:\n"
- ."Type:\t$db_type\nHost:\t$db_host\nName:\t$db_name\n"
+ ."Type:\t$db_type\nHost:\t$db_host\nPort:\t$db_port\nName:\t$db_name\n"
."User:\t$db_user\nDBA:\t$dba_user" . ($args{'skip-create'} ? ' (No DBA)' : '') . "\n";
foreach my $action ( @actions ) {
@@ -220,7 +226,7 @@ sub action_drop {
unless ( $args{'force'} ) {
print <<END;
-About to drop $db_type database $db_name on $db_host.
+About to drop $db_type database $db_name on $db_host (port '$db_port').
WARNING: This will erase all data in $db_name.
END
@@ -308,18 +314,17 @@ sub action_upgrade {
return (0, "Couldn't read dir '$base_dir' with upgrade data")
unless -d $base_dir || -r _;
- my $version_word_regex = join '|', RT::Handle->version_words;
my $upgrading_from = undef;
do {
if ( defined $upgrading_from ) {
print "Doesn't match #.#.#: ";
} else {
- print "Enter RT version you're upgrading from: ";
+ print "Enter $args{package} version you're upgrading from: ";
}
- $upgrading_from = scalar <STDIN>;
+ $upgrading_from = $args{'upgrade-from'} || scalar <STDIN>;
chomp $upgrading_from;
$upgrading_from =~ s/\s+//g;
- } while $upgrading_from !~ /^\d+\.\d+\.\d+(?:$version_word_regex)?\d*$/;
+ } while $upgrading_from !~ /$version_dir/;
my $upgrading_to = $RT::VERSION;
return (0, "The current version $upgrading_to is lower than $upgrading_from")
@@ -347,14 +352,14 @@ sub action_upgrade {
if ( defined $custom_upgrading_to ) {
print "Doesn't match #.#.#: ";
} else {
- print "\nEnter RT version if you want to stop upgrade at some point,\n";
+ print "\nEnter $args{package} version if you want to stop upgrade at some point,\n";
print " or leave it blank if you want apply above upgrades: ";
}
- $custom_upgrading_to = scalar <STDIN>;
+ $custom_upgrading_to = $args{'upgrade-to'} || scalar <STDIN>;
chomp $custom_upgrading_to;
$custom_upgrading_to =~ s/\s+//g;
last unless $custom_upgrading_to;
- } while $custom_upgrading_to !~ /^\d+\.\d+\.\d+(?:$version_word_regex)?\d*$/;
+ } while $custom_upgrading_to !~ /$version_dir/;
if ( $custom_upgrading_to ) {
return (
@@ -410,9 +415,12 @@ sub get_versions_from_to {
my ($base_dir, $from, $to) = @_;
opendir( my $dh, $base_dir ) or die "couldn't open dir: $!";
- my @versions = grep -d "$base_dir/$_" && /\d+\.\d+\.\d+/, readdir $dh;
+ my @versions = grep -d "$base_dir/$_" && /$version_dir/, readdir $dh;
closedir $dh;
+ die "\nERROR: No upgrade data found in '$base_dir'! Perhaps you specified the wrong --datadir?\n"
+ unless @versions;
+
return
grep defined $to ? RT::Handle::cmp_version($_, $to) <= 0 : 1,
grep RT::Handle::cmp_version($_, $from) > 0,
@@ -429,7 +437,7 @@ sub error {
sub get_dba_password {
print "In order to create or update your RT database,"
. " this script needs to connect to your "
- . " $db_type instance on $db_host as $dba_user\n";
+ . " $db_type instance on $db_host (port '$db_port') as $dba_user\n";
print "Please specify that user's database password below. If the user has no database\n";
print "password, just press return.\n\n";
print "Password: ";
@@ -588,4 +596,14 @@ administrator privileges
for 'init' and 'insert': rather than using the default administrative password
for RT's "root" user, use the password in this file.
+=item upgrade-from
+
+for 'upgrade': specifies the version to upgrade from, and do not prompt
+for it if it appears to be a valid version.
+
+=item upgrade-to
+
+for 'upgrade': specifies the version to upgrade to, and do not prompt
+for it if it appears to be a valid version.
+
=back
diff --git a/rt/sbin/rt-setup-fulltext-index b/rt/sbin/rt-setup-fulltext-index
deleted file mode 100755
index ef9b7d5..0000000
--- a/rt/sbin/rt-setup-fulltext-index
+++ /dev/null
@@ -1,714 +0,0 @@
-#!/usr/bin/perl
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
-# <sales@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 strict;
-use warnings;
-no warnings 'once';
-
-# fix lib paths, some may be relative
-BEGIN {
- require File::Spec;
- my @libs = ("/opt/rt3/lib", "/opt/rt3/local/lib");
- my $bin_path;
-
- for my $lib (@libs) {
- unless ( File::Spec->file_name_is_absolute($lib) ) {
- unless ($bin_path) {
- if ( File::Spec->file_name_is_absolute(__FILE__) ) {
- $bin_path = ( File::Spec->splitpath(__FILE__) )[1];
- }
- else {
- require FindBin;
- no warnings "once";
- $bin_path = $FindBin::Bin;
- }
- }
- $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib );
- }
- unshift @INC, $lib;
- }
-}
-
-BEGIN {
- use RT;
- RT::LoadConfig();
- RT::Init();
-};
-use RT::Interface::CLI ();
-
-my %DB = (
- type => scalar RT->Config->Get('DatabaseType'),
- user => scalar RT->Config->Get('DatabaseUser'),
- admin => 'freeside',
- admin_password => undef,
-);
-
-my %OPT = (
- help => 0,
- ask => 1,
- dryrun => 0,
- attachments => 1,
-);
-
-my %DEFAULT;
-if ( $DB{'type'} eq 'Pg' ) {
- %DEFAULT = (
- table => 'Attachments',
- column => 'ContentIndex',
- );
-}
-elsif ( $DB{'type'} eq 'mysql' ) {
- %DEFAULT = (
- table => 'AttachmentsIndex',
- );
-}
-elsif ( $DB{'type'} eq 'Oracle' ) {
- %DEFAULT = (
- prefix => 'rt_fts_',
- );
-}
-
-use Getopt::Long qw(GetOptions);
-GetOptions(
- 'h|help!' => \$OPT{'help'},
- 'ask!' => \$OPT{'ask'},
- 'dry-run!' => \$OPT{'dryrun'},
- 'attachments!' => \$OPT{'attachments'},
-
- 'table=s' => \$OPT{'table'},
- 'column=s' => \$OPT{'column'},
- 'url=s' => \$OPT{'url'},
- 'maxmatches=i' => \$OPT{'maxmatches'},
- 'index-type=s' => \$OPT{'index-type'},
-
- 'dba=s' => \$DB{'admin'},
- 'dba-password=s' => \$DB{'admin_password'},
-) or show_help();
-
-if ( $OPT{'help'} || (!$DB{'admin'} && $DB{'type'} eq 'Oracle' ) ) {
- show_help( !$OPT{'help'} );
-}
-
-my $dbh = $RT::Handle->dbh;
-$dbh->{'RaiseError'} = 1;
-$dbh->{'PrintError'} = 1;
-
-if ( $DB{'type'} eq 'mysql' ) {
- check_sphinx();
- my $table = $OPT{'table'} || prompt(
- message => "Enter name of a new MySQL table that will be used to connect to the\n"
- . "Sphinx server:",
- default => $DEFAULT{'table'},
- silent => !$OPT{'ask'},
- );
- my $url = $OPT{'url'} || prompt(
- message => "Enter URL of the sphinx search server; this should be of the form\n"
- . "sphinx://<server>:<port>/<index name>",
- default => 'sphinx://localhost:3312/rt',
- silent => !$OPT{'ask'},
- );
- my $maxmatches = $OPT{'maxmatches'} || prompt(
- message => "Maximum number of matches to return; this is the maximum number of\n"
- . "attachment records returned by the search, not the maximum number\n"
- . "of tickets. Both your RT_SiteConfig.pm and your sphinx.conf must\n"
- . "agree on this value. Larger values cause your Sphinx server to\n"
- . "consume more memory and CPU time per query.",
- default => 10000,
- silent => !$OPT{'ask'},
- );
-
- my $schema = <<END;
-CREATE TABLE $table (
- id INTEGER UNSIGNED NOT NULL,
- weight INTEGER NOT NULL,
- query VARCHAR(3072) NOT NULL,
- INDEX(query)
-) ENGINE=SPHINX CONNECTION="$url" CHARACTER SET utf8
-END
-
- do_error_is_ok( dba_handle() => "DROP TABLE $table" )
- unless $OPT{'dryrun'};
- insert_schema( $schema );
-
- print_rt_config( Table => $table, MaxMatches => $maxmatches );
-
- require URI;
- my $urlo = URI->new( $url );
- my ($host, $port) = split /:/, $urlo->authority;
- my $index = $urlo->path;
- $index =~ s{^/+}{};
-
- my $var_path = $RT::VarPath;
-
- my %sphinx_conf = ();
- $sphinx_conf{'host'} = RT->Config->Get('DatabaseHost');
- $sphinx_conf{'db'} = RT->Config->Get('DatabaseName');
- $sphinx_conf{'user'} = RT->Config->Get('DatabaseUser');
- $sphinx_conf{'pass'} = RT->Config->Get('DatabasePassword');
-
- print <<END
-
-Below is a simple Sphinx configuration which can be used to index all
-text/plain attachments in your database. This configuration is not
-ideal; you should read the Sphinx documentation to understand how to
-configure it to better suit your needs.
-
-source rt {
- type = mysql
-
- sql_host = $sphinx_conf{'host'}
- sql_db = $sphinx_conf{'db'}
- sql_user = $sphinx_conf{'user'}
- sql_pass = $sphinx_conf{'pass'}
-
- sql_query_pre = SET NAMES utf8
- sql_query = \\
- SELECT a.id, a.content FROM Attachments a \\
- JOIN Transactions txn ON a.TransactionId = txn.id AND txn.ObjectType = 'RT::Ticket' \\
- JOIN Tickets t ON txn.ObjectId = t.id \\
- WHERE a.ContentType = 'text/plain' AND t.Status != 'deleted'
-
- sql_query_info = SELECT * FROM Attachments WHERE id=\$id
-}
-
-index $index {
- source = rt
- path = $var_path/sphinx/index
- docinfo = extern
- charset_type = utf-8
-}
-
-indexer {
- mem_limit = 32M
-}
-
-searchd {
- port = $port
- log = $var_path/sphinx/searchd.log
- query_log = $var_path/sphinx/query.log
- read_timeout = 5
- max_children = 30
- pid_file = $var_path/sphinx/searchd.pid
- max_matches = $maxmatches
- seamless_rotate = 1
- preopen_indexes = 0
- unlink_old = 1
-}
-
-END
-
-}
-elsif ( $DB{'type'} eq 'Pg' ) {
- check_tsvalue();
- my $table = $OPT{'table'} || prompt(
- message => "Enter the name of a DB table that will be used to store the Pg tsvector.\n"
- . "You may either use the existing Attachments table, or create a new\n"
- . "table.",
- default => $DEFAULT{'table'},
- silent => !$OPT{'ask'},
- );
- my $column = $OPT{'column'} || prompt(
- message => 'Enter the name of a column that will be used to store the Pg tsvector:',
- default => $DEFAULT{'column'},
- silent => !$OPT{'ask'},
- );
-
- my $schema;
- my $drop;
- if ( lc($table) eq 'attachments' ) {
- $drop = "ALTER TABLE $table DROP COLUMN $column";
- $schema = "ALTER TABLE $table ADD COLUMN $column tsvector";
- } else {
- $drop = "DROP TABLE $table";
- $schema = "CREATE TABLE $table ( "
- ."id INTEGER NOT NULL,"
- ."$column tsvector )";
- }
-
- my $index_type = lc($OPT{'index-type'} || '');
- while ( $index_type ne 'gist' and $index_type ne 'gin' ) {
- $index_type = lc prompt(
- message => "You may choose between GiST or GIN indexes; the former is several times\n"
- . "slower to search, but takes less space on disk and is faster to update.",
- default => 'GiST',
- silent => !$OPT{'ask'},
- );
- }
-
- do_error_is_ok( dba_handle() => $drop )
- unless $OPT{'dryrun'};
- insert_schema( $schema );
- insert_schema("CREATE INDEX ${column}_idx ON $table USING $index_type($column)");
-
- print_rt_config( Table => $table, Column => $column );
-}
-elsif ( $DB{'type'} eq 'Oracle' ) {
- {
- my $dbah = dba_handle();
- do_print_error( $dbah => 'GRANT CTXAPP TO '. $DB{'user'} );
- do_print_error( $dbah => 'GRANT EXECUTE ON CTXSYS.CTX_DDL TO '. $DB{'user'} );
- }
-
- my %PREFERENCES = (
- datastore => {
- type => 'DIRECT_DATASTORE',
- },
- filter => {
- type => 'AUTO_FILTER',
-# attributes => {
-# timeout => 120, # seconds
-# timeout_type => 'HEURISTIC', # or 'FIXED'
-# },
- },
- lexer => {
- type => 'WORLD_LEXER',
- },
- word_list => {
- type => 'BASIC_WORDLIST',
- attributes => {
- stemmer => 'AUTO',
- fuzzy_match => 'AUTO',
-# fuzzy_score => undef,
-# fuzzy_numresults => undef,
-# substring_index => undef,
-# prefix_index => undef,
-# prefix_length_min => undef,
-# prefix_length_max => undef,
-# wlidcard_maxterms => undef,
- },
- },
- 'section_group' => {
- type => 'NULL_SECTION_GROUP',
- },
-
- storage => {
- type => 'BASIC_STORAGE',
- attributes => {
- R_TABLE_CLAUSE => 'lob (data) store as (cache)',
- I_INDEX_CLAUSE => 'compress 2',
- },
- },
- );
-
- my @params = ();
- push @params, ora_create_datastore( %{ $PREFERENCES{'datastore'} } );
- push @params, ora_create_filter( %{ $PREFERENCES{'filter'} } );
- push @params, ora_create_lexer( %{ $PREFERENCES{'lexer'} } );
- push @params, ora_create_word_list( %{ $PREFERENCES{'word_list'} } );
- push @params, ora_create_stop_list();
- push @params, ora_create_section_group( %{ $PREFERENCES{'section_group'} } );
- push @params, ora_create_storage( %{ $PREFERENCES{'storage'} } );
-
- my $index_params = join "\n", @params;
- my $index_name = $DEFAULT{prefix} .'index';
- do_error_is_ok( $dbh => "DROP INDEX $index_name" )
- unless $OPT{'dryrun'};
- $dbh->do(
- "CREATE INDEX $index_name ON Attachments(Content)
- indextype is ctxsys.context parameters('
- $index_params
- ')",
- ) unless $OPT{'dryrun'};
-
- print_rt_config( IndexName => $index_name );
-}
-else {
- die "Full-text indexes on $DB{type} are not yet supported";
-}
-
-sub check_tsvalue {
- my $dbh = $RT::Handle->dbh;
- my $fts = ($dbh->selectrow_array(<<EOQ))[0];
-SELECT 1 FROM information_schema.routines WHERE routine_name = 'plainto_tsquery'
-EOQ
- unless ($fts) {
- print STDERR <<EOT;
-
-Your PostgreSQL server does not include full-text support. You will
-need to upgrade to PostgreSQL version 8.3 or higher to use full-text
-indexing.
-
-EOT
- exit 1;
- }
-}
-
-sub check_sphinx {
- return if $RT::Handle->CheckSphinxSE;
-
- print STDERR <<EOT;
-
-Your MySQL server has not been compiled with the Sphinx storage engine
-(sphinxse). You will need to recompile MySQL according to the
-instructions in Sphinx's documentation at
-http://sphinxsearch.com/docs/current.html#sphinxse-installing
-
-EOT
- exit 1;
-}
-
-sub ora_create_datastore {
- return sprintf 'datastore %s', ora_create_preference(
- @_,
- name => 'datastore',
- );
-}
-
-sub ora_create_filter {
- my $res = '';
- $res .= sprintf "format column %s\n", ora_create_format_column();
- $res .= sprintf 'filter %s', ora_create_preference(
- @_,
- name => 'filter',
- );
- return $res;
-}
-
-sub ora_create_lexer {
- return sprintf 'lexer %s', ora_create_preference(
- @_,
- name => 'lexer',
- );
-}
-
-sub ora_create_word_list {
- return sprintf 'wordlist %s', ora_create_preference(
- @_,
- name => 'word_list',
- );
-}
-
-sub ora_create_stop_list {
- my $file = shift || 'etc/stopwords/en.txt';
- return '' unless -e $file;
-
- my $name = $DEFAULT{'prefix'} .'stop_list';
- unless ($OPT{'dryrun'}) {
- do_error_is_ok( $dbh => 'begin ctx_ddl.drop_stoplist(?); end;', $name );
-
- $dbh->do(
- 'begin ctx_ddl.create_stoplist(?, ?); end;',
- undef, $name, 'BASIC_STOPLIST'
- );
-
- open( my $fh, '<:utf8', $file )
- or die "couldn't open file '$file': $!";
- while ( my $word = <$fh> ) {
- chomp $word;
- $dbh->do(
- 'begin ctx_ddl.add_stopword(?, ?); end;',
- undef, $name, $word
- );
- }
- close $fh;
- }
- return sprintf 'stoplist %s', $name;
-}
-
-sub ora_create_section_group {
- my %args = @_;
- my $name = $DEFAULT{'prefix'} .'section_group';
- unless ($OPT{'dryrun'}) {
- do_error_is_ok( $dbh => 'begin ctx_ddl.drop_section_group(?); end;', $name );
- $dbh->do(
- 'begin ctx_ddl.create_section_group(?, ?); end;',
- undef, $name, $args{'type'}
- );
- }
- return sprintf 'section group %s', $name;
-}
-
-sub ora_create_storage {
- return sprintf 'storage %s', ora_create_preference(
- @_,
- name => 'storage',
- );
-}
-
-sub ora_create_format_column {
- my $column_name = 'ContentOracleFormat';
- return $column_name if $OPT{'dryrun'};
- unless (
- $dbh->column_info(
- undef, undef, uc('Attachments'), uc( $column_name )
- )->fetchrow_array
- ) {
- $dbh->do(qq{
- ALTER TABLE Attachments ADD $column_name VARCHAR2(10)
- });
- }
-
- my $detect_format = qq{
- CREATE OR REPLACE FUNCTION $DEFAULT{prefix}detect_format_simple(
- parent IN NUMBER,
- type IN VARCHAR2,
- encoding IN VARCHAR2,
- fname IN VARCHAR2
- )
- RETURN VARCHAR2
- AS
- format VARCHAR2(10);
- BEGIN
- format := CASE
- };
- unless ( $OPT{'attachments'} ) {
- $detect_format .= qq{
- WHEN fname IS NOT NULL THEN 'ignore'
- };
- }
- $detect_format .= qq{
- WHEN type = 'text' THEN 'text'
- WHEN type = 'text/rtf' THEN 'ignore'
- WHEN type LIKE 'text/%' THEN 'text'
- WHEN type LIKE 'message/%' THEN 'text'
- ELSE 'ignore'
- END;
- RETURN format;
- END;
- };
- ora_create_procedure( $detect_format );
-
- $dbh->do(qq{
- UPDATE Attachments
- SET $column_name = $DEFAULT{prefix}detect_format_simple(
- Parent,
- ContentType, ContentEncoding,
- Filename
- )
- WHERE $column_name IS NULL
- });
- $dbh->do(qq{
- CREATE OR REPLACE TRIGGER $DEFAULT{prefix}set_format
- BEFORE INSERT
- ON Attachments
- FOR EACH ROW
- BEGIN
- :new.$column_name := $DEFAULT{prefix}detect_format_simple(
- :new.Parent,
- :new.ContentType, :new.ContentEncoding,
- :new.Filename
- );
- END;
- });
- return $column_name;
-}
-
-sub ora_create_preference {
- my %info = @_;
- my $name = $DEFAULT{'prefix'} . $info{'name'};
- return $name if $OPT{'dryrun'};
- do_error_is_ok( $dbh => 'begin ctx_ddl.drop_preference(?); end;', $name );
- $dbh->do(
- 'begin ctx_ddl.create_preference(?, ?); end;',
- undef, $name, $info{'type'}
- );
- return $name unless $info{'attributes'};
-
- while ( my ($attr, $value) = each %{ $info{'attributes'} } ) {
- $dbh->do(
- 'begin ctx_ddl.set_attribute(?, ?, ?); end;',
- undef, $name, $attr, $value
- );
- }
-
- return $name;
-}
-
-sub ora_create_procedure {
- my $text = shift;
-
- return if $OPT{'dryrun'};
- my $status = $dbh->do($text, { RaiseError => 0 });
-
- # Statement succeeded
- return if $status;
-
- if ( 6550 != $dbh->err ) {
- # Utter failure
- die $dbh->errstr;
- }
- else {
- my $msg = $dbh->func( 'plsql_errstr' );
- die $dbh->errstr if !defined $msg;
- die $msg if $msg;
- }
-}
-
-sub dba_handle {
- if ( $DB{'type'} eq 'Oracle' ) {
- $ENV{'NLS_LANG'} = "AMERICAN_AMERICA.AL32UTF8";
- $ENV{'NLS_NCHAR'} = "AL32UTF8";
- }
- my $dsn = do { my $h = new RT::Handle; $h->BuildDSN; $h->DSN };
- my $dbh = DBI->connect(
- $dsn, $DB{admin}, $DB{admin_password},
- { RaiseError => 1, PrintError => 1 },
- );
- unless ( $dbh ) {
- die "Failed to connect to $dsn as user '$DB{admin}': ". $DBI::errstr;
- }
- return $dbh;
-}
-
-sub do_error_is_ok {
- my $dbh = shift;
- local $dbh->{'RaiseError'} = 0;
- local $dbh->{'PrintError'} = 0;
- return $dbh->do(shift, undef, @_);
-}
-
-sub do_print_error {
- my $dbh = shift;
- local $dbh->{'RaiseError'} = 0;
- local $dbh->{'PrintError'} = 1;
- return $dbh->do(shift, undef, @_);
-}
-
-sub prompt {
- my %args = ( @_ );
- return $args{'default'} if $args{'silent'};
-
- local $| = 1;
- print $args{'message'};
- if ( $args{'default'} ) {
- print "\n[". $args{'default'} .']: ';
- } else {
- print ":\n";
- }
-
- my $res = <STDIN>;
- chomp $res;
- print "\n";
- return $args{'default'} if !$res && $args{'default'};
- return $res;
-}
-
-sub verbose { print @_, "\n" if $OPT{verbose} || $OPT{verbose}; 1 }
-sub debug { print @_, "\n" if $OPT{debug}; 1 }
-sub error { $RT::Logger->error( @_ ); verbose(@_); 1 }
-sub warning { $RT::Logger->warning( @_ ); verbose(@_); 1 }
-
-sub show_help {
- my $error = shift;
- RT::Interface::CLI->ShowHelp(
- ExitValue => $error,
- Sections => 'NAME|DESCRIPTION',
- );
-}
-
-sub print_rt_config {
- my %args = @_;
- my $config = <<END;
-
-You can now configure RT to use the newly-created full-text index by
-adding the following to your RT_SiteConfig.pm:
-
-Set( %FullTextSearch,
- Enable => 1,
- Indexed => 1,
-END
-
- $config .= sprintf(" %-10s => '$args{$_}',\n",$_)
- foreach grep defined $args{$_}, keys %args;
- $config .= ");\n";
-
- print $config;
-}
-
-sub insert_schema {
- my $dbh = dba_handle();
- my $message = "Going to run the following in the DB:";
- my $schema = shift;
- print "$message\n";
- my $disp = $schema;
- $disp =~ s/^/ /mg;
- print "$disp\n\n";
- return if $OPT{'dryrun'};
-
- my $res = $dbh->do( $schema );
- unless ( $res ) {
- die "Couldn't run DDL query: ". $dbh->errstr;
- }
-}
-
-=head1 NAME
-
-rt-setup-fulltext-index - Create indexes for full text search
-
-=head1 DESCRIPTION
-
-This script creates the appropriate tables, columns, functions, and / or
-views necessary for full-text searching for your database type. It will
-drop any existing indexes in the process.
-
-Please read F<docs/full_text_indexing.pod> for complete documentation on
-full-text indexing for your database type.
-
-If you have a non-standard database administrator user or password, you
-may use the C<--dba> and C<--dba-password> parameters to set them
-explicitly:
-
- rt-setup-fulltext-index --dba sysdba --dba-password 'secret'
-
-To test what will happen without running any DDL, pass the C<--dryrun>
-flag.
-
-The Oracle index determines which content-types it will index at
-creation time. By default, textual message bodies and textual uploaded
-attachments (attachments with filenames) are indexed; to ignore textual
-attachments, pass the C<--no-attachments> flag when the index is
-created.
-
-
-=head1 AUTHOR
-
-Ruslan Zakirov E<lt>ruz@bestpractical.comE<gt>,
-Alex Vandiver E<lt>alexmv@bestpractical.comE<gt>
-
-=cut
-
diff --git a/rt/sbin/rt-setup-fulltext-index.in b/rt/sbin/rt-setup-fulltext-index.in
index eab7203..ade728f 100644
--- a/rt/sbin/rt-setup-fulltext-index.in
+++ b/rt/sbin/rt-setup-fulltext-index.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-shredder.in b/rt/sbin/rt-shredder.in
index e7910e5..a903728 100755
--- a/rt/sbin/rt-shredder.in
+++ b/rt/sbin/rt-shredder.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -135,7 +135,10 @@ BEGIN {
}
-use RT::Shredder ();
+use RT -init;
+
+require RT::Shredder;
+
use Getopt::Long qw(GetOptions);
use File::Spec ();
@@ -146,7 +149,6 @@ our %plugins = RT::Shredder::Plugin->List;
our %opt;
parse_args();
-RT::Shredder::Init( %opt );
my $shredder = RT::Shredder->new;
{
diff --git a/rt/sbin/rt-test-dependencies.in b/rt/sbin/rt-test-dependencies.in
index df1ef13..8681054 100644
--- a/rt/sbin/rt-test-dependencies.in
+++ b/rt/sbin/rt-test-dependencies.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -295,6 +295,7 @@ Test::WWW::Mechanize::PSGI
Plack::Middleware::Test::StashWarnings 0.06
Test::LongString
Test::NoWarnings
+Locale::PO
.
$deps{'FASTCGI'} = [ text_to_hash( << '.') ];
diff --git a/rt/sbin/rt-validate-aliases.in b/rt/sbin/rt-validate-aliases.in
index 5dbfaa4..97252ae 100644
--- a/rt/sbin/rt-validate-aliases.in
+++ b/rt/sbin/rt-validate-aliases.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/rt-validator.in b/rt/sbin/rt-validator.in
index d902801..128e60a 100644
--- a/rt/sbin/rt-validator.in
+++ b/rt/sbin/rt-validator.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/sbin/standalone_httpd b/rt/sbin/standalone_httpd
deleted file mode 100755
index 5bc8d0c..0000000
--- a/rt/sbin/standalone_httpd
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/perl -w
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
-# <sales@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;
-
-# fix lib paths, some may be relative
-BEGIN {
- die <<EOT if ${^TAINT};
-RT does not run under Perl's "taint mode". Remove -T from the command
-line, or remove the PerlTaintCheck parameter from your mod_perl
-configuration.
-EOT
-
- require File::Spec;
- my @libs = ("/opt/rt3/lib", "/opt/rt3/local/lib");
- my $bin_path;
-
- for my $lib (@libs) {
- unless ( File::Spec->file_name_is_absolute($lib) ) {
- unless ($bin_path) {
- if ( File::Spec->file_name_is_absolute(__FILE__) ) {
- $bin_path = ( File::Spec->splitpath(__FILE__) )[1];
- }
- else {
- require FindBin;
- no warnings "once";
- $bin_path = $FindBin::Bin;
- }
- }
- $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib );
- }
- unshift @INC, $lib;
- }
-
-}
-
-use Getopt::Long;
-no warnings 'once';
-
-if (grep { m/help/ } @ARGV) {
- require Pod::Usage;
- print Pod::Usage::pod2usage( { verbose => 2 } );
- exit;
-}
-
-require RT;
-RT->LoadConfig();
-RT->InitPluginPaths();
-RT->InitLogging();
-require Module::Refresh if RT->Config->Get('DevelMode');
-
-require RT::Handle;
-my ($integrity, $state, $msg) = RT::Handle->CheckIntegrity;
-
-unless ( $integrity ) {
- print STDERR <<EOF;
-
-RT couldn't connect to the database where tickets are stored.
-If this is a new installation of RT, you should visit the URL below
-to configure RT and initialize your database.
-
-If this is an existing RT installation, this may indicate a database
-connectivity problem.
-
-The error RT got back when trying to connect to your database was:
-
-$msg
-
-EOF
-
- require RT::Installer;
- # don't enter install mode if the file exists but is unwritable
- if (-e RT::Installer->ConfigFile && !-w _) {
- die 'Since your configuration exists ('
- . RT::Installer->ConfigFile
- . ") but is not writable, I'm refusing to do anything.\n";
- }
-
- RT->Config->Set( 'LexiconLanguages' => '*' );
- RT::I18N->Init;
-
- RT->InstallMode(1);
-} else {
- RT->Init();
-
- my ($status, $msg) = RT::Handle->CheckCompatibility( $RT::Handle->dbh, 'post');
- unless ( $status ) {
- print STDERR $msg, "\n\n";
- exit -1;
- }
-}
-
-# we must disconnect DB before fork
-if ($RT::Handle) {
- $RT::Handle->dbh(undef);
- undef $RT::Handle;
-}
-
-require RT::Interface::Web::Handler;
-my $app = RT::Interface::Web::Handler->PSGIApp;
-
-if ($ENV{RT_TESTING}) {
- my $screen_logger = $RT::Logger->remove('screen');
- require Log::Dispatch::Perl;
- $RT::Logger->add(
- Log::Dispatch::Perl->new(
- name => 'rttest',
- min_level => $screen_logger->min_level,
- action => {
- error => 'warn',
- critical => 'warn'
- }
- )
- );
- require Plack::Middleware::Test::StashWarnings;
- $app = Plack::Middleware::Test::StashWarnings->wrap($app);
-}
-
-# when used as a psgi file
-if (caller) {
- return $app;
-}
-
-
-# load appropriate server
-
-require Plack::Runner;
-
-my $is_fastcgi = $0 =~ m/fcgi$/;
-my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) :
- $is_fastcgi ? ( server => 'FCGI' )
- : (),
- env => 'deployment' );
-
-# figure out the port
-my $port;
-
-# handle "rt-server 8888" for back-compat, but complain about it
-if ($ARGV[0] && $ARGV[0] =~ m/^\d+$/) {
- warn "Deprecated: please run $0 --port $ARGV[0] instead\n";
- unshift @ARGV, '--port';
-}
-
-my @args = @ARGV;
-
-use List::MoreUtils 'last_index';
-my $last_index = last_index { $_ eq '--port' } @args;
-
-my $explicit_port;
-
-if ( $last_index != -1 && $args[$last_index+1] =~ /^\d+$/ ) {
- $explicit_port = $args[$last_index+1];
- $port = $explicit_port;
-
- # inform the rest of the system what port we manually chose
- my $old_app = $app;
- $app = sub {
- my $env = shift;
-
- $env->{'rt.explicit_port'} = $port;
-
- $old_app->($env, @_);
- };
-}
-else {
- # default to the configured WebPort and inform Plack::Runner
- $port = RT->Config->Get('WebPort') || '8080';
- push @args, '--port', $port;
-}
-
-push @args, '--server', 'Standalone' if RT->InstallMode;
-push @args, '--server', 'Starlet' unless $r->{server} || grep { m/--server/ } @args;
-
-$r->parse_options(@args);
-
-delete $r->{options} if $is_fastcgi; ### mangle_host_port_socket ruins everything
-
-unless ($r->{env} eq 'development') {
- push @{$r->{options}}, server_ready => sub {
- my($args) = @_;
- my $name = $args->{server_software} || ref($args); # $args is $server
- my $host = $args->{host} || 0;
- my $proto = $args->{proto} || 'http';
- print STDERR "$name: Accepting connections at $proto://$host:$args->{port}/\n";
- };
-}
-eval { $r->run($app) };
-if (my $err = $@) {
- handle_startup_error($err);
-}
-
-exit 0;
-
-sub handle_startup_error {
- my $err = shift;
- if ( $err =~ /listen/ ) {
- handle_bind_error();
- } else {
- die
- "Something went wrong while trying to run RT's standalone web server:\n\t"
- . $err;
- }
-}
-
-
-sub handle_bind_error {
-
- print STDERR <<EOF;
-WARNING: RT couldn't start up a web server on port @{[$port]}.
-This is often the case if the port is already in use or you're running @{[$0]}
-as someone other than your system's "root" user. You may also specify a
-temporary port with: $0 --port <port>
-EOF
-
- if ($explicit_port) {
- print STDERR
- "Please check your system configuration or choose another port\n\n";
- }
-}
-
-__END__
-
-=head1 NAME
-
-rt-server - RT standalone server
-
-=head1 SYNOPSIS
-
- # runs prefork server listening on port 8080, requires Starlet
- rt-server --port 8080
-
- # runs server listening on port 8080
- rt-server --server Standalone --port 8080
- # or
- standalone_httpd --port 8080
-
- # runs other PSGI server on port 8080
- rt-server --server Starman --port 8080
diff --git a/rt/sbin/standalone_httpd.in b/rt/sbin/standalone_httpd.in
index 632ba0b..0d11f01 100644
--- a/rt/sbin/standalone_httpd.in
+++ b/rt/sbin/standalone_httpd.in
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -127,7 +127,7 @@ EOF
RT->InstallMode(1);
} else {
- RT->Init();
+ RT->Init( Heavy => 1 );
my ($status, $msg) = RT::Handle->CheckCompatibility( $RT::Handle->dbh, 'post');
unless ( $status ) {