[Rt-commit] r5399 - in rt/branches/3.7-EXPERIMENTAL: . html/Elements html/REST/1.0/Forms/ticket html/REST/1.0/NoAuth html/REST/1.0/search html/SelfService html/Ticket html/Ticket/Elements lib/RT lib/RT/Interface lib/RT/Interface/Web lib/t/regression

ruz at bestpractical.com ruz at bestpractical.com
Fri Jun 16 20:27:31 EDT 2006


Author: ruz
Date: Fri Jun 16 18:02:52 2006
New Revision: 5399

Added:
   rt/branches/3.7-EXPERIMENTAL/lib/t/regression/23-web_attachments.t
Modified:
   rt/branches/3.7-EXPERIMENTAL/   (props changed)
   rt/branches/3.7-EXPERIMENTAL/config.layout
   rt/branches/3.7-EXPERIMENTAL/html/Admin/Groups/index.html
   rt/branches/3.7-EXPERIMENTAL/html/Elements/SelectNewTicketQueue
   rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/Forms/ticket/default
   rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/NoAuth/mail-gateway
   rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/search/ticket
   rt/branches/3.7-EXPERIMENTAL/html/SelfService/Create.html
   rt/branches/3.7-EXPERIMENTAL/html/Ticket/Create.html
   rt/branches/3.7-EXPERIMENTAL/html/Ticket/Display.html
   rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/PreviewScrips
   rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/ShowRequestor
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Attachment_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/CustomField_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Date.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Email.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web/Handler.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Record.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Ticket_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Tickets_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm
   rt/branches/3.7-EXPERIMENTAL/lib/RT/URI.pm
   rt/branches/3.7-EXPERIMENTAL/lib/t/regression/22search_tix_by_txn.t

Log:
merge 3.4 -> 3.7

 r2079 at cubic-pc (orig r4686):  jesse | 2006-03-05 01:47:46 +0300
  r22962 at truegrounds:  jesse | 2006-01-25 05:18:09 -0800
  * Updated mandatory fields for ticket creation forms
 
 r2190 at cubic-pc (orig r4799):  jesse | 2006-03-23 09:37:59 +0300
  r30313 at truegrounds:  jesse | 2006-03-23 01:36:27 -0500
  * Better mp2 bulletproofing
 
 r2191 at cubic-pc (orig r4814):  jesse | 2006-03-24 06:40:37 +0300
  r10436 at hualien:  jesse | 2006-03-23 22:40:25 -0500
  * It helps when there aren't typos
 
 r2262 at cubic-pc (orig r4847):  alexmv | 2006-03-29 00:50:07 +0400
  r11918 at zoq-fot-pik:  chmrr | 2006-03-28 15:49:56 -0500
   * Backport TXN fixes from 3.7 and 3.5
 
 r2321 at cubic-pc (orig r4924):  jesse | 2006-03-31 06:07:23 +0400
  r10636 at hualien:  jesse | 2006-03-31 11:06:57 +0900
  RT-Ticket: 7398
  RT-Status: resolved
  RT-Update: correspond
  
  * Added a "RH" RedHat layout option to config.layout  -- Paulo Matos
 
 r2396 at cubic-pc (orig r5047):  ruz | 2006-04-18 04:40:06 +0400
 * check and report error to the logs
 r2421 at cubic-pc (orig r5060):  jesse | 2006-04-24 18:49:40 +0400
  r11842 at hualien:  jesse | 2006-04-24 10:49:13 -0400
  The following patch adds the useful LastUpdated field to the fields
  returned through the REST interface.
  David - who starts to wonder if his patches are actually read by someone :-)
  --
  David Schweikert        | phone: +41 44 632 7019
  System manager ISG.EE   | walk:  ETH Zentrum, ETL F24.1
  ETH Zurich, Switzerland | web:   http://people.ee.ethz.ch/dws
  
 
 r2422 at cubic-pc (orig r5064):  ruz | 2006-04-25 00:42:43 +0400
 * max subject is 200 character long
 r2423 at cubic-pc (orig r5065):  ruz | 2006-04-25 01:25:15 +0400
 * convert only if $enc'oding contains something
 r2424 at cubic-pc (orig r5066):  ruz | 2006-04-25 04:21:32 +0400
 * simple tests for Attachments manipulation from web interface
 r2548 at cubic-pc (orig r5115):  ruz | 2006-04-26 03:24:45 +0400
 * (cond) && 'selected' outputs 0 if condition fails on my system 
 r2549 at cubic-pc (orig r5116):  ruz | 2006-04-26 03:35:09 +0400
 * get queue ID from page
 r2658 at cubic-pc (orig r5118):  jesse | 2006-04-26 06:43:31 +0400
  r11882 at hualien:  jesse | 2006-04-25 22:43:11 -0400
  * Mark Eichin picked up that http://lists.fsck.com/pipermail/rt-devel/2004-August/006216.html had never been applied. 
  
  rt ls -l broke because of it, if your RT server wasn't at / 
 
 r2862 at cubic-pc (orig r5183):  jesse | 2006-05-09 06:31:56 +0400
  r13313 at hualien:  jesse | 2006-05-08 12:01:55 -0400
   * Finding disabled groups should actually find them, now
 
 r2863 at cubic-pc (orig r5184):  jesse | 2006-05-09 06:32:10 +0400
  r13314 at hualien:  jesse | 2006-05-08 12:14:26 -0400
  * Minor reformatting
 
 r2864 at cubic-pc (orig r5185):  jesse | 2006-05-09 06:32:19 +0400
  r13315 at hualien:  jesse | 2006-05-08 22:31:30 -0400
  * Mail gateway refactoring to make added functioanlity a bit easier. 
    No (intentional) functional changes.
 
 r2865 at cubic-pc (orig r5186):  jesse | 2006-05-09 06:56:20 +0400
  r13330 at hualien:  jesse | 2006-05-08 22:55:56 -0400
   * Reed Loden caught a perltidy error that, somewhat terrifiyingly, was still a valid mason page
 
 r2866 at cubic-pc (orig r5187):  jesse | 2006-05-09 08:48:10 +0400
  r13332 at hualien:  jesse | 2006-05-09 00:47:49 -0400
  * Mismatched parens
 
 r2867 at cubic-pc (orig r5206):  ruz | 2006-05-12 00:48:53 +0400
 * return values checking and more logging on errors
 r2868 at cubic-pc (orig r5207):  ruz | 2006-05-12 00:56:24 +0400
 * more checks on attachments processing
 r2869 at cubic-pc (orig r5208):  ruz | 2006-05-12 02:24:17 +0400
 * if ( not $xxx || $xxx->foo ) is equivalent to
   if ( not ( $xxx || $xxx->foo ) ) due to perl5 rules
   which is not expected behaviour
 r2870 at cubic-pc (orig r5209):  ruz | 2006-05-12 02:31:58 +0400
 * user do next steps:
     1) open ticket #1
     2) click reply
     3) upload attachment
     4) open ticket #2 in another browser window
     5) send reply to the ticket #1
   RT looses uploaded attachment due to step 4) as RT tries
   to add attchement to the ticket #2 and drops them from session.
   As solution don't ProcessTicketMessage if there is attachments,
   but only if there is real update message.
 r2885 at cubic-pc (orig r5216):  ruz | 2006-05-13 00:54:41 +0400
 * add Timezone argument in SetToMidnight
 r2886 at cubic-pc (orig r5217):  ruz | 2006-05-13 01:02:54 +0400
 * use SetToMidnight( Timezone => 'server' ) to calc start and end of the day
 r2888 at cubic-pc (orig r5218):  ruz | 2006-05-13 04:31:33 +0400
 * get rid of "masks earlier declaration" warnings
 r2889 at cubic-pc (orig r5238):  ruz | 2006-05-17 02:39:59 +0400
 * really noisy warning
   *NOTE* that option we use is not described in config
 r2895 at cubic-pc (orig r5249):  ruz | 2006-05-18 20:17:47 +0400
 * add bug comment
 r2896 at cubic-pc (orig r5256):  ruz | 2006-05-19 05:45:58 +0400
 * allow to complete actions in mail plugins
 r2897 at cubic-pc (orig r5257):  ruz | 2006-05-19 05:53:40 +0400
 * minor
 r3099 at cubic-pc (orig r5268):  jesse | 2006-05-20 01:17:41 +0400
  r13935 at hualien:  jesse | 2006-05-19 17:17:27 -0400
  * There were divergent copies of this code. The EmailParser code was more correct
 
 r3130 at cubic-pc (orig r5310):  ruz | 2006-05-27 04:39:49 +0400
 * when we could parse URI, for example object doesn't exist
   fallback to RT::URI::base resolver, so $uri->IsLocal and
   other methods wouldn't die but return undef
 r3132 at cubic-pc (orig r5315):  ruz | 2006-05-28 15:19:20 +0400
 * Use "Requestor.id = $requestor->id" search instead of search by email address
   as latter is not indexed
 r3133 at cubic-pc (orig r5317):  ruz | 2006-05-31 00:13:02 +0400
 * If current user changes owner from somebody else to nobody user,
   the action fails with "You can only reassign tickets that you own
   or that are unowned", but we must change owner if he has no right
   to own tickets in dest queue. Do it with Force and with SystemUser
   context.


Modified: rt/branches/3.7-EXPERIMENTAL/config.layout
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/config.layout	(original)
+++ rt/branches/3.7-EXPERIMENTAL/config.layout	Fri Jun 16 18:02:52 2006
@@ -127,3 +127,26 @@
   customlexdir:		${customdir}/po
   customlibdir:		${customdir}/lib
 </Layout>
+
+#   RH path layout.
+<Layout RH>
+  prefix:		/usr/
+  exec_prefix:		${prefix}
+  bindir:		${exec_prefix}/bin
+  sbindir:		${exec_prefix}/sbin
+  sysconfdir:		/etc/rt
+  mandir:		${prefix}/man
+  libdir:		${prefix}/lib/rt
+  datadir:		/var/rt
+  htmldir:		${datadir}/html
+  manualdir:		${datadir}/doc
+  localstatedir:	/var/
+  logfiledir:		${localstatedir}/log/rt
+  masonstatedir:	${localstatedir}/rt/mason_data
+  sessionstatedir:	${localstatedir}/rt/session_data
+  customdir:		${prefix}/local/rt
+  custometcdir:		${customdir}/etc
+  customhtmldir:	${customdir}/html
+  customlexdir:		${customdir}/po
+  customlibdir:		${customdir}/lib
+</Layout>

Modified: rt/branches/3.7-EXPERIMENTAL/html/Admin/Groups/index.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Admin/Groups/index.html	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Admin/Groups/index.html	Fri Jun 16 18:02:52 2006
@@ -78,6 +78,10 @@
 my $title = loc('Select a group');
 my $caption;
 
+if ($FindDisabledGroups) {
+    $Groups->FindAllRows();
+}
+
 if (length $GroupString) {
     $caption = loc("Groups matching search criteria");
     if ($GroupField =~ /^CustomField-(\d+)/) {

Modified: rt/branches/3.7-EXPERIMENTAL/html/Elements/SelectNewTicketQueue
==============================================================================

Modified: rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/Forms/ticket/default
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/Forms/ticket/default	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/Forms/ticket/default	Fri Jun 16 18:02:52 2006
@@ -58,7 +58,7 @@
 my ($c, $o, $k, $e) = ("", [], {}, 0);
 my %data   = %$changes;
 my $ticket = new RT::Ticket $session{CurrentUser};
-my @dates  = qw(Created Starts Started Due Resolved Told);
+my @dates  = qw(Created Starts Started Due Resolved Told LastUpdated);
 my @people = qw(Requestors Cc AdminCc);
 my @create = qw(Queue Requestor Subject Cc AdminCc Owner Status Priority
                 InitialPriority FinalPriority TimeEstimated TimeWorked

Modified: rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/NoAuth/mail-gateway
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/NoAuth/mail-gateway	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/NoAuth/mail-gateway	Fri Jun 16 18:02:52 2006
@@ -52,26 +52,30 @@
 $ticket => undef
 </%ARGS>
 <%init>
-use RT::Interface::Email; 
+use RT::Interface::Email ();    # It's an exporter, but we don't care
 $r->content_type('text/plain; charset=utf-8');
 $m->error_format('text');
-my ( $status, $error, $Ticket ) = RT::Interface::Email::Gateway(\%ARGS);
- if ($status == -75 ) {
-$m->out("temporary failure - ". $error);
- }
-    elsif ($status == 1) {
-$m->out('ok');
-        if ( $Ticket->Id ) {
-$m->out('Ticket: '. $Ticket->Id);
-$m->out('Queue: '. $Ticket->QueueObj->Name );
-$m->out('Owner: '. $Ticket->OwnerObj->Name);
-$m->out('Status: '. $Ticket->Status );
-$m->out('Subject: '. $Ticket->Subject );
-$m->out('Requestor: '. $Ticket->Requestors->MemberEmailAddressesAsString );
-        }
- }   else { 
-$m->out('not ok - '.$error);
- }
-
+my ( $status, $error, $Ticket ) = RT::Interface::Email::Gateway( \%ARGS );
+if ( $status == 1 ) {
+  $m->out('ok');
+  if ( $Ticket->Id ) {
+    $m->out( 'Ticket: ' . $Ticket->Id );
+    $m->out( 'Queue: ' . $Ticket->QueueObj->Name );
+    $m->out( 'Owner: ' . $Ticket->OwnerObj->Name );
+    $m->out( 'Status: ' . $Ticket->Status );
+    $m->out( 'Subject: ' . $Ticket->Subject );
+    $m->out(
+      'Requestor: ' . $Ticket->Requestors->MemberEmailAddressesAsString );
+  }
+}
+else {
+  $RT::Logger->error( "Could not record email: " . $error );
+  if ( $status == -75 ) {
+    $m->out( "temporary failure - " . $error );
+  }
+  else {
+    $m->out( 'not ok - ' . $error );
+  }
+}
 $m->abort();
 </%init>

Modified: rt/branches/3.7-EXPERIMENTAL/html/REST/1.0/search/ticket
==============================================================================

Modified: rt/branches/3.7-EXPERIMENTAL/html/SelfService/Create.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/SelfService/Create.html	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/SelfService/Create.html	Fri Jun 16 18:02:52 2006
@@ -79,7 +79,7 @@
 <&|/l&>Subject</&>:
 </td>
 <td class="value">
-<input name="Subject" size="60" maxsize="100" value="" />
+<input name="Subject" size="60" maxsize="200" value="" />
 </td>
 </tr>
 <tr>

Modified: rt/branches/3.7-EXPERIMENTAL/html/Ticket/Create.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Ticket/Create.html	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Ticket/Create.html	Fri Jun 16 18:02:52 2006
@@ -107,7 +107,7 @@
 <&|/l&>Subject</&>:
 </td>
 <td class="value" colspan="5">
-<input name="Subject" size="60" maxsize="100" value="<%$ARGS{Subject} || ''%>" />
+<input name="Subject" size="60" maxsize="200" value="<%$ARGS{Subject} || ''%>" />
 </td>
 </tr>
 <tr>

Modified: rt/branches/3.7-EXPERIMENTAL/html/Ticket/Display.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Ticket/Display.html	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Ticket/Display.html	Fri Jun 16 18:02:52 2006
@@ -118,6 +118,7 @@
         }
     }
 
+    # XXX: Most probably we delete atachments here!
     $ARGS{UpdateAttachments} = delete $session{'Attachments'};
     push @Actions, ProcessUpdateMessage( ARGSRef => \%ARGS, TicketObj => $TicketObj );
     push @Actions, ProcessTicketBasics(  ARGSRef => \%ARGS, TicketObj => $TicketObj );

Modified: rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/PreviewScrips
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/PreviewScrips	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/PreviewScrips	Fri Jun 16 18:02:52 2006
@@ -86,16 +86,20 @@
     TimeTaken    => $ARGS{'UpdateTimeWorked'},
     DryRun       => 1
 );
+unless ( $Transaction ) {
+    $RT::Logger->error("Coulfn't fire '$action' action: $Description");
+}
 
 
 my @non_recipients = $TicketObj->SquelchMailTo;
 </%init>
 <h2><&|/l&>This message will be sent to...</&></h2>
+% if ( $Object ) {
 <i><&|/l&>(Check boxes to disable notifications to the listed recipients)</&></i><br />
-% if ($Object) {
+
 % foreach my $scrip (@{$Object->Scrips->Prepared}) {
 % next unless $scrip->ActionObj->Action->isa('RT::Action::SendEmail');
-<b><%$scrip->Description%></b><br />
+<b><% $scrip->Description %></b><br />
 <&|/l, loc($scrip->ConditionObj->Name), loc($scrip->ActionObj->Name), loc($scrip->TemplateObj->Name)&>[_1] [_2] with template [_3]</&>
 <br />
 %foreach my $type qw(To Cc Bcc) {
@@ -111,9 +115,10 @@
 <%$scrip->ActionObj->TemplateObj->MIMEObj->as_string%>
 </textarea>
 % }
-%}
-%}
+% }
+% }
 <br />
+
 <h2><&|/l&>Messages about this ticket will not be sent to...</&></h2>
 <i><&|/l&>(Check boxes to enable notifications to the listed recipients)</&></i>
 <br />

Modified: rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/ShowRequestor
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/ShowRequestor	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Ticket/Elements/ShowRequestor	Fri Jun 16 18:02:52 2006
@@ -47,18 +47,16 @@
 my $rows = 10;
 my $people = $Ticket->Requestors->UserMembersObj;
 while (my $requestor=$people->Next) {
+next if $requestor->Privileged;
 my $name=$requestor->RealName || $requestor->EmailAddress;	
-my $tickets = RT::Tickets->new($session{'CurrentUser'});
 my $has_right_adminusers = $session{'CurrentUser'}->HasRight(Object => $RT::System, Right => 'AdminUsers');
-$tickets->LimitWatcher(TYPE => 'Requestor', VALUE => $requestor->EmailAddress );
-$tickets->LimitStatus( VALUE => 'open');
-$tickets->LimitStatus( VALUE => 'new');
+
+my $tickets = RT::Tickets->new($session{'CurrentUser'});
+$tickets->FromSQL( "Requestor.id = ". $requestor->id ." AND (Status = 'open' OR Status = 'new')" );
 $tickets->RowsPerPage($rows);
-$tickets->OrderBy(FIELD => 'Priority',
-		  ORDER => 'DESC');
+$tickets->OrderBy(FIELD => 'Priority', ORDER => 'DESC');
 </%PERL>
 
-% unless ($requestor->Privileged) {
 <&| /Widgets/TitleBox,
     title_href => $has_right_adminusers? RT->Config->Get('WebPath')."/Admin/Users/Modify.html?id=".$requestor->id: '',
     title => loc("More about [_1]", $name),
@@ -84,7 +82,6 @@
 </&>
 
 % }
-%}
 <%ARGS>
 $Ticket=>undef
 $DisplayPath => "/Ticket/Display.html"

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Attachment_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Attachment_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Attachment_Overlay.pm	Fri Jun 16 18:02:52 2006
@@ -300,7 +300,7 @@
         eval { return( Encode::decode_utf8($content)) } || return ($content);
     }
 
-    eval { Encode::from_to( $content, 'utf8' => $enc ) };
+    eval { Encode::from_to($content, 'utf8' => $enc) } if $enc;
     if ($@) {
         $RT::Logger->error("Could not convert attachment from assumed utf8 to '$enc' :".$@);
     }

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/CustomField_Overlay.pm
==============================================================================

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Date.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Date.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Date.pm	Fri Jun 16 18:02:52 2006
@@ -251,19 +251,27 @@
 
 # {{{ sub SetToMidnight 
 
-=head2 SetToMidnight
+=head2 SetToMidnight [Timezone => 'utc']
 
-Sets the date to midnight (at the beginning of the day) GMT
+Sets the date to midnight (at the beginning of the day).
 Returns the unixtime at midnight.
 
+Arguments:
+
+=over 4
+
+=item Timezone - Timezone context C<server> or C<UTC>
+
 =cut
 
 sub SetToMidnight {
     my $self = shift;
-    
-    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($self->Unix);
-    $self->Unix(timegm (0,0,0,$mday,$mon,$year,$wday,$yday));
-    
+    my %args = ( Timezone => 'UTC', @_ );
+    if ( lc $args{'Timezone'} eq 'server' ) {
+        $self->Unix( timelocal( 0,0,0,(localtime $self->Unix)[3..7] ) );
+    } else {
+        $self->Unix( timegm( 0,0,0,(gmtime $self->Unix)[3..7] ) );
+    }
     return ($self->Unix);
 }
 

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Email.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Email.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Email.pm	Fri Jun 16 18:02:52 2006
@@ -1,38 +1,38 @@
 # BEGIN BPS TAGGED BLOCK {{{
-# 
+#
 # COPYRIGHT:
-#  
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
 #                                          <jesse at bestpractical.com>
-# 
+#
 # (Except where explicitly superseded by other copyright notices)
-# 
-# 
+#
+#
 # LICENSE:
-# 
+#
 # This work is made available to you under the terms of Version 2 of
 # the GNU General Public License. A copy of that license should have
 # been provided with this software, but in any event can be snarfed
 # from www.gnu.org.
-# 
+#
 # This work is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-# 
-# 
+#
+#
 # CONTRIBUTION SUBMISSION POLICY:
-# 
+#
 # (The following paragraph is not intended to limit the rights granted
 # to you to modify and distribute this software under the terms of
 # the GNU General Public License and is only of importance to you if
 # you choose to contribute your changes and enhancements to the
 # community by submitting them to Best Practical Solutions, LLC.)
-# 
+#
 # By intentionally submitting any modifications, corrections or
 # derivatives to this work, or any other work intended for use with
 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
@@ -41,7 +41,7 @@
 # royalty-free, perpetual, license to use, copy, create derivative
 # works based on those contributions, and sublicense and distribute
 # those contributions and any derivatives thereof.
-# 
+#
 # END BPS TAGGED BLOCK }}}
 package RT::Interface::Email;
 
@@ -50,31 +50,32 @@
 use MIME::Entity;
 use RT::EmailParser;
 use File::Temp;
+use UNIVERSAL::require;
 
 BEGIN {
     use Exporter ();
-    use vars qw ($VERSION  @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
-    
+    use vars qw ( @ISA @EXPORT_OK);
+
     # set the version for version checking
-    $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
-    
-    @ISA         = qw(Exporter);
-    
+    our $VERSION = 2.0;
+
+    @ISA = qw(Exporter);
+
     # your exported package globals go here,
     # as well as any optionally exported functions
-    @EXPORT_OK   = qw(
-              &CreateUser
-              &GetMessageContent
-              &CheckForLoops 
-              &CheckForSuspiciousSender
-              &CheckForAutoGenerated 
-              &CheckForBounce 
-              &MailError 
-              &ParseCcAddressesFromHead
-              &ParseSenderAddressFromHead 
-              &ParseErrorsToAddressFromHead
-              &ParseAddressFromHeader
-              &Gateway);
+    @EXPORT_OK = qw(
+        &CreateUser
+        &GetMessageContent
+        &CheckForLoops
+        &CheckForSuspiciousSender
+        &CheckForAutoGenerated
+        &CheckForBounce
+        &MailError
+        &ParseCcAddressesFromHead
+        &ParseSenderAddressFromHead
+        &ParseErrorsToAddressFromHead
+        &ParseAddressFromHeader
+        &Gateway);
 
 }
 
@@ -103,12 +104,11 @@
 
 =cut
 
+# {{{ sub CheckForLoops
 
-# {{{ sub CheckForLoops 
-
-sub CheckForLoops  {
+sub CheckForLoops {
     my $head = shift;
-    
+
     # If this instance of RT sent it our, we don't want to take it in
     my $RTLoop = $head->get("X-RT-Loop-Prevention") || "";
     chomp ($RTLoop); # remove that newline
@@ -129,17 +129,17 @@
     my $head = shift;
 
     #if it's from a postmaster or mailer daemon, it's likely a bounce.
-    
+
     #TODO: better algorithms needed here - there is no standards for
     #bounces, so it's very difficult to separate them from anything
     #else.  At the other hand, the Return-To address is only ment to be
     #used as an error channel, we might want to put up a separate
     #Return-To address which is treated differently.
-    
+
     #TODO: search through the whole email and find the right Ticket ID.
 
-    my ($From, $junk) = ParseSenderAddressFromHead($head);
-    
+    my ( $From, $junk ) = ParseSenderAddressFromHead($head);
+
     if ( $From =~ /^(?:mailer-daemon|postmaster)\@/i ) {
         return 1;
     }
@@ -152,15 +152,15 @@
 # {{{ sub CheckForAutoGenerated
 sub CheckForAutoGenerated {
     my $head = shift;
-    
-    my $Precedence = $head->get("Precedence") || "" ;
-    if ($Precedence =~ /^(bulk|junk)/i) {
-	return (1);
+
+    my $Precedence = $head->get("Precedence") || "";
+    if ( $Precedence =~ /^(bulk|junk)/i ) {
+        return (1);
     }
-    
+
     # First Class mailer uses this as a clue.
     my $FCJunk = $head->get("X-FC-Machinegenerated") || "";
-    if ($FCJunk =~ /^true/i) {
+    if ( $FCJunk =~ /^true/i ) {
         return (1);
     }
 
@@ -172,9 +172,9 @@
 # {{{ sub CheckForBounce
 sub CheckForBounce {
     my $head = shift;
-   
-    my $ReturnPath = $head->get("Return-path") || "" ;
-    return ($ReturnPath =~ /<>/);
+
+    my $ReturnPath = $head->get("Return-path") || "";
+    return ( $ReturnPath =~ /<>/ );
 }
 
 # }}}
@@ -213,47 +213,49 @@
 =cut
 
 sub CullRTAddresses {
-    return (grep { IsRTAddress($_) } @_);
+    return ( grep { IsRTAddress($_) } @_ );
 }
 
 # }}}
 
-# {{{ sub MailError 
+# {{{ sub MailError
 sub MailError {
     my %args = (
-        To => RT->Config->Get('OwnerEmail'),
-		Bcc => undef,
-		From => RT->Config->Get('CorrespondAddress'),
-		Subject => 'There has been an error',
-		Explanation => 'Unexplained error',
-		MIMEObj => undef,
-        Attach => undef,
-		LogLevel => 'crit',
-		@_);
-
-
-    $RT::Logger->log(level => $args{'LogLevel'}, 
-		     message => $args{'Explanation'}
-		    );
-    my $entity = MIME::Entity->build( Type  =>"multipart/mixed",
-				      From => $args{'From'},
-				      Bcc => $args{'Bcc'},
-				      To => $args{'To'},
-				      Subject => $args{'Subject'},
-				      Precedence => 'bulk',
-				      'X-RT-Loop-Prevention' => RT->Config->Get('rtname'),
-				    );
+        To          => RT->Config->Get('OwnerEmail'),
+        Bcc         => undef,
+        From        => RT->Config->Get('CorrespondAddress'),
+        Subject     => 'There has been an error',
+        Explanation => 'Unexplained error',
+        MIMEObj     => undef,
+        Attach      => undef,
+        LogLevel    => 'crit',
+        @_
+    );
+
+    $RT::Logger->log(
+        level   => $args{'LogLevel'},
+        message => $args{'Explanation'}
+    );
+    my $entity = MIME::Entity->build(
+        Type                   => "multipart/mixed",
+        From                   => $args{'From'},
+        Bcc                    => $args{'Bcc'},
+        To                     => $args{'To'},
+        Subject                => $args{'Subject'},
+        Precedence             => 'bulk',
+        'X-RT-Loop-Prevention' => RT->Config->Get('rtname'),
+    );
+
+    $entity->attach( Data => $args{'Explanation'} . "\n" );
 
-    $entity->attach(  Data => $args{'Explanation'}."\n");
-    
     my $mimeobj = $args{'MIMEObj'};
     if ($mimeobj) {
         $mimeobj->sync_headers();
         $entity->add_part($mimeobj);
     }
-   
-    if ($args{'Attach'}) {
-        $entity->attach(Data => $args{'Attach'}, Type => 'message/rfc822');
+
+    if ( $args{'Attach'} ) {
+        $entity->attach( Data => $args{'Attach'}, Type => 'message/rfc822' );
 
     }
 
@@ -339,38 +341,40 @@
 # {{{ Create User
 
 sub CreateUser {
-    my ($Username, $Address, $Name, $ErrorsTo, $entity) = @_;
+    my ( $Username, $Address, $Name, $ErrorsTo, $entity ) = @_;
 
     my $NewUser = RT::User->new( $RT::SystemUser );
 
-    my ($Val, $Message) = $NewUser->Create(
-        Name         => ($Username || $Address),
+    my ( $Val, $Message ) = $NewUser->Create(
+        Name => ( $Username || $Address ),
         EmailAddress => $Address,
         RealName     => $Name,
         Password     => undef,
         Privileged   => 0,
         Comments     => 'Autocreated on ticket submission',
     );
-    
+
     unless ($Val) {
-        
+
         # Deal with the race condition of two account creations at once
         #
         if ($Username) {
             $NewUser->LoadByName($Username);
         }
-        
+
         unless ( $NewUser->Id ) {
             $NewUser->LoadByEmail($Address);
         }
-        
-        unless ($NewUser->Id) {  
-            MailError( To => $ErrorsTo,
-                       Subject => "User could not be created",
-                       Explanation => "User creation failed in mailgateway: $Message",
-                       MIMEObj => $entity,
-                       LogLevel => 'crit',
-                     );
+
+        unless ( $NewUser->Id ) {
+            MailError(
+                To          => $ErrorsTo,
+                Subject     => "User could not be created",
+                Explanation =>
+                    "User creation failed in mailgateway: $Message",
+                MIMEObj  => $entity,
+                LogLevel => 'crit',
+            );
         }
     }
 
@@ -378,21 +382,25 @@
     my $CurrentUser = new RT::CurrentUser;
     $CurrentUser->LoadByEmail( $Address );
 
-    unless ($CurrentUser->id) {
-            $RT::Logger->warning("Couldn't load user '$Address'.".  "giving up");
-                MailError( To => $ErrorsTo,
-                           Subject => "User could not be loaded",
-                           Explanation => "User  '$Address' could not be loaded in the mail gateway",
-                           MIMEObj => $entity,
-                           LogLevel => 'crit'
-                     );
+    unless ( $CurrentUser->id ) {
+        $RT::Logger->warning(
+            "Couldn't load user '$Address'." . "giving up" );
+        MailError(
+            To          => $ErrorsTo,
+            Subject     => "User could not be loaded",
+            Explanation =>
+                "User  '$Address' could not be loaded in the mail gateway",
+            MIMEObj  => $entity,
+            LogLevel => 'crit'
+        );
     }
 
     return $CurrentUser;
 }
+
 # }}}
 
-# {{{ ParseCcAddressesFromHead 
+# {{{ ParseCcAddressesFromHead
 
 =head2 ParseCcAddressesFromHead HASHREF
 
@@ -402,32 +410,34 @@
 email address  and anything that the configuration sub RT::IsRTAddress matches.
 
 =cut
-  
+
 sub ParseCcAddressesFromHead {
-    my %args = ( Head => undef,
-		 QueueObj => undef,
-		 CurrentUser => undef,
-		 @_ );
-    
+    my %args = (
+        Head        => undef,
+        QueueObj    => undef,
+        CurrentUser => undef,
+        @_
+    );
+
     my (@Addresses);
-        
-    my @ToObjs = Mail::Address->parse($args{'Head'}->get('To'));
-    my @CcObjs = Mail::Address->parse($args{'Head'}->get('Cc'));
-    
-    foreach my $AddrObj (@ToObjs, @CcObjs) {
-	my $Address = $AddrObj->address;
-	$Address = $args{'CurrentUser'}->UserObj->CanonicalizeEmailAddress($Address);
- 	next if ($args{'CurrentUser'}->EmailAddress =~ /^\Q$Address\E$/i);
-	next if ($args{'QueueObj'}->CorrespondAddress =~ /^\Q$Address\E$/i);
-	next if ($args{'QueueObj'}->CommentAddress =~ /^\Q$Address\E$/i);
-	next if (RT::EmailParser->IsRTAddress($Address));
-	
-	push (@Addresses, $Address);
+
+    my @ToObjs = Mail::Address->parse( $args{'Head'}->get('To') );
+    my @CcObjs = Mail::Address->parse( $args{'Head'}->get('Cc') );
+
+    foreach my $AddrObj ( @ToObjs, @CcObjs ) {
+        my $Address = $AddrObj->address;
+        $Address = $args{'CurrentUser'}
+            ->UserObj->CanonicalizeEmailAddress($Address);
+        next if ( $args{'CurrentUser'}->EmailAddress   =~ /^\Q$Address\E$/i );
+        next if ( $args{'QueueObj'}->CorrespondAddress =~ /^\Q$Address\E$/i );
+        next if ( $args{'QueueObj'}->CommentAddress    =~ /^\Q$Address\E$/i );
+        next if ( RT::EmailParser->IsRTAddress($Address) );
+
+        push( @Addresses, $Address );
     }
     return (@Addresses);
 }
 
-
 # }}}
 
 # {{{ ParseSenderAdddressFromHead
@@ -441,12 +451,14 @@
 
 sub ParseSenderAddressFromHead {
     my $head = shift;
+
     #Figure out who's sending this message.
     my $From = $head->get('Reply-To')
         || $head->get('From')
         || $head->get('Sender');
-    return (ParseAddressFromHeader($From));
+    return ( ParseAddressFromHeader($From) );
 }
+
 # }}}
 
 # {{{ ParseErrorsToAdddressFromHead
@@ -461,18 +473,22 @@
 
 sub ParseErrorsToAddressFromHead {
     my $head = shift;
+
     #Figure out who's sending this message.
 
-    foreach my $header ('Return-path', 'Errors-To' , 'Reply-To', 'From', 'Sender' ) {
-	# If there's a header of that name
-	my $headerobj = $head->get($header);
-	if ($headerobj) {
-		my ($addr, $name ) = ParseAddressFromHeader($headerobj);
-		# If it's got actual useful content...
-		return ($addr) if ($addr);
-	}
+    foreach my $header ( 'Errors-To', 'Reply-To', 'From', 'Sender' ) {
+
+        # If there's a header of that name
+        my $headerobj = $head->get($header);
+        if ($headerobj) {
+            my ( $addr, $name ) = ParseAddressFromHeader($headerobj);
+
+            # If it's got actual useful content...
+            return ($addr) if ($addr);
+        }
     }
 }
+
 # }}}
 
 # {{{ ParseAddressFromHeader
@@ -483,31 +499,28 @@
 
 =cut
 
-
-sub ParseAddressFromHeader{
+sub ParseAddressFromHeader {
     my $Addr = shift;
-    
-    # Perl 5.8.0 breaks when doing regex matches on utf8
-    Encode::_utf8_off($Addr) if $] == 5.008;
+
     my @Addresses = Mail::Address->parse($Addr);
-    
+
     my $AddrObj = $Addresses[0];
 
-    unless (ref($AddrObj)) {
-	return(undef,undef);
+    unless ( ref($AddrObj) ) {
+        return ( undef, undef );
     }
- 
-    my $Name =  ($AddrObj->phrase || $AddrObj->comment || $AddrObj->address);
-    
+
+    my $Name = ( $AddrObj->phrase || $AddrObj->comment || $AddrObj->address );
+
     #Lets take the from and load a user object.
     my $Address = $AddrObj->address;
 
-    return ($Address, $Name);
+    return ( $Address, $Name );
 }
-# }}}
 
-# {{{ sub ParseTicketId 
+# }}}
 
+# {{{ sub ParseTicketId
 
 sub ParseTicketId {
     my $Subject = shift;
@@ -520,15 +533,13 @@
         my $id = $1;
         $RT::Logger->debug("Found a ticket ID. It's $id");
         return $id;
-    }
-    else {
+    } else {
         return undef;
     }
 }
 
 # }}}
 
-
 =head2 Gateway ARGSREF
 
 
@@ -567,50 +578,53 @@
 
 sub Gateway {
     my $argsref = shift;
+    my %args    = (
+        action  => 'correspond',
+        queue   => '1',
+        ticket  => undef,
+        message => undef,
+        %$argsref
+    );
 
-    my %args = %$argsref;
-
-    # Set some reasonable defaults
-    $args{'action'} ||= 'correspond';
-    $args{'queue'}  ||= 1;
+    my $SystemTicket;
+    my $Right;
 
     # Validate the action
-    my ($status, @actions) = IsCorrectAction( $args{'action'} );
-    unless ( $status ) {
-
-        # Can't safely loc this. What object do we loc around?
-        $RT::Logger->crit("Mail gateway called with an invalid action paramenter '".$actions[0]."' for queue '".$args{'queue'}."'");
-
-        return ( -75, "Invalid 'action' parameter", undef );
+    my ( $status, @actions ) = IsCorrectAction( $args{'action'} );
+    unless ($status) {
+        return (
+            -75,
+            "Invalid 'action' parameter "
+                . $actions[0]
+                . " for queue "
+                . $args{'queue'},
+            undef
+        );
     }
 
     my $parser = RT::EmailParser->new();
+    $parser->SmartParseMIMEEntityFromScalar( Message => $args{'message'} );
+    my $Message = $parser->Entity();
 
-    $parser->SmartParseMIMEEntityFromScalar( Message => $args{'message'});
-
-    if (!$parser->Entity()) {
+    unless ($Message) {
         MailError(
             To          => RT->Config->Get('OwnerEmail'),
             Subject     => "RT Bounce: Unparseable message",
             Explanation => "RT couldn't process the message below",
-            Attach     => $args{'message'}
+            Attach      => $args{'message'}
         );
 
-        return(0,"Failed to parse this message. Something is likely badly wrong with the message");
+        return ( 0,
+            "Failed to parse this message. Something is likely badly wrong with the message"
+        );
     }
 
-    my $Message = $parser->Entity();
-    my $head    = $Message->head;
-
-    my ( $CurrentUser, $AuthStat, $error );
-
-    # Initalize AuthStat so comparisons work correctly
-    $AuthStat = -9999999;
+    my $head = $Message->head;
 
     my $ErrorsTo = ParseErrorsToAddressFromHead( $head );
 
     my $MessageId = $head->get('Message-ID')
-      || "<no-message-id-". time . rand(2000) .'@'. RT->Config->Get('Organization') .'>';
+        || "<no-message-id-". time . rand(2000) .'@'. RT->Config->Get('Organization') .'>';
 
     #Pull apart the subject line
     my $Subject = $head->get('Subject') || '';
@@ -618,13 +632,12 @@
 
     $args{'ticket'} ||= ParseTicketId( $Subject );
 
-    my $SystemTicket;
-    my $Right = 'CreateTicket';
-    if ( $args{'ticket'} ) {
-        $SystemTicket = RT::Ticket->new( $RT::SystemUser );
-        $SystemTicket->Load( $args{'ticket'} );
-        # if there's an existing ticket, this must be a reply
+    $SystemTicket = RT::Ticket->new( $RT::SystemUser );
+    $SystemTicket->Load( $args{'ticket'} ) if ( $args{'ticket'} ) ;
+    if ( $SystemTicket->id ) {
         $Right = 'ReplyToTicket';
+    } else {
+        $Right = 'CreateTicket';
     }
 
     #Set up a queue object
@@ -632,193 +645,127 @@
     $SystemQueueObj->Load( $args{'queue'} );
 
     # We can safely have no queue of we have a known-good ticket
-    unless ( $args{'ticket'} || $SystemQueueObj->id ) {
+    unless ( $SystemTicket->id || $SystemQueueObj->id ) {
         return ( -75, "RT couldn't find the queue: " . $args{'queue'}, undef );
     }
-
-    # Authentication Level
+    # Authentication Level ($AuthStat)
     # -1 - Get out.  this user has been explicitly declined
     # 0 - User may not do anything (Not used at the moment)
     # 1 - Normal user
     # 2 - User is allowed to specify status updates etc. a la enhanced-mailgate
 
+    # Initalize AuthStat so comparisons work correctly
+    my $AuthStat = -9999999;
+
     my @mail_plugins = grep $_, RT->Config->Get('MailPlugins');
     push @mail_plugins, "Auth::MailFrom" unless @mail_plugins;
 
+    my ( $CurrentUser, $error );
 
-    # Since this needs loading, no matter what
+    # if plugin returns AuthStat -2 we skip action
+    # NOTE: this is experimental API and it would be changed
+    my %skip_action = ();
 
-    foreach ( @mail_plugins ) {
-        my $Code;
+    # Since this needs loading, no matter what
+    foreach (@mail_plugins) {
+        my ($Code, $Class, $NewAuthStat);
         if ( ref($_) eq "CODE" ) {
             $Code = $_;
-        }
-        else {
-            $_ = "RT::Interface::Email::".$_ unless $_ =~ /^RTx?::Interface::Email::/;
-            eval "require $_;";
-            if ( $@ ) {
-                $RT::Logger->crit("Couldn't load module '$_': $@");
-                next;
-            }
+        } else {
+            $Class = $_;
+            $Class = "RT::Interface::Email::" . $Class
+                unless $Class =~ /^RT::Interface::Email::/;
+            $Class->require or
+                do { $RT::Logger->error("Couldn't load $Class: $@"); next };
 
             no strict 'refs';
-            if ( !defined( $Code = *{ $_ . "::GetCurrentUser" }{CODE} ) ) {
-                $RT::Logger->crit("No GetCurrentUser code found in $_ module");
+            unless ( defined( $Code = *{ $Class . "::GetCurrentUser" }{CODE} ) ) {
+                $RT::Logger->crit( "No GetCurrentUser code found in $Class module");
                 next;
             }
         }
 
-        my $NewAuthStat;
-        foreach my $action ( @actions ) {
 
+        foreach my $action (@actions) {
             ( $CurrentUser, $NewAuthStat ) = $Code->(
-                Message     => $Message,
+                Message       => $Message,
                 RawMessageRef => \$args{'message'},
-                CurrentUser => $CurrentUser,
-                AuthLevel   => $AuthStat,
-                Action      => $action,
-                Ticket      => $SystemTicket,
-                Queue       => $SystemQueueObj
+                CurrentUser   => $CurrentUser,
+                AuthLevel     => $AuthStat,
+                Action        => $action,
+                Ticket        => $SystemTicket,
+                Queue         => $SystemQueueObj
             );
 
-
-            # If a module returns a "-1" then we discard the ticket, so.
-            $AuthStat = -1 if $NewAuthStat == -1;
-
-            # You get the highest level of authentication you were assigned.
-            $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
+# You get the highest level of authentication you were assigned, unless you get the magic -1
+# If a module returns a "-1" then we discard the ticket, so.
+            $AuthStat = $NewAuthStat
+                if ( $NewAuthStat > $AuthStat or $NewAuthStat == -1 or $NewAuthStat == -2 );
 
             last if $AuthStat == -1;
+            $skip_action{$action}++ if $AuthStat == -2;
         }
 
         last if $AuthStat == -1;
     }
-
     # {{{ If authentication fails and no new user was created, get out.
-    if ( !$CurrentUser or !$CurrentUser->Id or $AuthStat == -1 ) {
+    if ( !$CurrentUser || !$CurrentUser->id || $AuthStat == -1 ) {
 
         # If the plugins refused to create one, they lose.
         unless ( $AuthStat == -1 ) {
-
-            # Notify the RT Admin of the failure.
-            # XXX Should this be configurable?
-            MailError(
-                To          => RT->Config->Get('OwnerEmail'),
-                Subject     => "Could not load a valid user",
-                Explanation => <<EOT,
-RT could not load a valid user, and RT's configuration does not allow
-for the creation of a new user for this email ($ErrorsTo).
-
-You might need to grant 'Everyone' the right '$Right' for the
-queue @{[$args{'queue'}]}.
-
-EOT
-                MIMEObj  => $Message,
-                LogLevel => 'error'
+            _NoAuthorizedUserFound(
+                Right     => $Right,
+                Message   => $Message,
+                Requestor => $ErrorsTo,
+                Queue     => $args{'queue'}
             );
 
-            # Also notify the requestor that his request has been dropped.
-            MailError(
-                To          => $ErrorsTo,
-                Subject     => "Could not load a valid user",
-                Explanation => <<EOT,
-RT could not load a valid user, and RT's configuration does not allow
-for the creation of a new user for your email.
-
-EOT
-                MIMEObj  => $Message,
-                LogLevel => 'error'
-            );
         }
         return ( 0, "Could not load a valid user", undef );
     }
 
-    # }}}
-
-    # {{{ Lets check for mail loops of various sorts.
-    my $IsBounce = CheckForBounce($head);
-
-    my $IsAutoGenerated = CheckForAutoGenerated($head);
-
-    my $IsSuspiciousSender = CheckForSuspiciousSender($head);
-
-    my $IsALoop = CheckForLoops($head);
-
-    my $SquelchReplies = 0;
-
-    #If the message is autogenerated, we need to know, so we can not
-    # send mail to the sender
-    if ( $IsBounce || $IsSuspiciousSender || $IsAutoGenerated || $IsALoop ) {
-        $SquelchReplies = 1;
-        $ErrorsTo       = RT->Config->Get('OwnerEmail');
-    }
-
-    # }}}
-
-    # {{{ Drop it if it's disallowed
+    # If we got a user, but they don't have the right to say things
     if ( $AuthStat == 0 ) {
         MailError(
             To          => $ErrorsTo,
             Subject     => "Permission Denied",
-            Explanation => "You do not have permission to communicate with RT",
-            MIMEObj     => $Message
+            Explanation =>
+                "You do not have permission to communicate with RT",
+            MIMEObj => $Message
         );
-    }
-
-    # }}}
-    # {{{ Warn someone  if it's a loop
-
-    # Warn someone if it's a loop, before we drop it on the ground
-    if ( $IsALoop ) {
-        $RT::Logger->crit("RT Recieved mail ($MessageId) from itself.");
-
-        #Should we mail it to RTOwner?
-        if (RT->Config->Get('LoopsToRTOwner')) {
-            MailError(
-                To          => RT->Config->Get('OwnerEmail'),
-                Subject     => "RT Bounce: $Subject",
-                Explanation => "RT thinks this message may be a bounce",
-                MIMEObj     => $Message
-            );
-        }
-
-        #Do we actually want to store it?
-        return ( 0, "Message Bounced", undef ) unless (RT->Config->Get('StoreLoops'));
-    }
-
-    # }}}
-
-    # {{{ Squelch replies if necessary
-    # Don't let the user stuff the RT-Squelch-Replies-To header.
-    if ( $head->get('RT-Squelch-Replies-To') ) {
-        $head->add(
-            'RT-Relocated-Squelch-Replies-To',
-            $head->get('RT-Squelch-Replies-To')
+        return (
+            0,
+            "$ErrorsTo tried to submit a message to "
+                . $args{'Queue'}
+                . " without permission.",
+            undef
         );
-        $head->delete('RT-Squelch-Replies-To');
     }
 
-    if ($SquelchReplies) {
+    # {{{ Lets check for mail loops of various sorts.
+    my ($continue, $result);
+     ( $continue, $ErrorsTo, $result ) = _HandleMachineGeneratedMail(
+        Message  => $Message,
+        ErrorsTo => $ErrorsTo,
+        Subject  => $Subject,
+        MessageId => $MessageId
+    );
 
-        # Squelch replies to the sender, and also leave a clue to
-        # allow us to squelch ALL outbound messages. This way we
-        # can punt the logic of "what to do when we get a bounce"
-        # to the scrip. We might want to notify nobody. Or just
-        # the RT Owner. Or maybe all Privileged watchers.
-        my ( $Sender, $junk ) = ParseSenderAddressFromHead($head);
-        $head->add( 'RT-Squelch-Replies-To', $Sender );
-        $head->add( 'RT-DetectedAutoGenerated', 'true' );
+    unless ($continue) {
+        return ( 0, $result, undef );
     }
+    
+    # strip actions we should skip
+    @actions = grep !$skip_action{$_}, @actions;
 
-    # }}}
+    # if plugin's updated SystemTicket then update arguments
+    $args{'ticket'} = $SystemTicket->Id if $SystemTicket && $SystemTicket->Id;
 
     my $Ticket = RT::Ticket->new($CurrentUser);
 
-    # {{{ If we don't have a ticket Id, we're creating a new ticket
-    if ( (!$SystemTicket || !$SystemTicket->Id) && 
-           grep /^(comment|correspond)$/, @actions ) {
-
-        # {{{ Create a new ticket
+    if (( !$SystemTicket || !$SystemTicket->Id )
+        && grep /^(comment|correspond)$/, @actions )
+    {
 
         my @Cc;
         my @Requestors = ( $CurrentUser->id );
@@ -845,43 +792,45 @@
                 Explanation => $ErrStr,
                 MIMEObj     => $Message
             );
-            $RT::Logger->error("Create failed: $id / $Transaction / $ErrStr ");
-            return ( 0, "Ticket creation failed", $Ticket );
+            return ( 0, "Ticket creation failed: $ErrStr", $Ticket );
         }
-        # strip comments&corresponds from the actions we don't need record twice
+
+# strip comments&corresponds from the actions we don't need to record them if we've created the ticket just now
         @actions = grep !/^(comment|correspond)$/, @actions;
         $args{'ticket'} = $id;
 
-        # }}}
-    }
+    } else {
 
-    $Ticket->Load( $args{'ticket'} );
-    unless ( $Ticket->Id ) {
-        my $message = "Could not find a ticket with id " . $args{'ticket'};
-        MailError(
-            To          => $ErrorsTo,
-            Subject     => "Message not recorded",
-            Explanation => $message,
-            MIMEObj     => $Message
-        );
+        $Ticket->Load( $args{'ticket'} );
+        unless ( $Ticket->Id ) {
+            my $error = "Could not find a ticket with id " . $args{'ticket'};
+            MailError(
+                To          => $ErrorsTo,
+                Subject     => "Message not recorded",
+                Explanation => $error,
+                MIMEObj     => $Message
+            );
 
-        return ( 0, $message );
+            return ( 0, $error );
+        }
     }
 
     # }}}
+
     my $unsafe_actions = RT->Config->Get('UnsafeEmailCommands');
-    foreach my $action( @actions ) {
+    foreach my $action (@actions) {
+
         #   If the action is comment, add a comment.
-        if ( $action =~ /^(comment|correspond)$/i ) {
+        if ( $action =~ /^(?:comment|correspond)$/i ) {
             my ( $status, $msg );
             if ( $action =~ /^correspond$/i ) {
-                ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message );
-            }
-            else {
+                ( $status, $msg )
+                    = $Ticket->Correspond( MIMEObj => $Message );
+            } else {
                 ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message );
             }
             unless ($status) {
-    
+
                 #Warn the sender that we couldn't actually submit the comment.
                 MailError(
                     To          => $ErrorsTo,
@@ -891,76 +840,198 @@
                 );
                 return ( 0, "Message not recorded", $Ticket );
             }
+        } elsif ( $unsafe_actions ) {
+            return _RunUnsafeAction(
+                Action      => $action,
+                ErrorsTo    => $ErrorsTo,
+                Message     => $Message,
+                Ticket      => $Ticket,
+                CurrentUser => $CurrentUser
+            );
         }
-        elsif ( $unsafe_actions && $action =~ /^take$/i ) {
-            my ( $status, $msg ) = $Ticket->SetOwner( $CurrentUser->id );
-            unless ($status) {
-    
-                #Warn the sender that we couldn't actually submit the comment.
-                MailError(
-                    To          => $ErrorsTo,
-                    Subject     => "Ticket not taken",
-                    Explanation => $msg,
-                    MIMEObj     => $Message
-                );
-                return ( 0, "Ticket not taken", $Ticket );
-            }
+    }
+    return ( 1, "Success", $Ticket );
+}
+
+sub _RunUnsafeAction {
+    my %args = (
+        Action      => undef,
+        ErrorsTo    => undef,
+        Message     => undef,
+        Ticket      => undef,
+        CurrentUser => undef,
+        @_
+    );
+
+    if ( $args{'Action'} =~ /^take$/i ) {
+        my ( $status, $msg ) = $args{'Ticket'}->SetOwner( $args{'CurrentUser'}->id );
+        unless ($status) {
+            MailError(
+                To          => $args{'ErrorsTo'},
+                Subject     => "Ticket not taken",
+                Explanation => $msg,
+                MIMEObj     => $args{'Message'}
+            );
+            return ( 0, "Ticket not taken", $args{'Ticket'} );
         }
-        elsif ( $unsafe_actions && $action =~ /^resolve$/i ) {
-            my ( $status, $msg ) = $Ticket->SetStatus( 'resolved' );
-            unless ($status) {
-                #Warn the sender that we couldn't actually submit the comment.
-                MailError(
-                    To          => $ErrorsTo,
-                    Subject     => "Ticket not resolved",
-                    Explanation => $msg,
-                    MIMEObj     => $Message
-                );
-                return ( 0, "Ticket not resolved", $Ticket );
-            }
+    } elsif ( $args{'Action'} =~ /^resolve$/i ) {
+        my ( $status, $msg ) = $args{'Ticket'}->SetStatus('resolved');
+        unless ($status) {
+
+            #Warn the sender that we couldn't actually submit the comment.
+            MailError(
+                To          => $args{'ErrorsTo'},
+                Subject     => "Ticket not resolved",
+                Explanation => $msg,
+                MIMEObj     => $args{'Message'}
+            );
+            return ( 0, "Ticket not resolved", $args{'Ticket'} );
         }
+    }
+    return ( 0, 'Unknown action' );
+}
+
+=head2 _NoAuthorizedUserFound
+
+Emails the RT Owner and the requestor when the auth plugins return "No auth user found"
+
+=cut
+
+sub _NoAuthorizedUserFound {
+    my %args = (
+        Right     => undef,
+        Message   => undef,
+        Requestor => undef,
+        Queue     => undef,
+        @_
+    );
+
+    # Notify the RT Admin of the failure.
+    MailError(
+        To          => $RT::OwnerEmail,
+        Subject     => "Could not load a valid user",
+        Explanation => <<EOT,
+RT could not load a valid user, and RT's configuration does not allow
+for the creation of a new user for this email (@{[$args{Requestor}]}).
+
+You might need to grant 'Everyone' the right '@{[$args{Right}]}' for the
+queue @{[$args{'Queue'}]}.
+
+EOT
+        MIMEObj  => $args{'Message'},
+        LogLevel => 'error'
+    );
+
+    # Also notify the requestor that his request has been dropped.
+    MailError(
+        To          => $args{'Requestor'},
+        Subject     => "Could not load a valid user",
+        Explanation => <<EOT,
+RT could not load a valid user, and RT's configuration does not allow
+for the creation of a new user for your email.
+
+EOT
+        MIMEObj  => $args{'Message'},
+        LogLevel => 'error'
+    );
+}
+
+=head2 _HandleMachineGeneratedMail
+
+Takes named params:
+    Message
+    ErrorsTo
+    Subject
+
+Checks the message to see if it's a bounce, if it looks like a loop, if it's autogenerated, etc.
+Returns a triple of ("Should we continue (boolean)", "New value for $ErrorsTo", "Status message");
+
+=cut
+
+sub _HandleMachineGeneratedMail {
+    my %args = ( Message => undef, ErrorsTo => undef, Subject => undef, MessageId => undef, @_ );
+    my $head = $args{'Message'}->head;
+    my $ErrorsTo = $args{'ErrorsTo'};
+
+    my $IsBounce = CheckForBounce($head);
+
+    my $IsAutoGenerated = CheckForAutoGenerated($head);
+
+    my $IsSuspiciousSender = CheckForSuspiciousSender($head);
+
+    my $IsALoop = CheckForLoops($head);
+
+    my $SquelchReplies = 0;
     
-        else {
-    
-            #Return mail to the sender with an error
+    my $owner_mail = RT->Config->Get('OwnerEmail');
+
+    #If the message is autogenerated, we need to know, so we can not
+    # send mail to the sender
+    if ( $IsBounce || $IsSuspiciousSender || $IsAutoGenerated || $IsALoop ) {
+        $SquelchReplies = 1;
+        $ErrorsTo       = $owner_mail;
+    }
+
+    # Warn someone if it's a loop, before we drop it on the ground
+    if ($IsALoop) {
+        $RT::Logger->crit("RT Recieved mail (".$args{MessageId}.") from itself.");
+
+        #Should we mail it to RTOwner?
+        if ( RT->Config->Get('LoopsToRTOwner') ) {
             MailError(
-                To          => $ErrorsTo,
-                Subject     => "RT Configuration error",
-                Explanation => "'"
-                  . $args{'action'}
-                  . "' not a recognized action."
-                  . " Your RT administrator has misconfigured "
-                  . "the mail aliases which invoke RT",
-                MIMEObj => $Message
-            );
-            $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
-            return (
-                -75,
-                "Configuration error: "
-                  . $args{'action'}
-                  . " not a recognized action",
-                $Ticket
+                To          => $owner_mail,
+                Subject     => "RT Bounce: ".$args{'Subject'},
+                Explanation => "RT thinks this message may be a bounce",
+                MIMEObj     => $args{Message}
             );
         }
+
+        #Do we actually want to store it?
+        return ( 0, $ErrorsTo, "Message Bounced" ) unless RT->Config->Get('StoreLoops');
     }
 
-    return ( 1, "Success", $Ticket );
+    # Squelch replies if necessary
+    # Don't let the user stuff the RT-Squelch-Replies-To header.
+    if ( $head->get('RT-Squelch-Replies-To') ) {
+        $head->add(
+            'RT-Relocated-Squelch-Replies-To',
+            $head->get('RT-Squelch-Replies-To')
+        );
+        $head->delete('RT-Squelch-Replies-To');
+    }
+
+    if ($SquelchReplies) {
+
+        # Squelch replies to the sender, and also leave a clue to
+        # allow us to squelch ALL outbound messages. This way we
+        # can punt the logic of "what to do when we get a bounce"
+        # to the scrip. We might want to notify nobody. Or just
+        # the RT Owner. Or maybe all Privileged watchers.
+        my ( $Sender, $junk ) = ParseSenderAddressFromHead($head);
+        $head->add( 'RT-Squelch-Replies-To',    $Sender );
+        $head->add( 'RT-DetectedAutoGenerated', 'true' );
+    }
+    return ( 1, $ErrorsTo, "Handled machine detection" );
 }
 
-sub IsCorrectAction
-{
+=head2 IsCorrectAction
+
+Returns a list of valid actions we've found for this message
+
+=cut
+
+sub IsCorrectAction {
     my $action = shift;
     my @actions = split /-/, $action;
     foreach ( @actions ) {
-        return (0, $_) unless /^(?:comment|correspond|take|resolve)$/;
+        return ( 0, $_ ) unless /^(?:comment|correspond|take|resolve)$/;
     }
-    return (1, @actions);
+    return ( 1, @actions );
 }
 
-
 eval "require RT::Interface::Email_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Vendor.pm});
+die $@ if ( $@ && $@ !~ qr{^Can't locate RT/Interface/Email_Vendor.pm} );
 eval "require RT::Interface::Email_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Local.pm});
+die $@ if ( $@ && $@ !~ qr{^Can't locate RT/Interface/Email_Local.pm} );
 
 1;

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web.pm	Fri Jun 16 18:02:52 2006
@@ -287,9 +287,18 @@
         Body                => $ARGS{'Content'},
     );
 
-    if ($ARGS{'Attachments'}) {
-        $MIMEObj->make_multipart;
-        $MIMEObj->add_part($_) foreach values %{$ARGS{'Attachments'}};
+    if ( $ARGS{'Attachments'} ) {
+        my $rv = $MIMEObj->make_multipart;
+        $RT::Logger->error("Couldn't make multipart message")
+            if !$rv || $rv !~ /^(?:DONE|ALREADY)$/;
+
+        foreach ( values %{$ARGS{'Attachments'}} ) {
+            unless ( $_ ) {
+                $RT::Logger->error("Couldn't add empty attachemnt");
+                next;
+            }
+            $MIMEObj->add_part($_);
+        }
     }
 
     my %create_args = (

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web/Handler.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web/Handler.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Interface/Web/Handler.pm	Fri Jun 16 18:02:52 2006
@@ -107,10 +107,12 @@
         # Clean up our umask to protect session files
         umask(0077);
 
-        if ($CGI::MOD_PERL) { local $@; eval {
+        if ($CGI::MOD_PERL and $CGI::MOD_PERL < 1.9908 ) {
+
             chown( Apache->server->uid, Apache->server->gid,
                 $RT::MasonSessionDir )
-        } }
+            if Apache->server->can('uid');
+        }
 
         # Die if WebSessionDir doesn't exist or we can't write to it
         stat($RT::MasonSessionDir);

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Record.pm
==============================================================================

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Ticket_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Ticket_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Ticket_Overlay.pm	Fri Jun 16 18:02:52 2006
@@ -440,9 +440,9 @@
     if ( $args{'Due'} ) {
         $Due->Set( Format => 'ISO', Value => $args{'Due'} );
     }
-    elsif ( $QueueObj->DefaultDueIn ) {
+    elsif ( my $due_in = $QueueObj->DefaultDueIn ) {
         $Due->SetToNow;
-        $Due->AddDays( $QueueObj->DefaultDueIn );
+        $Due->AddDays( $due_in );
     }
 
     my $Starts = new RT::Date( $self->CurrentUser );
@@ -1331,6 +1331,10 @@
         @_
     );
 
+    # XXX, FIXME, BUG: if only email is provided then we only check
+    # for ModifyTicket right, but must try to get PrincipalId and
+    # check Watch* rights too if user exist
+
     # {{{ Check ACLS
     #If the watcher we're trying to add is for the current user
     if ( $self->CurrentUser->PrincipalId  eq $args{'PrincipalId'}
@@ -1998,11 +2002,16 @@
         )
       )
     {
-        $self->Untake();
+        my $clone = RT::Ticket->new( $RT::SystemUser );
+        $clone->Load( $self->Id );
+        unless ( $clone->Id ) {
+            return ( 0, $self->loc("Couldn't load copy of ticket #[_1].", $self->Id) );
+        }
+        my ($status, $msg) = $clone->SetOwner( $RT::Nobody->Id, 'Force' );
+        $RT::Logger->error("Couldn't set owner on queue change: $msg") unless $status;
     }
 
     return ( $self->_Set( Field => 'Queue', Value => $NewQueueObj->Id() ) );
-
 }
 
 # }}}
@@ -3084,14 +3093,13 @@
                                              OldValue  => $OldOwnerObj->Id,
                                              TimeTaken => 0 );
 
-    if ($trans) {
+    if ( $val ) {
         $msg = $self->loc( "Owner changed from [_1] to [_2]",
                            $OldOwnerObj->Name, $NewOwnerObj->Name );
 
         # TODO: make sure the trans committed properly
     }
-    return ( $trans, $msg );
-
+    return ( $val, $msg );
 }
 
 # }}}

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Tickets_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Tickets_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Tickets_Overlay.pm	Fri Jun 16 18:02:52 2006
@@ -471,11 +471,8 @@
     die "Incorrect Meta Data for $field"
         unless ( defined $meta->[1] );
 
-    use POSIX 'strftime';
-
     my $date = RT::Date->new( $sb->CurrentUser );
     $date->Set( Format => 'unknown', Value => $value );
-    my $time = $date->Unix;
 
     if ( $op eq "=" ) {
 
@@ -483,10 +480,10 @@
         # particular single day.  in the database, we need to check for >
         # and < the edges of that day.
 
-        my $daystart = strftime( "%Y-%m-%d %H:%M",
-            gmtime( $time - ( $time % 86400 ) ) );
-        my $dayend = strftime( "%Y-%m-%d %H:%M",
-            gmtime( $time + ( 86399 - $time % 86400 ) ) );
+        $date->SetToMidnight( Timezone => 'server' );
+        my $daystart = $date->ISO;
+        $date->AddDay;
+        my $dayend = $date->ISO;
 
         $sb->_OpenParen;
 
@@ -509,11 +506,10 @@
 
     }
     else {
-        $value = strftime( "%Y-%m-%d %H:%M", gmtime($time) );
         $sb->_SQLLimit(
             FIELD    => $meta->[1],
             OPERATOR => $op,
-            VALUE    => $value,
+            VALUE    => $date->ISO,
             @rest,
         );
     }
@@ -566,7 +562,6 @@
 
     my $date = RT::Date->new( $sb->CurrentUser );
     $date->Set( Format => 'unknown', Value => $value );
-    my $time = $date->Unix;
 
     $sb->_OpenParen;
     if ( $op eq "=" ) {
@@ -575,10 +570,10 @@
         # particular single day.  in the database, we need to check for >
         # and < the edges of that day.
 
-        my $daystart = strftime( "%Y-%m-%d %H:%M",
-            gmtime( $time - ( $time % 86400 ) ) );
-        my $dayend = strftime( "%Y-%m-%d %H:%M",
-            gmtime( $time + ( 86399 - $time % 86400 ) ) );
+        $date->SetToMidnight( Timezone => 'server' );
+        my $daystart = $date->ISO;
+        $date->AddDay;
+        my $dayend = $date->ISO;
 
         $sb->_SQLLimit(
             ALIAS         => $sb->{_sql_transalias},
@@ -608,7 +603,7 @@
             ALIAS         => $sb->{_sql_transalias},
             FIELD         => 'Created',
             OPERATOR      => $op,
-            VALUE         => $value,
+            VALUE         => $date->ISO,
             CASESENSITIVE => 0,
             @rest
         );

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm	Fri Jun 16 18:02:52 2006
@@ -153,7 +153,13 @@
  
     my $id = $self->SUPER::Create(%params);
     $self->Load($id);
-    $self->_Attach( $args{'MIMEObj'} ) if defined $args{'MIMEObj'};
+    if ( defined $args{'MIMEObj'} ) {
+        my ($id, $msg) = $self->_Attach( $args{'MIMEObj'} );
+        unless ( $id ) {
+            $RT::Logger->error("Couldn't add attachment: $msg");
+            return ( 0, $self->loc("Couldn't add attachment") );
+        }
+    }
 
 
     #Provide a way to turn off scrips if we need to
@@ -477,11 +483,11 @@
     }
 
     my $Attachment = new RT::Attachment( $self->CurrentUser );
-    $Attachment->Create(
+    my ($id, $msg) = $Attachment->Create(
         TransactionId => $self->Id,
         Attachment    => $MIMEObject
     );
-    return ( $Attachment, $self->loc("Attachment created") );
+    return ( $Attachment, $msg || $self->loc("Attachment created") );
 
 }
 

Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/URI.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/URI.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/URI.pm	Fri Jun 16 18:02:52 2006
@@ -143,7 +143,7 @@
     
     unless ($self->Resolver->ParseURI($uri)) {
         $RT::Logger->warning("Resolver ".ref($self->Resolver)." could not parse $uri");
-        $self->{resolver} = undef; # clear resolver
+        $self->{resolver} = RT::URI::base->new( $self->CurrentUser ); # clear resolver
     	return (undef);
     }
 

Modified: rt/branches/3.7-EXPERIMENTAL/lib/t/regression/22search_tix_by_txn.t
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/t/regression/22search_tix_by_txn.t	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/t/regression/22search_tix_by_txn.t	Fri Jun 16 18:02:52 2006
@@ -1,6 +1,13 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
 #use Test::More tests => 26;
 use Test::More qw/no_plan/;
+
 $ENV{'TZ'} = 'GMT';
+
 use RT;
 RT::LoadConfig();
 RT::Init();
@@ -29,4 +36,5 @@
 
 $tix->FromSQL(qq{Updated = "2005-08-05" AND Subject = "$SUBJECT"});
 is( $tix->Count, 1);
-1;
+
+exit 0;

Added: rt/branches/3.7-EXPERIMENTAL/lib/t/regression/23-web_attachments.t
==============================================================================
--- (empty file)
+++ rt/branches/3.7-EXPERIMENTAL/lib/t/regression/23-web_attachments.t	Fri Jun 16 18:02:52 2006
@@ -0,0 +1,60 @@
+#!/usr/bin/perl -w
+use strict;
+
+use Test::More tests => 15;
+use RT;
+RT::LoadConfig;
+RT::Init;
+use Test::WWW::Mechanize;
+
+$RT::WebURL ||= 0; # avoid stupid warning
+my $BaseURL = $RT::WebURL;
+use constant LogoFile => $RT::MasonComponentRoot .'/NoAuth/images/bplogo.gif';
+use constant FaviconFile => $RT::MasonComponentRoot .'/NoAuth/images/favicon.png';
+
+my $queue_name = 'General';
+
+my $m = Test::WWW::Mechanize->new;
+isa_ok($m, 'Test::WWW::Mechanize');
+
+$m->get_ok( $BaseURL."?user=root;pass=password" );
+$m->content_like(qr/Logout/, 'we did log in');
+
+my $qid;
+{
+    $m->content =~ /<SELECT\s+NAME\s*="Queue">.*?<OPTION\s+VALUE="(\d+)"\s*\d*>\s*\Q$queue_name\E\s*<\/OPTION>/msi;
+    ok( $qid = $1, "found id of the '$queue_name' queue");
+}
+
+$m->form_number(1);
+$m->field('Queue', $qid);
+$m->submit;
+is($m->status, 200, "request successful");
+$m->content_like(qr/Create a new ticket/, 'ticket create page');
+
+$m->form('TicketCreate');
+$m->field('Subject', 'Attachments test');
+$m->field('Attach',  LogoFile);
+$m->field('Content', 'Some content');
+$m->submit;
+is($m->status, 200, "request successful");
+
+$m->content_like(qr/Attachments test/, 'we have subject on the page');
+$m->content_like(qr/Some content/, 'and content');
+$m->content_like(qr/Download bplogo\.gif/, 'page has file name');
+
+$m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
+$m->form('TicketUpdate');
+$m->field('Attach',  LogoFile);
+$m->click('AddMoreAttach');
+is($m->status, 200, "request successful");
+
+$m->form('TicketUpdate');
+$m->field('Attach',  FaviconFile);
+$m->field('UpdateContent', 'Message');
+$m->click('SubmitTicket');
+is($m->status, 200, "request successful");
+
+$m->content_like(qr/Download bplogo\.gif/, 'page has file name');
+$m->content_like(qr/Download favicon\.png/, 'page has file name');
+


More information about the Rt-commit mailing list