[Rt-commit] r17237 - in rt/branches/3.6-EXPERIMENTAL-CLI: . html html/Admin/Elements html/Admin/Groups html/Admin/Users html/Elements html/Search html/Search/Elements html/SelfService/Elements html/Ticket html/Ticket/Elements html/User/Groups html/Widgets lib lib/RT lib/RT/Action lib/RT/Interface sbin

ruz at bestpractical.com ruz at bestpractical.com
Mon Dec 15 15:14:51 EST 2008


Author: ruz
Date: Mon Dec 15 15:14:51 2008
New Revision: 17237

Added:
   rt/branches/3.6-EXPERIMENTAL-CLI/html/NoAuth/css/dhandler
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowQueue
Modified:
   rt/branches/3.6-EXPERIMENTAL-CLI/   (props changed)
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditScrips
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditTemplates
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Members.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Modify.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Users/Modify.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditCustomFieldFreeform
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditLinks
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Header
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/MyRT
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/PageLayout
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/ShowLinks
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Tabs
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Chart
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/DisplayOptions
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/EditSearches
   rt/branches/3.6-EXPERIMENTAL-CLI/html/SelfService/Elements/Tabs
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Create.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Display.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowBasics
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowMembers
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/History.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/ModifyLinks.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Update.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/User/Groups/Members.html
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/SavedSearch
   rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/TitleBoxStart
   rt/branches/3.6-EXPERIMENTAL-CLI/html/autohandler
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT.pm.in
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Action/SendEmail.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Attachment_Overlay.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/I18N.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Interface/Web.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Principal_Overlay.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Record.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Template_Overlay.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Transaction_Overlay.pm
   rt/branches/3.6-EXPERIMENTAL-CLI/releng.cnf
   rt/branches/3.6-EXPERIMENTAL-CLI/sbin/rt-test-dependencies.in

Log:
sync from trunk

 r9191 at cubic-pc (orig r9190):  jesse | 2007-10-02 01:09:35 +0400
  r27278 at hualien:  jesse | 2007-10-01 17:08:31 -0400
  3.6.5 releng
 
 r9193 at cubic-pc (orig r9192):  jesse | 2007-10-02 22:09:30 +0400
  r27297 at hualien:  jesse | 2007-10-02 14:08:53 -0400
  * HTML Table fixes from Dirk Pape (http://page.mi.fu-berlin.de/pape/rt3/patches/rt/3.6.4/rt3.6-xhtml-2.patch)
 
 r9215 at cubic-pc (orig r9214):  jesse | 2007-10-03 18:54:53 +0400
  r27337 at hualien:  jesse | 2007-10-03 10:54:11 -0400
  New callbacks from Dirk Pape: http://page.mi.fu-berlin.de/pape/rt3/patches/rt/3.6.4/add_callbacks_to_admin_us
  ers.patch
 
 r9246 at cubic-pc (orig r9245):  sunnavy | 2007-10-08 22:11:19 +0400
 added show_menu arg for Elements/Tabs and Elements/PageLayout, mainly for RTx-TicketBottomTabs
 r9259 at cubic-pc (orig r9258):  sunnavy | 2007-10-10 00:44:47 +0400
 added current_tab arg for AfterShowHistory Callback in Ticket/Display.html
 r9269 at cubic-pc (orig r9268):  jesse | 2007-10-11 05:35:37 +0400
  r68037 at h46055e4a:  jesse | 2007-10-10 19:45:05 -0500
   * A small fix to stop RT from complaining about categories when updating custom fields via the web ui.  Thanks to Brian Gallew
 
 r9271 at cubic-pc (orig r9270):  sunnavy | 2007-10-11 09:22:26 +0400
 added AfterShowHistory Callback in Ticket/History.html
 r9272 at cubic-pc (orig r9271):  jesse | 2007-10-11 19:40:59 +0400
  r68059 at pinglin:  jesse | 2007-10-11 11:40:39 -0400
  * We used the wrong variable name in html/Search/Chart (for fonts)
      Thanks to elacour at easter-eggs.com
  
  
 
 r9363 at cubic-pc (orig r9362):  sunnavy | 2007-10-19 23:23:08 +0400
 Ticket/Create.html can handle clone function now
 r9366 at cubic-pc (orig r9365):  sunnavy | 2007-10-19 23:42:07 +0400
 we shouldn't replace "\n" with whitespace if it's multiple type
 r9381 at cubic-pc (orig r9380):  sunnavy | 2007-10-20 11:06:24 +0400
 don't overwrite %ARGS; don't add cloned ticket to parents by default
 r9419 at cubic-pc (orig r9418):  sartak | 2007-10-23 22:14:23 +0400
  r44066 at onn:  sartak | 2007-10-23 14:14:02 -0400
  Allow Template->ParseContent to not require Ticket and Txn
 
 r9422 at cubic-pc (orig r9421):  ruz | 2007-10-24 00:41:07 +0400
 * add closing tags for elements of lists
 r9423 at cubic-pc (orig r9422):  ruz | 2007-10-24 02:43:38 +0400
 * pass a reference to @results into a callback, so extensions can fill it
 r9424 at cubic-pc (orig r9423):  ruz | 2007-10-24 02:44:53 +0400
 * update docs
 r9425 at cubic-pc (orig r9424):  ruz | 2007-10-24 03:02:34 +0400
 * move general if block into <%INIT>
 r9426 at cubic-pc (orig r9425):  ruz | 2007-10-24 03:03:34 +0400
 * add missing </li>
 r9427 at cubic-pc (orig r9426):  ruz | 2007-10-24 03:05:52 +0400
 * delete unused variable
 r9429 at cubic-pc (orig r9428):  ruz | 2007-10-24 04:12:43 +0400
 * switch to /Elements/ShowLink
 r9430 at cubic-pc (orig r9429):  ruz | 2007-10-24 04:16:06 +0400
 * oops, forgot commit one line, there is no $member anymore
 r9446 at cubic-pc (orig r9445):  tla | 2007-10-25 02:03:16 +0400
 Save the transaction ID of the outgoing message transaction
 r9447 at cubic-pc (orig r9446):  tla | 2007-10-25 06:04:45 +0400
 store the outgoing txn ID in  for later access
 r9448 at cubic-pc (orig r9447):  tla | 2007-10-25 06:20:11 +0400
 don't want RecordOutgoingMailTransaction to be fatal to the scrip.
 r9458 at cubic-pc (orig r9457):  tla | 2007-10-25 13:33:58 +0400
 refrain from shifting args off the argument array
 r9461 at cubic-pc (orig r9460):  tla | 2007-10-25 18:39:42 +0400
 change comment
 r9463 at cubic-pc (orig r9462):  sunnavy | 2007-10-26 00:04:40 +0400
 add a callback for SelfService/Elements/Tabs
 r9472 at cubic-pc (orig r9471):  tla | 2007-10-26 18:36:52 +0400
 get rid of overly verbose debug statement
 r9533 at cubic-pc (orig r9532):  ruz | 2007-11-01 17:07:17 +0300
 * convert mason comments into css comments
 r9559 at cubic-pc (orig r9558):  ruz | 2007-11-06 12:40:57 +0300
 * revert rev. 9532 as we now more interested in mason comments instead of css comments
 r9560 at cubic-pc (orig r9559):  ruz | 2007-11-06 12:59:01 +0300
 * don't send Last-Modified field in a response
 * make cache public
 r9561 at cubic-pc (orig r9560):  ruz | 2007-11-06 13:03:32 +0300
 * squish our CSS into one big thing use CSS::Squish and dhandler
 r9611 at cubic-pc (orig r9610):  ruz | 2007-11-07 00:30:42 +0300
 * add Ticket/Elements/ShowQueue and use it on create and in ShowBasics,
   tiny comp for overriding in extensions
 r9616 at cubic-pc (orig r9615):  ruz | 2007-11-08 20:19:48 +0300
 * align comments
 r9617 at cubic-pc (orig r9616):  audreyt | 2007-11-08 23:06:00 +0300
 * Add new dep: CSS::Squish 0.06
 r9618 at cubic-pc (orig r9617):  ruz | 2007-11-09 01:38:33 +0300
 * add max-age along to Expires
 r9619 at cubic-pc (orig r9618):  ruz | 2007-11-09 01:55:41 +0300
 * RFC dictates to encode by chars, so if char is two octets then
   it MUST be in one chunk
 r9620 at cubic-pc (orig r9619):  ruz | 2007-11-09 02:05:04 +0300
 * The <nobr> opening tag came before the IF statement,
   and the </nobr> closing tag was inside the IF statement.
   Thanks to Jason Long.
 r9621 at cubic-pc (orig r9620):  ruz | 2007-11-09 02:08:32 +0300
 * In this case the <ul> was opened inside an IF block,
   but </ul> closed outside the IF block.
   Thanks to Jason Long.
 r9624 at cubic-pc (orig r9623):  audreyt | 2007-11-09 22:07:05 +0300
 * MakeMIMEEntity now takes an optional "Type" field to denote
   the MIME Type of the body.  (Default to 'text/plain'.)
 
 * CreateTicket() now supports $ARGS{ContentType}, and
   ProcessUpdateMessage() now supports $ARGS{UpdateContentType}.
 r9626 at cubic-pc (orig r9625):  ruz | 2007-11-09 22:57:37 +0300
 * delete double width definition
 * don't escape html
 r9627 at cubic-pc (orig r9626):  audreyt | 2007-11-09 23:06:09 +0300
 * RT::Transaction_Overlay: Signatures in text/html content objects should be
   removed in a way that doesn't depend on whitespace.
   Also, remove an unneccessary regex capture.
 
 r9628 at cubic-pc (orig r9627):  audreyt | 2007-11-09 23:23:38 +0300
 * _DecodeLOB: All text/* are treated as UTF-8, not only text/plain.
 r9629 at cubic-pc (orig r9628):  sartak | 2007-11-09 23:49:01 +0300
  r44879 at onn:  sartak | 2007-11-09 15:48:26 -0500
  If there are no tickets found in a search, give an error-message image instead of silently failing to load.
 
 r9640 at cubic-pc (orig r9639):  audreyt | 2007-11-11 22:06:06 +0300
 * RT::Transaction_Overlay: Unify the idea of "textual" MIME types
   to text/plain, text/html and message/*. (Previously it was defined
   differently for e.g. the first part and the other parts.)
 
 * RT::Transaction_Overlay: Introduce the variable
   $RT::Transaction::PreferredContentType to control the context
   where ->Content() is evaluated in.  If not set, it defaults
   to text/plain.
 
 r9641 at cubic-pc (orig r9640):  audreyt | 2007-11-11 22:07:43 +0300
 * RT::Action::SendEmail: Allow user-specified Content-Type
   in outgoing templates.  Currently, only text/* is supported
   for security reasons.  Eventually maybe multipart/* with
   all textual subparts might be allowed, too.
 r9642 at cubic-pc (orig r9641):  audreyt | 2007-11-11 22:58:21 +0300
 * RT.pm.in: Add support for loading RT_Vendor.pm by default
   before RT_Local, for greater consistency.
 r9643 at cubic-pc (orig r9642):  audreyt | 2007-11-11 23:05:50 +0300
 * RT::Transaction_Overlay: Be saner and allows explicitly
   calling $txn->Content(Type => 'text/html'), instead of
   relying on action-at-a-distance $PreferredContentType.
 r9644 at cubic-pc (orig r9643):  audreyt | 2007-11-12 10:52:35 +0300
 * RT::Action::SendEmail - Minor comment typo: "use" ne "sue"
 r9645 at cubic-pc (orig r9644):  audreyt | 2007-11-12 10:56:43 +0300
 * RT::I18N - Introduce a new utility function, IsTextualContentType($type),
   that determines whether $type can be sensibly converted to Unicode text.
 
   Currently it uses this regex (case-insensitively):
 
       ^(?:text/(?:plain|html)|message/rfc822)\b
 
   The idea is to unify all the inconsistent uses all over RT's code
   (some tested for text/*, some for text/plain|message/rfc822, some
   for text/plain|text/html|message/*) to use this function instead.
 
 * Minor POD glitch - Say "function" when it said "method" but really wasn't.
 
 r9646 at cubic-pc (orig r9645):  audreyt | 2007-11-12 10:58:56 +0300
 * RT::Record - _DecodeLOB now respects RT::I18N::IsTextualContentType.
 r9647 at cubic-pc (orig r9646):  audreyt | 2007-11-12 11:02:35 +0300
 * RT::Attachment_Overlay - Fix several broken logic in ->OriginalContent:
 
     - When $self->ContentEncoding eq 'quoted-printable', a premature
       "return" prevented any encoding conversion from taking place.
 
     - A bogus Encode::_utf8_on($content) later prevented any encoding
       conversino from taking place _anyway_.
 
 * $attachment->Quote now respects RT::I18N::IsTextualContentType.
 
 r9648 at cubic-pc (orig r9647):  audreyt | 2007-11-12 11:03:52 +0300
 * RT::Transaction_Overlay - use RT::I18N::IsTextualContentType.
 r9649 at cubic-pc (orig r9648):  audreyt | 2007-11-12 23:46:09 +0300
 * RT::Transaction->ContentObj - Prefer the first part that
   matches $PreferredContentType, instead of always 'text/plain'.
 r9650 at cubic-pc (orig r9649):  audreyt | 2007-11-12 23:48:07 +0300
 * RT::Action::SendEmail - Support for multipart/* emails; we now
   textualify all MIME parts, instead of collapsing the whole multipart.
 r9654 at cubic-pc (orig r9653):  ruz | 2007-11-13 20:45:26 +0300
 * we don't use some vars anymore so don't fool people
   by defining them in the %ARGS block
 r9655 at cubic-pc (orig r9654):  ruz | 2007-11-13 20:59:32 +0300
 * add labeling of portlets that are based on components,
   it doesn't support localization, but it's better than empty label
 * allow to manage many portlets that are based on the same
   comp by adding optional 'id' key
 r9660 at cubic-pc (orig r9659):  falcone | 2007-11-14 03:09:02 +0300
  r26553 at ketch:  falcone | 2007-11-13 19:07:28 -0500
  * set the prefix so that CFs can be added during Group Creation
 
 r9693 at cubic-pc (orig r9692):  ruz | 2007-11-17 01:37:59 +0300
 * minor
 r9694 at cubic-pc (orig r9693):  ruz | 2007-11-17 01:42:23 +0300
 * unshift more global objects instead of pushing them,
   so we'll get them earlier in an upcoming refactoring
 * do all things related to EquivObjects in HasRight and
   leave only checks in _HasRight
 r9696 at cubic-pc (orig r9695):  ruz | 2007-11-19 00:56:52 +0300
 * add caching based on short keys
 * split _HasRight into _HasGroupRight and _HasRoleRight
 * use more queries for roles
 r9716 at cubic-pc (orig r9715):  ruz | 2007-11-21 04:27:25 +0300
 * revert rev9654 as it breaks charts on home page
 r9728 at cubic-pc (orig r9727):  ruz | 2007-11-22 03:38:24 +0300
 * add handling of arguments with multiple values into Widgets/SavedSearch


Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditScrips
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditScrips	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditScrips	Mon Dec 15 15:14:51 2008
@@ -54,7 +54,7 @@
 % if ($Scrips->Count == 0 ) {
 <p><i><&|/l&>(No scrips)</&></i></p>
 % } else {
-<table>
+<table width="100%">
 <p><i><&|/l&>(Check box to delete)</&></i></p>
 
 %   while (my $scrip = $Scrips->Next ) {

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditTemplates
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditTemplates	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Elements/EditTemplates	Mon Dec 15 15:14:51 2008
@@ -53,7 +53,7 @@
 % if ($Templates->Count == 0 ) {
 <p><i><&|/l&>(No templates)</&></i></p>
 % } else {
-<table>
+<table width="100%">
 <tr>
 <th>
 <i><&|/l&>(Check box to delete)</&></i>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Members.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Members.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Members.html	Mon Dec 15 15:14:51 2008
@@ -94,8 +94,8 @@
 <li><input type="checkbox" class="checkbox" name="DeleteMember-<%$member->MemberId%>" value="1" />
 <%$member->MemberObj->Object->Name%>
 % }
-% }
 </ul>
+% }
 </td>
 <td valign="top">
 <& /Admin/Elements/SelectNewGroupMembers, Name => "AddMembers", Group => $Group,

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Modify.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Modify.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Groups/Modify.html	Mon Dec 15 15:14:51 2008
@@ -77,7 +77,10 @@
 <tr valign="top"><td align="right">
 <% $CF->Name %>:
 </td><td>
-<& /Elements/EditCustomField, CustomField => $CF, Object => $Group &>
+<& /Elements/EditCustomField, CustomField => $CF, 
+                              Object => $Group, 
+                              ($Create ? (NamePrefix => 'Object-RT::Group--CustomField-') 
+                                       : () )&>
 </td></tr>
 % }
 <tr>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Users/Modify.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Users/Modify.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Admin/Users/Modify.html	Mon Dec 15 15:14:51 2008
@@ -134,6 +134,7 @@
 </table>
 % }
 </&>
+<& /Elements/Callback, _CallbackName => 'LeftColumnBottom', UserObj => $UserObj, %ARGS &>
 </td>
 
 <td valign="top" class="boxcontainer">
@@ -201,6 +202,7 @@
 </td><td>
 <input name="PagerPhone" value="<%$UserObj->PagerPhone%>" size="13" /><br />
 </td>
+</tr>
 </table>
 </&>
 <br />
@@ -218,10 +220,10 @@
 % }
 </td></tr>
 % }
-<tr>
-</tr>
 </table>
 </&>
+<& /Elements/Callback, _CallbackName => 'RightColumnBottom', UserObj => $UserObj, %ARGS &>
+</td></tr>
 <tr>
 <td colspan="2">
 <&| /Widgets/TitleBox, title => loc('Comments about this user') &>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditCustomFieldFreeform
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditCustomFieldFreeform	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditCustomFieldFreeform	Mon Dec 15 15:14:51 2008
@@ -57,7 +57,8 @@
   while (my $value = $Values->Next ) {
     $Default .= $value->Content."\n";
   }
-} else {
+} 
+elsif ( ! $Multiple ) {
   $Default =~ s/\s*\n\s*/ /g if $Default;
 }
 </%INIT>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditLinks
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditLinks	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/EditLinks	Mon Dec 15 15:14:51 2008
@@ -68,7 +68,6 @@
     <td class="labeltop"><&|/l&>Depended on by</&>:</td>
     <td class="value">
 % while (my $link = $Object->DependedOnBy->Next) {
-% my $member = $link->BaseObj;
       <input type="checkbox" class="checkbox" name="DeleteLink-<%$link->Base%>-<%$link->Type%>-" value="1" />
         <& ShowLink, URI => $link->BaseURI &><br />
 % }

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Header
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Header	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Header	Mon Dec 15 15:14:51 2008
@@ -58,7 +58,7 @@
 % }
 
 <link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png" />
-<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/<% $RT::WebDefaultStylesheet %>/main.css" type="text/css" media="all" />
+<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/<% $RT::WebDefaultStylesheet %>/main-squished.css" type="text/css" media="all" />
 <link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/print.css" type="text/css" media="print" />
 
 % if ( $RSSAutoDiscovery ) {

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/MyRT
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/MyRT	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/MyRT	Mon Dec 15 15:14:51 2008
@@ -48,7 +48,7 @@
 <table border="0" width="100%">
 <tr valign="top">
 
-<td class="boxcontainer" width="70%" <% $summary? 'width="70%"': '' %>>
+<td class="boxcontainer" <% $summary? 'width="70%"': '' |n %>>
 % $show_cb->($_) foreach @$body;
 </td>
 

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/PageLayout
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/PageLayout	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/PageLayout	Mon Dec 15 15:14:51 2008
@@ -56,9 +56,11 @@
 %# End of div#quickbar from /Elements/Header
 </div>
 
+% if ( $show_menu ) {
 <div id="nav">
 <& /Elements/Menu, toptabs => $toptabs, current_toptab => $current_toptab &>
 </div>
+% }
 
 <div id="header">
   <h1><%$title%></h1>
@@ -231,4 +233,5 @@
 $subactions => undef
 $title => $m->callers(-1)->path
 $AppName => undef
+$show_menu => 1
 </%ARGS>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/ShowLinks
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/ShowLinks	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/ShowLinks	Mon Dec 15 15:14:51 2008
@@ -51,7 +51,7 @@
     <td class="value">
 <ul>
 % while (my $Link = $Ticket->DependsOn->Next) {
-<li><& ShowLink, URI => $Link->TargetURI &>
+<li><& ShowLink, URI => $Link->TargetURI &></li>
 % }
 </ul>
     </td>
@@ -61,7 +61,7 @@
     <td class="value">
 <ul>
 % while (my $Link = $Ticket->DependedOnBy->Next) {
-<li><& ShowLink, URI => $Link->BaseURI &>
+<li><& ShowLink, URI => $Link->BaseURI &></li>
 % }
 </ul>
     </td>
@@ -71,7 +71,7 @@
     <td class="value">
 <ul>
 % while (my $Link = $Ticket->MemberOf->Next) {
-<li><& ShowLink, URI => $Link->TargetURI &>
+<li><& ShowLink, URI => $Link->TargetURI &></li>
 % }
 </ul>
     </td>
@@ -85,7 +85,7 @@
     <td class="value">
 <ul>
 % while (my $Link = $Ticket->RefersTo->Next) {
-<li><& ShowLink, URI => $Link->TargetURI &>
+<li><& ShowLink, URI => $Link->TargetURI &></li>
 % }
 </ul>
     </td>
@@ -96,7 +96,7 @@
     <ul>
 % while (my $Link = $Ticket->ReferredToBy->Next) {
 % next if (UNIVERSAL::isa($Link->BaseObj, 'RT::Ticket')  && $Link->BaseObj->Type eq 'reminder');
-<li><& ShowLink, URI => $Link->BaseURI &>
+<li><& ShowLink, URI => $Link->BaseURI &></li>
 % }
 </ul>
     </td>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Tabs
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Tabs	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Elements/Tabs	Mon Dec 15 15:14:51 2008
@@ -53,7 +53,8 @@
     tabs => $tabs,
     actions => $actions,
     subactions => $subactions,
-    title => $Title
+    title => $Title,
+    show_menu => $show_menu,
 &>
 <a name="skipnav" id="skipnav" accesskey="8"></a>
 <%INIT>
@@ -117,4 +118,5 @@
 $actions => undef
 $subactions => undef
 $Title => undef
+$show_menu => 1
 </%ARGS>

Added: rt/branches/3.6-EXPERIMENTAL-CLI/html/NoAuth/css/dhandler
==============================================================================
--- (empty file)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/NoAuth/css/dhandler	Mon Dec 15 15:14:51 2008
@@ -0,0 +1,30 @@
+<%ONCE>
+my $squisher;
+</%ONCE>
+<%INIT>
+my $arg = $m->dhandler_arg;
+my $path;
+if ( $arg =~ m{^(.*)-squished(\.[^\.]+)$} ) {
+    $path = $m->current_comp->dir_path .'/'. $1 . $2;
+}
+else {
+    return $m->decline;
+}
+
+$squisher = new RT::CSS::Squish unless $squisher;
+$squisher->{'mason'} = $m;
+
+$m->out( $squisher->concatenate( $path ) );
+
+package RT::CSS::Squish;
+use CSS::Squish '0.06';
+use base qw(CSS::Squish);
+sub file_handle {
+    my $self = shift;
+    my $file = shift;
+    my $content = $self->{'mason'}->scomp($file);
+    open my $fh, '<', \$content or die "$!";
+    return $fh;
+}
+
+</%INIT>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Chart
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Chart	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Chart	Mon Dec 15 15:14:51 2008
@@ -75,7 +75,7 @@
 
 my $chart = $chart_class->new( 600 => 400 );
 
-my $font = $RT::FontForCharts || ['verdana', 'arial', gdMediumBoldFont];
+my $font = $RT::ChartFont || ['verdana', 'arial', gdMediumBoldFont];
 $chart->set_title_font( $font, 12 ) if $chart->can('set_title_font');
 $chart->set_legend_font( $font, 12 ) if $chart->can('set_legend_font');
 $chart->set_x_label_font( $font, 10 ) if $chart->can('set_x_label_font');
@@ -86,6 +86,26 @@
 $chart->set_values_font( $font, 9 ) if $chart->can('set_values_font');
 $chart->set_value_font( $font, 9 ) if $chart->can('set_value_font');
 
+# Pie charts don't like having no input, so we show a special image
+# that indicates an error message. Because this is used in an <img>
+# context, it can't be a simple error message. Without this check,
+# the chart will just be a non-loading image.
+if ($tix->Count == 0) {
+    my $plot = GD::Image->new(600 => 400);
+    $plot->colorAllocate(255, 255, 255); # background
+    my $black = $plot->colorAllocate(0, 0, 0);
+
+    require GD::Text::Wrap;
+    my $error = GD::Text::Wrap->new($plot,
+        color => $black,
+        text  => loc("No tickets found."),
+    );
+    $error->set_font( $font, 12 );
+    $error->draw(0, 0);
+
+    $m->comp( 'SELF:Plot', plot => $plot, %ARGS );
+}
+
 if ($chart_class eq "GD::Graph::bars") {
     $chart->set(
         x_label => $tix->Label( $PrimaryGroupBy ),
@@ -143,17 +163,26 @@
 
 
 my $plot = $chart->plot( [ [@sorted_keys], [@sorted_values] ] ) or die $chart->error;
+$m->comp( 'SELF:Plot', plot => $plot, %ARGS );
+</%init>
 
-if ( $plot->can('png') ) {
-    $r->content_type('image/png');
-    $m->out( $plot->png );
-}
-elsif ( $plot->can('gif') ) {
-    $r->content_type('image/gif');
-    $m->out( $plot->gif );
+<%METHOD Plot>
+<%ARGS>
+$plot => undef
+</%ARGS>
+<%INIT>
+my @types = ('png', 'gif');
+
+for my $type (@types) {
+    $plot->can($type)
+        or next;
+
+    $r->content_type("image/$type");
+    $m->out( $plot->$type );
+    $m->abort();
 }
-else { 
-    die "Your GD library appears to support neither PNG nor GIF";
-}
-$m->abort();
-</%init>
+
+die "Your GD library appears to support none of the following image types: " . join(', ', @types);
+</%INIT>
+
+</%METHOD>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/DisplayOptions
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/DisplayOptions	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/DisplayOptions	Mon Dec 15 15:14:51 2008
@@ -46,7 +46,7 @@
 %# 
 %# END BPS TAGGED BLOCK }}}
 <&| /Widgets/TitleBox, title => loc("Display Columns") &>
-<table>
+<table width="100%">
 <tr>
 <td>
 <& EditFormat, %ARGS &>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/EditSearches
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/EditSearches	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Search/Elements/EditSearches	Mon Dec 15 15:14:51 2008
@@ -57,8 +57,8 @@
 % }
 <&|/l&>Description</&>:<br>
 <font size="-1"><input size="25" name="Description" value="<%$CurrentSearch->{'Description'} || ''%>" /></font>
-<nobr>
 % if ($SearchId ne 'new') {
+<nobr>
 % if ($Dirty) {
 <input type="submit" class="button" name="Revert" value="<%loc('Revert')%>" />
 % }

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/SelfService/Elements/Tabs
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/SelfService/Elements/Tabs	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/SelfService/Elements/Tabs	Mon Dec 15 15:14:51 2008
@@ -45,6 +45,7 @@
 %# those contributions and any derivatives thereof.
 %# 
 %# END BPS TAGGED BLOCK }}}
+<& /Elements/Callback, tabs => $tabs, %ARGS &>
 <& /Elements/PageLayout,
     current_toptab => $current_toptab,
     current_tab => $current_tab,
@@ -79,7 +80,7 @@
                       },
              B => { title => loc('Closed tickets'),
                          path => 'SelfService/Closed.html',
-                       }
+                       },
            };
 
 if ($queue_count > 1) {

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Create.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Create.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Create.html	Mon Dec 15 15:14:51 2008
@@ -62,8 +62,8 @@
 <&| /Widgets/TitleBox, title => loc("Create a new ticket") &>
 <table border="0" cellpadding="0" cellspacing="0">
 <tr><td class="label"><&|/l&>Queue</&>:</td>
-<td class="value"><% $QueueObj->Name %>
-<input type="hidden" class="hidden" name="Queue" value="<%$QueueObj->Name%>" />
+<td class="value"><& Elements/ShowQueue, QueueObj => $QueueObj &>
+<input type="hidden" class="hidden" name="Queue" value="<% $QueueObj->Name %>" />
 </td>
 <td class="label"><&|/l&>Status</&>:
 </td>
@@ -240,6 +240,78 @@
 
 <%INIT>
 
+my $CloneTicketObj;
+if ( $CloneTicket ) {
+    $CloneTicketObj = RT::Ticket->new( $session{CurrentUser} );
+    $CloneTicketObj->Load($CloneTicket) or Abort(loc("Ticket could not be loaded"));
+    
+    my $clone = {
+        Requestors       => join( ',', $CloneTicketObj->RequestorAddresses ),
+        Cc               => join( ',', $CloneTicketObj->CcAddresses),
+        AdminCc          => join( ',', $CloneTicketObj->AdminCcAddresses),
+        InitialPriority => $CloneTicketObj->Priority, 
+    };
+    
+    $clone->{$_} = $CloneTicketObj->$_() 
+        for qw/Owner Subject FinalPriority TimeEstimated TimeWorked 
+                Status TimeLeft Starts Started Due Resolved/;
+    
+        my $members = $CloneTicketObj->Members;
+        my ( @members, @members_of, @refers, @refers_by, @depends, @depends_by );
+        while ( my $member = $members->Next ) {
+            push @members, $member->LocalBase;
+        }
+        $clone->{'MemberOf-new'} = join ' ', @members;
+    
+        my $members_of = $CloneTicketObj->MemberOf;
+        while ( my $member_of = $members_of->Next ) {
+            push @members_of, $member_of->LocalTarget;
+        }
+        $clone->{'new-MemberOf'} = join ' ', @members_of;
+        
+        my $refers = $CloneTicketObj->RefersTo;
+        while ( my $refer = $refers->Next ) {
+            push @refers, $refer->LocalTarget;
+        }
+        $clone->{'new-RefersTo'} = join ' ', @refers;
+    
+        my $refers_by = $CloneTicketObj->ReferredToBy;
+        while ( my $refer_by = $refers_by->Next ) {
+            push @refers_by, $refer_by->LocalBase;
+        }
+        $clone->{'RefersTo-new'} = join ' ', @refers_by;
+    
+        my $depends = $CloneTicketObj->DependsOn;
+        while ( my $depend = $depends->Next ) {
+            push @depends, $depend->LocalTarget;
+        }
+        $clone->{'new-DependsOn'} = join ' ', @depends;
+    
+        my $depends_by = $CloneTicketObj->DependedOnBy;
+        while ( my $depend_by = $depends_by->Next ) {
+            push @depends_by, $depend_by->LocalBase;
+        }
+        $clone->{'DependsOn-new'} = join ' ', @depends_by;
+    
+    
+    
+    my $cfs = $CloneTicketObj->QueueObj->TicketCustomFields();
+    while ( my $cf = $cfs->Next ) {
+        my $cf_id = $cf->id;
+        my $cf_values = $CloneTicketObj->CustomFieldValues( $cf->id );
+        my @cf_values;
+        while ( my $cf_value = $cf_values->Next ) {
+            push @cf_values, $cf_value->Content;
+        }
+        $clone->{"Object-RT::Ticket--CustomField-$cf_id-Value"} 
+            = join "\n", @cf_values;
+    }
+    
+    for ( keys %$clone ) {
+        $ARGS{$_} = $clone->{$_} if not defined $ARGS{$_};
+    }
+
+}
 
 my @results;
 my $QueueObj = new RT::Queue($session{'CurrentUser'});
@@ -329,4 +401,5 @@
 $MemberOf => undef
 $QuoteTransaction => undef
 $Queue => undef
+$CloneTicket => undef
 </%ARGS>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Display.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Display.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Display.html	Mon Dec 15 15:14:51 2008
@@ -72,7 +72,8 @@
       
       &> 
 
-<& /Elements/Callback, _CallbackName => 'AfterShowHistory', Ticket => $TicketObj, %ARGS &>
+<& /Elements/Callback, _CallbackName => 'AfterShowHistory', Ticket => $TicketObj, 
+current_tab => 'Ticket/Display.html?id=' . $TicketObj->id, %ARGS &>
 
 <%ARGS>
 $id => undef

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowBasics
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowBasics	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowBasics	Mon Dec 15 15:14:51 2008
@@ -76,7 +76,7 @@
   </tr>
   <tr>
     <td class="label queue"><&|/l&>Queue</&>:</td>
-    <td class="value queue"><%$Ticket->QueueObj->Name%></td>
+    <td class="value queue"><& ShowQueue, QueueObj => $Ticket->QueueObj &></td>
   </tr>
 <& /Elements/Callback, _CallbackName => 'EndOfList', TicketObj => $Ticket, %ARGS &>
 </table>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowMembers
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowMembers	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowMembers	Mon Dec 15 15:14:51 2008
@@ -45,21 +45,20 @@
 %# those contributions and any derivatives thereof.
 %# 
 %# END BPS TAGGED BLOCK }}}
-% if ($members->Count) {
 <ul>
 % while (my $link = $members->Next) {
-% my $member= $link->BaseObj;
-<li><a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$member->Id%>"><%$member->Id%></a>: <%$member->Subject%> [<%loc($member->Status)%>]<br />
+<li><& /Elements/ShowLink, URI => $link->BaseURI &><br />
 % if ($depth < 8) {
-<&/Ticket/Elements/ShowMembers, Ticket => $member, depth => ($depth+1) &> 
+<& /Ticket/Elements/ShowMembers, Ticket => $link->BaseObj, depth => ($depth+1) &> 
 % }
+</li>
 % }
 </ul>
-% }
 
 <%INIT>
 
 my $members = $Ticket->Members;
+return unless $members->Count;
 
 </%INIT>
 

Added: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowQueue
==============================================================================
--- (empty file)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Elements/ShowQueue	Mon Dec 15 15:14:51 2008
@@ -0,0 +1,9 @@
+<% $QueueObj->Name %>
+<%ARGS>
+$QueueObj
+</%ARGS>
+<%INIT>
+my $value = $QueueObj->Name;
+$value = '#'. $QueueObj->id
+    unless defined $value && length $value;
+</%INIT>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/History.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/History.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/History.html	Mon Dec 15 15:14:51 2008
@@ -60,6 +60,8 @@
     AttachmentContent => $attachment_content
     &> 
 
+<& /Elements/Callback, _CallbackName => 'AfterShowHistory', Ticket => $Ticket, 
+current_tab => 'Ticket/History.html?id=' . $Ticket->id, %ARGS &>
 
 <%ARGS>
 $id => undef

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/ModifyLinks.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/ModifyLinks.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/ModifyLinks.html	Mon Dec 15 15:14:51 2008
@@ -67,10 +67,12 @@
 
 
 <%INIT>
-  
+
 my $Ticket = LoadTicket($id);
-$m->comp('/Elements/Callback', TicketObj => $Ticket, ARGSRef => \%ARGS);
-my @results = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
+
+my @results;  
+$m->comp('/Elements/Callback', TicketObj => $Ticket, ARGSRef => \%ARGS, Results => \@results );
+push @results, ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS );
     
 </%INIT>
       

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Update.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Update.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Ticket/Update.html	Mon Dec 15 15:14:51 2008
@@ -56,7 +56,7 @@
 <input type="hidden" class="hidden" name="QuoteTransaction" value="<% $ARGS{QuoteTransaction} %>" />
 <input type="hidden" class="hidden" name="DefaultStatus" value="<% $DefaultStatus %>" />
 <input type="hidden" class="hidden" name="Action" value="<% $ARGS{Action} %>" />
-<table border="0">
+<table width="100%" border="0">
 
 <tr><td align="right"><&|/l&>Status</&>:</td>
 <td>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/User/Groups/Members.html
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/User/Groups/Members.html	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/User/Groups/Members.html	Mon Dec 15 15:14:51 2008
@@ -95,8 +95,8 @@
 <li><input type="checkbox" class="checkbox" name="DeleteMember-<%$member->MemberId%>" value="1" />
 <%$member->MemberObj->Object->Name%>
 % }
-% }
 </ul>
+% }
 </td>
 </tr>
 </table>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/SavedSearch
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/SavedSearch	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/SavedSearch	Mon Dec 15 15:14:51 2008
@@ -136,8 +136,16 @@
 <form method="post" action="<% $Action %>" name="SaveSearch">
 <& /Search/Elements/EditSearches, Name => 'Owner', SearchType => $self->{SearchType}, AllowCopy => 0,
    CurrentSearch => $self->{CurrentSearch}, SearchId => $self->{SearchId}, Title => $Title  &><br />
-% for my $field (@{$self->{SearchFields}}) {
-<input type="hidden" class="hidden" name="<%$field%>" value="<%$ARGS{$field} || ''%>" />
+<%PERL>
+foreach my $field ( @{$self->{SearchFields}} ) {
+    if ( ref($ARGS{$field}) && ref($ARGS{$field}) ne 'ARRAY' ) {
+        $RT::Logger->error("Couldn't store '$field'. it's reference to ". ref($ARGS{$field}) );
+        next;
+    }
+    foreach my $value ( grep defined, ref($ARGS{$field})? @{ $ARGS{$field} } : $ARGS{$field} ) {
+</%PERL>
+<input type="hidden" class="hidden" name="<% $field %>" value="<% $value %>" />
+%   }
 % }
 </form>
 <%ARGS>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/TitleBoxStart
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/TitleBoxStart	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/Widgets/TitleBoxStart	Mon Dec 15 15:14:51 2008
@@ -64,8 +64,6 @@
 $title_class => ''
 $titleright_href => undef
 $titleright => undef
-$contentbg => "#dddddd"
-$color => "#336699"
 $id => ''
 $hideable => 1
 </%ARGS>

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/html/autohandler
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/html/autohandler	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/html/autohandler	Mon Dec 15 15:14:51 2008
@@ -165,12 +165,12 @@
 
             if ($val) {
 
-               # now get user specific information, to better create our user.
+                # 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
+                # 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',

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT.pm.in
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT.pm.in	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT.pm.in	Mon Dec 15 15:14:51 2008
@@ -459,6 +459,8 @@
 
 =cut
 
+eval "require RT_Vendor";
+die $@ if ($@ && $@ !~ qr{^Can't locate RT_Vendor.pm});
 eval "require RT_Local";
 die $@ if ($@ && $@ !~ qr{^Can't locate RT_Local.pm});
 

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Action/SendEmail.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Action/SendEmail.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Action/SendEmail.pm	Mon Dec 15 15:14:51 2008
@@ -100,7 +100,9 @@
 # {{{ sub Commit
 
 sub Commit {
-    my $self = shift;
+    # DO NOT SHIFT @_ in this subroutine.  It breaks Hook::LexWrap's
+    # ability to pass @_ to a 'post' routine.
+    my $self = $_[0];
 
     my ($ret) = $self->SendMessage( $self->TemplateObj->MIMEObj );
     if ( $ret > 0 ) {
@@ -162,16 +164,24 @@
     # We should never have to set the MIME-Version header
     $self->SetHeader( 'MIME-Version', '1.0' );
 
-    # try to convert message body from utf-8 to $RT::EmailOutputEncoding
-    $self->SetHeader( 'Content-Type', 'text/plain; charset="utf-8"' );
-
     # fsck.com #5959: Since RT sends 8bit mail, we should say so.
     $self->SetHeader( 'Content-Transfer-Encoding','8bit');
 
+    # For security reasons, we only send out textual mails.
+    my @parts = $MIMEObj;
+    while (my $part = shift @parts) {
+        if ($part->is_multipart) {
+            push @parts, $part->parts;
+        }
+        else {
+            $part->head->mime_attr( "Content-Type" => 'text/plain' )
+                unless RT::I18N::IsTextualContentType($part->mime_type);
+            $part->head->mime_attr( "Content-Type.charset" => 'utf-8' );
+        }
+    }
 
-    RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding,
-        'mime_words_ok' );
-    $self->SetHeader( 'Content-Type', 'text/plain; charset="' . $RT::EmailOutputEncoding . '"' );
+
+    RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding, 'mime_words_ok' );
 
     # Build up a MIME::Entity that looks like the original message.
     $self->AddAttachments() if ( $MIMEObj->head->get('RT-Attach-Message') );
@@ -241,8 +251,9 @@
 =cut
 
 sub SendMessage {
-    my $self    = shift;
-    my $MIMEObj = shift;
+    # DO NOT SHIFT @_ in this subroutine.  It breaks Hook::LexWrap's
+    # ability to pass @_ to a 'post' routine.
+    my ( $self, $MIMEObj ) = @_;
 
     my $msgid = $MIMEObj->head->get('Message-ID');
     chomp $msgid;
@@ -395,7 +406,7 @@
         # Don't attach anything blank
         next unless ( $attach->ContentLength );
 
-# We want to make sure that we don't include the attachment that's being sued as the "Content" of this message"
+# We want to make sure that we don't include the attachment that's being used as the "Content" of this message.
         next
           if ( $transaction_content_obj
             && $transaction_content_obj->Id == $attach->Id
@@ -473,7 +484,12 @@
         ActivateScrips => 0
     );
 
-
+    if( $id ) {
+	$self->{'OutgoingMailTransaction'} = $id;
+    } else {
+        $RT::Logger->warning( "Could not record outgoing message transaction: $msg" );
+    }
+    return $id;
 }
 
 # }}}
@@ -907,10 +923,6 @@
 
     my $value = $self->TemplateObj->MIMEObj->head->get($field);
 
-    # don't bother if it's us-ascii
-
-    # See RT::I18N, 'NOTES:  Why Encode::_utf8_off before Encode::from_to'
-
     $value =  $self->MIMEEncodeString($value, $enc);
 
     $self->TemplateObj->MIMEObj->head->replace( $field, $value );
@@ -946,25 +958,36 @@
     $max = int($max/3)*3;
 
     chomp $value;
-    return ($value) unless $value =~ /[^\x20-\x7e]/;
 
-    $value =~ s/\s*$//;
-    Encode::_utf8_off($value);
-    my $res = Encode::from_to( $value, "utf-8", $charset );
-   
-    if ($max > 0) {
-      # copy value and split in chuncks
-      my $str=$value;
-      my @chunks = unpack("a$max" x int(length($str)/$max 
-                                  + ((length($str) % $max) ? 1:0)), $str);
-      # encode an join chuncks
-      $value = join " ", 
-                     map encode_mimeword( $_, $encoding, $charset ), @chunks ;
-      return($value); 
-    } else {
+    if ( $max <= 0 ) {
       # gives an error...
       $RT::Logger->crit("Can't encode! Charset or encoding too big.\n");
+      return ($value);
     }
+
+    return ($value) unless $value =~ /[^\x20-\x7e]/;
+
+    $value =~ s/\s*$//;
+
+    # we need perl string to split thing char by char
+    Encode::_utf8_on($value) unless Encode::is_utf8( $value );
+
+    my ($tmp, @chunks) = ('', ());
+    while ( length $value ) {
+        my $char = substr($value, 0, 1, '');
+        my $octets = Encode::encode( $charset, $char );
+        if ( length($tmp) + length($octets) > $max ) {
+            push @chunks, $tmp;
+            $tmp = '';
+        }
+        $tmp .= $octets;
+    }
+    push @chunks, $tmp if length $tmp;
+
+    # encode an join chuncks
+    $value = join "\n ",
+               map encode_mimeword( $_, $encoding, $charset ), @chunks ;
+    return($value); 
 }
 
 # }}}

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Attachment_Overlay.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Attachment_Overlay.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Attachment_Overlay.pm	Mon Dec 15 15:14:51 2008
@@ -276,8 +276,8 @@
 sub OriginalContent {
   my $self = shift;
 
-  return $self->Content unless (
-     $self->ContentType =~ qr{^(text/plain|message/rfc822)$}i) ;
+  return $self->Content unless RT::I18N::IsTextualContentType($self->ContentType);
+
   my $enc = $self->OriginalEncoding;
 
   my $content;
@@ -286,12 +286,15 @@
   } elsif ( $self->ContentEncoding eq 'base64' ) {
       $content = MIME::Base64::decode_base64($self->_Value('Content', decode_utf8 => 0));
   } elsif ( $self->ContentEncoding eq 'quoted-printable' ) {
-      return MIME::QuotedPrint::decode($self->_Value('Content', decode_utf8 => 0));
+      $content = MIME::QuotedPrint::decode($self->_Value('Content', decode_utf8 => 0));
   } else {
       return( $self->loc("Unknown ContentEncoding [_1]", $self->ContentEncoding));
   }
 
-   Encode::_utf8_on($content);
+  # Turn *off* the SvUTF8 bits here so decode_utf8 and from_to below can work.
+  local $@;
+  Encode::_utf8_off($content);
+
   if (!$enc || $enc eq '' ||  $enc eq 'utf8' || $enc eq 'utf-8') {
     # If we somehow fail to do the decode, at least push out the raw bits
     eval {return( Encode::decode_utf8($content))} || return ($content);
@@ -356,7 +359,7 @@
 
     # TODO: Handle Multipart/Mixed (eventually fix the link in the
     # ShowHistory web template?)
-    if ($self->ContentType =~ m{^(text/plain|message)}i) {
+    if (RT::I18N::IsTextualContentType($self->ContentType)) {
 	$body=$self->Content;
 
 	# Do we need any preformatting (wrapping, that is) of the message?

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/I18N.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/I18N.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/I18N.pm	Mon Dec 15 15:14:51 2008
@@ -153,7 +153,7 @@
 
 =head2 SetMIMEEntityToUTF8 $entity
 
-An utility method which will try to convert entity body into utf8.
+An utility function which will try to convert entity body into utf8.
 It's now a wrap-up of SetMIMEEntityToEncoding($entity, 'utf-8').
 
 =cut
@@ -164,16 +164,37 @@
 
 # }}}
 
+# {{{ IsTextualContentType
+
+=head2 IsTextualContentType $type
+
+An utility function that determines whether $type is I<textual>, meaning
+that it can sensibly be converted to Unicode text.
+
+Currently, it returns true iff $type matches this regular expression
+(case-insensitively):
+
+    ^(?:text/(?:plain|html)|message/rfc822)\b
+
+# }}}
+
+=cut
+
+sub IsTextualContentType {
+    my $type = shift;
+    ($type =~ m{^(?:text/(?:plain|html)|message/rfc822)\b}i) ? 1 : 0;
+}
+
 # {{{ SetMIMEEntityToEncoding
 
 =head2 SetMIMEEntityToEncoding $entity, $encoding
 
-An utility method which will try to convert entity body into specified
+An utility function which will try to convert entity body into specified
 charset encoding (encoded as octets, *not* unicode-strings).  It will
 iterate all the entities in $entity, and try to convert each one into
 specified charset if whose Content-Type is 'text/plain'.
 
-This method doesn't return anything meaningful.
+This function doesn't return anything meaningful.
 
 =cut
 
@@ -205,11 +226,9 @@
 
     # If this is a textual entity, we'd need to preserve its original encoding
     $head->add( "X-RT-Original-Encoding" => $charset )
-	if $head->mime_attr('content-type.charset') or $head->mime_type =~ /^text/;
-
+	if $head->mime_attr('content-type.charset') or IsTextualContentType($head->mime_type);
 
-    return unless ( $head->mime_type =~ qr{^(text/plain|message/rfc822)$}i  );
-    
+    return unless IsTextualContentType($head->mime_type);
 
     my $body = $entity->bodyhandle;
 

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Interface/Web.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Interface/Web.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Interface/Web.pm	Mon Dec 15 15:14:51 2008
@@ -214,11 +214,16 @@
 =cut
 
 sub StaticFileHeaders {
+    # make cache public
+    $HTML::Mason::Commands::r->headers_out->{'Cache-Control'} = 'max-age=259200, public';
+
     # Expire things in a month.
     $HTML::Mason::Commands::r->headers_out->{'Expires'} = HTTP::Date::time2str( time() + 2592000 );
 
+    # if we set 'Last-Modified' then browser request a comp using 'If-Modified-Since'
+    # request, but we don't handle it and generate full reply again
     # Last modified at server start time
-    $HTML::Mason::Commands::r->headers_out->{'Last-Modified'} = HTTP::Date::time2str($^T);
+    #$HTML::Mason::Commands::r->headers_out->{'Last-Modified'} = HTTP::Date::time2str($^T);
 
 }
 
@@ -336,6 +341,7 @@
         From                => $ARGS{'From'},
         Cc                  => $ARGS{'Cc'},
         Body                => $ARGS{'Content'},
+        Type                => $ARGS{'ContentType'},
     );
 
     if ( $ARGS{'Attachments'} ) {
@@ -533,6 +539,7 @@
         my $Message = MakeMIMEEntity(
             Subject => $args{ARGSRef}->{'UpdateSubject'},
             Body    => $args{ARGSRef}->{'UpdateContent'},
+            Type    => $args{ARGSRef}->{'UpdateContentType'},
         );
 
         $Message->head->add( 'Message-ID' => 
@@ -610,6 +617,8 @@
 
 Takes a paramhash Subject, Body and AttachmentFieldName.
 
+Also takes Form, Cc and Type as optional paramhash keys.
+
   Returns a MIME::Entity.
 
 =cut
@@ -623,6 +632,7 @@
         Cc                  => undef,
         Body                => undef,
         AttachmentFieldName => undef,
+        Type                => undef,
 #        map Encode::encode_utf8($_), @_,
         @_,
     );
@@ -640,6 +650,7 @@
             Subject => $args{'Subject'} || "",
             From    => $args{'From'},
             Cc      => $args{'Cc'},
+            Type    => $args{'Type'} || 'text/plain',
             'Charset:' => 'utf8',
             Data    => [ $args{'Body'} ]
         );
@@ -1254,6 +1265,8 @@
 
     my @results;
     foreach my $arg ( keys %{ $args{'ARGS'} } ) {
+        
+        next if $arg =~ /Category$/;
 
         # since http won't pass in a form element with a null value, we need
         # to fake it

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Principal_Overlay.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Principal_Overlay.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Principal_Overlay.pm	Mon Dec 15 15:14:51 2008
@@ -303,7 +303,8 @@
         return (undef);
     }
 
-    $args{EquivObjects} = [ @{ $args{EquivObjects} } ] if $args{EquivObjects};
+    $args{'EquivObjects'} = [ @{ $args{'EquivObjects'} } ]
+        if $args{'EquivObjects'};
 
     if ( $self->Disabled ) {
         $RT::Logger->error( "Disabled User #"
@@ -317,7 +318,7 @@
         && UNIVERSAL::can( $args{'Object'}, 'id' )
         && $args{'Object'}->id ) {
 
-        push( @{ $args{'EquivObjects'} }, $args{Object} );
+        push @{ $args{'EquivObjects'} }, $args{'Object'};
     }
     else {
         $RT::Logger->crit("HasRight called with no valid object");
@@ -330,47 +331,44 @@
         # this is a little bit hacky, but basically, now that we've done
         # the ticket roles magic, we load the queue object
         # and ask all the rest of our questions about the queue.
-        push( @{ $args{'EquivObjects'} }, $args{'Object'}->QueueObj );
+        unshift @{ $args{'EquivObjects'} }, $args{'Object'}->QueueObj;
 
     }
 
+    unshift @{ $args{'EquivObjects'} }, $RT::System
+        unless $self->can('_IsOverrideGlobalACL')
+               && $self->_IsOverrideGlobalACL( $args{'Object'} );
+
+
     # {{{ If we've cached a win or loss for this lookup say so
 
-    # {{{ Construct a hashkey to cache decisions in
-    my $hashkey = do {
-        no warnings 'uninitialized';
-
-        # We don't worry about the hash ordering, as this is only
-        # temporarily used; also if the key changes it would be
-        # invalidated anyway.
-        join(
-            ";:;",
-            $self->Id,
-            map {
-                $_,    # the key of each arguments
-                  ( $_ eq 'EquivObjects' )    # for object arrayref...
-                  ? map( _ReferenceId($_), @{ $args{$_} } )    # calculate each
-                  : _ReferenceId( $args{$_} )    # otherwise just the value
-              } keys %args
-        );
-    };
-
-    # }}}
-
-    # Returns undef on cache miss
-    my $cached_answer = $_ACL_CACHE->fetch($hashkey);
-    if ( defined $cached_answer ) {
-        if ( $cached_answer == 1 ) {
-            return (1);
-        }
-        elsif ( $cached_answer == -1 ) {
-            return (undef);
-        }
+    # Construct a hashkeys to cache decisions:
+    # 1) full_hashkey - key for any result and for full combination of uid, right and objects
+    # 2) short_hashkey - one key for each object to store positive results only, it applies
+    # only to direct group rights and partly to role rights
+    my $self_id = $self->id;
+    my $full_hashkey = join ";:;", $self_id, $args{'Right'};
+    foreach ( @{ $args{'EquivObjects'} } ) {
+        my $ref_id = _ReferenceId($_);
+        $full_hashkey .= ";:;$ref_id";
+
+        my $short_hashkey = join ";:;", $self_id, $args{'Right'}, $ref_id;
+        my $cached_answer = $_ACL_CACHE->fetch($short_hashkey);
+        return $cached_answer > 0 if defined $cached_answer;
+    }
+
+    {
+        my $cached_answer = $_ACL_CACHE->fetch($full_hashkey);
+        return $cached_answer > 0 if defined $cached_answer;
     }
 
-    my $hitcount = $self->_HasRight( %args );
 
-    $_ACL_CACHE->set( $hashkey => $hitcount? 1:-1 );
+    my ($hitcount, $via_obj) = $self->_HasRight( %args );
+
+    $_ACL_CACHE->set( $full_hashkey => $hitcount? 1: -1 );
+    $_ACL_CACHE->set( "$self_id;:;$args{'Right'};:;$via_obj" => 1 )
+        if $via_obj && $hitcount;
+
     return ($hitcount);
 }
 
@@ -383,54 +381,93 @@
 sub _HasRight
 {
     my $self = shift;
+    {
+        my ($hit, @other) = $self->_HasGroupRight( @_ );
+        return ($hit, @other) if $hit;
+    }
+    {
+        my ($hit, @other) = $self->_HasRoleRight( @_ );
+        return ($hit, @other) if $hit;
+    }
+    return (0);
+}
+
+# this method handles role rights partly in situations
+# where user plays role X on an object and as well the right is
+# assigned to this role X of the object, for example right CommentOnTicket
+# is granted to Cc role of a queue and user is in cc list of the queue
+sub _HasGroupRight
+{
+    my $self = shift;
     my %args = (
         Right        => undef,
-        Object       => undef,
         EquivObjects => [],
         @_
     );
-
     my $right = $args{'Right'};
-    my @objects = @{ $args{'EquivObjects'} };
 
-    # If an object is defined, we want to look at rights for that object
+    my $query =
+      "SELECT ACL.id, ACL.ObjectType, ACL.ObjectId " .
+      "FROM ACL, Principals, CachedGroupMembers WHERE " .
 
-    push( @objects, 'RT::System' )
-      unless $self->can('_IsOverrideGlobalACL')
-             && $self->_IsOverrideGlobalACL( $args{Object} );
-
-    my ($check_roles, $check_objects) = ('','');
-    if( @objects ) {
-        my @role_clauses;
-        my @object_clauses;
-        foreach my $obj ( @objects ) {
-            my $type = ref($obj)? ref($obj): $obj;
-            my $id;
-            $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
-
-            my $role_clause = "Groups.Domain = '$type-Role'";
-            # XXX: Groups.Instance is VARCHAR in DB, we should quote value
-            # if we want mysql 4.0 use indexes here. we MUST convert that
-            # field to integer and drop this quotes.
-            $role_clause   .= " AND Groups.Instance = '$id'" if $id;
-            push @role_clauses, "($role_clause)";
-
-            my $object_clause = "ACL.ObjectType = '$type'";
-            $object_clause   .= " AND ACL.ObjectId = $id" if $id;
-            push @object_clauses, "($object_clause)";
+      # Only find superuser or rights with the name $right
+      "(ACL.RightName = 'SuperUser' OR ACL.RightName = '$right') "
+
+      # Never find disabled groups.
+      . "AND Principals.id = ACL.PrincipalId "
+      . "AND Principals.PrincipalType = 'Group' "
+      . "AND Principals.Disabled = 0 "
+
+      # See if the principal is a member of the group recursively or _is the rightholder_
+      # never find recursively disabled group members
+      # also, check to see if the right is being granted _directly_ to this principal,
+      #  as is the case when we want to look up group rights
+      . "AND CachedGroupMembers.GroupId  = ACL.PrincipalId "
+      . "AND CachedGroupMembers.GroupId  = Principals.id "
+      . "AND CachedGroupMembers.MemberId = ". $self->Id ." "
+      . "AND CachedGroupMembers.Disabled = 0 ";
+
+    my @clauses;
+    foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+        my $type = ref( $obj ) || $obj;
+        my $clause = "ACL.ObjectType = '$type'";
+
+        if ( ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id ) {
+            $clause .= " AND ACL.ObjectId = ". $obj->id;
         }
 
-        $check_roles .= join ' OR ', @role_clauses;
-        $check_objects = join ' OR ', @object_clauses;
+        push @clauses, "($clause)";
+    }
+    if ( @clauses ) {
+        $query .= " AND (". join( ' OR ', @clauses ) .")";
     }
 
-    my $query_base =
-      "SELECT ACL.id from ACL, Groups, Principals, CachedGroupMembers WHERE  " .
+    $self->_Handle->ApplyLimits( \$query, 1 );
+    my ($hit, $obj, $id) = $self->_Handle->FetchResult( $query );
+    return (0) unless $hit;
+
+    $obj .= "-$id" if $id;
+    return (1, $obj);
+}
+
+sub _HasRoleRight
+{
+    my $self = shift;
+    my %args = (
+        Right        => undef,
+        EquivObjects => [],
+        @_
+    );
+    my $right = $args{'Right'};
+
+    my $query =
+      "SELECT ACL.id" .
+      "FROM ACL, Groups, Principals, CachedGroupMembers WHERE " .
 
       # Only find superuser or rights with the name $right
-      "(ACL.RightName = 'SuperUser' OR  ACL.RightName = '$right') "
+      "(ACL.RightName = 'SuperUser' OR ACL.RightName = '$right') "
 
-      # Never find disabled groups.
+      # Never find disabled things
       . "AND Principals.Disabled = 0 "
       . "AND CachedGroupMembers.Disabled = 0 "
 
@@ -444,30 +481,39 @@
       #  as is the case when we want to look up group rights
       . "AND Principals.id = CachedGroupMembers.GroupId "
       . "AND CachedGroupMembers.MemberId = ". $self->Id ." "
+      . "AND ACL.PrincipalType = Groups.Type ";
 
-      # Make sure the rights apply to the entire system or to the object in question
-      . "AND ($check_objects) ";
-
-    # The groups query does the query based on group membership and individual user rights
-    my $groups_query = $query_base
-      # limit the result set to groups of types ACLEquivalence (user),
-      # UserDefined, SystemInternal and Personal. All this we do
-      # via (ACL.PrincipalType = 'Group') condition
-      . "AND ACL.PrincipalId = Principals.id "
-      . "AND ACL.PrincipalType = 'Group' ";
-
-    $self->_Handle->ApplyLimits( \$groups_query, 1 ); #only return one result
-    my $hitcount = $self->_Handle->FetchResult($groups_query);
-    return 1 if $hitcount; # get out of here if success
-
-    # The roles query does the query based on roles
-    my $roles_query = $query_base
-      . "AND ACL.PrincipalType = Groups.Type "
-      . "AND ($check_roles) ";
-    $self->_Handle->ApplyLimits( \$roles_query, 1 ); #only return one result
+    my (@object_clauses);
+    foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+        my $type = ref($obj)? ref($obj): $obj;
+        my $id;
+        $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
+
+        my $object_clause = "ACL.ObjectType = '$type'";
+        $object_clause   .= " AND ACL.ObjectId = $id" if $id;
+        push @object_clauses, "($object_clause)";
+    }
+    # find ACLs that are related to our objects only
+    $query .= " AND (". join( ' OR ', @object_clauses ) .")";
 
-    $hitcount = $self->_Handle->FetchResult($roles_query);
-    return 1 if $hitcount; # get out of here if success
+    # because of mysql bug in versions up to 5.0.45 we do one query per object
+    # each query should be faster on any DB as it uses indexes more effective
+    foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+        my $type = ref($obj)? ref($obj): $obj;
+        my $id;
+        $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
+
+        my $tmp = $query;
+        $tmp .= " AND Groups.Domain = '$type-Role'";
+        # XXX: Groups.Instance is VARCHAR in DB, we should quote value
+        # if we want mysql 4.0 use indexes here. we MUST convert that
+        # field to integer and drop this quotes.
+        $tmp .= " AND Groups.Instance = '$id'" if $id;
+
+        $self->_Handle->ApplyLimits( \$tmp, 1 );
+        my ($hit) = $self->_Handle->FetchResult( $tmp );
+        return (1) if $hit;
+    }
 
     return 0;
 }

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Record.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Record.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Record.pm	Mon Dec 15 15:14:51 2008
@@ -862,7 +862,7 @@
     elsif ( $ContentEncoding && $ContentEncoding ne 'none' ) {
         return ( $self->loc( "Unknown ContentEncoding [_1]", $ContentEncoding ) );
     }
-    if ( $ContentType eq 'text/plain' ) {
+    if ( RT::I18N::IsTextualContentType($ContentType) ) {
        $Content = Encode::decode_utf8($Content) unless Encode::is_utf8($Content);
     }
         return ($Content);
@@ -1033,7 +1033,7 @@
 
 =head2 ReferredToBy
 
-  This returns an RT::Links object which shows all references for which this ticket is a target
+This returns an L<RT::Links> object which shows all references for which this ticket is a target
 
 =cut
 
@@ -1236,9 +1236,14 @@
 
 # {{{ sub _Links 
 
-=head2 Links DIRECTION TYPE 
+=head2 Links DIRECTION [TYPE]
 
-return links to/from this object. 
+Return links (L<RT::Links>) to/from this object.
+
+DIRECTION is either 'Base' or 'Target'.
+
+TYPE is a type of links to return, it can be omitted to get
+links of any type.
 
 =cut
 

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Template_Overlay.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Template_Overlay.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Template_Overlay.pm	Mon Dec 15 15:14:51 2008
@@ -299,7 +299,8 @@
  This routine performs Text::Template parsing on the template and then
  imports the results into a MIME::Entity so we can really use it
 
- Takes a hash containing Argument, TicketObj, and TransactionObj.
+ Takes a hash containing Argument, TicketObj, and TransactionObj. TicketObj
+ and TransactionObj are not mandatory, but highly recommended.
 
  It returns a tuple of (val, message)
  If val is 0, the message contains an error message
@@ -365,9 +366,13 @@
     local $T::Ticket      = $args{'TicketObj'};
     local $T::Transaction = $args{'TransactionObj'};
     local $T::Argument    = $args{'Argument'};
-    local $T::Requestor   = eval { $T::Ticket->Requestors->UserMembersObj->First->Name };
+    local $T::Requestor   = eval { $T::Ticket->Requestors->UserMembersObj->First->Name } if $T::Ticket;
     local $T::rtname      = $RT::rtname;
-    local *T::loc         = sub { $T::Ticket->loc(@_) };
+
+    local *T::loc         = sub {
+        $T::Ticket ? $T::Ticket->loc(@_)
+                   : $self->CurrentUser->loc(@_)
+    };
 
     my $content = $self->Content;
     unless ( defined $content ) {

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Transaction_Overlay.pm
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Transaction_Overlay.pm	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/lib/RT/Transaction_Overlay.pm	Mon Dec 15 15:14:51 2008
@@ -78,7 +78,7 @@
 use strict;
 no warnings qw(redefine);
 
-use vars qw( %_BriefDescriptions );
+use vars qw( %_BriefDescriptions $PreferredContentType );
 
 use RT::Attachments;
 use RT::Scrips;
@@ -271,18 +271,23 @@
 
 =head2 Content PARAMHASH
 
-If this transaction has attached mime objects, returns the first text/plain part.
-Otherwise, returns undef.
+If this transaction has attached mime objects, returns the body of the first
+textual part (as defined in RT::I18N::IsTextualContentType).  Otherwise,
+returns undef.
 
 Takes a paramhash.  If the $args{'Quote'} parameter is set, wraps this message 
 at $args{'Wrap'}.  $args{'Wrap'} defaults to 70.
 
+If $args{'Type'} is set to C<text/html>, plain texts are upgraded to HTML.
+Otherwise, HTML texts are downgraded to plain text.  If $args{'Type'} is
+missing, it defaults to the value of C<$RT::Transaction::PreferredContentType>.
 
 =cut
 
 sub Content {
     my $self = shift;
     my %args = (
+        Type  => $PreferredContentType,
         Quote => 0,
         Wrap  => 70,
         @_
@@ -293,9 +298,28 @@
         $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));
+            $content =~ s/<p>--\s+<br \/>.*?$//s if $args{'Quote'};
 
+            if ($args{Type} ne 'text/html') {
+                $content = HTML::FormatText->new(
+                    leftmargin  => 0,
+                    rightmargin => 78,
+                )->format(
+                    HTML::TreeBuilder->new_from_content( $content )
+                );
+            }
 	}
+        else {
+            $content =~ s/\n-- \n.*?$//s if $args{'Quote'};
+
+            if ($args{Type} eq 'text/html') {
+                # Extremely simple text->html converter
+                $content =~ s/&/&#38;/g;
+                $content =~ s/</&lt;/g;
+                $content =~ s/>/&gt;/g;
+                $content = "<pre>$content</pre>";
+            }
+        }
     }
 
     # If all else fails, return a message that we couldn't find any content
@@ -305,9 +329,6 @@
 
     if ( $args{'Quote'} ) {
 
-        # Remove quoted signature.
-        $content =~ s/\n-- \n(.*?)$//s;
-
         # What's the longest line like?
         my $max = 0;
         foreach ( split ( /\n/, $content ) ) {
@@ -355,18 +376,17 @@
     # Get the set of toplevel attachments to this transaction.
     my $Attachment = $self->Attachments->First();
 
-    # If it's a message or a plain part, just return the
-    # body.
-    if ( $Attachment->ContentType() =~ '^(?:text/plain$|text/html|message/)' ) {
+    # If it's a textual part, just return the body.
+    if ( RT::I18N::IsTextualContentType($Attachment->ContentType) ) {
         return ($Attachment);
     }
 
-    # If it's a multipart object, first try returning the first
-    # text/plain part.
+    # If it's a multipart object, first try returning the first part with preferred
+    # MIME type ('text/plain' by default).
 
     elsif ( $Attachment->ContentType() =~ '^multipart/' ) {
         my $plain_parts = $Attachment->Children();
-        $plain_parts->ContentType( VALUE => 'text/plain' );
+        $plain_parts->ContentType( VALUE => ($PreferredContentType || 'text/plain') );
 
         # If we actully found a part, return its content
         if ( $plain_parts->First && $plain_parts->First->Content ne '' ) {
@@ -374,13 +394,12 @@
         }
 
 
-        # If that fails, return the  first text/plain or message/ part
-        # which has some content.
+        # If that fails, return the first textual part which has some content.
 
         else {
             my $all_parts = $self->Attachments();
             while ( my $part = $all_parts->Next ) {
-                if (( $part->ContentType() =~ '^(text/plain$|message/)' ) &&  $part->Content()  ) {
+                if ( ( RT::I18N::IsTextualContentType($part->ContentType) ) and ( $part->Content() ne '' ) ) {
                     return ($part);
                 }
             }

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/releng.cnf
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/releng.cnf	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/releng.cnf	Mon Dec 15 15:14:51 2008
@@ -1,5 +1,5 @@
 PRODUCT			        = rt
-TAG			            = 3.6.5RC2
+TAG			            = 3.6.5
 CANONICAL_REPO		    = svn+ssh://svn.bestpractical.com/svn/bps-public/rt/
 TAGS		            = tags/
 TRUNK	                = branches/3.6-RELEASE

Modified: rt/branches/3.6-EXPERIMENTAL-CLI/sbin/rt-test-dependencies.in
==============================================================================
--- rt/branches/3.6-EXPERIMENTAL-CLI/sbin/rt-test-dependencies.in	(original)
+++ rt/branches/3.6-EXPERIMENTAL-CLI/sbin/rt-test-dependencies.in	Mon Dec 15 15:14:51 2008
@@ -200,6 +200,7 @@
 Cache::Simple::TimedExpiry
 UNIVERSAL::require
 Calendar::Simple
+CSS::Squish 0.06
 .
 
 $deps{'MASON'} = [ text_to_hash( << '.') ];
@@ -214,6 +215,7 @@
 GD::Graph
 GD::Text
 Text::WikiFormat 0.76
+CSS::Squish 0.06
 .
 
 $deps{'STANDALONE'} = [ text_to_hash( << '.') ];


More information about the Rt-commit mailing list