summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Interface
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Interface')
-rw-r--r--rt/lib/RT/Interface/CLI.pm246
-rwxr-xr-xrt/lib/RT/Interface/Email.pm648
-rwxr-xr-xrt/lib/RT/Interface/Email/Auth/GnuPG.pm123
-rw-r--r--rt/lib/RT/Interface/Email/Auth/MailFrom.pm189
-rw-r--r--rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm96
-rw-r--r--rt/lib/RT/Interface/REST.pm288
-rw-r--r--rt/lib/RT/Interface/Web.pm1377
-rw-r--r--rt/lib/RT/Interface/Web/Handler.pm211
-rw-r--r--rt/lib/RT/Interface/Web/Menu.pm68
-rw-r--r--rt/lib/RT/Interface/Web/Menu/Item.pm86
-rwxr-xr-xrt/lib/RT/Interface/Web/QueryBuilder.pm58
-rwxr-xr-xrt/lib/RT/Interface/Web/QueryBuilder/Tree.pm247
-rwxr-xr-xrt/lib/RT/Interface/Web/Standalone.pm84
-rw-r--r--rt/lib/RT/Interface/Web_Vendor.pm95
14 files changed, 0 insertions, 3816 deletions
diff --git a/rt/lib/RT/Interface/CLI.pm b/rt/lib/RT/Interface/CLI.pm
deleted file mode 100644
index ec0e877..0000000
--- a/rt/lib/RT/Interface/CLI.pm
+++ /dev/null
@@ -1,246 +0,0 @@
-# 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
-use strict;
-
-use RT;
-package RT::Interface::CLI;
-
-
-
-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
-
- @ISA = qw(Exporter);
-
- # your exported package globals go here,
- # as well as any optionally exported functions
- @EXPORT_OK = qw(&CleanEnv
- &GetCurrentUser &GetMessageContent &debug &loc);
-}
-
-=head1 NAME
-
- RT::Interface::CLI - helper functions for creating a commandline RT interface
-
-=head1 SYNOPSIS
-
- use lib "/path/to/rt/libraries/";
-
- use RT::Interface::CLI qw(CleanEnv
- GetCurrentUser GetMessageContent loc);
-
- #Clean out all the nasties from the environment
- CleanEnv();
-
- #let's talk to RT'
- use RT;
-
- #Load RT's config file
- RT::LoadConfig();
-
- # Connect to the database. set up loggign
- RT::Init();
-
- #Get the current user all loaded
- my $CurrentUser = GetCurrentUser();
-
- print loc('Hello!'); # Synonym of $CuurentUser->loc('Hello!');
-
-=head1 DESCRIPTION
-
-
-=head1 METHODS
-
-=begin testing
-
-ok(require RT::Interface::CLI);
-
-=end testing
-
-=cut
-
-
-=head2 CleanEnv
-
-Removes some of the nastiest nasties from the user\'s environment.
-
-=cut
-
-sub CleanEnv {
- $ENV{'PATH'} = '/bin:/usr/bin'; # or whatever you need
- $ENV{'CDPATH'} = '' if defined $ENV{'CDPATH'};
- $ENV{'SHELL'} = '/bin/sh' if defined $ENV{'SHELL'};
- $ENV{'ENV'} = '' if defined $ENV{'ENV'};
- $ENV{'IFS'} = '' if defined $ENV{'IFS'};
-}
-
-
-
-
-{
-
- my $CurrentUser; # shared betwen GetCurrentUser and loc
-
-# {{{ sub GetCurrentUser
-
-=head2 GetCurrentUser
-
- Figures out the uid of the current user and returns an RT::CurrentUser object
-loaded with that user. if the current user isn't found, returns a copy of RT::Nobody.
-
-=cut
-
-sub GetCurrentUser {
-
- require RT::CurrentUser;
-
- #Instantiate a user object
-
- my $Gecos= ($^O eq 'MSWin32') ? Win32::LoginName() : (getpwuid($<))[0];
-
- #If the current user is 0, then RT will assume that the User object
- #is that of the currentuser.
-
- $CurrentUser = new RT::CurrentUser();
- $CurrentUser->LoadByGecos($Gecos);
-
- unless ($CurrentUser->Id) {
- $RT::Logger->debug("No user with a unix login of '$Gecos' was found. ");
- }
-
- return($CurrentUser);
-}
-# }}}
-
-
-# {{{ sub loc
-
-=head2 loc
-
- Synonym of $CurrentUser->loc().
-
-=cut
-
-sub loc {
- die "No current user yet" unless $CurrentUser ||= RT::CurrentUser->new;
- return $CurrentUser->loc(@_);
-}
-# }}}
-
-}
-
-
-# {{{ sub GetMessageContent
-
-=head2 GetMessageContent
-
-Takes two arguments a source file and a boolean "edit". If the source file
-is undef or "", assumes an empty file. Returns an edited file as an
-array of lines.
-
-=cut
-
-sub GetMessageContent {
- my %args = ( Source => undef,
- Content => undef,
- Edit => undef,
- CurrentUser => undef,
- @_);
- my $source = $args{'Source'};
-
- my $edit = $args{'Edit'};
-
- my $currentuser = $args{'CurrentUser'};
- my @lines;
-
- use File::Temp qw/ tempfile/;
-
- #Load the sourcefile, if it's been handed to us
- if ($source) {
- open (SOURCE, "<$source");
- @lines = (<SOURCE>);
- close (SOURCE);
- }
- elsif ($args{'Content'}) {
- @lines = split('\n',$args{'Content'});
- }
- #get us a tempfile.
- my ($fh, $filename) = tempfile();
-
- #write to a tmpfile
- for (@lines) {
- print $fh $_;
- }
- close ($fh);
-
- #Edit the file if we need to
- if ($edit) {
-
- unless ($ENV{'EDITOR'}) {
- $RT::Logger->crit('No $EDITOR variable defined'. "\n");
- return undef;
- }
- system ($ENV{'EDITOR'}, $filename);
- }
-
- open (READ, "<$filename");
- my @newlines = (<READ>);
- close (READ);
-
- unlink ($filename) unless (debug());
- return(\@newlines);
-
-}
-
-# }}}
-
-# {{{ sub debug
-
-sub debug {
- my $val = shift;
- my ($debug);
- if ($val) {
- $RT::Logger->debug($val."\n");
- if ($debug) {
- print STDERR "$val\n";
- }
- }
- if ($debug) {
- return(1);
- }
-}
-
-# }}}
-
-
-eval "require RT::Interface::CLI_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/CLI_Vendor.pm});
-eval "require RT::Interface::CLI_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/CLI_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm
deleted file mode 100755
index 7eec050..0000000
--- a/rt/lib/RT/Interface/Email.pm
+++ /dev/null
@@ -1,648 +0,0 @@
-# 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
-package RT::Interface::Email;
-
-use strict;
-use Mail::Address;
-use MIME::Entity;
-use RT::EmailParser;
-
-
-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
-
- @ISA = qw(Exporter);
-
- # your exported package globals go here,
- # as well as any optionally exported functions
- @EXPORT_OK = qw(
- &CreateUser
- &GetMessageContent
- &CheckForLoops
- &CheckForSuspiciousSender
- &CheckForAutoGenerated
- &MailError
- &ParseCcAddressesFromHead
- &ParseSenderAddressFromHead
- &ParseErrorsToAddressFromHead
- &ParseAddressFromHeader
- &Gateway);
-
-}
-
-=head1 NAME
-
- RT::Interface::CLI - helper functions for creating a commandline RT interface
-
-=head1 SYNOPSIS
-
- use lib "!!RT_LIB_PATH!!";
- use lib "!!RT_ETC_PATH!!";
-
- use RT::Interface::Email qw(Gateway CreateUser);
-
-=head1 DESCRIPTION
-
-
-=begin testing
-
-ok(require RT::Interface::Email);
-
-=end testing
-
-
-=head1 METHODS
-
-=cut
-
-
-# {{{ sub CheckForLoops
-
-sub CheckForLoops {
- my $head = shift;
-
- #If this instance of RT sent it our, we don't want to take it in
- my $RTLoop = $head->get("X-RT-Loop-Prevention") || "";
- chomp ($RTLoop); #remove that newline
- if ($RTLoop eq "$RT::rtname") {
- return (1);
- }
-
- # TODO: We might not trap the case where RT instance A sends a mail
- # to RT instance B which sends a mail to ...
- return (undef);
-}
-
-# }}}
-
-# {{{ sub CheckForSuspiciousSender
-
-sub CheckForSuspiciousSender {
- my $head = shift;
-
- #if it's from a postmaster or mailer daemon, it's likely a bounce.
-
- #TODO: better algorithms needed here - there is no standards for
- #bounces, so it's very difficult to separate them from anything
- #else. At the other hand, the Return-To address is only ment to be
- #used as an error channel, we might want to put up a separate
- #Return-To address which is treated differently.
-
- #TODO: search through the whole email and find the right Ticket ID.
-
- my ($From, $junk) = ParseSenderAddressFromHead($head);
-
- if (($From =~ /^mailer-daemon/i) or
- ($From =~ /^postmaster/i)){
- return (1);
-
- }
-
- return (undef);
-
-}
-
-# }}}
-
-# {{{ sub CheckForAutoGenerated
-sub CheckForAutoGenerated {
- my $head = shift;
-
- my $Precedence = $head->get("Precedence") || "" ;
- if ($Precedence =~ /^(bulk|junk)/i) {
- return (1);
- }
- else {
- return (0);
- }
-}
-
-# }}}
-
-
-# {{{ sub MailError
-sub MailError {
- my %args = (To => $RT::OwnerEmail,
- Bcc => undef,
- From => $RT::CorrespondAddress,
- Subject => 'There has been an error',
- Explanation => 'Unexplained error',
- MIMEObj => undef,
- LogLevel => 'crit',
- @_);
-
-
- $RT::Logger->log(level => $args{'LogLevel'},
- message => $args{'Explanation'}
- );
- my $entity = MIME::Entity->build( Type =>"multipart/mixed",
- From => $args{'From'},
- Bcc => $args{'Bcc'},
- To => $args{'To'},
- Subject => $args{'Subject'},
- 'X-RT-Loop-Prevention' => $RT::rtname,
- );
-
- $entity->attach( Data => $args{'Explanation'}."\n");
-
- my $mimeobj = $args{'MIMEObj'};
- if ($mimeobj) {
- $mimeobj->sync_headers();
- $entity->add_part($mimeobj);
- }
-
- if ($RT::MailCommand eq 'sendmailpipe') {
- open (MAIL, "|$RT::SendmailPath $RT::SendmailArguments") || return(0);
- print MAIL $entity->as_string;
- close(MAIL);
- }
- else {
- $entity->send($RT::MailCommand, $RT::MailParams);
- }
-}
-
-# }}}
-
-# {{{ Create User
-
-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,
- RealName => $Name,
- Password => undef,
- Privileged => 0,
- Comments => 'Autocreated on ticket submission'
- );
-
- unless ($Val) {
-
- # Deal with the race condition of two account creations at once
- #
- if ($Username) {
- $NewUser->LoadByName($Username);
- }
-
- unless ($NewUser->Id) {
- $NewUser->LoadByEmail($Address);
- }
-
- unless ($NewUser->Id) {
- MailError( To => $ErrorsTo,
- Subject => "User could not be created",
- Explanation => "User creation failed in mailgateway: $Message",
- MIMEObj => $entity,
- LogLevel => 'crit'
- );
- }
- }
-
- #Load the new user object
- my $CurrentUser = RT::CurrentUser->new();
- $CurrentUser->LoadByEmail($Address);
-
- unless ($CurrentUser->id) {
- $RT::Logger->warning("Couldn't load user '$Address'.". "giving up");
- MailError( To => $ErrorsTo,
- Subject => "User could not be loaded",
- Explanation => "User '$Address' could not be loaded in the mail gateway",
- MIMEObj => $entity,
- LogLevel => 'crit'
- );
- }
-
- return $CurrentUser;
-}
-# }}}
-# {{{ ParseCcAddressesFromHead
-
-=head2 ParseCcAddressesFromHead HASHREF
-
-Takes a hashref object containing QueueObj, Head and CurrentUser objects.
-Returns a list of all email addresses in the To and Cc
-headers b<except> the current Queue\'s email addresses, the CurrentUser\'s
-email address and anything that the configuration sub RT::IsRTAddress matches.
-
-=cut
-
-sub ParseCcAddressesFromHead {
- my %args = ( Head => undef,
- QueueObj => undef,
- CurrentUser => undef,
- @_ );
-
- my (@Addresses);
-
- my @ToObjs = Mail::Address->parse($args{'Head'}->get('To'));
- my @CcObjs = Mail::Address->parse($args{'Head'}->get('Cc'));
-
- foreach my $AddrObj (@ToObjs, @CcObjs) {
- my $Address = $AddrObj->address;
- $Address = $args{'CurrentUser'}->UserObj->CanonicalizeEmailAddress($Address);
- next if ($args{'CurrentUser'}->EmailAddress =~ /^$Address$/i);
- next if ($args{'QueueObj'}->CorrespondAddress =~ /^$Address$/i);
- next if ($args{'QueueObj'}->CommentAddress =~ /^$Address$/i);
- next if (RT::EmailParser::IsRTAddress(undef, $Address));
-
- push (@Addresses, $Address);
- }
- return (@Addresses);
-}
-
-
-# }}}
-
-# {{{ ParseSenderAdddressFromHead
-
-=head2 ParseSenderAddressFromHead
-
-Takes a MIME::Header object. Returns a tuple: (user@host, friendly name)
-of the From (evaluated in order of Reply-To:, From:, Sender)
-
-=cut
-
-sub ParseSenderAddressFromHead {
- my $head = shift;
- #Figure out who's sending this message.
- my $From = $head->get('Reply-To') ||
- $head->get('From') ||
- $head->get('Sender');
- return (ParseAddressFromHeader($From));
-}
-# }}}
-
-# {{{ ParseErrorsToAdddressFromHead
-
-=head2 ParseErrorsToAddressFromHead
-
-Takes a MIME::Header object. Return a single value : user@host
-of the From (evaluated in order of Errors-To:,Reply-To:, From:, Sender)
-
-=cut
-
-sub ParseErrorsToAddressFromHead {
- my $head = shift;
- #Figure out who's sending this message.
-
- foreach my $header ('Errors-To' , 'Reply-To', 'From', 'Sender' ) {
- # If there's a header of that name
- my $headerobj = $head->get($header);
- if ($headerobj) {
- my ($addr, $name ) = ParseAddressFromHeader($headerobj);
- # If it's got actual useful content...
- return ($addr) if ($addr);
- }
- }
-}
-# }}}
-
-# {{{ ParseAddressFromHeader
-
-=head2 ParseAddressFromHeader ADDRESS
-
-Takes an address from $head->get('Line') and returns a tuple: user@host, friendly name
-
-=cut
-
-
-sub ParseAddressFromHeader{
- my $Addr = shift;
-
- my @Addresses = Mail::Address->parse($Addr);
-
- my $AddrObj = $Addresses[0];
-
- unless (ref($AddrObj)) {
- return(undef,undef);
- }
-
- my $Name = ($AddrObj->phrase || $AddrObj->comment || $AddrObj->address);
-
- #Lets take the from and load a user object.
- my $Address = $AddrObj->address;
-
- return ($Address, $Name);
-}
-# }}}
-
-
-
-=head2 Gateway
-
-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.
-
-=cut
-
-sub Gateway {
- my %args = ( message => undef,
- queue => 1,
- action => 'correspond',
- ticket => undef,
- @_ );
-
- # 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 );
- }
-
- my $parser = RT::EmailParser->new();
- $parser->ParseMIMEEntityFromScalar( $args{'message'} );
-
- my $Message = $parser->Entity();
- my $head = $Message->head;
-
- my ( $CurrentUser, $AuthStat, $status, $error );
-
- my $ErrorsTo = ParseErrorsToAddressFromHead($head);
-
- my $MessageId = $head->get('Message-Id')
- || "<no-message-id-" . time . rand(2000) . "\@.$RT::Organization>";
-
- #Pull apart the subject line
- my $Subject = $head->get('Subject') || '';
- chomp $Subject;
-
-
- $args{'ticket'} ||= $parser->ParseTicketId($Subject);
-
- my $SystemTicket;
- if ($args{'ticket'} ) {
- $SystemTicket = RT::Ticket->new($RT::SystemUser);
- $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 );
- }
-
- # Authentication Level
- # -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;
- # Since this needs loading, no matter what
-
- for (@RT::MailPlugins) {
- my $Code;
- my $NewAuthStat;
- if ( ref($_) eq "CODE" ) {
- $Code = $_;
- }
- else {
- $_ = "RT::Interface::Email::$_" unless /^RT::Interface::Email::/;
- eval "require $_;";
- if ($@) {
- die ("Couldn't load module $_: $@");
- next;
- }
- no strict 'refs';
- if ( !defined( $Code = *{ $_ . "::GetCurrentUser" }{CODE} ) ) {
- die ("No GetCurrentUser code found in $_ module");
- next;
- }
- }
-
- ( $CurrentUser, $NewAuthStat ) = $Code->( Message => $Message,
- CurrentUser => $CurrentUser,
- AuthLevel => $AuthStat,
- Action => $args{'action'},
- Ticket => $SystemTicket,
- Queue => $SystemQueueObj );
-
- # You get the highest level of authentication you were assigned.
- last if $AuthStat == -1;
- $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
- }
-
- # {{{ 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,
-RT could not load a valid user, and RT's configuration does not allow
-for the creation of a new user for your email.
-
-Your RT administrator needs to grant 'Everyone' the right 'CreateTicket'
-for this queue.
-
-EOT
- MIMEObj => $Message,
- LogLevel => 'error' )
- unless $AuthStat == -1;
- return ( 0, "Could not load a valid user", undef );
- }
-
- # }}}
-
- # {{{ Lets check for mail loops of various sorts.
- my $IsAutoGenerated = CheckForAutoGenerated($head);
-
- my $IsSuspiciousSender = CheckForSuspiciousSender($head);
-
- my $IsALoop = CheckForLoops($head);
-
- my $SquelchReplies = 0;
-
- #If the message is autogenerated, we need to know, so we can not
- # send mail to the sender
- if ( $IsSuspiciousSender || $IsAutoGenerated || $IsALoop ) {
- $SquelchReplies = 1;
- $ErrorsTo = $RT::OwnerEmail;
- }
-
- # }}}
-
- # {{{ 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 );
- }
-
- # }}}
- # {{{ Warn someone if it's a loop
-
- # Warn someone if it's a loop, before we drop it on the ground
- if ($IsALoop) {
- $RT::Logger->crit("RT Recieved mail ($MessageId) from itself.");
-
- #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 );
-
- #Do we actually want to store it?
- return ( 0, "Message Bounced", undef ) unless ($RT::StoreLoops);
- }
- }
-
- # }}}
-
- # {{{ 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->delete('RT-Squelch-Replies-To');
- }
-
- if ($SquelchReplies) {
- ## TODO: This is a hack. It should be some other way to
- ## indicate that the transaction should be "silent".
-
- my ( $Sender, $junk ) = ParseSenderAddressFromHead($head);
- $head->add( 'RT-Squelch-Replies-To', $Sender );
- }
-
- # }}}
-
- my $Ticket = RT::Ticket->new($CurrentUser);
-
- # {{{ If we don't have a ticket Id, we're creating a new ticket
- if ( !$args{'ticket'} ) {
-
- # {{{ Create a new ticket
-
- my @Cc;
- my @Requestors = ( $CurrentUser->id );
-
- if ($RT::ParseNewMessageForTicketCcs) {
- @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 );
- if ( $id == 0 ) {
- 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 );
- }
-
- # }}}
- }
-
- # }}}
-
- # If the action is comment, add a comment.
- elsif ( $args{'action'} =~ /^(comment|correspond)$/i ) {
- $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 ( $status, $msg );
- if ( $args{'action'} =~ /^correspond$/ ) {
- ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message );
- }
- else {
- ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message );
- }
- unless ($status) {
-
- #Warn the sender that we couldn't actually submit the comment.
- MailError( To => $ErrorsTo,
- Subject => "Message not recorded",
- Explanation => $msg,
- MIMEObj => $Message );
- return ( 0, "Message not recorded", $Ticket );
- }
- }
-
- 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 );
- $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
- return ( 0, "Configuration error: " . $args{'action'} . " not a recognized action", $Ticket );
-
- }
-
-
-return ( 1, "Success", $Ticket );
-}
-
-eval "require RT::Interface::Email_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Vendor.pm});
-eval "require RT::Interface::Email_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/Email/Auth/GnuPG.pm b/rt/lib/RT/Interface/Email/Auth/GnuPG.pm
deleted file mode 100755
index 1150807..0000000
--- a/rt/lib/RT/Interface/Email/Auth/GnuPG.pm
+++ /dev/null
@@ -1,123 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-#
-package RT::Interface::Email::Auth::GnuPG;
-use Mail::GnuPG;
-
-=head2 GetCurrentUser
-
-To use the gnupg-secured mail gateway, you need to do the following:
-
-Set up a gnupgp key directory with a pubring containing only the keys
-you care about and specify the following in your SiteConfig.pm
-
-Set($RT::GPGKeyDir, "/path/to/keyring-directory");
-@RT::MailPlugins = qw(Auth::MailFrom Auth::GnuPG Filter::TakeAction);
-
-
-
-=cut
-
-
-
-sub GetCurrentUser {
- my %args = (
- Message => undef,
- RawMessageRef => undef,
- CurrentUser => undef,
- AuthLevel => undef,
- Ticket => undef,
- Queue => undef,
- Action => undef,
- @_
- );
-
- my ( $val, $key, $address,$gpg );
-
- eval {
-
- my $parser = RT::EmailParser->new();
- $parser->SmartParseMIMEEntityFromScalar(Message => ${$args{'RawMessageRef'}}, Decode => 0);
- $gpg = Mail::GnuPG->new( keydir => $RT::GPGKeyDir );
- my $entity = $parser->Entity;
- ( $val, $key, $address ) = $gpg->verify( $parser->Entity);
- $RT::Logger->crit("Got $val - $key - $address");
- };
-
- if ($@) {
- $RT::Logger->crit($@);
- }
-
- unless ($address) {
- $RT::Logger->crit( "Couldn't find a valid signature" . join ( "\n", @{ $gpg->{'last_message'} } ) );
- return ( $args{'CurrentUser'}, $args{'AuthLevel'} );
- }
-
- my @addrs = Mail::Address->parse($address);
- $address = $addrs[0]->address();
-
- my $CurrentUser = RT::CurrentUser->new();
- $CurrentUser->LoadByEmail($address);
-
- if ( $CurrentUser->Id ) {
- $RT::Logger->crit($address . " authenticated via PGP signature");
- return ( $CurrentUser, 2 );
- }
-
-}
-
-eval "require RT::Interface::Email::Auth::GnuPG_Vendor";
-die $@
- if ( $@
- && $@ !~ qr{^Can't locate RT/Interface/Email/Auth/GnuPG_Vendor.pm} );
-eval "require RT::Interface::Email::Auth::GnuPG_Local";
-die $@
- if ( $@
- && $@ !~ qr{^Can't locate RT/Interface/Email/Auth/GnuPG_Local.pm} );
-
-1;
diff --git a/rt/lib/RT/Interface/Email/Auth/MailFrom.pm b/rt/lib/RT/Interface/Email/Auth/MailFrom.pm
deleted file mode 100644
index 32009c3..0000000
--- a/rt/lib/RT/Interface/Email/Auth/MailFrom.pm
+++ /dev/null
@@ -1,189 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Email::Auth::MailFrom;
-use RT::Interface::Email qw(ParseSenderAddressFromHead CreateUser);
-
-# This is what the ordinary, non-enhanced gateway does at the moment.
-
-sub GetCurrentUser {
- my %args = ( Message => undef,
- CurrentUser => undef,
- AuthLevel => undef,
- Ticket => undef,
- Queue => undef,
- Action => undef,
- @_ );
-
-
- # We don't need to do any external lookups
- my ( $Address, $Name ) = ParseSenderAddressFromHead( $args{'Message'}->head );
-
- unless ($Address) {
- return ( $args{'CurrentUser'}, -1 );
- }
-
- my $CurrentUser = RT::CurrentUser->new();
- $CurrentUser->LoadByEmail($Address);
-
- unless ( $CurrentUser->Id ) {
- $CurrentUser->LoadByName($Address);
- }
-
- if ( $CurrentUser->Id ) {
- return ( $CurrentUser, 1 );
- }
-
-
-
- # If the user can't be loaded, we may need to create one. Figure out the acl situation.
- my $unpriv = RT::Group->new($RT::SystemUser);
- $unpriv->LoadSystemInternalGroup('Unprivileged');
- unless ( $unpriv->Id ) {
- $RT::Logger->crit( "Auth::MailFrom couldn't find the 'Unprivileged' internal group" );
- return ( $args{'CurrentUser'}, -1 );
- }
-
- my $everyone = RT::Group->new($RT::SystemUser);
- $everyone->LoadSystemInternalGroup('Everyone');
- unless ( $everyone->Id ) {
- $RT::Logger->crit( "Auth::MailFrom couldn't find the 'Everyone' internal group");
- return ( $args{'CurrentUser'}, -1 );
- }
-
- # but before we do that, we need to make sure that the created user would have the right
- # to do what we're doing.
- if ( $args{'Ticket'} && $args{'Ticket'}->Id ) {
- # We have a ticket. that means we're commenting or corresponding
- if ( $args{'Action'} =~ /^comment$/i ) {
-
- # check to see whether "Everyone" or "Unprivileged users" can comment on tickets
- unless ( $everyone->PrincipalObj->HasRight(
- Object => $args{'Queue'},
- Right => 'CommentOnTicket'
- )
- || $unpriv->PrincipalObj->HasRight(
- Object => $args{'Queue'},
- Right => 'CommentOnTicket'
- )
- ) {
- return ( $args{'CurrentUser'}, 0 );
- }
- }
- elsif ( $args{'Action'} =~ /^correspond$/i ) {
-
- # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets
- unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'},
- Right => 'ReplyToTicket'
- )
- || $unpriv->PrincipalObj->HasRight(
- Object => $args{'Queue'},
- Right => 'ReplyToTicket'
- )
- ) {
- return ( $args{'CurrentUser'}, 0 );
- }
-
- }
- elsif ( $args{'Action'} =~ /^take$/i ) {
-
- # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets
- unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'},
- Right => 'OwnTicket'
- )
- || $unpriv->PrincipalObj->HasRight(
- Object => $args{'Queue'},
- Right => 'OwnTicket'
- )
- ) {
- return ( $args{'CurrentUser'}, 0 );
- }
-
- }
- elsif ( $args{'Action'} =~ /^resolve$/i ) {
-
- # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets
- unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'},
- Right => 'ModifyTicket'
- )
- || $unpriv->PrincipalObj->HasRight(
- Object => $args{'Queue'},
- Right => 'ModifyTicket'
- )
- ) {
- return ( $args{'CurrentUser'}, 0 );
- }
-
- }
- else {
- return ( $args{'CurrentUser'}, 0 );
- }
- }
-
- # We're creating a ticket
- elsif ( $args{'Queue'} && $args{'Queue'}->Id ) {
-
- # check to see whether "Everybody" or "Unprivileged users" can create tickets in this queue
- unless ( $everyone->PrincipalObj->HasRight( Object => $args{'Queue'},
- Right => 'CreateTicket' )
- ) {
- return ( $args{'CurrentUser'}, 0 );
- }
-
- }
-
- $CurrentUser = CreateUser( undef, $Address, $Name, $Address, $args{'Message'} );
-
- return ( $CurrentUser, 1 );
-}
-
-eval "require RT::Interface::Email::Auth::MailFrom_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email/Auth/MailFrom_Vendor.pm});
-eval "require RT::Interface::Email::Auth::MailFrom_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email/Auth/MailFrom_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm b/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm
deleted file mode 100644
index 2f8b61c..0000000
--- a/rt/lib/RT/Interface/Email/Filter/SpamAssassin.pm
+++ /dev/null
@@ -1,96 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Email::Filter::SpamAssassin;
-
-use Mail::SpamAssassin;
-my $spamtest = Mail::SpamAssassin->new();
-
-sub GetCurrentUser {
- my %args = (
- Message => undef,
- CurrentUser => undef,
- AuthLevel => undef,
- @_
- );
- my $status = $spamtest->check( $args{'Message'} );
- return ( $args{'CurrentUser'}, $args{'AuthLevel'} )
- unless $status->is_spam();
-
- eval { $status->rewrite_mail() };
- if ( $status->get_hits > $status->get_required_hits() * 1.5 ) {
-
- # Spammy indeed
- return ( $args{'CurrentUser'}, -1 );
- }
- return ( $args{'CurrentUser'}, $args{'AuthLevel'} );
-
-}
-
-=head1 NAME
-
-RT::Interface::Email::Filter::SpamAssassin - Spam filter for RT
-
-=head1 SYNOPSIS
-
- @RT::MailPlugins = ("Filter::SpamAssassin", ...);
-
-=head1 DESCRIPTION
-
-This plugin checks to see if an incoming mail is spam (using
-C<spamassassin>) and if so, rewrites its headers. If the mail is very
-definitely spam - 1.5x more hits than required - then it is dropped on
-the floor; otherwise, it is passed on as normal.
-
-=cut
-
-eval "require RT::Interface::Email::Filter::SpamAssassin_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email/Filter/SpamAssassin_Vendor.pm});
-eval "require RT::Interface::Email::Filter::SpamAssassin_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email/Filter/SpamAssassin_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/REST.pm b/rt/lib/RT/Interface/REST.pm
deleted file mode 100644
index bb2bf24..0000000
--- a/rt/lib/RT/Interface/REST.pm
+++ /dev/null
@@ -1,288 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-# lib/RT/Interface/REST.pm
-#
-
-package RT::Interface::REST;
-use strict;
-use RT;
-
-BEGIN {
- use Exporter ();
- use vars qw($VERSION @ISA @EXPORT);
-
- $VERSION = do { my @r = (q$Revision: 1.1.1.6 $ =~ /\d+/g); sprintf "%d."."%02d"x$#r, @r };
-
- @ISA = qw(Exporter);
- @EXPORT = qw(expand_list form_parse form_compose vpush vsplit);
-}
-
-my $field = '(?i:[a-z][a-z0-9_-]*|C(?:ustom)?F(?:ield)?-(?:[a-z0-9_ -]|\s)+)';
-
-# WARN: this code is duplicated in bin/rt.in,
-# change both functions at once
-sub expand_list {
- my ($list) = @_;
-
- my @elts;
- foreach (split /,/, $list) {
- push @elts, /^(\d+)-(\d+)$/? ($1..$2): $_;
- }
-
- return map $_->[0], # schwartzian transform
- sort {
- defined $a->[1] && defined $b->[1]?
- # both numbers
- $a->[1] <=> $b->[1]
- :!defined $a->[1] && !defined $b->[1]?
- # both letters
- $a->[2] cmp $b->[2]
- # mix, number must be first
- :defined $a->[1]? -1: 1
- }
- map [ $_, (defined( /^(\d+)$/ )? $1: undef), lc($_) ],
- @elts;
-}
-
-# Returns a reference to an array of parsed forms.
-sub form_parse {
- my $state = 0;
- my @forms = ();
- my @lines = split /\n/, $_[0];
- my ($c, $o, $k, $e) = ("", [], {}, "");
-
- LINE:
- while (@lines) {
- my $line = shift @lines;
-
- next LINE if $line eq '';
-
- if ($line eq '--') {
- # We reached the end of one form. We'll ignore it if it was
- # empty, and store it otherwise, errors and all.
- if ($e || $c || @$o) {
- push @forms, [ $c, $o, $k, $e ];
- $c = ""; $o = []; $k = {}; $e = "";
- }
- $state = 0;
- }
- elsif ($state != -1) {
- if ($state == 0 && $line =~ /^#/) {
- # Read an optional block of comments (only) at the start
- # of the form.
- $state = 1;
- $c = $line;
- while (@lines && $lines[0] =~ /^#/) {
- $c .= "\n".shift @lines;
- }
- $c .= "\n";
- }
- elsif ($state <= 1 && $line =~ /^($field):(?:\s+(.*))?$/i) {
- # Read a field: value specification.
- my $f = $1;
- my @v = ($2 || ());
-
- # Read continuation lines, if any.
- while (@lines && ($lines[0] eq '' || $lines[0] =~ /^\s+/)) {
- push @v, shift @lines;
- }
- pop @v while (@v && $v[-1] eq '');
-
- # Strip longest common leading indent from text.
- my ($ws, $ls) = ("");
- foreach $ls (map {/^(\s+)/} @v[1..$#v]) {
- $ws = $ls if (!$ws || length($ls) < length($ws));
- }
- s/^$ws// foreach @v;
-
- push(@$o, $f) unless exists $k->{$f};
- vpush($k, $f, join("\n", @v));
-
- $state = 1;
- }
- elsif ($line !~ /^#/) {
- # We've found a syntax error, so we'll reconstruct the
- # form parsed thus far, and add an error marker. (>>)
- $state = -1;
- $e = form_compose([[ "", $o, $k, "" ]]);
- $e.= $line =~ /^>>/ ? "$line\n" : ">> $line\n";
- }
- }
- else {
- # We saw a syntax error earlier, so we'll accumulate the
- # contents of this form until the end.
- $e .= "$line\n";
- }
- }
- push(@forms, [ $c, $o, $k, $e ]) if ($e || $c || @$o);
-
- my $l;
- foreach $l (keys %$k) {
- $k->{$l} = vsplit($k->{$l}) if (ref $k->{$l} eq 'ARRAY');
- }
-
- return \@forms;
-}
-
-# Returns text representing a set of forms.
-sub form_compose {
- my ($forms) = @_;
- my (@text, $form);
-
- foreach $form (@$forms) {
- my ($c, $o, $k, $e) = @$form;
- my $text = "";
-
- if ($c) {
- $c =~ s/\n*$/\n/;
- $text = "$c\n";
- }
- if ($e) {
- $text .= $e;
- }
- elsif ($o) {
- my (@lines, $key);
-
- foreach $key (@$o) {
- my ($line, $sp, $v);
- my @values = (ref $k->{$key} eq 'ARRAY') ?
- @{ $k->{$key} } :
- $k->{$key};
-
- $sp = " "x(length("$key: "));
- $sp = " "x4 if length($sp) > 16;
-
- foreach $v (@values) {
- if ($v =~ /\n/) {
- $v =~ s/^/$sp/gm;
- $v =~ s/^$sp//;
-
- if ($line) {
- push @lines, "$line\n\n";
- $line = "";
- }
- elsif (@lines && $lines[-1] !~ /\n\n$/) {
- $lines[-1] .= "\n";
- }
- push @lines, "$key: $v\n\n";
- }
- elsif ($line &&
- length($line)+length($v)-rindex($line, "\n") >= 70)
- {
- $line .= ",\n$sp$v";
- }
- else {
- $line = $line ? "$line, $v" : "$key: $v";
- }
- }
-
- $line = "$key:" unless @values;
- if ($line) {
- if ($line =~ /\n/) {
- if (@lines && $lines[-1] !~ /\n\n$/) {
- $lines[-1] .= "\n";
- }
- $line .= "\n";
- }
- push @lines, "$line\n";
- }
- }
-
- $text .= join "", @lines;
- }
- else {
- chomp $text;
- }
- push @text, $text;
- }
-
- return join "\n--\n\n", @text;
-}
-
-# Add a value to a (possibly multi-valued) hash key.
-sub vpush {
- my ($hash, $key, $val) = @_;
- my @val = ref $val eq 'ARRAY' ? @$val : $val;
-
- if (exists $hash->{$key}) {
- unless (ref $hash->{$key} eq 'ARRAY') {
- my @v = $hash->{$key} ne '' ? $hash->{$key} : ();
- $hash->{$key} = \@v;
- }
- push @{ $hash->{$key} }, @val;
- }
- else {
- $hash->{$key} = $val;
- }
-}
-
-# "Normalise" a hash key that's known to be multi-valued.
-sub vsplit {
- my ($val) = @_;
- my ($line, $word, @words);
-
- foreach $line (map {split /\n/} (ref $val eq 'ARRAY') ? @$val : $val)
- {
- # XXX: This should become a real parser, à la Text::ParseWords.
- $line =~ s/^\s+//;
- $line =~ s/\s+$//;
- push @words, split /\s*,\s*/, $line;
- }
-
- return \@words;
-}
-
-1;
-
-=head1 NAME
-
- RT::Interface::REST - helper functions for the REST interface.
-
-=head1 SYNOPSIS
-
- Only the REST should use this module.
diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm
deleted file mode 100644
index 5097f54..0000000
--- a/rt/lib/RT/Interface/Web.pm
+++ /dev/null
@@ -1,1377 +0,0 @@
-# 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
-## Portions Copyright 2000 Tobias Brox <tobix@fsck.com>
-
-## This is a library of static subs to be used by the Mason web
-## interface to RT
-
-
-=head1 NAME
-
-RT::Interface::Web
-
-=begin testing
-
-use_ok(RT::Interface::Web);
-
-=end testing
-
-=cut
-
-
-package RT::Interface::Web;
-use strict;
-
-
-
-
-
-# {{{ sub NewApacheHandler
-
-=head2 NewApacheHandler
-
- Takes extra options to pass to HTML::Mason::ApacheHandler->new
- Returns a new Mason::ApacheHandler object
-
-=cut
-
-sub NewApacheHandler {
- require HTML::Mason::ApacheHandler;
- my $ah = new HTML::Mason::ApacheHandler(
-
- comp_root => [
- [ local => $RT::MasonLocalComponentRoot ],
- [ standard => $RT::MasonComponentRoot ]
- ],
- args_method => "CGI",
- default_escape_flags => 'h',
- allow_globals => [qw(%session)],
- data_dir => "$RT::MasonDataDir",
- @_
- );
-
- $ah->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 );
-
- return ($ah);
-}
-
-# }}}
-
-# {{{ sub NewCGIHandler
-
-=head2 NewCGIHandler
-
- Returns a new Mason::CGIHandler object
-
-=cut
-
-sub NewCGIHandler {
- my %args = (
- @_
- );
-
- my $handler = HTML::Mason::CGIHandler->new(
- comp_root => [
- [ local => $RT::MasonLocalComponentRoot ],
- [ standard => $RT::MasonComponentRoot ]
- ],
- data_dir => "$RT::MasonDataDir",
- default_escape_flags => 'h',
- allow_globals => [qw(%session)]
- );
-
-
- $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 );
-
-
- return ($handler);
-
-}
-# }}}
-
-
-# {{{ EscapeUTF8
-
-=head2 EscapeUTF8 SCALARREF
-
-does a css-busting but minimalist escaping of whatever html you're passing in.
-
-=cut
-
-sub EscapeUTF8 {
- my $ref = shift;
- my $val = $$ref;
- use bytes;
- $val =~ s/&/&#38;/g;
- $val =~ s/</&lt;/g;
- $val =~ s/>/&gt;/g;
- $val =~ s/\(/&#40;/g;
- $val =~ s/\)/&#41;/g;
- $val =~ s/"/&#34;/g;
- $val =~ s/'/&#39;/g;
- $$ref = $val;
- Encode::_utf8_on($$ref);
-
-}
-
-# }}}
-
-
-package HTML::Mason::Commands;
-use strict;
-use vars qw/$r $m %session/;
-
-
-# {{{ loc
-
-=head2 loc ARRAY
-
-loc is a nice clean global routine which calls $session{'CurrentUser'}->loc()
-with whatever it's called with. If there is no $session{'CurrentUser'},
-it creates a temporary user, so we have something to get a localisation handle
-through
-
-=cut
-
-sub loc {
-
- if ($session{'CurrentUser'} &&
- UNIVERSAL::can($session{'CurrentUser'}, 'loc')){
- return($session{'CurrentUser'}->loc(@_));
- }
- else {
- my $u = RT::CurrentUser->new($RT::SystemUser);
- return ($u->loc(@_));
- }
-}
-
-# }}}
-
-
-# {{{ loc_fuzzy
-
-=head2 loc_fuzzy STRING
-
-loc_fuzzy is for handling localizations of messages that may already
-contain interpolated variables, typically returned from libraries
-outside RT's control. It takes the message string and extracts the
-variable array automatically by matching against the candidate entries
-inside the lexicon file.
-
-=cut
-
-sub loc_fuzzy {
- my $msg = shift;
-
- if ($session{'CurrentUser'} &&
- UNIVERSAL::can($session{'CurrentUser'}, 'loc')){
- return($session{'CurrentUser'}->loc_fuzzy($msg));
- }
- else {
- my $u = RT::CurrentUser->new($RT::SystemUser);
- return ($u->loc_fuzzy($msg));
- }
-}
-
-# }}}
-
-
-# {{{ sub Abort
-# Error - calls Error and aborts
-sub Abort {
-
- if ($session{'ErrorDocument'} &&
- $session{'ErrorDocumentType'}) {
- $r->content_type($session{'ErrorDocumentType'});
- $m->comp($session{'ErrorDocument'} , Why => shift);
- $m->abort;
- }
- else {
- $m->comp("/Elements/Error" , Why => shift);
- $m->abort;
- }
-}
-
-# }}}
-
-# {{{ sub CreateTicket
-
-=head2 CreateTicket ARGS
-
-Create a new ticket, using Mason's %ARGS. returns @results.
-
-=cut
-
-sub CreateTicket {
- my %ARGS = (@_);
-
- my (@Actions);
-
- my $Ticket = new RT::Ticket( $session{'CurrentUser'} );
-
- my $Queue = new RT::Queue( $session{'CurrentUser'} );
- unless ( $Queue->Load( $ARGS{'Queue'} ) ) {
- Abort('Queue not found');
- }
-
- unless ( $Queue->CurrentUserHasRight('CreateTicket') ) {
- Abort('You have no permission to create tickets in that queue.');
- }
-
- my $due = new RT::Date( $session{'CurrentUser'} );
- $due->Set( Format => 'unknown', Value => $ARGS{'Due'} );
- my $starts = new RT::Date( $session{'CurrentUser'} );
- $starts->Set( Format => 'unknown', Value => $ARGS{'Starts'} );
-
- my @Requestors = split ( /\s*,\s*/, $ARGS{'Requestors'} );
- my @Cc = split ( /\s*,\s*/, $ARGS{'Cc'} );
- my @AdminCc = split ( /\s*,\s*/, $ARGS{'AdminCc'} );
-
- my $MIMEObj = MakeMIMEEntity(
- Subject => $ARGS{'Subject'},
- From => $ARGS{'From'},
- Cc => $ARGS{'Cc'},
- Body => $ARGS{'Content'},
- );
-
- if ($ARGS{'Attachments'}) {
- $MIMEObj->make_multipart;
- $MIMEObj->add_part($_) foreach values %{$ARGS{'Attachments'}};
- }
-
- my %create_args = (
- Queue => $ARGS{'Queue'},
- Owner => $ARGS{'Owner'},
- InitialPriority => $ARGS{'InitialPriority'},
- FinalPriority => $ARGS{'FinalPriority'},
- TimeLeft => $ARGS{'TimeLeft'},
- TimeEstimated => $ARGS{'TimeEstimated'},
- TimeWorked => $ARGS{'TimeWorked'},
- Requestor => \@Requestors,
- Cc => \@Cc,
- AdminCc => \@AdminCc,
- Subject => $ARGS{'Subject'},
- Status => $ARGS{'Status'},
- Due => $due->ISO,
- Starts => $starts->ISO,
- MIMEObj => $MIMEObj
- );
- foreach my $arg (%ARGS) {
- if ($arg =~ /^CustomField-(\d+)(.*?)$/) {
- next if ($arg =~ /-Magic$/);
- $create_args{"CustomField-".$1} = $ARGS{"$arg"};
- }
- }
- my ( $id, $Trans, $ErrMsg ) = $Ticket->Create(%create_args);
- unless ( $id && $Trans ) {
- Abort($ErrMsg);
- }
- my @linktypes = qw( DependsOn MemberOf RefersTo );
-
- foreach my $linktype (@linktypes) {
- foreach my $luri ( split ( / /, $ARGS{"new-$linktype"} ) ) {
- $luri =~ s/\s*$//; # Strip trailing whitespace
- my ( $val, $msg ) = $Ticket->AddLink(
- Target => $luri,
- Type => $linktype
- );
- push ( @Actions, $msg ) unless ($val);
- }
-
- foreach my $luri ( split ( / /, $ARGS{"$linktype-new"} ) ) {
- my ( $val, $msg ) = $Ticket->AddLink(
- Base => $luri,
- Type => $linktype
- );
-
- push ( @Actions, $msg ) unless ($val);
- }
- }
-
- push ( @Actions, split("\n", $ErrMsg) );
- unless ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
- Abort( "No permission to view newly created ticket #"
- . $Ticket->id . "." );
- }
- return ( $Ticket, @Actions );
-
-}
-
-# }}}
-
-# {{{ sub LoadTicket - loads a ticket
-
-=head2 LoadTicket id
-
-Takes a ticket id as its only variable. if it's handed an array, it takes
-the first value.
-
-Returns an RT::Ticket object as the current user.
-
-=cut
-
-sub LoadTicket {
- my $id = shift;
-
- if ( ref($id) eq "ARRAY" ) {
- $id = $id->[0];
- }
-
- unless ($id) {
- Abort("No ticket specified");
- }
-
- my $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
- $Ticket->Load($id);
- unless ( $Ticket->id ) {
- Abort("Could not load ticket $id");
- }
- return $Ticket;
-}
-
-# }}}
-
-# {{{ sub ProcessUpdateMessage
-
-sub ProcessUpdateMessage {
-
- #TODO document what else this takes.
- my %args = (
- ARGSRef => undef,
- Actions => undef,
- TicketObj => undef,
- @_
- );
-
- #Make the update content have no 'weird' newlines in it
- if ( $args{ARGSRef}->{'UpdateContent'} ) {
-
- if (
- $args{ARGSRef}->{'UpdateSubject'} eq $args{'TicketObj'}->Subject() )
- {
- $args{ARGSRef}->{'UpdateSubject'} = undef;
- }
-
- my $Message = MakeMIMEEntity(
- Subject => $args{ARGSRef}->{'UpdateSubject'},
- Body => $args{ARGSRef}->{'UpdateContent'},
- );
-
- if ($args{ARGSRef}->{'UpdateAttachments'}) {
- $Message->make_multipart;
- $Message->add_part($_) foreach values %{$args{ARGSRef}->{'UpdateAttachments'}};
- }
-
- ## TODO: Implement public comments
- if ( $args{ARGSRef}->{'UpdateType'} =~ /^(private|public)$/ ) {
- my ( $Transaction, $Description ) = $args{TicketObj}->Comment(
- CcMessageTo => $args{ARGSRef}->{'UpdateCc'},
- BccMessageTo => $args{ARGSRef}->{'UpdateBcc'},
- MIMEObj => $Message,
- TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
- );
- push ( @{ $args{Actions} }, $Description );
- }
- elsif ( $args{ARGSRef}->{'UpdateType'} eq 'response' ) {
- my ( $Transaction, $Description ) = $args{TicketObj}->Correspond(
- CcMessageTo => $args{ARGSRef}->{'UpdateCc'},
- BccMessageTo => $args{ARGSRef}->{'UpdateBcc'},
- MIMEObj => $Message,
- TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
- );
- push ( @{ $args{Actions} }, $Description );
- }
- else {
- push ( @{ $args{'Actions'} },
- loc("Update type was neither correspondence nor comment.").
- " ".
- loc("Update not recorded.")
- );
- }
- }
-}
-
-# }}}
-
-# {{{ sub MakeMIMEEntity
-
-=head2 MakeMIMEEntity PARAMHASH
-
-Takes a paramhash Subject, Body and AttachmentFieldName.
-
- Returns a MIME::Entity.
-
-=cut
-
-sub MakeMIMEEntity {
-
- #TODO document what else this takes.
- my %args = (
- Subject => undef,
- From => undef,
- Cc => undef,
- Body => undef,
- AttachmentFieldName => undef,
- map Encode::encode_utf8($_), @_,
- );
-
- #Make the update content have no 'weird' newlines in it
-
- $args{'Body'} =~ s/\r\n/\n/gs;
- my $Message;
- {
- # MIME::Head is not happy in utf-8 domain. This only happens
- # when processing an incoming email (so far observed).
- no utf8;
- use bytes;
- $Message = MIME::Entity->build(
- Subject => $args{'Subject'} || "",
- From => $args{'From'},
- Cc => $args{'Cc'},
- Data => [ $args{'Body'} ]
- );
- }
-
- my $cgi_object = $m->cgi_object;
-
- if (my $filehandle = $cgi_object->upload( $args{'AttachmentFieldName'} ) ) {
-
-
-
- use File::Temp qw(tempfile tempdir);
-
- #foreach my $filehandle (@filenames) {
-
- my ( $fh, $temp_file ) = tempfile();
-
- binmode $fh; #thank you, windows
- my ($buffer);
- while ( my $bytesread = read( $filehandle, $buffer, 4096 ) ) {
- print $fh $buffer;
- }
-
- my $uploadinfo = $cgi_object->uploadInfo($filehandle);
-
- # Prefer the cached name first over CGI.pm stringification.
- my $filename = $RT::Mason::CGI::Filename;
- $filename = "$filehandle" unless defined($filename);
-
- $filename =~ s#^.*[\\/]##;
-
- $Message->attach(
- Path => $temp_file,
- Filename => $filename,
- Type => $uploadinfo->{'Content-Type'},
- );
- close($fh);
-
- # }
-
- }
-
- $Message->make_singlepart();
- RT::I18N::SetMIMEEntityToUTF8($Message); # convert text parts into utf-8
-
- return ($Message);
-
-}
-
-# }}}
-
-# {{{ sub ProcessSearchQuery
-
-=head2 ProcessSearchQuery
-
- Takes a form such as the one filled out in webrt/Search/Elements/PickRestriction and turns it into something that RT::Tickets can understand.
-
-TODO Doc exactly what comes in the paramhash
-
-
-=cut
-
-sub ProcessSearchQuery {
- my %args = @_;
-
- ## TODO: The only parameter here is %ARGS. Maybe it would be
- ## cleaner to load this parameter as $ARGS, and use $ARGS->{...}
- ## instead of $args{ARGS}->{...} ? :)
-
- #Searches are sticky.
- if ( defined $session{'tickets'} ) {
-
- # Reset the old search
- $session{'tickets'}->GotoFirstItem;
- }
- else {
-
- # Init a new search
- $session{'tickets'} = RT::Tickets->new( $session{'CurrentUser'} );
- }
-
- #Import a bookmarked search if we have one
- if ( defined $args{ARGS}->{'Bookmark'} ) {
- $session{'tickets'}->ThawLimits( $args{ARGS}->{'Bookmark'} );
- }
-
- # {{{ Goto next/prev page
- if ( $args{ARGS}->{'GotoPage'} eq 'Next' ) {
- $session{'tickets'}->NextPage;
- }
- elsif ( $args{ARGS}->{'GotoPage'} eq 'Prev' ) {
- $session{'tickets'}->PrevPage;
- }
- elsif ( $args{ARGS}->{'GotoPage'} > 0 ) {
- $session{'tickets'}->GotoPage( $args{ARGS}->{GotoPage} - 1 );
- }
-
- # }}}
-
- # {{{ Deal with limiting the search
-
- if ( $args{ARGS}->{'RefreshSearchInterval'} ) {
- $session{'tickets_refresh_interval'} =
- $args{ARGS}->{'RefreshSearchInterval'};
- }
-
- if ( $args{ARGS}->{'TicketsSortBy'} ) {
- $session{'tickets_sort_by'} = $args{ARGS}->{'TicketsSortBy'};
- $session{'tickets_sort_order'} = $args{ARGS}->{'TicketsSortOrder'};
- $session{'tickets'}->OrderBy(
- FIELD => $args{ARGS}->{'TicketsSortBy'},
- ORDER => $args{ARGS}->{'TicketsSortOrder'}
- );
- }
-
- # }}}
-
- # {{{ Set the query limit
- if ( defined $args{ARGS}->{'RowsPerPage'} ) {
- $RT::Logger->debug(
- "limiting to " . $args{ARGS}->{'RowsPerPage'} . " rows" );
-
- $session{'tickets_rows_per_page'} = $args{ARGS}->{'RowsPerPage'};
- $session{'tickets'}->RowsPerPage( $args{ARGS}->{'RowsPerPage'} );
- }
-
- # }}}
- # {{{ Limit priority
- if ( $args{ARGS}->{'ValueOfPriority'} ne '' ) {
- $session{'tickets'}->LimitPriority(
- VALUE => $args{ARGS}->{'ValueOfPriority'},
- OPERATOR => $args{ARGS}->{'PriorityOp'}
- );
- }
-
- # }}}
- # {{{ Limit owner
- if ( $args{ARGS}->{'ValueOfOwner'} ne '' ) {
- $session{'tickets'}->LimitOwner(
- VALUE => $args{ARGS}->{'ValueOfOwner'},
- OPERATOR => $args{ARGS}->{'OwnerOp'}
- );
- }
-
- # }}}
- # {{{ Limit requestor email
-
- if ( $args{ARGS}->{'ValueOfRequestor'} ne '' ) {
- my $alias = $session{'tickets'}->LimitRequestor(
- VALUE => $args{ARGS}->{'ValueOfRequestor'},
- OPERATOR => $args{ARGS}->{'RequestorOp'},
- );
-
- }
-
- # }}}
- # {{{ Limit Queue
- if ( $args{ARGS}->{'ValueOfQueue'} ne '' ) {
- $session{'tickets'}->LimitQueue(
- VALUE => $args{ARGS}->{'ValueOfQueue'},
- OPERATOR => $args{ARGS}->{'QueueOp'}
- );
- }
-
- # }}}
- # {{{ Limit Status
- if ( $args{ARGS}->{'ValueOfStatus'} ne '' ) {
- if ( ref( $args{ARGS}->{'ValueOfStatus'} ) ) {
- foreach my $value ( @{ $args{ARGS}->{'ValueOfStatus'} } ) {
- $session{'tickets'}->LimitStatus(
- VALUE => $value,
- OPERATOR => $args{ARGS}->{'StatusOp'},
- );
- }
- }
- else {
- $session{'tickets'}->LimitStatus(
- VALUE => $args{ARGS}->{'ValueOfStatus'},
- OPERATOR => $args{ARGS}->{'StatusOp'},
- );
- }
-
- }
-
- # }}}
- # {{{ Limit Subject
- if ( $args{ARGS}->{'ValueOfSubject'} ne '' ) {
- my $val = $args{ARGS}->{'ValueOfSubject'};
- if ($args{ARGS}->{'SubjectOp'} =~ /like/) {
- $val = "%".$val."%";
- }
- $session{'tickets'}->LimitSubject(
- VALUE => $val,
- OPERATOR => $args{ARGS}->{'SubjectOp'},
- );
- }
-
- # }}}
- # {{{ Limit Dates
- if ( $args{ARGS}->{'ValueOfDate'} ne '' ) {
- my $date = ParseDateToISO( $args{ARGS}->{'ValueOfDate'} );
- $args{ARGS}->{'DateType'} =~ s/_Date$//;
-
- if ( $args{ARGS}->{'DateType'} eq 'Updated' ) {
- $session{'tickets'}->LimitTransactionDate(
- VALUE => $date,
- OPERATOR => $args{ARGS}->{'DateOp'},
- );
- }
- else {
- $session{'tickets'}->LimitDate( FIELD => $args{ARGS}->{'DateType'},
- VALUE => $date,
- OPERATOR => $args{ARGS}->{'DateOp'},
- );
- }
- }
-
- # }}}
- # {{{ Limit Content
- if ( $args{ARGS}->{'ValueOfAttachmentField'} ne '' ) {
- my $val = $args{ARGS}->{'ValueOfAttachmentField'};
- if ($args{ARGS}->{'AttachmentFieldOp'} =~ /like/) {
- $val = "%".$val."%";
- }
- $session{'tickets'}->Limit(
- FIELD => $args{ARGS}->{'AttachmentField'},
- VALUE => $val,
- OPERATOR => $args{ARGS}->{'AttachmentFieldOp'},
- );
- }
-
- # }}}
-
- # {{{ Limit CustomFields
-
- foreach my $arg ( keys %{ $args{ARGS} } ) {
- my $id;
- if ( $arg =~ /^CustomField(\d+)$/ ) {
- $id = $1;
- }
- else {
- next;
- }
- next unless ( $args{ARGS}->{$arg} );
-
- my $form = $args{ARGS}->{$arg};
- my $oper = $args{ARGS}->{ "CustomFieldOp" . $id };
- foreach my $value ( ref($form) ? @{$form} : ($form) ) {
- my $quote = 1;
- if ($oper =~ /like/i) {
- $value = "%".$value."%";
- }
- if ( $value =~ /^null$/i ) {
-
- #Don't quote the string 'null'
- $quote = 0;
-
- # Convert the operator to something apropriate for nulls
- $oper = 'IS' if ( $oper eq '=' );
- $oper = 'IS NOT' if ( $oper eq '!=' );
- }
- $session{'tickets'}->LimitCustomField( CUSTOMFIELD => $id,
- OPERATOR => $oper,
- QUOTEVALUE => $quote,
- VALUE => $value );
- }
- }
-
- # }}}
-
-
-}
-
-# }}}
-
-# {{{ sub ParseDateToISO
-
-=head2 ParseDateToISO
-
-Takes a date in an arbitrary format.
-Returns an ISO date and time in GMT
-
-=cut
-
-sub ParseDateToISO {
- my $date = shift;
-
- my $date_obj = RT::Date->new($session{'CurrentUser'});
- $date_obj->Set(
- Format => 'unknown',
- Value => $date
- );
- return ( $date_obj->ISO );
-}
-
-# }}}
-
-# {{{ sub Config
-# TODO: This might eventually read the cookies, user configuration
-# information from the DB, queue configuration information from the
-# DB, etc.
-
-sub Config {
- my $args = shift;
- my $key = shift;
- return $args->{$key} || $RT::WebOptions{$key};
-}
-
-# }}}
-
-# {{{ sub ProcessACLChanges
-
-sub ProcessACLChanges {
- my $ARGSref = shift;
-
- my %ARGS = %$ARGSref;
-
- my ( $ACL, @results );
-
-
- foreach my $arg (keys %ARGS) {
- if ($arg =~ /GrantRight-(\d+)-(.*?)-(\d+)$/) {
- my $principal_id = $1;
- my $object_type = $2;
- my $object_id = $3;
- my $rights = $ARGS{$arg};
-
- my $principal = RT::Principal->new($session{'CurrentUser'});
- $principal->Load($principal_id);
-
- 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') {
- $obj = $RT::System;
- } else {
- push (@results, loc("System Error").
- loc("Rights could not be granted for [_1]", $object_type));
- next;
- }
-
- my @rights = ref($ARGS{$arg}) eq 'ARRAY' ? @{$ARGS{$arg}} : ($ARGS{$arg});
- foreach my $right (@rights) {
- next unless ($right);
- my ($val, $msg) = $principal->GrantRight(Object => $obj, Right => $right);
- push (@results, $msg);
- }
- }
- elsif ($arg =~ /RevokeRight-(\d+)-(.*?)-(\d+)-(.*?)$/) {
- my $principal_id = $1;
- my $object_type = $2;
- my $object_id = $3;
- my $right = $4;
-
- my $principal = RT::Principal->new($session{'CurrentUser'});
- $principal->Load($principal_id);
- 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') {
- $obj = $RT::System;
- } else {
- push (@results, loc("System Error").
- loc("Rights could not be revoked for [_1]", $object_type));
- next;
- }
- my ($val, $msg) = $principal->RevokeRight(Object => $obj, Right => $right);
- push (@results, $msg);
- }
-
-
- }
-
- return (@results);
-
- }
-
-# }}}
-
-# {{{ sub UpdateRecordObj
-
-=head2 UpdateRecordObj ( ARGSRef => \%ARGS, Object => RT::Record, AttributesRef => \@attribs)
-
-@attribs is a list of ticket fields to check and update if they differ from the B<Object>'s current values. ARGSRef is a ref to HTML::Mason's %ARGS.
-
-Returns an array of success/failure messages
-
-=cut
-
-sub UpdateRecordObject {
- my %args = (
- ARGSRef => undef,
- AttributesRef => undef,
- Object => undef,
- AttributePrefix => undef,
- @_
- );
-
- my (@results);
-
- my $object = $args{'Object'};
- my $attributes = $args{'AttributesRef'};
- my $ARGSRef = $args{'ARGSRef'};
- foreach my $attribute (@$attributes) {
- my $value;
- if ( defined $ARGSRef->{$attribute} ) {
- $value = $ARGSRef->{$attribute};
- }
- elsif (
- defined( $args{'AttributePrefix'} )
- && defined(
- $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute }
- )
- ) {
- $value = $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute };
-
- } else {
- next;
- }
-
- $value =~ s/\r\n/\n/gs;
-
- if ($value ne $object->$attribute()){
-
- my $method = "Set$attribute";
- my ( $code, $msg ) = $object->$method($value);
-
- push @results, loc($attribute) . ': ' . loc_fuzzy($msg);
-=for loc
- "[_1] could not be set to [_2].", # loc
- "That is already the current value", # loc
- "No value sent to _Set!\n", # loc
- "Illegal value for [_1]", # loc
- "The new value has been set.", # loc
- "No column specified", # loc
- "Immutable field", # loc
- "Nonexistant field?", # loc
- "Invalid data", # loc
- "Couldn't find row", # loc
- "Missing a primary key?: [_1]", # loc
- "Found Object", # loc
-=cut
- };
- }
- return (@results);
-}
-
-# }}}
-
-# {{{ Sub ProcessCustomFieldUpdates
-
-sub ProcessCustomFieldUpdates {
- my %args = (
- CustomFieldObj => undef,
- ARGSRef => undef,
- @_
- );
-
- my $Object = $args{'CustomFieldObj'};
- my $ARGSRef = $args{'ARGSRef'};
-
- my @attribs = qw( Name Type Description Queue SortOrder);
- my @results = UpdateRecordObject(
- AttributesRef => \@attribs,
- Object => $Object,
- ARGSRef => $ARGSRef
- );
-
- if ( $ARGSRef->{ "CustomField-" . $Object->Id . "-AddValue-Name" } ) {
-
- my ( $addval, $addmsg ) = $Object->AddValue(
- Name =>
- $ARGSRef->{ "CustomField-" . $Object->Id . "-AddValue-Name" },
- Description => $ARGSRef->{ "CustomField-"
- . $Object->Id
- . "-AddValue-Description" },
- SortOrder => $ARGSRef->{ "CustomField-"
- . $Object->Id
- . "-AddValue-SortOrder" },
- );
- push ( @results, $addmsg );
- }
- my @delete_values = (
- ref $ARGSRef->{ 'CustomField-' . $Object->Id . '-DeleteValue' } eq
- 'ARRAY' )
- ? @{ $ARGSRef->{ 'CustomField-' . $Object->Id . '-DeleteValue' } }
- : ( $ARGSRef->{ 'CustomField-' . $Object->Id . '-DeleteValue' } );
- foreach my $id (@delete_values) {
- next unless defined $id;
- my ( $err, $msg ) = $Object->DeleteValue($id);
- push ( @results, $msg );
- }
- return (@results);
-}
-
-# }}}
-
-# {{{ sub ProcessTicketBasics
-
-=head2 ProcessTicketBasics ( TicketObj => $Ticket, ARGSRef => \%ARGS );
-
-Returns an array of results messages.
-
-=cut
-
-sub ProcessTicketBasics {
-
- my %args = (
- TicketObj => undef,
- ARGSRef => undef,
- @_
- );
-
- my $TicketObj = $args{'TicketObj'};
- my $ARGSRef = $args{'ARGSRef'};
-
- # {{{ Set basic fields
- my @attribs = qw(
- Subject
- FinalPriority
- Priority
- TimeEstimated
- TimeWorked
- TimeLeft
- Status
- Queue
- );
-
- if ( $ARGSRef->{'Queue'} and ( $ARGSRef->{'Queue'} !~ /^(\d+)$/ ) ) {
- my $tempqueue = RT::Queue->new($RT::SystemUser);
- $tempqueue->Load( $ARGSRef->{'Queue'} );
- if ( $tempqueue->id ) {
- $ARGSRef->{'Queue'} = $tempqueue->Id();
- }
- }
-
- my @results = UpdateRecordObject(
- AttributesRef => \@attribs,
- Object => $TicketObj,
- ARGSRef => $ARGSRef
- );
-
- # We special case owner changing, so we can use ForceOwnerChange
- if ( $ARGSRef->{'Owner'} && ( $TicketObj->Owner != $ARGSRef->{'Owner'} ) ) {
- my ($ChownType);
- if ( $ARGSRef->{'ForceOwnerChange'} ) {
- $ChownType = "Force";
- }
- else {
- $ChownType = "Give";
- }
-
- my ( $val, $msg ) =
- $TicketObj->SetOwner( $ARGSRef->{'Owner'}, $ChownType );
- push ( @results, $msg );
- }
-
- # }}}
-
- return (@results);
-}
-
-# }}}
-
-# {{{ Sub ProcessTicketCustomFieldUpdates
-
-sub ProcessTicketCustomFieldUpdates {
- my %args = (
- ARGSRef => undef,
- @_
- );
-
- my @results;
-
- my $ARGSRef = $args{'ARGSRef'};
-
- # Build up a list of tickets that we want to work with
- my %tickets_to_mod;
- my %custom_fields_to_mod;
- foreach my $arg ( keys %{$ARGSRef} ) {
- if ( $arg =~ /^Ticket-(\d+)-CustomField-(\d+)-/ ) {
-
- # For each of those tickets, find out what custom fields we want to work with.
- $custom_fields_to_mod{$1}{$2} = 1;
- }
- }
-
- # For each of those tickets
- foreach my $tick ( keys %custom_fields_to_mod ) {
- my $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
- $Ticket->Load($tick);
-
- # For each custom field
- foreach my $cf ( keys %{ $custom_fields_to_mod{$tick} } ) {
-
- my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'});
- $CustomFieldObj->LoadById($cf);
-
- foreach my $arg ( keys %{$ARGSRef} ) {
- # since http won't pass in a form element with a null value, we need
- # to fake it
- if ($arg =~ /^(.*?)-Values-Magic$/ ) {
- # We don't care about the magic, if there's really a values element;
- next if (exists $ARGSRef->{$1.'-Values'}) ;
-
- $arg = $1."-Values";
- $ARGSRef->{$1."-Values"} = undef;
-
- }
- next unless ( $arg =~ /^Ticket-$tick-CustomField-$cf-/ );
- my @values =
- ( ref( $ARGSRef->{$arg} ) eq 'ARRAY' )
- ? @{ $ARGSRef->{$arg} }
- : ( $ARGSRef->{$arg} );
- if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) {
- foreach my $value (@values) {
- next unless ($value);
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
- }
- elsif ( $arg =~ /-DeleteValues$/ ) {
- foreach my $value (@values) {
- next unless ($value);
- my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
- }
- elsif ( $arg =~ /-Values$/ and $CustomFieldObj->Type !~ /Entry/) {
- my $cf_values = $Ticket->CustomFieldValues($cf);
-
- my %values_hash;
- foreach my $value (@values) {
- next unless ($value);
-
- # build up a hash of values that the new set has
- $values_hash{$value} = 1;
-
- unless ( $cf_values->HasEntry($value) ) {
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
-
- }
- while ( my $cf_value = $cf_values->Next ) {
- unless ( $values_hash{ $cf_value->Content } == 1 ) {
- my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue(
- Field => $cf,
- Value => $cf_value->Content
- );
- push ( @results, $msg);
-
- }
-
- }
- }
- elsif ( $arg =~ /-Values$/ ) {
- my $cf_values = $Ticket->CustomFieldValues($cf);
-
- # keep everything up to the point of difference, delete the rest
- my $delete_flag;
- foreach my $old_cf (@{$cf_values->ItemsArrayRef}) {
- if (!$delete_flag and @values and $old_cf->Content eq $values[0]) {
- shift @values;
- next;
- }
-
- $delete_flag ||= 1;
- $old_cf->Delete;
- }
-
- # now add/replace extra things, if any
- foreach my $value (@values) {
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
- }
- else {
- push ( @results, "User asked for an unknown update type for custom field " . $cf->Name . " for ticket " . $Ticket->id );
- }
- }
- }
- return (@results);
- }
-}
-
-# }}}
-
-# {{{ sub ProcessTicketWatchers
-
-=head2 ProcessTicketWatchers ( TicketObj => $Ticket, ARGSRef => \%ARGS );
-
-Returns an array of results messages.
-
-=cut
-
-sub ProcessTicketWatchers {
- my %args = (
- TicketObj => undef,
- ARGSRef => undef,
- @_
- );
- my (@results);
-
- my $Ticket = $args{'TicketObj'};
- my $ARGSRef = $args{'ARGSRef'};
-
- # {{{ Munge watchers
-
- foreach my $key ( keys %$ARGSRef ) {
-
- # {{{ Delete deletable watchers
- if ( ( $key =~ /^Ticket-DelWatcher-Type-(.*)-Principal-(\d+)$/ ) ) {
- my ( $code, $msg ) =
- $Ticket->DeleteWatcher(PrincipalId => $2,
- Type => $1);
- push @results, $msg;
- }
-
- # Delete watchers in the simple style demanded by the bulk manipulator
- elsif ( $key =~ /^Delete(Requestor|Cc|AdminCc)$/ ) {
- my ( $code, $msg ) = $Ticket->DeleteWatcher( Type => $ARGSRef->{$key}, PrincipalId => $1 );
- push @results, $msg;
- }
-
- # }}}
-
- # Add new wathchers by email address
- elsif ( ( $ARGSRef->{$key} =~ /^(AdminCc|Cc|Requestor)$/ )
- and ( $key =~ /^WatcherTypeEmail(\d*)$/ ) )
- {
-
- #They're in this order because otherwise $1 gets clobbered :/
- my ( $code, $msg ) = $Ticket->AddWatcher(
- Type => $ARGSRef->{$key},
- Email => $ARGSRef->{ "WatcherAddressEmail" . $1 }
- );
- push @results, $msg;
- }
-
- #Add requestors in the simple style demanded by the bulk manipulator
- elsif ( $key =~ /^Add(Requestor|Cc|AdminCc)$/ ) {
- my ( $code, $msg ) = $Ticket->AddWatcher(
- Type => $1,
- Email => $ARGSRef->{$key}
- );
- push @results, $msg;
- }
-
- # Add new watchers by owner
- elsif ( ( $ARGSRef->{$key} =~ /^(AdminCc|Cc|Requestor)$/ )
- and ( $key =~ /^Ticket-AddWatcher-Principal-(\d*)$/ ) ) {
-
- #They're in this order because otherwise $1 gets clobbered :/
- my ( $code, $msg ) =
- $Ticket->AddWatcher( Type => $ARGSRef->{$key}, PrincipalId => $1 );
- push @results, $msg;
- }
- }
-
- # }}}
-
- return (@results);
-}
-
-# }}}
-
-# {{{ sub ProcessTicketDates
-
-=head2 ProcessTicketDates ( TicketObj => $Ticket, ARGSRef => \%ARGS );
-
-Returns an array of results messages.
-
-=cut
-
-sub ProcessTicketDates {
- my %args = (
- TicketObj => undef,
- ARGSRef => undef,
- @_
- );
-
- my $Ticket = $args{'TicketObj'};
- my $ARGSRef = $args{'ARGSRef'};
-
- my (@results);
-
- # {{{ Set date fields
- my @date_fields = qw(
- Told
- Resolved
- Starts
- Started
- Due
- );
-
- #Run through each field in this list. update the value if apropriate
- foreach my $field (@date_fields) {
- my ( $code, $msg );
-
- my $DateObj = RT::Date->new( $session{'CurrentUser'} );
-
- #If it's something other than just whitespace
- if ( $ARGSRef->{ $field . '_Date' } ne '' ) {
- $DateObj->Set(
- Format => 'unknown',
- Value => $ARGSRef->{ $field . '_Date' }
- );
- my $obj = $field . "Obj";
- if ( ( defined $DateObj->Unix )
- and ( $DateObj->Unix ne $Ticket->$obj()->Unix() ) )
- {
- my $method = "Set$field";
- my ( $code, $msg ) = $Ticket->$method( $DateObj->ISO );
- push @results, "$msg";
- }
- }
- }
-
- # }}}
- return (@results);
-}
-
-# }}}
-
-# {{{ sub ProcessTicketLinks
-
-=head2 ProcessTicketLinks ( TicketObj => $Ticket, ARGSRef => \%ARGS );
-
-Returns an array of results messages.
-
-=cut
-
-sub ProcessTicketLinks {
- my %args = ( TicketObj => undef,
- ARGSRef => undef,
- @_ );
-
- my $Ticket = $args{'TicketObj'};
- my $ARGSRef = $args{'ARGSRef'};
-
- my (@results);
-
- # Delete links that are gone gone gone.
- foreach my $arg ( keys %$ARGSRef ) {
- if ( $arg =~ /DeleteLink-(.*?)-(DependsOn|MemberOf|RefersTo)-(.*)$/ ) {
- my $base = $1;
- my $type = $2;
- my $target = $3;
-
- push @results,
- "Trying to delete: Base: $base Target: $target Type $type";
- my ( $val, $msg ) = $Ticket->DeleteLink( Base => $base,
- Type => $type,
- Target => $target );
-
- push @results, $msg;
-
- }
-
- }
-
- my @linktypes = qw( DependsOn MemberOf RefersTo );
-
- foreach my $linktype (@linktypes) {
- if ( $ARGSRef->{ $Ticket->Id . "-$linktype" } ) {
- for my $luri ( split ( / /, $ARGSRef->{ $Ticket->Id . "-$linktype" } ) ) {
- $luri =~ s/\s*$//; # Strip trailing whitespace
- my ( $val, $msg ) = $Ticket->AddLink( Target => $luri,
- Type => $linktype );
- push @results, $msg;
- }
- }
- if ( $ARGSRef->{ "$linktype-" . $Ticket->Id } ) {
-
- for my $luri ( split ( / /, $ARGSRef->{ "$linktype-" . $Ticket->Id } ) ) {
- my ( $val, $msg ) = $Ticket->AddLink( Base => $luri,
- Type => $linktype );
-
- push @results, $msg;
- }
- }
- }
-
- #Merge if we need to
- if ( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ) {
- my ( $val, $msg ) =
- $Ticket->MergeInto( $ARGSRef->{ $Ticket->Id . "-MergeInto" } );
- push @results, $msg;
- }
-
- return (@results);
-}
-
-# }}}
-
-eval "require RT::Interface::Web_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web_Vendor.pm});
-eval "require RT::Interface::Web_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/Web/Handler.pm b/rt/lib/RT/Interface/Web/Handler.pm
deleted file mode 100644
index 1e871ec..0000000
--- a/rt/lib/RT/Interface/Web/Handler.pm
+++ /dev/null
@@ -1,211 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Web::Handler;
-
-use CGI qw/-private_tempfiles/;
-use MIME::Entity;
-use Text::Wrapper;
-use CGI::Cookie;
-use Time::ParseDate;
-use Time::HiRes;
-use HTML::Entities;
-use HTML::Scrubber;
-use RT::Interface::Web::Handler;
-use File::Path qw( rmtree );
-use File::Glob qw( bsd_glob );
-use File::Spec::Unix;
-
-sub DefaultHandlerArgs { (
- comp_root => [
- [ local => $RT::MasonLocalComponentRoot ],
- [ standard => $RT::MasonComponentRoot ]
- ],
- default_escape_flags => 'h',
- data_dir => "$RT::MasonDataDir",
- allow_globals => [qw(%session)],
- # Turn off static source if we're in developer mode.
- static_source => ($RT::DevelMode ? '0' : '1'),
- use_object_files => ($RT::DevelMode ? '0' : '1'),
- autoflush => 0
-) };
-
-# {{{ sub new
-
-=head2 new
-
- Constructs a web handler of the appropriate class.
- Takes options to pass to the constructor.
-
-=cut
-
-sub new {
- my $class = shift;
- $class->InitSessionDir;
-
- if ( $mod_perl::VERSION && $mod_perl::VERSION >= 1.9908 ) {
- goto &NewApacheHandler;
- }
- elsif ($CGI::MOD_PERL) {
- goto &NewApacheHandler;
- }
- else {
- goto &NewCGIHandler;
- }
-}
-
-sub InitSessionDir {
- # Activate the following if running httpd as root (the normal case).
- # Resets ownership of all files created by Mason at startup.
- # Note that mysql uses DB for sessions, so there's no need to do this.
- unless ( $RT::DatabaseType =~ /(?:mysql|Pg)/ ) {
-
- # Clean up our umask to protect session files
- umask(0077);
-
- if ($CGI::MOD_PERL) { local $@; eval {
-
- chown( Apache->server->uid, Apache->server->gid,
- $RT::MasonSessionDir )
- }}
-
- # Die if WebSessionDir doesn't exist or we can't write to it
- stat($RT::MasonSessionDir);
- die "Can't read and write $RT::MasonSessionDir"
- unless ( ( -d _ ) and ( -r _ ) and ( -w _ ) );
- }
-
-}
-
-# }}}
-
-# {{{ sub NewApacheHandler
-
-=head2 NewApacheHandler
-
- Takes extra options to pass to HTML::Mason::ApacheHandler->new
- Returns a new Mason::ApacheHandler object
-
-=cut
-
-sub NewApacheHandler {
- require HTML::Mason::ApacheHandler;
- return NewHandler('HTML::Mason::ApacheHandler', args_method => "CGI", @_);
-}
-
-# }}}
-
-# {{{ sub NewApache2Handler
-
-=head2 NewApache2Handler
-
- Takes extra options to pass to MasonX::Apache2Handler->new
- Returns a new MasonX::Apache2Handler object
-
-=cut
-
-sub NewApache2Handler {
- require MasonX::Apache2Handler;
- return NewHandler('MasonX::Apache2Handler', args_method => "CGI", @_);
-}
-
-# }}}
-
-# {{{ sub NewCGIHandler
-
-=head2 NewCGIHandler
-
- Returns a new Mason::CGIHandler object
-
-=cut
-
-sub NewCGIHandler {
- require HTML::Mason::CGIHandler;
- return NewHandler('HTML::Mason::CGIHandler', @_);
-}
-
-sub NewHandler {
- my $class = shift;
- my $handler = $class->new(
- DefaultHandlerArgs(),
- @_
- );
-
- $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 );
- $handler->interp->set_escape( u => \&RT::Interface::Web::EscapeURI );
- return($handler);
-}
-
-=head2 CleanupRequest
-
-Rollback any uncommitted transaction.
-Flush the ACL cache
-Flush the searchbuilder query cache
-
-=cut
-
-sub CleanupRequest {
-
- if ( $RT::Handle->TransactionDepth ) {
- $RT::Handle->ForceRollback;
- $RT::Logger->crit(
- "Transaction not committed. Usually indicates a software fault."
- . "Data loss may have occurred" );
- }
-
- # Clean out the ACL cache. the performance impact should be marginal.
- # Consistency is imprived, too.
- RT::Principal->InvalidateACLCache();
- DBIx::SearchBuilder::Record::Cachable->FlushCache
- if ( $RT::WebFlushDbCacheEveryRequest
- and UNIVERSAL::can(
- 'DBIx::SearchBuilder::Record::Cachable' => 'FlushCache' ) );
-
-}
-# }}}
-
-1;
diff --git a/rt/lib/RT/Interface/Web/Menu.pm b/rt/lib/RT/Interface/Web/Menu.pm
deleted file mode 100644
index f2d78ef..0000000
--- a/rt/lib/RT/Interface/Web/Menu.pm
+++ /dev/null
@@ -1,68 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Web::Menu;
-
-
-sub new {
- my $class = shift;
- my $self = bless {}, $class;
- $self->{'root_node'} = RT::Interface::Web::Menu::Item->new();
- return $self;
-}
-
-
-sub as_hash_of_hashes {
-
-}
-
-sub root {
- my $self = shift;
- return $self->{'root_node'};
-}
-
-1;
diff --git a/rt/lib/RT/Interface/Web/Menu/Item.pm b/rt/lib/RT/Interface/Web/Menu/Item.pm
deleted file mode 100644
index 5365db3..0000000
--- a/rt/lib/RT/Interface/Web/Menu/Item.pm
+++ /dev/null
@@ -1,86 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Web::Menu::Item;
-
-
-sub new {
- my $class = shift;
- my $self = bless {},$class;
- $self->{'_attributes'} = {};
- return($self);
-}
-
-sub label { my $self = shift; $self->_accessor( label => @_) } ;
-sub absolute_url { my $self = shift; $self->_accessor( absolute_url => @_) } ;
-sub rt_path { my $self = shift; $self->_accessor( rt_path => @_) } ;
-sub hilight { my $self = shift; $self->_accessor( hilight => @_);
- $self->parent->hilight(1);
- } ;
-sub sort_order { my $self = shift; $self->_accessor( sort_order => @_) } ;
-
-sub add_child {
-}
-
-sub delete {
-}
-
-sub children {
-
-}
-
-sub _accessor {
- my $self = shift;
- my $key = shift;
- if (@_){
- $self->{'attributes'}->{$key} = shift;
-
- }
- return $self->{'_attributes'}->{$key};
-}
-
-1;
diff --git a/rt/lib/RT/Interface/Web/QueryBuilder.pm b/rt/lib/RT/Interface/Web/QueryBuilder.pm
deleted file mode 100755
index 56c5b03..0000000
--- a/rt/lib/RT/Interface/Web/QueryBuilder.pm
+++ /dev/null
@@ -1,58 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Web::QueryBuilder;
-
-use strict;
-use warnings;
-
-eval "require RT::Interface::Web::QueryBuilder_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder_Vendor.pm});
-eval "require RT::Interface::Web::QueryBuilder_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm b/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm
deleted file mode 100755
index 4676273..0000000
--- a/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm
+++ /dev/null
@@ -1,247 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Web::QueryBuilder::Tree;
-
-use strict;
-use warnings;
-
-use base qw/Tree::Simple/;
-
-=head1 NAME
-
- RT::Interface::Web::QueryBuilder::Tree - subclass of Tree::Simple used in Query Builder
-
-=head1 DESCRIPTION
-
-This class provides support functionality for the Query Builder (Search/Build.html).
-It is a subclass of L<Tree::Simple>.
-
-=head1 METHODS
-
-=head2 TraversePrePost PREFUNC POSTFUNC
-
-Traverses the tree depth-first. Before processing the node's children,
-calls PREFUNC with the node as its argument; after processing all of the
-children, calls POSTFUNC with the node as its argument.
-
-(Note that unlike Tree::Simple's C<traverse>, it actually calls its functions
-on the root node passed to it.)
-
-=cut
-
-sub TraversePrePost {
- my ($self, $prefunc, $postfunc) = @_;
-
- $prefunc->($self);
-
- foreach my $child ($self->getAllChildren()) {
- $child->TraversePrePost($prefunc, $postfunc);
- }
-
- $postfunc->($self);
-}
-
-=head2 GetReferencedQueues
-
-Returns a hash reference with keys each queue name referenced in a clause in
-the key (even if it's "Queue != 'Foo'"), and values all 1.
-
-=cut
-
-sub GetReferencedQueues {
- my $self = shift;
-
- my $queues = {};
-
- $self->traverse(
- sub {
- my $node = shift;
-
- return if $node->isRoot;
-
- my $clause = $node->getNodeValue();
-
- if ( ref($clause) and $clause->{Key} eq 'Queue' ) {
- $queues->{ $clause->{Value} } = 1;
- };
- }
- );
-
- return $queues;
-}
-
-=head2 GetQueryAndOptionList SELECTED_NODES
-
-Given an array reference of tree nodes that have been selected by the user,
-traverses the tree and returns the equivalent SQL query and a list of hashes
-representing the "clauses" select option list. Each has contains the keys
-TEXT, INDEX, SELECTED, and DEPTH. TEXT is the displayed text of the option
-(including parentheses, not including indentation); INDEX is the 0-based
-index of the option in the list (also used as its CGI parameter); SELECTED
-is either 'SELECTED' or '', depending on whether the node corresponding
-to the select option was in the SELECTED_NODES list; and DEPTH is the
-level of indentation for the option.
-
-=cut
-
-sub GetQueryAndOptionList {
- my $self = shift;
- my $selected_nodes = shift;
-
- my $optionlist = [];
-
- my $i = 0;
-
- $self->TraversePrePost(
- sub { # This is called before recursing to the node's children.
- my $node = shift;
-
- return if $node->isRoot or $node->getParent->isRoot;
-
- my $clause = $node->getNodeValue();
- my $str = ' ';
- my $aggregator_context = $node->getParent()->getNodeValue();
- $str = $aggregator_context . " " if $node->getIndex() > 0;
-
- if ( ref($clause) ) { # ie, it's a leaf
- $str .=
- $clause->{Key} . " " . $clause->{Op} . " " . $clause->{Value};
- }
-
- unless ($node->getParent->getParent->isRoot) {
- # used to check !ref( $parent->getNodeValue() ) )
- if ( $node->getIndex() == 0 ) {
- $str = '( ' . $str;
- }
- }
-
- push @$optionlist, {
- TEXT => $str,
- INDEX => $i,
- SELECTED => (grep { $_ == $node } @$selected_nodes) ? 'SELECTED' : '',
- DEPTH => $node->getDepth() - 1,
- };
-
- $i++;
- }, sub {
- # This is called after recursing to the node's children.
- my $node = shift;
-
- return if $node->isRoot or $node->getParent->isRoot or $node->getParent->getParent->isRoot;
-
- # Only do this for the rightmost child.
- return unless $node->getIndex == $node->getParent->getChildCount - 1;
-
- $optionlist->[-1]{TEXT} .= ' )';
- }
- );
-
- return (join ' ', map { $_->{TEXT} } @$optionlist), $optionlist;
-}
-
-=head2 PruneChildLessAggregators
-
-If tree manipulation has left it in a state where there are ANDs, ORs,
-or parenthesizations with no children, get rid of them.
-
-=cut
-
-sub PruneChildlessAggregators {
- my $self = shift;
-
- $self->TraversePrePost(
- sub {
- },
- sub {
- my $node = shift;
-
- return if $node->isRoot or $node->getParent->isRoot;
-
- # We're only looking for aggregators (AND/OR)
- return if ref $node->getNodeValue;
-
- return if $node->getChildCount != 0;
-
- # OK, this is a childless aggregator. Remove self.
-
- $node->getParent->removeChild($node);
-
- # Deal with circular refs
- $node->DESTROY;
- }
- );
-}
-
-=head2 GetDisplayedNodes
-
-This function returns a list of the nodes of the tree in depth-first
-order which correspond to options in the "clauses" multi-select box.
-In fact, it's all of them but the root and its child.
-
-=cut
-
-sub GetDisplayedNodes {
- my $self = shift;
- my @lines;
-
- $self->traverse(sub {
- my $node = shift;
-
- push @lines, $node unless $node->isRoot or $node->getParent->isRoot;
- });
-
- return @lines;
-}
-
-
-eval "require RT::Interface::Web::QueryBuilder::Tree_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder/Tree_Vendor.pm});
-eval "require RT::Interface::Web::QueryBuilder::Tree_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder/Tree_Local.pm});
-
-1;
diff --git a/rt/lib/RT/Interface/Web/Standalone.pm b/rt/lib/RT/Interface/Web/Standalone.pm
deleted file mode 100755
index 319e317..0000000
--- a/rt/lib/RT/Interface/Web/Standalone.pm
+++ /dev/null
@@ -1,84 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2007 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/copyleft/gpl.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 }}}
-package RT::Interface::Web::Standalone;
-
-use strict;
-use base 'HTTP::Server::Simple::Mason';
-use RT::Interface::Web::Handler;
-use RT::Interface::Web;
-
-sub handler_class { "RT::Interface::Web::Handler" }
-
-sub setup_escapes {
- my $self = shift;
- my $handler = shift;
-
- # Override HTTP::Server::Simple::Mason's version of this method to do
- # nothing. (RT::Interface::Web::Handler does this already for us in
- # NewHandler.)
-}
-
-sub default_mason_config {
- return @RT::MasonParameters;
-}
-
-sub handle_request {
-
- my $self = shift;
- my $cgi = shift;
-
- Module::Refresh->refresh if $RT::DevelMode;
-
- $self->SUPER::handle_request($cgi);
- $RT::Logger->crit($@) if ($@);
-
- RT::Interface::Web::Handler->CleanupRequest();
-
-}
-
-1;
diff --git a/rt/lib/RT/Interface/Web_Vendor.pm b/rt/lib/RT/Interface/Web_Vendor.pm
deleted file mode 100644
index 5be20e6..0000000
--- a/rt/lib/RT/Interface/Web_Vendor.pm
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
-#
-# 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.
-
-=head1 NAME
-
-RT::Interface::Web_Vendor
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-Freeside vendor overlay for RT::Interface::Web.
-
-=begin testing
-
-use_ok(RT::Interface::Web_Vendor);
-
-=end testing
-
-=cut
-
-#package RT::Interface::Web;
-#use strict;
-
-package HTML::Mason::Commands;
-use strict;
-
-=head2 ProcessTicketCustomers
-
-=cut
-
-sub ProcessTicketCustomers {
- my %args = (
- TicketObj => undef,
- ARGSRef => undef,
- @_
- );
- my @results = ();
-
- my $Ticket = $args{'TicketObj'};
- my $ARGSRef = $args{'ARGSRef'};
-
- ### false laziness w/RT::Interface::Web::ProcessTicketLinks
- # Delete links that are gone gone gone.
- foreach my $arg ( keys %$ARGSRef ) {
- if ( $arg =~ /DeleteLink-(.*?)-(DependsOn|MemberOf|RefersTo)-(.*)$/ ) {
- my $base = $1;
- my $type = $2;
- my $target = $3;
-
- push @results,
- "Trying to delete: Base: $base Target: $target Type $type";
- my ( $val, $msg ) = $Ticket->DeleteLink( Base => $base,
- Type => $type,
- Target => $target );
-
- push @results, $msg;
-
- }
-
- }
- ###
-
- my @delete_custnums =
- map { /^Ticket-AddCustomer-(\d+)$/; $1 }
- grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} }
- keys %$ARGSRef;
-
- my @custnums = map { /^Ticket-AddCustomer-(\d+)$/; $1 }
- grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} }
- keys %$ARGSRef;
-
- foreach my $custnum ( @custnums ) {
- my( $val, $msg ) =
- $Ticket->AddLink( 'Type' => 'MemberOf',
- 'Target' => "freeside://freeside/cust_main/$custnum",
- );
- push @results, $msg;
- }
-
- return @results;
-
-}
-
-1;
-