summaryrefslogtreecommitdiff
path: root/rt/lib
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2014-02-25 18:34:25 -0800
committerIvan Kohler <ivan@freeside.biz>2014-02-25 18:34:25 -0800
commit45d35d5739d05e602bc317739485693e0e9ff0b5 (patch)
tree61801368d96662baff145d3271fd887ca104391c /rt/lib
parent662be3ece2ef8c7f05fcbfaa699d80a6a73ca110 (diff)
RT 4.0.19
Diffstat (limited to 'rt/lib')
-rw-r--r--rt/lib/RT.pm16
-rwxr-xr-xrt/lib/RT/ACE.pm2
-rwxr-xr-xrt/lib/RT/ACL.pm2
-rwxr-xr-xrt/lib/RT/Action.pm2
-rw-r--r--rt/lib/RT/Action/AutoOpen.pm2
-rwxr-xr-xrt/lib/RT/Action/Autoreply.pm2
-rw-r--r--rt/lib/RT/Action/CreateTickets.pm2
-rw-r--r--rt/lib/RT/Action/EscalatePriority.pm2
-rw-r--r--rt/lib/RT/Action/ExtractSubjectTag.pm2
-rwxr-xr-xrt/lib/RT/Action/LinearEscalate.pm2
-rwxr-xr-xrt/lib/RT/Action/Notify.pm2
-rwxr-xr-xrt/lib/RT/Action/NotifyAsComment.pm2
-rw-r--r--rt/lib/RT/Action/NotifyGroup.pm2
-rw-r--r--rt/lib/RT/Action/NotifyGroupAsComment.pm2
-rw-r--r--rt/lib/RT/Action/RecordComment.pm2
-rw-r--r--rt/lib/RT/Action/RecordCorrespondence.pm2
-rwxr-xr-xrt/lib/RT/Action/SendEmail.pm24
-rw-r--r--rt/lib/RT/Action/SetPriority.pm2
-rw-r--r--rt/lib/RT/Action/SetStatus.pm2
-rw-r--r--rt/lib/RT/Action/UserDefined.pm2
-rw-r--r--rt/lib/RT/Approval.pm2
-rw-r--r--rt/lib/RT/Approval/Rule.pm2
-rw-r--r--rt/lib/RT/Approval/Rule/Created.pm2
-rw-r--r--rt/lib/RT/Approval/Rule/NewPending.pm2
-rw-r--r--rt/lib/RT/Approval/Rule/Passed.pm2
-rw-r--r--rt/lib/RT/Approval/Rule/Rejected.pm2
-rw-r--r--rt/lib/RT/Article.pm2
-rw-r--r--rt/lib/RT/Articles.pm8
-rwxr-xr-xrt/lib/RT/Attachment.pm2
-rwxr-xr-xrt/lib/RT/Attachments.pm2
-rw-r--r--rt/lib/RT/Attribute.pm4
-rw-r--r--rt/lib/RT/Attributes.pm7
-rw-r--r--rt/lib/RT/Base.pm2
-rw-r--r--rt/lib/RT/CachedGroupMember.pm2
-rw-r--r--rt/lib/RT/CachedGroupMembers.pm2
-rw-r--r--rt/lib/RT/Class.pm2
-rw-r--r--rt/lib/RT/Classes.pm11
-rwxr-xr-xrt/lib/RT/Condition.pm2
-rw-r--r--rt/lib/RT/Condition/AnyTransaction.pm2
-rw-r--r--rt/lib/RT/Condition/BeforeDue.pm2
-rw-r--r--rt/lib/RT/Condition/CloseTicket.pm2
-rw-r--r--rt/lib/RT/Condition/Overdue.pm2
-rw-r--r--rt/lib/RT/Condition/OwnerChange.pm2
-rw-r--r--rt/lib/RT/Condition/PriorityChange.pm2
-rw-r--r--rt/lib/RT/Condition/PriorityExceeds.pm2
-rw-r--r--rt/lib/RT/Condition/QueueChange.pm2
-rw-r--r--rt/lib/RT/Condition/ReopenTicket.pm2
-rw-r--r--rt/lib/RT/Condition/StatusChange.pm2
-rw-r--r--rt/lib/RT/Condition/UserDefined.pm2
-rw-r--r--rt/lib/RT/Config.pm2
-rw-r--r--rt/lib/RT/Crypt/GnuPG.pm7
-rwxr-xr-xrt/lib/RT/CurrentUser.pm2
-rw-r--r--rt/lib/RT/CustomField.pm64
-rw-r--r--rt/lib/RT/CustomFieldValue.pm2
-rw-r--r--rt/lib/RT/CustomFieldValues.pm2
-rw-r--r--rt/lib/RT/CustomFieldValues/External.pm2
-rw-r--r--rt/lib/RT/CustomFieldValues/Groups.pm34
-rw-r--r--rt/lib/RT/CustomFields.pm35
-rw-r--r--rt/lib/RT/Dashboard.pm2
-rw-r--r--rt/lib/RT/Dashboard/Mailer.pm9
-rw-r--r--rt/lib/RT/Dashboards.pm2
-rw-r--r--rt/lib/RT/Date.pm34
-rw-r--r--rt/lib/RT/EmailParser.pm32
-rw-r--r--rt/lib/RT/Generated.pm4
-rw-r--r--rt/lib/RT/Generated.pm.in2
-rw-r--r--rt/lib/RT/Graph/Tickets.pm2
-rwxr-xr-xrt/lib/RT/Group.pm2
-rwxr-xr-xrt/lib/RT/GroupMember.pm2
-rwxr-xr-xrt/lib/RT/GroupMembers.pm2
-rwxr-xr-xrt/lib/RT/Groups.pm2
-rw-r--r--rt/lib/RT/Handle.pm37
-rw-r--r--rt/lib/RT/I18N.pm3
-rw-r--r--rt/lib/RT/I18N/cs.pm2
-rw-r--r--rt/lib/RT/I18N/de.pm61
-rw-r--r--rt/lib/RT/I18N/fr.pm69
-rw-r--r--rt/lib/RT/I18N/i_default.pm2
-rwxr-xr-xrt/lib/RT/I18N/ru.pm2
-rw-r--r--rt/lib/RT/Installer.pm2
-rw-r--r--rt/lib/RT/Interface/CLI.pm2
-rwxr-xr-xrt/lib/RT/Interface/Email.pm37
-rwxr-xr-xrt/lib/RT/Interface/Email/Auth/GnuPG.pm2
-rw-r--r--rt/lib/RT/Interface/Email/Auth/MailFrom.pm2
-rw-r--r--rt/lib/RT/Interface/REST.pm44
-rw-r--r--rt/lib/RT/Interface/Web.pm36
-rw-r--r--rt/lib/RT/Interface/Web/Handler.pm2
-rw-r--r--rt/lib/RT/Interface/Web/Menu.pm2
-rwxr-xr-xrt/lib/RT/Interface/Web/QueryBuilder.pm2
-rwxr-xr-xrt/lib/RT/Interface/Web/QueryBuilder/Tree.pm2
-rw-r--r--rt/lib/RT/Interface/Web/Request.pm2
-rw-r--r--rt/lib/RT/Interface/Web/Session.pm55
-rw-r--r--rt/lib/RT/Lifecycle.pm8
-rw-r--r--rt/lib/RT/Link.pm2
-rw-r--r--rt/lib/RT/Links.pm2
-rw-r--r--rt/lib/RT/ObjectClass.pm2
-rw-r--r--rt/lib/RT/ObjectClasses.pm2
-rw-r--r--rt/lib/RT/ObjectCustomField.pm2
-rw-r--r--rt/lib/RT/ObjectCustomFieldValue.pm2
-rw-r--r--rt/lib/RT/ObjectCustomFieldValues.pm2
-rw-r--r--rt/lib/RT/ObjectCustomFields.pm2
-rw-r--r--rt/lib/RT/ObjectTopic.pm2
-rw-r--r--rt/lib/RT/ObjectTopics.pm2
-rw-r--r--rt/lib/RT/Plugin.pm2
-rw-r--r--rt/lib/RT/Pod/HTML.pm35
-rw-r--r--rt/lib/RT/Pod/HTMLBatch.pm9
-rw-r--r--rt/lib/RT/Pod/Search.pm2
-rw-r--r--rt/lib/RT/Principal.pm7
-rw-r--r--rt/lib/RT/Principals.pm3
-rwxr-xr-xrt/lib/RT/Queue.pm2
-rwxr-xr-xrt/lib/RT/Queues.pm2
-rwxr-xr-xrt/lib/RT/Record.pm52
-rw-r--r--rt/lib/RT/Reminders.pm5
-rw-r--r--rt/lib/RT/Report/Tickets.pm6
-rw-r--r--rt/lib/RT/Report/Tickets/Entry.pm2
-rw-r--r--rt/lib/RT/Rule.pm2
-rw-r--r--rt/lib/RT/Ruleset.pm2
-rw-r--r--rt/lib/RT/SQL.pm2
-rw-r--r--rt/lib/RT/SavedSearch.pm2
-rw-r--r--rt/lib/RT/SavedSearches.pm2
-rwxr-xr-xrt/lib/RT/Scrip.pm2
-rwxr-xr-xrt/lib/RT/ScripAction.pm2
-rwxr-xr-xrt/lib/RT/ScripActions.pm2
-rwxr-xr-xrt/lib/RT/ScripCondition.pm2
-rwxr-xr-xrt/lib/RT/ScripConditions.pm2
-rwxr-xr-xrt/lib/RT/Scrips.pm2
-rwxr-xr-xrt/lib/RT/Search.pm2
-rw-r--r--rt/lib/RT/Search/ActiveTicketsInQueue.pm2
-rw-r--r--rt/lib/RT/Search/FromSQL.pm2
-rw-r--r--rt/lib/RT/Search/Googleish.pm4
-rw-r--r--rt/lib/RT/SearchBuilder.pm6
-rw-r--r--rt/lib/RT/SharedSetting.pm2
-rw-r--r--rt/lib/RT/SharedSettings.pm2
-rw-r--r--rt/lib/RT/Shredder.pm17
-rw-r--r--rt/lib/RT/Shredder/ACE.pm2
-rw-r--r--rt/lib/RT/Shredder/Attachment.pm2
-rw-r--r--rt/lib/RT/Shredder/CachedGroupMember.pm2
-rw-r--r--rt/lib/RT/Shredder/Constants.pm2
-rw-r--r--rt/lib/RT/Shredder/CustomField.pm2
-rw-r--r--rt/lib/RT/Shredder/CustomFieldValue.pm2
-rw-r--r--rt/lib/RT/Shredder/Dependencies.pm2
-rw-r--r--rt/lib/RT/Shredder/Dependency.pm2
-rw-r--r--rt/lib/RT/Shredder/Exceptions.pm2
-rw-r--r--rt/lib/RT/Shredder/Group.pm2
-rw-r--r--rt/lib/RT/Shredder/GroupMember.pm2
-rw-r--r--rt/lib/RT/Shredder/Link.pm2
-rw-r--r--rt/lib/RT/Shredder/ObjectCustomFieldValue.pm2
-rw-r--r--rt/lib/RT/Shredder/POD.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Attachments.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Base.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Base/Dump.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Base/Search.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Objects.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/SQLDump.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Summary.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Tickets.pm2
-rw-r--r--rt/lib/RT/Shredder/Plugin/Users.pm2
-rw-r--r--rt/lib/RT/Shredder/Principal.pm2
-rw-r--r--rt/lib/RT/Shredder/Queue.pm2
-rw-r--r--rt/lib/RT/Shredder/Record.pm2
-rw-r--r--rt/lib/RT/Shredder/Scrip.pm2
-rw-r--r--rt/lib/RT/Shredder/ScripAction.pm2
-rw-r--r--rt/lib/RT/Shredder/ScripCondition.pm2
-rw-r--r--rt/lib/RT/Shredder/Template.pm2
-rw-r--r--rt/lib/RT/Shredder/Ticket.pm2
-rw-r--r--rt/lib/RT/Shredder/Transaction.pm2
-rw-r--r--rt/lib/RT/Shredder/User.pm2
-rw-r--r--rt/lib/RT/Squish.pm2
-rw-r--r--rt/lib/RT/Squish/CSS.pm2
-rw-r--r--rt/lib/RT/Squish/JS.pm2
-rw-r--r--rt/lib/RT/System.pm2
-rwxr-xr-xrt/lib/RT/Template.pm10
-rwxr-xr-xrt/lib/RT/Templates.pm2
-rw-r--r--rt/lib/RT/Test.pm9
-rw-r--r--rt/lib/RT/Test/Apache.pm2
-rw-r--r--rt/lib/RT/Test/Email.pm2
-rw-r--r--rt/lib/RT/Test/GnuPG.pm2
-rw-r--r--rt/lib/RT/Test/Web.pm2
-rwxr-xr-xrt/lib/RT/Ticket.pm6
-rwxr-xr-xrt/lib/RT/Tickets.pm191
-rw-r--r--rt/lib/RT/Tickets_SQL.pm106
-rw-r--r--rt/lib/RT/Topic.pm2
-rw-r--r--rt/lib/RT/Topics.pm2
-rwxr-xr-xrt/lib/RT/Transaction.pm143
-rwxr-xr-xrt/lib/RT/Transactions.pm2
-rw-r--r--rt/lib/RT/URI.pm4
-rw-r--r--rt/lib/RT/URI/a.pm2
-rw-r--r--rt/lib/RT/URI/base.pm2
-rw-r--r--rt/lib/RT/URI/fsck_com_article.pm2
-rw-r--r--rt/lib/RT/URI/fsck_com_rt.pm2
-rw-r--r--rt/lib/RT/URI/t.pm2
-rwxr-xr-xrt/lib/RT/User.pm2
-rwxr-xr-xrt/lib/RT/Users.pm2
-rw-r--r--rt/lib/RT/Util.pm13
193 files changed, 1144 insertions, 425 deletions
diff --git a/rt/lib/RT.pm b/rt/lib/RT.pm
index da60ef7..0f0c79a 100644
--- a/rt/lib/RT.pm
+++ b/rt/lib/RT.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -181,8 +181,8 @@ up logging|/InitLogging>, and L<loads plugins|/InitPlugins>.
=cut
sub Init {
-
- my @arg = @_;
+ shift if @_%2; # code is inconsistent about calling as method
+ my %args = (@_);
CheckPerlRequirements();
@@ -191,8 +191,8 @@ sub Init {
#Get a database connection
ConnectToDatabase();
InitSystemObjects();
- InitClasses();
- InitLogging(@arg);
+ InitClasses(%args);
+ InitLogging(%args);
InitPlugins();
RT::I18N->Init;
RT->Config->PostLoadCheck;
@@ -264,7 +264,7 @@ sub InitLogging {
my ($package, $filename, $line) = caller($frame);
$p{'message'} =~ s/(?:\r*\n)+$//;
- return "[". gmtime(time) ."] [". $p{'level'} ."]: "
+ return "[$$] [". gmtime(time) ."] [". $p{'level'} ."]: "
. $p{'message'} ." ($filename:$line)\n";
};
@@ -283,9 +283,9 @@ sub InitLogging {
$p{message} =~ s/(?:\r*\n)+$//;
if ($p{level} eq 'debug') {
- return "$p{message}\n";
+ return "[$$] $p{message} ($filename:$line)\n";
} else {
- return "$p{message} ($filename:$line)\n";
+ return "[$$] $p{message}\n";
}
};
diff --git a/rt/lib/RT/ACE.pm b/rt/lib/RT/ACE.pm
index c752aa2..baf6fb2 100755
--- a/rt/lib/RT/ACE.pm
+++ b/rt/lib/RT/ACE.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ACL.pm b/rt/lib/RT/ACL.pm
index d1e0df5..0662b39 100755
--- a/rt/lib/RT/ACL.pm
+++ b/rt/lib/RT/ACL.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action.pm b/rt/lib/RT/Action.pm
index dc10d0d..88e5b15 100755
--- a/rt/lib/RT/Action.pm
+++ b/rt/lib/RT/Action.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/AutoOpen.pm b/rt/lib/RT/Action/AutoOpen.pm
index 8566c62..e819ca9 100644
--- a/rt/lib/RT/Action/AutoOpen.pm
+++ b/rt/lib/RT/Action/AutoOpen.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/Autoreply.pm b/rt/lib/RT/Action/Autoreply.pm
index 89b7536..a2703e5 100755
--- a/rt/lib/RT/Action/Autoreply.pm
+++ b/rt/lib/RT/Action/Autoreply.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/CreateTickets.pm b/rt/lib/RT/Action/CreateTickets.pm
index 8030802..e3c7b53 100644
--- a/rt/lib/RT/Action/CreateTickets.pm
+++ b/rt/lib/RT/Action/CreateTickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/EscalatePriority.pm b/rt/lib/RT/Action/EscalatePriority.pm
index 1300b4f..38cad94 100644
--- a/rt/lib/RT/Action/EscalatePriority.pm
+++ b/rt/lib/RT/Action/EscalatePriority.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/ExtractSubjectTag.pm b/rt/lib/RT/Action/ExtractSubjectTag.pm
index 6a3898e..92a7214 100644
--- a/rt/lib/RT/Action/ExtractSubjectTag.pm
+++ b/rt/lib/RT/Action/ExtractSubjectTag.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/LinearEscalate.pm b/rt/lib/RT/Action/LinearEscalate.pm
index 13913e6..9b75286 100755
--- a/rt/lib/RT/Action/LinearEscalate.pm
+++ b/rt/lib/RT/Action/LinearEscalate.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/Notify.pm b/rt/lib/RT/Action/Notify.pm
index 3553cbc..26aae47 100755
--- a/rt/lib/RT/Action/Notify.pm
+++ b/rt/lib/RT/Action/Notify.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/NotifyAsComment.pm b/rt/lib/RT/Action/NotifyAsComment.pm
index 0016a36..a2c57db 100755
--- a/rt/lib/RT/Action/NotifyAsComment.pm
+++ b/rt/lib/RT/Action/NotifyAsComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/NotifyGroup.pm b/rt/lib/RT/Action/NotifyGroup.pm
index 1dece60..789c182 100644
--- a/rt/lib/RT/Action/NotifyGroup.pm
+++ b/rt/lib/RT/Action/NotifyGroup.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/NotifyGroupAsComment.pm b/rt/lib/RT/Action/NotifyGroupAsComment.pm
index cf6952a..135ef7f 100644
--- a/rt/lib/RT/Action/NotifyGroupAsComment.pm
+++ b/rt/lib/RT/Action/NotifyGroupAsComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/RecordComment.pm b/rt/lib/RT/Action/RecordComment.pm
index a384af3..8f55ff1 100644
--- a/rt/lib/RT/Action/RecordComment.pm
+++ b/rt/lib/RT/Action/RecordComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/RecordCorrespondence.pm b/rt/lib/RT/Action/RecordCorrespondence.pm
index cc21503..2304f28 100644
--- a/rt/lib/RT/Action/RecordCorrespondence.pm
+++ b/rt/lib/RT/Action/RecordCorrespondence.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/SendEmail.pm b/rt/lib/RT/Action/SendEmail.pm
index 0a52904..0f11cc1 100755
--- a/rt/lib/RT/Action/SendEmail.pm
+++ b/rt/lib/RT/Action/SendEmail.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -382,7 +382,7 @@ sub AddAttachments {
=head2 AddAttachment $attachment
-Takes one attachment object of L<RT::Attachmment> class and attaches it to the message
+Takes one attachment object of L<RT::Attachment> class and attaches it to the message
we're building.
=cut
@@ -397,14 +397,15 @@ sub AddAttachment {
and $attach->TransactionObj->CurrentUserCanSee;
# ->attach expects just the disposition type; extract it if we have the header
+ # or default to "attachment"
my $disp = ($attach->GetHeader('Content-Disposition') || '')
- =~ /^\s*(inline|attachment)/i ? $1 : undef;
+ =~ /^\s*(inline|attachment)/i ? $1 : "attachment";
$MIMEObj->attach(
Type => $attach->ContentType,
Charset => $attach->OriginalEncoding,
Data => $attach->OriginalContent,
- Disposition => $disp, # a false value defaults to inline in MIME::Entity
+ Disposition => $disp,
Filename => $self->MIMEEncodeString( $attach->Filename ),
'RT-Attachment:' => $self->TicketObj->Id . "/"
. $self->TransactionObj->Id . "/"
@@ -975,7 +976,7 @@ sub SetSubject {
$subject =~ s/(\r\n|\n|\s)/ /g;
- $self->SetHeader( 'Subject', $subject );
+ $self->SetHeader( 'Subject', Encode::encode_utf8( $subject ) );
}
@@ -989,11 +990,14 @@ sub SetSubjectToken {
my $self = shift;
my $head = $self->TemplateObj->MIMEObj->head;
- $head->replace(
- Subject => RT::Interface::Email::AddSubjectTag(
- Encode::decode_utf8( $head->get('Subject') ),
- $self->TicketObj,
- ),
+ $self->SetHeader(
+ Subject =>
+ Encode::encode_utf8(
+ RT::Interface::Email::AddSubjectTag(
+ Encode::decode_utf8( $head->get('Subject') ),
+ $self->TicketObj,
+ ),
+ ),
);
}
diff --git a/rt/lib/RT/Action/SetPriority.pm b/rt/lib/RT/Action/SetPriority.pm
index 2043532..7385c13 100644
--- a/rt/lib/RT/Action/SetPriority.pm
+++ b/rt/lib/RT/Action/SetPriority.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/SetStatus.pm b/rt/lib/RT/Action/SetStatus.pm
index be00396..c7a3127 100644
--- a/rt/lib/RT/Action/SetStatus.pm
+++ b/rt/lib/RT/Action/SetStatus.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/UserDefined.pm b/rt/lib/RT/Action/UserDefined.pm
index b259323..adc40e9 100644
--- a/rt/lib/RT/Action/UserDefined.pm
+++ b/rt/lib/RT/Action/UserDefined.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Approval.pm b/rt/lib/RT/Approval.pm
index dc60222..34cf100 100644
--- a/rt/lib/RT/Approval.pm
+++ b/rt/lib/RT/Approval.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Approval/Rule.pm b/rt/lib/RT/Approval/Rule.pm
index 6892f41..1b7b7ac 100644
--- a/rt/lib/RT/Approval/Rule.pm
+++ b/rt/lib/RT/Approval/Rule.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Approval/Rule/Created.pm b/rt/lib/RT/Approval/Rule/Created.pm
index 8fcaeb2..91063d1 100644
--- a/rt/lib/RT/Approval/Rule/Created.pm
+++ b/rt/lib/RT/Approval/Rule/Created.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Approval/Rule/NewPending.pm b/rt/lib/RT/Approval/Rule/NewPending.pm
index 97d3cfb..3fdb99d 100644
--- a/rt/lib/RT/Approval/Rule/NewPending.pm
+++ b/rt/lib/RT/Approval/Rule/NewPending.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Approval/Rule/Passed.pm b/rt/lib/RT/Approval/Rule/Passed.pm
index acc4916..241e604 100644
--- a/rt/lib/RT/Approval/Rule/Passed.pm
+++ b/rt/lib/RT/Approval/Rule/Passed.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Approval/Rule/Rejected.pm b/rt/lib/RT/Approval/Rule/Rejected.pm
index 0a02568..adc3063 100644
--- a/rt/lib/RT/Approval/Rule/Rejected.pm
+++ b/rt/lib/RT/Approval/Rule/Rejected.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Article.pm b/rt/lib/RT/Article.pm
index ec1ae3c..e9f3d43 100644
--- a/rt/lib/RT/Article.pm
+++ b/rt/lib/RT/Article.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Articles.pm b/rt/lib/RT/Articles.pm
index d69eabf..9bee844 100644
--- a/rt/lib/RT/Articles.pm
+++ b/rt/lib/RT/Articles.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -597,7 +597,11 @@ sub Search {
require Time::ParseDate;
foreach my $date (qw(Created< Created> LastUpdated< LastUpdated>)) {
next unless ( $args{$date} );
- my $seconds = Time::ParseDate::parsedate( $args{$date}, FUZZY => 1, PREFER_PAST => 1 );
+ my ($seconds, $error) = Time::ParseDate::parsedate( $args{$date}, FUZZY => 1, PREFER_PAST => 1 );
+ unless ( defined $seconds ) {
+ $RT::Logger->warning(
+ "Couldn't parse date '$args{$date}' by Time::ParseDate" );
+ }
my $date_obj = RT::Date->new( $self->CurrentUser );
$date_obj->Set( Format => 'unix', Value => $seconds );
$dates->{$date} = $date_obj;
diff --git a/rt/lib/RT/Attachment.pm b/rt/lib/RT/Attachment.pm
index 54217b3..07fdea3 100755
--- a/rt/lib/RT/Attachment.pm
+++ b/rt/lib/RT/Attachment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Attachments.pm b/rt/lib/RT/Attachments.pm
index 5b087a4..7f6f258 100755
--- a/rt/lib/RT/Attachments.pm
+++ b/rt/lib/RT/Attachments.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Attribute.pm b/rt/lib/RT/Attribute.pm
index 10971a2..745f95f 100644
--- a/rt/lib/RT/Attribute.pm
+++ b/rt/lib/RT/Attribute.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -148,7 +148,7 @@ sub Create {
@_);
if ($args{Object} and UNIVERSAL::can($args{Object}, 'Id')) {
- $args{ObjectType} = ref($args{Object});
+ $args{ObjectType} = $args{Object}->isa("RT::CurrentUser") ? "RT::User" : ref($args{Object});
$args{ObjectId} = $args{Object}->Id;
} else {
return(0, $self->loc("Required parameter '[_1]' not specified", 'Object'));
diff --git a/rt/lib/RT/Attributes.pm b/rt/lib/RT/Attributes.pm
index 9c18c1a..c556756 100644
--- a/rt/lib/RT/Attributes.pm
+++ b/rt/lib/RT/Attributes.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -210,7 +210,10 @@ sub LimitToObject {
unless (eval { $obj->id} ){
return undef;
}
- $self->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => ref($obj), ENTRYAGGREGATOR => 'OR');
+
+ my $type = $obj->isa("RT::CurrentUser") ? "RT::User" : ref($obj);
+
+ $self->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => $type, ENTRYAGGREGATOR => 'OR');
$self->Limit(FIELD => 'ObjectId', OPERATOR=> '=', VALUE => $obj->id, ENTRYAGGREGATOR => 'OR', QUOTEVALUE => 0);
}
diff --git a/rt/lib/RT/Base.pm b/rt/lib/RT/Base.pm
index 403c318..f83ed8e 100644
--- a/rt/lib/RT/Base.pm
+++ b/rt/lib/RT/Base.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/CachedGroupMember.pm b/rt/lib/RT/CachedGroupMember.pm
index b334d4d..66e7c7a 100644
--- a/rt/lib/RT/CachedGroupMember.pm
+++ b/rt/lib/RT/CachedGroupMember.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/CachedGroupMembers.pm b/rt/lib/RT/CachedGroupMembers.pm
index 4d8f356..f65796a 100644
--- a/rt/lib/RT/CachedGroupMembers.pm
+++ b/rt/lib/RT/CachedGroupMembers.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Class.pm b/rt/lib/RT/Class.pm
index dfe8eb3..8f68924 100644
--- a/rt/lib/RT/Class.pm
+++ b/rt/lib/RT/Class.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Classes.pm b/rt/lib/RT/Classes.pm
index 60122c7..6b50d5d 100644
--- a/rt/lib/RT/Classes.pm
+++ b/rt/lib/RT/Classes.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -54,6 +54,15 @@ use base 'RT::SearchBuilder';
sub Table {'Classes'}
+=head2 _Init
+
+=cut
+
+ sub _Init {
+ my $self = shift;
+ $self->{'with_disabled_column'} = 1;
+ return ($self->SUPER::_Init(@_));
+ }
=head2 Next
diff --git a/rt/lib/RT/Condition.pm b/rt/lib/RT/Condition.pm
index 0751815..80cf019 100755
--- a/rt/lib/RT/Condition.pm
+++ b/rt/lib/RT/Condition.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/AnyTransaction.pm b/rt/lib/RT/Condition/AnyTransaction.pm
index 2c9129c..5d8b3bc 100644
--- a/rt/lib/RT/Condition/AnyTransaction.pm
+++ b/rt/lib/RT/Condition/AnyTransaction.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/BeforeDue.pm b/rt/lib/RT/Condition/BeforeDue.pm
index 8df73ca..73015bc 100644
--- a/rt/lib/RT/Condition/BeforeDue.pm
+++ b/rt/lib/RT/Condition/BeforeDue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/CloseTicket.pm b/rt/lib/RT/Condition/CloseTicket.pm
index bdeaf2d..2e027f4 100644
--- a/rt/lib/RT/Condition/CloseTicket.pm
+++ b/rt/lib/RT/Condition/CloseTicket.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/Overdue.pm b/rt/lib/RT/Condition/Overdue.pm
index 547aea2..462fa40 100644
--- a/rt/lib/RT/Condition/Overdue.pm
+++ b/rt/lib/RT/Condition/Overdue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/OwnerChange.pm b/rt/lib/RT/Condition/OwnerChange.pm
index 8500548..407d5a5 100644
--- a/rt/lib/RT/Condition/OwnerChange.pm
+++ b/rt/lib/RT/Condition/OwnerChange.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/PriorityChange.pm b/rt/lib/RT/Condition/PriorityChange.pm
index a600453..25e6bfb 100644
--- a/rt/lib/RT/Condition/PriorityChange.pm
+++ b/rt/lib/RT/Condition/PriorityChange.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/PriorityExceeds.pm b/rt/lib/RT/Condition/PriorityExceeds.pm
index a28d6df..e35d0b5 100644
--- a/rt/lib/RT/Condition/PriorityExceeds.pm
+++ b/rt/lib/RT/Condition/PriorityExceeds.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/QueueChange.pm b/rt/lib/RT/Condition/QueueChange.pm
index ba7a8a4..91cd88c 100644
--- a/rt/lib/RT/Condition/QueueChange.pm
+++ b/rt/lib/RT/Condition/QueueChange.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/ReopenTicket.pm b/rt/lib/RT/Condition/ReopenTicket.pm
index a057e40..69ef8f9 100644
--- a/rt/lib/RT/Condition/ReopenTicket.pm
+++ b/rt/lib/RT/Condition/ReopenTicket.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/StatusChange.pm b/rt/lib/RT/Condition/StatusChange.pm
index e84915d..55fe234 100644
--- a/rt/lib/RT/Condition/StatusChange.pm
+++ b/rt/lib/RT/Condition/StatusChange.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Condition/UserDefined.pm b/rt/lib/RT/Condition/UserDefined.pm
index 1abee67..4f4ff18 100644
--- a/rt/lib/RT/Condition/UserDefined.pm
+++ b/rt/lib/RT/Condition/UserDefined.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Config.pm b/rt/lib/RT/Config.pm
index ee426bf..fee6c51 100644
--- a/rt/lib/RT/Config.pm
+++ b/rt/lib/RT/Config.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Crypt/GnuPG.pm b/rt/lib/RT/Crypt/GnuPG.pm
index 6164a42..d0587d4 100644
--- a/rt/lib/RT/Crypt/GnuPG.pm
+++ b/rt/lib/RT/Crypt/GnuPG.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -2160,7 +2160,10 @@ sub GetKeysInfo {
}
$RT::Logger->debug( $res{'status'} ) if $res{'status'};
$RT::Logger->warning( $res{'stderr'} ) if $res{'stderr'};
- $RT::Logger->error( $res{'logger'} ) if $res{'logger'} && $?;
+ if ( $res{'logger'} && $? ) {
+ $RT::Logger->error( $res{'logger'} );
+ $RT::Logger->error( 'The above error may result from an unconfigured RT/GPG installation. See perldoc etc/RT_Config.pm for information about configuring or disabling GPG support for RT' );
+ }
if ( $@ || $? ) {
$res{'message'} = $@? $@: "gpg exitted with error code ". ($? >> 8);
return %res;
diff --git a/rt/lib/RT/CurrentUser.pm b/rt/lib/RT/CurrentUser.pm
index fa0d4ca..c11d460 100755
--- a/rt/lib/RT/CurrentUser.pm
+++ b/rt/lib/RT/CurrentUser.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/CustomField.pm b/rt/lib/RT/CustomField.pm
index 01b4970..e71bbf7 100644
--- a/rt/lib/RT/CustomField.pm
+++ b/rt/lib/RT/CustomField.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -51,7 +51,7 @@ package RT::CustomField;
use strict;
use warnings;
-
+use Scalar::Util 'blessed';
use base 'RT::Record';
@@ -1111,11 +1111,6 @@ sub SetRenderType {
$self->FriendlyType));
}
- # XXX: Remove this restriction once we support lists and cascaded selects
- if ( $self->BasedOnObj->id and $type =~ /List/ ) {
- return (0, $self->loc("We can't currently render as a List when basing categories on another custom field. Please use another render type."));
- }
-
return $self->_Set( Field => 'RenderType', Value => $type, @_ );
}
@@ -1193,7 +1188,7 @@ Returns an array of LookupTypes available
sub LookupTypes {
my $self = shift;
- return keys %FRIENDLY_OBJECT_TYPES;
+ return sort keys %FRIENDLY_OBJECT_TYPES;
}
my @FriendlyObjectTypes = (
@@ -1222,14 +1217,57 @@ sub FriendlyLookupType {
return ( $self->loc( $FriendlyObjectTypes[$#types], @types ) );
}
+=head1 RecordClassFromLookupType
+
+Returns the type of Object referred to by ObjectCustomFields' ObjectId column
+
+Optionally takes a LookupType to use instead of using the value on the loaded
+record. In this case, the method may be called on the class instead of an
+object.
+
+=cut
+
sub RecordClassFromLookupType {
my $self = shift;
- my ($class) = ($self->LookupType =~ /^([^-]+)/);
+ my $type = shift || $self->LookupType;
+ my ($class) = ($type =~ /^([^-]+)/);
unless ( $class ) {
- $RT::Logger->error(
- "Custom Field #". $self->id
- ." has incorrect LookupType '". $self->LookupType ."'"
- );
+ if (blessed($self) and $self->LookupType eq $type) {
+ $RT::Logger->error(
+ "Custom Field #". $self->id
+ ." has incorrect LookupType '$type'"
+ );
+ } else {
+ RT->Logger->error("Invalid LookupType passed as argument: $type");
+ }
+ return undef;
+ }
+ return $class;
+}
+
+=head1 ObjectTypeFromLookupType
+
+Returns the ObjectType used in ObjectCustomFieldValues rows for this CF
+
+Optionally takes a LookupType to use instead of using the value on the loaded
+record. In this case, the method may be called on the class instead of an
+object.
+
+=cut
+
+sub ObjectTypeFromLookupType {
+ my $self = shift;
+ my $type = shift || $self->LookupType;
+ my ($class) = ($type =~ /([^-]+)$/);
+ unless ( $class ) {
+ if (blessed($self) and $self->LookupType eq $type) {
+ $RT::Logger->error(
+ "Custom Field #". $self->id
+ ." has incorrect LookupType '$type'"
+ );
+ } else {
+ RT->Logger->error("Invalid LookupType passed as argument: $type");
+ }
return undef;
}
return $class;
diff --git a/rt/lib/RT/CustomFieldValue.pm b/rt/lib/RT/CustomFieldValue.pm
index 6dffc34..4adb84d 100644
--- a/rt/lib/RT/CustomFieldValue.pm
+++ b/rt/lib/RT/CustomFieldValue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/CustomFieldValues.pm b/rt/lib/RT/CustomFieldValues.pm
index e3380b7..18bc6b4 100644
--- a/rt/lib/RT/CustomFieldValues.pm
+++ b/rt/lib/RT/CustomFieldValues.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/CustomFieldValues/External.pm b/rt/lib/RT/CustomFieldValues/External.pm
index e6bf2f8..375f5c5 100644
--- a/rt/lib/RT/CustomFieldValues/External.pm
+++ b/rt/lib/RT/CustomFieldValues/External.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/CustomFieldValues/Groups.pm b/rt/lib/RT/CustomFieldValues/Groups.pm
index feeeadb..48234e2 100644
--- a/rt/lib/RT/CustomFieldValues/Groups.pm
+++ b/rt/lib/RT/CustomFieldValues/Groups.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -53,10 +53,42 @@ use warnings;
use base qw(RT::CustomFieldValues::External);
+=head1 NAME
+
+RT::CustomFieldValues::Groups - Provide RT's groups as a dynamic list of CF values
+
+=head1 SYNOPSIS
+
+To use as a source of CF values, add the following to your F<RT_SiteConfig.pm>
+and restart RT.
+
+ # In RT_SiteConfig.pm
+ Set( @CustomFieldValuesSources, "RT::CustomFieldValues::Groups" );
+
+Then visit the modify CF page in the RT admin configuration.
+
+=head1 METHODS
+
+Most methods are inherited from L<RT::CustomFieldValues::External>, except the
+ones below.
+
+=head2 SourceDescription
+
+Returns a brief string describing this data source.
+
+=cut
+
sub SourceDescription {
return 'RT user defined groups';
}
+=head2 ExternalValues
+
+Returns an arrayref containing a hashref for each possible value in this data
+source, where the value name is the group name.
+
+=cut
+
sub ExternalValues {
my $self = shift;
diff --git a/rt/lib/RT/CustomFields.pm b/rt/lib/RT/CustomFields.pm
index 017018e..7c77015 100644
--- a/rt/lib/RT/CustomFields.pm
+++ b/rt/lib/RT/CustomFields.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -141,6 +141,25 @@ sub LimitToParentType {
$self->Limit( FIELD => 'LookupType', STARTSWITH => "$lookup" );
}
+=head2 LimitToObjectId
+
+Takes an ObjectId and limits the collection to CFs applied to said object.
+
+When called multiple times the ObjectId limits are joined with OR.
+
+=cut
+
+sub LimitToObjectId {
+ my $self = shift;
+ my $id = shift;
+ $self->Limit(
+ ALIAS => $self->_OCFAlias,
+ FIELD => 'ObjectId',
+ OPERATOR => '=',
+ VALUE => $id || 0,
+ ENTRYAGGREGATOR => 'OR'
+ );
+}
=head2 LimitToGlobalOrObjectId
@@ -155,19 +174,11 @@ sub LimitToGlobalOrObjectId {
foreach my $id (@_) {
- $self->Limit( ALIAS => $self->_OCFAlias,
- FIELD => 'ObjectId',
- OPERATOR => '=',
- VALUE => $id || 0,
- ENTRYAGGREGATOR => 'OR' );
- $global_only = 0 if $id;
+ $self->LimitToObjectId($id);
+ $global_only = 0 if $id;
}
- $self->Limit( ALIAS => $self->_OCFAlias,
- FIELD => 'ObjectId',
- OPERATOR => '=',
- VALUE => 0,
- ENTRYAGGREGATOR => 'OR' ) unless $global_only;
+ $self->LimitToObjectId(0) unless $global_only;
}
sub _LimitToOCFs {
diff --git a/rt/lib/RT/Dashboard.pm b/rt/lib/RT/Dashboard.pm
index 349864e..6d4c515 100644
--- a/rt/lib/RT/Dashboard.pm
+++ b/rt/lib/RT/Dashboard.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Dashboard/Mailer.pm b/rt/lib/RT/Dashboard/Mailer.pm
index 9d28c49..eb620e6 100644
--- a/rt/lib/RT/Dashboard/Mailer.pm
+++ b/rt/lib/RT/Dashboard/Mailer.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -146,7 +146,7 @@ sub IsSubscriptionReady {
my $sub_hour = $subscription->SubValue('Hour');
my $sub_dow = $subscription->SubValue('Dow');
my $sub_dom = $subscription->SubValue('Dom');
- my $sub_fow = $subscription->SubValue('Fow');
+ my $sub_fow = $subscription->SubValue('Fow') || 1;
my ($hour, $dow, $dom) = @{ $args{LocalTime} };
@@ -165,8 +165,6 @@ sub IsSubscriptionReady {
return 0 if $sub_dow ne $dow;
# does it match the "every N weeks" clause?
- $sub_fow = 1 if !$sub_fow;
-
return 1 if $counter % $sub_fow == 0;
$subscription->SetSubValues(Counter => $counter + 1)
@@ -422,12 +420,15 @@ sub BuildEmail {
Type => 'text/html',
Charset => 'UTF-8',
Disposition => 'inline',
+ Encoding => "base64",
);
for my $part (@parts) {
$entity->add_part($part);
}
+ $entity->make_singlepart;
+
return $entity;
}
diff --git a/rt/lib/RT/Dashboards.pm b/rt/lib/RT/Dashboards.pm
index f9cbbe8..1c5fe3d 100644
--- a/rt/lib/RT/Dashboards.pm
+++ b/rt/lib/RT/Dashboards.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Date.pm b/rt/lib/RT/Date.pm
index 031f9c8..db56cfe 100644
--- a/rt/lib/RT/Date.pm
+++ b/rt/lib/RT/Date.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -208,7 +208,7 @@ sub Set {
# should be applied to absolute times, so compensate shift in NOW
my $now = time;
$now += ($self->Localtime( $args{Timezone}, $now ))[9];
- my $date = Time::ParseDate::parsedate(
+ my ($date, $error) = Time::ParseDate::parsedate(
$args{'Value'},
GMT => 1,
NOW => $now,
@@ -216,6 +216,13 @@ sub Set {
PREFER_PAST => RT->Config->Get('AmbiguousDayInPast'),
PREFER_FUTURE => RT->Config->Get('AmbiguousDayInFuture'),
);
+ unless ( defined $date ) {
+ $RT::Logger->warning(
+ "Couldn't parse date '$args{'Value'}' by Time::ParseDate"
+ );
+ return $self->Unix(0);
+ }
+
# apply timezone offset
$date -= ($self->Localtime( $args{Timezone}, $date ))[9];
@@ -895,7 +902,7 @@ sub RFC2822 {
my ($date, $time) = ('','');
$date .= "$DAYS_OF_WEEK[$wday], " if $args{'DayOfWeek'} && $args{'Date'};
- $date .= "$mday $MONTHS[$mon] $year" if $args{'Date'};
+ $date .= sprintf("%02d %s %04d", $mday, $MONTHS[$mon], $year) if $args{'Date'};
if ( $args{'Time'} ) {
$time .= sprintf("%02d:%02d", $hour, $min);
@@ -960,21 +967,20 @@ sub iCal {
Date => 1, Time => 1,
@_,
);
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
- $self->Localtime( 'utc' );
-
- #the month needs incrementing, as gmtime returns 0-11
- $mon++;
my $res;
if ( $args{'Date'} && !$args{'Time'} ) {
- $res = sprintf( '%04d%02d%02d', $year, $mon, $mday );
- }
- elsif ( !$args{'Date'} && $args{'Time'} ) {
+ my (undef, undef, undef, $mday, $mon, $year) =
+ $self->Localtime( 'user' );
+ $res = sprintf( '%04d%02d%02d', $year, $mon+1, $mday );
+ } elsif ( !$args{'Date'} && $args{'Time'} ) {
+ my ($sec, $min, $hour) =
+ $self->Localtime( 'utc' );
$res = sprintf( 'T%02d%02d%02dZ', $hour, $min, $sec );
- }
- else {
- $res = sprintf( '%04d%02d%02dT%02d%02d%02dZ', $year, $mon, $mday, $hour, $min, $sec );
+ } else {
+ my ($sec, $min, $hour, $mday, $mon, $year) =
+ $self->Localtime( 'utc' );
+ $res = sprintf( '%04d%02d%02dT%02d%02d%02dZ', $year, $mon+1, $mday, $hour, $min, $sec );
}
return $res;
}
diff --git a/rt/lib/RT/EmailParser.pm b/rt/lib/RT/EmailParser.pm
index 19dc2c9..89f7ea4 100644
--- a/rt/lib/RT/EmailParser.pm
+++ b/rt/lib/RT/EmailParser.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -110,7 +110,7 @@ sub SmartParseMIMEEntityFromScalar {
# accommodate this by pausing and retrying.
last
if ( $fh, $temp_file ) =
- eval { File::Temp::tempfile( undef, UNLINK => 0 ) };
+ eval { File::Temp::tempfile( UNLINK => 0 ) };
sleep 1;
}
if ($fh) {
@@ -546,10 +546,38 @@ sub ParseEmailAddress {
@addresses = Email::Address->parse($address_string);
}
+ $self->CleanupAddresses(@addresses);
+
return @addresses;
}
+=head2 CleanupAddresses ARRAY
+
+Massages an array of L<Email::Address> objects to make their email addresses
+more palatable.
+
+Currently this strips off surrounding single quotes around C<< ->address >> and
+B<< modifies the L<Email::Address> objects in-place >>.
+
+Returns the list of objects for convienence in C<map>/C<grep> chains.
+
+=cut
+
+sub CleanupAddresses {
+ my $self = shift;
+
+ for my $addr (@_) {
+ next unless defined $addr;
+ # Outlook sometimes sends addresses surrounded by single quotes;
+ # clean them all up
+ if ((my $email = $addr->address) =~ s/^'(.+)'$/$1/) {
+ $addr->address($email);
+ }
+ }
+ return @_;
+}
+
=head2 RescueOutlook
Outlook 2007/2010 have a bug when you write an email with the html format.
diff --git a/rt/lib/RT/Generated.pm b/rt/lib/RT/Generated.pm
index 4f74ea9..5edd7e3 100644
--- a/rt/lib/RT/Generated.pm
+++ b/rt/lib/RT/Generated.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -50,7 +50,7 @@ package RT;
use warnings;
use strict;
-our $VERSION = '4.0.13';
+our $VERSION = '4.0.19';
diff --git a/rt/lib/RT/Generated.pm.in b/rt/lib/RT/Generated.pm.in
index 91aa840..dc4163e 100644
--- a/rt/lib/RT/Generated.pm.in
+++ b/rt/lib/RT/Generated.pm.in
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Graph/Tickets.pm b/rt/lib/RT/Graph/Tickets.pm
index 753ff20..477a5d0 100644
--- a/rt/lib/RT/Graph/Tickets.pm
+++ b/rt/lib/RT/Graph/Tickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Group.pm b/rt/lib/RT/Group.pm
index d4d2802..dc52957 100755
--- a/rt/lib/RT/Group.pm
+++ b/rt/lib/RT/Group.pm
@@ -3,7 +3,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/GroupMember.pm b/rt/lib/RT/GroupMember.pm
index e3c5e1d..1d4090c 100755
--- a/rt/lib/RT/GroupMember.pm
+++ b/rt/lib/RT/GroupMember.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/GroupMembers.pm b/rt/lib/RT/GroupMembers.pm
index 52244bd..49cd8de 100755
--- a/rt/lib/RT/GroupMembers.pm
+++ b/rt/lib/RT/GroupMembers.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Groups.pm b/rt/lib/RT/Groups.pm
index e7734e0..c234858 100755
--- a/rt/lib/RT/Groups.pm
+++ b/rt/lib/RT/Groups.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Handle.pm b/rt/lib/RT/Handle.pm
index b449d20..4ea1576 100644
--- a/rt/lib/RT/Handle.pm
+++ b/rt/lib/RT/Handle.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -114,6 +114,7 @@ sub Connect {
$self->SUPER::Connect(
User => RT->Config->Get('DatabaseUser'),
Password => RT->Config->Get('DatabasePassword'),
+ DisconnectHandleOnDestroy => 1,
%args,
);
@@ -161,7 +162,6 @@ sub BuildDSN {
Port => $db_port,
Driver => $db_type,
RequireSSL => RT->Config->Get('DatabaseRequireSSL'),
- DisconnectHandleOnDestroy => 1,
);
if ( $db_type eq 'Oracle' && $db_host ) {
$args{'SID'} = delete $args{'Database'};
@@ -361,6 +361,9 @@ sub CreateDatabase {
elsif ( $db_type eq 'Pg' ) {
$status = $dbh->do("CREATE DATABASE $db_name WITH ENCODING='UNICODE' TEMPLATE template0");
}
+ elsif ( $db_type eq 'mysql' ) {
+ $status = $dbh->do("CREATE DATABASE $db_name DEFAULT CHARACTER SET utf8");
+ }
else {
$status = $dbh->do("CREATE DATABASE $db_name");
}
@@ -872,7 +875,9 @@ sub InsertData {
}
if ( $item->{'BasedOn'} ) {
- if ( $item->{'LookupType'} ) {
+ if ( $item->{'BasedOn'} =~ /^\d+$/) {
+ # Already have an ID -- should be fine
+ } elsif ( $item->{'LookupType'} ) {
my $basedon = RT::CustomField->new($RT::SystemUser);
my ($ok, $msg ) = $basedon->LoadByCols( Name => $item->{'BasedOn'},
LookupType => $item->{'LookupType'} );
@@ -1203,6 +1208,32 @@ sub _LogSQLStatement {
push @{$self->{'StatementLog'}} , ([Time::HiRes::time(), $statement, [@bind], $duration, HTML::Mason::Exception->new->as_string]);
}
+
+sub _TableNames {
+ my $self = shift;
+ my $dbh = shift || $self->dbh;
+
+ {
+ local $@;
+ if (
+ $dbh->{Driver}->{Name} eq 'Pg'
+ && $dbh->{'pg_server_version'} >= 90200
+ && !eval { DBD::Pg->VERSION('2.19.3'); 1 }
+ ) {
+ die "You're using PostgreSQL 9.2 or newer. You have to upgrade DBD::Pg module to 2.19.3 or newer: $@";
+ }
+ }
+
+ my @res;
+
+ my $sth = $dbh->table_info( '', undef, undef, "'TABLE'");
+ while ( my $table = $sth->fetchrow_hashref ) {
+ push @res, $table->{TABLE_NAME} || $table->{table_name};
+ }
+
+ return @res;
+}
+
__PACKAGE__->FinalizeDatabaseType;
RT::Base->_ImportOverlays();
diff --git a/rt/lib/RT/I18N.pm b/rt/lib/RT/I18N.pm
index 0e75b9f..bc267e4 100644
--- a/rt/lib/RT/I18N.pm
+++ b/rt/lib/RT/I18N.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -388,6 +388,7 @@ sub DecodeMIMEWordsToEncoding {
$enc_str = qq{"$enc_str"}
if $enc_str =~ /[,;]/
and $enc_str !~ /^".*"$/
+ and $prefix !~ /"$/ and $trailing !~ /^"/
and (!$field || $field =~ /^(?:To$|From$|B?Cc$|Content-)/i);
$str .= $prefix . $enc_str . $trailing;
diff --git a/rt/lib/RT/I18N/cs.pm b/rt/lib/RT/I18N/cs.pm
index faea9d7..30da114 100644
--- a/rt/lib/RT/I18N/cs.pm
+++ b/rt/lib/RT/I18N/cs.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/I18N/de.pm b/rt/lib/RT/I18N/de.pm
new file mode 100644
index 0000000..3a40a7f
--- /dev/null
+++ b/rt/lib/RT/I18N/de.pm
@@ -0,0 +1,61 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
+# <sales@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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# 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
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# 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 }}}
+
+use strict;
+use warnings;
+
+package RT::I18N::de;
+use base 'RT::I18N';
+
+sub init {
+ $_[0]->{numf_comma} = 1;
+}
+
+RT::Base->_ImportOverlays();
+
+1;
diff --git a/rt/lib/RT/I18N/fr.pm b/rt/lib/RT/I18N/fr.pm
new file mode 100644
index 0000000..23b047a
--- /dev/null
+++ b/rt/lib/RT/I18N/fr.pm
@@ -0,0 +1,69 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
+# <sales@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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# 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
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# 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 }}}
+
+use strict;
+use warnings;
+use utf8;
+
+package RT::I18N::fr;
+use base 'RT::I18N';
+
+use strict;
+use warnings;
+
+sub numf {
+ my ($handle, $num) = @_[0,1];
+ my $fr_num = $handle->SUPER::numf($num);
+ # French prefer to print 1000 as 1 000 rather than 1,000
+ $fr_num =~ tr<.,><, >;
+ return $fr_num;
+}
+
+RT::Base->_ImportOverlays();
+
+1;
diff --git a/rt/lib/RT/I18N/i_default.pm b/rt/lib/RT/I18N/i_default.pm
index 2b48c62..316f51a 100644
--- a/rt/lib/RT/I18N/i_default.pm
+++ b/rt/lib/RT/I18N/i_default.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/I18N/ru.pm b/rt/lib/RT/I18N/ru.pm
index a98636f..5b34d77 100755
--- a/rt/lib/RT/I18N/ru.pm
+++ b/rt/lib/RT/I18N/ru.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Installer.pm b/rt/lib/RT/Installer.pm
index d876e10..c48b06c 100644
--- a/rt/lib/RT/Installer.pm
+++ b/rt/lib/RT/Installer.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/CLI.pm b/rt/lib/RT/Interface/CLI.pm
index c1a6f4f..feef6b8 100644
--- a/rt/lib/RT/Interface/CLI.pm
+++ b/rt/lib/RT/Interface/CLI.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm
index ab319e6..74120ba 100755
--- a/rt/lib/RT/Interface/Email.pm
+++ b/rt/lib/RT/Interface/Email.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -431,21 +431,24 @@ sub SendEmail {
# SetOutgoingMailFrom and bounces conflict, since they both want -f
if ( $args{'Bounce'} ) {
push @args, shellwords(RT->Config->Get('SendmailBounceArguments'));
- } elsif ( RT->Config->Get('SetOutgoingMailFrom') ) {
- my $OutgoingMailAddress;
+ } elsif ( my $MailFrom = RT->Config->Get('SetOutgoingMailFrom') ) {
+ my $OutgoingMailAddress = $MailFrom =~ /\@/ ? $MailFrom : undef;
+ my $Overrides = RT->Config->Get('OverrideOutgoingMailFrom') || {};
if ($TicketObj) {
my $QueueName = $TicketObj->QueueObj->Name;
- my $QueueAddressOverride = RT->Config->Get('OverrideOutgoingMailFrom')->{$QueueName};
+ my $QueueAddressOverride = $Overrides->{$QueueName};
if ($QueueAddressOverride) {
$OutgoingMailAddress = $QueueAddressOverride;
} else {
- $OutgoingMailAddress = $TicketObj->QueueObj->CorrespondAddress;
+ $OutgoingMailAddress ||= $TicketObj->QueueObj->CorrespondAddress
+ || RT->Config->Get('CorrespondAddress');
}
}
-
- $OutgoingMailAddress ||= RT->Config->Get('OverrideOutgoingMailFrom')->{'Default'};
+ elsif ($Overrides->{'Default'}) {
+ $OutgoingMailAddress = $Overrides->{'Default'};
+ }
push @args, "-f", $OutgoingMailAddress
if $OutgoingMailAddress;
@@ -1084,7 +1087,7 @@ sub ParseCcAddressesFromHead {
&& !IgnoreCcAddress( $_ )
}
map lc $user->CanonicalizeEmailAddress( $_->address ),
- map Email::Address->parse( $args{'Head'}->get( $_ ) ),
+ map RT::EmailParser->CleanupAddresses( Email::Address->parse( $args{'Head'}->get( $_ ) ) ),
qw(To Cc);
}
@@ -1464,6 +1467,9 @@ sub Gateway {
my $head = $Message->head;
my $ErrorsTo = ParseErrorsToAddressFromHead( $head );
+ my $Sender = (ParseSenderAddressFromHead( $head ))[0];
+ my $From = $head->get("From");
+ chomp $From if defined $From;
my $MessageId = $head->get('Message-ID')
|| "<no-message-id-". time . rand(2000) .'@'. RT->Config->Get('Organization') .'>';
@@ -1548,7 +1554,8 @@ sub Gateway {
);
return (
0,
- "$ErrorsTo tried to submit a message to "
+ ($CurrentUser->EmailAddress || $CurrentUser->Name)
+ . " ($Sender) tried to submit a message to "
. $args{'Queue'}
. " without permission.",
undef
@@ -1595,7 +1602,7 @@ sub Gateway {
Explanation => $ErrStr,
MIMEObj => $Message
);
- return ( 0, "Ticket creation failed: $ErrStr", $Ticket );
+ return ( 0, "Ticket creation From: $From failed: $ErrStr", $Ticket );
}
# strip comments&corresponds from the actions we don't need
@@ -1640,7 +1647,7 @@ sub Gateway {
Explanation => $msg,
MIMEObj => $Message
);
- return ( 0, "Message not recorded: $msg", $Ticket );
+ return ( 0, "Message From: $From not recorded: $msg", $Ticket );
}
} elsif ($unsafe_actions) {
my ( $status, $msg ) = _RunUnsafeAction(
@@ -1739,6 +1746,8 @@ sub _RunUnsafeAction {
@_
);
+ my $From = $args{Message}->head->get("From");
+
if ( $args{'Action'} =~ /^take$/i ) {
my ( $status, $msg ) = $args{'Ticket'}->SetOwner( $args{'CurrentUser'}->id );
unless ($status) {
@@ -1748,7 +1757,7 @@ sub _RunUnsafeAction {
Explanation => $msg,
MIMEObj => $args{'Message'}
);
- return ( 0, "Ticket not taken" );
+ return ( 0, "Ticket not taken, by email From: $From" );
}
} elsif ( $args{'Action'} =~ /^resolve$/i ) {
my $new_status = $args{'Ticket'}->FirstInactiveStatus;
@@ -1763,11 +1772,11 @@ sub _RunUnsafeAction {
Explanation => $msg,
MIMEObj => $args{'Message'}
);
- return ( 0, "Ticket not resolved" );
+ return ( 0, "Ticket not resolved, by email From: $From" );
}
}
} else {
- return ( 0, "Not supported unsafe action $args{'Action'}", $args{'Ticket'} );
+ return ( 0, "Not supported unsafe action $args{'Action'}, by email From: $From", $args{'Ticket'} );
}
return ( 1, "Success" );
}
diff --git a/rt/lib/RT/Interface/Email/Auth/GnuPG.pm b/rt/lib/RT/Interface/Email/Auth/GnuPG.pm
index c14bcf0..5137707 100755
--- a/rt/lib/RT/Interface/Email/Auth/GnuPG.pm
+++ b/rt/lib/RT/Interface/Email/Auth/GnuPG.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Email/Auth/MailFrom.pm b/rt/lib/RT/Interface/Email/Auth/MailFrom.pm
index bfe4939..b353907 100644
--- a/rt/lib/RT/Interface/Email/Auth/MailFrom.pm
+++ b/rt/lib/RT/Interface/Email/Auth/MailFrom.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/REST.pm b/rt/lib/RT/Interface/REST.pm
index 5f8ff99..17fe446 100644
--- a/rt/lib/RT/Interface/REST.pm
+++ b/rt/lib/RT/Interface/REST.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -47,12 +47,13 @@
# END BPS TAGGED BLOCK }}}
package RT::Interface::REST;
+use LWP::MediaTypes qw(guess_media_type);
use strict;
use warnings;
use RT;
use base 'Exporter';
-our @EXPORT = qw(expand_list form_parse form_compose vpush vsplit);
+our @EXPORT = qw(expand_list form_parse form_compose vpush vsplit process_attachments);
sub custom_field_spec {
my $self = shift;
@@ -296,6 +297,45 @@ sub vsplit {
return \@words;
}
+sub process_attachments {
+ my $entity = shift;
+ my @list = @_;
+ return 1 unless @list;
+
+ my $m = $HTML::Mason::Commands::m;
+ my $cgi = $m->cgi_object;
+
+ my $i = 1;
+ foreach my $e ( @list ) {
+
+ my $fh = $cgi->upload("attachment_$i");
+ return (0, "No attachment for $e") unless $fh;
+
+ local $/=undef;
+
+ my $file = $e;
+ $file =~ s#^.*[\\/]##;
+
+ my ($tmp_fh, $tmp_fn) = File::Temp::tempfile( UNLINK => 1 );
+
+ my $buf;
+ while (sysread($fh, $buf, 8192)) {
+ syswrite($tmp_fh, $buf);
+ }
+
+ my $info = $cgi->uploadInfo($fh);
+ my $new_entity = $entity->attach(
+ Path => $tmp_fn,
+ Type => $info->{'Content-Type'} || guess_media_type($tmp_fn),
+ Filename => $file,
+ Disposition => "attachment",
+ );
+ $new_entity->bodyhandle->{'_dirty_hack_to_save_a_ref_tmp_fh'} = $tmp_fh;
+ $i++;
+ }
+ return (1);
+}
+
RT::Base->_ImportOverlays();
1;
diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm
index 5ca4a9f..1f2f488 100644
--- a/rt/lib/RT/Interface/Web.pm
+++ b/rt/lib/RT/Interface/Web.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -1283,10 +1283,16 @@ our %is_whitelisted_component = (
# While these can be used for denial-of-service against RT
# (construct a very inefficient query and trick lots of users into
# running them against RT) it's incredibly useful to be able to link
- # to a search result or bookmark a result page.
+ # to a search result (or chart) or bookmark a result page.
'/Search/Results.html' => 1,
'/Search/Simple.html' => 1,
- '/m/tickets/search' => 1,
+ '/m/tickets/search' => 1,
+ '/Search/Chart.html' => 1,
+
+ # This page takes Attachment and Transaction argument to figure
+ # out what to show, but it's read only and will deny information if you
+ # don't have ShowOutgoingEmail.
+ '/Ticket/ShowEmailRecord.html' => 1,
);
# Components which are blacklisted from automatic, argument-based whitelisting.
@@ -1762,7 +1768,7 @@ sub CreateTicket {
$RT::Logger->error("Couldn't make multipart message")
if !$rv || $rv !~ /^(?:DONE|ALREADY)$/;
- foreach ( values %{ $ARGS{'Attachments'} } ) {
+ foreach ( map $ARGS{Attachments}->{$_}, sort keys %{ $ARGS{'Attachments'} } ) {
unless ($_) {
$RT::Logger->error("Couldn't add empty attachemnt");
next;
@@ -2017,7 +2023,8 @@ sub ProcessUpdateMessage {
if ( $args{ARGSRef}->{'UpdateAttachments'} ) {
$Message->make_multipart;
- $Message->add_part($_) foreach values %{ $args{ARGSRef}->{'UpdateAttachments'} };
+ $Message->add_part($_) foreach map $args{ARGSRef}->{UpdateAttachments}{$_},
+ sort keys %{ $args{ARGSRef}->{'UpdateAttachments'} };
}
if ( $args{ARGSRef}->{'AttachTickets'} ) {
@@ -2619,18 +2626,23 @@ sub ProcessTicketReminders {
while ( my $reminder = $reminder_collection->Next ) {
my $resolve_status = $reminder->QueueObj->Lifecycle->ReminderStatusOnResolve;
if ( $reminder->Status ne $resolve_status && $args->{ 'Complete-Reminder-' . $reminder->id } ) {
- $Ticket->Reminders->Resolve($reminder);
+ my ($status, $msg) = $Ticket->Reminders->Resolve($reminder);
+ push @results, loc("Reminder #[_1]: [_2]", $reminder->id, $msg);
+
}
elsif ( $reminder->Status eq $resolve_status && !$args->{ 'Complete-Reminder-' . $reminder->id } ) {
- $Ticket->Reminders->Open($reminder);
+ my ($status, $msg) = $Ticket->Reminders->Open($reminder);
+ push @results, loc("Reminder #[_1]: [_2]", $reminder->id, $msg);
}
if ( exists( $args->{ 'Reminder-Subject-' . $reminder->id } ) && ( $reminder->Subject ne $args->{ 'Reminder-Subject-' . $reminder->id } )) {
- $reminder->SetSubject( $args->{ 'Reminder-Subject-' . $reminder->id } ) ;
+ my ($status, $msg) = $reminder->SetSubject( $args->{ 'Reminder-Subject-' . $reminder->id } ) ;
+ push @results, loc("Reminder #[_1]: [_2]", $reminder->id, $msg);
}
if ( exists( $args->{ 'Reminder-Owner-' . $reminder->id } ) && ( $reminder->Owner != $args->{ 'Reminder-Owner-' . $reminder->id } )) {
- $reminder->SetOwner( $args->{ 'Reminder-Owner-' . $reminder->id } , "Force" ) ;
+ my ($status, $msg) = $reminder->SetOwner( $args->{ 'Reminder-Owner-' . $reminder->id } , "Force" ) ;
+ push @results, loc("Reminder #[_1]: [_2]", $reminder->id, $msg);
}
if ( exists( $args->{ 'Reminder-Due-' . $reminder->id } ) && $args->{ 'Reminder-Due-' . $reminder->id } ne '' ) {
@@ -2640,7 +2652,8 @@ sub ProcessTicketReminders {
Value => $args->{ 'Reminder-Due-' . $reminder->id }
);
if ( defined $DateObj->Unix && $DateObj->Unix != $reminder->DueObj->Unix ) {
- $reminder->SetDue( $DateObj->ISO );
+ my ($status, $msg) = $reminder->SetDue( $DateObj->ISO );
+ push @results, loc("Reminder #[_1]: [_2]", $reminder->id, $msg);
}
}
}
@@ -3180,7 +3193,8 @@ sub GetColumnMapEntry {
}
# complex things
- elsif ( my ( $mainkey, $subkey ) = $args{'Name'} =~ /^(.*?)\.{(.+)}$/ ) {
+ elsif ( my ( $mainkey, $subkey ) = $args{'Name'} =~ /^(.*?)\.(.+)$/ ) {
+ $subkey =~ s/^\{(.*)\}$/$1/;
return undef unless $args{'Map'}->{$mainkey};
return $args{'Map'}{$mainkey}{ $args{'Attribute'} }
unless ref $args{'Map'}{$mainkey}{ $args{'Attribute'} } eq 'CODE';
diff --git a/rt/lib/RT/Interface/Web/Handler.pm b/rt/lib/RT/Interface/Web/Handler.pm
index a1784c2..37031b1 100644
--- a/rt/lib/RT/Interface/Web/Handler.pm
+++ b/rt/lib/RT/Interface/Web/Handler.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Web/Menu.pm b/rt/lib/RT/Interface/Web/Menu.pm
index e4e08d6..e783382 100644
--- a/rt/lib/RT/Interface/Web/Menu.pm
+++ b/rt/lib/RT/Interface/Web/Menu.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Web/QueryBuilder.pm b/rt/lib/RT/Interface/Web/QueryBuilder.pm
index 5464278..a1b0662 100755
--- a/rt/lib/RT/Interface/Web/QueryBuilder.pm
+++ b/rt/lib/RT/Interface/Web/QueryBuilder.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm b/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm
index 9bbd876..f930554 100755
--- a/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm
+++ b/rt/lib/RT/Interface/Web/QueryBuilder/Tree.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Web/Request.pm b/rt/lib/RT/Interface/Web/Request.pm
index cdd4594..13d6672 100644
--- a/rt/lib/RT/Interface/Web/Request.pm
+++ b/rt/lib/RT/Interface/Web/Request.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Interface/Web/Session.pm b/rt/lib/RT/Interface/Web/Session.pm
index 4edd9bd..aded596 100644
--- a/rt/lib/RT/Interface/Web/Session.pm
+++ b/rt/lib/RT/Interface/Web/Session.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -192,7 +192,7 @@ sub _ClearOldDB {
die "couldn't execute query: ". $dbh->errstr unless defined $rows;
}
- $RT::Logger->info("successfuly deleted $rows sessions");
+ $RT::Logger->info("successfully deleted $rows sessions");
return;
}
@@ -222,15 +222,53 @@ sub _ClearOldDir {
next;
}
tied(%session)->delete;
- $RT::Logger->info("successfuly deleted session '$id'");
+ $RT::Logger->info("successfully deleted session '$id'");
}
+ # Apache::Session::Lock::File will clean out locks older than X, but it
+ # leaves around bogus locks if they're too new, even though they're
+ # guaranteed dead. On even just largeish installs, the accumulated number
+ # of them may bump into ext3/4 filesystem limits since Apache::Session
+ # doesn't use a fan-out tree.
my $lock = Apache::Session::Lock::File->new;
$lock->clean( $dir, $older_than );
+ # Take matters into our own hands and clear bogus locks hanging around
+ # regardless of how recent they are.
+ $self->ClearOrphanLockFiles($dir);
+
return;
}
+=head3 ClearOrphanLockFiles
+
+Takes a directory in which to look for L<Apache::Session::Lock::File> locks
+which no longer have a corresponding session file. If not provided, the
+directory is taken from the session configuration data.
+
+=cut
+
+sub ClearOrphanLockFiles {
+ my $class = shift;
+ my $dir = shift || $class->Attributes->{Directory}
+ or return;
+
+ if (opendir my $dh, $dir) {
+ for (readdir $dh) {
+ next unless /^Apache-Session-([0-9a-f]{32})\.lock$/;
+ next if -e "$dir/$1";
+
+ RT->Logger->debug("deleting orphaned session lockfile '$_'");
+
+ unlink "$dir/$_"
+ or warn "Failed to unlink session lockfile $dir/$_: $!";
+ }
+ closedir $dh;
+ } else {
+ warn "Unable to open directory '$dir' for reading: $!";
+ }
+}
+
=head3 ClearByUser
Checks all sessions and if user has more then one session
@@ -243,6 +281,7 @@ sub ClearByUser {
my $class = $self->Class;
my $attrs = $self->Attributes;
+ my $deleted;
my %seen = ();
foreach my $id( @{ $self->Ids } ) {
my %session;
@@ -259,8 +298,10 @@ sub ClearByUser {
}
}
tied(%session)->delete;
- $RT::Logger->info("successfuly deleted session '$id'");
+ $RT::Logger->info("successfully deleted session '$id'");
+ $deleted++;
}
+ $self->ClearOrphanLockFiles if $deleted;
}
sub TIEHASH {
@@ -276,10 +317,8 @@ sub TIEHASH {
eval { tie %session, $class, $id, $attrs };
eval { tie %session, $class, undef, $attrs } if $@;
if ( $@ ) {
- die loc("RT couldn't store your session.") . "\n"
- . loc("This may mean that that the directory '[_1]' isn't writable or a database table is missing or corrupt.",
- $RT::MasonSessionDir)
- . "\n\n"
+ die "RT couldn't store your session. "
+ . "This may mean that that the directory '$RT::MasonSessionDir' isn't writable or a database table is missing or corrupt.\n\n"
. $@;
}
diff --git a/rt/lib/RT/Lifecycle.pm b/rt/lib/RT/Lifecycle.pm
index c905282..accef22 100644
--- a/rt/lib/RT/Lifecycle.pm
+++ b/rt/lib/RT/Lifecycle.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -707,11 +707,11 @@ sub FillCache {
}
my %seen;
- @statuses = grep !$seen{ $_ }++, @statuses;
+ @statuses = grep !$seen{ lc $_ }++, @statuses;
$lifecycle->{''} = \@statuses;
unless ( $lifecycle->{'transitions'}{''} ) {
- $lifecycle->{'transitions'}{''} = [ grep $_ ne 'deleted', @statuses ];
+ $lifecycle->{'transitions'}{''} = [ grep lc $_ ne 'deleted', @statuses ];
}
my @actions;
@@ -767,7 +767,7 @@ sub FillCache {
foreach my $type ( qw(initial active inactive), '' ) {
my %seen;
- @{ $all{ $type } } = grep !$seen{ $_ }++, @{ $all{ $type } };
+ @{ $all{ $type } } = grep !$seen{ lc $_ }++, @{ $all{ $type } };
push @{ $all{''} }, @{ $all{ $type } } if $type;
}
$LIFECYCLES_CACHE{''} = \%all;
diff --git a/rt/lib/RT/Link.pm b/rt/lib/RT/Link.pm
index 7a27747..305c345 100644
--- a/rt/lib/RT/Link.pm
+++ b/rt/lib/RT/Link.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Links.pm b/rt/lib/RT/Links.pm
index af36a5b..d90865d 100644
--- a/rt/lib/RT/Links.pm
+++ b/rt/lib/RT/Links.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectClass.pm b/rt/lib/RT/ObjectClass.pm
index 684af13..7fd8d90 100644
--- a/rt/lib/RT/ObjectClass.pm
+++ b/rt/lib/RT/ObjectClass.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectClasses.pm b/rt/lib/RT/ObjectClasses.pm
index 01cf77f..b179180 100644
--- a/rt/lib/RT/ObjectClasses.pm
+++ b/rt/lib/RT/ObjectClasses.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectCustomField.pm b/rt/lib/RT/ObjectCustomField.pm
index e7f350a..1acf891 100644
--- a/rt/lib/RT/ObjectCustomField.pm
+++ b/rt/lib/RT/ObjectCustomField.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectCustomFieldValue.pm b/rt/lib/RT/ObjectCustomFieldValue.pm
index 63da581..de4bc74 100644
--- a/rt/lib/RT/ObjectCustomFieldValue.pm
+++ b/rt/lib/RT/ObjectCustomFieldValue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectCustomFieldValues.pm b/rt/lib/RT/ObjectCustomFieldValues.pm
index a1d5391..486265e 100644
--- a/rt/lib/RT/ObjectCustomFieldValues.pm
+++ b/rt/lib/RT/ObjectCustomFieldValues.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectCustomFields.pm b/rt/lib/RT/ObjectCustomFields.pm
index 5bdc069..97e4f91 100644
--- a/rt/lib/RT/ObjectCustomFields.pm
+++ b/rt/lib/RT/ObjectCustomFields.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectTopic.pm b/rt/lib/RT/ObjectTopic.pm
index 8ca01ae..a5e36c3 100644
--- a/rt/lib/RT/ObjectTopic.pm
+++ b/rt/lib/RT/ObjectTopic.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ObjectTopics.pm b/rt/lib/RT/ObjectTopics.pm
index bdcff77..f376f53 100644
--- a/rt/lib/RT/ObjectTopics.pm
+++ b/rt/lib/RT/ObjectTopics.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Plugin.pm b/rt/lib/RT/Plugin.pm
index 1f97ec2..82f4de2 100644
--- a/rt/lib/RT/Plugin.pm
+++ b/rt/lib/RT/Plugin.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Pod/HTML.pm b/rt/lib/RT/Pod/HTML.pm
index 6896063..6904559 100644
--- a/rt/lib/RT/Pod/HTML.pm
+++ b/rt/lib/RT/Pod/HTML.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -54,6 +54,10 @@ use base 'Pod::Simple::XHTML';
use HTML::Entities qw//;
+__PACKAGE__->_accessorize(
+ "batch"
+);
+
sub new {
my $self = shift->SUPER::new(@_);
$self->index(1);
@@ -118,27 +122,35 @@ sub resolve_local_link {
my $self = shift;
my ($name, $section) = @_;
+ $name .= ""; # stringify name, it may be an object
+
$section = defined $section
? '#' . $self->idify($section, 1)
: '';
my $local;
- if ($name =~ /^RT::/) {
+ if ($name =~ /^RT(::(?!Extension::|Authen::)|$)/ or $self->batch->found($name)) {
$local = join "/",
map { $self->encode_entities($_) }
split /::/, $name;
}
- elsif ($name =~ /^rt[-_]/) {
+ elsif ($name =~ /^rt([-_]|$)/) {
$local = $self->encode_entities($name);
}
- elsif ($name eq "RT_Config" or $name eq "RT_Config.pm") {
- $local = "RT_Config";
+ elsif ($name =~ /^(\w+)_Config(\.pm)?$/) {
+ $name = "$1_Config";
+ $local = "$1_Config";
+ }
+ elsif ($name eq 'README') {
+ # We process README separately in devel/tools/rt-static-docs
+ $local = $name;
}
# These matches handle links that look like filenames, such as those we
# parse out of F<> tags.
elsif ( $name =~ m{^(?:lib/)(RT/[\w/]+?)\.pm$}
or $name =~ m{^(?:docs/)(.+?)\.pod$})
{
+ $name = join "::", split '/', $1;
$local = join "/",
map { $self->encode_entities($_) }
split /\//, $1;
@@ -146,11 +158,20 @@ sub resolve_local_link {
if ($local) {
# Resolve links correctly by going up
- my $depth = $self->batch_mode_current_level - 1;
- return ($depth ? "../" x $depth : "") . "$local.html$section";
+ my $found = $self->batch->found($name);
+ my $depth = $self->batch_mode_current_level
+ + ($found ? -1 : 1);
+ return ($depth ? "../" x $depth : "") . ($found ? "" : "rt/latest/") . "$local.html$section";
} else {
return;
}
}
+sub batch_mode_page_object_init {
+ my ($self, $batch, $module, $infile, $outfile, $depth) = @_;
+ $self->SUPER::batch_mode_page_object_init(@_[1..$#_]);
+ $self->batch( $batch );
+ return $self;
+}
+
1;
diff --git a/rt/lib/RT/Pod/HTMLBatch.pm b/rt/lib/RT/Pod/HTMLBatch.pm
index f41a43a..2545ea9 100644
--- a/rt/lib/RT/Pod/HTMLBatch.pm
+++ b/rt/lib/RT/Pod/HTMLBatch.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -84,7 +84,7 @@ sub classify {
my %page = @_;
local $_ = $page{name};
return 1 if /^(README|UPGRADING)/;
- return 1 if $_ eq "RT_Config";
+ return 1 if /^RT\w*?_Config$/;
return 1 if $_ eq "web_deployment";
return 1 if $page{infile} =~ m{^configure(\.ac)?$};
return 0;
@@ -176,4 +176,9 @@ sub esc {
Pod::Simple::HTMLBatch::esc(@_);
}
+sub found {
+ my ($self, $module) = @_;
+ return grep { $_->[0] eq $module } @{$self->_contents};
+}
+
1;
diff --git a/rt/lib/RT/Pod/Search.pm b/rt/lib/RT/Pod/Search.pm
index 29e7d43..e0670ea 100644
--- a/rt/lib/RT/Pod/Search.pm
+++ b/rt/lib/RT/Pod/Search.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Principal.pm b/rt/lib/RT/Principal.pm
index 175f1b0..76582d6 100644
--- a/rt/lib/RT/Principal.pm
+++ b/rt/lib/RT/Principal.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -263,8 +263,9 @@ sub HasRight {
return 1;
}
- $args{'Right'} = RT::ACE->CanonicalizeRightName( $args{'Right'} );
- unless ( $args{'Right'} ) {
+ if ( my $right = RT::ACE->CanonicalizeRightName( $args{'Right'} ) ) {
+ $args{'Right'} = $right;
+ } else {
$RT::Logger->error(
"Invalid right. Couldn't canonicalize right '$args{'Right'}'");
return undef;
diff --git a/rt/lib/RT/Principals.pm b/rt/lib/RT/Principals.pm
index 9cf8cbb..145ec17 100644
--- a/rt/lib/RT/Principals.pm
+++ b/rt/lib/RT/Principals.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -78,6 +78,7 @@ sub Table { 'Principals'}
sub _Init {
my $self = shift;
+ $self->{'with_disabled_column'} = 1;
return ( $self->SUPER::_Init(@_) );
}
diff --git a/rt/lib/RT/Queue.pm b/rt/lib/RT/Queue.pm
index ee68b81..677a05a 100755
--- a/rt/lib/RT/Queue.pm
+++ b/rt/lib/RT/Queue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Queues.pm b/rt/lib/RT/Queues.pm
index 45cb686..f5cd2b2 100755
--- a/rt/lib/RT/Queues.pm
+++ b/rt/lib/RT/Queues.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm
index 6601a0d..59867aa 100755
--- a/rt/lib/RT/Record.pm
+++ b/rt/lib/RT/Record.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -730,9 +730,20 @@ sub _Accessible {
}
-=head2 _EncodeLOB BODY MIME_TYPE
+=head2 _EncodeLOB BODY MIME_TYPE FILENAME
-Takes a potentially large attachment. Returns (ContentEncoding, EncodedBody) based on system configuration and selected database
+Takes a potentially large attachment. Returns (ContentEncoding,
+EncodedBody, MimeType, Filename) based on system configuration and
+selected database. Returns a custom (short) text/plain message if
+DropLongAttachments causes an attachment to not be stored.
+
+Encodes your data as base64 or Quoted-Printable as needed based on your
+Databases's restrictions and the UTF-8ness of the data being passed in. Since
+we are storing in columns marked UTF8, we must ensure that binary data is
+encoded on databases which are strict.
+
+This function expects to receive an octet string in order to properly
+evaluate and encode it. It will return an octet string.
=cut
@@ -760,7 +771,7 @@ sub _EncodeLOB {
$MaxSize = $MaxSize * 3 / 4;
# Some databases (postgres) can't handle non-utf8 data
} elsif ( !$RT::Handle->BinarySafeBLOBs
- && $MIMEType !~ /text\/plain/gi
+ && $Body =~ /\P{ASCII}/
&& !Encode::is_utf8( $Body, 1 ) ) {
$ContentEncoding = 'quoted-printable';
}
@@ -784,7 +795,7 @@ sub _EncodeLOB {
. length($Body));
$RT::Logger->info( "It started: " . substr( $Body, 0, 60 ) );
$Filename .= ".txt" if $Filename;
- return ("none", "Large attachment dropped", "plain/text", $Filename );
+ return ("none", "Large attachment dropped", "text/plain", $Filename );
}
}
@@ -805,6 +816,27 @@ sub _EncodeLOB {
}
+=head2 _DecodeLOB
+
+Unpacks data stored in the database, which may be base64 or QP encoded
+because of our need to store binary and badly encoded data in columns
+marked as UTF-8. Databases such as PostgreSQL and Oracle care that you
+are feeding them invalid UTF-8 and will refuse the content. This
+function handles unpacking the encoded data.
+
+It returns textual data as a UTF-8 string which has been processed by Encode's
+PERLQQ filter which will replace the invalid bytes with \x{HH} so you can see
+the invalid byte but won't run into problems treating the data as UTF-8 later.
+
+This is similar to how we filter all data coming in via the web UI in
+RT::Interface::Web::DecodeARGS. This filter should only end up being
+applied to old data from less UTF-8-safe versions of RT.
+
+Important Note - This function expects an octet string and returns a
+character string for non-binary data.
+
+=cut
+
sub _DecodeLOB {
my $self = shift;
my $ContentType = shift || '';
@@ -821,7 +853,7 @@ sub _DecodeLOB {
return ( $self->loc( "Unknown ContentEncoding [_1]", $ContentEncoding ) );
}
if ( RT::I18N::IsTextualContentType($ContentType) ) {
- $Content = Encode::decode_utf8($Content) unless Encode::is_utf8($Content);
+ $Content = Encode::decode('UTF-8',$Content,Encode::FB_PERLQQ) unless Encode::is_utf8($Content);
}
return ($Content);
}
@@ -1372,7 +1404,7 @@ sub _AddLink {
if ( $args{'Base'} and $args{'Target'} ) {
$RT::Logger->debug( "$self tried to create a link. both base and target were specified" );
- return ( 0, $self->loc("Can't specifiy both base and target") );
+ return ( 0, $self->loc("Can't specify both base and target") );
}
elsif ( $args{'Base'} ) {
$args{'Target'} = $self->URI();
@@ -1450,7 +1482,7 @@ sub _DeleteLink {
if ( $args{'Base'} and $args{'Target'} ) {
$RT::Logger->debug("$self ->_DeleteLink. got both Base and Target");
- return ( 0, $self->loc("Can't specifiy both base and target") );
+ return ( 0, $self->loc("Can't specify both base and target") );
}
elsif ( $args{'Base'} ) {
$args{'Target'} = $self->URI();
@@ -1686,7 +1718,7 @@ Returns the path RT uses to figure out which custom fields apply to this object.
sub CustomFieldLookupType {
my $self = shift;
- return ref($self);
+ return ref($self) || $self;
}
@@ -1789,7 +1821,7 @@ sub _AddCustomFieldValue {
my $is_the_same = 1;
if ( defined $args{'Value'} ) {
$is_the_same = 0 unless defined $old_content
- && lc $old_content eq lc $args{'Value'};
+ && $old_content eq $args{'Value'};
} else {
$is_the_same = 0 if defined $old_content;
}
diff --git a/rt/lib/RT/Reminders.pm b/rt/lib/RT/Reminders.pm
index 42f4e1d..133dbf0 100644
--- a/rt/lib/RT/Reminders.pm
+++ b/rt/lib/RT/Reminders.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -122,7 +122,7 @@ sub Add {
return ( 0, $self->loc( "Failed to load ticket [_1]", $self->Ticket ) );
}
- if ( $ticket->Status eq 'deleted' ) {
+ if ( lc $ticket->Status eq 'deleted' ) {
return ( 0, $self->loc("Can't link to a deleted ticket") );
}
@@ -134,6 +134,7 @@ sub Add {
RefersTo => $self->Ticket,
Type => 'reminder',
Queue => $self->TicketObj->Queue,
+ Status => $self->TicketObj->QueueObj->Lifecycle->ReminderStatusOnOpen,
);
$self->TicketObj->_NewTransaction(
Type => 'AddReminder',
diff --git a/rt/lib/RT/Report/Tickets.pm b/rt/lib/RT/Report/Tickets.pm
index b73bbaa..aa27b17 100644
--- a/rt/lib/RT/Report/Tickets.pm
+++ b/rt/lib/RT/Report/Tickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -111,7 +111,7 @@ sub Groupings {
sub Label {
my $self = shift;
my $field = shift;
- if ( $field =~ /^(?:CF|CustomField)\.{(.*)}$/ ) {
+ if ( $field =~ /^(?:CF|CustomField)\.\{(.*)\}$/ ) {
my $cf = $1;
return $self->CurrentUser->loc( "Custom field '[_1]'", $cf ) if $cf =~ /\D/;
my $obj = RT::CustomField->new( $self->CurrentUser );
@@ -239,7 +239,7 @@ sub _FieldToFunction {
$func = "SUBSTR($func,1,4)";
}
$args{'FUNCTION'} = $func;
- } elsif ( $field =~ /^(?:CF|CustomField)\.{(.*)}$/ ) { #XXX: use CFDecipher method
+ } elsif ( $field =~ /^(?:CF|CustomField)\.\{(.*)\}$/ ) { #XXX: use CFDecipher method
my $cf_name = $1;
my $cf = RT::CustomField->new( $self->CurrentUser );
$cf->Load($cf_name);
diff --git a/rt/lib/RT/Report/Tickets/Entry.pm b/rt/lib/RT/Report/Tickets/Entry.pm
index eb38993..fc0b633 100644
--- a/rt/lib/RT/Report/Tickets/Entry.pm
+++ b/rt/lib/RT/Report/Tickets/Entry.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Rule.pm b/rt/lib/RT/Rule.pm
index c5c8b09..6751915 100644
--- a/rt/lib/RT/Rule.pm
+++ b/rt/lib/RT/Rule.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Ruleset.pm b/rt/lib/RT/Ruleset.pm
index 26227b7..e6267da 100644
--- a/rt/lib/RT/Ruleset.pm
+++ b/rt/lib/RT/Ruleset.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/SQL.pm b/rt/lib/RT/SQL.pm
index 15715a7..94b5665 100644
--- a/rt/lib/RT/SQL.pm
+++ b/rt/lib/RT/SQL.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/SavedSearch.pm b/rt/lib/RT/SavedSearch.pm
index 7c4df8b..3e0e928 100644
--- a/rt/lib/RT/SavedSearch.pm
+++ b/rt/lib/RT/SavedSearch.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/SavedSearches.pm b/rt/lib/RT/SavedSearches.pm
index af8f482..25c7e4a 100644
--- a/rt/lib/RT/SavedSearches.pm
+++ b/rt/lib/RT/SavedSearches.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Scrip.pm b/rt/lib/RT/Scrip.pm
index 5fa7165..71080a0 100755
--- a/rt/lib/RT/Scrip.pm
+++ b/rt/lib/RT/Scrip.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ScripAction.pm b/rt/lib/RT/ScripAction.pm
index 44f9bd8..be8b130 100755
--- a/rt/lib/RT/ScripAction.pm
+++ b/rt/lib/RT/ScripAction.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ScripActions.pm b/rt/lib/RT/ScripActions.pm
index a3a1622..41ac60e 100755
--- a/rt/lib/RT/ScripActions.pm
+++ b/rt/lib/RT/ScripActions.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ScripCondition.pm b/rt/lib/RT/ScripCondition.pm
index e7e4652..0d0fa66 100755
--- a/rt/lib/RT/ScripCondition.pm
+++ b/rt/lib/RT/ScripCondition.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/ScripConditions.pm b/rt/lib/RT/ScripConditions.pm
index 6668497..368008b 100755
--- a/rt/lib/RT/ScripConditions.pm
+++ b/rt/lib/RT/ScripConditions.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Scrips.pm b/rt/lib/RT/Scrips.pm
index af8323e..de9d1ea 100755
--- a/rt/lib/RT/Scrips.pm
+++ b/rt/lib/RT/Scrips.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Search.pm b/rt/lib/RT/Search.pm
index 7ec50de..8e13987 100755
--- a/rt/lib/RT/Search.pm
+++ b/rt/lib/RT/Search.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Search/ActiveTicketsInQueue.pm b/rt/lib/RT/Search/ActiveTicketsInQueue.pm
index da1cdb6..1c69e93 100644
--- a/rt/lib/RT/Search/ActiveTicketsInQueue.pm
+++ b/rt/lib/RT/Search/ActiveTicketsInQueue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Search/FromSQL.pm b/rt/lib/RT/Search/FromSQL.pm
index 4cb17f5..2f27fee 100644
--- a/rt/lib/RT/Search/FromSQL.pm
+++ b/rt/lib/RT/Search/FromSQL.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Search/Googleish.pm b/rt/lib/RT/Search/Googleish.pm
index f8465f0..d11fa2b 100644
--- a/rt/lib/RT/Search/Googleish.pm
+++ b/rt/lib/RT/Search/Googleish.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -197,6 +197,7 @@ our @GUESS = (
[ 10 => sub { return "subject" if $_[1] } ],
[ 20 => sub { return "id" if /^#?\d+$/ } ],
[ 30 => sub { return "requestor" if /\w+@\w+/} ],
+ [ 35 => sub { return "domain" if /^@\w+/} ],
[ 40 => sub {
return "status" if RT::Queue->new( $_[2] )->IsValidStatus( $_ )
}],
@@ -260,6 +261,7 @@ sub HandleWatcher {
return watcher => (!$_[2] and $_[1] eq "me") ? "Watcher.id = '__CurrentUser__'" : "Watcher = '$_[1]'";
}
sub HandleRequestor { return requestor => "Requestor STARTSWITH '$_[1]'"; }
+sub HandleDomain { $_[1] =~ s/^@?/@/; return requestor => "Requestor ENDSWITH '$_[1]'"; }
sub HandleQueue { return queue => "Queue = '$_[1]'"; }
sub HandleQ { return queue => "Queue = '$_[1]'"; }
sub HandleCf { return "cf.$_[3]" => "'CF.{$_[3]}' LIKE '$_[1]'"; }
diff --git a/rt/lib/RT/SearchBuilder.pm b/rt/lib/RT/SearchBuilder.pm
index adc8a98..8b808c6 100644
--- a/rt/lib/RT/SearchBuilder.pm
+++ b/rt/lib/RT/SearchBuilder.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -86,9 +86,13 @@ sub _Init {
$self->SUPER::_Init( 'Handle' => $RT::Handle);
}
+sub _Handle { return $RT::Handle }
+
sub CleanSlate {
my $self = shift;
$self->{'_sql_aliases'} = {};
+ delete $self->{'handled_disabled_column'};
+ delete $self->{'find_disabled_rows'};
return $self->SUPER::CleanSlate(@_);
}
diff --git a/rt/lib/RT/SharedSetting.pm b/rt/lib/RT/SharedSetting.pm
index 3467167..0bdd196 100644
--- a/rt/lib/RT/SharedSetting.pm
+++ b/rt/lib/RT/SharedSetting.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/SharedSettings.pm b/rt/lib/RT/SharedSettings.pm
index 6e7ec3b..51b4965 100644
--- a/rt/lib/RT/SharedSettings.pm
+++ b/rt/lib/RT/SharedSettings.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder.pm b/rt/lib/RT/Shredder.pm
index bebd599..125ed0d 100644
--- a/rt/lib/RT/Shredder.pm
+++ b/rt/lib/RT/Shredder.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -164,6 +164,21 @@ your F<RT_SiteConfig.pm>:
Be sure to specify an absolute path.
+=head1 Database Indexes
+
+We have found that the following indexes significantly speed up
+shredding on most databases.
+
+ CREATE INDEX SHREDDER_CGM1 ON CachedGroupMembers(MemberId, GroupId, Disabled);
+ CREATE INDEX SHREDDER_CGM2 ON CachedGroupMembers(ImmediateParentId,MemberId);
+ CREATE INDEX SHREDDER_CGM3 on CachedGroupMembers (Via, Id);
+
+ CREATE UNIQUE INDEX SHREDDER_GM1 ON GroupMembers(MemberId, GroupId);
+
+ CREATE INDEX SHREDDER_TXN1 ON Transactions(ReferenceType, OldReference);
+ CREATE INDEX SHREDDER_TXN2 ON Transactions(ReferenceType, NewReference);
+ CREATE INDEX SHREDDER_TXN3 ON Transactions(Type, OldValue);
+ CREATE INDEX SHREDDER_TXN4 ON Transactions(Type, NewValue)
=head1 INFORMATION FOR DEVELOPERS
diff --git a/rt/lib/RT/Shredder/ACE.pm b/rt/lib/RT/Shredder/ACE.pm
index 7a50d9a..1f882e2 100644
--- a/rt/lib/RT/Shredder/ACE.pm
+++ b/rt/lib/RT/Shredder/ACE.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Attachment.pm b/rt/lib/RT/Shredder/Attachment.pm
index 9cd4088..a3705fa 100644
--- a/rt/lib/RT/Shredder/Attachment.pm
+++ b/rt/lib/RT/Shredder/Attachment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/CachedGroupMember.pm b/rt/lib/RT/Shredder/CachedGroupMember.pm
index 9f1668f..ffd4ada 100644
--- a/rt/lib/RT/Shredder/CachedGroupMember.pm
+++ b/rt/lib/RT/Shredder/CachedGroupMember.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Constants.pm b/rt/lib/RT/Shredder/Constants.pm
index b09b52f..b71e191 100644
--- a/rt/lib/RT/Shredder/Constants.pm
+++ b/rt/lib/RT/Shredder/Constants.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/CustomField.pm b/rt/lib/RT/Shredder/CustomField.pm
index 8c7dc22..e6fcc5f 100644
--- a/rt/lib/RT/Shredder/CustomField.pm
+++ b/rt/lib/RT/Shredder/CustomField.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/CustomFieldValue.pm b/rt/lib/RT/Shredder/CustomFieldValue.pm
index 9a9d369..0cefc9b 100644
--- a/rt/lib/RT/Shredder/CustomFieldValue.pm
+++ b/rt/lib/RT/Shredder/CustomFieldValue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Dependencies.pm b/rt/lib/RT/Shredder/Dependencies.pm
index 9364887..fdfcb8b 100644
--- a/rt/lib/RT/Shredder/Dependencies.pm
+++ b/rt/lib/RT/Shredder/Dependencies.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Dependency.pm b/rt/lib/RT/Shredder/Dependency.pm
index 2800771..b94f43a 100644
--- a/rt/lib/RT/Shredder/Dependency.pm
+++ b/rt/lib/RT/Shredder/Dependency.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Exceptions.pm b/rt/lib/RT/Shredder/Exceptions.pm
index 8c1d6ed..d0cc2db 100644
--- a/rt/lib/RT/Shredder/Exceptions.pm
+++ b/rt/lib/RT/Shredder/Exceptions.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Group.pm b/rt/lib/RT/Shredder/Group.pm
index bbf84ab..ad74e97 100644
--- a/rt/lib/RT/Shredder/Group.pm
+++ b/rt/lib/RT/Shredder/Group.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/GroupMember.pm b/rt/lib/RT/Shredder/GroupMember.pm
index a7e0b42..ed632e3 100644
--- a/rt/lib/RT/Shredder/GroupMember.pm
+++ b/rt/lib/RT/Shredder/GroupMember.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Link.pm b/rt/lib/RT/Shredder/Link.pm
index a442910..32d583d 100644
--- a/rt/lib/RT/Shredder/Link.pm
+++ b/rt/lib/RT/Shredder/Link.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/ObjectCustomFieldValue.pm b/rt/lib/RT/Shredder/ObjectCustomFieldValue.pm
index 7612f4a..dab4d5b 100644
--- a/rt/lib/RT/Shredder/ObjectCustomFieldValue.pm
+++ b/rt/lib/RT/Shredder/ObjectCustomFieldValue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/POD.pm b/rt/lib/RT/Shredder/POD.pm
index 6cc8695..ee4fb09 100644
--- a/rt/lib/RT/Shredder/POD.pm
+++ b/rt/lib/RT/Shredder/POD.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin.pm b/rt/lib/RT/Shredder/Plugin.pm
index 60ba333..84d20eb 100644
--- a/rt/lib/RT/Shredder/Plugin.pm
+++ b/rt/lib/RT/Shredder/Plugin.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Attachments.pm b/rt/lib/RT/Shredder/Plugin/Attachments.pm
index f0f64a1..05f264e 100644
--- a/rt/lib/RT/Shredder/Plugin/Attachments.pm
+++ b/rt/lib/RT/Shredder/Plugin/Attachments.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Base.pm b/rt/lib/RT/Shredder/Plugin/Base.pm
index 0adadfd..7ada97e 100644
--- a/rt/lib/RT/Shredder/Plugin/Base.pm
+++ b/rt/lib/RT/Shredder/Plugin/Base.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Base/Dump.pm b/rt/lib/RT/Shredder/Plugin/Base/Dump.pm
index 903a962..945bd93 100644
--- a/rt/lib/RT/Shredder/Plugin/Base/Dump.pm
+++ b/rt/lib/RT/Shredder/Plugin/Base/Dump.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Base/Search.pm b/rt/lib/RT/Shredder/Plugin/Base/Search.pm
index a493cd8..bb21bd6 100644
--- a/rt/lib/RT/Shredder/Plugin/Base/Search.pm
+++ b/rt/lib/RT/Shredder/Plugin/Base/Search.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Objects.pm b/rt/lib/RT/Shredder/Plugin/Objects.pm
index 2090574..ebfe2a0 100644
--- a/rt/lib/RT/Shredder/Plugin/Objects.pm
+++ b/rt/lib/RT/Shredder/Plugin/Objects.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/SQLDump.pm b/rt/lib/RT/Shredder/Plugin/SQLDump.pm
index 2e7c259..cc0d4cc 100644
--- a/rt/lib/RT/Shredder/Plugin/SQLDump.pm
+++ b/rt/lib/RT/Shredder/Plugin/SQLDump.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Summary.pm b/rt/lib/RT/Shredder/Plugin/Summary.pm
index 9b533bc..9ccd66e 100644
--- a/rt/lib/RT/Shredder/Plugin/Summary.pm
+++ b/rt/lib/RT/Shredder/Plugin/Summary.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Tickets.pm b/rt/lib/RT/Shredder/Plugin/Tickets.pm
index 0344487..180c45c 100644
--- a/rt/lib/RT/Shredder/Plugin/Tickets.pm
+++ b/rt/lib/RT/Shredder/Plugin/Tickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Plugin/Users.pm b/rt/lib/RT/Shredder/Plugin/Users.pm
index 244a262..5b7ccae 100644
--- a/rt/lib/RT/Shredder/Plugin/Users.pm
+++ b/rt/lib/RT/Shredder/Plugin/Users.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Principal.pm b/rt/lib/RT/Shredder/Principal.pm
index 5dc04b3..14f446a 100644
--- a/rt/lib/RT/Shredder/Principal.pm
+++ b/rt/lib/RT/Shredder/Principal.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Queue.pm b/rt/lib/RT/Shredder/Queue.pm
index 80a1c84..426170e 100644
--- a/rt/lib/RT/Shredder/Queue.pm
+++ b/rt/lib/RT/Shredder/Queue.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Record.pm b/rt/lib/RT/Shredder/Record.pm
index d70bf12..6a8777a 100644
--- a/rt/lib/RT/Shredder/Record.pm
+++ b/rt/lib/RT/Shredder/Record.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Scrip.pm b/rt/lib/RT/Shredder/Scrip.pm
index 74878b6..9a80cf9 100644
--- a/rt/lib/RT/Shredder/Scrip.pm
+++ b/rt/lib/RT/Shredder/Scrip.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/ScripAction.pm b/rt/lib/RT/Shredder/ScripAction.pm
index cdad7e4..ebe7ce5 100644
--- a/rt/lib/RT/Shredder/ScripAction.pm
+++ b/rt/lib/RT/Shredder/ScripAction.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/ScripCondition.pm b/rt/lib/RT/Shredder/ScripCondition.pm
index 857f062..6d2b83e 100644
--- a/rt/lib/RT/Shredder/ScripCondition.pm
+++ b/rt/lib/RT/Shredder/ScripCondition.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Template.pm b/rt/lib/RT/Shredder/Template.pm
index 4ac6daf..89859a6 100644
--- a/rt/lib/RT/Shredder/Template.pm
+++ b/rt/lib/RT/Shredder/Template.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Ticket.pm b/rt/lib/RT/Shredder/Ticket.pm
index 2e54536..b70e8bb 100644
--- a/rt/lib/RT/Shredder/Ticket.pm
+++ b/rt/lib/RT/Shredder/Ticket.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/Transaction.pm b/rt/lib/RT/Shredder/Transaction.pm
index 37e6ba5..1fe42f9 100644
--- a/rt/lib/RT/Shredder/Transaction.pm
+++ b/rt/lib/RT/Shredder/Transaction.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Shredder/User.pm b/rt/lib/RT/Shredder/User.pm
index 6e19da7..0cd5bf3 100644
--- a/rt/lib/RT/Shredder/User.pm
+++ b/rt/lib/RT/Shredder/User.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Squish.pm b/rt/lib/RT/Squish.pm
index e64b711..e0e6106 100644
--- a/rt/lib/RT/Squish.pm
+++ b/rt/lib/RT/Squish.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Squish/CSS.pm b/rt/lib/RT/Squish/CSS.pm
index 1e2a453..5ce3882 100644
--- a/rt/lib/RT/Squish/CSS.pm
+++ b/rt/lib/RT/Squish/CSS.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Squish/JS.pm b/rt/lib/RT/Squish/JS.pm
index 4dd24b7..9a4cac5 100644
--- a/rt/lib/RT/Squish/JS.pm
+++ b/rt/lib/RT/Squish/JS.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/System.pm b/rt/lib/RT/System.pm
index cf3d2d0..4c1f5f1 100644
--- a/rt/lib/RT/System.pm
+++ b/rt/lib/RT/System.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Template.pm b/rt/lib/RT/Template.pm
index fd4b511..d15c1cd 100755
--- a/rt/lib/RT/Template.pm
+++ b/rt/lib/RT/Template.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -256,7 +256,7 @@ sub Create {
$args{'Queue'} = $QueueObj->Id;
}
- my $result = $self->SUPER::Create(
+ my ( $result, $msg ) = $self->SUPER::Create(
Content => $args{'Content'},
Queue => $args{'Queue'},
Description => $args{'Description'},
@@ -264,7 +264,11 @@ sub Create {
Type => $args{'Type'},
);
- return ($result);
+ if ( wantarray ) {
+ return ( $result, $msg );
+ } else {
+ return ( $result );
+ }
}
diff --git a/rt/lib/RT/Templates.pm b/rt/lib/RT/Templates.pm
index b4da636..7d117fa 100755
--- a/rt/lib/RT/Templates.pm
+++ b/rt/lib/RT/Templates.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Test.pm b/rt/lib/RT/Test.pm
index 55fd88a..2a1f52b 100644
--- a/rt/lib/RT/Test.pm
+++ b/rt/lib/RT/Test.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -51,6 +51,7 @@ package RT::Test;
use strict;
use warnings;
+BEGIN { $^W = 1 };
use base 'Test::More';
@@ -925,7 +926,7 @@ sub set_rights {
$acl->Limit( FIELD => 'RightName', OPERATOR => '!=', VALUE => 'SuperUser' );
while ( my $ace = $acl->Next ) {
my $obj = $ace->PrincipalObj->Object;
- if ( $obj->isa('RT::Group') && $obj->Type eq 'UserEquiv' && $obj->Instance == RT->Nobody->id ) {
+ if ( $obj->isa('RT::Group') && ($obj->Type||'') eq 'UserEquiv' && $obj->Instance == RT->Nobody->id ) {
next;
}
$ace->Delete;
@@ -1502,9 +1503,7 @@ sub stop_server {
my $in_end = shift;
return unless @SERVERS;
- my $sig = 'TERM';
- $sig = 'INT' if $ENV{'RT_TEST_WEB_HANDLER'} eq "plack";
- kill $sig, @SERVERS;
+ kill 'TERM', @SERVERS;
foreach my $pid (@SERVERS) {
if ($ENV{RT_TEST_WEB_HANDLER} =~ /^apache/) {
sleep 1 while kill 0, $pid;
diff --git a/rt/lib/RT/Test/Apache.pm b/rt/lib/RT/Test/Apache.pm
index 256945a..31ad9bc 100644
--- a/rt/lib/RT/Test/Apache.pm
+++ b/rt/lib/RT/Test/Apache.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Test/Email.pm b/rt/lib/RT/Test/Email.pm
index 8cf6839..54aa87d 100644
--- a/rt/lib/RT/Test/Email.pm
+++ b/rt/lib/RT/Test/Email.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Test/GnuPG.pm b/rt/lib/RT/Test/GnuPG.pm
index ec44672..95c21f8 100644
--- a/rt/lib/RT/Test/GnuPG.pm
+++ b/rt/lib/RT/Test/GnuPG.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Test/Web.pm b/rt/lib/RT/Test/Web.pm
index 8611102..8164481 100644
--- a/rt/lib/RT/Test/Web.pm
+++ b/rt/lib/RT/Test/Web.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Ticket.pm b/rt/lib/RT/Ticket.pm
index 6165378..6a8b40c 100755
--- a/rt/lib/RT/Ticket.pm
+++ b/rt/lib/RT/Ticket.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -642,7 +642,7 @@ sub Create {
}
}
- if ( $obj && $obj->Status eq 'deleted' ) {
+ if ( $obj && lc $obj->Status eq 'deleted' ) {
push @non_fatal_errors,
$self->loc("Linking. Can't link to a deleted ticket");
next;
@@ -2681,7 +2681,7 @@ sub AddLink {
}
return ( 0, "Can't link to a deleted ticket" )
- if $other_ticket && $other_ticket->Status eq 'deleted';
+ if $other_ticket && lc $other_ticket->Status eq 'deleted';
return $self->_AddLink(%args);
}
diff --git a/rt/lib/RT/Tickets.pm b/rt/lib/RT/Tickets.pm
index 06b17e2..2220a07 100755
--- a/rt/lib/RT/Tickets.pm
+++ b/rt/lib/RT/Tickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -142,9 +142,9 @@ our %FIELD_METADATA = (
QueueCc => [ 'WATCHERFIELD' => 'Cc' => 'Queue', ], #loc_left_pair
QueueAdminCc => [ 'WATCHERFIELD' => 'AdminCc' => 'Queue', ], #loc_left_pair
QueueWatcher => [ 'WATCHERFIELD' => undef => 'Queue', ], #loc_left_pair
- CustomFieldValue => [ 'CUSTOMFIELD', ], #loc_left_pair
- CustomField => [ 'CUSTOMFIELD', ], #loc_left_pair
- CF => [ 'CUSTOMFIELD', ], #loc_left_pair
+ CustomFieldValue => [ 'CUSTOMFIELD' => 'Ticket' ], #loc_left_pair
+ CustomField => [ 'CUSTOMFIELD' => 'Ticket' ], #loc_left_pair
+ CF => [ 'CUSTOMFIELD' => 'Ticket' ], #loc_left_pair
Updated => [ 'TRANSDATE', ], #loc_left_pair
RequestorGroup => [ 'MEMBERSHIPFIELD' => 'Requestor', ], #loc_left_pair
CCGroup => [ 'MEMBERSHIPFIELD' => 'Cc', ], #loc_left_pair
@@ -443,10 +443,6 @@ sub _LinkLimit {
my $is_null = 0;
$is_null = 1 if !$value || $value =~ /^null$/io;
- unless ($is_null) {
- $value = RT::URI->new( $sb->CurrentUser )->CanonicalizeURI( $value );
- }
-
my $direction = $meta->[1] || '';
my ($matchfield, $linkfield) = ('', '');
if ( $direction eq 'To' ) {
@@ -473,6 +469,7 @@ sub _LinkLimit {
$op = ($op =~ /^(=|IS)$/i)? 'IS': 'IS NOT';
}
elsif ( $value =~ /\D/ ) {
+ $value = RT::URI->new( $sb->CurrentUser )->CanonicalizeURI( $value );
$is_local = 0;
}
$matchfield = "Local$matchfield" if $is_local;
@@ -977,13 +974,18 @@ sub _WatcherLimit {
}
$rest{SUBKEY} ||= 'EmailAddress';
- my $groups = $self->_RoleGroupsJoin( Type => $type, Class => $class, New => !$type );
+ my ($groups, $group_members, $users);
+ if ( $rest{'BUNDLE'} ) {
+ ($groups, $group_members, $users) = @{ $rest{'BUNDLE'} };
+ } else {
+ $groups = $self->_RoleGroupsJoin( Type => $type, Class => $class, New => !$type );
+ }
$self->_OpenParen;
if ( $op =~ /^IS(?: NOT)?$/i ) {
# is [not] empty case
- my $group_members = $self->_GroupMembersJoin( GroupsAlias => $groups );
+ $group_members ||= $self->_GroupMembersJoin( GroupsAlias => $groups );
# to avoid joining the table Users into the query, we just join GM
# and make sure we don't match records where group is member of itself
$self->SUPER::Limit(
@@ -1021,7 +1023,7 @@ sub _WatcherLimit {
$users_obj->RowsPerPage(2);
my @users = @{ $users_obj->ItemsArrayRef };
- my $group_members = $self->_GroupMembersJoin( GroupsAlias => $groups );
+ $group_members ||= $self->_GroupMembersJoin( GroupsAlias => $groups );
if ( @users <= 1 ) {
my $uid = 0;
$uid = $users[0]->id if @users;
@@ -1046,7 +1048,7 @@ sub _WatcherLimit {
VALUE => "$group_members.MemberId",
QUOTEVALUE => 0,
);
- my $users = $self->Join(
+ $users ||= $self->Join(
TYPE => 'LEFT',
ALIAS1 => $group_members,
FIELD1 => 'MemberId',
@@ -1072,10 +1074,10 @@ sub _WatcherLimit {
} else {
# positive condition case
- my $group_members = $self->_GroupMembersJoin(
+ $group_members ||= $self->_GroupMembersJoin(
GroupsAlias => $groups, New => 1, Left => 0
);
- my $users = $self->Join(
+ $users ||= $self->Join(
TYPE => 'LEFT',
ALIAS1 => $group_members,
FIELD1 => 'MemberId',
@@ -1092,6 +1094,7 @@ sub _WatcherLimit {
);
}
$self->_CloseParen;
+ return ($groups, $group_members, $users);
}
sub _RoleGroupsJoin {
@@ -1342,33 +1345,44 @@ sub _WatcherMembershipLimit {
Try and turn a CF descriptor into (cfid, cfname) object pair.
+Takes an optional second parameter of the CF LookupType, defaults to Ticket CFs.
+
=cut
sub _CustomFieldDecipher {
- my ($self, $string) = @_;
+ my ($self, $string, $lookuptype) = @_;
+ $lookuptype ||= $self->_SingularClass->CustomFieldLookupType;
- my ($queue, $field, $column) = ($string =~ /^(?:(.+?)\.)?{(.+)}(?:\.(Content|LargeContent))?$/);
+ my ($object, $field, $column) = ($string =~ /^(?:(.+?)\.)?\{(.+)\}(?:\.(Content|LargeContent))?$/);
$field ||= ($string =~ /^{(.*?)}$/)[0] || $string;
- my $cf;
- if ( $queue ) {
- my $q = RT::Queue->new( $self->CurrentUser );
- $q->Load( $queue );
+ my ($cf, $applied_to);
+
+ if ( $object ) {
+ my $record_class = RT::CustomField->RecordClassFromLookupType($lookuptype);
+ $applied_to = $record_class->new( $self->CurrentUser );
+ $applied_to->Load( $object );
- if ( $q->id ) {
- # $queue = $q->Name; # should we normalize the queue?
- $cf = $q->CustomField( $field );
+ if ( $applied_to->id ) {
+ RT->Logger->debug("Limiting to CFs identified by '$field' applied to $record_class #@{[$applied_to->id]} (loaded via '$object')");
}
else {
- $RT::Logger->warning("Queue '$queue' doesn't exist, parsed from '$string'");
- $queue = 0;
+ RT->Logger->warning("$record_class '$object' doesn't exist, parsed from '$string'");
+ $object = 0;
+ undef $applied_to;
}
}
- elsif ( $field =~ /\D/ ) {
- $queue = '';
+
+ if ( $field =~ /\D/ ) {
+ $object ||= '';
my $cfs = RT::CustomFields->new( $self->CurrentUser );
- $cfs->Limit( FIELD => 'Name', VALUE => $field );
- $cfs->LimitToLookupType('RT::Queue-RT::Ticket');
+ $cfs->Limit( FIELD => 'Name', VALUE => $field, ($applied_to ? (CASESENSITIVE => 0) : ()) );
+ $cfs->LimitToLookupType($lookuptype);
+
+ if ($applied_to) {
+ $cfs->SetContextObject($applied_to);
+ $cfs->LimitToObjectId($applied_to->id);
+ }
# if there is more then one field the current user can
# see with the same name then we shouldn't return cf object
@@ -1381,9 +1395,11 @@ sub _CustomFieldDecipher {
else {
$cf = RT::CustomField->new( $self->CurrentUser );
$cf->Load( $field );
+ $cf->SetContextObject($applied_to)
+ if $cf->id and $applied_to;
}
- return ($queue, $field, $cf, $column);
+ return ($object, $field, $cf, $column);
}
=head2 _CustomFieldJoin
@@ -1392,8 +1408,14 @@ Factor out the Join of custom fields so we can use it for sorting too
=cut
+our %JOIN_ALIAS_FOR_LOOKUP_TYPE = (
+ RT::Ticket->CustomFieldLookupType => sub { "main" },
+);
+
sub _CustomFieldJoin {
- my ($self, $cfkey, $cfid, $field) = @_;
+ my ($self, $cfkey, $cfid, $field, $type) = @_;
+ $type ||= RT::Ticket->CustomFieldLookupType;
+
# Perform one Join per CustomField
if ( $self->{_sql_object_cfv_alias}{$cfkey} ||
$self->{_sql_cf_alias}{$cfkey} )
@@ -1402,17 +1424,21 @@ sub _CustomFieldJoin {
$self->{_sql_cf_alias}{$cfkey} );
}
- my ($TicketCFs, $CFs);
+ my $ObjectAlias = $JOIN_ALIAS_FOR_LOOKUP_TYPE{$type}
+ ? $JOIN_ALIAS_FOR_LOOKUP_TYPE{$type}->($self)
+ : die "We don't know how to join on $type";
+
+ my ($ObjectCFs, $CFs);
if ( $cfid ) {
- $TicketCFs = $self->{_sql_object_cfv_alias}{$cfkey} = $self->Join(
+ $ObjectCFs = $self->{_sql_object_cfv_alias}{$cfkey} = $self->Join(
TYPE => 'LEFT',
- ALIAS1 => 'main',
+ ALIAS1 => $ObjectAlias,
FIELD1 => 'id',
TABLE2 => 'ObjectCustomFieldValues',
FIELD2 => 'ObjectId',
);
$self->SUPER::Limit(
- LEFTJOIN => $TicketCFs,
+ LEFTJOIN => $ObjectCFs,
FIELD => 'CustomField',
VALUE => $cfid,
ENTRYAGGREGATOR => 'AND'
@@ -1444,7 +1470,7 @@ sub _CustomFieldJoin {
LEFTJOIN => $CFs,
ENTRYAGGREGATOR => 'AND',
FIELD => 'LookupType',
- VALUE => 'RT::Queue-RT::Ticket',
+ VALUE => $type,
);
$self->SUPER::Limit(
LEFTJOIN => $CFs,
@@ -1453,7 +1479,7 @@ sub _CustomFieldJoin {
VALUE => $field,
);
- $TicketCFs = $self->{_sql_object_cfv_alias}{$cfkey} = $self->Join(
+ $ObjectCFs = $self->{_sql_object_cfv_alias}{$cfkey} = $self->Join(
TYPE => 'LEFT',
ALIAS1 => $CFs,
FIELD1 => 'id',
@@ -1461,28 +1487,29 @@ sub _CustomFieldJoin {
FIELD2 => 'CustomField',
);
$self->SUPER::Limit(
- LEFTJOIN => $TicketCFs,
+ LEFTJOIN => $ObjectCFs,
FIELD => 'ObjectId',
- VALUE => 'main.id',
+ VALUE => "$ObjectAlias.id",
QUOTEVALUE => 0,
ENTRYAGGREGATOR => 'AND',
);
}
+
$self->SUPER::Limit(
- LEFTJOIN => $TicketCFs,
+ LEFTJOIN => $ObjectCFs,
FIELD => 'ObjectType',
- VALUE => 'RT::Ticket',
+ VALUE => RT::CustomField->ObjectTypeFromLookupType($type),
ENTRYAGGREGATOR => 'AND'
);
$self->SUPER::Limit(
- LEFTJOIN => $TicketCFs,
+ LEFTJOIN => $ObjectCFs,
FIELD => 'Disabled',
OPERATOR => '=',
VALUE => '0',
ENTRYAGGREGATOR => 'AND'
);
- return ($TicketCFs, $CFs);
+ return ($ObjectCFs, $CFs);
}
=head2 _CustomFieldLimit
@@ -1501,12 +1528,16 @@ use Regexp::Common::net::CIDR;
sub _CustomFieldLimit {
my ( $self, $_field, $op, $value, %rest ) = @_;
+ my $meta = $FIELD_METADATA{ $_field };
+ my $class = $meta->[1] || 'Ticket';
+ my $type = "RT::$class"->CustomFieldLookupType;
+
my $field = $rest{'SUBKEY'} || die "No field specified";
# For our sanity, we can only limit on one queue at a time
- my ($queue, $cfid, $cf, $column);
- ($queue, $field, $cf, $column) = $self->_CustomFieldDecipher( $field );
+ my ($object, $cfid, $cf, $column);
+ ($object, $field, $cf, $column) = $self->_CustomFieldDecipher( $field, $type );
$cfid = $cf ? $cf->id : 0 ;
# If we're trying to find custom fields that don't match something, we
@@ -1602,16 +1633,16 @@ sub _CustomFieldLimit {
my $single_value = !$cf || !$cfid || $cf->SingleValue;
- my $cfkey = $cfid ? $cfid : "$queue.$field";
+ my $cfkey = $cfid ? $cfid : "$type-$object.$field";
if ( $null_op && !$column ) {
# IS[ NOT] NULL without column is the same as has[ no] any CF value,
# we can reuse our default joins for this operation
# with column specified we have different situation
- my ($TicketCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field );
+ my ($ObjectCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field, $type );
$self->_OpenParen;
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'id',
OPERATOR => $op,
VALUE => $value,
@@ -1634,11 +1665,11 @@ sub _CustomFieldLimit {
$self->_OpenParen;
if ( $op !~ /NOT|!=|<>/i ) { # positive equation
$self->_CustomFieldLimit(
- 'CF', '<=', $end_ip, %rest,
+ $_field, '<=', $end_ip, %rest,
SUBKEY => $rest{'SUBKEY'}. '.Content',
);
$self->_CustomFieldLimit(
- 'CF', '>=', $start_ip, %rest,
+ $_field, '>=', $start_ip, %rest,
SUBKEY => $rest{'SUBKEY'}. '.LargeContent',
ENTRYAGGREGATOR => 'AND',
);
@@ -1646,20 +1677,20 @@ sub _CustomFieldLimit {
# estimations and scan less rows
# have to disable this tweak because of ipv6
# $self->_CustomFieldLimit(
-# $field, '>=', '000.000.000.000', %rest,
+# $_field, '>=', '000.000.000.000', %rest,
# SUBKEY => $rest{'SUBKEY'}. '.Content',
# ENTRYAGGREGATOR => 'AND',
# );
# $self->_CustomFieldLimit(
-# $field, '<=', '255.255.255.255', %rest,
+# $_field, '<=', '255.255.255.255', %rest,
# SUBKEY => $rest{'SUBKEY'}. '.LargeContent',
# ENTRYAGGREGATOR => 'AND',
# );
}
else { # negative equation
- $self->_CustomFieldLimit($field, '>', $end_ip, %rest);
+ $self->_CustomFieldLimit($_field, '>', $end_ip, %rest);
$self->_CustomFieldLimit(
- $field, '<', $start_ip, %rest,
+ $_field, '<', $start_ip, %rest,
SUBKEY => $rest{'SUBKEY'}. '.LargeContent',
ENTRYAGGREGATOR => 'OR',
);
@@ -1671,7 +1702,7 @@ sub _CustomFieldLimit {
}
elsif ( !$negative_op || $single_value ) {
$cfkey .= '.'. $self->{'_sql_multiple_cfs_index'}++ if !$single_value && !$range_op;
- my ($TicketCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field );
+ my ($ObjectCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field, $type );
$self->_OpenParen;
@@ -1682,7 +1713,7 @@ sub _CustomFieldLimit {
# otherwise search in Content and in LargeContent
if ( $column ) {
$self->_SQLLimit( $fix_op->(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => $column,
OPERATOR => $op,
VALUE => $value,
@@ -1708,7 +1739,7 @@ sub _CustomFieldLimit {
$self->_OpenParen;
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => ">=",
VALUE => $daystart,
@@ -1716,7 +1747,7 @@ sub _CustomFieldLimit {
);
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => "<",
VALUE => $dayend,
@@ -1729,7 +1760,7 @@ sub _CustomFieldLimit {
elsif ( $op eq '=' || $op eq '!=' || $op eq '<>' ) {
if ( length( Encode::encode_utf8($value) ) < 256 ) {
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => $op,
VALUE => $value,
@@ -1740,14 +1771,14 @@ sub _CustomFieldLimit {
else {
$self->_OpenParen;
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => '=',
VALUE => '',
ENTRYAGGREGATOR => 'OR'
);
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => 'IS',
VALUE => 'NULL',
@@ -1755,7 +1786,7 @@ sub _CustomFieldLimit {
);
$self->_CloseParen;
$self->_SQLLimit( $fix_op->(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'LargeContent',
OPERATOR => $op,
VALUE => $value,
@@ -1766,7 +1797,7 @@ sub _CustomFieldLimit {
}
else {
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => $op,
VALUE => $value,
@@ -1777,14 +1808,14 @@ sub _CustomFieldLimit {
$self->_OpenParen;
$self->_OpenParen;
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => '=',
VALUE => '',
ENTRYAGGREGATOR => 'OR'
);
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => 'IS',
VALUE => 'NULL',
@@ -1792,7 +1823,7 @@ sub _CustomFieldLimit {
);
$self->_CloseParen;
$self->_SQLLimit( $fix_op->(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'LargeContent',
OPERATOR => $op,
VALUE => $value,
@@ -1826,7 +1857,7 @@ sub _CustomFieldLimit {
if ($negative_op) {
$self->_SQLLimit(
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => $column || 'Content',
OPERATOR => 'IS',
VALUE => 'NULL',
@@ -1840,7 +1871,7 @@ sub _CustomFieldLimit {
}
else {
$cfkey .= '.'. $self->{'_sql_multiple_cfs_index'}++;
- my ($TicketCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field );
+ my ($ObjectCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field, $type );
# reverse operation
$op =~ s/!|NOT\s+//i;
@@ -1849,8 +1880,8 @@ sub _CustomFieldLimit {
# otherwise search in Content and in LargeContent
if ( $column ) {
$self->SUPER::Limit( $fix_op->(
- LEFTJOIN => $TicketCFs,
- ALIAS => $TicketCFs,
+ LEFTJOIN => $ObjectCFs,
+ ALIAS => $ObjectCFs,
FIELD => $column,
OPERATOR => $op,
VALUE => $value,
@@ -1859,8 +1890,8 @@ sub _CustomFieldLimit {
}
else {
$self->SUPER::Limit(
- LEFTJOIN => $TicketCFs,
- ALIAS => $TicketCFs,
+ LEFTJOIN => $ObjectCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'Content',
OPERATOR => $op,
VALUE => $value,
@@ -1869,7 +1900,7 @@ sub _CustomFieldLimit {
}
$self->_SQLLimit(
%rest,
- ALIAS => $TicketCFs,
+ ALIAS => $ObjectCFs,
FIELD => 'id',
OPERATOR => 'IS',
VALUE => 'NULL',
@@ -1979,10 +2010,10 @@ sub OrderByCols {
}
push @res, { %$row, ALIAS => $users, FIELD => $subkey };
} elsif ( defined $meta->[0] && $meta->[0] eq 'CUSTOMFIELD' ) {
- my ($queue, $field, $cf_obj, $column) = $self->_CustomFieldDecipher( $subkey );
- my $cfkey = $cf_obj ? $cf_obj->id : "$queue.$field";
+ my ($object, $field, $cf_obj, $column) = $self->_CustomFieldDecipher( $subkey );
+ my $cfkey = $cf_obj ? $cf_obj->id : "$object.$field";
$cfkey .= ".ordering" if !$cf_obj || ($cf_obj->MaxValues||0) != 1;
- my ($TicketCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, ($cf_obj ?$cf_obj->id :0) , $field );
+ my ($ObjectCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, ($cf_obj ?$cf_obj->id :0) , $field );
# this is described in _CustomFieldLimit
$self->_SQLLimit(
ALIAS => $CFs,
@@ -2004,7 +2035,7 @@ sub OrderByCols {
}
my $CFvs = $self->Join(
TYPE => 'LEFT',
- ALIAS1 => $TicketCFs,
+ ALIAS1 => $ObjectCFs,
FIELD1 => 'CustomField',
TABLE2 => 'CustomFieldValues',
FIELD2 => 'CustomField',
@@ -2013,12 +2044,12 @@ sub OrderByCols {
LEFTJOIN => $CFvs,
FIELD => 'Name',
QUOTEVALUE => 0,
- VALUE => $TicketCFs . ".Content",
+ VALUE => $ObjectCFs . ".Content",
ENTRYAGGREGATOR => 'AND'
);
push @res, { %$row, ALIAS => $CFvs, FIELD => 'SortOrder' };
- push @res, { %$row, ALIAS => $TicketCFs, FIELD => 'Content' };
+ push @res, { %$row, ALIAS => $ObjectCFs, FIELD => 'Content' };
} elsif ( $field eq "Custom" && $subkey eq "Ownership") {
# PAW logic is "reversed"
my $order = "ASC";
@@ -3144,7 +3175,7 @@ sub LimitCustomField {
$self->Limit(
VALUE => $args{VALUE},
FIELD => "CF"
- .(defined $args{'QUEUE'}? ".{$args{'QUEUE'}}" : '' )
+ .(defined $args{'QUEUE'}? ".$args{'QUEUE'}" : '' )
.".{" . $CF->Name . "}",
OPERATOR => $args{OPERATOR},
CUSTOMFIELD => 1,
diff --git a/rt/lib/RT/Tickets_SQL.pm b/rt/lib/RT/Tickets_SQL.pm
index 608862a..f667b06 100644
--- a/rt/lib/RT/Tickets_SQL.pm
+++ b/rt/lib/RT/Tickets_SQL.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -74,7 +74,7 @@ sub _InitSQL {
sub _SQLLimit {
my $self = shift;
- my %args = (@_);
+ my %args = (FIELD => '', @_);
if ($args{'FIELD'} eq 'EffectiveId' &&
(!$args{'ALIAS'} || $args{'ALIAS'} eq 'main' ) ) {
$self->{'looking_at_effective_id'} = 1;
@@ -171,19 +171,69 @@ sub _parser {
my @bundle;
my $ea = '';
+ # Bundling of joins is implemented by dynamically tracking a parallel query
+ # tree in %sub_tree as the TicketSQL is parsed. Don't be fooled by
+ # _close_bundle(), @bundle, and %can_bundle; they are completely unused for
+ # quite a long time and removed in RT 4.2. For now they stay, a useless
+ # relic.
+ #
+ # Only positive, OR'd watcher conditions are bundled currently. Each key
+ # in %sub_tree is a watcher type (Requestor, Cc, AdminCc) or the generic
+ # "Watcher" for any watcher type. Owner is not bundled because it is
+ # denormalized into a Tickets column and doesn't need a join. AND'd
+ # conditions are not bundled since a record may have multiple watchers
+ # which independently match the conditions, thus necessitating two joins.
+ #
+ # The values of %sub_tree are arrayrefs made up of:
+ #
+ # * Open parentheses "(" pushed on by the OpenParen callback
+ # * Arrayrefs of bundled join aliases pushed on by the Condition callback
+ # * Entry aggregators (AND/OR) pushed on by the EntryAggregator callback
+ #
+ # The CloseParen callback takes care of backing off the query trees until
+ # outside of the just-closed parenthetical, thus restoring the tree state
+ # an equivalent of before the parenthetical was entered.
+ #
+ # The Condition callback handles starting a new subtree or extending an
+ # existing one, determining if bundling the current condition with any
+ # subtree is possible, and pruning any dangling entry aggregators from
+ # trees.
+ #
+
+ my %sub_tree;
+ my $depth = 0;
+
my %callback;
$callback{'OpenParen'} = sub {
$self->_close_bundle(@bundle); @bundle = ();
- $self->_OpenParen
+ $self->_OpenParen;
+ $depth++;
+ push @$_, '(' foreach values %sub_tree;
};
$callback{'CloseParen'} = sub {
$self->_close_bundle(@bundle); @bundle = ();
$self->_CloseParen;
+ $depth--;
+ foreach my $list ( values %sub_tree ) {
+ if ( $list->[-1] eq '(' ) {
+ pop @$list;
+ pop @$list if $list->[-1] =~ /^(?:AND|OR)$/i;
+ }
+ else {
+ pop @$list while $list->[-2] ne '(';
+ $list->[-1] = pop @$list;
+ }
+ }
+ };
+ $callback{'EntryAggregator'} = sub {
+ $ea = $_[0] || '';
+ push @$_, $ea foreach grep @$_ && $_->[-1] ne '(', values %sub_tree;
};
- $callback{'EntryAggregator'} = sub { $ea = $_[0] || '' };
$callback{'Condition'} = sub {
my ($key, $op, $value) = @_;
+ my ($negative_op, $null_op, $inv_op, $range_op)
+ = $self->ClassifySQLOperation( $op );
# key has dot then it's compound variant and we have subkey
my $subkey = '';
($key, $subkey) = ($1, $2) if $key =~ /^([^\.]+)\.(.+)$/;
@@ -225,10 +275,28 @@ sub _parser {
}
else {
$self->_close_bundle(@bundle); @bundle = ();
- $sub->( $self, $key, $op, $value,
+ my @res; my $bundle_with;
+ if ( $class eq 'WATCHERFIELD' && $key ne 'Owner' && !$negative_op && (!$null_op || $subkey) ) {
+ if ( !$sub_tree{$key} ) {
+ $sub_tree{$key} = [ ('(')x$depth, \@res ];
+ } else {
+ $bundle_with = $self->_check_bundling_possibility( $string, @{ $sub_tree{$key} } );
+ if ( $sub_tree{$key}[-1] eq '(' ) {
+ push @{ $sub_tree{$key} }, \@res;
+ }
+ }
+ }
+
+ # Remove our aggregator from subtrees where our condition didn't get added
+ pop @$_ foreach grep @$_ && $_->[-1] =~ /^(?:AND|OR)$/i, values %sub_tree;
+
+ # A reference to @res may be pushed onto $sub_tree{$key} from
+ # above, and we fill it here.
+ @res = $sub->( $self, $key, $op, $value,
SUBCLAUSE => '', # don't need anymore
ENTRYAGGREGATOR => $ea,
SUBKEY => $subkey,
+ BUNDLE => $bundle_with,
);
}
$self->{_sql_looking_at}{lc $key} = 1;
@@ -238,6 +306,29 @@ sub _parser {
$self->_close_bundle(@bundle); @bundle = ();
}
+sub _check_bundling_possibility {
+ my $self = shift;
+ my $string = shift;
+ my @list = reverse @_;
+ while (my $e = shift @list) {
+ next if $e eq '(';
+ if ( lc($e) eq 'and' ) {
+ return undef;
+ }
+ elsif ( lc($e) eq 'or' ) {
+ return shift @list;
+ }
+ else {
+ # should not happen
+ $RT::Logger->error(
+ "Joins optimization failed when parsing '$string'. It's bug in RT, contact Best Practical"
+ );
+ die "Internal error. Contact your system administrator.";
+ }
+ }
+ return undef;
+}
+
=head2 ClausesToSQL
=cut
@@ -292,8 +383,9 @@ sub FromSQL {
$self->{_sql_query} = $query;
eval { $self->_parser( $query ); };
if ( $@ ) {
- $RT::Logger->error( $@ );
- return (0, $@);
+ my $error = "$@";
+ $RT::Logger->error("Couldn't parse query: $error");
+ return (0, $error);
}
# We only want to look at EffectiveId's (mostly) for these searches.
diff --git a/rt/lib/RT/Topic.pm b/rt/lib/RT/Topic.pm
index 3e91e9d..d6a88e1 100644
--- a/rt/lib/RT/Topic.pm
+++ b/rt/lib/RT/Topic.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Topics.pm b/rt/lib/RT/Topics.pm
index 01674fb..5c735b7 100644
--- a/rt/lib/RT/Topics.pm
+++ b/rt/lib/RT/Topics.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Transaction.pm b/rt/lib/RT/Transaction.pm
index 48d4e8c..5c903e9 100755
--- a/rt/lib/RT/Transaction.pm
+++ b/rt/lib/RT/Transaction.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -368,24 +368,9 @@ sub Content {
}
if ( $args{'Quote'} ) {
+ $content = $self->ApplyQuoteWrap(content => $content,
+ cols => $args{'Wrap'} );
- # What's the longest line like?
- my $max = 0;
- foreach ( split ( /\n/, $content ) ) {
- $max = length if length > $max;
- }
-
- if ( $max > $args{'Wrap'}+6 ) { # 76 ) {
- require Text::Wrapper;
- my $wrapper = Text::Wrapper->new(
- columns => $args{'Wrap'},
- body_start => ( $max > 70 * 3 ? ' ' : '' ),
- par_start => ''
- );
- $content = $wrapper->wrap($content);
- }
-
- $content =~ s/^/> /gm;
$content = $self->QuoteHeader . "\n$content\n\n";
}
@@ -405,6 +390,84 @@ sub QuoteHeader {
return $self->loc("On [_1], [_2] wrote:", $self->CreatedAsString, $self->CreatorObj->Name);
}
+=head2 ApplyQuoteWrap PARAMHASH
+
+Wrapper to calculate wrap criteria and apply quote wrapping if needed.
+
+=cut
+
+sub ApplyQuoteWrap {
+ my $self = shift;
+ my %args = @_;
+ my $content = $args{content};
+
+ # What's the longest line like?
+ my $max = 0;
+ foreach ( split ( /\n/, $args{content} ) ) {
+ $max = length if length > $max;
+ }
+
+ if ( $max > 76 ) {
+ require Text::Quoted;
+ require Text::Wrapper;
+
+ my $structure = Text::Quoted::extract($args{content});
+ $content = $self->QuoteWrap(content_ref => $structure,
+ cols => $args{cols},
+ max => $max );
+ }
+
+ $content =~ s/^/> /gm; # use regex since string might be multi-line
+ return $content;
+}
+
+=head2 QuoteWrap PARAMHASH
+
+Wrap the contents of transactions based on Wrap settings, maintaining
+the quote character from the original.
+
+=cut
+
+sub QuoteWrap {
+ my $self = shift;
+ my %args = @_;
+ my $ref = $args{content_ref};
+ my $final_string;
+
+ if ( ref $ref eq 'ARRAY' ){
+ foreach my $array (@$ref){
+ $final_string .= $self->QuoteWrap(content_ref => $array,
+ cols => $args{cols},
+ max => $args{max} );
+ }
+ }
+ elsif ( ref $ref eq 'HASH' ){
+ return $ref->{quoter} . "\n" if $ref->{empty}; # Blank line
+
+ my $col = $args{cols} - (length $ref->{quoter});
+ my $wrapper = Text::Wrapper->new( columns => $col );
+
+ # Wrap on individual lines to honor incoming line breaks
+ # Otherwise deliberate separate lines (like a list or a sig)
+ # all get combined incorrectly into single paragraphs.
+
+ my @lines = split /\n/, $ref->{text};
+ my $wrap = join '', map { $wrapper->wrap($_) } @lines;
+ my $quoter = $ref->{quoter};
+
+ # Only add the space if actually quoting
+ $quoter .= ' ' if length $quoter;
+ $wrap =~ s/^/$quoter/mg; # use regex since string might be multi-line
+
+ return $wrap;
+ }
+ else{
+ $RT::Logger->warning("Can't apply quoting with $ref");
+ return;
+ }
+ return $final_string;
+}
+
=head2 Addresses
@@ -725,8 +788,9 @@ sub BriefDescription {
my $self = shift;
my $field = $self->loc('CustomField');
+ my $cf;
if ( $self->Field ) {
- my $cf = RT::CustomField->new( $self->CurrentUser );
+ $cf = RT::CustomField->new( $self->CurrentUser );
$cf->SetContextObject( $self->Object );
$cf->Load( $self->Field );
$field = $cf->Name();
@@ -736,6 +800,44 @@ sub BriefDescription {
my $new = $self->NewValue;
my $old = $self->OldValue;
+ if ( $cf ) {
+
+ if ( $cf->Type eq 'DateTime' ) {
+ if ($old) {
+ my $date = RT::Date->new( $self->CurrentUser );
+ $date->Set( Format => 'ISO', Value => $old );
+ $old = $date->AsString;
+ }
+
+ if ($new) {
+ my $date = RT::Date->new( $self->CurrentUser );
+ $date->Set( Format => 'ISO', Value => $new );
+ $new = $date->AsString;
+ }
+ }
+ elsif ( $cf->Type eq 'Date' ) {
+ if ($old) {
+ my $date = RT::Date->new( $self->CurrentUser );
+ $date->Set(
+ Format => 'unknown',
+ Value => $old,
+ Timezone => 'UTC',
+ );
+ $old = $date->AsString( Time => 0, Timezone => 'UTC' );
+ }
+
+ if ($new) {
+ my $date = RT::Date->new( $self->CurrentUser );
+ $date->Set(
+ Format => 'unknown',
+ Value => $new,
+ Timezone => 'UTC',
+ );
+ $new = $date->AsString( Time => 0, Timezone => 'UTC' );
+ }
+ }
+ }
+
if ( !defined($old) || $old eq '' ) {
return $self->loc("[_1] [_2] added", $field, $new);
}
@@ -938,7 +1040,8 @@ sub BriefDescription {
else {
return $self->loc( "[_1] changed from [_2] to [_3]",
$self->loc($self->Field),
- ($self->OldValue? "'".$self->OldValue ."'" : $self->loc("(no value)")) , "'". $self->NewValue."'" );
+ ($self->OldValue? "'".$self->OldValue ."'" : $self->loc("(no value)")),
+ ($self->NewValue? "'".$self->NewValue ."'" : $self->loc("(no value)")));
}
},
PurgeTransaction => sub {
diff --git a/rt/lib/RT/Transactions.pm b/rt/lib/RT/Transactions.pm
index 3c9dac4..82bd50f 100755
--- a/rt/lib/RT/Transactions.pm
+++ b/rt/lib/RT/Transactions.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/URI.pm b/rt/lib/RT/URI.pm
index c0958ca..11a9e3e 100644
--- a/rt/lib/RT/URI.pm
+++ b/rt/lib/RT/URI.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -199,6 +199,8 @@ sub _GetResolver {
if ($resolver) {
$self->{'resolver'} = $resolver;
} else {
+ RT->Logger->warning("Failed to create new resolver object for scheme '$scheme': $@")
+ if $@ !~ m{Can't locate RT/URI/\Q$scheme\E};
$self->{'resolver'} = RT::URI::base->new($self->CurrentUser);
}
diff --git a/rt/lib/RT/URI/a.pm b/rt/lib/RT/URI/a.pm
index 9475ba1..76bd4e8 100644
--- a/rt/lib/RT/URI/a.pm
+++ b/rt/lib/RT/URI/a.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/URI/base.pm b/rt/lib/RT/URI/base.pm
index 63af140..820f83f 100644
--- a/rt/lib/RT/URI/base.pm
+++ b/rt/lib/RT/URI/base.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/URI/fsck_com_article.pm b/rt/lib/RT/URI/fsck_com_article.pm
index 2b2132f..34c81a8 100644
--- a/rt/lib/RT/URI/fsck_com_article.pm
+++ b/rt/lib/RT/URI/fsck_com_article.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/URI/fsck_com_rt.pm b/rt/lib/RT/URI/fsck_com_rt.pm
index 34249d0..9f68aa5 100644
--- a/rt/lib/RT/URI/fsck_com_rt.pm
+++ b/rt/lib/RT/URI/fsck_com_rt.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/URI/t.pm b/rt/lib/RT/URI/t.pm
index 71c81fa..d3a1214 100644
--- a/rt/lib/RT/URI/t.pm
+++ b/rt/lib/RT/URI/t.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm
index 5511b9f..018ac8a 100755
--- a/rt/lib/RT/User.pm
+++ b/rt/lib/RT/User.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Users.pm b/rt/lib/RT/Users.pm
index 0f5ca70..1c75f42 100755
--- a/rt/lib/RT/Users.pm
+++ b/rt/lib/RT/Users.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Util.pm b/rt/lib/RT/Util.pm
index 38c3c20..9720f1d 100644
--- a/rt/lib/RT/Util.pm
+++ b/rt/lib/RT/Util.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -65,8 +65,11 @@ sub safe_run_child (&) {
# values. Instead we set values, eval code, check pid
# on failure and reset values only in our original
# process
+ my ($oldv_dbh, $oldv_rth);
my $dbh = $RT::Handle->dbh;
+ $oldv_dbh = $dbh->{'InactiveDestroy'} if $dbh;
$dbh->{'InactiveDestroy'} = 1 if $dbh;
+ $oldv_rth = $RT::Handle->{'DisconnectHandleOnDestroy'};
$RT::Handle->{'DisconnectHandleOnDestroy'} = 0;
my ($reader, $writer);
@@ -90,8 +93,8 @@ sub safe_run_child (&) {
my $err = $@;
$err =~ s/^Stack:.*$//ms;
if ( $our_pid == $$ ) {
- $dbh->{'InactiveDestroy'} = 0 if $dbh;
- $RT::Handle->{'DisconnectHandleOnDestroy'} = 1;
+ $dbh->{'InactiveDestroy'} = $oldv_dbh if $dbh;
+ $RT::Handle->{'DisconnectHandleOnDestroy'} = $oldv_rth;
die "System Error: $err";
} else {
print $writer "System Error: $err";
@@ -104,8 +107,8 @@ sub safe_run_child (&) {
my ($response) = $reader->getline;
warn $response if $response;
- $dbh->{'InactiveDestroy'} = 0 if $dbh;
- $RT::Handle->{'DisconnectHandleOnDestroy'} = 1;
+ $dbh->{'InactiveDestroy'} = $oldv_dbh if $dbh;
+ $RT::Handle->{'DisconnectHandleOnDestroy'} = $oldv_rth;
return $want? (@res) : $res[0];
}