summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Attachment_Overlay.pm
diff options
context:
space:
mode:
authorivan <ivan>2009-12-31 13:16:41 +0000
committerivan <ivan>2009-12-31 13:16:41 +0000
commitb4b0c7e72d7eaee2fbfc7022022c9698323203dd (patch)
treeba4cd21399e412c32fe3737eaa8478e3271509f9 /rt/lib/RT/Attachment_Overlay.pm
parent2dfda73eeb3eae2d4f894099754794ef07d060dd (diff)
import rt 3.8.7
Diffstat (limited to 'rt/lib/RT/Attachment_Overlay.pm')
-rw-r--r--rt/lib/RT/Attachment_Overlay.pm604
1 files changed, 373 insertions, 231 deletions
diff --git a/rt/lib/RT/Attachment_Overlay.pm b/rt/lib/RT/Attachment_Overlay.pm
index 7ab6d0ae9..1d508c0fe 100644
--- a/rt/lib/RT/Attachment_Overlay.pm
+++ b/rt/lib/RT/Attachment_Overlay.pm
@@ -1,8 +1,8 @@
# BEGIN BPS TAGGED BLOCK {{{
#
# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
+#
+# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -45,10 +45,10 @@
# those contributions and any derivatives thereof.
#
# END BPS TAGGED BLOCK }}}
-=head1 SYNOPSIS
- use RT::Attachment;
+=head1 SYNOPSIS
+ use RT::Attachment;
=head1 DESCRIPTION
@@ -56,15 +56,9 @@ This module should never be instantiated directly by client code. it's an intern
module which should only be instantiated through exported APIs in Ticket, Queue and other
similar objects.
-
=head1 METHODS
-=begin testing
-
-ok (require RT::Attachment);
-
-=end testing
=cut
@@ -74,13 +68,12 @@ package RT::Attachment;
use strict;
no warnings qw(redefine);
+use RT::Transaction;
use MIME::Base64;
use MIME::QuotedPrint;
-
-# {{{ sub _OverlayAccessible
sub _OverlayAccessible {
- {
+ {
TransactionId => { 'read'=>1, 'public'=>1, 'write' => 0 },
MessageId => { 'read'=>1, 'write' => 0 },
Parent => { 'read'=>1, 'write' => 0 },
@@ -94,32 +87,6 @@ sub _OverlayAccessible {
Created => { 'read'=>1, 'auto'=>1, },
};
}
-# }}}
-
-# {{{ sub TransactionObj
-
-=head2 TransactionObj
-
-Returns the transaction object asscoiated with this attachment.
-
-=cut
-
-sub TransactionObj {
- require RT::Transaction;
- my $self=shift;
- unless (exists $self->{_TransactionObj}) {
- $self->{_TransactionObj}=RT::Transaction->new($self->CurrentUser);
- $self->{_TransactionObj}->Load($self->TransactionId);
- }
- unless ($self->{_TransactionObj}->Id) {
- $RT::Logger->crit("Attachment ".$self->id." can't find transaction ".$self->TransactionId." which it is ostensibly part of. That's bad");
- }
- return $self->{_TransactionObj};
-}
-
-# }}}
-
-# {{{ sub Create
=head2 Create
@@ -139,20 +106,19 @@ sub Create {
Attachment => undef,
@_ );
- #For ease of reference
+ # For ease of reference
my $Attachment = $args{'Attachment'};
- #if we didn't specify a ticket, we need to bail
- if ( $args{'TransactionId'} == 0 ) {
- $RT::Logger->crit( "RT::Attachment->Create couldn't, as you didn't specify a transaction\n" );
+ # if we didn't specify a ticket, we need to bail
+ unless ( $args{'TransactionId'} ) {
+ $RT::Logger->crit( "RT::Attachment->Create couldn't, as you didn't specify a transaction" );
return (0);
-
}
- #If we possibly can, collapse it to a singlepart
+ # If we possibly can, collapse it to a singlepart
$Attachment->make_singlepart;
- #Get the subject
+ # Get the subject
my $Subject = $Attachment->head->get( 'subject', 0 );
defined($Subject) or $Subject = '';
chomp($Subject);
@@ -161,27 +127,30 @@ sub Create {
my $MessageId = $Attachment->head->get( 'Message-ID', 0 );
defined($MessageId) or $MessageId = '';
chomp ($MessageId);
- $MessageId =~ s/^<(.*)>$/$1/go;
-
+ $MessageId =~ s/^<(.*?)>$/$1/o;
#Get the filename
my $Filename = $Attachment->head->recommended_filename;
+ # MIME::Head doesn't support perl strings well and can return
+ # octets which later will be double encoded in low-level code
+ my $head = $Attachment->head->as_string;
+ utf8::decode( $head );
+
# If a message has no bodyhandle, that means that it has subparts (or appears to)
# and we should act accordingly.
unless ( defined $Attachment->bodyhandle ) {
-
- my $id = $self->SUPER::Create(
+ my ($id) = $self->SUPER::Create(
TransactionId => $args{'TransactionId'},
- Parent => 0,
+ Parent => $args{'Parent'},
ContentType => $Attachment->mime_type,
- Headers => $Attachment->head->as_string,
+ Headers => $head,
MessageId => $MessageId,
- Subject => $Subject
+ Subject => $Subject,
);
-
+
unless ($id) {
- $RT::Logger->crit("Attachment insert failed - ".$RT::Handle->dbh->errstr);
+ $RT::Logger->crit("Attachment insert failed - ". $RT::Handle->dbh->errstr);
}
foreach my $part ( $Attachment->parts ) {
@@ -192,7 +161,7 @@ sub Create {
Attachment => $part,
);
unless ($id) {
- $RT::Logger->crit("Attachment insert failed - ".$RT::Handle->dbh->errstr);
+ $RT::Logger->crit("Attachment insert failed: ". $RT::Handle->dbh->errstr);
}
}
return ($id);
@@ -201,69 +170,115 @@ sub Create {
#If it's not multipart
else {
- my ($ContentEncoding, $Body) = $self->_EncodeLOB( $Attachment->bodyhandle->as_string,
- $Attachment->mime_type
- );
+ my ($ContentEncoding, $Body) = $self->_EncodeLOB(
+ $Attachment->bodyhandle->as_string,
+ $Attachment->mime_type
+ );
+
my $id = $self->SUPER::Create(
TransactionId => $args{'TransactionId'},
ContentType => $Attachment->mime_type,
ContentEncoding => $ContentEncoding,
Parent => $args{'Parent'},
- Headers => $Attachment->head->as_string,
+ Headers => $head,
Subject => $Subject,
Content => $Body,
Filename => $Filename,
MessageId => $MessageId,
);
+
unless ($id) {
- $RT::Logger->crit("Attachment insert failed - ".$RT::Handle->dbh->errstr);
+ $RT::Logger->crit("Attachment insert failed: ". $RT::Handle->dbh->errstr);
}
-
- return ($id);
+ return $id;
}
}
-# }}}
-
-
=head2 Import
Create an attachment exactly as specified in the named parameters.
=cut
-
sub Import {
my $self = shift;
- my %args = ( ContentEncoding => 'none',
+ my %args = ( ContentEncoding => 'none', @_ );
- @_ );
+ ( $args{'ContentEncoding'}, $args{'Content'} ) =
+ $self->_EncodeLOB( $args{'Content'}, $args{'MimeType'} );
+ return ( $self->SUPER::Create(%args) );
+}
- ($args{'ContentEncoding'}, $args{'Content'}) = $self->_EncodeLOB($args{'Content'}, $args{'MimeType'});
+=head2 TransactionObj
- return($self->SUPER::Create(%args));
+Returns the transaction object asscoiated with this attachment.
+
+=cut
+
+sub TransactionObj {
+ my $self = shift;
+
+ unless ( $self->{_TransactionObj} ) {
+ $self->{_TransactionObj} = RT::Transaction->new( $self->CurrentUser );
+ $self->{_TransactionObj}->Load( $self->TransactionId );
+ }
+
+ unless ($self->{_TransactionObj}->Id) {
+ $RT::Logger->crit( "Attachment ". $self->id
+ ." can't find transaction ". $self->TransactionId
+ ." which it is ostensibly part of. That's bad");
+ }
+ return $self->{_TransactionObj};
}
-# {{{ sub Content
+=head2 ParentObj
-=head2 Content
+Returns a parent's L<RT::Attachment> object if this attachment
+has a parent, otherwise returns undef.
-Returns the attachment's content. if it's base64 encoded, decode it
-before returning it.
+=cut
+
+sub ParentObj {
+ my $self = shift;
+ return undef unless $self->Parent;
+
+ my $parent = RT::Attachment->new( $self->CurrentUser );
+ $parent->LoadById( $self->Parent );
+ return $parent;
+}
+
+=head2 Children
+
+Returns an L<RT::Attachments> object which is preloaded with
+all attachments objects with this attachment\'s Id as their
+C<Parent>.
=cut
-sub Content {
- my $self = shift;
- $self->_DecodeLOB($self->ContentType, $self->ContentEncoding, $self->_Value('Content', decode_utf8 => 0));
+sub Children {
+ my $self = shift;
+
+ my $kids = RT::Attachments->new( $self->CurrentUser );
+ $kids->ChildrenOf( $self->Id );
+ return($kids);
}
+=head2 Content
-# }}}
+Returns the attachment's content. if it's base64 encoded, decode it
+before returning it.
+=cut
-# {{{ sub OriginalContent
+sub Content {
+ my $self = shift;
+ return $self->_DecodeLOB(
+ $self->ContentType,
+ $self->ContentEncoding,
+ $self->_Value('Content', decode_utf8 => 0),
+ );
+}
=head2 OriginalContent
@@ -274,43 +289,37 @@ original encoding.
=cut
sub OriginalContent {
- my $self = shift;
-
- return $self->Content unless RT::I18N::IsTextualContentType($self->ContentType);
-
- my $enc = $self->OriginalEncoding;
-
- my $content;
- if ( $self->ContentEncoding eq 'none' || ! $self->ContentEncoding ) {
- $content = $self->_Value('Content', decode_utf8 => 0);
- } elsif ( $self->ContentEncoding eq 'base64' ) {
- $content = MIME::Base64::decode_base64($self->_Value('Content', decode_utf8 => 0));
- } elsif ( $self->ContentEncoding eq 'quoted-printable' ) {
- $content = MIME::QuotedPrint::decode($self->_Value('Content', decode_utf8 => 0));
- } else {
- return( $self->loc("Unknown ContentEncoding [_1]", $self->ContentEncoding));
- }
-
- # Turn *off* the SvUTF8 bits here so decode_utf8 and from_to below can work.
- local $@;
- Encode::_utf8_off($content);
-
- if (!$enc || $enc eq '' || $enc eq 'utf8' || $enc eq 'utf-8') {
- # If we somehow fail to do the decode, at least push out the raw bits
- eval {return( Encode::decode_utf8($content))} || return ($content);
- }
-
- eval { Encode::from_to($content, 'utf8' => $enc) } if $enc;
- if ($@) {
- $RT::Logger->error("Could not convert attachment from assumed utf8 to '$enc' :".$@);
- }
- return $content;
-}
+ my $self = shift;
-# }}}
+ return $self->Content unless RT::I18N::IsTextualContentType($self->ContentType);
+ my $enc = $self->OriginalEncoding;
+ my $content;
+ if ( !$self->ContentEncoding || $self->ContentEncoding eq 'none' ) {
+ $content = $self->_Value('Content', decode_utf8 => 0);
+ } elsif ( $self->ContentEncoding eq 'base64' ) {
+ $content = MIME::Base64::decode_base64($self->_Value('Content', decode_utf8 => 0));
+ } elsif ( $self->ContentEncoding eq 'quoted-printable' ) {
+ $content = MIME::QuotedPrint::decode($self->_Value('Content', decode_utf8 => 0));
+ } else {
+ return( $self->loc("Unknown ContentEncoding [_1]", $self->ContentEncoding));
+ }
+
+ # Turn *off* the SvUTF8 bits here so decode_utf8 and from_to below can work.
+ local $@;
+ Encode::_utf8_off($content);
-# {{{ sub OriginalEncoding
+ if (!$enc || $enc eq '' || $enc eq 'utf8' || $enc eq 'utf-8') {
+ # If we somehow fail to do the decode, at least push out the raw bits
+ eval { return( Encode::decode_utf8($content)) } || return ($content);
+ }
+
+ eval { Encode::from_to($content, 'utf8' => $enc) } if $enc;
+ if ($@) {
+ $RT::Logger->error("Could not convert attachment from assumed utf8 to '$enc' :".$@);
+ }
+ return $content;
+}
=head2 OriginalEncoding
@@ -319,35 +328,34 @@ Returns the attachment's original encoding.
=cut
sub OriginalEncoding {
- my $self = shift;
- return $self->GetHeader('X-RT-Original-Encoding');
+ my $self = shift;
+ return $self->GetHeader('X-RT-Original-Encoding');
}
-# }}}
-
-# {{{ sub Children
-
-=head2 Children
+=head2 ContentLength
- Returns an RT::Attachments object which is preloaded with all Attachments objects with this Attachment\'s Id as their 'Parent'
+Returns length of L</Content> in bytes.
=cut
-sub Children {
+sub ContentLength {
my $self = shift;
-
- my $kids = new RT::Attachments($self->CurrentUser);
- $kids->ChildrenOf($self->Id);
- return($kids);
-}
-
-# }}}
-# {{{ UTILITIES
+ return undef unless $self->TransactionObj->CurrentUserCanSee;
-# {{{ sub Quote
+ my $len = $self->GetHeader('Content-Length');
+ unless ( defined $len ) {
+ use bytes;
+ no warnings 'uninitialized';
+ $len = length($self->Content);
+ $self->SetHeader('Content-Length' => $len);
+ }
+ return $len;
+}
+=head2 Quote
+=cut
sub Quote {
my $self=shift;
@@ -399,9 +407,64 @@ sub Quote {
return (\$body, $max);
}
-# }}}
-# {{{ sub NiceHeaders - pulls out only the most relevant headers
+=head2 ContentAsMIME
+
+Returns MIME entity built from this attachment.
+
+=cut
+
+sub ContentAsMIME {
+ my $self = shift;
+
+ my $entity = new MIME::Entity;
+ foreach my $header ($self->SplitHeaders) {
+ my ($h_key, $h_val) = split /:/, $header, 2;
+ $entity->head->add( $h_key, RT::Interface::Email::EncodeToMIME( String => $h_val ) );
+ }
+
+ use MIME::Body;
+ $entity->bodyhandle(
+ MIME::Body::Scalar->new( $self->OriginalContent )
+ );
+
+ return $entity;
+}
+
+
+=head2 Addresses
+
+Returns a hashref of all addresses related to this attachment.
+The keys of the hash are C<From>, C<To>, C<Cc>, C<Bcc>, C<RT-Send-Cc>
+and C<RT-Send-Bcc>. The values are references to lists of
+L<Email::Address> objects.
+
+=cut
+
+sub Addresses {
+ my $self = shift;
+
+ my %data = ();
+ my $current_user_address = lc $self->CurrentUser->EmailAddress;
+ my $correspond = lc $self->TransactionObj->TicketObj->QueueObj->CorrespondAddress;
+ my $comment = lc $self->TransactionObj->TicketObj->QueueObj->CommentAddress;
+ foreach my $hdr (qw(From To Cc Bcc RT-Send-Cc RT-Send-Bcc)) {
+ my @Addresses;
+ my $line = $self->GetHeader($hdr);
+
+ foreach my $AddrObj ( Email::Address->parse( $line )) {
+ my $address = $AddrObj->address;
+ $address = lc RT::User->CanonicalizeEmailAddress($address);
+ next if ( $current_user_address eq $address );
+ next if ( $comment eq $address );
+ next if ( $correspond eq $address );
+ next if ( RT::EmailParser->IsRTAddress($address) );
+ push @Addresses, $AddrObj ;
+ }
+ $data{$hdr} = \@Addresses;
+ }
+ return \%data;
+}
=head2 NiceHeaders
@@ -420,34 +483,37 @@ sub NiceHeaders {
}
return $hdrs;
}
-# }}}
-
-# {{{ sub Headers
=head2 Headers
Returns this object's headers as a string. This method specifically
removes the RT-Send-Bcc: header, so as to never reveal to whom RT sent a Bcc.
We need to record the RT-Send-Cc and RT-Send-Bcc values so that we can actually send
-out mail. (The mailing rules are separated from the ticket update code by
-an abstraction barrier that makes it impossible to pass this data directly
+out mail. The mailing rules are separated from the ticket update code by
+an abstraction barrier that makes it impossible to pass this data directly.
=cut
sub Headers {
- my $self = shift;
- my $hdrs="";
- my @headers = grep { !/^RT-Send-Bcc/i } $self->_SplitHeaders;
- return join("\n",@headers);
-
+ return join("\n", $_[0]->SplitHeaders);
}
+=head2 EncodedHeaders
-# }}}
+Takes encoding as argument and returns the attachment's headers as octets in encoded
+using the encoding.
-# {{{ sub GetHeader
+This is not protection using quoted printable or base64 encoding.
-=head2 GetHeader ( 'Tag')
+=cut
+
+sub EncodedHeaders {
+ my $self = shift;
+ my $encoding = shift || 'utf8';
+ return Encode::encode( $encoding, $self->Headers );
+}
+
+=head2 GetHeader $TAG
Returns the value of the header Tag as a string. This bypasses the weeding out
done in Headers() above.
@@ -458,17 +524,52 @@ sub GetHeader {
my $self = shift;
my $tag = shift;
foreach my $line ($self->_SplitHeaders) {
- if ($line =~ /^\Q$tag\E:\s+(.*)$/si) { #if we find the header, return its value
- return ($1);
- }
+ next unless $line =~ /^\Q$tag\E:\s+(.*)$/si;
+
+ #if we find the header, return its value
+ return ($1);
}
# we found no header. return an empty string
return undef;
}
-# }}}
-# {{{ sub SetHeader
+=head2 DelHeader $TAG
+
+Delete a field from the attachment's headers.
+
+=cut
+
+sub DelHeader {
+ my $self = shift;
+ my $tag = shift;
+
+ my $newheader = '';
+ foreach my $line ($self->_SplitHeaders) {
+ next if $line =~ /^\Q$tag\E:\s+(.*)$/is;
+ $newheader .= "$line\n";
+ }
+ return $self->__Set( Field => 'Headers', Value => $newheader);
+}
+
+=head2 AddHeader $TAG, $VALUE, ...
+
+Add one or many fields to the attachment's headers.
+
+=cut
+
+sub AddHeader {
+ my $self = shift;
+
+ my $newheader = $self->__Value( 'Headers' );
+ while ( my ($tag, $value) = splice @_, 0, 2 ) {
+ $value = '' unless defined $value;
+ $value =~ s/\s+$//s;
+ $value =~ s/\r+\n/\n /g;
+ $newheader .= "$tag: $value\n";
+ }
+ return $self->__Set( Field => 'Headers', Value => $newheader);
+}
=head2 SetHeader ( 'Tag', 'Value' )
@@ -479,8 +580,8 @@ Replace or add a Header to the attachment's headers.
sub SetHeader {
my $self = shift;
my $tag = shift;
- my $newheader = '';
+ my $newheader = '';
foreach my $line ($self->_SplitHeaders) {
if (defined $tag and $line =~ /^\Q$tag\E:\s+(.*)$/i) {
$newheader .= "$tag: $_[0]\n";
@@ -494,80 +595,26 @@ sub SetHeader {
$newheader .= "$tag: $_[0]\n" if defined $tag;
$self->__Set( Field => 'Headers', Value => $newheader);
}
-# }}}
-# {{{ sub _Value
+=head2 SplitHeaders
-=head2 _Value
+Returns an array of this attachment object's headers, with one header
+per array entry. Multiple lines are folded.
-Takes the name of a table column.
-Returns its value as a string, if the user passes an ACL check
+B<Never> returns C<RT-Send-Bcc> field.
=cut
-sub _Value {
-
- my $self = shift;
- my $field = shift;
-
- #if the field is public, return it.
- if ( $self->_Accessible( $field, 'public' ) ) {
- return ( $self->__Value( $field, @_ ) );
- }
-
- #If it's a comment, we need to be extra special careful
- elsif ( $self->TransactionObj->Type =~ /^Comment/ ) {
- if ( $self->TransactionObj->CurrentUserHasRight('ShowTicketComments') )
- {
- return ( $self->__Value( $field, @_ ) );
- }
- }
- elsif ( $self->TransactionObj->CurrentUserHasRight('ShowTicket') ) {
- return ( $self->__Value( $field, @_ ) );
- }
-
- #if they ain't got rights to see, don't let em
- else {
- return (undef);
- }
-
+sub SplitHeaders {
+ my $self = shift;
+ return (grep !/^RT-Send-Bcc/i, $self->_SplitHeaders(@_) );
}
-# }}}
-
=head2 _SplitHeaders
Returns an array of this attachment object's headers, with one header
per array entry. multiple lines are folded.
-=begin testing
-
-my $test1 = "From: jesse";
-my @headers = RT::Attachment->_SplitHeaders($test1);
-is ($#headers, 0, $test1 );
-
-my $test2 = qq{From: jesse
-To: bobby
-Subject: foo
-};
-
-@headers = RT::Attachment->_SplitHeaders($test2);
-is ($#headers, 2, "testing a bunch of singline multiple headers" );
-
-
-my $test3 = qq{From: jesse
-To: bobby,
- Suzie,
- Sally,
- Joey: bizzy,
-Subject: foo
-};
-
-@headers = RT::Attachment->_SplitHeaders($test3);
-is ($#headers, 2, "testing a bunch of singline multiple headers" );
-
-
-=end testing
=cut
@@ -583,35 +630,130 @@ sub _SplitHeaders {
}
-sub ContentLength {
+sub Encrypt {
my $self = shift;
- unless ( (($self->TransactionObj->CurrentUserHasRight('ShowTicketComments')) and
- ($self->TransactionObj->Type eq 'Comment') ) or
- ($self->TransactionObj->CurrentUserHasRight('ShowTicket'))) {
- return undef;
+ my $txn = $self->TransactionObj;
+ return (0, $self->loc('Permission Denied')) unless $txn->CurrentUserCanSee;
+ return (0, $self->loc('Permission Denied'))
+ unless $txn->TicketObj->CurrentUserHasRight('ModifyTicket');
+ return (0, $self->loc('GnuPG integration is disabled'))
+ unless RT->Config->Get('GnuPG')->{'Enable'};
+ return (0, $self->loc('Attachments encryption is disabled'))
+ unless RT->Config->Get('GnuPG')->{'AllowEncryptDataInDB'};
+
+ require RT::Crypt::GnuPG;
+
+ my $type = $self->ContentType;
+ if ( $type =~ /^x-application-rt\/gpg-encrypted/i ) {
+ return (1, $self->loc('Already encrypted'));
+ } elsif ( $type =~ /^multipart\//i ) {
+ return (1, $self->loc('No need to encrypt'));
+ } else {
+ $type = qq{x-application-rt\/gpg-encrypted; original-type="$type"};
}
- if (my $len = $self->GetHeader('Content-Length')) {
- return $len;
+ my $queue = $txn->TicketObj->QueueObj;
+ my $encrypt_for;
+ foreach my $address ( grep $_,
+ $queue->CorrespondAddress,
+ $queue->CommentAddress,
+ RT->Config->Get('CorrespondAddress'),
+ RT->Config->Get('CommentAddress'),
+ ) {
+ my %res = RT::Crypt::GnuPG::GetKeysInfo( $address, 'private' );
+ next if $res{'exit_code'} || !$res{'info'};
+ %res = RT::Crypt::GnuPG::GetKeysForEncryption( $address );
+ next if $res{'exit_code'} || !$res{'info'};
+ $encrypt_for = $address;
+ }
+ unless ( $encrypt_for ) {
+ return (0, $self->loc('No key suitable for encryption'));
}
- {
- use bytes;
- my $len = length($self->Content);
- $self->SetHeader('Content-Length' => $len);
- return $len;
+ $self->__Set( Field => 'ContentType', Value => $type );
+ $self->SetHeader( 'Content-Type' => $type );
+
+ my $content = $self->Content;
+ my %res = RT::Crypt::GnuPG::SignEncryptContent(
+ Content => \$content,
+ Sign => 0,
+ Encrypt => 1,
+ Recipients => [ $encrypt_for ],
+ );
+ if ( $res{'exit_code'} ) {
+ return (0, $self->loc('GnuPG error. Contact with administrator'));
}
+
+ my ($status, $msg) = $self->__Set( Field => 'Content', Value => $content );
+ unless ( $status ) {
+ return ($status, $self->loc("Couldn't replace content with encrypted data: [_1]", $msg));
+ }
+ return (1, $self->loc('Successfuly encrypted data'));
}
-# }}}
+sub Decrypt {
+ my $self = shift;
+
+ my $txn = $self->TransactionObj;
+ return (0, $self->loc('Permission Denied')) unless $txn->CurrentUserCanSee;
+ return (0, $self->loc('Permission Denied'))
+ unless $txn->TicketObj->CurrentUserHasRight('ModifyTicket');
+ return (0, $self->loc('GnuPG integration is disabled'))
+ unless RT->Config->Get('GnuPG')->{'Enable'};
+
+ require RT::Crypt::GnuPG;
+
+ my $type = $self->ContentType;
+ if ( $type =~ /^x-application-rt\/gpg-encrypted/i ) {
+ ($type) = ($type =~ /original-type="(.*)"/i);
+ $type ||= 'application/octeat-stream';
+ } else {
+ return (1, $self->loc('Is not encrypted'));
+ }
+ $self->__Set( Field => 'ContentType', Value => $type );
+ $self->SetHeader( 'Content-Type' => $type );
+
+ my $content = $self->Content;
+ my %res = RT::Crypt::GnuPG::DecryptContent( Content => \$content, );
+ if ( $res{'exit_code'} ) {
+ return (0, $self->loc('GnuPG error. Contact with administrator'));
+ }
+
+ my ($status, $msg) = $self->__Set( Field => 'Content', Value => $content );
+ unless ( $status ) {
+ return ($status, $self->loc("Couldn't replace content with decrypted data: [_1]", $msg));
+ }
+ return (1, $self->loc('Successfuly decrypted data'));
+}
+
+=head2 _Value
+
+Takes the name of a table column.
+Returns its value as a string, if the user passes an ACL check
+
+=cut
+
+sub _Value {
+ my $self = shift;
+ my $field = shift;
+
+ #if the field is public, return it.
+ if ( $self->_Accessible( $field, 'public' ) ) {
+ return ( $self->__Value( $field, @_ ) );
+ }
+
+ return undef unless $self->TransactionObj->CurrentUserCanSee;
+ return $self->__Value( $field, @_ );
+}
-# Transactions don't change. by adding this cache congif directiove, we don't lose pathalogically on long tickets.
+# Transactions don't change. by adding this cache congif directiove,
+# we don't lose pathalogically on long tickets.
sub _CacheConfig {
{
- 'cache_p' => 1,
- 'fast_update_p' => 1,
- 'cache_for_sec' => 180,
+ 'cache_p' => 1,
+ 'fast_update_p' => 1,
+ 'cache_for_sec' => 180,
}
}