[Rt-commit] r7484 - in rt/branches/3.7-EXPERIMENTAL-TUNIS: .
html/Admin/Elements html/Admin/Queues html/Admin/Users
html/Prefs html/Ticket html/Ticket/Elements html/Widgets/Form
lib/RT lib/RT/Action lib/RT/Condition lib/RT/Crypt lib/RT/Interface
jesse at bestpractical.com
jesse at bestpractical.com
Tue Apr 10 16:46:25 EDT 2007
Author: jesse
Date: Tue Apr 10 16:46:22 2007
New Revision: 7484
Added:
rt/branches/3.7-EXPERIMENTAL-TUNIS/docs/using_forms_widgets.pod
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Elements/ShowKeyInfo
Modified:
rt/branches/3.7-EXPERIMENTAL-TUNIS/ (props changed)
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Queues/Modify.html
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Users/Modify.html
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Prefs/Other.html
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Create.html
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Elements/ShowTransaction
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Forward.html
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Boolean
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Integer
rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Select
rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Action/SendEmail.pm
rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Condition/OwnerChange.pm
rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Crypt/GnuPG.pm
rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Interface/Email.pm
rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Ticket_Overlay.pm
rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Tickets_Overlay.pm
Log:
r54305 at pinglin (orig r7378): ruz | 2007-03-27 20:01:17 -0400
r4823 at cubic-pc: cubic | 2007-03-28 04:01:01 +0400
* if we cache aliases then we should not apply limits multiple times
r54307 at pinglin (orig r7380): ruz | 2007-03-28 15:47:52 -0400
r4825 at cubic-pc: cubic | 2007-03-28 23:45:49 +0400
* add results to the forward page
r54321 at pinglin (orig r7381): ruz | 2007-03-29 11:03:47 -0400
r4827 at cubic-pc: cubic | 2007-03-29 02:18:46 +0400
* add GetPassphrase function
r54322 at pinglin (orig r7382): ruz | 2007-03-29 11:03:56 -0400
r4828 at cubic-pc: cubic | 2007-03-29 02:19:08 +0400
* update docs
r54323 at pinglin (orig r7383): ruz | 2007-03-29 11:04:05 -0400
r4829 at cubic-pc: cubic | 2007-03-29 10:40:47 +0400
* docs update
r54324 at pinglin (orig r7384): ruz | 2007-03-29 11:04:21 -0400
r4830 at cubic-pc: cubic | 2007-03-29 10:42:38 +0400
* use CamelCase args in SendEmail with backward compatibility
r54325 at pinglin (orig r7385): ruz | 2007-03-29 11:04:29 -0400
r4831 at cubic-pc: cubic | 2007-03-29 10:48:51 +0400
* pass the current ticket to mailer
r54326 at pinglin (orig r7386): ruz | 2007-03-29 11:04:40 -0400
r4832 at cubic-pc: cubic | 2007-03-29 10:49:26 +0400
* use camel case
r54327 at pinglin (orig r7387): ruz | 2007-03-29 11:04:55 -0400
r4833 at cubic-pc: cubic | 2007-03-29 10:50:24 +0400
* fetch ticket from transaction if the former is not provided
r54328 at pinglin (orig r7388): ruz | 2007-03-29 11:05:04 -0400
r4834 at cubic-pc: cubic | 2007-03-29 10:58:07 +0400
* if ticket is there and Queue dictates to sign or encrypt then
do it
r54329 at pinglin (orig r7389): ruz | 2007-03-29 11:05:21 -0400
r4835 at cubic-pc: cubic | 2007-03-29 17:43:28 +0400
* add GetPublicKeyInfo and helpers
r54330 at pinglin (orig r7390): ruz | 2007-03-29 11:05:31 -0400
r4836 at cubic-pc: cubic | 2007-03-29 17:43:54 +0400
* show user's public key if it's exists
r54331 at pinglin (orig r7391): ruz | 2007-03-29 11:52:48 -0400
r4847 at cubic-pc: cubic | 2007-03-29 19:10:50 +0400
* use an address as argument instead of an user's object
r54332 at pinglin (orig r7392): ruz | 2007-03-29 11:53:02 -0400
r4848 at cubic-pc: cubic | 2007-03-29 19:45:47 +0400
* parse info about private keys
r54333 at pinglin (orig r7393): ruz | 2007-03-29 11:53:12 -0400
r4849 at cubic-pc: cubic | 2007-03-29 19:47:03 +0400
* if trust char is empty then use '-' as substitution as
this value is closest one.
r54334 at pinglin (orig r7394): ruz | 2007-03-29 11:53:36 -0400
r4850 at cubic-pc: cubic | 2007-03-29 19:47:34 +0400
* add GetPrivateKeyInfo
r54335 at pinglin (orig r7395): ruz | 2007-03-29 11:54:11 -0400
r4851 at cubic-pc: cubic | 2007-03-29 19:47:58 +0400
* Elements/ShowPrivateKeyInfo
r54336 at pinglin (orig r7396): ruz | 2007-03-29 11:54:21 -0400
r4852 at cubic-pc: cubic | 2007-03-29 19:48:55 +0400
* show information about queue's private keys
r54337 at pinglin (orig r7397): ruz | 2007-03-29 11:54:28 -0400
r4853 at cubic-pc: cubic | 2007-03-29 19:52:25 +0400
* move ShowPublicKeyInfo
** sync it with ShowPrivateKeyInfo
r54338 at pinglin (orig r7398): ruz | 2007-03-29 21:27:05 -0400
r4865 at cubic-pc: cubic | 2007-03-30 05:12:16 +0400
* add _ParseDate
r54339 at pinglin (orig r7399): ruz | 2007-03-29 21:27:14 -0400
r4866 at cubic-pc: cubic | 2007-03-30 05:13:09 +0400
* add support for uid records in key lists
r54340 at pinglin (orig r7400): ruz | 2007-03-29 21:27:21 -0400
r4867 at cubic-pc: cubic | 2007-03-30 05:13:40 +0400
* parse dates
r54341 at pinglin (orig r7401): ruz | 2007-03-29 21:27:28 -0400
r4868 at cubic-pc: cubic | 2007-03-30 05:14:45 +0400
* use fixed-list-mode, so each user has own uid record
r54342 at pinglin (orig r7402): ruz | 2007-03-29 21:27:45 -0400
r4869 at cubic-pc: cubic | 2007-03-30 05:15:37 +0400
* update according to new API, now we support keys with multiple uids
r54343 at pinglin (orig r7403): ruz | 2007-03-29 21:28:03 -0400
r4870 at cubic-pc: cubic | 2007-03-30 05:23:11 +0400
* generalize comp for any type of keys
r54344 at pinglin (orig r7404): ruz | 2007-03-29 21:28:10 -0400
r4871 at cubic-pc: cubic | 2007-03-30 05:26:26 +0400
* use ShowKeyInfo for secret and public keys
r54486 at pinglin (orig r7446): ruz | 2007-04-04 17:50:24 -0400
r4879 at cubic-pc: cubic | 2007-04-03 18:29:01 +0400
* delete empty row in a table
r54487 at pinglin (orig r7447): ruz | 2007-04-04 17:50:33 -0400
r4880 at cubic-pc: cubic | 2007-04-03 18:35:59 +0400
* add Sign/Encrypt boxes to Create page
r54488 at pinglin (orig r7448): ruz | 2007-04-04 17:50:48 -0400
r4881 at cubic-pc: cubic | 2007-04-03 19:09:32 +0400
* call CanonicalizeEmailAddress as class method as we do in other places
r54489 at pinglin (orig r7449): ruz | 2007-04-04 17:51:04 -0400
r4882 at cubic-pc: cubic | 2007-04-04 02:26:41 +0400
* get rid of uninit warning
r54490 at pinglin (orig r7450): ruz | 2007-04-04 17:51:12 -0400
r4883 at cubic-pc: cubic | 2007-04-04 02:29:36 +0400
Boolean widget
* get rid of Boolean- prefix in name of field
* add InputOnly method
* use magic field trick to save a state of the checkbox
r54492 at pinglin (orig r7451): ruz | 2007-04-04 17:51:20 -0400
r4884 at cubic-pc: cubic | 2007-04-04 02:32:15 +0400
* use widgets for Sign and Encrypt args
r54493 at pinglin (orig r7452): ruz | 2007-04-04 17:51:38 -0400
r4885 at cubic-pc: cubic | 2007-04-04 02:33:20 +0400
* move field's comment into own cell
r54494 at pinglin (orig r7453): ruz | 2007-04-04 17:51:47 -0400
r4886 at cubic-pc: cubic | 2007-04-04 02:33:58 +0400
* tidy, before change
r54495 at pinglin (orig r7454): ruz | 2007-04-04 17:52:06 -0400
r4887 at cubic-pc: cubic | 2007-04-04 14:48:11 +0400
* add support for Empty option in Boolean widget.
display such widget with three radio buttons and Process method returns
0, 1 or undef if value is empty
r54496 at pinglin (orig r7455): ruz | 2007-04-04 17:52:14 -0400
r4888 at cubic-pc: cubic | 2007-04-04 14:53:45 +0400
* remove NamePrefix and make Name mandatory argument
r54497 at pinglin (orig r7456): ruz | 2007-04-04 17:52:32 -0400
r4889 at cubic-pc: cubic | 2007-04-04 14:58:36 +0400
* get rid of Integer- prefix in name
r54498 at pinglin (orig r7457): ruz | 2007-04-04 17:52:41 -0400
r4890 at cubic-pc: cubic | 2007-04-04 17:04:04 +0400
* make Name mandatory arg
* add InputOnly method
r54500 at pinglin (orig r7458): ruz | 2007-04-04 17:52:58 -0400
r4891 at cubic-pc: cubic | 2007-04-04 17:04:46 +0400
* fix empty value handling
r54501 at pinglin (orig r7459): ruz | 2007-04-04 17:53:07 -0400
r4892 at cubic-pc: cubic | 2007-04-04 17:33:13 +0400
* add InputOnly method
r54502 at pinglin (orig r7460): ruz | 2007-04-04 17:53:24 -0400
r4893 at cubic-pc: cubic | 2007-04-04 17:39:16 +0400
* in Widget/Form/*:Process rename CurrenValue argument to DefaultValue,
as old one is really confusing
r54503 at pinglin (orig r7461): ruz | 2007-04-04 17:53:35 -0400
r4894 at cubic-pc: cubic | 2007-04-05 01:38:20 +0400
* add docs for html/Widgets/Form/*
* use Default instead of Empty
r54504 at pinglin (orig r7462): ruz | 2007-04-04 17:53:57 -0400
r4895 at cubic-pc: cubic | 2007-04-05 01:38:42 +0400
* drop uninit warning
r54742 at pinglin (orig r7482): ruz | 2007-04-09 17:48:37 -0400
r4913 at cubic-pc: cubic | 2007-04-06 16:37:26 +0400
* force scalar context
Added: rt/branches/3.7-EXPERIMENTAL-TUNIS/docs/using_forms_widgets.pod
==============================================================================
--- (empty file)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/docs/using_forms_widgets.pod Tue Apr 10 16:46:22 2007
@@ -0,0 +1,113 @@
+=head1 Using widgets F<html/Widgets/Form*>
+
+This widgets was implemented to address several common issues in handling
+request arguments and allow developers to avoid reinventing the wheel.
+
+=head2 General info
+
+Each component shows widget by default and has two methods: Process and
+InputOnly. The first one method process arguments and return new value
+of a parametr. The second one is helper that shows only form elements
+with minimum of required text labels.
+
+So you show a widget with:
+ <& /Widgets/Form/Integer,
+ Name => 'NameOfInputElement',
+ Description => 'Input integer',
+ &>
+
+You can show only C<input> box using:
+ <& /Widgets/Form/Integer:InputOnly,
+ Name => 'NameOfInputElement',
+ &>
+
+In such a simple case you even can avoid processing. Yeah, most probably
+you want to check if value is really integer, but these widgets don't
+do validation for you, but they are more about fetching values from
+hash of arguments, showing these values to user and preserving state
+of value between form reloads (see below).
+
+=head2 Processing
+
+Processing is required when you use L<extended features|/Extendent features>,
+such as Default, Multiple or Alternative.
+
+To process arguments of a request you have to do the following:
+ $ARGS{'NameOfInputElement'} = $m->comp(
+ '/Widgets/Form/Integer:Process',
+ Arguments => \%ARGS,
+ Name => 'NameOfInputElement',
+ );
+
+The method returns processed value in canonical form. For different widgets
+a canonical form is different and depends on activated features, so you must
+always activate the same features during showing a widget and processing
+results.
+
+=head2 Extendent features
+
+=head3 Default value
+
+If C<Default> argument is true then widgets expect that there is some
+default value for argument if user fills nothing. 'Nothing' in each
+widget is different, for example in select box it's special option
+which is always the first one, in integer box string '' means empty
+value, but boolean box uses radio buttons in this case with three
+options: Yes, No and Default.
+
+Each widget that supports C<Default> feature as well has C<DefaultLabel> and
+C<DefaultValue> arguments.
+
+=head4 Processing and showing with activated Default feature
+
+When this option is activated then C<Process> method returns undef
+value if user selected default value. So for integer box it's empty
+string and so on.
+
+As well when you show a widget you should pass undef as C<CurrentValue>
+to inform widget that the current value is default one.
+
+As all methods of a widget are consistent in this behaviour so you
+shouldn't care much about that, but this allows you to implement
+custom actions if processing returned undef, for example delete user's
+preference record instead of updating it (default value may change later to).
+
+=head4 C<DefaultValue> when C<Default> is not active
+
+DefaultValue argument is still actual in the Process method even if
+C<Default> is not true. This argument defines intial value. If value
+of a key in Arguments is not defined then it's treated as intial state
+and the method returns default value.
+
+=head3 Multiple and Alternative
+
+These options are only supported by the select widget.
+
+TODO: Add more info
+
+=head2 Implementation details
+
+=head3 Boolean widget
+
+This widget a little bit tricky. When you use Default option then
+things are simple and you see three radio buttons, but in other
+case we use a checkbox. But as you know browsers don't pass unchecked
+boxes to server, so arguments of a request has no entry for them.
+
+In the latter case it's hard to figure out case when user unselected
+value. Imagine form with a checkbox, you want show it checked by
+default and as well form is reloadable (like Reply forms that have
+"Add Another File" buttons). User uncheck the box and then upload
+file, in this case you want to show user's choice instead of default,
+but browser doesn't send any value and you can not figure out if
+it's initial state or page reload. To solve this problem we use magic
+hidden input field with the same name as the box and value equal to
+zero (0). Mason folds arguments with the same name into array refs, so
+we get 0 if box is unchecked and [0, 1] if box is checked. An array
+reference is true value and 0 is defined value so we know that it's
+not initial state and avoid switching back to default. As well this
+trick works good in a case when you want show a link to a page and
+define default choice for some boolean argument, you don't need
+to set argument twice, you just set it to true value (for ex. 1) and
+things just work.
+
Added: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Elements/ShowKeyInfo
==============================================================================
--- (empty file)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Elements/ShowKeyInfo Tue Apr 10 16:46:22 2007
@@ -0,0 +1,44 @@
+<&| /Widgets/TitleBox, title => $title &>
+% if ( $res{'exit_code'} || !keys %{ $res{'info'} } ) {
+<% loc('No keys for this address') %>
+% } else {
+<table>
+
+% unless ( $Type eq 'private' ) {
+<tr><th><% loc('Trust') %>:</th> <td><% loc( $res{'info'}{'Trust'} ) %></td></tr>
+% }
+
+<tr><th><% loc('Created') %>:</th>
+<td><% $res{'info'}{'Created'}? $res{'info'}{'Created'}->AsString( Time => 0 ): loc('never') %></td></tr>
+
+<tr><th><% loc('Expire') %>:</th>
+<td><% $res{'info'}{'Expire'}? $res{'info'}{'Expire'}->AsString( Time => 0 ): loc('never') %></td></tr>
+
+% foreach my $uinfo( @{ $res{'info'}{'User'} } ) {
+<tr><th><% loc('User (created - expire)') %>:</th>
+<td><% $uinfo->{'String'} %>\
+(<% $uinfo->{'Created'}->AsString( Time => 0 ) %> - \
+<% $uinfo->{'Expire'}? $uinfo->{'Expire'}->AsString( Time => 0 ): loc('never') %>)
+</td></tr>
+% }
+
+</table>
+% }
+</&>
+
+<%ARGS>
+$EmailAddress
+$Type => 'public'
+</%ARGS>
+<%INIT>
+require RT::Crypt::GnuPG;
+my %res = RT::Crypt::GnuPG::GetKeyInfo( $EmailAddress, $Type );
+
+my $title;
+unless ( $Type eq 'private' ) {
+ $title = loc('GnuPG public key(s) for [_1]', $EmailAddress);
+} else {
+ $title = loc('GnuPG private key(s) for [_1]', $EmailAddress);
+}
+
+</%INIT>
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Queues/Modify.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Queues/Modify.html (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Queues/Modify.html Tue Apr 10 16:46:22 2007
@@ -94,6 +94,13 @@
% $m->callback( %ARGS, QueueObj => $QueueObj, results => \@results );
</td></tr>
+% if ( my $email = $QueueObj->CorrespondAddress || RT->Config->Get('CorrespondAddress') ) {
+<tr><td colspan="4"><& /Admin/Elements/ShowKeyInfo, Type => 'private', EmailAddress => $email &></td></tr>
+% }
+% if ( my $email = $QueueObj->CommentAddress || RT->Config->Get('CommentAddress') ) {
+<tr><td colspan="4"><& /Admin/Elements/ShowKeyInfo, Type => 'private', EmailAddress => $email &></td></tr>
+% }
+
</table>
<& /Elements/Submit, Label => loc('Save Changes') &>
</form>
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Users/Modify.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Users/Modify.html (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Admin/Users/Modify.html Tue Apr 10 16:46:22 2007
@@ -232,6 +232,10 @@
</&>
% }
+% if ( my $email = $UserObj->EmailAddress ) {
+<& /Admin/Elements/ShowKeyInfo, EmailAddress => $email &>
+% }
+
</td>
</tr>
</table>
@@ -373,7 +377,7 @@
}
-# {{{ Do some setup for the ui
+# Do some setup for the ui
unless ( $UserObj->id && $UserObj->Disabled ) {
$EnabledChecked ="CHECKED";
}
@@ -382,8 +386,6 @@
$PrivilegedChecked = "CHECKED";
}
-# }}}
-
# set the id, so the the menu will have the right info, this needs to
# be done here to avoid creating and then modifying a user
$id = $UserObj->Id;
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Prefs/Other.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Prefs/Other.html (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Prefs/Other.html Tue Apr 10 16:46:22 2007
@@ -11,10 +11,10 @@
% foreach my $option( RT->Config->Options( Section => $section ) ) {
% my $meta = RT->Config->Meta( $option );
<& $meta->{'Widget'},
- Empty => 1,
+ Default => 1,
%{ $localize_meta->( $meta->{'WidgetArguments'} ) },
Name => $option,
- EmptyValue => scalar RT->Config->Get( $option ),
+ DefaultValue => scalar RT->Config->Get( $option ),
CurrentValue => $preferences->{ $option },
&>
% }
@@ -35,11 +35,10 @@
my $meta = RT->Config->Meta( $option );
my $value = $m->comp($meta->{'Widget'} .":Process",
Arguments => \%ARGS,
- Empty => 1,
+ Default => 1,
%{ $meta->{'WidgetArguments'} },
Name => $option,
- EmptyValue => scalar RT->Config->Get( $option ),
- CurrentValue => $preferences->{ $option },
+ DefaultValue => scalar RT->Config->Get( $option ),
);
if ( defined $value ) {
$preferences->{ $option } = $value;
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Create.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Create.html (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Create.html Tue Apr 10 16:46:22 2007
@@ -87,9 +87,8 @@
<td class="labeltop">
<&|/l&>Cc</&>:
</td>
-<td class="value" colspan="5">
-<input name="Cc" size="40" value="<% $ARGS{Cc} %>" /><br />
-<i><font size="-2">
+<td class="value" colspan="3"><input name="Cc" size="40" value="<% $ARGS{Cc} %>" /></td>
+<td class="comment" colspan="2"><i><font size="-2">
<&|/l&>(Sends a carbon-copy of this update to a comma-delimited list of email addresses. These people <strong>will</strong> receive future updates.)</&></font></i>
</td>
</tr>
@@ -97,9 +96,8 @@
<td class="labeltop">
<&|/l&>Admin Cc</&>:
</td>
-<td class="value" colspan="5">
-<input name="AdminCc" size="40" value="<% $ARGS{AdminCc} %>" /><br />
-<i><font size="-2">
+<td class="value" colspan="3"><input name="AdminCc" size="40" value="<% $ARGS{AdminCc} %>" /></td>
+<td class="comment" colspan="2"><i><font size="-2">
<&|/l&>(Sends a carbon-copy of this update to a comma-delimited list of administrative email addresses. These people <strong>will</strong> receive future updates.)</&></font></i>
</td>
</tr>
@@ -147,6 +145,15 @@
<input type="submit" class="button" name="AddMoreAttach" value="<&|/l&>Add More Files</&>" />
</td>
</tr>
+
+<tr>
+<td><% loc('Sign')%></td>
+<td><& /Widgets/Form/Boolean:InputOnly, Name => 'Sign', CurrentValue => $ARGS{'Sign'} &></td>
+<td><% loc('Encrypt')%></td>
+<td><& /Widgets/Form/Boolean:InputOnly, Name => 'Encrypt', CurrentValue => $ARGS{'Encrypt'} &></td>
+<td colspan="2"> </td>
+</tr>
+
<tr>
<td colspan="6">
<&|/l&>Describe the issue below</&>:<br />
@@ -159,10 +166,6 @@
<br />
</td>
</tr>
-<tr>
-<td align="right" colspan="2">
-</td>
-</tr>
</table>
</&>
<& /Elements/Submit, Label => loc("Create")&>
@@ -253,6 +256,14 @@
ARGSRef => \%ARGS
);
+foreach ( qw(Sign Encrypt) ) {
+ $ARGS{ $_ } = $m->comp( '/Widgets/Form/Boolean:Process',
+ Name => $_,
+ CurrentValue => $QueueObj->$_,
+ Arguments => \%ARGS,
+ );
+}
+
# if no due date has been set explicitly, then use the
# queue's default if it exists
if ($QueueObj->DefaultDueIn && !$ARGS{'Due'}) {
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Elements/ShowTransaction
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Elements/ShowTransaction (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Elements/ShowTransaction Tue Apr 10 16:46:22 2007
@@ -113,7 +113,7 @@
my $transdate = $Transaction->CreatedAsString();
$transdate =~ s/\s/ /g;
-my ($type, $field) = ($Transaction->Type, $Transaction->Field);
+my ($type, $field) = ($Transaction->Type, $Transaction->Field || '');
my $type_class = $class{ $type };
unless ( $type_class ) {
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Forward.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Forward.html (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Ticket/Forward.html Tue Apr 10 16:46:22 2007
@@ -3,6 +3,7 @@
Ticket => $TicketObj,
Title => $Title,
&>
+<& /Elements/ListActions, actions => \@results &>
<form action="Forward.html" name="ForwardMessage" method="post">
% $m->callback( CallbackName => 'FormStart', ARGSRef => \%ARGS );
@@ -39,9 +40,11 @@
Abort( loc("Couldn't load transaction #[_1]", $QuoteTransaction) )
unless $txn->id;
+my @results;
if ( $ARGS{'Forward'} ) {
require RT::Interface::Email;
- RT::Interface::Email::ForwardTransaction( $txn, %ARGS );
+ my ($status, $msg) = RT::Interface::Email::ForwardTransaction( $txn, %ARGS );
+ push @results, $msg;
}
my $Title = loc('Forward message');
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Boolean
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Boolean (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Boolean Tue Apr 10 16:46:22 2007
@@ -1,26 +1,54 @@
+<%DOC>
+see docs/using_forms_widgets.pod
+</%DOC>
<div id="form-box-<% lc $Name %>">
-<span class="description"><% $Description %></span>:
-<input type="checkbox" name="Boolean-<% $Name %>" <% $value && 'checked' %>" />
+<span class="description"><% $Description %></span>:\
+<& SELF:InputOnly, %ARGS &>
</div>
-<%INIT>
-my $value = defined $CurrentValue ? $CurrentValue : $EmptyValue;
-</%INIT>
<%ARGS>
$Name => undef,
$Description => undef,
-$EmptyValue => 0,
+</%ARGS>
+
+<%METHOD InputOnly>
+<%ARGS>
+$Name => undef,
+
+$Default => 0,
+$DefaultValue => 0,
+$DefaultLabel => loc( 'Use system default ([_1])', $DefaultValue? loc('Yes'): loc('No') ),
+
$CurrentValue => undef,
</%ARGS>
+% unless ( $Default ) {
+<input type="hidden" name="<% $Name %>" value="0" />\
+<input type="checkbox" name="<% $Name %>" <% $CurrentValue? 'checked="checked"': '' %> />\
+% } else {
+<input type="radio" name="<% $Name %>" value="1" <% $CurrentValue? 'checked="checked"': '' %> />\
+<% loc('Yes') %>
+<input type="radio" name="<% $Name %>" value="0" <% defined $CurrentValue && !$CurrentValue? 'checked="checked"': '' %> />\
+<% loc('No') %>
+<input type="radio" name="<% $Name %>" value="__empty_value__" <% !defined $CurrentValue? 'checked="checked"': '' %> />\
+<% $DefaultLabel %>
+% }
+</%METHOD>
<%METHOD Process>
<%ARGS>
+$Name
$Arguments => {},
-$Name => undef,
-$CurrentValue => 0,
+$Default => 0,
+$DefaultValue => 0,
</%ARGS>
<%INIT>
-return $Arguments->{ "Boolean-$Name" }? 1: 0;
+my $value = $Arguments->{ $Name };
+if ( $Default ) {
+ return undef if !defined $value || $value eq '__empty_value__';
+ return $value? 1: 0;
+} else {
+ return $value? 1: 0 if defined $value;
+ return $DefaultValue;
+}
</%INIT>
</%METHOD>
-
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Integer
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Integer (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Integer Tue Apr 10 16:46:22 2007
@@ -1,35 +1,48 @@
+<%DOC>
+see docs/using_forms_widgets.pod
+</%DOC>
<div id="form-box-<% lc $Name %>">
-<span class="description"><% $Description %></span>:
-<input type="text" name="Integer-<% $Name %>" value="<% $CurrentValue || '' %>" />
-% if ( $Empty ) {
-<span class="comment"><% $EmptyLabel %></span>
+<span class="description"><% $Description %></span>:\
+<& SELF:InputOnly, %ARGS &>
+% if ( $Default ) {
+<span class="comment"><% $DefaultLabel %></span>
% }
</div>
<%INIT>
</%INIT>
<%ARGS>
-$Name => undef,
+$Name
+
$Description => undef,
$CurrentValue => '',
-$Empty => 0,
-$EmptyValue => 0,
-$EmptyLabel => loc( 'Leaving this empty will default to the system default of [_1]', $EmptyValue ),
+$Default => 0,
+$DefaultValue => 0,
+$DefaultLabel => loc( 'Leaving this empty will default to the system default of [_1]', $DefaultValue ),
+</%ARGS>
+
+<%METHOD InputOnly>
+<input type="text" name="<% $Name %>" value="<% $CurrentValue || '' %>" />\
+<%ARGS>
+$Name
+$CurrentValue => '',
</%ARGS>
+</%METHOD>
<%METHOD Process>
<%ARGS>
+$Name
+
$Arguments => {},
-$Name => undef,
-$CurrentValue => '',
-$Empty => 0,
+$Default => 0,
+$DefaultValue => '',
</%ARGS>
<%INIT>
-my $value = $Arguments->{ "Integer-$Name" };
+my $value = $Arguments->{ $Name };
if ( !defined $value || $value eq '' ) {
- return $CurrentValue unless $Empty;
+ return $DefaultValue unless $Default;
return undef;
}
return $value;
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Select
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Select (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/html/Widgets/Form/Select Tue Apr 10 16:46:22 2007
@@ -1,30 +1,59 @@
+<%DOC>
+see docs/using_forms_widgets.pod
+</%DOC>
<div id="form-box-<% lc $Name %>">
% if ( $Description ) {
-<% $Description %>:
+<% $Description %>:\
% }
-<select name="<% $NamePrefix %><% $Name %>">
+<& SELF:InputOnly, %ARGS &>
+</div>
+<%ARGS>
+$Name
+$Description => undef,
+</%ARGS>
+
+<%METHOD InputOnly>
+<%ARGS>
+$Name
+$Description => undef,
+
+ at Values => (),
+$ValuesCallback => undef,
+%ValuesLabel => (),
+ at CurrentValue => (),
+
+$Default => 1,
+ at DefaultValue => (),
+$DefaultLabel => loc('Use system default ([_1])', join ', ', @DefaultValue),
+
+$Alternative => 0,
+$AlternativeLabel => loc('other...'),
-% if ( $Empty ) {
+$Multiple => 0,
+</%ARGS>
+<select name="<% $Name %>">
+
+% if ( $Default ) {
% my $selected = '';
-% $selected = 'selected' unless @CurrentValue;
-<option value="__empty_value__" <% $selected %>><% $EmptyLabel %></option>
+% $selected = 'selected="selected"' unless @CurrentValue;
+<option value="__empty_value__" <% $selected |n %>><% $DefaultLabel %></option>
% }
% foreach my $v( @Values ) {
% my $selected = '';
-% $selected = 'selected' if delete $CurrentValue{ $v };
-<option value="<% $v %>" <% $selected %>><% $ValuesLabel{ $v } || $v %></option>
+% $selected = 'selected="selected"' if delete $CurrentValue{ $v };
+<option value="<% $v %>" <% $selected |n %>><% $ValuesLabel{ $v } || $v %></option>
% }
% if ( $Alternative ) {
% my $selected = '';
-% $selected = 'selected' if keys %CurrentValue;
-<option value="__alternative_value__" <% $selected %>><% $AlternativeLabel %></option>
+% $selected = 'selected="selected"' if keys %CurrentValue;
+<option value="__alternative_value__" <% $selected |n %>><% $AlternativeLabel %></option>
% }
</select>
% if ( $Alternative ) {
-<input type="text" class="alternative" name="<% $NamePrefix %>Alternative-<% $Name %>" value="<% join ', ', @CurrentValue %>" />
+<input type="text" class="alternative" name="Alternative-<% $Name %>" value="<% join ', ', @CurrentValue %>" />
% }
</div>
<%INIT>
@@ -32,7 +61,6 @@
if ( $ValuesCallback ) {
my $values = $ValuesCallback->(
CurrentUser => $session{'CurrentUser'},
- NamePrefix => $NamePrefix,
Name => $Name,
);
if ( ref $values eq 'ARRAY' ) {
@@ -43,54 +71,34 @@
}
}
</%INIT>
-<%ARGS>
-$NamePrefix => 'Select-',
-$Name => '',
-$Description => undef,
-
- at Values => (),
-$ValuesCallback => undef,
-%ValuesLabel => (),
- at CurrentValue => (),
-
-$Empty => 1,
- at EmptyValue => (),
-$EmptyLabel => loc('Use system default ([_1])', join ', ', @EmptyValue),
-
-$Alternative => 0,
-$AlternativeLabel => loc('other...'),
-
-$Multiple => 0,
-</%ARGS>
+</%METHOD>
<%METHOD Process>
<%ARGS>
-$Arguments => {},
+$Name
-$NamePrefix => 'Select-',
-$Name => undef,
+$Arguments => {},
@Values => (),
%ValuesLabel => (),
- at CurrentValue => (),
-$Empty => 1,
+$Default => 0,
+ at DefaultValue => (),
+
$Alternative => 0,
$Multiple => 0,
</%ARGS>
<%INIT>
-my $value = $Arguments->{ $NamePrefix . $Name };
+my $value = $Arguments->{ $Name };
if( !defined $value || $value eq '__empty_value__' ) {
- unless ( $Empty ) {
- return [ @CurrentValue ] if $Multiple;
- return $CurrentValue[0];
- }
- return undef;
+ return undef if $Default;
+ return [ @DefaultValue ] if $Multiple;
+ return $DefaultValue[0];
}
$value = [$value] unless ref $value;
if ( $Alternative ) {
- my $alt = $Arguments->{ $NamePrefix ."Alternative-". $Name };
+ my $alt = $Arguments->{ "Alternative-". $Name };
if( $Multiple ) {
push @$value, split /\s*,\s*/, $alt;
} else {
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Action/SendEmail.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Action/SendEmail.pm (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Action/SendEmail.pm Tue Apr 10 16:46:22 2007
@@ -250,8 +250,9 @@
}
return(0) unless RT::Interface::Email::SendEmail(
- entity => $MIMEObj,
- transaction => $self->TransactionObj,
+ Entity => $MIMEObj,
+ Ticket => $self->TicketObj,
+ Transaction => $self->TransactionObj,
);
my $success = $msgid . " sent ";
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Condition/OwnerChange.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Condition/OwnerChange.pm (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Condition/OwnerChange.pm Tue Apr 10 16:46:22 2007
@@ -64,7 +64,7 @@
sub IsApplicable {
my $self = shift;
- if ($self->TransactionObj->Field eq 'Owner') {
+ if ( ( $self->TransactionObj->Field || '' ) eq 'Owner' ) {
return(1);
}
else {
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Crypt/GnuPG.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Crypt/GnuPG.pm (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Crypt/GnuPG.pm Tue Apr 10 16:46:22 2007
@@ -35,9 +35,18 @@
verbose
);
-=head2 SignEncrypt Entity => MIME::Entity, [ Encrypt => 1, Sign => 1, Passphrase => '' ]
+=head2 SignEncrypt Entity => MIME::Entity, [ Encrypt => 1, Sign => 1, Passphrase => undef ]
-Sign and/or encrypt email message with GnuPG.
+Signs and/or encrypts an email message with GnuPG utility. A passphrase is required
+only during signing.
+
+Returns a hash with the follwoing keys:
+
+* exit_code
+* error
+* logger
+* status
+* message
=cut
@@ -51,6 +60,10 @@
);
my $entity = $args{'Entity'};
+ if ( $args{'Sign'} && !defined $args{'Passphrase'} ) {
+ $args{'Passphrase'} = GetPassphrase();
+ }
+
my $gnupg = new GnuPG::Interface;
my %opt = RT->Config->Get('GnuPG');
$opt{'digest-algo'} ||= 'SHA1';
@@ -471,7 +484,13 @@
}
sub DecryptRFC3156 {
- my %args = ( Data => undef, Info => undef, Top => undef, Passphrase => undef, @_ );
+ my %args = (
+ Data => undef,
+ Info => undef,
+ Top => undef,
+ Passphrase => undef,
+ @_
+ );
my $gnupg = new GnuPG::Interface;
my %opt = RT->Config->Get('GnuPG');
@@ -481,6 +500,9 @@
meta_interactive => 0,
);
+ $args{'Passphrase'} = GetPassphrase()
+ unless defined $args{'Passphrase'};
+
my ($tmp_fh, $tmp_fn) = File::Temp::tempfile();
binmode $tmp_fh, ':raw';
@@ -530,6 +552,10 @@
return %res;
}
+sub GetPassphrase {
+ return undef;
+}
+
my %inv_recp_reason = (
0 => "No specific reason given",
1 => "Not Found",
@@ -683,7 +709,19 @@
}
foreach my $line ( @status[ $i .. $#status ] ) {
next unless $line =~ /^VALIDSIG\s+(.*)/;
- @res{ qw(Fingerprint CreationDate Timestamp ExpireTimestamp Version Reserved PubkeyAlgo HashAlgo Class PKFingerprint Other) } = split /\s+/, $1, 11;
+ @res{ qw(
+ Fingerprint
+ CreationDate
+ Timestamp
+ ExpireTimestamp
+ Version
+ Reserved
+ PubkeyAlgo
+ HashAlgo
+ Class
+ PKFingerprint
+ Other
+ ) } = split /\s+/, $1, 10;
last;
}
push @res, \%res;
@@ -775,6 +813,158 @@
return %res;
}
+sub GetPublicKeyInfo {
+ return GetKeyInfo(shift, 'public');
+}
+
+sub GetPrivateKeyInfo {
+ return GetKeyInfo(shift, 'private');
+}
+
+sub GetKeyInfo {
+ my $email = shift;
+ my $type = shift || 'public';
+
+ my $gnupg = new GnuPG::Interface;
+ my %opt = RT->Config->Get('GnuPG');
+ $opt{'digest-algo'} ||= 'SHA1';
+ $opt{'with-colons'} = undef; # parseable format
+ $opt{'fixed-list-mode'} = undef; # don't merge uid with keys
+ $gnupg->options->hash_init(
+ _PrepareGnuPGOptions( %opt ),
+ armor => 1,
+ meta_interactive => 0,
+ );
+
+ my %res;
+
+ my %handle;
+ my $handles = GnuPG::Handles->new(
+ stdout => ($handle{'output'} = new IO::Handle),
+ stderr => ($handle{'error'} = new IO::Handle),
+ logger => ($handle{'logger'} = new IO::Handle),
+ status => ($handle{'status'} = new IO::Handle),
+ );
+
+ eval {
+ local $SIG{'CHLD'} = 'DEFAULT';
+ local @ENV{'LANG', 'LC_ALL'} = ('C', 'C');
+ my $method = $type eq 'private'? 'list_secret_keys': 'list_public_keys';
+ my $pid = $gnupg->$method( handles => $handles, command_args => [ $email ] );
+ waitpid $pid, 0;
+ };
+
+ my @info = readline $handle{'output'};
+ use Data::Dumper; $RT::Logger->error( Dumper(\@info) );
+
+ close $handle{'output'};
+
+ $res{'exit_code'} = $?;
+ foreach ( qw(error logger status) ) {
+ $res{$_} = do { local $/; readline $handle{$_} };
+ delete $res{$_} unless $res{$_} && $res{$_} =~ /\S/s;
+ close $handle{$_};
+ }
+ $RT::Logger->debug( $res{'status'} ) if $res{'status'};
+ $RT::Logger->warning( $res{'error'} ) if $res{'error'};
+ $RT::Logger->error( $res{'logger'} ) if $res{'logger'} && $?;
+ if ( $@ || $? ) {
+ $res{'message'} = $@? $@: "gpg exitted with error code ". ($? >> 8);
+ return %res;
+ }
+
+ @info = ParseKeysInfo( @info );
+ $res{'info'} = $info[0];
+ return %res;
+}
+
+sub ParseKeysInfo {
+ my @lines = @_;
+
+ my @res = ();
+ foreach my $line( @lines ) {
+ chomp $line;
+ my ($tag, $line) = split /:/, $line, 2;
+ if ( $tag eq 'pub' ) {
+ my %info;
+ @info{ qw(
+ Trust KeyLenght Algorithm Key
+ Created Expire Empty OwnerTrust
+ Empty Empty KeyCapabilities Other
+ ) } = split /:/, $line, 12;
+ $info{'Trust'} = _ConvertTrustChar( $info{'Trust'} );
+ $info{'OwnerTrust'} = _ConvertTrustChar( $info{'OwnerTrust'} );
+ $info{ $_ } = _ParseDate( $info{ $_ } )
+ foreach qw(Created Expire);
+ push @res, \%info;
+ }
+ elsif ( $tag eq 'sec' ) {
+ my %info;
+ @info{ qw(
+ Empty KeyLenght Algorithm Key
+ Created Expire Empty OwnerTrust
+ Empty Empty KeyCapabilities Other
+ ) } = split /:/, $line, 12;
+ $info{'OwnerTrust'} = _ConvertTrustChar( $info{'OwnerTrust'} );
+ $info{ $_ } = _ParseDate( $info{ $_ } )
+ foreach qw(Created Expire);
+ push @res, \%info;
+ }
+ elsif ( $tag eq 'uid' ) {
+ my %info;
+ @info{ qw(Trust Created Expire String) }
+ = (split /:/, $line)[0,4,5,8];
+ $info{ $_ } = _ParseDate( $info{ $_ } )
+ foreach qw(Created Expire);
+ push @{ $res[-1]{'User'} ||= [] }, \%info;
+ }
+ elsif ( $tag eq 'fpr' ) {
+ $res[-1]{'Fingerprint'} = (split /:/, $line, 10)[8];
+ }
+ }
+ return @res;
+}
+
+{
+ my %mapping = (
+ o => 'Unknown (this value is new to the system)', #loc
+ # deprecated
+ d => "The key has been disabled", #loc
+ r => "The key has been revoked", #loc
+ e => "The key has expired", #loc
+ '-' => 'Unknown (no trust value assigned)', #loc
+ #gpupg docs says that '-' and 'q' may safely be treated as the same value
+ q => 'Unknown (no trust value assigned)', #loc
+ n => "Don't trust this key at all", #loc
+ m => "There is marginal trust in this key", #loc
+ f => "The key is fully trusted", #loc
+ u => "The key is ultimately trusted", #loc
+ );
+ sub _ConvertTrustChar {
+ my $value = shift;
+ return $mapping{'-'} unless $value;
+
+ $value = substr $value, 0, 1;
+ return $mapping{ $value } || $mapping{'o'};
+ }
+}
+
+sub _ParseDate {
+ my $value = shift;
+ # never
+ return $value unless $value;
+
+ require RT::Date;
+ my $obj = RT::Date->new( $RT::SystemUser );
+ # unix time
+ if ( $value =~ /^\d+$/ ) {
+ $obj->Set( Value => $value );
+ } else {
+ $obj->Set( Format => 'unknown', Value => $value, Timezone => 'utc' );
+ }
+ return $obj;
+}
+
1;
# helper package to avoid using temp file
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Interface/Email.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Interface/Email.pm (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Interface/Email.pm Tue Apr 10 16:46:22 2007
@@ -99,8 +99,9 @@
=head2 CheckForLoops HEAD
-Returns true if the message's been sent by this RT instance.
-Uses "X-RT-Loop-Prevention" field of the head for that.
+Takes a HEAD object of L<MIME::Head> class and returns true if the
+message's been sent by this RT instance. Uses "X-RT-Loop-Prevention"
+field of the head for test.
=cut
@@ -121,7 +122,8 @@
=head2 CheckForSuspiciousSender HEAD
-Returns true if sender is suspicious. Suspicious means mailer daemon.
+Takes a HEAD object of L<MIME::Head> class and returns true if sender
+is suspicious. Suspicious means mailer daemon.
See also L</ParseSenderAddressFromHead>.
@@ -151,8 +153,9 @@
=head2 CheckForAutoGenerated HEAD
-Returns true if message is autogenerated. Checks 'Precedence'
-and 'X-FC-Machinegenerated' fields of the head.
+Takes a HEAD object of L<MIME::Head> class and returns true if message
+is autogenerated. Checks 'Precedence' and 'X-FC-Machinegenerated'
+fields of the head in tests.
=cut
@@ -262,6 +265,7 @@
level => $args{'LogLevel'},
message => $args{'Explanation'}
) if $args{'LogLevel'};
+
my $entity = MIME::Entity->build(
Type => "multipart/mixed",
From => $args{'From'},
@@ -269,7 +273,7 @@
To => $args{'To'},
Subject => $args{'Subject'},
Precedence => 'bulk',
- 'X-RT-Loop-Prevention' => RT->Config->Get('rtname'),
+ 'X-RT-Loop-Prevention' => scalar RT->Config->Get('rtname'),
'In-Reply-To:' => $args{'MIMEObj'} ? $args{'MIMEObj'}->head->get('Message-Id') : undef,
);
@@ -285,38 +289,68 @@
}
- SendEmail(entity => $entity, bounce => 1);
+ SendEmail( Entity => $entity, Bounce => 1 );
}
-=head2 SendEmail entity => ENTITY, [bounce => BOUNCE]
+=head2 SendEmail Entity => undef, [ Bounce => 0, Ticket => undef, Transaction => undef ]
Sends an email (passed as a L<MIME::Entity> object C<ENTITY>) using
-RT's outgoing mail configuration. If C<BOUNCE> is passed, and is a
+RT's outgoing mail configuration. If C<BOUNCE> is passed, and is a
true value, the message will be marked as an autogenerated error, if
possible.
+Sets Date field of the head to now if it's not set.
+
=cut
sub SendEmail {
my (%args) = (
- entity => undef,
- bounce => 0,
+ Entity => undef,
+ Bounce => 0,
+ Ticket => undef,
+ Transaction => undef,
@_,
);
- unless ( $args{'entity'} ) {
- $RT::Logger->crit( "Could not send mail without 'entity' object" );
+ foreach my $arg( qw(Entity Bounce) ) {
+ next unless defined $args{ lc $arg };
+
+ $RT::Logger->warning("'". lc($arg) ."' argument is deprecated, use '$arg' instead");
+ $args{ $arg } = delete $args{ lc $arg };
+ }
+
+ unless ( $args{'Entity'} ) {
+ $RT::Logger->crit( "Could not send mail without 'Entity' object" );
return 0;
}
- my $msgid = $args{'entity'}->head->get('Message-ID') || '';
+ if ( $args{'Transaction'} && !$args{'Ticket'}
+ && $args{'Transaction'}->ObjectType eq 'RT::Ticket' )
+ {
+ $args{'Ticket'} = $args{'Transaction'}->Object;
+ }
+
+ if ( $args{'Ticket'} ) {
+ my $sign = $args{'Ticket'}->QueueObj->Sign;
+ my $encrypt = $args{'Ticket'}->QueueObj->Encrypt;
+ if ( $sign || $encrypt ) {
+ require RT::Crypt::GnuPG;
+ my %res = RT::Crypt::GnuPG::SignEncrypt(
+ Entity => $args{'Entity'},
+ Sign => $sign, Encrypt => $encrypt,
+ );
+ return 0 if $res{'exit_code'};
+ }
+ }
+
+ my $msgid = $args{'Entity'}->head->get('Message-ID') || '';
chomp $msgid;
- unless ( $args{'entity'}->head->get('Date') ) {
+ unless ( $args{'Entity'}->head->get('Date') ) {
require RT::Date;
my $date = RT::Date->new( $RT::SystemUser );
$date->SetToNow;
- $args{'entity'}->head->set( 'Date', $date->RFC2822( Timezone => 'server' ) );
+ $args{'Entity'}->head->set( 'Date', $date->RFC2822( Timezone => 'server' ) );
}
my $mail_command = RT->Config->Get('MailCommand');
@@ -324,14 +358,14 @@
if ( $mail_command eq 'sendmailpipe' ) {
my $path = RT->Config->Get('SendmailPath');
my $args = RT->Config->Get('SendmailArguments');
- $args .= ' '. RT->Config->Get('SendmailBounceArguments') if $args{'bounce'};
+ $args .= ' '. RT->Config->Get('SendmailBounceArguments') if $args{'Bounce'};
# VERP
- if ( $args{'transaction'} and
+ if ( $args{'Transaction'} and
my $prefix = RT->Config->Get('VERPPrefix') and
my $domain = RT->Config->Get('VERPDomain') )
{
- my $from = $args{'transaction'}->CreatorObj->EmailAddress;
+ my $from = $args{'Transaction'}->CreatorObj->EmailAddress;
$from =~ s/@/=/g;
$from =~ s/\s//g;
$args .= " -f $prefix$from\@$domain";
@@ -345,7 +379,7 @@
# if something wrong with $mail->print we will get PIPE signal, handle it
local $SIG{'PIPE'} = sub { die "program unexpectedly closed pipe" };
- $args{'entity'}->print($mail);
+ $args{'Entity'}->print($mail);
unless ( close $mail ) {
die "close pipe failed: $!" if $!; # system error
@@ -370,7 +404,7 @@
push @mailer_args, split(/\s+/, RT->Config->Get('SendmailArguments'));
}
elsif ( $mail_command eq 'smtp' ) {
- $ENV{'MAILADDRESS'} = RT->Config->Get('SMTPFrom') || $args{'entity'}->head->get('From');
+ $ENV{'MAILADDRESS'} = RT->Config->Get('SMTPFrom') || $args{'Entity'}->head->get('From');
push @mailer_args, ( Server => RT->Config->Get('SMTPServer') );
push @mailer_args, ( Debug => RT->Config->Get('SMTPDebug') );
}
@@ -378,7 +412,7 @@
push @mailer_args, RT->Config->Get('MailParams');
}
- unless ( $args{'entity'}->send( @mailer_args ) ) {
+ unless ( $args{'Entity'}->send( @mailer_args ) ) {
$RT::Logger->crit( "$msgid: Could not send mail." );
return 0;
}
@@ -441,7 +475,9 @@
Encoding => '8bit',
Data => $entity->as_string,
);
- SendEmail( entity => $mail );
+ my $status = SendEmail( Entity => $mail, Transaction => $txn );
+ return (0, $txn->loc("Couldn't send email")) unless $status;
+ return (1, $txn->loc("Send email successfully"));
}
sub CreateUser {
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Ticket_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Ticket_Overlay.pm (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Ticket_Overlay.pm Tue Apr 10 16:46:22 2007
@@ -2171,44 +2171,42 @@
=cut
sub _RecordNote {
-
my $self = shift;
- my %args = ( CcMessageTo => undef,
- BccMessageTo => undef,
- MIMEObj => undef,
- Content => undef,
- TimeTaken => 0,
- CommitScrips => 1,
- @_ );
+ my %args = (
+ CcMessageTo => undef,
+ BccMessageTo => undef,
+ MIMEObj => undef,
+ Content => undef,
+ TimeTaken => 0,
+ CommitScrips => 1,
+ @_
+ );
unless ( $args{'MIMEObj'} || $args{'Content'} ) {
- return ( 0, $self->loc("No message attached"), undef );
+ return ( 0, $self->loc("No message attached"), undef );
}
+
unless ( $args{'MIMEObj'} ) {
- $args{'MIMEObj'} = MIME::Entity->build( Data => (
- ref $args{'Content'}
- ? $args{'Content'}
- : [ $args{'Content'} ]
- ) );
- }
+ $args{'MIMEObj'} = MIME::Entity->build(
+ Data => ( ref $args{'Content'}? $args{'Content'}: [ $args{'Content'} ] )
+ );
+ }
# convert text parts into utf-8
RT::I18N::SetMIMEEntityToUTF8( $args{'MIMEObj'} );
-# If we've been passed in CcMessageTo and BccMessageTo fields,
-# add them to the mime object for passing on to the transaction handler
-# The "NotifyOtherRecipients" scripAction will look for RT-Send-Cc: and RT-Send-Bcc:
-# headers
-
- $args{'MIMEObj'}->head->add( 'RT-Send-Cc', RT::User::CanonicalizeEmailAddress(
- undef, $args{'CcMessageTo'}
- ) )
- if defined $args{'CcMessageTo'};
- $args{'MIMEObj'}->head->add( 'RT-Send-Bcc',
- RT::User::CanonicalizeEmailAddress(
- undef, $args{'BccMessageTo'}
- ) )
- if defined $args{'BccMessageTo'};
+ # If we've been passed in CcMessageTo and BccMessageTo fields,
+ # add them to the mime object for passing on to the transaction handler
+ # The "NotifyOtherRecipients" scripAction will look for RT-Send-Cc: and
+ # RT-Send-Bcc: headers
+
+ $args{'MIMEObj'}->head->add(
+ 'RT-Send-Cc' => RT::User->CanonicalizeEmailAddress( $args{'CcMessageTo'} )
+ ) if defined $args{'CcMessageTo'};
+
+ $args{'MIMEObj'}->head->add(
+ 'RT-Send-Bcc' => RT::User->CanonicalizeEmailAddress( $args{'BccMessageTo'} )
+ ) if defined $args{'BccMessageTo'};
# XXX: This code is duplicated several times
# If this is from an external source, we need to come up with its
Modified: rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Tickets_Overlay.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Tickets_Overlay.pm (original)
+++ rt/branches/3.7-EXPERIMENTAL-TUNIS/lib/RT/Tickets_Overlay.pm Tue Apr 10 16:46:22 2007
@@ -593,8 +593,20 @@
# See the comments for TransLimit, they apply here too
- $sb->{_sql_transalias} = $sb->NewAlias('Transactions')
- unless defined $sb->{_sql_transalias};
+ unless ( $sb->{_sql_transalias} ) {
+ $sb->{_sql_transalias} = $sb->Join(
+ ALIAS1 => 'main',
+ FIELD1 => 'id',
+ TABLE2 => 'Transactions',
+ FIELD2 => 'ObjectId',
+ );
+ $sb->SUPER::Limit(
+ ALIAS => $sb->{_sql_transalias},
+ FIELD => 'ObjectType',
+ VALUE => 'RT::Ticket',
+ ENTRYAGGREGATOR => 'AND',
+ );
+ }
my $date = RT::Date->new( $sb->CurrentUser );
$date->Set( Format => 'unknown', Value => $value );
@@ -645,20 +657,6 @@
);
}
- # Join Transactions to Tickets
- $sb->_SQLJoin(
- ALIAS1 => 'main',
- FIELD1 => $sb->{'primary_key'}, # UGH!
- ALIAS2 => $sb->{_sql_transalias},
- FIELD2 => 'ObjectId'
- );
-
- $sb->SUPER::Limit(
- ALIAS => $sb->{_sql_transalias},
- FIELD => 'ObjectType',
- VALUE => 'RT::Ticket'
- );
-
$sb->_CloseParen;
}
@@ -707,10 +705,29 @@
my ( $self, $field, $op, $value, @rest ) = @_;
- $self->{_sql_transalias} = $self->NewAlias('Transactions')
- unless defined $self->{_sql_transalias};
- $self->{_sql_trattachalias} = $self->NewAlias('Attachments')
- unless defined $self->{_sql_trattachalias};
+ unless ( $self->{_sql_transalias} ) {
+ $self->{_sql_transalias} = $self->Join(
+ ALIAS1 => 'main',
+ FIELD1 => 'id',
+ TABLE2 => 'Transactions',
+ FIELD2 => 'ObjectId',
+ );
+ $self->SUPER::Limit(
+ ALIAS => $self->{_sql_transalias},
+ FIELD => 'ObjectType',
+ VALUE => 'RT::Ticket',
+ ENTRYAGGREGATOR => 'AND',
+ );
+ }
+ unless ( defined $self->{_sql_trattachalias} ) {
+ $self->{_sql_trattachalias} = $self->_SQLJoin(
+ TYPE => 'LEFT', # not all txns have an attachment
+ ALIAS1 => $self->{_sql_transalias},
+ FIELD1 => 'id',
+ TABLE2 => 'Attachments',
+ FIELD2 => 'TransactionId',
+ );
+ }
$self->_OpenParen;
@@ -746,28 +763,6 @@
);
}
- $self->_SQLJoin(
- ALIAS1 => $self->{_sql_trattachalias},
- FIELD1 => 'TransactionId',
- ALIAS2 => $self->{_sql_transalias},
- FIELD2 => 'id'
- );
-
- # Join Transactions to Tickets
- $self->_SQLJoin(
- ALIAS1 => 'main',
- FIELD1 => $self->{'primary_key'}, # Why not use "id" here?
- ALIAS2 => $self->{_sql_transalias},
- FIELD2 => 'ObjectId'
- );
-
- $self->SUPER::Limit(
- ALIAS => $self->{_sql_transalias},
- FIELD => 'ObjectType',
- VALUE => 'RT::Ticket',
- ENTRYAGGREGATOR => 'AND'
- );
-
$self->_CloseParen;
}
More information about the Rt-commit
mailing list