X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=rt%2Fbin%2Frt;h=1757d08c0d6cf83413263b6c4d3a07885d8a5991;hp=41220bb56009d7326959601ab2387274d02579fc;hb=187086c479a09629b7d180eec513fb7657f4e291;hpb=3ef62a0570055da710328937e7f65dbb2c027c62 diff --git a/rt/bin/rt b/rt/bin/rt index 41220bb56..1757d08c0 100755 --- a/rt/bin/rt +++ b/rt/bin/rt @@ -1,1391 +1,2680 @@ -#!!!PERL!! -w +#!/usr/bin/perl -w +# BEGIN BPS TAGGED BLOCK {{{ # -# $Header: /home/cvs/cvsroot/freeside/rt/bin/Attic/rt,v 1.1 2002-08-12 06:17:07 ivan Exp $ -# RT is (c) 1996-2001 Jesse Vincent +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC +# +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +# Designed and implemented for Best Practical Solutions, LLC by +# Abhijit Menon-Sen use strict; -use Carp; -use Getopt::Long; +use warnings; -use lib "!!RT_LIB_PATH!!"; -use lib "!!RT_ETC_PATH!!"; +if ( $ARGV[0] && $ARGV[0] =~ /^(?:--help|-h)$/ ) { + require Pod::Usage; + print Pod::Usage::pod2usage( { verbose => 2 } ); + exit; +} + +# This program is intentionally written to have as few non-core module +# dependencies as possible. It should stay that way. + +use Cwd; +use LWP; +use Text::ParseWords; +use HTTP::Request::Common; +use HTTP::Headers; +use Term::ReadLine; +use Time::Local; # used in prettyshow +use File::Temp; + +# We derive configuration information from hardwired defaults, dotfiles, +# and the RT* environment variables (in increasing order of precedence). +# Session information is stored in ~/.rt_sessions. + +my $VERSION = 0.02; +my $HOME = eval{(getpwuid($<))[7]} + || $ENV{HOME} || $ENV{LOGDIR} || $ENV{HOMEPATH} + || "."; +my %config = ( + ( + debug => 0, + user => eval{(getpwuid($<))[0]} || $ENV{USER} || $ENV{USERNAME}, + passwd => undef, + server => 'http://localhost/', + query => "Status!='resolved' and Status!='rejected'", + orderby => 'id', + queue => undef, +# to protect against unlimited searches a better choice would be +# queue => 'Unknown_Queue', + auth => "rt", + ), + config_from_file($ENV{RTCONFIG} || ".rtrc"), + config_from_env() +); + +$config{auth} = "basic" if delete $config{externalauth}; + +my $session = Session->new("$HOME/.rt_sessions"); +my $REST = "$config{server}/REST/1.0"; + +my $prompt = 'rt> '; + +sub whine; +sub DEBUG { warn @_ if $config{debug} >= shift } + +# These regexes are used by command handlers to parse arguments. +# (XXX: Ask Autrijus how i18n changes these definitions.) + +my $name = '[\w.-]+'; +my $CF_name = '[^,]+?'; +my $field = '(?i:[a-z][a-z0-9_-]*|C(?:ustom)?F(?:ield)?-'.$CF_name.'|CF\.\{'.$CF_name.'\})'; +my $label = '[^,\\/]+'; +my $labels = "(?:$label,)*$label"; +my $idlist = '(?:(?:\d+-)?\d+,)*(?:\d+-)?\d+'; + +# Our command line looks like this: +# +# rt [options] [arguments] +# +# We'll parse just enough of it to decide upon an action to perform, and +# leave the rest to per-action handlers to interpret appropriately. + +my %handlers = ( +# handler => [ ...aliases... ], + version => ["version", "ver"], + shell => ["shell"], + logout => ["logout"], + help => ["help", "man"], + show => ["show", "cat"], + edit => ["create", "edit", "new", "ed"], + list => ["search", "list", "ls"], + comment => ["comment", "correspond"], + link => ["link", "ln"], + merge => ["merge"], + grant => ["grant", "revoke"], + take => ["take", "steal", "untake"], + quit => ["quit", "exit"], + setcommand => ["del", "delete", "give", "res", "resolve", + "subject"], +); + +my %actions; +foreach my $fn (keys %handlers) { + foreach my $alias (@{ $handlers{$fn} }) { + $actions{$alias} = \&{"$fn"}; + } +} -use RT::Interface::CLI qw(CleanEnv LoadConfig DBConnect - GetCurrentUser GetMessageContent); +# Once we find and call an appropriate handler, we're done. -#Clean out all the nasties from the environment -CleanEnv(); +sub handler { + my $action; -#Load etc/config.pm and drop privs -LoadConfig(); + push @ARGV, 'shell' if (!@ARGV); # default to shell mode + shift @ARGV if ($ARGV[0] eq 'rt'); # ignore a leading 'rt' + if (@ARGV && exists $actions{$ARGV[0]}) { + $action = shift @ARGV; + return $actions{$action}->($action); + } + else { + print STDERR "rt: Unknown command '@ARGV'.\n"; + print STDERR "rt: For help, run 'rt help'.\n"; + return 1; + } +} -#Connect to the database and get RT::SystemUser and RT::Nobody loaded -DBConnect(); +exit handler(); -#Drop setgid permissions -RT::DropSetGIDPermissions(); +# Handler functions. +# ------------------ +# +# The following subs are handlers for each entry in %actions. -#Get the current user all loaded -my $CurrentUser = GetCurrentUser(); +sub shell { + $|=1; + my $term = Term::ReadLine->new('RT CLI'); + while ( defined ($_ = $term->readline($prompt)) ) { + next if /^#/ || /^\s*$/; -unless ($CurrentUser->Id) { - print "No RT user found. Please consult your RT administrator.\n"; - exit(1); + @ARGV = shellwords($_); + handler(); + } } +sub version { + print "rt $VERSION\n"; + return 0; +} -# {{{ commandline flags - -my ( @id, - @limit_queue, - @limit_status, - @limit_owner, - @limit_priority, - @limit_final_priority, - @limit_requestor, - @limit_subject, - @limit_body, - @limit_created, - @limit_resolved, - @limit_lastupdated, - @limit_dependson, - @limit_dependedonby, - @limit_memberof, - @limit_hasmember, - @limit_refersto, - @limit_referredtoby, - @limit_keyword, - - @limit_due, - @limit_starts, - @limit_started, - $limit_first, - $limit_rows, - $history, - $summary, - $create, - @requestors, - @cc, - @admincc, - $status, - $subject, - $owner, - $steal, - $queue, - $time_left, - $priority, - $final_priority, - $due, - $starts, - $started, - $contacted, - $comment, - $reply, - $source, - $edit, - @dependson, - @memberof, - @refersto, - $mergeinto, - @keywords, - $time_taken, - $verbose, - $debug, - $help, - $version); - -# }}} - -# Set defaults for cli args - -$edit = 1; # Assume the user wants to edit replies and comments - # unless they specify --noedit - -# {{{ args - -my @args =("id=s" => \@id, - "limit-queue=s" => \@limit_queue, - "limit-status=s" => \@limit_status, - "limit-owner=s" => \@limit_owner, - "limit-priority=s" => \@limit_priority, - "limit-final-priority=s" => \@limit_final_priority, - "limit-requestor=s" => \@limit_requestor, - "limit-subject=s" => \@limit_subject, - "limit-body=s", \@limit_body, - "limit-created=s" => \@limit_created, - "limit-due=s" => \@limit_due, - "limit-last-updated=s" => \@limit_lastupdated, - "limit-keyword=s" => \@limit_keyword, - - "limit-member-of=s" => \@limit_memberof, - "limit-has-member=s" => \@limit_hasmember, - "limit-depended-on-by=s" => \@limit_dependedonby, - "limit-depends-on=s" => \@limit_dependson, - "limit-referred-to-by=s" => \@limit_referredtoby, - "limit-refers-to=s" => \@limit_refersto, - - "limit-starts=s" => \@limit_starts, - "limit-started=s" => \@limit_started, - "limit-first=i" => \$limit_first, - "limit-rows=i" => \$limit_rows, - "history|show" => \$history, - "summary:s" => \$summary, - "create" => \$create, - "keywords=s" => \@keywords, - "requestor|requestors=s" => \@requestors, - "cc=s" => \@cc, - "admincc=s" => \@admincc, - "status=s" => \$status, - "subject=s" => \$subject, - "owner=s" => \$owner, - "steal" => \$steal, - "queue=s" => \$queue, - - - "priority=i" => \$priority, - "final-priority=i" => \$final_priority, - "due=s" => \$due, - "starts=s" => \$starts, - "started=s" => \$started, - "contacted=s" => \$contacted, - "comment", \$comment, - "reply|respond", \$reply, - "source=s" => \$source, - "edit!" => \$edit, - "depends-on=s" => \@dependson, - "member-of=s" => \@memberof, - "merge-into=s" => \$mergeinto, - "refers-to=s" => \@refersto, - "time-left=i" => \$time_left, - "time-taken=i" => \$time_taken, - "verbose+" => \$verbose, - "debug" => \$debug, - "version" => \$version, - "help|h|usage" => \$help - ); - -# }}} - - - -GetOptions(@args); - -print join(':',@keywords); -# {{{ If they want it, print a usage message and get out - -if ($help) { - - -print < - --limit-status=[!](new|open|stalled|resolved) - - --limit-owner=[!] - --limit-priority=[starts][-][ends] - --limit-final-priority=[starts][-][ends] - starts is less than ends - --limit-requestor=[!]| - --limit-subject=[!] - --limit-body=[!] - --limit-keyword=[!]