Skip to content

Commit

Permalink
Item13432: handlers have to work on the byte level, they are too stup…
Browse files Browse the repository at this point in the history
…id for characters. Means a few more calls to Encode, but there should be no great extra cost from that.
  • Loading branch information
Comment committed May 27, 2015
1 parent b63fb4e commit d4561ad
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 78 deletions.
Expand Up @@ -32,7 +32,7 @@ sub checkRCSProgram {
$err .= $key . ' is not set';
}
else {
my $version = `$prog -V` || '';
my $version = `$prog --version` || '';
if (
$version !~ /Can't exec/

Expand Down
58 changes: 2 additions & 56 deletions RCSStoreContrib/lib/Foswiki/Store/Rcs/Handler.pm
Expand Up @@ -124,53 +124,6 @@ sub new {
return $this;
}

=begin TML
---++ StaticMethod encode($string) -> $encoded_string
Convert a string in the site encoding into the store encoding. This is
used to encode strings for printing to files.
=cut

sub encode {
my ( $str, $fn ) = @_;

return $str unless defined $str;

if ( $Foswiki::UNICODE && !$fn ) {
return Encode::encode( $Foswiki::cfg{Store}{Encoding} || 'utf-8',
$str, Encode::FB_CROAK );
}

# otherwise we are using the old {Site}{CharSet} encoding
# and the string needs no conversion
return $str;
}

=begin TML
---++ StaticMethod decode($encoded_string) -> $string
Convert a string from the store encoding into unicode.
=cut

sub decode {
my $str = shift;

return $str unless defined $str;

if ($Foswiki::UNICODE) {
return Encode::decode( $Foswiki::cfg{Store}{Encoding} || 'utf-8',
$str, Encode::FB_PERLQQ );
}

# otherwise we are using the old {Site}{CharSet} encoding
# and the string needs no conversion
return $str;
}

# Convert a unicode filename to bytes. Normally a NOP, used for debugging
# encodings
sub fn2b {
Expand Down Expand Up @@ -1153,7 +1106,7 @@ sub saveFile {
binmode($fh)
or throw Error::Simple(
'Rcs::Handler: failed to binmode ' . $name . ': ' . $! );
print $fh encode($text)
print $fh $text
or throw Error::Simple(
'Rcs::Handler: failed to print into ' . $name . ': ' . $! );
close($fh)
Expand All @@ -1176,14 +1129,7 @@ sub readFile {
$data = <$IN_FILE>;
close($IN_FILE);
}
$data ||= '';
return Encode::decode(
$Foswiki::cfg{Store}{Encoding} || 'utf-8',
$data,

#Encode::FB_CROAK # DEBUG
Encode::FB_PERLQQ
);
return $data;
}

# Used by subclasses
Expand Down
4 changes: 2 additions & 2 deletions RCSStoreContrib/lib/Foswiki/Store/Rcs/RcsLiteHandler.pm
Expand Up @@ -268,7 +268,7 @@ sub _ensureRead {
$this->{state} = 'nocommav';
return;
}
binmode( $fh, $Foswiki::UNICODE ? ':utf8' : undef );
binmode($fh);

my $state = 'admin.head'; # reset to start
my $term = ';';
Expand Down Expand Up @@ -560,7 +560,7 @@ sub _writeMe {
'Cannot open ' . $this->{rcsFile} . ' for write: ' . $! );
}
else {
binmode( $out, $Foswiki::UNICODE ? ':utf8' : undef );
binmode($out);
_write( $this, $out );
close($out);
}
Expand Down
65 changes: 48 additions & 17 deletions RCSStoreContrib/lib/Foswiki/Store/Rcs/Store.pm
Expand Up @@ -96,7 +96,7 @@ sub readTopic {
return ( undef, undef ) unless $handler->storedDataExists();

( my $text, $isLatest ) = $handler->getRevision($version);

$text = Encode::decode_utf8( $text, Encode::FB_CROAK ) if $Foswiki::UNICODE;
$text =~ s/\r//g; # Remove carriage returns
Foswiki::Serialise::deserialise( $text, 'Embedded', $topicObject );

Expand Down Expand Up @@ -270,8 +270,16 @@ sub getRevisionDiff {
ASSERT( defined($contextLines) ) if DEBUG;

my $rcs = $this->getHandler( $topicObject->web, $topicObject->topic );
return $rcs->revisionDiff( $topicObject->getLoadedRev(), $rev2,
$contextLines );
my $diffs =
$rcs->revisionDiff( $topicObject->getLoadedRev(), $rev2, $contextLines );
if ($Foswiki::UNICODE) {
foreach my $d (@$diffs) {
for my $i ( 1, 2 ) {
$d->[$i] = Encode::decode_utf8( $d->[$i], Encode::FB_CROAK );
}
}
}
return $diffs;
}

sub _getAttachmentVersionInfo {
Expand Down Expand Up @@ -308,6 +316,12 @@ sub _getAttachmentVersionInfo {
$this->getHandler( $topicObject->web, $topicObject->topic,
$attachment );
$info = $handler->getInfo( $rev || 0 );
$info->{author} =
Encode::decode_utf8( $info->{author}, Encode::FB_CROAK )
if $info->{author};
$info->{comment} =
Encode::decode_utf8( $info->{comment}, Encode::FB_CROAK )
if $info->{comment};
}

return $info;
Expand Down Expand Up @@ -342,8 +356,15 @@ sub getVersionInfo {
if ( not defined $info ) {
my $handler =
$this->getHandler( $topicObject->web, $topicObject->topic );

$info = $handler->getInfo($rev);
if ($Foswiki::UNICODE) {
$info->{author} =
Encode::decode_utf8( $info->{author}, Encode::FB_CROAK )
if $info->{author};
$info->{comment} =
Encode::decode_utf8( $info->{comment}, Encode::FB_CROAK )
if $info->{comment};
}
}

# make sure there's at least author, date and version
Expand All @@ -364,6 +385,11 @@ sub saveAttachment {
my $verb = ( $topicObject->hasAttachment($name) ) ? 'update' : 'insert';
my $comment = $options->{comment} || '';

if ($Foswiki::UNICODE) {
$comment = Encode::encode_utf8($comment);
$cUID = Encode::encode_utf8($cUID);
}

$handler->addRevisionFromStream( $stream, $comment, $cUID,
$options->{forcedate} );

Expand All @@ -379,7 +405,6 @@ sub saveTopic {

my $handler = $this->getHandler( $topicObject->web, $topicObject->topic );
my $verb = ( $topicObject->existsInStore() ) ? 'update' : 'insert';
my $comment = ( ref $options ) ? $options->{comment} : $options;

# just in case they are not sequential
my $nextRev = $handler->getNextRevisionID();
Expand All @@ -395,12 +420,16 @@ sub saveTopic {
author => $cUID,
);
}
my $comment = $options->{comment} || '';

$handler->addRevisionFromText(
Foswiki::Serialise::serialise( $topicObject, 'Embedded' ),
$options->{comment} || '',
$cUID, $options->{forcedate}
);
my $text = Foswiki::Serialise::serialise( $topicObject, 'Embedded' );
if ($Foswiki::UNICODE) {
$text = Encode::encode_utf8($text);
$cUID = Encode::encode_utf8($cUID);
$comment = Encode::encode_utf8($cUID);
}
$handler->addRevisionFromText( $text, $comment, $cUID,
$options->{forcedate} );

# reload the topic object
$topicObject->unload();
Expand All @@ -414,14 +443,16 @@ sub repRev {

ASSERT( $topicObject->isa('Foswiki::Meta') ) if DEBUG;
ASSERT($cUID) if DEBUG;
my $info = $topicObject->getRevisionInfo();
my $info = $topicObject->getRevisionInfo();
my $handler = $this->getHandler( $topicObject->web, $topicObject->topic );
$handler->replaceRevision(
Foswiki::Serialise::serialise( $topicObject, 'Embedded' ),
'reprev',
$cUID,
defined $options{forcedate} ? $options{forcedate} : $info->{date}
);
my $text = Foswiki::Serialise::serialise( $topicObject, 'Embedded' );
if ($Foswiki::UNICODE) {
$text = Encode::encode_utf8($text);
$cUID = Encode::encode_utf8($cUID);
}

$handler->replaceRevision( $text, 'reprev', $cUID,
defined $options{forcedate} ? $options{forcedate} : $info->{date} );

my $rev = $handler->getLatestRevisionID();

Expand Down
2 changes: 1 addition & 1 deletion UnitTestContrib/test/unit/FoswikiStoreTestCase.pm
Expand Up @@ -18,7 +18,7 @@ sub rcs_is_installed {
if ( !defined($rcs_installed) ) {
$ENV{PATH} =~ m/^(.*)$/ms;
local $ENV{PATH} = $1; # untaint
if ( eval { `co -V`; 1; } ) # Check to see if we have co
if ( eval { `co --version`; 1; } ) # Check to see if we have co
{
$rcs_installed = 1;
}
Expand Down
2 changes: 1 addition & 1 deletion core/lib/Foswiki/UI/Viewfile.pm
Expand Up @@ -205,7 +205,7 @@ sub viewfile {

# SMELL: Maybe could be less memory hungry if we could
# set the response body to the file handle.
$session->{response}->print(<$fh>);
$session->{response}->body(<$fh>);
}

sub _suffixToMimeType {
Expand Down

0 comments on commit d4561ad

Please sign in to comment.