summaryrefslogtreecommitdiff
path: root/rt/html
diff options
context:
space:
mode:
Diffstat (limited to 'rt/html')
-rw-r--r--rt/html/Admin/Elements/EditCustomField2
-rw-r--r--rt/html/Admin/Elements/EditCustomFieldValues2
-rw-r--r--rt/html/Admin/Elements/EditCustomFields41
-rw-r--r--rt/html/Admin/Elements/EditScrip9
-rw-r--r--rt/html/Admin/Elements/EditScrips4
-rw-r--r--rt/html/Admin/Elements/SelectGroups3
-rw-r--r--rt/html/Admin/Elements/SelectRights3
-rw-r--r--rt/html/Admin/Elements/SelectStage39
-rw-r--r--rt/html/Admin/Queues/CustomFields.html3
-rw-r--r--rt/html/Admin/Queues/index.html2
-rw-r--r--rt/html/Admin/Users/Modify.html8
-rw-r--r--rt/html/Admin/Users/index.html2
-rw-r--r--rt/html/Approvals/Display.html2
-rw-r--r--rt/html/Elements/Callback7
-rw-r--r--rt/html/Elements/MessageBox6
-rw-r--r--rt/html/Elements/MyTickets2
-rw-r--r--rt/html/Elements/SelectLang56
-rw-r--r--rt/html/Elements/SelectStatus2
-rw-r--r--rt/html/Elements/SelectWatcherType3
-rw-r--r--rt/html/Elements/SetupSessionCookie18
-rw-r--r--rt/html/Elements/SimpleSearch2
-rw-r--r--rt/html/NoAuth/webrt.css4
-rw-r--r--rt/html/REST/1.0/Forms/queue/default123
-rw-r--r--rt/html/REST/1.0/Forms/queue/ns38
-rw-r--r--rt/html/REST/1.0/Forms/ticket/attachments107
-rw-r--r--rt/html/REST/1.0/Forms/ticket/default253
-rw-r--r--rt/html/REST/1.0/Forms/ticket/history144
-rw-r--r--rt/html/REST/1.0/Forms/ticket/links148
-rw-r--r--rt/html/REST/1.0/Forms/user/default141
-rw-r--r--rt/html/REST/1.0/Forms/user/ns41
-rw-r--r--rt/html/REST/1.0/NoAuth/mail-gateway7
-rw-r--r--rt/html/REST/1.0/autohandler32
-rw-r--r--rt/html/REST/1.0/dhandler287
-rw-r--r--rt/html/REST/1.0/logout27
-rw-r--r--rt/html/REST/1.0/search/dhandler32
-rw-r--r--rt/html/REST/1.0/search/ticket119
-rw-r--r--rt/html/REST/1.0/ticket/comment149
-rw-r--r--rt/html/REST/1.0/ticket/link96
-rw-r--r--rt/html/REST/1.0/ticket/merge78
-rw-r--r--rt/html/Search/Bulk.html1
-rw-r--r--rt/html/Search/Elements/PickRestriction11
-rw-r--r--rt/html/SelfService/Display.html43
-rw-r--r--rt/html/SelfService/Elements/MyRequests1
-rw-r--r--rt/html/SelfService/Update.html19
-rw-r--r--rt/html/Ticket/Attachment/dhandler4
-rw-r--r--rt/html/Ticket/Create.html69
-rw-r--r--rt/html/Ticket/Display.html76
-rw-r--r--rt/html/Ticket/Elements/AddWatchers2
-rw-r--r--rt/html/Ticket/Elements/EditCustomField4
-rw-r--r--rt/html/Ticket/Elements/EditLinks29
-rw-r--r--rt/html/Ticket/Elements/EditPeople3
-rw-r--r--rt/html/Ticket/Elements/ShowAttachments5
-rw-r--r--rt/html/Ticket/Elements/ShowDates11
-rw-r--r--rt/html/Ticket/Elements/ShowHistory2
-rw-r--r--rt/html/Ticket/Elements/ShowMessageStanza12
-rw-r--r--rt/html/Ticket/Elements/ShowPeople6
-rw-r--r--rt/html/Ticket/Elements/ShowTransaction24
-rw-r--r--rt/html/Ticket/Elements/Tabs10
-rw-r--r--rt/html/Ticket/Modify.html2
-rw-r--r--rt/html/Ticket/ModifyAll.html2
-rw-r--r--rt/html/Ticket/ModifyPeople.html3
-rw-r--r--rt/html/Ticket/Update.html36
-rw-r--r--rt/html/User/Prefs.html106
-rw-r--r--rt/html/autohandler144
-rw-r--r--rt/html/index.html3
65 files changed, 2394 insertions, 276 deletions
diff --git a/rt/html/Admin/Elements/EditCustomField b/rt/html/Admin/Elements/EditCustomField
index a09600b..7baed16 100644
--- a/rt/html/Admin/Elements/EditCustomField
+++ b/rt/html/Admin/Elements/EditCustomField
@@ -24,7 +24,7 @@
<& /Elements/ListActions, actions => \@results &>
-<FORM METHOD=GET ACTION="CustomField.html">
+<FORM METHOD=POST ACTION="CustomField.html">
<INPUT TYPE=HIDDEN NAME="CustomField" VALUE="<%$id %>">
<INPUT TYPE=HIDDEN name="Queue" value="<%$Queue%>">
diff --git a/rt/html/Admin/Elements/EditCustomFieldValues b/rt/html/Admin/Elements/EditCustomFieldValues
index 64564ad..2c9e6d0 100644
--- a/rt/html/Admin/Elements/EditCustomFieldValues
+++ b/rt/html/Admin/Elements/EditCustomFieldValues
@@ -25,7 +25,7 @@
<ul>
% while (my $v = $values->Next) {
<li>
-<font size=-1 color="#336699"><%$v->SortOrder%>:</font>
+<INPUT TYPE="text" SIZE="2" NAME="CustomField-<%$CustomField->Id%>-SortOrder<%$v->Id()%>" VALUE="<%$v->SortOrder()%>">
<input type="checkbox" name="CustomField-<%$CustomField->Id%>-DeleteValue" value="<%$v->id%>">
<%$v->Name%>
% if ($v->Description) {
diff --git a/rt/html/Admin/Elements/EditCustomFields b/rt/html/Admin/Elements/EditCustomFields
index a86b051..81c984d 100644
--- a/rt/html/Admin/Elements/EditCustomFields
+++ b/rt/html/Admin/Elements/EditCustomFields
@@ -26,44 +26,43 @@
<TABLE>
<TR>
<TD VALIGN=TOP>
-<%$caption%>:<BR>
+<h2><%$caption%></h2>
</TD></TR></TABLE>
% if ($CustomFields->Count == 0 ) {
<P><i><&|/l&>(No custom fields)</&></i></P>
% } else {
-<TABLE>
-
-<TR>
-<TD ROWSPAN="<% $CustomFields->Count %>">
-<UL>
-% while (my $CustomFieldObj = $CustomFields->Next) {
-<LI><A HREF="CustomField.html?Queue=<%$id%>&CustomField=<%$CustomFieldObj->id()%>"><b><%$CustomFieldObj->Name%></b></a> (<% $CustomFieldObj->FriendlyType %>)<br>
-<%$CustomFieldObj->Description%>
-</LI>
-% }
-</UL>
-</TD>
-
+<TABLE cellspacing=0 cellpadding=2>
% my $count;
% while (my $CustomFieldObj = $CustomFields->Next) {
+<TR>
+ <TD valign="TOP">
+% if ($CustomFieldObj->Name) {
+ <A HREF="CustomField.html?Queue=<%$id%>&CustomField=<%$CustomFieldObj->id()%>"><b><%$CustomFieldObj->Name%></b></a><br>
+% } else {
+ <A HREF="CustomField.html?Queue=<%$id%>&CustomField=<%$CustomFieldObj->id()%>"><i>(<%loc("no name")%>)</i></a><br>
+% }
+ <%$CustomFieldObj->Description%>
+ </TD>
+ <TD valign="TOP">
+ <i><% $CustomFieldObj->FriendlyType %></i>
+ </TD>
% # show 'move up' unless it's the first item
% if ($count++) {
-<TR><TD>
-<a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=-1"><&|/l&>Move up</&></a>
+ <TD valign="TOP">
+ <a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=-1"><&|/l&>Move up</&></a>
% } else {
-<TD ALIGN=RIGHT>
+ <TD valign="TOP" ALIGN=RIGHT>
% }
% # show 'move down' unless it's the last item
% if (!$CustomFields->IsLast) {
% $m->print(' | ') if $count > 1;
-<a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=1"><&|/l&>Move down</&></a>
+ <a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=1"><&|/l&>Move down</&></a>
% }
-</TD></TR>
-% }
-
</TD>
</TR>
+% }
+
</TABLE>
% }
<FORM METHOD=GET ACTION="CustomFields.html">
diff --git a/rt/html/Admin/Elements/EditScrip b/rt/html/Admin/Elements/EditScrip
index 5393ebf..1f186c2 100644
--- a/rt/html/Admin/Elements/EditScrip
+++ b/rt/html/Admin/Elements/EditScrip
@@ -77,6 +77,14 @@
</TR>
<TR>
<TD ALIGN=RIGHT>
+<&|/l&>Stage</&>:
+</TD>
+<TD>
+<& /Admin/Elements/SelectStage, Name => "Scrip-$id-Stage", Default => $scrip->Stage &>
+</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT>
<&|/l&>Template</&>:
</TD>
<TD>
@@ -123,6 +131,7 @@ elsif ($id) {
ScripAction
ScripCondition
Template
+ Stage
Description
CustomPrepareCode
CustomCommitCode
diff --git a/rt/html/Admin/Elements/EditScrips b/rt/html/Admin/Elements/EditScrips
index 24515d8..07a57f4 100644
--- a/rt/html/Admin/Elements/EditScrips
+++ b/rt/html/Admin/Elements/EditScrips
@@ -48,7 +48,9 @@
</TABLE>
% }
-<& /Elements/Submit &>
+<& /Elements/Submit,
+ Caption => loc("Delete selected scrips"),
+ Label => loc("Delete") &>
</form>
<%init>
my (@actions);
diff --git a/rt/html/Admin/Elements/SelectGroups b/rt/html/Admin/Elements/SelectGroups
index 5df49ad..3cc909b 100644
--- a/rt/html/Admin/Elements/SelectGroups
+++ b/rt/html/Admin/Elements/SelectGroups
@@ -29,9 +29,10 @@
<%INIT>
my $groups = new RT::Groups($session{'CurrentUser'});
-$groups->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'System');
+$groups->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => $Domain);
</%INIT>
<%ARGS>
$Name => 'groups'
+$Domain => 'UserDefined';
</%ARGS>
diff --git a/rt/html/Admin/Elements/SelectRights b/rt/html/Admin/Elements/SelectRights
index 37a06dc..8d87ac9 100644
--- a/rt/html/Admin/Elements/SelectRights
+++ b/rt/html/Admin/Elements/SelectRights
@@ -24,7 +24,7 @@
<INPUT TYPE=HIDDEN NAME="CheckACL" VALUE="<%$ACLDesc%>">
<TABLE BORDER=0>
<TR>
-<TD valign=top width="180">
+<TD valign=top width="180" align="left">
<h3><&|/l&>Current rights</&></h3>
% if ($ACLObj->Count() > 0) {
<i>(<&|/l&>Check box to revoke right</&>)</i> <BR>
@@ -71,6 +71,7 @@
$ACLObj->LimitToObject( $Object);
$ACLObj->LimitToPrincipal( Id => $PrincipalId);
+ $ACLObj->OrderBy(FIELD=>'RightName');
if (ref($Object) && UNIVERSAL::can($Object, 'AvailableRights')) {
%Rights = %{$Object->AvailableRights};
diff --git a/rt/html/Admin/Elements/SelectStage b/rt/html/Admin/Elements/SelectStage
new file mode 100644
index 0000000..b62964b
--- /dev/null
+++ b/rt/html/Admin/Elements/SelectStage
@@ -0,0 +1,39 @@
+%# 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
+<SELECT NAME=<%$Name%>>
+% foreach my $stage (qw(TransactionCreate TransactionBatch)) {
+<OPTION VALUE=<%$stage%>
+<% ($stage eq $Default) && 'SELECTED' %>
+><% loc($stage) %>
+</OPTION>
+% }
+<%INIT>
+if ($Default eq '') {
+ $Default = 'TransactionCreate';
+}
+</%INIT>
+<%ARGS>
+$Default => 'TransactionCreate'
+$Name => 'Stage'
+</%ARGS>
diff --git a/rt/html/Admin/Queues/CustomFields.html b/rt/html/Admin/Queues/CustomFields.html
index 78c6c27..ddf39d7 100644
--- a/rt/html/Admin/Queues/CustomFields.html
+++ b/rt/html/Admin/Queues/CustomFields.html
@@ -32,7 +32,8 @@
<& /Admin/Elements/EditCustomFields, title => $title, %ARGS &>
<%INIT>
my $Queue = new RT::Queue($session{'CurrentUser'});
-$Queue->Load($id);
+$Queue->Load($id) || Abort(loc("Couldn't load queue", $id));
+
my $CustomFields = RT::CustomFields->new($RT::SystemUser);
$CustomFields->LimitToQueue($Queue->Id);
my $subtabs = {
diff --git a/rt/html/Admin/Queues/index.html b/rt/html/Admin/Queues/index.html
index f733c25..78a1d5d 100644
--- a/rt/html/Admin/Queues/index.html
+++ b/rt/html/Admin/Queues/index.html
@@ -38,7 +38,7 @@
%}
</UL>
<BR>
-<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Queues/">
+<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Queues/index.html">
<input type="checkbox" name="FindDisabledQueues"> <&|/l&>Include disabled queues in listing.</&>
<div align=right><input type=submit value="<&|/l&>Go!</&>"></div>
</FORM>
diff --git a/rt/html/Admin/Users/Modify.html b/rt/html/Admin/Users/Modify.html
index 370c2e8..b424ae9 100644
--- a/rt/html/Admin/Users/Modify.html
+++ b/rt/html/Admin/Users/Modify.html
@@ -224,9 +224,11 @@ else {
} else {
push @results, loc('User could not be created: [_1]', $msg);
}
-
- }
- else {
+
+ # set the id, so the the menu will have the right info
+ $id = $UserObj->Id;
+
+ } else {
$UserObj->Load($id) || $UserObj->Load($Name) || Abort("Couldn't load user '$Name'");
$val = $UserObj->Id();
}
diff --git a/rt/html/Admin/Users/index.html b/rt/html/Admin/Users/index.html
index a95d411..7dc9af6 100644
--- a/rt/html/Admin/Users/index.html
+++ b/rt/html/Admin/Users/index.html
@@ -40,7 +40,7 @@
</UL>
<br><br>
-<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Users/">
+<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Users/index.html">
<&|/l&>Find people whose</&> <& /Elements/SelectUsers &><BR>
<input type="checkbox" name="FindDisabledUsers"> <&|/l&>Include disabled users in search.</&>
diff --git a/rt/html/Approvals/Display.html b/rt/html/Approvals/Display.html
index 921c1e3..6a265e2 100644
--- a/rt/html/Approvals/Display.html
+++ b/rt/html/Approvals/Display.html
@@ -26,7 +26,7 @@
<& Elements/Tabs,
current_tab => "Approvals/Display.html",
Title => $title &>
-<form method=post action="<%$RT::WebPath%>/Approvals/">
+<form method=post action="<%$RT::WebPath%>/Approvals/index.html">
<& /Elements/TitleBoxStart, title => $title &>
<& /Ticket/Elements/ShowHistory , Ticket => $Ticket, Collapsed => 0, ShowTitle => 0, ShowHeaders => 0, ShowDisplayModes => 0, ShowTitleBarCommands => 0 &>
diff --git a/rt/html/Elements/Callback b/rt/html/Elements/Callback
index 93ac4c0..79157e7 100644
--- a/rt/html/Elements/Callback
+++ b/rt/html/Elements/Callback
@@ -54,10 +54,11 @@ if (!$callbacks) {
$cache{$Page,$_CallbackName} = $callbacks;
}
-foreach my $comp (@$callbacks) {
- $m->comp($comp, %ARGS) if $m->comp_exists($comp);
+my @rv;
+foreach my $comp (sort @$callbacks) {
+ push @rv, $m->comp($comp, %ARGS) if $m->comp_exists($comp);
}
-return(1);
+return @rv;
</%init>
<%args>
$_CallbackName => 'Default'
diff --git a/rt/html/Elements/MessageBox b/rt/html/Elements/MessageBox
index 64fdf38..32f4222 100644
--- a/rt/html/Elements/MessageBox
+++ b/rt/html/Elements/MessageBox
@@ -21,7 +21,7 @@
%#
%#
%# END LICENSE BLOCK
-<TEXTAREA COLS=<%$Width%> ROWS=15 WRAP=HARD NAME="<%$Name%>"><& /Elements/Callback, %ARGS &><% $Default %><%$message%><%$signature%></TEXTAREA>
+<TEXTAREA COLS=<%$Width%> ROWS=15 WRAP=<%$Wrap%> NAME="<%$Name%>"><& /Elements/Callback, %ARGS &><% $Default %><%$message%><%$IncludeSignature ? $signature : ''%></TEXTAREA>
<%INIT>
my ($message);
@@ -42,6 +42,8 @@ if ($session{'CurrentUser'}->UserObj->Signature) {
$QuoteTransaction => undef
$Name => 'Content'
$Default => ''
-$Width => 72
+$Width => $RT::MessageBoxWidth
+$Wrap => $RT::MessageBoxWrap
+$IncludeSignature => 1
</%ARGS>
diff --git a/rt/html/Elements/MyTickets b/rt/html/Elements/MyTickets
index 6e2ddc6..52dae3b 100644
--- a/rt/html/Elements/MyTickets
+++ b/rt/html/Elements/MyTickets
@@ -69,7 +69,7 @@
<%INIT>
-my $rows = 10;
+my $rows = $RT::MyTicketsLength;
my $MyTickets;
$MyTickets = new RT::Tickets ($session{'CurrentUser'});
$MyTickets->LimitOwner(VALUE => $session{'CurrentUser'}->Id);
diff --git a/rt/html/Elements/SelectLang b/rt/html/Elements/SelectLang
new file mode 100644
index 0000000..cc2c357
--- /dev/null
+++ b/rt/html/Elements/SelectLang
@@ -0,0 +1,56 @@
+%# 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
+<SELECT NAME ="<%$Name%>">
+% if ($ShowNullOption) {
+<OPTION VALUE="">-</OPTION>
+% }
+% foreach my $lang (@lang) {
+<OPTION VALUE="<%$lang%>" <%($Default && ($lang eq $Default)) && 'SELECTED'%>><% $lang_to_desc{$lang} %>
+% if (($Verbose) and (my $description = I18N::LangTags::List::native_name($lang)) ){
+(<%$description%>)
+% }
+</OPTION>
+% }
+</SELECT>
+<%ARGS>
+$ShowNullOption => 1
+$ShowAllQueues => 1
+$Name => undef
+$Verbose => undef
+$Default => 0
+$Lite => 0
+</%ARGS>
+
+<%ONCE>
+use I18N::LangTags::List;
+my (@lang, %lang_to_desc);
+foreach my $lang (map { s/:://; s/_/-/g; $_ } grep { /^\w+::$/ } keys %RT::I18N::) {
+ next if $lang =~ /i-default|en-us/;
+ my $desc = I18N::LangTags::List::name($lang);
+ next unless ($desc);
+ $desc =~ s/(.*) (.*)/$2 ($1)/;
+ $lang_to_desc{$lang} = $desc;
+}
+@lang = sort { $lang_to_desc{$a} cmp $lang_to_desc{$b} } keys %lang_to_desc;
+</%ONCE>
diff --git a/rt/html/Elements/SelectStatus b/rt/html/Elements/SelectStatus
index 2c1ffad..16a5f29 100644
--- a/rt/html/Elements/SelectStatus
+++ b/rt/html/Elements/SelectStatus
@@ -24,6 +24,7 @@
<SELECT NAME ="<%$Name%>">
<OPTION VALUE="">-</OPTION>
%foreach my $status (@status) {
+%next if ($SkipDeleted && $status eq 'deleted');
<OPTION VALUE="<%$status%>" <%($Default eq $status) && 'SELECTED'%>><%loc($status)%></OPTION>
% }
</SELECT>
@@ -34,4 +35,5 @@ my @status = $queue->StatusArray();
<%ARGS>
$Name => undef
$Default => undef
+$SkipDeleted => 0
</%ARGS>
diff --git a/rt/html/Elements/SelectWatcherType b/rt/html/Elements/SelectWatcherType
index 26de8f7..82aab2a 100644
--- a/rt/html/Elements/SelectWatcherType
+++ b/rt/html/Elements/SelectWatcherType
@@ -22,7 +22,9 @@
%#
%# END LICENSE BLOCK
<SELECT NAME ="<%$Name%>">
+% if ($AllowNull) {
<OPTION VALUE="">-</OPTION>
+% }
%for my $option (@types) {
<OPTION VALUE="<%$option%>" <%$option eq $Default && "SELECTED"%>><%loc($option)%></OPTION>
%}
@@ -38,6 +40,7 @@ else {
}
</%INIT>
<%ARGS>
+$AllowNull => 1
$Default=>undef
$Scope => 'ticket'
$Name => 'WatcherType'
diff --git a/rt/html/Elements/SetupSessionCookie b/rt/html/Elements/SetupSessionCookie
index 4d728ce..7a2ad9f 100644
--- a/rt/html/Elements/SetupSessionCookie
+++ b/rt/html/Elements/SetupSessionCookie
@@ -22,18 +22,25 @@
%#
%# END LICENSE BLOCK
<%init>
+return if $m->is_subrequest; # avoid reentrancy, as suggested by masonbook
+
my %cookies = CGI::Cookie->fetch();
+my $cookiename = "RT_SID_".$RT::rtname.".".$ENV{'SERVER_PORT'};
my %backends = (
mysql => 'Apache::Session::MySQL',
Pg => 'Apache::Session::Postgres',
- Oracle => 'Apache::Session::Oracle',
+# Oracle => 'Apache::Session::Oracle',
) unless $RT::WebSessionClass;
my $session_class = $RT::WebSessionClass || $backends{$RT::DatabaseType} || 'Apache::Session::File';
my $pm = "$session_class.pm"; $pm =~ s|::|/|g; require $pm;
+ # morning bug avoidance attempt -- pdh 20030815
+ unless ($RT::Handle->dbh && $RT::Handle->dbh->ping) {
+ $RT::Handle->Connect();
+ }
eval {
tie %session, $session_class,
- $SessionCookie || ( $cookies{'RT_SID'} ? $cookies{'RT_SID'}->value() : undef ),
+ $SessionCookie || ( $cookies{$cookiename} ? $cookies{$cookiename}->value() : undef ),
$backends{$RT::DatabaseType} ? {
Handle => $RT::Handle->dbh,
LockHandle => $RT::Handle->dbh,
@@ -54,22 +61,23 @@ my $pm = "$session_class.pm"; $pm =~ s|::|/|g; require $pm;
Directory => $RT::MasonSessionDir,
LockDirectory => $RT::MasonSessionDir,
};
- undef $cookies{'RT_SID'};
+ undef $cookies{$cookiename};
}
else {
die "RT Couldn't write to session directory '$RT::MasonSessionDir': $@. Check that this dir ectory's permissions are correct.";
}
}
- if ( !$cookies{'RT_SID'} ) {
+ if ( !$cookies{$cookiename} ) {
my $cookie = new CGI::Cookie(
- -name => 'RT_SID',
+ -name => $cookiename,
-value => $session{_session_id},
-path => '/',
);
$r->header_out('Set-Cookie', $cookie->as_string);
}
+
return();
</%init>
<%args>
diff --git a/rt/html/Elements/SimpleSearch b/rt/html/Elements/SimpleSearch
index 69541f8..4a0d106 100644
--- a/rt/html/Elements/SimpleSearch
+++ b/rt/html/Elements/SimpleSearch
@@ -22,6 +22,6 @@
%#
%# END LICENSE BLOCK
<form action="<% $RT::WebPath %>/index.html">
-<input size="12" name="q" accesskey="0">
+<input size="12" name="q" autocomplete="off" accesskey="0">
<input type="submit" value="<&|/l&>Search</&>">&nbsp;
</form>
diff --git a/rt/html/NoAuth/webrt.css b/rt/html/NoAuth/webrt.css
index 62c6d66..159e79c 100644
--- a/rt/html/NoAuth/webrt.css
+++ b/rt/html/NoAuth/webrt.css
@@ -331,7 +331,9 @@ ul.topnav {
margin-bottom:0;
}
-
+<%flags>
+inherit => undef
+</%flags>
<%init>
$r->content_type('text/css');
$r->header_out('Expires' ,'+30m');
diff --git a/rt/html/REST/1.0/Forms/queue/default b/rt/html/REST/1.0/Forms/queue/default
new file mode 100644
index 0000000..ce54088
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/queue/default
@@ -0,0 +1,123 @@
+%# REST/1.0/Forms/queue/default
+%#
+<%ARGS>
+$id
+$format => 's'
+$changes => {}
+</%ARGS>
+<%perl>
+my @comments;
+my ($c, $o, $k, $e) = ("", [], {}, 0);
+my %data = %$changes;
+my $queue = new RT::Queue $session{CurrentUser};
+my @fields = qw(Name Description CorrespondAddress CommentAddress
+ InitialPriority FinalPriority DefaultDueIn);
+my %fields = map { lc $_ => $_ } @fields;
+
+if ($id ne 'new') {
+ $queue->Load($id);
+ if (!$queue->Id) {
+ return [ "# Queue $id does not exist.", [], {}, 1 ];
+ }
+}
+else {
+ if (%data == 0) {
+ return [
+ "# Required: Name",
+ [ "id", @fields ],
+ {
+ id => 'queue/new',
+ Name => '<queue name>',
+ Description => "",
+ CommentAddress => "",
+ CorrespondAddress => "",
+ InitialPriority => "",
+ FinalPriority => "",
+ DefaultDueIn => "",
+ },
+ 0
+ ];
+ }
+ else {
+ my %v;
+ my %create = %fields;
+
+ foreach my $k (keys %data) {
+ if (exists $create{lc $k}) {
+ $v{$create{lc $k}} = delete $data{$k};
+ }
+ }
+
+ if ($v{Name} eq '<queue name>') {
+ my %o = keys %$changes;
+ delete @o{"id", @fields};
+ return [
+ "# Please set the queue name.",
+ [ "id", @fields, keys %o ], $changes, 1
+ ];
+ }
+
+ $queue->Create(%v);
+ unless ($queue->Id) {
+ return [ "# Could not create queue.", [], {}, 1 ];
+ }
+
+ delete $data{id};
+ $id = $queue->Id;
+ push(@comments, "# Queue $id created.");
+ goto DONE if %data == 0;
+ }
+}
+
+if (%data == 0) {
+ my @data;
+
+ push @data, [ id => "queue/".$queue->Id ];
+ foreach my $key (@fields) {
+ push @data, [ $key => $queue->$key ];
+ }
+
+ my %k = map {@$_} @data;
+ $o = [ map {$_->[0]} @data ];
+ $k = \%k;
+}
+else {
+ my ($get, $set, $key, $val, $n, $s);
+
+ foreach $key (keys %data) {
+ $val = $data{$key};
+ $key = lc $key;
+ $n = 1;
+
+ if (exists $fields{$key}) {
+ $key = $fields{$key};
+ $set = "Set$key";
+
+ next if $val eq $queue->$key;
+ ($n, $s) = $queue->$set($val);
+ }
+ elsif ($key ne 'id') {
+ $n = 0;
+ $s = "Unknown field.";
+ }
+
+ SET:
+ if ($n == 0) {
+ $e = 1;
+ push @comments, "# $key: $s";
+ unless (@$o) {
+ my %o = keys %$changes;
+ delete @o{"id", @fields};
+ @$o = ("id", @fields, keys %o);
+ $k = $changes;
+ }
+ }
+ }
+
+ push(@comments, "# Queue $id updated.") unless $n == 0;
+}
+
+DONE:
+$c ||= join("\n", @comments) if @comments;
+return [ $c, $o, $k, $e ];
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/queue/ns b/rt/html/REST/1.0/Forms/queue/ns
new file mode 100644
index 0000000..360eea8
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/queue/ns
@@ -0,0 +1,38 @@
+%# 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
+%# REST/1.0/Forms/queue/ns
+%#
+<%ARGS>
+$id
+</%ARGS>
+<%perl>
+use RT::Queues;
+
+my $queues = new RT::Queues $session{CurrentUser};
+$queues->Limit(FIELD => 'Name', OPERATOR => '=', VALUE => $id);
+if ($queues->Count == 0) {
+ return (0, "No queue named $id exists.");
+}
+return $queues->Next->Id;
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/ticket/attachments b/rt/html/REST/1.0/Forms/ticket/attachments
new file mode 100644
index 0000000..bcb571a
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/ticket/attachments
@@ -0,0 +1,107 @@
+%# 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
+%# REST/1.0/Forms/ticket/attachments
+%#
+<%ARGS>
+$id
+$args => undef
+</%ARGS>
+<%perl>
+my @data;
+my ($c, $o, $k, $e) = ("", [], {}, "");
+my $ticket = new RT::Ticket $session{CurrentUser};
+
+$ticket->Load($id);
+unless ($ticket->Id) {
+ return [ "# Ticket $id does not exist.", [], {}, 1 ];
+}
+
+my @arglist = split('/', $args);
+my ($aid, $content);
+
+if ($arglist[1] eq 'content') {
+ $aid = $arglist[0];
+ $content = 1;
+} else {
+ $aid = $args;
+ $content = 0;
+}
+
+if ($aid) {
+ unless ($aid =~ /^\d+$/) {
+ return [ "# Invalid attachment id: $aid", [], {}, 1 ];
+ }
+ my $attachment = new RT::Attachment $session{CurrentUser};
+ $attachment->Load($aid);
+ unless ($attachment->Id eq $aid) {
+ return [ "# Invalid attachment id: $aid", [], {}, 1 ];
+ }
+ if ($content) {
+ $c = $attachment->Content;
+ } else {
+ my @data;
+ push @data, [ id => $attachment->Id ];
+ push @data, [ Subject => $attachment->Subject ];
+ push @data, [ Creator => $attachment->Creator ];
+ push @data, [ Created => $attachment->Created ];
+ push @data, [ Transaction => $attachment->TransactionId ];
+ push @data, [ Parent => $attachment->Parent ];
+ push @data, [ MessageId => $attachment->MessageId ];
+ push @data, [ Filename => $attachment->Filename ];
+ push @data, [ ContentType => $attachment->ContentType ];
+ push @data, [ ContentEncoding => $attachment->ContentEncoding ];
+ push @data, [ Headers => $attachment->Headers ];
+ push @data, [ Content => $attachment->Content ];
+
+ my %k = map {@$_} @data;
+ $o = [ map {$_->[0]} @data ];
+ $k = \%k;
+ }
+
+}
+else {
+ my @attachments;
+ my $transactions = $ticket->Transactions;
+ while (my $t = $transactions->Next) {
+ my $attachments = $t->Attachments;
+ while (my $a = $attachments->Next) {
+ next unless $a->Filename;
+ my $size = length($a->Content);
+ if ($size > 1024) { $size = int($size/102.4)/10 . "k" }
+ else { $size .= "b" }
+ push @attachments, $a->Id.": ".$a->Filename." (".$size.")";
+ }
+ }
+
+ if (@attachments) {
+ $o = [ "id", "Attachments" ];
+ $k = {
+ id => "ticket/".$ticket->Id."/attachments",
+ Attachments => \@attachments
+ };
+ }
+}
+
+return [ $c, $o, $k, $e ];
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/ticket/default b/rt/html/REST/1.0/Forms/ticket/default
new file mode 100644
index 0000000..fec499b
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/ticket/default
@@ -0,0 +1,253 @@
+%# REST/1.0/Forms/ticket/default
+%#
+<%ARGS>
+$id
+$changes => {}
+$fields => undef
+</%ARGS>
+<%perl>
+use MIME::Entity;
+
+my @comments;
+my ($c, $o, $k, $e) = ("", [], {}, 0);
+my %data = %$changes;
+my $ticket = new RT::Ticket $session{CurrentUser};
+my @dates = qw(Created Starts Started Due Resolved Told);
+my @people = qw(Requestors Cc AdminCc);
+my @create = qw(Queue Requestor Subject Cc AdminCc Owner Status Priority
+ InitialPriority FinalPriority TimeEstimated TimeWorked
+ TimeLeft Starts Started Due Resolved);
+my @simple = qw(Subject Status Priority Disabled TimeEstimated TimeWorked
+ TimeLeft InitialPriority FinalPriority);
+my %dates = map {lc $_ => $_} @dates;
+my %people = map {lc $_ => $_} @people;
+my %create = map {lc $_ => $_} @create;
+my %simple = map {lc $_ => $_} @simple;
+
+# Are we dealing with an existing ticket?
+if ($id ne 'new') {
+ $ticket->Load($id);
+ if (!$ticket->Id) {
+ return [ "# Ticket $id does not exist.", [], {}, 1 ];
+ }
+ elsif (!$ticket->CurrentUserHasRight('ShowTicket') ||
+ (%data && !$ticket->CurrentUserHasRight('ModifyTicket')))
+ {
+ my $act = %data ? "modify" : "display";
+ return [ "# You are not allowed to $act ticket $id.", [], {}, 1 ];
+ }
+}
+else {
+ if (%data == 0) {
+ # GET ticket/new: Return a suitable default form.
+ # We get defaults from queue/1 (XXX: What if it isn't there?).
+ my $due = new RT::Date $session{CurrentUser};
+ my $queue = new RT::Queue $session{CurrentUser};
+ my $starts = new RT::Date $session{CurrentUser};
+ $queue->Load(1);
+ $due->SetToNow;
+ $due->AddDays($queue->DefaultDueIn) if $queue->DefaultDueIn;
+ $starts->SetToNow;
+
+ return [
+ "# Required: Queue, Requestor, Subject",
+ [ qw(id Queue Requestor Subject Cc AdminCc Owner Status Priority
+ InitialPriority FinalPriority TimeEstimated Starts Due Text) ],
+ {
+ id => "ticket/new",
+ Queue => $queue->Name,
+ Requestor => $session{CurrentUser}->Name,
+ Subject => "",
+ Cc => [],
+ AdminCc => [],
+ Owner => "",
+ Status => "new",
+ Priority => $queue->InitialPriority,
+ InitialPriority => $queue->InitialPriority,
+ FinalPriority => $queue->FinalPriority,
+ TimeEstimated => 0,
+ Starts => $starts->ISO,
+ Due => $due->ISO,
+ Text => "",
+ },
+ 0
+ ];
+ }
+ else {
+ # We'll create a new ticket, and fall through to set fields that
+ # can't be set in the call to Create().
+ my (%v, $text);
+
+ foreach my $k (keys %data) {
+ if (exists $create{lc $k}) {
+ $v{$create{lc $k}} = delete $data{$k};
+ }
+ elsif (lc $k eq 'text') {
+ $text = delete $data{$k};
+ }
+ }
+
+ if ($text) {
+ $v{MIMEObj} =
+ MIME::Entity->build(
+ From => $session{CurrentUser}->EmailAddress,
+ Subject => $v{Subject},
+ Data => $text
+ );
+ }
+
+ $ticket->Create(%v);
+ unless ($ticket->Id) {
+ return [ "# Could not create ticket.", [], {}, 1 ];
+ }
+
+ delete $data{id};
+ $id = $ticket->Id;
+ push(@comments, "# Ticket $id created.");
+ goto DONE if %data == 0;
+ }
+}
+
+# Now we know we're dealing with an existing ticket.
+if (%data == 0) {
+ my ($time, $key, $val, @data);
+
+ push @data, [ id => "ticket/".$ticket->Id ];
+ push @data, [ Queue => $ticket->QueueObj->Name ]
+ if (!%$fields || exists $fields->{lc 'Queue'});
+ push @data, [ Owner => $ticket->OwnerObj->Name ]
+ if (!%$fields || exists $fields->{lc 'Owner'});
+ push @data, [ Creator => $ticket->CreatorObj->Name ]
+ if (!%$fields || exists $fields->{lc 'Creator'});
+
+ foreach (qw(Subject Status Priority InitialPriority FinalPriority)) {
+ next unless (!%$fields || (exists $fields->{lc $_}));
+ push @data, [$_ => $ticket->$_ ];
+ }
+
+ foreach $key (@people) {
+ next unless (!%$fields || (exists $fields->{lc $key}));
+ push @data, [ $key => [ $ticket->$key->MemberEmailAddresses ] ];
+ }
+
+ $time = new RT::Date ($session{CurrentUser});
+ foreach $key (@dates) {
+ next unless (!%$fields || (exists $fields->{lc $key}));
+ $time->Set(Format => 'sql', Value => $ticket->$key);
+ push @data, [ $key => $time->AsString ];
+ }
+
+ $time = new RT::Date ($session{CurrentUser});
+ foreach $key (qw(TimeEstimated TimeWorked TimeLeft)) {
+ next unless (!%$fields || (exists $fields->{lc $key}));
+ $val = $ticket->$key || 0;
+ $val = $time->DurationAsString($val*60) if $val;
+ push @data, [ $key => $val ];
+ }
+
+ my %k = map {@$_} @data;
+ $o = [ map {$_->[0]} @data ];
+ $k = \%k;
+}
+else {
+ my ($get, $set, $key, $val, $n, $s);
+
+ foreach $key (keys %data) {
+ $val = $data{$key};
+ $key = lc $key;
+ $n = 1;
+
+ if (ref $val eq 'ARRAY') {
+ unless ($key =~ /^(?:Requestors|Cc|AdminCc)$/i) {
+ $n = 0;
+ $s = "$key may have only one value.";
+ goto SET;
+ }
+ }
+
+ if ($key =~ /^queue$/i) {
+ next if $val eq $ticket->QueueObj->Name;
+ ($n, $s) = $ticket->SetQueue($val);
+ }
+ elsif ($key =~ /^owner$/i) {
+ next if $val eq $ticket->OwnerObj->Name;
+ ($n, $s) = $ticket->SetOwner($val);
+ }
+ elsif (exists $simple{$key}) {
+ $key = $simple{$key};
+ $set = "Set$key";
+
+ next if $val eq $ticket->$key;
+ ($n, $s) = $ticket->$set($val);
+ }
+ elsif (exists $dates{$key}) {
+ $key = $dates{$key};
+ $set = "Set$key";
+
+ my $time = new RT::Date $session{CurrentUser};
+ $time->Set(Format => 'sql', Value => $ticket->$key);
+ next if ($val =~ /^not set$/i || $val eq $time->AsString);
+ ($n, $s) = $ticket->$set($val);
+ }
+ elsif (exists $people{$key}) {
+ $key = $people{$key};
+ my ($p, @msgs);
+
+ my %new = map {$_=>1} @{ vsplit($val) };
+ my %old = map {$_=>1} $ticket->$key->MemberEmailAddresses;
+ my $type = $key eq 'Requestors' ? 'Requestor' : $key;
+
+ foreach $p (keys %old) {
+ unless (exists $new{$p}) {
+ ($s, $n) = $ticket->DeleteWatcher(Type => $type,
+ Email => $p);
+ push @msgs, [ $s, $n ];
+ }
+ }
+ foreach $p (keys %new) {
+ # XXX: This is a stupid test.
+ unless ($p =~ /^[\w.+-]+\@([\w.-]+\.)*\w+.?$/) {
+ $s = 0;
+ $n = "$p is not a valid email address.";
+ push @msgs, [ $s, $n ];
+ next;
+ }
+ unless ($ticket->IsWatcher(Type => $type, Email => $p)) {
+ ($s, $n) = $ticket->AddWatcher(Type => $type,
+ Email => $p);
+ push @msgs, [ $s, $n ];
+ }
+ }
+
+ $n = 1;
+ if (@msgs = grep {$_->[0] == 0} @msgs) {
+ $n = 0;
+ $s = join "\n", map {"# ".$_->[1]} @msgs;
+ $s =~ s/^# //;
+ }
+ }
+ elsif ($key ne 'id' && $key ne 'type') {
+ $n = 0;
+ $s = "Unknown field.";
+ }
+
+ SET:
+ if ($n == 0) {
+ $e = 1;
+ push @comments, "# $key: $s";
+ unless (@$o) {
+ my %o = keys %$changes;
+ delete $o{id};
+ @$o = ("id", keys %o);
+ $k = $changes;
+ }
+ }
+ }
+ push(@comments, "# Ticket ".$ticket->id." updated.") unless $n == 0;
+}
+
+DONE:
+$c ||= join("\n", @comments) if @comments;
+return [$c, $o, $k, $e];
+
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/ticket/history b/rt/html/REST/1.0/Forms/ticket/history
new file mode 100644
index 0000000..f5c1dc9
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/ticket/history
@@ -0,0 +1,144 @@
+%# REST/1.0/Forms/ticket/history
+%#
+<%ARGS>
+$id
+$args => undef
+$format => undef
+$fields => undef
+</%ARGS>
+<%perl>
+my $ticket = new RT::Ticket $session{CurrentUser};
+my ($c, $o, $k, $e) = ("", [], {}, "");
+
+$ticket->Load($id);
+unless ($ticket->Id) {
+ return [ "# Ticket $id does not exist.", [], {}, 1 ];
+}
+
+my $trans = $ticket->Transactions();
+my $total = $trans->Count();
+
+chomp $args;
+my @arglist = split('/', $args);
+my ($type, $tid);
+
+if ($arglist[0] eq 'type') {
+ $type = $arglist[1];
+} elsif ($arglist[0] eq 'id') {
+ $tid = $arglist[1];
+} else {
+ $type = $args;
+}
+
+if ($type) {
+ # Create, Set, Status, Correspond, Comment, Give, Steal, Take, Told
+ # CustomField, AddLink, DeleteLink, AddWatcher, DelWatcher
+ if ($args =~ /^links?$/) {
+ $trans->Limit(FIELD => 'Type', OPERATOR => 'LIKE', VALUE => '%Link');
+ }
+ elsif ($args =~ /^watchers?$/) {
+ $trans->Limit(FIELD => 'Type', OPERATOR => 'LIKE', VALUE => '%Watcher');
+ }
+ else {
+ $trans->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => $type);
+ }
+} elsif ($tid) {
+ $trans->Limit(FIELD => 'Id', OPERATOR => '=', VALUE => $tid);
+}
+
+if ($tid) {
+ my @data;
+ my $t = new RT::Transaction $session{CurrentUser};
+ $t->Load($tid);
+
+ push @data, [ id => $t->Id ];
+ push @data, [ EffectiveTicket => $t->EffectiveTicket ]
+ if (!%$fields || exists $fields->{lc 'EffectiveTicket'});
+ push @data, [ Ticket => $t->Ticket ]
+ if (!%$fields || exists $fields->{lc 'Ticket'});
+ push @data, [ TimeTaken => $t->TimeTaken ]
+ if (!%$fields || exists $fields->{lc 'TimeTaken'});
+ push @data, [ Type => $t->Type ]
+ if (!%$fields || exists $fields->{lc 'Type'});
+ push @data, [ Field => $t->Field ]
+ if (!%$fields || exists $fields->{lc 'Field'});
+ push @data, [ OldValue => $t->OldValue ]
+ if (!%$fields || exists $fields->{lc 'OldValue'});
+ push @data, [ NewValue => $t->NewValue ]
+ if (!%$fields || exists $fields->{lc 'NewValue'});
+ push @data, [ Data => $t->Data ]
+ if (!%$fields || exists $fields->{lc 'Data'});
+ push @data, [ Description => $t->Description ]
+ if (!%$fields || exists $fields->{lc 'Description'});
+ push @data, [ Content => $t->Content ]
+ if (!%$fields || exists $fields->{lc 'Content'});
+
+
+ if (!%$fields || exists $fields->{lc 'Content'}) {
+ my $creator = new RT::User $session{CurrentUser};
+ $creator->Load($t->Creator);
+ push @data, [ Creator => $creator->Name ];
+ }
+ push @data, [ Created => $t->Created ]
+ if (!%$fields || exists $fields->{lc 'Created'});
+
+ if (!%$fields || exists $fields->{lc 'Attachments'}) {
+ my $attachlist;
+ my $attachments = $t->Attachments;
+ while (my $a = $attachments->Next) {
+ my $size = length($a->Content);
+ if ($size > 1024) { $size = int($size/102.4)/10 . "k" }
+ else { $size .= "b" }
+ $attachlist .= "\n" . $a->Id.": ".($a->Filename || "untitled")." (".$size.")";
+ }
+
+ push @data, [Attachments => $attachlist];
+ }
+
+ my %k = map {@$_} @data;
+ $o = [ map {$_->[0]} @data ];
+ $k = \%k;
+
+} else {
+ my (@data, $tids);
+ $format ||= "s";
+ $format = "l" if (%$fields);
+
+ while (my $t = $trans->Next) {
+ my $tid = $t->Id;
+
+ if ($format eq "l") {
+ $tids .= "," if $tids;
+ $tids .= $tid;
+ } else {
+ push @$o, $tid;
+ $k->{$tid} = $t->Description;
+ }
+ }
+
+ if ($format eq "l") {
+ my @tid;
+ push @tid, "ticket/$id/history/id/$tids";
+ my $fieldstring;
+ foreach my $key (keys %$fields) {
+ $fieldstring .= "," if $fieldstring;
+ $fieldstring .= $key;
+ }
+ my ($content, $forms);
+
+ $m->subexec("$RT::WebPath/REST/1.0/show",
+ id => \@tid,
+ format => $format,
+ fields => $fieldstring);
+ return [ $c, $o, $k, $e ];
+ }
+}
+
+if (!$c) {
+ my $sub = $trans->Count();
+ $c = "# $sub/$total ($args/total)";
+}
+
+return [ $c, $o, $k, $e ];
+
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/ticket/links b/rt/html/REST/1.0/Forms/ticket/links
new file mode 100644
index 0000000..8ac9dc2
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/ticket/links
@@ -0,0 +1,148 @@
+%# 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
+%# REST/1.0/Forms/ticket/links
+%#
+<%ARGS>
+$id
+$format => 's'
+$changes => undef
+</%ARGS>
+<%perl>
+my @data;
+my $ticket = new RT::Ticket $session{CurrentUser};
+
+$ticket->Load($id);
+if (!$ticket->Id) {
+ return [ "# Ticket $id does not exist.", [], {}, 1 ];
+}
+
+my ($c, $o, $k, $e) = ("", [], {}, 0);
+my @fields = qw(DependsOn DependedOnBy RefersTo ReferredToBy Members MemberOf);
+my %fields = map { lc $_ => $_ } @fields;
+
+my %lfields = (
+ Members => { Type => 'MemberOf', Mode => 'Base' },
+ ReferredToBy => { Type => 'RefersTo', Mode => 'Base' },
+ DependedOnBy => { Type => 'DependsOn', Mode => 'Base' },
+ MemberOf => { Type => 'MemberOf', Mode => 'Target' },
+ RefersTo => { Type => 'RefersTo', Mode => 'Target' },
+ DependsOn => { Type => 'DependsOn', Mode => 'Target' },
+);
+
+if ($changes) {
+ my ($get, $set, $key, $val, $n, $s);
+ my %data = %$changes;
+ my @comments;
+
+ foreach $key (keys %data) {
+ $val = $data{$key};
+ $key = lc $key;
+ $n = 1;
+
+ if (exists $fields{$key}) {
+ $key = $fields{$key};
+
+ my %old;
+ my $field = $lfields{$key}->{Mode};
+ while (my $link = $ticket->$key->Next) {
+ $old{$link->$field} = 1;
+ }
+
+ my %new;
+ foreach my $nkey (@{vsplit($val)}) {
+ if ($nkey =~ /^\d+$/) {
+ my $uri = new RT::URI $session{CurrentUser};
+ my $tick = new RT::Ticket $session{CurrentUser};
+ $tick->Load($nkey);
+ if ($tick->Id) {
+ $nkey = $uri->FromObject($tick);
+ }
+ else {
+ $n = 0;
+ $s = "Ticket $nkey does not exist.";
+ goto SET;
+ }
+ }
+ $new{$nkey} = 1;
+ }
+
+ foreach my $u (keys %old) {
+ if (exists $new{$u}) {
+ delete $new{$u};
+ }
+ else {
+ my $type = $lfields{$key}->{Type};
+ my $mode = $lfields{$key}->{Mode};
+ ($n, $s) = $ticket->DeleteLink(Type => $type, $mode => $u);
+ goto SET;
+ }
+ }
+ foreach my $u (keys %new) {
+ my $type = $lfields{$key}->{Type};
+ my $mode = $lfields{$key}->{Mode};
+ ($n, $s) = $ticket->AddLink(Type => $type, $mode => $u);
+ goto SET;
+ }
+ }
+ elsif ($key ne 'id' && $key ne 'type') {
+ $n = 0;
+ $s = "Unknown field: $key";
+ }
+
+ SET:
+ if ($n == 0) {
+ $e = 1;
+ push @comments, "# $key: $s";
+ unless (@$o) {
+ @$o = ("id", @fields);
+ %$k = %data;
+ }
+ }
+ }
+
+ push(@comments, "# Links for ticket $id updated.") unless @comments;
+ $c = join("\n", @comments) if @comments;
+}
+else {
+ my @data;
+
+ push @data, [ id => "ticket/".$ticket->Id."/links" ];
+ foreach my $key (@fields) {
+ my @val;
+
+ my $field = $lfields{$key}->{Mode};
+ while (my $link = $ticket->$key->Next) {
+ push @val, $link->$field;
+ }
+ push(@val, "") if (@val == 0 && $format eq 'l');
+ push @data, [ $key => [ @val ] ] if @val;
+ }
+
+ my %k = map {@$_} @data;
+ $o = [ map {$_->[0]} @data ];
+ $k = \%k;
+}
+
+return [ $c, $o, $k, $e ];
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/user/default b/rt/html/REST/1.0/Forms/user/default
new file mode 100644
index 0000000..6b216e0
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/user/default
@@ -0,0 +1,141 @@
+%# REST/1.0/Forms/user/default
+%#
+<%ARGS>
+$id
+$format => 's'
+$changes => {}
+</%ARGS>
+<%perl>
+my @comments;
+my ($c, $o, $k, $e) = ("", [], {}, 0);
+my %data = %$changes;
+my $user = new RT::User $session{CurrentUser};
+my @fields = qw(RealName NickName Gecos Organization Address1 Address2 City
+ State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
+ FreeformContactInfo Comments Signature Lang EmailEncoding
+ WebEncoding ExternalContactInfoId ContactInfoSystem
+ ExternalAuthId AuthSystem);
+my %fields = map { lc $_ => $_ } @fields;
+
+if ($id ne 'new') {
+ $user->Load($id);
+ if (!$user->Id) {
+ return [ "# User $id does not exist.", [], {}, 1 ];
+ }
+}
+else {
+ if (%data == 0) {
+ return [
+ "# Required: Name, EmailAddress",
+ [ qw(id Name EmailAddress Organization Password Comments) ],
+ {
+ id => "user/new",
+ Name => "",
+ EmailAddress => "",
+ Organization => "",
+ Password => "",
+ Comments => ""
+ },
+ 0
+ ];
+ }
+ else {
+ my %v;
+ my %create = %fields;
+ $create{name} = "Name";
+ $create{password} = "Password";
+ $create{emailaddress} = "EmailAddress";
+ $create{contactinfo} = "FreeformContactInfo";
+ # Do any fields need to be excluded here?
+
+ foreach my $k (keys %data) {
+ if (exists $create{lc $k}) {
+ $v{$create{lc $k}} = delete $data{$k};
+ }
+ }
+
+ $user->Create(%v);
+ unless ($user->Id) {
+ return [ "# Could not create user.", [], {}, 1 ];
+ }
+
+ $id = $user->Id;
+ delete $data{id};
+ push(@comments, "# User $id created.");
+ goto DONE if %data == 0;
+ }
+}
+
+if (%data == 0) {
+ my @data;
+
+ push @data, [ id => "user/".$user->Id ];
+ push @data, [ Name => $user->Name ];
+ push @data, [ Password => '********' ];
+ push @data, [ EmailAddress => $user->EmailAddress ];
+
+ foreach my $key (@fields) {
+ my $val = $user->$key;
+
+ if ($format eq 'l' || (defined $val && $val ne '')) {
+ $key = "ContactInfo" if $key eq 'FreeformContactInfo';
+ push @data, [ $key => $val ];
+ }
+ }
+
+ my %k = map {@$_} @data;
+ $o = [ map {$_->[0]} @data ];
+ $k = \%k;
+}
+else {
+ my ($get, $set, $key, $val, $n, $s);
+
+ foreach $key (keys %data) {
+ $val = $data{$key};
+ $key = lc $key;
+ $n = 1;
+
+ if ($key eq 'name' || $key eq 'emailaddress' ||
+ $key eq 'contactinfo' || exists $fields{$key})
+ {
+ if (exists $fields{$key}) {
+ $key = $fields{$key};
+ }
+ else {
+ $key = "FreeformContactInfo" if $key eq 'contactinfo';
+ $key = "EmailAddress" if $key eq 'emailaddress';
+ $key = "Name" if $key eq 'name';
+ }
+ $set = "Set$key";
+
+ next if $val eq $user->$key;
+ ($n, $s) = $user->$set($val);
+ }
+ elsif ($key eq 'password') {
+ ($n, $s) = $user->SetPassword($val) unless $val =~ /^\**$/;
+ }
+ elsif ($key ne 'id') {
+ $n = 0;
+ $s = "Unknown field.";
+ }
+
+ SET:
+ if ($n == 0) {
+ $e = 1;
+ push @comments, "# $key: $s";
+ unless (@$o) {
+ my %o = keys %$changes;
+ delete @o{"id", @fields};
+ @$o = ("id", @fields, keys %o);
+ $k = $changes;
+ }
+ }
+ }
+
+ push(@comments, "# User $id updated.") unless $n == 0;
+}
+
+DONE:
+$c ||= join("\n", @comments) if @comments;
+return [ $c, $o, $k, $e ];
+</%perl>
diff --git a/rt/html/REST/1.0/Forms/user/ns b/rt/html/REST/1.0/Forms/user/ns
new file mode 100644
index 0000000..36b3237
--- /dev/null
+++ b/rt/html/REST/1.0/Forms/user/ns
@@ -0,0 +1,41 @@
+%# 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
+%# REST/1.0/Forms/user/ns
+%#
+<%ARGS>
+$id
+</%ARGS>
+<%perl>
+use RT::Users;
+
+my $field = "Name";
+$field = "EmailAddress" if $id =~ /\@/;
+
+my $users = new RT::Users $session{CurrentUser};
+$users->Limit(FIELD => $field, OPERATOR => '=', VALUE => $id);
+if ($users->Count == 0) {
+ return (0, "No user named $id exists.");
+}
+return $users->Next->Id;
+</%perl>
diff --git a/rt/html/REST/1.0/NoAuth/mail-gateway b/rt/html/REST/1.0/NoAuth/mail-gateway
index 8db80d5..359331f 100644
--- a/rt/html/REST/1.0/NoAuth/mail-gateway
+++ b/rt/html/REST/1.0/NoAuth/mail-gateway
@@ -29,12 +29,15 @@ $ticket => undef
</%ARGS>
<%init>
use RT::Interface::Email;
-my ( $status, $error, $Ticket ) = RT::Interface::Email::Gateway( %ARGS);
+my ( $status, $error, $Ticket ) = RT::Interface::Email::Gateway(\%ARGS);
</%init>
<%flags>
inherit => undef # inhibit UTF8 conversion done in /autohandler
</%flags>
-% if ($status) {
+% if ($status == -75 ) {
+temporary failure
+% }
+% elsif ($status == 1) {
ok
% if ( $Ticket->Id ) {
Ticket: <% $Ticket->Id %>
diff --git a/rt/html/REST/1.0/autohandler b/rt/html/REST/1.0/autohandler
new file mode 100644
index 0000000..9084a1b
--- /dev/null
+++ b/rt/html/REST/1.0/autohandler
@@ -0,0 +1,32 @@
+%# 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
+%# REST/1.0/autohandler
+%#
+<%INIT>
+use RT::Interface::REST;
+$r->content_type('text/plain');
+$m->error_format('text');
+$m->call_next();
+$m->abort();
+</%INIT>
diff --git a/rt/html/REST/1.0/dhandler b/rt/html/REST/1.0/dhandler
new file mode 100644
index 0000000..ef5217f
--- /dev/null
+++ b/rt/html/REST/1.0/dhandler
@@ -0,0 +1,287 @@
+%# 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
+%# REST/1.0/dhandler
+%#
+<%ARGS>
+@id => ()
+$fields => undef
+$format => undef
+$content => undef
+</%ARGS>
+<%INIT>
+use RT::Interface::REST;
+
+my $output = "";
+my $status = "200 Ok";
+my $object = $m->dhandler_arg;
+
+my $name = qr{[\w.-]+};
+my $list = '(?:(?:\d+-)?\d+,)*(?:\d+-)?\d+';
+my $label = '[a-zA-Z0-9@_.+-]+';
+my $field = '[a-zA-Z][a-zA-Z0-9_-]*';
+my $labels = "(?:$label,)*$label";
+
+# We must handle requests such as the following:
+#
+# 1. http://.../REST/1.0/show (with a list of object specifications).
+# 2. http://.../REST/1.0/edit (with a self-contained list of forms).
+# 3. http://.../REST/1.0/ticket/show (implicit type specification).
+# http://.../REST/1.0/ticket/edit
+# 4. http://.../REST/1.0/ticket/nn (all possibly with a single form).
+# http://.../REST/1.0/ticket/nn/history
+# http://.../REST/1.0/ticket/nn/attachment/1
+#
+# Objects are specified by their type, and either a unique numeric ID,
+# or a unique name (e.g. ticket/1, queue/foo). Multiple objects of the
+# same type may be specified by a comma-separated list of identifiers
+# (e.g., user/ams,rai or ticket/1-3,5-7).
+#
+# Ultimately, we want a list of object specifications to operate upon.
+# The URLs in (4) provide enough information to identify an object. We
+# will assemble submitted information into that format in other cases.
+#
+my (@objects, $forms);
+my $utype;
+
+if ($object eq 'show' || # $REST/show
+ (($utype) = ($object =~ m{^($name)/show$}))) # $REST/ticket/show
+{
+ # We'll convert type/range specifications ("ticket/1-3,7-9/history")
+ # into a list of singular object specifications ("ticket/1/history").
+ # If the URL specifies a type, we'll accept only that one.
+ foreach my $id (@id) {
+ $id =~ s|^(?:$utype/)?|$utype/| if $utype;
+ if (my ($type, $oids, $extra) =
+ ($id =~ m#^($name)/($list|$labels)(?:(/.*))?$#o))
+ {
+ foreach my $oid (expand_list($oids)) {
+ if ($extra =~ m{^(?:/($name)(?:/(.*))?)?$}o) {
+ my ($attr, $args) = ($1, $2);
+ # expand transaction and attachment range specifications
+ # (if applicable)
+ my $tids;
+ if ($attr eq 'history' && $args =~ m#id/(\d.*)#o) {
+ $tids = $1;
+ }
+ if ($tids) {
+ push(@objects, "$type/$oid/$attr/id/$_") for expand_list($tids);
+ } else {
+ push(@objects, "$type/$oid$extra");
+ }
+ }
+ }
+ }
+ else {
+ $status = "400 Bad Request";
+ $output = "Invalid object ID specified: '$id'";
+ goto OUTPUT;
+ }
+ }
+}
+elsif ($object eq 'edit' || # $REST/edit
+ (($utype) = ($object =~ m{^($name)/edit$}))) # $REST/ticket/edit
+{
+ # We'll make sure each of the submitted forms is syntactically valid
+ # and sufficiently identifies an object to operate upon, then add to
+ # the object list as above.
+ my @output;
+
+ $forms = form_parse($content);
+ foreach my $form (@$forms) {
+ my ($c, $o, $k, $e) = @$form;
+
+ if ($e) {
+ push @output, [ "# Syntax error.", $o, $k, $e ];
+ }
+ else {
+ my ($type, $id);
+
+ # Look for matching types in the ID, form, and URL.
+ $type = exists $k->{type} ? $k->{type} : $utype;
+ $type =~ s|^(?:$utype)?|$utype/| if $utype;
+ $type =~ s|/$||;
+
+ if (exists $k->{id}) {
+ $id = $k->{id};
+ $id =~ s|^(?:$type/)?|$type/| if $type;
+
+ if ($id =~ m#^$name/(?:$label|\d+)(?:/.*)?#o) {
+ push @objects, $id;
+ }
+ else {
+ push @output, [ "# Invalid object ID: '$id'", $o, $k, $e ];
+ }
+ }
+ else {
+ push @output, [ "# No object ID specified.", $o, $k, $e ];
+ }
+ }
+ }
+ # If we saw any errors at this stage, we won't process any part of
+ # the submitted data.
+ if (@output) {
+ unshift @output, [ "# Please resubmit with errors corrected." ];
+ $status = "409 Syntax Error";
+ $output = form_compose(\@output);
+ goto OUTPUT;
+ }
+}
+else {
+ # We'll assume that this is in the correct format already. Otherwise
+ # it will be caught by the loop below.
+ push @objects, $object;
+
+ if ($content) {
+ $forms = form_parse($content);
+
+ if (@$forms > 1) {
+ $status = "400 Bad Request";
+ $output = "You may submit only one form to this object.";
+ goto OUTPUT;
+ }
+
+ my ($c, $o, $k, $e) = @{ $forms->[0] };
+ if ($e) {
+ $status = "409 Syntax Error";
+ $output = form_compose([ ["# Syntax error.", $o, $k, $e] ]);
+ goto OUTPUT;
+ }
+ }
+}
+
+# Make sure we have something to do.
+unless (@objects) {
+ $status = "400 Bad Request";
+ $output = "No objects specified.";
+ goto OUTPUT;
+}
+
+# Parse and validate any field specifications.
+my (%fields, @fields);
+if ($fields) {
+ unless ($fields =~ /^(?:$field,)*$field$/) {
+ $status = "400 Bad Request";
+ $output = "Invalid field specification: $fields";
+ goto OUTPUT;
+ }
+ @fields = map lc, split /,/, $fields;
+ @fields{@fields} = ();
+ unless (exists $fields{id}) {
+ unshift @fields, "id";
+ $fields{id} = ();
+ }
+}
+
+my (@comments, @output);
+
+foreach $object (@objects) {
+ my ($handler, $type, $id, $attr, $args);
+ my ($c, $o, $k, $e) = ("", ["id"], {id => $object}, 0);
+
+ my $i = 0;
+ if ($object =~ m{^($name)/(\d+|$label)(?:/($name)(?:/(.*))?)?$}o ||
+ $object =~ m{^($name)/(new)$}o)
+ {
+ ($type, $id, $attr, $args) = ($1, $2, ($3 || 'default'), $4);
+ $handler = "Forms/$type/$attr";
+
+ unless ($m->comp_exists($handler)) {
+ $args = "$attr/$args";
+ $handler = "Forms/$type/default";
+
+ unless ($m->comp_exists($handler)) {
+ $i = 2;
+ $c = "# Unknown object type: $type";
+ }
+ }
+ elsif ($id ne 'new' && $id !~ /^\d+$/) {
+ my $ns = "Forms/$type/ns";
+
+ # Can we resolve named objects?
+ unless ($m->comp_exists($ns)) {
+ $i = 3;
+ $c = "# Objects of type $type must be specified by numeric id.";
+ }
+ else {
+ my ($n, $s) = $m->comp("Forms/$type/ns", id => $id);
+ if ($n <= 0) { $i = 4; $c = "# $s"; }
+ else { $i = 0; $id = $n; }
+ }
+ }
+ else {
+ $i = 0;
+ }
+ }
+ else {
+ $i = 1;
+ $c = "# Invalid object specification: '$object'";
+ }
+
+ if ($i != 0) {
+ if ($content) {
+ (undef, $o, $k, $e) = @{ shift @$forms };
+ }
+ push @output, [ $c, $o, $k ];
+ next;
+ }
+
+ unless ($content) {
+ my $d = $m->comp($handler, id => $id, args => $args, format => $format, fields => \%fields);
+ my ($c, $o, $k, $e) = @$d;
+
+ if (!$e && @$o && keys %fields) {
+ my %lk = map { lc $_ => $_ } keys %$k;
+ @$o = map { $lk{$_} } @fields;
+ foreach my $key (keys %$k) {
+ delete $k->{$key} unless exists $fields{lc $key};
+ }
+ }
+ push(@output, [ $c, $o, $k ]) if ($c || @$o || keys %$k);
+ }
+ else {
+ my ($c, $o, $k, $e) = @{ shift @$forms };
+ my $d = $m->comp($handler, id => $id, args => $args, format => $format,
+ changes => $k);
+ ($c, $o, $k, $e) = @$d;
+
+ # We won't pass $e through to compose, trusting instead that the
+ # handler added suitable comments for the user.
+ if ($e) {
+ $status = "409 Syntax Error" if @$o;
+ push @output, [ $c, $o, $k ];
+ }
+ else {
+ push @comments, $c;
+ }
+ }
+}
+
+unshift(@output, [ join "\n", @comments ]) if @comments;
+$output = form_compose(\@output);
+
+OUTPUT:
+</%INIT>
+RT/<% $RT::VERSION %> <% $status %>
+
+<% $output |n %>
diff --git a/rt/html/REST/1.0/logout b/rt/html/REST/1.0/logout
new file mode 100644
index 0000000..b64938b
--- /dev/null
+++ b/rt/html/REST/1.0/logout
@@ -0,0 +1,27 @@
+%# 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
+<%PERL>
+tied(%session)->delete if (defined %session);
+</%PERL>
+RT/<% $RT::VERSION %> 200 Ok
diff --git a/rt/html/REST/1.0/search/dhandler b/rt/html/REST/1.0/search/dhandler
new file mode 100644
index 0000000..90b4653
--- /dev/null
+++ b/rt/html/REST/1.0/search/dhandler
@@ -0,0 +1,32 @@
+%# 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
+%# REST/1.0/search/dhandler
+%#
+<%INIT>
+my $status = "500 Server Error";
+my $output = "Unsupported object type.";
+</%INIT>
+RT/<% $RT::VERSION %> <% $status %>
+
+<% $output |n %>
diff --git a/rt/html/REST/1.0/search/ticket b/rt/html/REST/1.0/search/ticket
new file mode 100644
index 0000000..2443529
--- /dev/null
+++ b/rt/html/REST/1.0/search/ticket
@@ -0,0 +1,119 @@
+%# 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
+%# REST/1.0/search/ticket
+%#
+<%ARGS>
+$query
+$format => undef
+$orderby => undef
+$fields => undef
+</%ARGS>
+<%INIT>
+my $output = "";
+my $status = "200 Ok";
+my $tickets = new RT::Tickets $session{CurrentUser};
+
+# Parse and validate any field specifications.
+my $field = '[a-zA-Z][a-zA-Z0-9_-]*';
+my (%fields, @fields);
+if ($fields) {
+ $format = "l";
+ unless ($fields =~ /^(?:$field,)*$field$/) {
+ $status = "400 Bad Request";
+ $output = "Invalid field specification: $fields";
+ goto OUTPUT;
+ }
+ @fields = map lc, split /,/, $fields;
+ @fields{@fields} = ();
+ unless (exists $fields{id}) {
+ unshift @fields, "id";
+ $fields{id} = ();
+ }
+}
+
+$format ||= "s";
+if ($format !~ /^[isl]$/) {
+ $status = "400 Bad request";
+ $output = "Unknown listing format: $format. (Use i, s, or l.)\n";
+ goto OUTPUT;
+}
+
+my ($n, $s);
+eval {
+ ($n, $s) = $tickets->FromSQL($query);
+};
+my $sortstring = "";
+if ($orderby) {
+ $sortstring = 'FIELD => ';
+ my $order = substr($orderby, 0, 1);
+ if ($order eq '+' || $order eq '-') {
+ $sortstring .= 'substr($orderby, 1)';
+ if ($order eq '+') {
+ $sortstring .= ", ORDER => 'ASC'";
+ } elsif ($order eq '-') {
+ $sortstring .= ", ORDER => 'DESC'";
+ }
+ } else {
+ $sortstring .= '$orderby';
+ }
+ my $foo = 'FIELD => ';
+ $foo .= '$orderby';
+ $tickets->OrderBy(eval $sortstring);
+}
+if ($@ || $n == 0) {
+ $s ||= $@;
+ $status = "400 Bad request";
+ $output = "Invalid query: '$s'.\n";
+ goto OUTPUT;
+}
+
+$n = 0;
+my @output;
+while (my $ticket = $tickets->Next) {
+ $n++;
+
+ if ($format eq "i") {
+ $output .= "ticket/" . $ticket->Id . "\n";
+ }
+ elsif ($format eq "s") {
+ $output .= $ticket->Id . ": ". $ticket->Subject . "\n";
+ }
+ else {
+ my $id = $ticket->Id;
+ my $d = $m->comp("$RT::WebPath/REST/1.0/Forms/ticket/default", id => $id, format => $format, fields => \%fields);
+ my ($c, $o, $k, $e) = @$d;
+ push @output, [ $c, $o, $k ];
+ }
+}
+if ($n == 0 && $format ne "i") {
+ $output = "No matching results.\n";
+}
+
+$output = form_compose(\@output) if @output;
+
+OUTPUT:
+</%INIT>
+RT/<% $RT::VERSION %> <% $status %>
+
+<% $output |n %>
diff --git a/rt/html/REST/1.0/ticket/comment b/rt/html/REST/1.0/ticket/comment
new file mode 100644
index 0000000..9d1b062
--- /dev/null
+++ b/rt/html/REST/1.0/ticket/comment
@@ -0,0 +1,149 @@
+%# 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
+%# REST/1.0/ticket/comment
+%#
+<%ARGS>
+$content
+</%ARGS>
+<%INIT>
+use MIME::Entity;
+use LWP::MediaTypes;
+use RT::Interface::REST;
+use File::Temp qw(tempfile);
+
+my $ticket = new RT::Ticket $session{CurrentUser};
+my $object = $r->path_info;
+my $status = "200 Ok";
+my $output;
+my $action;
+
+# http://.../REST/1.0/ticket/comment/1
+my ($c, $o, $k, $e) = @{ form_parse($content)->[0] };
+if ($e || !$o) {
+ if (!$o) {
+ $output = "Empty form submitted.\n";
+ }
+ else {
+ $c = "# Syntax error.";
+ $output = form_compose([[$c, $o, $k, $e]]);
+ }
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+
+$object =~ s#^/##;
+$object ||= $k->{Ticket};
+unless ($object =~ /^\d+/) {
+ $output = "Invalid ticket id: `$object'.\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+if ($k->{Ticket} && $object ne $k->{Ticket}) {
+ $output = "The submitted form and URL specify different tickets.\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+
+($action = $k->{Action}) =~ s/^(.)(.*)$/\U$1\L$2\E/;
+unless ($action =~ /^(?:Comment|Correspond)$/) {
+ $output = "Invalid action: `$action'.\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+
+my $text = $k->{Text};
+my @atts = @{ vsplit($k->{Attachment}) };
+
+if (!$k->{Text} && @atts == 0) {
+ $status = "400 Bad Request";
+ $output = "Empty comment with no attachments submitted.\n";
+ goto OUTPUT;
+}
+
+my $cgi = $m->cgi_object;
+my $ent = MIME::Entity->build(Type => "multipart/mixed");
+$ent->attach(Data => $k->{Text}) if $k->{Text};
+
+my $i = 1;
+foreach my $att (@atts) {
+ local $/=undef;
+ my $file = $att;
+ $file =~ s#^.*[\\/]##;
+
+ my $fh = $cgi->upload("attachment_$i");
+ if ($fh) {
+ my $buf;
+ my ($w, $tmp) = tempfile();
+ my $info = $cgi->uploadInfo();
+
+ while (sysread($fh, $buf, 8192)) {
+ syswrite($w, $buf);
+ }
+
+ $ent->attach(
+ Path => $tmp,
+ Type => $info->{'Content-Type'} || guess_media_type($tmp),
+ Filename => $file,
+ Disposition => "attachment"
+ );
+ }
+ else {
+ $status = "400 Bad Request";
+ $output = "No attachment for $att.\n";
+ goto OUTPUT;
+ }
+
+ $i++;
+}
+
+$ticket->Load($object);
+unless ($ticket->Id) {
+ $output = "Couldn't load ticket id: `$object'.\n";
+ $status = "404 Ticket not found";
+ goto OUTPUT;
+}
+unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
+ ($action eq "Comment" &&
+ $ticket->CurrentUserHasRight("CommentOnTicket")) ||
+ ($action eq "Correspond" &&
+ $ticket->CurrentUserHasRight("ReplyToTicket")))
+{
+ $output = "You are not allowed to $action on ticket $object.\n";
+ $status = "403 Permission denied";
+ goto OUTPUT;
+}
+
+my $cc = join ", ", @{ vsplit($k->{Cc}) };
+my $bcc = join ", ", @{ vsplit($k->{Bcc}) };
+my ($n, $s) = $ticket->$action(MIMEObj => $ent,
+ CcMessageTo => $cc,
+ BccMessageTo => $bcc,
+ TimeTaken => $k->{TimeWorked} || 0);
+$output = $s;
+
+OUTPUT:
+</%INIT>
+RT/<% $RT::VERSION %> <% $status %>
+
+<% $output |n %>
diff --git a/rt/html/REST/1.0/ticket/link b/rt/html/REST/1.0/ticket/link
new file mode 100644
index 0000000..5747625
--- /dev/null
+++ b/rt/html/REST/1.0/ticket/link
@@ -0,0 +1,96 @@
+%# 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
+%# REST/1.0/ticket/link
+%#
+<%ARGS>
+$id => undef
+$del => 0
+$rel
+$to
+</%ARGS>
+<%INIT>
+use RT::Interface::REST;
+
+my $output;
+my $status = "200 Ok";
+my $ticket = new RT::Ticket $session{CurrentUser};
+my $object = $r->path_info;
+
+my @fields = qw(DependsOn DependedOnBy RefersTo ReferredToBy HasMember MemberOf);
+my %fields = map { lc $_ => $_ } @fields;
+my %lfields = (
+ HasMember => { Type => 'MemberOf', Mode => 'Base' },
+ ReferredToBy => { Type => 'RefersTo', Mode => 'Base' },
+ DependedOnBy => { Type => 'DependsOn', Mode => 'Base' },
+ MemberOf => { Type => 'MemberOf', Mode => 'Target' },
+ RefersTo => { Type => 'RefersTo', Mode => 'Target' },
+ DependsOn => { Type => 'DependsOn', Mode => 'Target' },
+);
+
+# http://.../REST/1.0/ticket/link/1
+
+$object =~ s#^/##;
+if ($id && $object && $id != $object) {
+ $output = "Different ids in URL (`$object') and submitted form (`$id').\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+$id ||= $object;
+unless ($id =~ /^\d+$/ && $to =~ /^\d+$/) {
+ my $bad = ($id !~ /^\d+$/) ? $id : $to;
+ $output = $r->path_info. "\n";
+ $output .= "Invalid ticket id: '$bad'.\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+unless (exists $fields{lc $rel}) {
+ $output = "Invalid relationship: '$rel'.\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+$rel = $fields{lc $rel};
+
+$ticket->Load($id);
+unless ($ticket->Id) {
+ $output = "Couldn't load ticket id: '$id'.\n";
+ $status = "404 Ticket not found";
+ goto OUTPUT;
+}
+
+my $type = $lfields{$rel}->{Type};
+my $mode = $lfields{$rel}->{Mode};
+
+my $n = 1;
+my $op = $del ? "DeleteLink" : "AddLink";
+
+($n, $output) = $ticket->$op(Type => $type, $mode => $to);
+if ($n == 0) {
+ $status = "500 Error";
+}
+
+OUTPUT:
+</%INIT>
+RT/<% $RT::VERSION %> <% $status %>
+
+<% $output |n %>
diff --git a/rt/html/REST/1.0/ticket/merge b/rt/html/REST/1.0/ticket/merge
new file mode 100644
index 0000000..9cd2a7c
--- /dev/null
+++ b/rt/html/REST/1.0/ticket/merge
@@ -0,0 +1,78 @@
+%# 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
+%# REST/1.0/ticket/merge
+%#
+<%ARGS>
+$id => undef
+$into
+</%ARGS>
+<%INIT>
+use RT::Interface::REST;
+
+my $output;
+my $status = "200 Ok";
+my $ticket = new RT::Ticket $session{CurrentUser};
+my $object = $r->path_info;
+
+# http://.../REST/1.0/ticket/merge/1
+
+$object =~ s#^/##;
+if ($id && $object && $id != $object) {
+ $output = "Different ids in URL (`$object') and submitted form (`$id').\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+$id ||= $object;
+unless ($id =~ /^\d+$/ && $into =~ /^\d+$/) {
+ my $bad = ($id !~ /^\d+$/) ? $id : $into;
+ $output = $r->path_info. "\n";
+ $output .= "Invalid ticket id: `$bad'.\n";
+ $status = "400 Bad Request";
+ goto OUTPUT;
+}
+
+$ticket->Load($id);
+unless ($ticket->Id) {
+ $output = "Couldn't load ticket id: `$id'.\n";
+ $status = "404 Ticket not found";
+ goto OUTPUT;
+}
+unless ($ticket->CurrentUserHasRight('ModifyTicket')) {
+ $output = "You are not allowed to modify ticket $id.\n";
+ $status = "403 Permission denied";
+ goto OUTPUT;
+}
+
+my ($n, $s) = $ticket->MergeInto($into);
+
+if ($n == 0) {
+ $status = "500 Error";
+}
+$output = $s;
+
+OUTPUT:
+</%INIT>
+RT/<% $RT::VERSION %> <% $status %>
+
+<% $output |n %>
diff --git a/rt/html/Search/Bulk.html b/rt/html/Search/Bulk.html
index df43cfa..de9143c 100644
--- a/rt/html/Search/Bulk.html
+++ b/rt/html/Search/Bulk.html
@@ -175,6 +175,7 @@ if ($ARGS{'UpdateContent'} &&
#Iterate through each ticket we've been handed
my @linkresults;
+$session{'tickets'}->RedoSearch();
while (my $Ticket = $session{'tickets'}->Next) {
$RT::Logger->debug( "Checking Ticket ".$Ticket->Id ."\n");
next unless ($ARGS{"UpdateTicket".$Ticket->Id});
diff --git a/rt/html/Search/Elements/PickRestriction b/rt/html/Search/Elements/PickRestriction
index a6911df..0021ab2 100644
--- a/rt/html/Search/Elements/PickRestriction
+++ b/rt/html/Search/Elements/PickRestriction
@@ -34,9 +34,10 @@
<& /Elements/SelectOwner, Name => "ValueOfOwner" &>
<li>
-<&|/l&>Requestor email address</&>
-<& /Elements/SelectMatch, Name => "RequestorOp" &>
-<INPUT Name="ValueOfRequestor" SIZE=20>
+<& /Elements/SelectWatcherType, Name => "WatcherRole", AllowNull => 0 &>
+<&|/l&>email address</&>
+<& /Elements/SelectMatch, Name => "WatcherRoleOp" &>
+<INPUT Name="ValueOfWatcherRole" SIZE=20>
<li>
<&|/l&>Subject</&> <& /Elements/SelectMatch, Name => "SubjectOp" &>
@@ -47,7 +48,7 @@
False => loc("isn't"),
TrueVal=> '=',
FalseVal => '!=' &>
-<& /Elements/SelectQueue, Name => loc("ValueOfQueue") &>
+<& /Elements/SelectQueue, Name => "ValueOfQueue" &>
<li><&|/l&>Priority</&> <& /Elements/SelectEqualityOperator, Name => "PriorityOp" &>
@@ -77,7 +78,7 @@
TrueVal=> '=',
FalseVal => '!='
&>
-<& /Elements/SelectStatus, Name => "ValueOfStatus" &>
+<& /Elements/SelectStatus, Name => "ValueOfStatus", SkipDeleted => 1 &>
% while ( my $CustomField = $CustomFields->Next ) {
diff --git a/rt/html/SelfService/Display.html b/rt/html/SelfService/Display.html
index fc3fcb2..124ecf4 100644
--- a/rt/html/SelfService/Display.html
+++ b/rt/html/SelfService/Display.html
@@ -38,7 +38,7 @@
<& /Elements/TitleBoxStart, title => loc("Dates"),
title_class=> 'inverse',
color => "#663366" &>
- <& /Ticket/Elements/ShowDates, Ticket => $Ticket &>
+ <& /Ticket/Elements/ShowDates, Ticket => $Ticket, UpdatedLink => 0 &>
<& /Elements/TitleBoxEnd &>
</TD>
</TR>
@@ -46,7 +46,7 @@
-<& /Ticket/Elements/ShowHistory, Ticket => $Ticket&>
+<& /Ticket/Elements/ShowHistory, Ticket => $Ticket, AttachPath => "Attachment" &>
@@ -101,6 +101,12 @@ if ( $id[0] eq 'new' ) {
push ( @results, $ErrMsg );
# }}}
+
+# delete temporary storage entry to make WebUI clean
+unless (keys %{$session{'Attachments'}} and $ARGS{'UpdateAttach'}) {
+ delete $session{'Attachments'};
+}
+# }}}
}
else {
unless ( $Ticket->Load( $id[0] ) ) {
@@ -127,10 +133,43 @@ if ( ( defined $ARGS{'Status'} )
push @results, "$msg";
}
+# {{{ store the uploaded attachment in session
+if ($ARGS{'Attach'}) { # attachment?
+ $session{'Attachments'} = {} unless defined $session{'Attachments'};
+
+ my $subject = "$ARGS{'Attach'}";
+ # since CGI.pm deutf8izes the magic field, we need to add it back.
+ Encode::_utf8_on($subject);
+ # strip leading directories
+ $subject =~ s#^.*[\\/]##;
+
+ my $attachment = MakeMIMEEntity(
+ Subject => $subject,
+ Body => "",
+ AttachmentFieldName => 'Attach'
+ );
+
+ $session{'Attachments'} = { %{$session{'Attachments'} || {}},
+ $ARGS{'Attach'} => $attachment };
+}
+# }}}
+
+if ( $session{'Attachments'} ||
+ ( $ARGS{'UpdateContent'} ne ''
+ && $ARGS{'UpdateContent'} ne "-- \n"
+ . $session{'CurrentUser'}->UserObj->Signature )) {
+ $ARGS{UpdateAttachments} = $session{'Attachments'};
+}
ProcessUpdateMessage( ARGSRef => \%ARGS,
Actions => \@results,
TicketObj => $Ticket );
+# delete temporary storage entry to make WebUI clean
+unless (keys %{$session{'Attachments'}} and $ARGS{'UpdateAttach'}) {
+ delete $session{'Attachments'};
+}
+# }}}
+
my $Transactions = $Ticket->Transactions;
</%INIT>
diff --git a/rt/html/SelfService/Elements/MyRequests b/rt/html/SelfService/Elements/MyRequests
index 95ede08..839359a 100644
--- a/rt/html/SelfService/Elements/MyRequests
+++ b/rt/html/SelfService/Elements/MyRequests
@@ -49,6 +49,7 @@ $title ||= loc("My [_1] tickets", $friendly_status);
my $MyTickets;
$MyTickets = new RT::Tickets ($session{'CurrentUser'});
$MyTickets->LimitWatcher(TYPE => 'Requestor', VALUE => $session{'CurrentUser'}->EmailAddress);
+$MyTickets->OrderBy(FIELD => 'id', ORDER => 'ASC');
foreach my $status (@status) {
diff --git a/rt/html/SelfService/Update.html b/rt/html/SelfService/Update.html
index 9ff3177..9444aa7 100644
--- a/rt/html/SelfService/Update.html
+++ b/rt/html/SelfService/Update.html
@@ -29,7 +29,24 @@
<&|/l&>Status</&>: <& /Elements/SelectStatus, Name=>"Status", Default => $DefaultStatus &><br>
<&|/l&>Subject</&>: <input name="UpdateSubject" size=60 value="Re: <% $Ticket->Subject %>"> <br>
-<&|/l&>Attach</&>: <input name="UpdateAttachment" type=file><br>
+<table>
+<tr>
+% if (exists $session{'Attachments'}) {
+<TD>
+<&|/l&>Attached file</&>:
+</TD>
+<TD COLSPAN=5>
+<&|/l&>Check box to delete</&><BR>
+% foreach my $attach_name (keys %{$session{'Attachments'}}) {
+<input type="checkbox" name="DeleteAttach-<%$attach_name%>"><%$attach_name%><BR>
+% } # end of foreach
+</TD>
+</TR>
+<TR>
+% } # end of if
+<tr><td align=right><&|/l&>Attach</&>:</td><td><input name="Attach" type="file"><input type="hidden" name="UpdateAttach" value="1">
+</td></tr>
+</table>
<& /Elements/MessageBox, Name=>"UpdateContent", QuoteTransaction=>$ARGS{QuoteTransaction} &>
<INPUT TYPE=HIDDEN NAME=id VALUE="<%$Ticket->Id%>"><br>
diff --git a/rt/html/Ticket/Attachment/dhandler b/rt/html/Ticket/Attachment/dhandler
index e0f00f5..ba82b5f 100644
--- a/rt/html/Ticket/Attachment/dhandler
+++ b/rt/html/Ticket/Attachment/dhandler
@@ -65,4 +65,6 @@
$m->out($AttachmentObj->OriginalContent);
$m->abort;
</%perl>
-
+<%attr>
+AutoFlush => 0
+</%attr>
diff --git a/rt/html/Ticket/Create.html b/rt/html/Ticket/Create.html
index 5b8c908..435447a 100644
--- a/rt/html/Ticket/Create.html
+++ b/rt/html/Ticket/Create.html
@@ -34,55 +34,55 @@
<BR>
<& /Elements/TitleBoxStart, contentbg => "#cccccc", title => loc("Create a new ticket") &>
<TABLE border=0 cellpadding=0 cellspacing=0>
-<TR><TD><&|/l&>Queue</&></TD>
-<TD><% $QueueObj->Name %>
+<TR><TD class=label><&|/l&>Queue</&>:</TD>
+<TD class=value><% $QueueObj->Name %>
<INPUT TYPE=HIDDEN NAME=Queue Value="<%$QueueObj->Name%>">
</TD>
-<TD><&|/l&>Status</&>:
+<TD class=label><&|/l&>Status</&>:
</TD>
-<TD>
+<TD class=value>
<& /Elements/SelectStatus, Name => "Status", Default => $ARGS{Status}||'new' &>
</TD>
-<TD>
+<TD class=label>
<&|/l&>Owner</&>:
</TD>
-<TD>
+<TD class=value>
<& /Elements/SelectOwner, Name => "Owner", QueueObj => $QueueObj, Default => $ARGS{Owner}||undef &>
</TD>
</TR>
<TR>
-<TD>
+<TD class=label>
<&|/l&>Requestors</&>:
</TD>
-<TD COLSPAN=5>
+<TD class=value COLSPAN=5>
<INPUT Name="Requestors" Value="<% ($ARGS{Requestors}) || $session{CurrentUser}->EmailAddress %>" SIZE=40>
</TD>
</TR>
<TR>
-<TD>
+<TD class=labeltop>
<&|/l&>Cc</&>:
</TD>
-<TD COLSPAN=5>
-<INPUT NAME="Cc" SIZE=40<% $ARGS{Cc} && " VALUE=\"$ARGS{Cc}\""%>><BR>
+<TD class=value COLSPAN=5>
+<INPUT NAME="Cc" SIZE=40 VALUE="<% $ARGS{Cc} %>"><BR>
<i><font size=-2>
<&|/l&>(Sends a carbon-copy of this update to a comma-delimited list of email addresses. These people <b>will</b> receive future updates.)</&></font></i>
</TD>
</TR>
<TR>
-<TD>
+<TD class=labeltop>
<&|/l&>Admin Cc</&>:
</TD>
-<TD COLSPAN=5>
-<INPUT NAME="AdminCc" SIZE=40<% $ARGS{AdminCc} && " VALUE=\"$ARGS{AdminCc}\""%>><BR>
+<TD class=value COLSPAN=5>
+<INPUT NAME="AdminCc" SIZE=40 VALUE="<% $ARGS{AdminCc} %>"><BR>
<i><font size=-2>
<&|/l&>(Sends a carbon-copy of this update to a comma-delimited list of administrative email addresses. These people <b>will</b> receive future updates.)</&></font></i>
</TD>
</TR>
<TR>
-<TD>
+<TD class=label>
<&|/l&>Subject</&>:
</TD>
-<TD COLSPAN=5>
+<TD class=value COLSPAN=5>
<INPUT Name="Subject" SIZE=60 MAXSIZE=100 value="<%$ARGS{Subject} || ''%>">
</TD>
</TR>
@@ -93,7 +93,7 @@
</TR>
<TR>
% if (exists $session{'Attachments'}) {
-<TD>
+<TD class=label>
<&|/l&>Attached file</&>:
</TD>
<TD COLSPAN=5>
@@ -108,7 +108,7 @@
<TD>
<&|/l&>Attach file</&>:
</TD>
-<TD COLSPAN=5>
+<TD class=value COLSPAN=5>
<INPUT TYPE=FILE NAME="Attach">
<INPUT TYPE=SUBMIT NAME="AddMoreAttach" VALUE="<&|/l&>Add More Files</&>">
</TD>
@@ -152,8 +152,8 @@
<TABLE BORDER=0>
<TR><TD ALIGN=RIGHT><&|/l&>Priority</&>:</TD><TD><input size=3 name="InitialPriority" value="<% $ARGS{InitialPriority} ? $ARGS{InitialPriority} : $QueueObj->InitialPriority %>"></TD></TR>
<TR><TD ALIGN=RIGHT><&|/l&>Final Priority</&>:</TD><TD><input size=3 name="FinalPriority" value="<% $ARGS{FinalPriority} ? $ARGS{FinalPriority} : $QueueObj->FinalPriority %>"></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Time Worked</&>:</TD><TD><input size=3 name="TimeWorked"<% $ARGS{TimeWorked} && " VALUE=\"$ARGS{TimeWorked}\"" %>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Time Left</&>:</TD><TD><input size=3 name="TimeLeft"<% $ARGS{TimeLeft} && " VALUE=\"$ARGS{TimeLeft}\"" %>></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Time Worked</&>:</TD><TD><input size=3 name="TimeWorked" value="<% $ARGS{TimeWorked} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Time Left</&>:</TD><TD><input size=3 name="TimeLeft" value="<% $ARGS{TimeLeft} %>"></TD></TR>
</TABLE>
<& /Elements/TitleBoxEnd &>
<br>
@@ -162,8 +162,9 @@
color => "#663366" &>
<TABLE BORDER=0>
-<TR><TD ALIGN=RIGHT><&|/l&>Starts</&>:</TD><TD><input size=10 name="Starts"<% $ARGS{Starts} && " VALUE=\"$ARGS{Starts}\"" %>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Due</&>:</TD><TD><input size=10 name="Due"<% $ARGS{Due} && " VALUE=\"$ARGS{Due}\"" %>></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Starts</&>:</TD><TD><input size=10 name="Starts" value="<% $ARGS{Starts} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Due</&>:</TD><TD><input size=10 name="Due" value="<%
+$ARGS{Due}%>"></TD></TR>
</TABLE>
<& /Elements/TitleBoxEnd &>
<BR>
@@ -176,12 +177,12 @@
<i><&|/l&>(Enter ticket ids or URLs, seperated with spaces)</&></i>
<TABLE BORDER=0>
-<TR><TD ALIGN=RIGHT><&|/l&>Depends on</&></TD><TD><input size=10 name="new-DependsOn"<% $ARGS{'new-DependsOn'} && " VALUE=\"$ARGS{'new-DependsOn'}\""%>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Depended on by</&></TD><TD><input size=10 name="DependsOn-new"<% $ARGS{'DependsOn-new'} && " VALUE=\"$ARGS{'DependsOn-new'}\"" %>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Parents</&></TD><TD><input size=10 name="new-MemberOf"<% $ARGS{'new-MemberOf'} && " VALUE=\"$ARGS{'new-MemberOf'}\"" %>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Children</&></TD><TD><input size=10 name="MemberOf-new" <% $ARGS{'MemberOf-new'} && " VALUE=\"$ARGS{'MemberOf-new'}\"" %>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Refers to</&></TD><TD><input size=10 name="new-RefersTo"<% $ARGS{'new-RefersTo'} && " VALUE=\"$ARGS{'new-MemberOf'}\"" %>></TD></TR>
-<TR><TD ALIGN=RIGHT><&|/l&>Referred to by</&></TD><TD><input size=10 name="RefersTo-new"<% $ARGS{'RefersTo-new'} && " VALUE=\"$ARGS{'RefersTo-new'}\"" %>></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Depends on</&></TD><TD><input size=10 name="new-DependsOn" value="<% $ARGS{'new-DependsOn'} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Depended on by</&></TD><TD><input size=10 name="DependsOn-new" value="<% $ARGS{'DependsOn-new'} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Parents</&></TD><TD><input size=10 name="new-MemberOf" value="<% $ARGS{'new-MemberOf'} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Children</&></TD><TD><input size=10 name="MemberOf-new" value="<% $ARGS{'MemberOf-new'} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Refers to</&></TD><TD><input size=10 name="new-RefersTo" value="<% $ARGS{'new-RefersTo'} %>"></TD></TR>
+<TR><TD ALIGN=RIGHT><&|/l&>Referred to by</&></TD><TD><input size=10 name="RefersTo-new" value="<% $ARGS{'RefersTo-new'} %>"></TD></TR>
</TABLE>
@@ -200,10 +201,20 @@
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<%INIT>
+
+
+
my $QueueObj = new RT::Queue($session{'CurrentUser'});
$QueueObj->Load($Queue) || Abort(loc("Queue could not be loaded."));
my $CFs = $QueueObj->CustomFields();
+if ($QueueObj->DefaultDueIn) {
+ my $default_due = RT::Date->new($session{'CurrentUser'});
+ $default_due->SetToNow();
+ $default_due->AddDays($QueueObj->DefaultDueIn);
+ $ARGS{'Due'} = $default_due->ISO();
+}
+
# {{{ deal with deleting uploaded attachments
foreach my $key (keys %ARGS) {
if ($key =~ m/^DeleteAttach-(.+)$/) {
@@ -218,8 +229,6 @@ if ($ARGS{'Attach'}) { # attachment?
my $subject = "$ARGS{'Attach'}";
- # since CGI.pm deutf8izes the magic field, we need to add it back.
- Encode::_utf8_on($subject);
# strip leading directories
$subject =~ s#^.*[\\/]##;
diff --git a/rt/html/Ticket/Display.html b/rt/html/Ticket/Display.html
index cf32dce..276cee6 100644
--- a/rt/html/Ticket/Display.html
+++ b/rt/html/Ticket/Display.html
@@ -22,20 +22,20 @@
%#
%# END LICENSE BLOCK
<& /Elements/Header,
- Title => loc("#[_1]: [_2]", $Ticket->Id, $Ticket->Subject) &>
+ Title => loc("#[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
<& /Ticket/Elements/Tabs,
- Ticket => $Ticket,
- current_tab => 'Ticket/Display.html?id='.$Ticket->id,
- Title => loc("#[_1]: [_2]", $Ticket->Id, $Ticket->Subject) &>
+ Ticket => $TicketObj,
+ current_tab => 'Ticket/Display.html?id='.$TicketObj->id,
+ Title => loc("#[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
<& /Elements/ListActions, actions => \@Actions &>
-<& /Ticket/Elements/ShowSummary, Ticket => $Ticket &>
+<& /Ticket/Elements/ShowSummary, Ticket => $TicketObj &>
<BR>
<& /Ticket/Elements/ShowHistory ,
- Ticket => $Ticket,
+ Ticket => $TicketObj,
Collapsed => $ARGS{'Collapsed'},
ShowHeaders => $ARGS{'ShowHeaders'} &>
@@ -45,14 +45,13 @@ $id => undef
$Create => undef
$ShowHeaders => undef
$Collapsed => undef
+$TicketObj => undef
</%ARGS>
<%INIT>
- my ($linkid, $message, $tid, $Ticket, @Actions);
+ my ($linkid, $message, $tid, @Actions);
-$Ticket = new RT::Ticket($session{'CurrentUser'});
-
-unless ($id) {
+unless ($id || $TicketObj) {
Abort('No ticket specified');
}
@@ -67,47 +66,50 @@ if ($ARGS{'id'} eq 'new') {
unless ($Queue->CurrentUserHasRight('CreateTicket')) {
Abort('You have no permission to create tickets in that queue.');
}
- ($Ticket, @Actions) =
- CreateTicket(Attachments => $session{'Attachments'}, %ARGS);
+ ($TicketObj, @Actions) =
+ CreateTicket(Attachments => $session{'Attachments'}, %ARGS);
delete $session{'Attachments'};
- unless ($Ticket->CurrentUserHasRight('ShowTicket')) {
- Abort("No permission to view newly created ticket #".$Ticket->id.".");
- }
+ unless ($TicketObj->CurrentUserHasRight('ShowTicket')) {
+ Abort("No permission to view newly created ticket #".$TicketObj->id.".");
+ }
# }}}
-}
+} else {
+ if (!$TicketObj) {
-else {
- $Ticket = LoadTicket($ARGS{'id'});
- unless ($Ticket->CurrentUserHasRight('ShowTicket')) {
- Abort("No permission to view ticket");
- }
+ $TicketObj = RT::Ticket->new($session{'CurrentUser'});
+ $TicketObj = LoadTicket($ARGS{'id'});
+ unless ($TicketObj->CurrentUserHasRight('ShowTicket')) {
+ Abort("No permission to view ticket");
+ }
+ }
-if (defined $ARGS{'Action'}) {
- if ($ARGS{'Action'} =~ /^(Steal|Kill|Take|SetTold)$/) {
- my $action = $1;
- my ($res, $msg)=$Ticket->$action();
- push(@Actions, $msg);
- }
-}
+ if (defined $ARGS{'Action'}) {
+ if ($ARGS{'Action'} =~ /^(Steal|Kill|Take|SetTold)$/) {
+ my $action = $1;
+ my ($res, $msg)=$TicketObj->$action();
+ push(@Actions, $msg);
+ }
+ }
- if ( $ARGS{'UpdateContent'} ) {
+ if ( $ARGS{'UpdateContent'} || $session{'Attachments'}) {
$ARGS{'UpdateContent'} =~ s/\r\n/\n/g;
- if ( $ARGS{'UpdateContent'} ne ''
- && $ARGS{'UpdateContent'} ne "-- \n"
- . $session{'CurrentUser'}->UserObj->Signature ) {
+ if ( $session{'Attachments'} ||
+ ( $ARGS{'UpdateContent'} ne ''
+ && $ARGS{'UpdateContent'} ne "-- \n"
+ . $session{'CurrentUser'}->UserObj->Signature )) {
$ARGS{UpdateAttachments} = $session{'Attachments'};
ProcessUpdateMessage( ARGSRef => \%ARGS,
Actions => \@Actions,
- TicketObj => $Ticket );
+ TicketObj => $TicketObj );
delete $session{'Attachments'};
}
}
-#Process status updates
-my @BasicActions = ProcessTicketBasics(ARGSRef => \%ARGS, TicketObj=>$Ticket);
-my @results = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
+ #Process status updates
+ my @BasicActions = ProcessTicketBasics(ARGSRef => \%ARGS, TicketObj=>$TicketObj);
+ my @results = ProcessTicketLinks( TicketObj => $TicketObj, ARGSRef => \%ARGS);
-push (@Actions, @BasicActions, @results);
+ push (@Actions, @BasicActions, @results);
}
</%INIT>
diff --git a/rt/html/Ticket/Elements/AddWatchers b/rt/html/Ticket/Elements/AddWatchers
index e9f6515..96dd38f 100644
--- a/rt/html/Ticket/Elements/AddWatchers
+++ b/rt/html/Ticket/Elements/AddWatchers
@@ -77,6 +77,7 @@ my ($msg, $Users, $Groups);
if ($UserString) {
$Users = RT::Users->new($session{'CurrentUser'});
$Users->Limit(FIELD => $UserField, VALUE => $UserString, OPERATOR => $UserOp);
+ $Users->LimitToPrivileged if $PrivilegedOnly;
}
if ($GroupString) {
@@ -94,4 +95,5 @@ $UserString => undef
$GroupField => 'Name'
$GroupOp => '='
$GroupString => undef
+$PrivilegedOnly => undef
</%ARGS>
diff --git a/rt/html/Ticket/Elements/EditCustomField b/rt/html/Ticket/Elements/EditCustomField
index 1fc7d43..1634806 100644
--- a/rt/html/Ticket/Elements/EditCustomField
+++ b/rt/html/Ticket/Elements/EditCustomField
@@ -30,6 +30,8 @@
size="<%$Cols%>"
% if ($TicketObj) {
value="<%$Values->Count ? $Values->First->Content : ''%>"
+% } elsif ($Default) {
+ value="<%$Default ? $Default : ''%>"
% }
>
% } elsif ($CustomField->Type eq 'FreeformMultiple') {
@@ -38,6 +40,8 @@
% while (my $value = $Values->Next ) {
% $content .= $value->Content;
% }
+% } elsif ($Default) {
+ value="<%$Default ? $Default : ''%>"
% }
<input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
<textarea cols=<%$Cols%> rows=<%$Rows%> name="<%$NamePrefix%><%$CustomField->Id%>-Values"><%$content%></textarea>
diff --git a/rt/html/Ticket/Elements/EditLinks b/rt/html/Ticket/Elements/EditLinks
index 7a522dd..bdb8a6b 100644
--- a/rt/html/Ticket/Elements/EditLinks
+++ b/rt/html/Ticket/Elements/EditLinks
@@ -35,10 +35,8 @@
<td class="labeltop"><&|/l&>Depends on</&>:</td>
<td class="value">
% while (my $link = $Ticket->DependsOn->Next) {
-% my $member = $link->TargetObj;
<INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: (<%$member->OwnerObj->Name%>) <%$member->Subject%>
- [<%$member->Status%>]<br>
+ <& ShowLink, URI => $link->TargetURI &><br>
% }
</td>
</tr>
@@ -48,8 +46,7 @@
% while (my $link = $Ticket->DependedOnBy->Next) {
% my $member = $link->BaseObj;
<INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-">
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: (<%$member->OwnerObj->Name%>) <%$member->Subject%>
- [<%$member->Status%>]<br>
+ <& ShowLink, URI => $link->BaseURI &><br>
% }
</td>
</tr>
@@ -57,10 +54,8 @@
<td class="labeltop"><&|/l&>Parents</&>:</td>
<td class="value">
% while (my $link = $Ticket->MemberOf->Next) {
-% my $member = $link->TargetObj;
<INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: (<%$member->OwnerObj->Name%>) <%$member->Subject%>
- [<%$member->Status%>]<br>
+ <& ShowLink, URI => $link->TargetURI &><br>
% }
</td>
</tr>
@@ -69,9 +64,7 @@
<td class="value">
% while (my $link = $Ticket->Members->Next) {
<INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-">
-% my $member = $link->BaseObj;
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: (<%$member->OwnerObj->Name%>) <%$member->Subject%>
- [<%$member->Status%>]<br>
+ <& ShowLink, URI => $link->BaseURI &><br>
% }
</td>
</tr>
@@ -80,12 +73,7 @@
<td class="value">
% while (my $link = $Ticket->RefersTo->Next) {
<INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
-% if ($link->TargetURI->IsLocal) {
-% my $member = $link->TargetObj;
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: (<%$member->OwnerObj->Name%>) <%$member->Subject%> [<%$member->Status%>]<br>
-% } else {
- <A HREF="<%$link->TargetURI->Resolver->HREF%>"><%$link->TargetURI->Resolver->AsString%></A><br>
-% }
+ <& ShowLink, URI => $link->TargetURI &><br>
%}
</td>
</tr>
@@ -94,12 +82,7 @@
<td class="value">
% while (my $link = $Ticket->ReferredToBy->Next) {
<INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-">
-% if ($link->BaseURI->IsLocal) {
-% my $member = $link->BaseObj;
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: (<%$member->OwnerObj->Name%>) <%$member->Subject%> [<%$member->Status%>]<br>
-% } else {
- <A HREF="<%$link->BaseURI->Resolver->HREF%>"><%$link->BaseURI->Resolver->AsString%></A><br>
-%}
+ <& ShowLink, URI => $link->BaseURI &><br>
% }
</td>
</tr>
diff --git a/rt/html/Ticket/Elements/EditPeople b/rt/html/Ticket/Elements/EditPeople
index 1ab8f4a..a1fc011 100644
--- a/rt/html/Ticket/Elements/EditPeople
+++ b/rt/html/Ticket/Elements/EditPeople
@@ -37,7 +37,7 @@
<& AddWatchers, Ticket => $Ticket, UserString => $UserString,
UserOp => $UserOp, UserField => $UserField,
GroupString => $GroupString, GroupOp => $GroupOp,
- GroupField => $GroupField &>
+ GroupField => $GroupField, PrivilegedOnly => $PrivilegedOnly &>
</TD><TD VALIGN=TOP>
<h3><&|/l&>Owner</&></h3>
<&|/l&>Owner</&>: <& /Elements/SelectOwner, Name => 'Owner', QueueObj => $Ticket->QueueObj, TicketObj => $Ticket, Default => $Ticket->OwnerObj->Id &>
@@ -64,5 +64,6 @@ $UserString => undef
$GroupField => undef
$GroupOp => undef
$GroupString => undef
+$PrivilegedOnly => undef
$Ticket => undef
</%ARGS>
diff --git a/rt/html/Ticket/Elements/ShowAttachments b/rt/html/Ticket/Elements/ShowAttachments
index 22b60d1..590a011 100644
--- a/rt/html/Ticket/Elements/ShowAttachments
+++ b/rt/html/Ticket/Elements/ShowAttachments
@@ -47,7 +47,7 @@ if ($size) {
</%PERL>
<li><font <%$fontsize%>>
- <A HREF="<%$RT::WebPath%>/Ticket/Attachment/<%$rev->TransactionObj->Id%>/<%$rev->Id%>/<%$rev->Filename%>"><%$rev->CreatedAsString%> (<% $size %>)</a></font></li>
+ <A HREF="<%$RT::WebPath%>/Ticket/Attachment/<%$rev->TransactionObj->Id%>/<%$rev->Id%>/<%$rev->Filename | u%>"><%$rev->CreatedAsString%> (<% $size %>)</a></font></li>
% }
% $fontsize='size="-2"';
% }
@@ -63,6 +63,9 @@ my %documents;
my $transactions = $Ticket->Transactions();
while (my $trans = $transactions->Next()) {
my $attachments = $trans->Attachments();
+ $attachments->Columns( qw( Id Filename ContentType Headers Subject Parent ContentEncoding ContentType TransactionId) );
+ $attachments->Limit(FIELD => 'Filename', OPERATOR => 'IS NOT', VALUE => 'NULL', QUOTEVALUE => 0, ENTRYAGGREGATOR => 'AND');
+ $attachments->Limit(FIELD => 'Filename', OPERATOR => '!=', VALUE => '', ENTRYAGGREGATOR => 'AND');
while (my $attach = $attachments->Next()) {
next unless ($attach->Filename());
# most recent at the top
diff --git a/rt/html/Ticket/Elements/ShowDates b/rt/html/Ticket/Elements/ShowDates
index da7f75b..b09b4bf 100644
--- a/rt/html/Ticket/Elements/ShowDates
+++ b/rt/html/Ticket/Elements/ShowDates
@@ -21,6 +21,7 @@
%#
%#
%# END LICENSE BLOCK
+
<TABLE>
<TR>
<TD class="label"><&|/l&>Created</&>:</TD>
@@ -35,7 +36,7 @@
<TD class="value"><% $Ticket->StartedObj->AsString %></TD>
</TR>
<TR>
- <TD class="label"><&|/l&>Last Contact</&>:</TD>
+ <TD class="label"><a href="Display.html?id=<%$Ticket->id%>&Action=SetTold"><&|/l&>Last Contact</&></a>:</TD>
<TD class="value"><% $Ticket->ToldObj->AsString %></TD>
</TR>
<TR>
@@ -48,9 +49,15 @@
</TR>
<TR>
<TD class="label"><&|/l&>Updated</&>:</TD>
- <TD class="value"><A HREF="#lasttrans"><% $Ticket->LastUpdated ? (loc("[_1] by [_2]", $Ticket->LastUpdatedAsString, $Ticket->LastUpdatedByObj->Name)) : loc("Never") | h %></a></TD>
+% my $UpdatedString = $Ticket->LastUpdated ? (loc("[_1] by [_2]", $Ticket->LastUpdatedAsString, $Ticket->LastUpdatedByObj->Name)) : loc("Never");
+% if ($UpdatedLink) {
+ <TD class="value"><A HREF="#lasttrans"><% $UpdatedString | h %></a></TD>
+% } else {
+ <TD class="value"><% $UpdatedString | h %></TD>
+% }
</TR>
</TABLE>
<%ARGS>
$Ticket => undef
+$UpdatedLink => 1
</%ARGS>
diff --git a/rt/html/Ticket/Elements/ShowHistory b/rt/html/Ticket/Elements/ShowHistory
index 2958f87..194be9b 100644
--- a/rt/html/Ticket/Elements/ShowHistory
+++ b/rt/html/Ticket/Elements/ShowHistory
@@ -62,7 +62,7 @@ else {
% if ($Transactions->IsLast) {
<a name="lasttrans"></a>
% }
- <& ShowTransaction, Ticket => $Ticket, Transaction => $Transaction, ShowHeaders => $ShowHeaders, Collapsed => $Collapsed, RowNum => $i, ShowTitleBarCommands => $ShowTitleBarCommands &>
+ <& ShowTransaction, Ticket => $Ticket, Transaction => $Transaction, ShowHeaders => $ShowHeaders, Collapsed => $Collapsed, RowNum => $i, ShowTitleBarCommands => $ShowTitleBarCommands, %ARGS &>
% }
</TABLE>
% if ($ShowDisplayModes or $ShowTitle) {
diff --git a/rt/html/Ticket/Elements/ShowMessageStanza b/rt/html/Ticket/Elements/ShowMessageStanza
index b099806..8e3045a 100644
--- a/rt/html/Ticket/Elements/ShowMessageStanza
+++ b/rt/html/Ticket/Elements/ShowMessageStanza
@@ -21,6 +21,8 @@
%#
%#
%# END LICENSE BLOCK
+% if (ref($Message)) {
+<font color="<%$colors[$Depth]%>">
<%perl>
foreach my $stanza (@$Message) {
if ( ref $stanza eq "ARRAY" ) {
@@ -36,8 +38,16 @@ foreach my $stanza (@$Message) {
$content =~ s/\n/<br>/gi;
</%perl>
-<font color="<%$colors[$Depth]%>"><%$content |n%><br></font>
+<%$content |n%><br>
% }
+% } # end foreach
+</font>
+% } else {
+% my $content = $Message;
+% RT::Interface::Web::EscapeUTF8(\$content);
+% $m->comp('/Elements/Callback', content => \$content, %ARGS);
+% $content =~ s/\n/<br>/gi;
+<%$content |n%><br>
% }
<%INIT>
use URI::URL;
diff --git a/rt/html/Ticket/Elements/ShowPeople b/rt/html/Ticket/Elements/ShowPeople
index 0b80269..160da70 100644
--- a/rt/html/Ticket/Elements/ShowPeople
+++ b/rt/html/Ticket/Elements/ShowPeople
@@ -27,15 +27,15 @@
<td class="value"><%$Ticket->OwnerObj->Name%></td>
</tr>
<tr>
- <td class="label"><&|/l&>Requestors</&>:</td>
+ <td class="labeltop"><&|/l&>Requestors</&>:</td>
<td class="value"><%$Ticket->RequestorAddresses%></td>
</tr>
<tr>
- <td class="label"><&|/l&>Cc</&>:</td>
+ <td class="labeltop"><&|/l&>Cc</&>:</td>
<td class="value"><%$Ticket->CcAddresses%></td>
</tr>
<tr>
- <td class="label"><&|/l&>AdminCc</&>:</td>
+ <td class="labeltop"><&|/l&>AdminCc</&>:</td>
<td class="value"><%$Ticket->AdminCcAddresses%></td>
</tr>
</table>
diff --git a/rt/html/Ticket/Elements/ShowTransaction b/rt/html/Ticket/Elements/ShowTransaction
index f2f89d3..2d710fc 100644
--- a/rt/html/Ticket/Elements/ShowTransaction
+++ b/rt/html/Ticket/Elements/ShowTransaction
@@ -38,8 +38,6 @@
unless ($Collapsed) {
$attachments->GotoFirstItem;
while (my $message=$attachments->Next) {
- #we don't want to show any empty transactions, unless they have kids
- next unless ($message->ContentLength || $message->Children->Count);
my ($headers, $quoted);
if ($ShowHeaders && ($ShowHeaders == $Ticket->Id)) {
@@ -53,11 +51,18 @@ unless ($Collapsed) {
eval {$headers =~ s/^([^:]+)(?=:)/loc($1)/em; } # we eval here to catch errors when 5.6 panics
}
# 13456 is a random # of about the biggest size we want to see inline text
- my $MAX_INLINE_BODY = 13456;
+ # It's here to catch anyone who hasn't updated RT_Config.pm since this
+ # constant was moved out there.
+ my $MAX_INLINE_BODY = $RT::MaxInlineBody || 13456;
if ($message->ContentType =~ m{^(text/plain|message|text$)}i &&
$message->ContentLength < $MAX_INLINE_BODY ) {
+ eval {
require Text::Quoted;
- $quoted = Text::Quoted::extract($message->Content);
+ $quoted = Text::Quoted::extract($message->Content);
+ };
+ if ($@) {
+ $quoted = $message->Content;
+ }
}
</%PERL>
@@ -69,7 +74,12 @@ unless ($Collapsed) {
<PRE>
<& ShowMessageHeaders, Headers => $headers, Transaction => $Transaction &>
</PRE>
+% if (!length($quoted) && $message->ContentType =~ m#^text/#) {
+<blockquote><i><&|/l&>Message body not shown because it is too large or is not plain text.</&><br>
+<&|/l&>You can access it with the Download button on the right.</&></i></blockquote>
+% } else {
<& ShowMessageStanza, Depth => 0, Message => $quoted, Transaction => $Transaction &>
+% }
</span>
</TD>
<TD VALIGN=TOP ALIGN=RIGHT>
@@ -78,7 +88,7 @@ unless ($Collapsed) {
<BR>
% }
<%PERL>
-my $size = $message->ContentLength;
+my $size = $message->ContentLength or next;
if ($size) {
if ($size > 1024) {
@@ -88,7 +98,7 @@ if ($size) {
$size = loc("[_1]b", $size);
}
</%PERL>
-<font size=-1><A HREF="<%$RT::WebPath%>/Ticket/Attachment/<%$Transaction->Id%>/<%$message->Id%>/<%$message->Filename%>"><&|/l&>Download</&> <% $message->Filename|| loc('(untitled)') %></a> <% $size %></font>
+<font size=-1><A HREF="<%$AttachPath%>/<%$Transaction->Id%>/<%$message->Id%>/<%$message->Filename | u%>"><&|/l&>Download</&> <% $message->Filename|| loc('(untitled)') %></a> <% $size %></font>
% }
</TD>
</TR>
@@ -104,6 +114,7 @@ $ShowHeaders => 0
$Collapsed => undef
$ShowTitleBarCommands => 1
$RowNum => 1
+$AttachPath => $RT::WebPath."/Ticket/Attachment"
</%ARGS>
<%INIT>
@@ -147,6 +158,7 @@ if ($Transaction->TimeTaken > 0) {
$TimeTaken = $Transaction->TimeTaken." min"
}
my $attachments = $Transaction->Attachments;
+$attachments->Columns( qw( Id Filename ContentType Headers Subject Parent ContentEncoding ContentType TransactionId) );
my $titlebar_commands='&nbsp;';
diff --git a/rt/html/Ticket/Elements/Tabs b/rt/html/Ticket/Elements/Tabs
index 81c92e8..cba45df 100644
--- a/rt/html/Ticket/Elements/Tabs
+++ b/rt/html/Ticket/Elements/Tabs
@@ -45,11 +45,17 @@ my $id = $Ticket->id();
if ( defined $session{'tickets'} ) {
+ # we have to update session data if we get new ItemMap
+ my $updatesession = 1 unless($session{'tickets'}->{'item_map'});
-my $item_map = $session{'tickets'}->ItemMap;
+ my $item_map = $session{'tickets'}->ItemMap;
- # Don't $current_toptab = display prev links if we're on the first ticket
+ if ($updatesession) {
+ $session{'i'}++;
+ $session{'tickets'}->PrepForSerialization();
+ }
+ # Don't $current_toptab = display prev links if we're on the first ticket
if ($item_map->{$Ticket->Id}->{prev}) {
$searchtabs->{'_a'} = {
class => "nav",
diff --git a/rt/html/Ticket/Modify.html b/rt/html/Ticket/Modify.html
index c97fd09..e504a3cb 100644
--- a/rt/html/Ticket/Modify.html
+++ b/rt/html/Ticket/Modify.html
@@ -46,7 +46,7 @@ my $CustomFields = $TicketObj->QueueObj->CustomFields();
$m->comp('/Elements/Callback', TicketObj => $TicketObj, CustomFields => $CustomFields, %ARGS);
my @results = ProcessTicketBasics(TicketObj => $TicketObj, ARGSRef => \%ARGS);
-my @cf_results = ProcessTicketCustomFieldUpdates(ARGSRef => \%ARGS);
+my @cf_results = ProcessTicketCustomFieldUpdates(TicketObj => $TicketObj, ARGSRef => \%ARGS);
push (@results, @cf_results);
# TODO: display the results, even if we can't display the ticket
diff --git a/rt/html/Ticket/ModifyAll.html b/rt/html/Ticket/ModifyAll.html
index a506893..1163f3f 100644
--- a/rt/html/Ticket/ModifyAll.html
+++ b/rt/html/Ticket/ModifyAll.html
@@ -115,7 +115,7 @@ my (@wresults, @results, @dresults, @lresults, @cf_results);
unless ($OnlySearchForPeople) {
@wresults = ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS);
@results = ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS);
- @cf_results = ProcessTicketCustomFieldUpdates(ARGSRef => \%ARGS);
+ @cf_results = ProcessTicketCustomFieldUpdates( TicketObj => $Ticket, ARGSRef => \%ARGS);
@dresults = ProcessTicketDates( TicketObj => $Ticket, ARGSRef => \%ARGS);
@lresults = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
diff --git a/rt/html/Ticket/ModifyPeople.html b/rt/html/Ticket/ModifyPeople.html
index 2e41664..debd27a 100644
--- a/rt/html/Ticket/ModifyPeople.html
+++ b/rt/html/Ticket/ModifyPeople.html
@@ -44,7 +44,7 @@ my (@results, @wresults);
my $Ticket = LoadTicket($id);
# if we're trying to search for watchers and nothing else
-unless ($OnlySearchForPeople) {
+unless ($OnlySearchForPeople or $OnlySearchForGroup) {
@results = ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS);
@wresults = ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS);
}
@@ -56,6 +56,7 @@ push @results, @wresults;
<%ARGS>
$OnlySearchForPeople => undef
+$OnlySearchForGroup => undef
$UserField => undef
$UserOp => undef
$UserString => undef
diff --git a/rt/html/Ticket/Update.html b/rt/html/Ticket/Update.html
index e19aacf..ad3b217 100644
--- a/rt/html/Ticket/Update.html
+++ b/rt/html/Ticket/Update.html
@@ -23,7 +23,7 @@
%# END LICENSE BLOCK
<& /Elements/Header, Title => $title &>
<& /Ticket/Elements/Tabs,
- Ticket => $Ticket ,
+ Ticket => $TicketObj,
Title=> $title &>
<FORM ACTION="Update.html" NAME="TicketUpdate"
@@ -35,20 +35,20 @@
<TABLE>
<TR><TD>
-<a href="ModifyPeople.html?id=<%$Ticket->Id%>"><&|/l&>Ticket watchers</&></A></TD><TD align=right>
+<a href="ModifyPeople.html?id=<%$TicketObj->Id%>"><&|/l&>Ticket watchers</&></A></TD><TD align=right>
<&|/l&>Requestor</&>:
</TD><TD>
-<b><% $Ticket->RequestorAddresses %></b>
+<b><% $TicketObj->RequestorAddresses %></b>
</TD></TR>
<TR><TD>&nbsp;</TD><TD align=right>
<&|/l&>Cc</&>:
</TD><TD>
-<b><% $Ticket->CcAddresses %></b>
+<b><% $TicketObj->CcAddresses %></b>
</TD></TR>
<TR><TD>&nbsp;</TD><TD align=right>
<&|/l&>AdminCc</&>:
</TD><TD>
-<b><% $Ticket->AdminCcAddresses %></b>
+<b><% $TicketObj->AdminCcAddresses %></b>
</TD></TR>
</TR>
</TABLE>
@@ -60,7 +60,7 @@
<td>
<& /Elements/SelectStatus, Name=>"Status", Default => $DefaultStatus &>
<&|/l&>Owner</&>:
-<& /Elements/SelectOwner, Name=>"Owner", Default => ($ARGS{'Owner'} || $Ticket->OwnerObj->Id()), QueueObj => $Ticket->QueueObj, TicketObj => $Ticket &>
+<& /Elements/SelectOwner, Name=>"Owner", Default => ($ARGS{'Owner'} || $TicketObj->OwnerObj->Id()), QueueObj => $TicketObj->QueueObj, TicketObj => $TicketObj &>
<&|/l&>Worked</&>: <input size=4 name="UpdateTimeWorked" value="<% $ARGS{UpdateTimeWorked}%>"> <&|/l&>minutes</&></td></tr>
<tr><td align=right><&|/l&>Update Type</&>:</td>
<td><select name="UpdateType">
@@ -72,7 +72,7 @@
% }
</select>
</td></tr>
-<tr><td align=right><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size=60 value="<% ($ARGS{UpdateSubject}) ? $ARGS{UpdateSubject} : $Ticket->Subject()%>"></td></tr>
+<tr><td align=right><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size=60 value="<% ($ARGS{UpdateSubject}) ? $ARGS{UpdateSubject} : $TicketObj->Subject()%>"></td></tr>
<tr><td align=right><&|/l&>Cc</&>:</td><td> <input name="UpdateCc" size=60
value=<% $ARGS{UpdateCc} %>><BR>
<i><font size=-2>
@@ -101,12 +101,12 @@ value=<% $ARGS{UpdateCc} %>><BR>
<& /Elements/Callback, _CallbackName => 'BeforeMessageBox', %ARGS &>
% if (exists $ARGS{UpdateContent}) {
% delete $ARGS{'QuoteTransaction'};
-<& /Elements/MessageBox, Name=>"UpdateContent", Default=>$ARGS{UpdateContent}, %ARGS&>
+<& /Elements/MessageBox, Name=>"UpdateContent", Default=>$ARGS{UpdateContent}, IncludeSignature => 0, %ARGS&>
% } else {
<& /Elements/MessageBox, Name=>"UpdateContent", %ARGS &>
% }
</td></tr>
- <INPUT TYPE=HIDDEN NAME=id VALUE="<%$Ticket->Id%>"><br>
+ <INPUT TYPE=HIDDEN NAME=id VALUE="<%$TicketObj->Id%>"><br>
</table>
@@ -123,10 +123,10 @@ my $CanRespond = 0;
my $CanComment = 0;
my $title;
-my $Ticket = LoadTicket($id);
+my $TicketObj = LoadTicket($id);
unless($DefaultStatus){
- $DefaultStatus=($ARGS{'Status'} ||$Ticket->Status());
+ $DefaultStatus=($ARGS{'Status'} ||$TicketObj->Status());
}
if ($DefaultStatus =~ '^new$'){
@@ -134,9 +134,9 @@ if ($DefaultStatus =~ '^new$'){
}
if ($DefaultStatus eq 'resolved') {
- $title = loc("Resolve ticket #[_1] ([_2])", $Ticket->id, $Ticket->Subject);
+ $title = loc("Resolve ticket #[_1] ([_2])", $TicketObj->id, $TicketObj->Subject);
} else {
- $title = loc("Update ticket #[_1] ([_2])", $Ticket->id, $Ticket->Subject);
+ $title = loc("Update ticket #[_1] ([_2])", $TicketObj->id, $TicketObj->Subject);
}
# Things needed in the template - we'll do the processing here, just
@@ -150,11 +150,11 @@ if (($Action eq 'Comment') or ($ARGS{'UpdateType'} eq 'private')) {
}
-$CanRespond = 1 if ( $Ticket->CurrentUserHasRight('ReplyToTicket') or
- $Ticket->CurrentUserHasRight('ModifyTicket') );
+$CanRespond = 1 if ( $TicketObj->CurrentUserHasRight('ReplyToTicket') or
+ $TicketObj->CurrentUserHasRight('ModifyTicket') );
-$CanComment = 1 if ( $Ticket->CurrentUserHasRight('CommentOnTicket') or
- $Ticket->CurrentUserHasRight('ModifyTicket') );
+$CanComment = 1 if ( $TicketObj->CurrentUserHasRight('CommentOnTicket') or
+ $TicketObj->CurrentUserHasRight('ModifyTicket') );
# {{{ deal with deleting uploaded attachments
@@ -193,7 +193,7 @@ unless (keys %{$session{'Attachments'}} and $ARGS{'UpdateAttach'}) {
# }}}
if ( exists $ARGS{SubmitTicket} ) {
- $m->comp('Display.html', %ARGS);
+ $m->comp('Display.html', TicketObj => $TicketObj, %ARGS);
return;
}
</%INIT>
diff --git a/rt/html/User/Prefs.html b/rt/html/User/Prefs.html
index b89fc40..c2746a3 100644
--- a/rt/html/User/Prefs.html
+++ b/rt/html/User/Prefs.html
@@ -38,21 +38,44 @@
<& /Elements/TitleBoxStart, title => loc('Identity') &>
<input type=hidden name="Name" value="<%$UserObj->Name%>">
-<&|/l&>Email</&>: <input name="EmailAddress" value="<%$UserObj->EmailAddress%>">
-<BR>
-<&|/l&>Real Name</&>: <input name="RealName" value="<%$UserObj->RealName%>">
-<BR>
-<&|/l&>Nickname</&>: <input name="NickName" value="<%$UserObj->NickName%>">
+<table callspacing=0 cellpadding=0>
+ <tr>
+ <td class=label><&|/l&>Email</&>: </td>
+ <td class=value><input name="EmailAddress" value="<%$UserObj->EmailAddress%>"></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Real Name</&>:</td>
+ <td class=value><input name="RealName" value="<%$UserObj->RealName%>"></td> </tr>
+ <tr>
+ <td class=label><&|/l&>Nickname</&>:</td>
+ <td class=value><input name="NickName" value="<%$UserObj->NickName%>"></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Language</&>:</td>
+ <td class=value><& /Elements/SelectLang, Name => 'Lang', Default => $UserObj->Lang &></td>
+ </tr>
+</table>
<& /Elements/TitleBoxEnd &>
<br>
<& /Elements/TitleBoxStart, title => loc('Phone numbers') &>
-<&|/l&>Residence</&>: <input name="HomePhone" value="<%$UserObj->HomePhone%>" size=13>
-<BR>
-<&|/l&>Work</&>: <input name="WorkPhone" value="<%$UserObj->WorkPhone%>" size=13>
-<BR>
-<&|/l&>Mobile</&>: <input name="MobilePhone" value="<%$UserObj->MobilePhone%>" size=13>
-<BR>
-<&|/l&>Pager</&>: <input name="PagerPhone" value="<%$UserObj->PagerPhone%>" size=13>
+<table callspacing=0 cellpadding=0>
+ <tr>
+ <td class=label><&|/l&>Residence</&>:</td>
+ <td class=value><input name="HomePhone" value="<%$UserObj->HomePhone%>" size=13></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Work</&>:</td>
+ <td class=value><input name="WorkPhone" value="<%$UserObj->WorkPhone%>" size=13></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Mobile</&>:</td>
+ <td class=value><input name="MobilePhone" value="<%$UserObj->MobilePhone%>" size=13></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Pager</&>:</td>
+ <td class=value><input name="PagerPhone" value="<%$UserObj->PagerPhone%>" size=13></td>
+ </tr>
+</table>
<& /Elements/TitleBoxEnd &>
</TD>
<TD VALIGN=TOP>
@@ -60,44 +83,58 @@
<& /Elements/TitleBoxStart, title => loc('Password') &>
<TABLE>
<TR>
-<TD ALIGN=RIGHT>
+<TD class=label>
<&|/l&>New Password</&>:
</TD>
-<TD ALIGN=LEFT>
+<TD class=value>
<input type=password name="Pass1">
</TD>
</TR>
-<TR><TD ALIGN=RIGHT>
+<TR><TD class=label>
<&|/l&>Retype Password</&>:
</TD>
-<TD>
+<TD class=value>
<input type=password name="Pass2">
</TD>
</TR>
</TABLE>
-% }
<& /Elements/TitleBoxEnd &>
+% }
</TD>
<TR>
<TD VALIGN=TOP>
<& /Elements/TitleBoxStart, title => loc('Location') &>
-<&|/l&>Organization</&>: <input name="Organization" value="<%$UserObj->Organization%>">
-<BR>
-<&|/l&>Address1</&>: <input name="Address1" value="<%$UserObj->Address1%>">
-<BR>
-<&|/l&>Address2</&>: <input name="Address2" value="<%$UserObj->Address2%>">
-<BR>
-<&|/l&>City</&>: <input name="City" value="<%$UserObj->City%>" size=14>
-
-<&|/l&>State</&>: <input name="State" value="<%$UserObj->State%>" size=3>
-
-<&|/l&>Zip</&>: <input name="Zip" value="<%$UserObj->Zip%>" size=9>
-<BR>
-<&|/l&>Country</&>: <input name="Country" value="<%$UserObj->Country%>">
-<BR>
-
-
+<table callspacing=0 cellpadding=0>
+ <tr>
+ <td class=label><&|/l&>Organization</&>:</td>
+ <td class=value><input name="Organization" value="<%$UserObj->Organization%>"></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Address1</&>:</td>
+ <td class=value><input name="Address1" value="<%$UserObj->Address1%>"></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Address2</&>:</td>
+ <td class=value><input name="Address2" value="<%$UserObj->Address2%>"></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>City</&>:</td>
+ <td><input name="City" value="<%$UserObj->City%>" size=14></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>State</&>:</td>
+ <td class=value><input name="State" value="<%$UserObj->State%>" size=3></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Zip</&>:</td>
+ <td class=value><input name="Zip" value="<%$UserObj->Zip%>" size=9></td>
+ </tr>
+ <tr>
+ <td class=label><&|/l&>Country</&>:</td>
+ <td class=value><input name="Country" value="<%$UserObj->Country%>"></td>
+ </tr>
+</table>
<& /Elements/TitleBoxEnd &>
</TD>
</TR>
@@ -147,12 +184,13 @@ if ($UserObj->Id) {
Organization RealName NickName Lang EmailEncoding WebEncoding
ExternalContactInfoId ContactInfoSystem Gecos ExternalAuthId
AuthSystem HomePhone WorkPhone MobilePhone PagerPhone Address1
- Address2 City State Zip Country
+ Address2 City State Zip Country Lang
);
my @fieldresults = UpdateRecordObject ( AttributesRef => \@fields,
Object => $UserObj,
ARGSRef => \%ARGS );
+ $session{'CurrentUser'}->LanguageHandle($Lang) if $Lang;
push (@results,@fieldresults);
diff --git a/rt/html/autohandler b/rt/html/autohandler
index ce8b756..b2a407a 100644
--- a/rt/html/autohandler
+++ b/rt/html/autohandler
@@ -27,18 +27,24 @@
$RT::Handle->ForceRollback() if $RT::Handle->TransactionDepth;
-local *session;
+local *session unless $m->is_subrequest; # avoid reentrancy, as suggested by masonbook
+
+# Disable AutoFlush using an attribute
+if ($m->request_comp->attr_exists('AutoFlush')) {
+ $m->autoflush($m->request_comp->attr('AutoFlush'));
+}
+
%ARGS = map {
- # if they've passed multiple values, they'll be an array. if they've passed just one, a scalar
- # whatever they are, mark them as utf8
+ # if they've passed multiple values, they'll be an array. if they've
+ # passed just one, a scalar whatever they are, mark them as utf8
my $type = ref($_);
(!$type)
? Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
- ($type eq 'ARRAY')
+ ($type eq 'ARRAY')
? [ map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
- ($type eq 'HASH')
+ ($type eq 'HASH')
? { map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
-} %ARGS;
+ } %ARGS;
if ($ARGS{'Debug'}) {
require Time::HiRes;
@@ -65,69 +71,95 @@ if ($m->base_comp->path =~ '^/+NoAuth/' ||
$m->abort();
}
-# If RT is configured for external auth, let's get REMOTE_USER
-elsif ($RT::WebExternalAuth and length($ENV{'REMOTE_USER'})) {
- my $orig_user = $user;
-
- $user = $ENV{'REMOTE_USER'};
- $session{'CurrentUser'} = RT::CurrentUser->new();
- my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
-
- if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
- my $NodeName = Win32::NodeName();
- $user =~ s/^\Q$NodeName\E\\//i;
- }
-
- $session{'CurrentUser'}->$load_method($user);
-
- if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
- # Create users on-the-fly with default attributes
-
- my $UserObj = RT::User->new(RT::CurrentUser->new('root'));
-
- my ($val, $msg) = $UserObj->Create(
- %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
- Name => $user,
- Gecos => $user,
- );
-
- if ($val) {
- $UserObj->SetPrivileged(1);
-
- if ($^O !~ /^(?:riscos|MacOS|MSWin32|dos|os2)$/) {
- # Populate fields with information from Unix /etc/passwd
-
- my ($comments, $realname) = (getpwnam($user))[5, 6];
- $UserObj->SetComments($comments) if defined $comments;
- $UserObj->SetRealName($realname) if defined $realname;
+# If RT is configured for external auth, let's go through and get REMOTE_USER
+elsif ( $RT::WebExternalAuth ) {
+
+ # do we actually have a REMOTE_USER equivlent?
+ if ( RT::Interface::Web::WebCanonicalizeInfo() ) {
+
+ my $orig_user = $user;
+
+ $user = RT::Interface::Web::WebCanonicalizeInfo();
+ $session{'CurrentUser'} = RT::CurrentUser->new();
+ my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
+
+ if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
+ my $NodeName = Win32::NodeName();
+ $user =~ s/^\Q$NodeName\E\\//i;
+ }
+
+ $session{'CurrentUser'}->$load_method($user);
+
+ if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
+ # Create users on-the-fly
+
+ my $UserObj = RT::User->new(RT::CurrentUser->new('root'));
+
+ my ($val, $msg) = $UserObj->Create(
+ %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
+ Name => $user,
+ Gecos => $user,
+ );
+
+ if ($val) {
+
+ # now get user specific information, to better create our user.
+ my $new_user_info = RT::Interface::Web::WebExternalAutoInfo($user);
+
+ # set the attributes that have been defined.
+ # FIXME: this is a horrible kludge. I'm sure there's something cleaner
+ foreach my $attribute ('Name', 'Comments', 'Signature', 'EmailAddress',
+ 'PagerEmailAddress', 'FreeformContactInfo',
+ 'Organization', 'Disabled', 'Privileged',
+ 'RealName', 'NickName', 'Lang', 'EmailEncoding',
+ 'WebEncoding', 'ExternalContactInfoId',
+ 'ContactInfoSystem', 'ExternalAuthId', 'Gecos',
+ 'HomePhone', 'WorkPhone', 'MobilePhone',
+ 'PagerPhone', 'Address1', 'Address2', 'City',
+ 'State', 'Zip', 'Country') {
+
+ my $method = "Set$attribute";
+ $UserObj->$method($new_user_info->{$attribute})
+ if( defined $new_user_info->{$attribute} );
+ }
+ $session{'CurrentUser'}->Load($user);
}
- elsif ($^O eq 'MSWin32' and eval 'use Net::AdminMisc; 1') {
- # Populate fields with information from NT domain controller
+ else {
+ # we failed to successfully create the user. abort abort abort.
+ delete $session{'CurrentUser'};
+ $m->abort() unless $RT::WebFallbackToInternalAuth;
+ $m->comp('/Elements/Login', %ARGS,
+ Error=> loc('Cannot create user: [_1]', $msg));
}
-
- $session{'CurrentUser'}->Load($user);
}
- else {
+
+ unless ( $session{'CurrentUser'}->Id() ) {
delete $session{'CurrentUser'};
- $m->abort() unless $RT::WebFallbackToInternalAuth;
- $m->comp('/Elements/Login', %ARGS, Error=> loc('Cannot create user: [_1]', $msg));
+ $user = $orig_user;
+
+ if ( $RT::WebExternalOnly ) {
+ $m->comp('/Elements/Login', %ARGS,
+ Error=> loc('You are not an authorized user'));
+ $m->abort();
+ }
}
}
-
- unless ( $session{'CurrentUser'}->Id() ) {
- delete $session{'CurrentUser'};
- $user = $orig_user;
-
- if ( $RT::WebExternalOnly ) {
- $m->comp('/Elements/Login', %ARGS, Error=> loc('You are not an authorized user'));
- $m->abort();
+ elsif ($RT::WebFallbackToInternalAuth) {
+ unless (defined($session{'CurrentUser'})) {
+ $m->comp('/Elements/Login', %ARGS,
+ Error=> loc('XXX CHANGEME You are not an authorized user'));
+ $m->abort();
}
+ } else {
+ # WebExternalAuth is set, but we don't have a REMOTE_USER. abort
+ delete $session{'CurrentUser'} if defined $session{'CurrentUser'};
}
}
delete $session{'CurrentUser'}
unless $session{'CurrentUser'} and defined $session{'CurrentUser'}->Id;
+
# Process per-page authentication callbacks
$m->comp('/Elements/Callback', %ARGS, _CallbackName => 'Auth');
diff --git a/rt/html/index.html b/rt/html/index.html
index 39eac8d..798972d 100644
--- a/rt/html/index.html
+++ b/rt/html/index.html
@@ -53,7 +53,8 @@ if ( $ARGS{'q'} ) {
$session{'tickets'} = RT::Tickets->new( $session{'CurrentUser'} );
if ( $query =~ m/\@/ ) {
- $session{'tickets'}->LimitRequestor( VALUE => $query,
+ $session{'tickets'}->LimitWatcher( VALUE => $query,
+ TYPE => 'Requestor',
OPERATOR => '=', );
$m->redirect("$RT::WebPath/Search/Listing.html");
}