[Rt-commit] r5395 - in rt/branches/3.7-EXPERIMENTAL-RTIR-2.0: . bin etc etc/upgrade/QUEBEC html/Elements html/NoAuth/css/3.5-default html/REST/1.0 html/REST/1.0/Forms/ticket html/REST/1.0/search lib/t/regression sbin

ruz at bestpractical.com ruz at bestpractical.com
Fri Jun 16 11:20:49 EDT 2006


Author: ruz
Date: Fri Jun 16 11:20:47 2006
New Revision: 5395

Removed:
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/etc/upgrade/QUEBEC/
Modified:
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/   (props changed)
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/bin/rt.in
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/etc/RT_Config.pm.in
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/Callback
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/QueueSummary
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/NoAuth/css/3.5-default/misc.css
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/default
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/history
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/take
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/dhandler
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/search/ticket
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/CustomField_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Date.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Record.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Ticket_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay_SQL.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Transaction_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/07-rights.t
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/09-api-date.t
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/13-attribute-tests.t
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/14-linking.t
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/26command_line.t
   rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/sbin/rt-setup-database.in

Log:
merge 3.7-EXP -> 3.7-EXP-RTIR-2.0, this is last feature merge before freeze
next only bug fixes

 r3145 at cubic-pc (orig r5353):  ruz | 2006-06-10 03:04:10 +0400
  r3112 at cubic-pc (orig r5287):  jesse | 2006-05-24 01:30:33 +0400
   r14034 at hualien:  jesse | 2006-05-23 17:28:31 -0400
   * the 3.5 upgrade scripts trump the quebec scripts. we can ignore quebec
  
 
 r3146 at cubic-pc (orig r5354):  ruz | 2006-06-10 03:04:19 +0400
  r3113 at cubic-pc (orig r5290):  ruz | 2006-05-25 01:12:02 +0400
  * Order attributes as we depend on ordering in tests
 
 r3147 at cubic-pc (orig r5355):  ruz | 2006-06-10 03:11:49 +0400
  r3114 at cubic-pc (orig r5291):  jesse | 2006-05-26 01:56:01 +0400
   r9817 at jesse-vincents-computer-2:  jesse | 2006-05-25 17:55:26 -0400
   * Cleaned up a couple of warnings for redeclared variables
  
 
 r3152 at cubic-pc (orig r5358):  ruz | 2006-06-15 02:23:58 +0400
  r3142 at cubic-pc:  cubic | 2006-06-04 04:50:18 +0400
  * forwardport of CSS changes
 
 r3153 at cubic-pc (orig r5359):  ruz | 2006-06-15 02:24:07 +0400
  r3148 at cubic-pc:  cubic | 2006-06-10 08:51:54 +0400
  * minor
 
 r3154 at cubic-pc (orig r5360):  ruz | 2006-06-15 02:24:27 +0400
  r3151 at cubic-pc:  cubic | 2006-06-15 02:28:53 +0400
  * oops, internal key was renamed
 
 r3155 at cubic-pc (orig r5373):  ruz | 2006-06-16 01:53:04 +0400
  r3115 at cubic-pc (orig r5292):  ruz | 2006-05-26 02:12:05 +0400
  * New option StrictLinkACL
    # When this feature is enabled an user need ModifyTicket right on both
    # tickets to link them together, otherwise he can have right on any of
    # two.
  ** update Create, _?AddLink, DeleteLink methods
  * fix: we created transaction if some tries to create link that allready
    exists
  * move all acl checks out from _AddLink to AddLink method
  * cover with every change with tests
 
 r3156 at cubic-pc (orig r5374):  ruz | 2006-06-16 01:53:15 +0400
  r3116 at cubic-pc (orig r5293):  ruz | 2006-05-26 02:25:21 +0400
  * return results of the Delete method as it may fail too
 
 r3157 at cubic-pc (orig r5375):  ruz | 2006-06-16 01:54:13 +0400
  r3117 at cubic-pc (orig r5294):  jesse | 2006-05-26 05:14:59 +0400
   r9822 at jesse-vincents-computer-2:  jesse | 2006-05-25 21:12:23 -0400
   * Small fixes to ticket history display
  
 
 r3158 at cubic-pc (orig r5376):  ruz | 2006-06-16 02:00:02 +0400
  r3118 at cubic-pc (orig r5295):  jesse | 2006-05-26 05:15:05 +0400
   r9823 at jesse-vincents-computer-2:  jesse | 2006-05-25 21:12:39 -0400
   * Quieting down some redefinition warnings
  
 
 r3159 at cubic-pc (orig r5377):  ruz | 2006-06-16 02:00:11 +0400
  r3119 at cubic-pc (orig r5296):  jesse | 2006-05-26 05:15:12 +0400
   r9824 at jesse-vincents-computer-2:  jesse | 2006-05-25 21:13:11 -0400
   * Actually do a credible job of showing html-only email messages in ticket history by downsampling them to plain text.
  
 
 r3160 at cubic-pc (orig r5378):  ruz | 2006-06-16 02:00:21 +0400
  r3120 at cubic-pc (orig r5297):  jesse | 2006-05-26 08:11:22 +0400
   r9830 at jesse-vincents-computer-2:  jesse | 2006-05-25 23:18:44 -0400
   Stopped using a deprecated API
  
 
 r3161 at cubic-pc (orig r5379):  ruz | 2006-06-16 02:03:12 +0400
  r3121 at cubic-pc (orig r5298):  jesse | 2006-05-26 08:11:28 +0400
   r9831 at jesse-vincents-computer-2:  jesse | 2006-05-25 23:20:36 -0400
   * Added custom summary "ticket lists" using the commandline (combining -f and -s) lists.
   * Fixed a couple small bugs
  
 
 r3162 at cubic-pc (orig r5380):  ruz | 2006-06-16 02:03:23 +0400
  r3122 at cubic-pc (orig r5299):  jesse | 2006-05-26 08:11:37 +0400
   r9832 at jesse-vincents-computer-2:  jesse | 2006-05-26 00:06:54 -0400
    *Fix compilation errors on wip to help make tests not bomb out
  
 
 r3163 at cubic-pc (orig r5381):  ruz | 2006-06-16 02:03:34 +0400
  r3123 at cubic-pc (orig r5300):  jesse | 2006-05-26 08:11:51 +0400
   r9833 at jesse-vincents-computer-2:  jesse | 2006-05-26 00:07:09 -0400
   * Typo fix 
  
 
 r3164 at cubic-pc (orig r5382):  ruz | 2006-06-16 02:03:51 +0400
  r3124 at cubic-pc (orig r5301):  jesse | 2006-05-26 08:11:58 +0400
   r9834 at jesse-vincents-computer-2:  jesse | 2006-05-26 00:07:24 -0400
    * Back out mistaken change
  
 
 r3165 at cubic-pc (orig r5383):  ruz | 2006-06-16 02:03:59 +0400
  r3125 at cubic-pc (orig r5302):  jesse | 2006-05-26 08:12:03 +0400
   r9835 at jesse-vincents-computer-2:  jesse | 2006-05-26 00:07:45 -0400
   * dont
  
 
 r3166 at cubic-pc (orig r5384):  ruz | 2006-06-16 02:04:10 +0400
  r3126 at cubic-pc (orig r5303):  ruz | 2006-05-26 19:15:46 +0400
  * take/steal actions in CLI
  ** pass 'take|steal|untake' as Action argument to REST
  ** don't check rights in REST interface, SetOwner do that for us
  ** return more descriptive message when we try to take ticket from
     other user
  ** all tests pass
 
 r3167 at cubic-pc (orig r5385):  ruz | 2006-06-16 02:04:29 +0400
  r3127 at cubic-pc (orig r5304):  ruz | 2006-05-26 19:50:44 +0400
  * add untake action
 
 r3168 at cubic-pc (orig r5386):  ruz | 2006-06-16 02:04:40 +0400
  r3128 at cubic-pc (orig r5306):  ruz | 2006-05-26 20:40:22 +0400
  * drop old bits
 
 r3169 at cubic-pc (orig r5387):  ruz | 2006-06-16 02:04:58 +0400
  r3129 at cubic-pc (orig r5307):  ruz | 2006-05-26 20:42:33 +0400
  * vsplit Requestor, Cc and AdminCc field on create
 
 r3208 at cubic-pc (orig r5388):  ruz | 2006-06-16 03:54:29 +0400
  r3203 at cubic-pc:  cubic | 2006-06-16 02:23:05 +0400
  * get rid of a warning
 
 r3209 at cubic-pc (orig r5389):  ruz | 2006-06-16 03:54:37 +0400
  r3204 at cubic-pc:  cubic | 2006-06-16 03:21:56 +0400
  * fix merge bugs
 
 r3210 at cubic-pc (orig r5390):  ruz | 2006-06-16 03:54:46 +0400
  r3205 at cubic-pc:  cubic | 2006-06-16 03:22:16 +0400
  * merge bug
 
 r3211 at cubic-pc (orig r5391):  ruz | 2006-06-16 03:55:02 +0400
  r3206 at cubic-pc:  cubic | 2006-06-16 03:41:57 +0400
  * use_ok takes list of modules not description
 
 r3212 at cubic-pc (orig r5392):  ruz | 2006-06-16 03:55:10 +0400
  r3207 at cubic-pc:  cubic | 2006-06-16 03:42:29 +0400
  * don't warn on undef in AddSeconds
 


Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/bin/rt.in
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/bin/rt.in	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/bin/rt.in	Fri Jun 16 11:20:47 2006
@@ -116,7 +116,7 @@
     link        => ["link", "ln"],
     merge       => ["merge"],
     grant       => ["grant", "revoke"],
-    take        => ["take", "steal"],
+    take        => ["take", "steal", "untake"],
     quit        => ["quit", "exit"],
 );
 
@@ -757,8 +757,6 @@
     my ($bad, %data) = (0, ());
 
     my $id;
-    my $force = 0;
-    $force = 1 if $cmd eq 'steal';
 
     # get the ticket id
     if (@ARGV == 1) {
@@ -769,10 +767,10 @@
         }
         my $form = [
             "",
-            [ "Ticket", "Force" ],
+            [ "Ticket", "Action" ],
             {
                 Ticket => $id,
-                Force => $force,
+                Action => $cmd,
                 Status => '',
             }
         ];
@@ -902,7 +900,7 @@
             # For anything else, we just die.
             elsif ($res->code != 409) {
                 warn "rt: ", $res->content;
-                exit;
+                #exit;
             }
         }
     }

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/etc/RT_Config.pm.in
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/etc/RT_Config.pm.in	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/etc/RT_Config.pm.in	Fri Jun 16 11:20:47 2006
@@ -593,6 +593,11 @@
 # only one of the link transactions to have scrips run.
 Set($LinkTransactionsRun1Scrip , 0);
 
+# When this feature is enabled an user need ModifyTicket right on both
+# tickets to link them together, otherwise he can have right on any of
+# two.
+Set($StrictLinkACL, 1);
+
 # Set $PreviewScripMessages to 1 if the scrips preview on the ticket
 # reply page should include the content of the messages to be sent.
 

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/Callback
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/Callback	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/Callback	Fri Jun 16 11:20:47 2006
@@ -47,7 +47,7 @@
 my %cache;
 </%once>
 <%init>
-$Page = $m->callers(1)->path unless ($Page);
+$Page ||= $m->callers(1)->path;
 
 my $CacheKey = "Callback--$Page--$_CallbackName";
 my $callbacks = $cache{$CacheKey} || $m->notes($CacheKey);
@@ -73,7 +73,7 @@
                    && !$seen{$_}++,
                  $m->interp->resolver->glob_path($path, $root);
     }
-    
+
     $m->notes($CacheKey => $callbacks);
     $cache{ $CacheKey } = $callbacks unless RT->Config->Get('DevelMode');
 }

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/QueueSummary
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/QueueSummary	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/Elements/QueueSummary	Fri Jun 16 11:20:47 2006
@@ -58,7 +58,7 @@
 <tr class="<% $i%2 ? 'oddline' : 'evenline'%>" >
 <td><a href="<% RT->Config->Get('WebPath')%>/Search/Results.html?Query=<%$all_q%>" title="<% $queue->{Description} %>"><%$queue->{Name}%></a></td>
 %   for my $condition (@$conditions) {
-%       $Tickets->FromSQL($queue_cond.$condition->{cond}), 
+%       $Tickets->FromSQL($queue_cond.$condition->{cond}); 
 <td align="right"><a href="<% RT->Config->Get('WebPath')%>/Search/Results.html?Query=<%$queue_cond.$condition->{cond}%>"><% $Tickets->Count %></a></td>
 %   }
 </tr>

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/NoAuth/css/3.5-default/misc.css
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/NoAuth/css/3.5-default/misc.css	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/NoAuth/css/3.5-default/misc.css	Fri Jun 16 11:20:47 2006
@@ -110,3 +110,9 @@
     margin: 0;
     padding: 2px;
 }
+
+#comp-Search-Build .titlebox-content {
+    padding-left: 0.7em;
+    padding-right: 0.3em;
+}
+

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/default
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/default	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/default	Fri Jun 16 11:20:47 2006
@@ -145,6 +145,9 @@
             }
         }
 
+        # people fields allow multiple values
+        $v{$_} = vsplit($v{$_}) foreach ( grep $create{lc $_}, @people );
+
         if ($text) {
             $v{MIMEObj} =
                 MIME::Entity->build(
@@ -185,7 +188,7 @@
     }
 
     foreach $key (@people) {
-	next unless (!%$fields || (exists $fields->{lc $key}));
+        next unless (!%$fields || (exists $fields->{lc $key}));
         push @data, [ $key => [ $ticket->$key->MemberEmailAddresses ] ];
     }
 
@@ -205,8 +208,9 @@
     }
 
     # Display custom fields
-    my $CustomFields = $ticket->QueueObj->CustomFields();
+    my $CustomFields = $ticket->QueueObj->TicketCustomFields();
     while (my $cf = $CustomFields->Next()) {
+	next unless (!%$fields || (exists $fields->{"cf-".lc $cf->Name}));
         my $vals = $ticket->CustomFieldValues($cf->Id());
         my @out = ();
         while (my $v = $vals->Next()) {

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/history
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/history	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/history	Fri Jun 16 11:20:47 2006
@@ -168,8 +168,7 @@
 	    $fieldstring .= $key;
 	}
 	my ($content, $forms);
-
-	$m->subexec(RT->Config->Get('WebPath')."/REST/1.0/show", 
+	$m->subexec("/REST/1.0/show", 
 		    id => \@tid, 
 		    format => $format,
                     fields => $fieldstring);

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/take
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/take	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/Forms/ticket/take	Fri Jun 16 11:20:47 2006
@@ -56,14 +56,17 @@
 my ($c, $o, $k, $e) = ("", [], {}, 0);
 
 # http://.../REST/1.0/ticket/1/take
-$ticket->Load($id);
-if (!$ticket->Id) {
+$ticket->Load( $id );
+unless ( $ticket->Id ) {
     $e = 1;
     $c = "# Ticket $id does not exist.";
     goto OUTPUT;
 }
 
 my $action;
+
+my @comments;
+
 ($action = $changes{Action}) =~ s/^(.)(.*)$/\U$1\L$2\E/;
 unless ($action =~ /^(?:Take|Steal|Untake)$/) {
     $e = 1;
@@ -71,58 +74,59 @@
     goto OUTPUT;
 }
 
-unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
-        ( ($action eq "Take" || $action eq 'Untake') &&
-         $ticket->CurrentUserHasRight("TakeTicket")) ||
-        ($action eq "Steal" &&
-         $ticket->CurrentUserHasRight("StealTicket")))
-{
-    $e = 1;
-    $c = "# You are not allowed to $action ticket $id.";
-    goto OUTPUT;
-}
-
-if (!keys(%data)) {
-    # assemble a form data structure
-    my @data;
-    push @data, [ Ticket => $ticket->Id ];
-    push @data, [ Force => '0' ];       # 1 => "steal"
-}
-else {
-    # process the form data structure
-    my ($key, $val);
-    
-    foreach $key (keys %data) {
-        $val = $data{$key};
-
-        if ($key =~ /^force$/i) {
-            if ($val !~ /^(?:0|1)$/) {
-                push(@comments, "# invalid value for 'force': $val");
-                goto DONE;
-            }
-            my ($ret_id, $msg);
-
-            ### take
-            if ($val == 0) {
-                ($ret_id, $msg) = $ticket->Take;
-                if (!$ret_id) {
-                    push(@comments, "# Couldn't take ticket $id: $msg");
-                    goto DONE;
-                }
-                push(@comments, "# Ticket $id taken.");
-            }
-            ### steal
-            else {
-                ($ret_id, $msg) = $ticket->Steal;
-                if (!$ret_id) {
-                    push(@comments, "# Couldn't steal ticket $id: $msg");
-                    goto DONE;
-                }
-                push(@comments, "# Ticket $id stolen.");
-            }
-        }
-    }
-}
+my ($status, $msg) = $ticket->$action();
+$c = "# $msg";
+$e = 1  unless $status;
+goto OUTPUT;
+
+#unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
+#        ( ($action eq "Take" || $action eq 'Untake') &&
+#         $ticket->CurrentUserHasRight("TakeTicket")) ||
+#        ($action eq "Steal" &&
+#         $ticket->CurrentUserHasRight("StealTicket")))
+#{
+#    $e = 1;
+#    $c = "# You are not allowed to $action ticket $id.";
+#    goto OUTPUT;
+#}
+
+#if ( keys %changes ) {
+#}
+#else {
+#    # process the form data structure
+#    my ($key, $val);
+#    
+#    foreach $key (keys %data) {
+#        $val = $data{$key};
+#
+#        if ($key =~ /^force$/i) {
+#            if ($val !~ /^(?:0|1)$/) {
+#                push(@comments, "# invalid value for 'force': $val");
+#                goto DONE;
+#            }
+#            my ($ret_id, $msg);
+#
+#            ### take
+#            if ($val == 0) {
+#                ($ret_id, $msg) = $ticket->Take;
+#                if (!$ret_id) {
+#                    push(@comments, "# Couldn't take ticket $id: $msg");
+#                    goto DONE;
+#                }
+#                push(@comments, "# Ticket $id taken.");
+#            }
+#            ### steal
+#            else {
+#                ($ret_id, $msg) = $ticket->Steal;
+#                if (!$ret_id) {
+#                    push(@comments, "# Couldn't steal ticket $id: $msg");
+#                    goto DONE;
+#                }
+#                push(@comments, "# Ticket $id stolen.");
+#            }
+#        }
+#    }
+#}
 
 OUTPUT:
 return [ $c, $o, $k, $e ];

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/dhandler
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/dhandler	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/dhandler	Fri Jun 16 11:20:47 2006
@@ -309,7 +309,6 @@
 $output = form_compose(\@output);
 
 OUTPUT:
+$m->out("RT/".$RT::VERSION ." ".$status ."\n\n$output\n") if ($output || $status != 200);
+return;
 </%INIT>
-RT/<% $RT::VERSION %> <% $status %>
-
-<% $output |n %>

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/search/ticket
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/search/ticket	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/html/REST/1.0/search/ticket	Fri Jun 16 11:20:47 2006
@@ -60,7 +60,7 @@
 my $field  = '[a-zA-Z][a-zA-Z0-9_-]*';
 my (%fields, @fields);
 if ($fields) {
-    $format = "l";
+    $format ||= "l";
     unless ($fields =~ /^(?:$field,)*$field$/) {
         $status = "400 Bad Request";
         $output = "Invalid field specification: $fields";
@@ -115,15 +115,29 @@
 while (my $ticket = $tickets->Next) {
     $n++;
 
+	my $id = $ticket->Id;
     if ($format eq "i") {
-        $output .= "ticket/" . $ticket->Id . "\n";
+        $output .= "ticket/" . $id . "\n";
     }
     elsif ($format eq "s") {
-        $output .= $ticket->Id . ": ". $ticket->Subject . "\n";
+	if ($fields) {
+        	my $result = $m->comp("/REST/1.0/Forms/ticket/default", id => $id, format => $format, fields => \%fields);
+		my ($notes, $order, $key_values, $errors) = @$result;
+		# If it's the first time through, add our header
+		if ($n == 1) {
+			$output .= join("\t",@$order)."\n";
+		}
+		# Cut off the annoying ticket/ before the id;
+		$key_values->{'id'} = $id;
+		$output .= join("\t", map {$key_values->{$_}} @$order)."\n";
+	
+
+	} else {	
+        	$output .= $ticket->Id . ": ". $ticket->Subject . "\n";
+	}
     }
     else {
-	my $id = $ticket->Id;
-        my $d = $m->comp('/REST/1.0/Forms/ticket/default', id => $id, format => $format, fields => \%fields);
+        my $d = $m->comp("/REST/1.0/Forms/ticket/default", id => $id, format => $format, fields => \%fields);
         my ($c, $o, $k, $e) = @$d;
 	push @output, [ $c, $o, $k ];
     }
@@ -138,4 +152,5 @@
 $m->out("RT/". $RT::VERSION . " " . $status ."\n\n");
 
 $m->out($output );
+return();
 </%INIT>

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/CustomField_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/CustomField_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/CustomField_Overlay.pm	Fri Jun 16 11:20:47 2006
@@ -854,6 +854,7 @@
 sub AddToObject {
     my $self  = shift;
     my $object = shift;
+    my $id = $object->Id || 0;
 
     unless (index($self->LookupType, ref($object)) == 0) {
     	return ( 0, $self->loc('Lookup type mismatch') );
@@ -863,17 +864,15 @@
         return ( 0, $self->loc('Permission Denied') );
     }
 
-    my $oid = $object->Id || 0;
     my $ObjectCF = RT::ObjectCustomField->new( $self->CurrentUser );
-    $ObjectCF->LoadByCols( ObjectId => $oid, CustomField => $self->Id );
+    $ObjectCF->LoadByCols( ObjectId => $id, CustomField => $self->Id );
     if ( $ObjectCF->Id ) {
         return ( 0, $self->loc("That is already the current value") );
     }
+    my ( $ret, $msg ) =
+      $ObjectCF->Create( ObjectId => $id, CustomField => $self->Id );
 
-    my ( $id, $msg ) =
-      $ObjectCF->Create( ObjectId => $oid, CustomField => $self->Id );
-
-    return ( $id, $msg );
+    return ( $ret, $msg );
 }
 
 
@@ -889,6 +888,7 @@
 sub RemoveFromObject {
     my $self = shift;
     my $object = shift;
+    my $id = $object->Id || 0;
 
     unless (index($self->LookupType, ref($object)) == 0) {
         return ( 0, $self->loc('Object type mismatch') );
@@ -898,15 +898,14 @@
         return ( 0, $self->loc('Permission Denied') );
     }
 
-    my $oid = $object->Id || 0;
     my $ObjectCF = RT::ObjectCustomField->new( $self->CurrentUser );
-    $ObjectCF->LoadByCols( ObjectId => $oid, CustomField => $self->Id );
+    $ObjectCF->LoadByCols( ObjectId => $id, CustomField => $self->Id );
     unless ( $ObjectCF->Id ) {
         return ( 0, $self->loc("This custom field does not apply to that object") );
     }
-    my ( $id, $msg ) = $ObjectCF->Delete;
+    my ( $ret, $msg ) = $ObjectCF->Delete;
 
-    return ( $id, $msg );
+    return ( $ret, $msg );
 }
 
 # {{{ AddValueForObject

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Date.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Date.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Date.pm	Fri Jun 16 11:20:47 2006
@@ -474,7 +474,7 @@
 
 sub AddSeconds {
     my $self = shift;
-    my $delta = shift;
+    my $delta = shift or return $self->Unix;
     
     $self->Set(Format => 'unix', Value => ($self->Unix + $delta));
     

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Record.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Record.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Record.pm	Fri Jun 16 11:20:47 2006
@@ -186,7 +186,7 @@
                                       Description => $args{'Description'},
                                       Content     => $args{'Content'} );
 
-                                     
+
     # XXX TODO: Why won't RedoSearch work here?                                     
     $self->Attributes->_DoSearch;
     
@@ -1257,6 +1257,8 @@
 
 Takes a paramhash of Type and one of Base or Target. Adds that link to this ticket.
 
+Returns C<link id>, C<message> and C<exist> flag.
+
 
 =cut
 
@@ -1302,7 +1304,7 @@
                              Target => $args{'Target'} );
     if ( $old_link->Id ) {
         $RT::Logger->debug("$self Somebody tried to duplicate a link");
-        return ( $old_link->id, $self->loc("Link already exists") );
+        return ( $old_link->id, $self->loc("Link already exists"), 1 );
     }
 
     # }}}
@@ -1367,7 +1369,7 @@
         $direction='Base';
     }
     else {
-        $RT::Logger->debug("$self: Base or Target must be specified\n");
+        $RT::Logger->error("Base or Target must be specified\n");
         return ( 0, $self->loc('Either base or target must be specified') );
     }
 

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Ticket_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Ticket_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Ticket_Overlay.pm	Fri Jun 16 11:20:47 2006
@@ -678,6 +678,20 @@
         foreach my $link (
             ref( $args{$type} ) ? @{ $args{$type} } : ( $args{$type} ) )
         {
+            # Check rights on the other end of the link if we must
+            # then run _AddLink that doesn't check for ACLs
+            if ( RT->Config->Get( 'StrictLinkACL' ) ) {
+                my ($val, $msg, $obj) = $self->__GetTicketFromURI( URI => $link );
+                unless ( $val ) {
+                    push @non_fatal_errors, $msg;
+                    next;
+                }
+                if ( $obj && !$obj->CurrentUserHasRight('ModifyTicket') ) {
+                    push @non_fatal_errors, $self->loc('Linking. Permission denied');
+                    next;
+                }
+            }
+            
             my ( $wval, $wmsg ) = $self->_AddLink(
                 Type                          => $LINKTYPEMAP{$type}->{'Type'},
                 $LINKTYPEMAP{$type}->{'Mode'} => $link,
@@ -2491,11 +2505,29 @@
         @_
     );
 
+    unless ( $args{'Target'} || $args{'Base'} ) {
+        $RT::Logger->error("Base or Target must be specified\n");
+        return ( 0, $self->loc('Either base or target must be specified') );
+    }
+
     #check acls
-    unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
-        $RT::Logger->debug("No permission to delete links\n");
-        return ( 0, $self->loc('Permission Denied'))
+    my $right = 0;
+    $right++ if $self->CurrentUserHasRight('ModifyTicket');
+    if ( !$right && RT->Config->Get( 'StrictLinkACL' ) ) {
+        return ( 0, $self->loc("Permission Denied") );
+    }
 
+    # If the other URI is an RT::Ticket, we want to make sure the user
+    # can modify it too...
+    my ($status, $msg, $other_ticket) = $self->__GetTicketFromURI( URI => $args{'Target'} || $args{'Base'} );
+    return (0, $msg) unless $status;
+    if ( !$other_ticket || $other_ticket->CurrentUserHasRight('ModifyTicket') ) {
+        $right++;
+    }
+    if ( ( !RT->Config->Get( 'StrictLinkACL' ) && $right == 0 ) ||
+         ( RT->Config->Get( 'StrictLinkACL' ) && $right < 2 ) )
+    {
+        return ( 0, $self->loc("Permission Denied") );
     }
 
     my ($val, $Msg) = $self->SUPER::_DeleteLink(%args);
@@ -2521,7 +2553,7 @@
         my ( $Trans, $Msg, $TransObj ) = $self->_NewTransaction(
             Type      => 'DeleteLink',
             Field     => $LINKDIRMAP{$args{'Type'}}->{$direction},
-            OldValue  =>  $remote_uri->URI || $remote_link,
+            OldValue  => $remote_uri->URI || $remote_link,
             TimeTaken => 0
         );
         $RT::Logger->error("Couldn't create transaction: $Msg") unless $Trans;
@@ -2568,13 +2600,52 @@
                  SilentTarget => undef,
                  @_ );
 
+    unless ( $args{'Target'} || $args{'Base'} ) {
+        $RT::Logger->error("Base or Target must be specified\n");
+        return ( 0, $self->loc('Either base or target must be specified') );
+    }
 
-    unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
+    my $right = 0;
+    $right++ if $self->CurrentUserHasRight('ModifyTicket');
+    if ( !$right && RT->Config->Get( 'StrictLinkACL' ) ) {
         return ( 0, $self->loc("Permission Denied") );
     }
 
+    # If the other URI is an RT::Ticket, we want to make sure the user
+    # can modify it too...
+    my ($status, $msg, $other_ticket) = $self->__GetTicketFromURI( URI => $args{'Target'} || $args{'Base'} );
+    return (0, $msg) unless $status;
+    if ( !$other_ticket || $other_ticket->CurrentUserHasRight('ModifyTicket') ) {
+        $right++;
+    }
+    if ( ( !RT->Config->Get( 'StrictLinkACL' ) && $right == 0 ) ||
+         ( RT->Config->Get( 'StrictLinkACL' ) && $right < 2 ) )
+    {
+        return ( 0, $self->loc("Permission Denied") );
+    }
+
+    return $self->_AddLink(%args);
+}
+
+sub __GetTicketFromURI {
+    my $self = shift;
+    my %args = ( URI => '', @_ );
+
+    # If the other URI is an RT::Ticket, we want to make sure the user
+    # can modify it too...
+    my $uri_obj = RT::URI->new( $self->CurrentUser );
+    $uri_obj->FromURI( $args{'URI'} );
 
-    $self->_AddLink(%args);
+    unless ( $uri_obj->Resolver && $uri_obj->Scheme ) {
+	    my $msg = $self->loc( "Couldn't resolve '[_1]' into a URI.", $args{'URI'} );
+        $RT::Logger->warning( "$msg\n" );
+        return( 0, $msg );
+    }
+    my $obj = $uri_obj->Resolver->Object;
+    unless ( UNIVERSAL::isa($obj, 'RT::Ticket') && $obj->id ) {
+        return (1, 'Found not a ticket', undef);
+    }
+    return (1, 'Found ticket', $obj);
 }
 
 =head2 _AddLink  
@@ -2593,45 +2664,9 @@
                  SilentTarget => undef,
                  @_ );
 
-    # {{{ If the other URI is an RT::Ticket, we want to make sure the user
-    # can modify it too...
-    my $other_ticket_uri = RT::URI->new($self->CurrentUser);
-
-    if ( $args{'Target'} ) {
-        $other_ticket_uri->FromURI( $args{'Target'} );
-    }
-    elsif ( $args{'Base'} ) {
-        $other_ticket_uri->FromURI( $args{'Base'} );
-    }
-
-    unless ( $other_ticket_uri->Resolver && $other_ticket_uri->Scheme ) {
-	my $msg = $args{'Target'} ? $self->loc("Couldn't resolve target '[_1]' into a URI.", $args{'Target'})
-          : $self->loc("Couldn't resolve base '[_1]' into a URI.", $args{'Base'});
-        $RT::Logger->warning( "$self $msg\n" );
-
-        return( 0, $msg );
-    }
-
-    # By popular demand, adding a ticket link doesn't check ACLs on the second ticket 
-    #
-    #    if ( $other_ticket_uri->Resolver->Scheme eq 'fsck.com-rt') {
-    #        my $object = $other_ticket_uri->Resolver->Object;
-    #
-    #        if (   UNIVERSAL::isa( $object, 'RT::Ticket' )
-    #            && $object->id
-    #            && !$object->CurrentUserHasRight('ModifyTicket') )
-    #        {
-    #            return ( 0, $self->loc("Permission Denied") );
-    #        }
-    #
-    #    }
-    #
-    # }}}
-
-    my ($val, $Msg) = $self->SUPER::_AddLink(%args);
-    return ($val, $Msg) unless $val;
-
-    return ($val, $Msg) if $args{'Silent'};
+    my ($val, $msg, $exist) = $self->SUPER::_AddLink(%args);
+    return ($val, $msg) if !$val || $exist;
+    return ($val, $msg) if $args{'Silent'};
 
     my ($direction, $remote_link);
     if ( $args{'Target'} ) {
@@ -2657,7 +2692,7 @@
 
     if ( !$args{ 'Silent'. ( $direction eq 'Target'? 'Base': 'Target' ) } && $remote_uri->IsLocal ) {
         my $OtherObj = $remote_uri->Object;
-        my ( $val, $Msg ) = $OtherObj->_NewTransaction(
+        my ( $val, $msg ) = $OtherObj->_NewTransaction(
             Type           => 'AddLink',
             Field          => $direction eq 'Target' ? $LINKDIRMAP{$args{'Type'}}->{Base}
                                             : $LINKDIRMAP{$args{'Type'}}->{Target},
@@ -2665,11 +2700,10 @@
             ActivateScrips => !RT->Config->Get('LinkTransactionsRun1Scrip'),
             TimeTaken      => 0,
         );
-        $RT::Logger->error("Couldn't create transaction: $Msg") unless $val;
+        $RT::Logger->error("Couldn't create transaction: $msg") unless $val;
     }
 
-    return ( $val, $Msg );
-
+    return ( $val, $msg );
 }
 
 # }}}
@@ -2982,9 +3016,12 @@
         ( $self->OwnerObj->Id != $RT::Nobody->Id ) and    #and the owner is set
         ( $self->CurrentUser->Id ne $self->OwnerObj->Id() )
       ) {                                                 #and it's not us
-        return ( 0,
-                 $self->loc(
-"You can only reassign tickets that you own or that are unowned" ) );
+        return ( 0, $self->loc("You can only take tickets that are unowned") )
+            if $NewOwnerObj->id == $self->CurrentUser->id;
+        return (
+            0,
+            $self->loc("You can only reassign tickets that you own or that are unowned" )
+        );
     }
 
     #If we've specified a new owner and that user can't modify the ticket

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay.pm	Fri Jun 16 11:20:47 2006
@@ -1303,7 +1303,6 @@
     my $field = $rest{SUBKEY} || die "No field specified";
 
     # For our sanity, we can only limit on one queue at a time
-
     my ($queue, $cfid);
     ($queue, $field, $cfid ) = $self->_CustomFieldDecipher( $field );
 
@@ -1330,9 +1329,9 @@
             ENTRYAGGREGATOR => 'AND',
         );
     }
-    
+
     $self->_OpenParen if $null_columns_ok;
-    
+
     $self->_SQLLimit(
         ALIAS      => $TicketCFs,
         FIELD      => 'Content',

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay_SQL.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay_SQL.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Tickets_Overlay_SQL.pm	Fri Jun 16 11:20:47 2006
@@ -67,7 +67,7 @@
   $self->{'_sql_transalias'}    = undef;
   $self->{'_sql_trattachalias'} = undef;
   $self->{'_sql_cf_alias'}  = undef;
-  $self->{'_sql_object_cf_alias'}  = undef;
+  $self->{'_sql_object_cfv_alias'}  = undef;
   $self->{'_sql_watcher_join_users_alias'} = undef;
   $self->{'_sql_query'}         = '';
   $self->{'_sql_looking_at'}    = {};

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Transaction_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Transaction_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/RT/Transaction_Overlay.pm	Fri Jun 16 11:20:47 2006
@@ -82,6 +82,10 @@
 use RT::Attachments;
 use RT::Scrips;
 
+use HTML::FormatText;
+use HTML::TreeBuilder;
+
+
 # {{{ sub Create 
 
 =head2 Create
@@ -278,9 +282,13 @@
     );
 
     my $content;
-    my $content_obj = $self->ContentObj;
-    if ($content_obj) {
+    if (my $content_obj = $self->ContentObj) {
         $content = $content_obj->Content;
+
+	if ($content_obj->ContentType =~ m{^text/html$}i) {
+        $content = HTML::FormatText->new(leftmargin => 0, rightmargin => 78)->format(  HTML::TreeBuilder->new_from_content( $content));
+
+	}
     }
 
     # If all else fails, return a message that we couldn't find any content
@@ -342,7 +350,7 @@
 
     # If it's a message or a plain part, just return the
     # body.
-    if ( $Attachment->ContentType() =~ '^(text/plain$|message/)' ) {
+    if ( $Attachment->ContentType() =~ '^(?:text/plain$|text/html|message/)' ) {
         return ($Attachment);
     }
 

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/07-rights.t
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/07-rights.t	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/07-rights.t	Fri Jun 16 11:20:47 2006
@@ -113,7 +113,7 @@
 $group = RT::Group->new( $RT::SystemUser );
 ok( $group->LoadQueueRoleGroup( Queue => $queue_id, Type=> 'AdminCc' ), "load queue AdminCc role group" );
 $ace = RT::ACE->new( $RT::SystemUser );
-my ($ace_id, $msg) = $group->PrincipalObj->GrantRight( Right => 'ModifyTicket', Object => $queue );
+($ace_id, $msg) = $group->PrincipalObj->GrantRight( Right => 'ModifyTicket', Object => $queue );
 ok( $ace_id, "Granted queue AdminCc role group with ModifyTicket right: $msg" );
 ok( $group->PrincipalObj->HasRight( Right => 'ModifyTicket', Object => $queue ), "role group can modify ticket" );
 ok( !$user->HasRight( Right => 'ModifyTicket', Object => $ticket ), "user is not AdminCc and can't modify ticket" );

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/09-api-date.t
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/09-api-date.t	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/09-api-date.t	Fri Jun 16 11:20:47 2006
@@ -10,7 +10,7 @@
 
 use RT::User;
 
-use_ok('RT::Date', "loaded RT::Date");
+use_ok('RT::Date');
 {
     my $date = RT::Date->new($RT::SystemUser);
     isa_ok($date, 'RT::Date', "constructor returned RT::Date oject");

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/13-attribute-tests.t
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/13-attribute-tests.t	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/13-attribute-tests.t	Fri Jun 16 11:20:47 2006
@@ -20,6 +20,8 @@
 
 ok(1, $user->Attributes->BuildSelectQuery);
 my $attr = $user->Attributes;
+# XXX: Order by id as some tests depend on it
+$attr->OrderByCols({ FIELD => 'id' });
 
 ok(1, $attr->BuildSelectQuery);
 

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/14-linking.t
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/14-linking.t	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/14-linking.t	Fri Jun 16 11:20:47 2006
@@ -1,4 +1,5 @@
-use Test::More tests => '59';
+use Test::More  tests => '89';
+
 use strict;
 use warnings;
 
@@ -17,6 +18,9 @@
 my $link_scrips_orig = RT->Config->Get( 'LinkTransactionsRun1Scrip' );
 RT->Config->Set( 'LinkTransactionsRun1Scrip', 1 );
 
+my $link_acl_checks_orig = RT->Config->Get( 'StrictLinkACL' );
+RT->Config->Set( 'StrictLinkACL', 1);
+
 my $condition = RT::ScripCondition->new( $RT::SystemUser );
 $condition->Load('User Defined');
 ok($condition->id);
@@ -80,8 +84,7 @@
 ok($id, "Scrip created");
 
 my $u1 = RT::User->new($RT::SystemUser);
-($id,$msg) =$u1->Create(Name => "LinkTestUser.$$");
-
+($id,$msg) = $u1->Create(Name => "LinkTestUser.$$");
 ok ($id,$msg);
 
 # grant ShowTicket right to allow count transactions
@@ -89,29 +92,122 @@
 ok ($id,$msg);
 ($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q2, Right => 'ShowTicket');
 ok ($id,$msg);
-
 ($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q1, Right => 'CreateTicket');
 ok ($id,$msg);
+
+my $creator = RT::CurrentUser->new($u1->id);
+
+diag('Create tickets without rights to link') if $ENV{'TEST_VERBOSE'};
+{
+    # on q2 we have no rights, yet
+    my $parent = RT::Ticket->new( $RT::SystemUser );
+    my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+    ok($id,$msg);
+    my $child = RT::Ticket->new( $creator );
+    ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id, MemberOf => $parent->id );
+    ok($id,$msg);
+    $child->CurrentUser( $RT::SystemUser );
+    is($child->_Links('Base')->Count, 0, 'link was not created, no permissions');
+    is($child->_Links('Target')->Count, 0, 'link was not create, no permissions');
+}
+
+diag('Create tickets with rights checks on one end of a link') if $ENV{'TEST_VERBOSE'};
+{
+    # on q2 we have no rights, but use checking one only on thing
+    RT->Config->Set( StrictLinkACL => 0 );
+    my $parent = RT::Ticket->new( $RT::SystemUser );
+    my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+    ok($id,$msg);
+    my $child = RT::Ticket->new( $creator );
+    ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id, MemberOf => $parent->id );
+    ok($id,$msg);
+    $child->CurrentUser( $RT::SystemUser );
+    is($child->_Links('Base')->Count, 1, 'link was created');
+    is($child->_Links('Target')->Count, 0, 'link was created only one');
+    # no scrip run on second ticket accroding to config option
+    is(link_count($filename), undef, "scrips ok");
+    RT->Config->Set( StrictLinkACL => 1 );
+}
+
 ($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q1, Right => 'ModifyTicket');
 ok ($id,$msg);
 
-my $tid;
+diag('try to add link without rights') if $ENV{'TEST_VERBOSE'};
+{
+    # on q2 we have no rights, yet
+    my $parent = RT::Ticket->new( $RT::SystemUser );
+    my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+    ok($id,$msg);
+    my $child = RT::Ticket->new( $creator );
+    ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id );
+    ok($id,$msg);
+    ($id, $msg) = $child->AddLink(Type => 'MemberOf', Target => $parent->id);
+    ok(!$id, $msg);
+    is(link_count($filename), undef, "scrips ok");
+    $child->CurrentUser( $RT::SystemUser );
+    is($child->_Links('Base')->Count, 0, 'link was not created, no permissions');
+    is($child->_Links('Target')->Count, 0, 'link was not create, no permissions');
+}
 
-my $creator = RT::CurrentUser->new($u1->id);
+diag('add link with rights only on base') if $ENV{'TEST_VERBOSE'};
+{
+    # on q2 we have no rights, but use checking one only on thing
+    RT->Config->Set( StrictLinkACL => 0 );
+    my $parent = RT::Ticket->new( $RT::SystemUser );
+    my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+    ok($id,$msg);
+    my $child = RT::Ticket->new( $creator );
+    ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id );
+    ok($id,$msg);
+    ($id, $msg) = $child->AddLink(Type => 'MemberOf', Target => $parent->id);
+    ok($id, $msg);
+    is(link_count($filename), 1, "scrips ok");
+    $child->CurrentUser( $RT::SystemUser );
+    is($child->_Links('Base')->Count, 1, 'link was created');
+    is($child->_Links('Target')->Count, 0, 'link was created only one');
+    $child->CurrentUser( $creator );
+
+    # turn off feature and try to delete link, we should fail
+    RT->Config->Set( StrictLinkACL => 1 );
+    ($id, $msg) = $child->AddLink(Type => 'MemberOf', Target => $parent->id);
+    ok(!$id, $msg);
+    is(link_count($filename), 1, "scrips ok");
+    $child->CurrentUser( $RT::SystemUser );
+    $child->_Links('Base')->_DoCount;
+    is($child->_Links('Base')->Count, 1, 'link was not deleted');
+    $child->CurrentUser( $creator );
+
+    # try to delete link, we should success as feature is active
+    RT->Config->Set( StrictLinkACL => 0 );
+    ($id, $msg) = $child->DeleteLink(Type => 'MemberOf', Target => $parent->id);
+    ok($id, $msg);
+    is(link_count($filename), 0, "scrips ok");
+    $child->CurrentUser( $RT::SystemUser );
+    $child->_Links('Base')->_DoCount;
+    is($child->_Links('Base')->Count, 0, 'link was deleted');
+    RT->Config->Set( StrictLinkACL => 1 );
+}
 
+my $tid;
 my $ticket = RT::Ticket->new( $creator);
 ok($ticket->isa('RT::Ticket'));
 ($id,$tid, $msg) = $ticket->Create(Subject => 'Link test 1', Queue => $q1->id);
 ok ($id,$msg);
 
+diag('try link to itself') if $ENV{'TEST_VERBOSE'};
+{
+    my ($id, $msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket->id);
+    ok(!$id, $msg);
+    is(link_count($filename), 0, "scrips ok");
+}
 
 my $ticket2 = RT::Ticket->new($RT::SystemUser);
 ($id, $tid, $msg) = $ticket2->Create(Subject => 'Link test 2', Queue => $q2->id);
 ok ($id, $msg);
-
 ($id,$msg) =$ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id);
 ok(!$id,$msg);
 is(link_count($filename), 0, "scrips ok");
+
 ($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q2, Right => 'CreateTicket');
 ok ($id,$msg);
 ($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q2, Right => 'ModifyTicket');
@@ -121,6 +217,8 @@
 is(link_count($filename), 1, "scrips ok");
 ($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => -1);
 ok(!$id,$msg);
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id);
+ok($id,$msg);
 is(link_count($filename), 1, "scrips ok");
 
 my $transactions = $ticket2->Transactions;
@@ -201,6 +299,7 @@
 
 # restore
 RT->Config->Set( LinkTransactionsRun1Scrip => $link_scrips_orig );
+RT->Config->Set( StrictLinkACL => $link_acl_checks_orig );
 
 {
     my $Scrips = RT::Scrips->new( $RT::SystemUser );
@@ -213,7 +312,9 @@
     my $file = shift;
     open my $fh, "<$file" or die "couldn't open $file";
     my $data = <$fh>;
+    close $fh;
+
+    return undef unless $data;
     chomp $data;
     return $data + 0;
-    close $fh;
 }

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/26command_line.t
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/26command_line.t	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/lib/t/regression/26command_line.t	Fri Jun 16 11:20:47 2006
@@ -3,7 +3,7 @@
 use strict;
 use Test::Expect;
 #use Test::More qw/no_plan/;
-use Test::More tests => 137;
+use Test::More tests => 138;
 
 use RT;
 RT::LoadConfig();
@@ -282,9 +282,7 @@
 # }}}
 
 # {{{ test taking/stealing tickets
-TODO: {
-    local $TODO = "Taking/stealing haven't been implemented yet.";
-
+{
     # create a user; give them privileges to take and steal
     ### TODO: implement 'grant' in the CLI tool; use that here instead.
     ###       this breaks the abstraction barrier, like, a lot.
@@ -297,10 +295,11 @@
     ok($steal_user_id, "Created the user? $msg");
     my $steal_queue = RT::Queue->new($RT::SystemUser);
     my $steal_queue_id;
-    ($steal_queue_id, $msg) = $steal_queue->Load( Name => "Steal$$" );
+    ($steal_queue_id, $msg) = $steal_queue->Create( Name => "Steal$$" );
     ok($steal_queue_id, "Got the queue? $msg");
+    ok($steal_queue->id, "queue obj has id");
     my $status;
-    ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'SeeTicket', Object => $steal_queue );
+    ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => $steal_queue );
     ok($status, "Gave 'SeeTicket' to our user? $msg");
     ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'OwnTicket', Object => $steal_queue );
     ok($status, "Gave 'OwnTicket' to our user? $msg");
@@ -310,7 +309,7 @@
     ok($status, "Gave 'TakeTicket' to our user? $msg");
 
     # create a ticket to take/steal
-    expect_send("create -t ticket set subject='CLIStealTest-$$'", 'Creating ticket to steal...');
+    expect_send("create -t ticket set queue=$steal_queue_id subject='CLIStealTest-$$'", 'Creating ticket to steal...');
     expect_like(qr/Ticket \d+ created/, 'Created ticket');
     expect_handle->before() =~ /Ticket (\d+) created/;
     my $steal_ticket_id = $1;
@@ -318,7 +317,7 @@
 
     # root takes the ticket
     expect_send("take $steal_ticket_id", 'root takes the ticket...');
-    expect_like(qr/Took ticket $steal_ticket_id/, 'root took the ticket');
+    expect_like(qr/Owner changed from Nobody to root/, 'root took the ticket');
 
     # log in as the non-root user
     #expect_quit();      # this is apparently unnecessary, but I'll leave it in
@@ -333,16 +332,16 @@
     # 'steal' it back from them.  'steal' can automatically 'take' a ticket,
     # though.
     expect_send("take $steal_ticket_id", 'user tries to take the ticket...');
-    expect_like(qr/Ticket $steal_ticket_id already owned by user root/, '...and fails.');
+    expect_like(qr/You can only take tickets that are unowned/, '...and fails.');
     expect_send("show ticket/$steal_ticket_id -f owner", 'Double-checking...');
     expect_like(qr/Owner: root/, '...no change.');
 
     # user steals the ticket
     expect_send("steal $steal_ticket_id", 'user tries to *steal* the ticket...');
-    expect_like(qr/Stole ticket $steal_ticket_id/, '...and succeeds!');
+    expect_like(qr/Owner changed from root to fooser$$/, '...and succeeds!');
     expect_send("show ticket/$steal_ticket_id -f owner", 'Double-checking...');
     expect_like(qr/Owner: fooser$$/, '...yup, it worked.');
-    
+
     # log back in as root
     #expect_quit();     # ditto
     $ENV{'RTUSER'} = 'root';
@@ -351,7 +350,7 @@
 
     # root steals the ticket back
     expect_send("steal $steal_ticket_id", 'root steals the ticket back...');
-    expect_like(qr/Stole ticket $steal_ticket_id/, '...and succeeds.');
+    expect_like(qr/Owner changed from fooser$$ to root/, '...and succeeds.');
 }
 # }}}
 

Modified: rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/sbin/rt-setup-database.in
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/sbin/rt-setup-database.in	(original)
+++ rt/branches/3.7-EXPERIMENTAL-RTIR-2.0/sbin/rt-setup-database.in	Fri Jun 16 11:20:47 2006
@@ -182,10 +182,12 @@
         no warnings 'unopened';
 
         open( SCHEMA, "<" . $base_path . "/schema." . $db_type );
-        open( SCHEMA_LOCAL, "<" . $RT::LocalEtcPath . "/schema." . $db_type );
+
+        my $has_local = 0;
+        open( SCHEMA_LOCAL, "<" . $RT::LocalEtcPath . "/schema." . $db_type ) and $has_local = 1;
 
         my $statement = "";
-        foreach my $line (<SCHEMA>, ($_ = ';;'), <SCHEMA_LOCAL>) {
+        foreach my $line (<SCHEMA>, ($_ = ';;'), ($has_local? <SCHEMA_LOCAL>: ()) ) {
             $line =~ s/\#.*//g;
             $line =~ s/--.*//g;
             $statement .= $line;


More information about the Rt-commit mailing list