X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=rt%2Flib%2FRT%2FRecord.pm;h=59867aae8216b6b304b70971f455e57cc12d721a;hp=313888cbc4a164351af193d6dc1fd5cd5c601408;hb=e9e0cf0989259b94d9758eceff448666a2e5a5cc;hpb=a60615bf7bde77aa2b9faf3fc268c149eecdb5ab diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm index 313888cbc..59867aae8 100755 --- a/rt/lib/RT/Record.pm +++ b/rt/lib/RT/Record.pm @@ -2,7 +2,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC # # # (Except where explicitly superseded by other copyright notices) @@ -501,19 +501,24 @@ sub _Set { # $ret is a Class::ReturnValue object. as such, in a boolean context, it's a bool # we want to change the standard "success" message if ($status) { - $msg = - $self->loc( - "[_1] changed from [_2] to [_3]", - $self->loc( $args{'Field'} ), - ( $old_val ? '"' . $old_val . '"' : $self->loc("(no value)") ), - '"' . $self->__Value( $args{'Field'}) . '"' - ); - } else { - - $msg = $self->CurrentUser->loc_fuzzy($msg); + if ($self->SQLType( $args{'Field'}) =~ /text/) { + $msg = $self->loc( + "[_1] updated", + $self->loc( $args{'Field'} ), + ); + } else { + $msg = $self->loc( + "[_1] changed from [_2] to [_3]", + $self->loc( $args{'Field'} ), + ( $old_val ? '"' . $old_val . '"' : $self->loc("(no value)") ), + '"' . $self->__Value( $args{'Field'}) . '"', + ); + } + } else { + $msg = $self->CurrentUser->loc_fuzzy($msg); } - return wantarray ? ($status, $msg) : $ret; + return wantarray ? ($status, $msg) : $ret; } @@ -725,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 @@ -755,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'; } @@ -779,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 ); } } @@ -800,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 || ''; @@ -816,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); } @@ -888,6 +925,8 @@ sub Update { $value =~ s/\r\n/\n/gs; + my $truncated_value = $self->TruncateValue($attribute, $value); + # If Queue is 'General', we want to resolve the queue name for # the object. @@ -902,8 +941,12 @@ sub Update { my $name = $self->$object->Name; next if $name eq $value || $name eq ($value || 0); }; - next if $value eq $self->$attribute(); - next if ($value || 0) eq $self->$attribute(); + + my $current = $self->$attribute(); + # RT::Queue->Lifecycle returns a Lifecycle object instead of name + $current = eval { $current->Name } if ref $current; + next if $truncated_value eq $current; + next if ( $truncated_value || 0 ) eq $current; }; $new_values{$attribute} = $value; @@ -1361,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(); @@ -1418,7 +1461,7 @@ sub _AddLink { Delete a link. takes a paramhash of Base, Target and Type. Either Base or Target must be null. The null value will -be replaced with this ticket\'s id +be replaced with this ticket's id =cut @@ -1439,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(); @@ -1633,29 +1676,37 @@ sub CustomFields { $cfs->SetContextObject( $self ); # XXX handle multiple types properly $cfs->LimitToLookupType( $self->CustomFieldLookupType ); - $cfs->LimitToGlobalOrObjectId( - $self->_LookupId( $self->CustomFieldLookupType ) - ); + $cfs->LimitToGlobalOrObjectId( $self->CustomFieldLookupId ); $cfs->ApplySortOrder; return $cfs; } -# TODO: This _only_ works for RT::Class classes. it doesn't work, for example, -# for RT::IR classes. +# TODO: This _only_ works for RT::Foo classes. it doesn't work, for +# example, for RT::IR::Foo classes. -sub _LookupId { +sub CustomFieldLookupId { my $self = shift; - my $lookup = shift; + my $lookup = shift || $self->CustomFieldLookupType; my @classes = ($lookup =~ /RT::(\w+)-/g); + # Work on "RT::Queue", for instance + return $self->Id unless @classes; + my $object = $self; + # Save a ->Load call by not calling ->FooObj->Id, just ->Foo + my $final = shift @classes; foreach my $class (reverse @classes) { my $method = "${class}Obj"; $object = $object->$method; } - return $object->Id; + my $id = $object->$final; + unless (defined $id) { + my $method = "${final}Obj"; + $id = $object->$method->Id; + } + return $id; } @@ -1667,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; } @@ -1770,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; }