Skip to content

Commit

Permalink
Item14447: streamline reading META attrs
Browse files Browse the repository at this point in the history
  • Loading branch information
cdot committed Jul 28, 2017
1 parent 3653b6f commit cdb81af
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 21 deletions.
14 changes: 5 additions & 9 deletions core/lib/Foswiki/Meta.pm
Expand Up @@ -3822,20 +3822,16 @@ sub isValidEmbedding {
---++ StaticMethod dataDecode( $encoded ) -> $decoded
Decode escapes in a string that was encoded using dataEncode
Decode escapes in a string that was encoded using
Foswiki::Serialise::Embedded::dataEncode
The encoding has to be exported because Foswiki (and plugins) use
encoded field data in other places e.g. RDiff, mainly as a shorthand
for the properly parsed meta object. Some day we may be able to
eliminate that....
DEPRECATED - DO NOT USE!
=cut

sub dataDecode {
my $datum = shift;

$datum =~ s/%([\da-f]{2})/chr(hex($1))/gei;
return $datum;
require Foswiki::Serialise::Embedded;
return Foswiki::Serialise::Embedded::dataDecode(@_);
}

1;
Expand Down
47 changes: 38 additions & 9 deletions core/lib/Foswiki/Serialise/Embedded.pm
Expand Up @@ -19,6 +19,18 @@ use Foswiki ();
use Foswiki::Meta ();
use Assert;

# Chars that must be encoded in META attr values
my $must_encode = "%\"\r\n{}";

# Map from char that needs encoding to the hex character number
my %encode = map { $_ => sprintf( '%02x', ord($_) ) } split( //, $must_encode );

# Map from hex character number to the character
my %decode;
while ( my ( $k, $v ) = each %encode ) {
$decode{$v} = $k;
}

=begin TML
---++ ClassMethod new( $class, ) -> $cereal
Expand Down Expand Up @@ -172,10 +184,17 @@ sub read {
sub _readKeyValues {
my ($args) = @_;
my %res;
my ( $k, $v );

# Format of data is name='value' name1='value1' [...]
$args =~ s/\s*(\w+)="([^"]*)"/
$res{$1} = Foswiki::Meta::dataDecode( $2 ), ''/ige;
while ( $args =~ /([a-zA-Z0-9_]+)="(.*?)"/g ) {
$k = $1;
$v = $2;

# Shortcut around dataDecode
$v =~ s/%([0-9a-fA-F]{2})/$decode{$1}/g;
$res{$k} = $v;
}

return \%res;
}
Expand Down Expand Up @@ -267,24 +286,34 @@ sub _writeTypes {

=begin TML
---++ StaticMethod dataDecode( $encoded ) -> $decoded
Decode escapes in a string that was encoded using dataEncode
=cut

sub dataDecode {
my $datum = shift;

$datum =~ s/(\%[\da-fA-F]{2})/$decode{$1}/g;
return $datum;
}

=begin TML
---++ StaticMethod dataEncode( $uncoded ) -> $coded
Encode meta-data field values, escaping out selected characters.
The encoding is chosen to avoid problems with parsing the attribute
values in embedded meta-data, while minimising the number of
characters encoded so searches can still work (fairly) sensibly.
The encoding has to be exported because Foswiki (and plugins) use
encoded field data in other places e.g. RDiff, mainly as a shorthand
for the properly parsed meta object. Some day we may be able to
eliminate that....
characters encoded so plain-text searches can still work (fairly) sensibly.
=cut

sub dataEncode {
my $datum = shift;

$datum =~ s/([%"\r\n{}])/'%'.sprintf('%02x',ord($1))/ge;
$datum =~ s/([%"\r\n{}])/\%$encode{$1}/g;
return $datum;
}

Expand Down
7 changes: 4 additions & 3 deletions core/lib/Foswiki/UI/RDiff.pm
Expand Up @@ -15,8 +15,9 @@ use warnings;
use Assert;
use Error qw( :try );

use Foswiki ();
use Foswiki::UI ();
use Foswiki ();
use Foswiki::UI ();
use Foswiki::Serialise::Embedded (); # for dataDecode

BEGIN {
if ( $Foswiki::cfg{UseLocale} ) {
Expand Down Expand Up @@ -109,7 +110,7 @@ sub _renderAttrs {
require Foswiki::Store;
if ($f) {
for my $key ( keys %$attrs ) {
my $av = Foswiki::Meta::dataDecode( $attrs->{$key} );
my $av = Foswiki::Serialise::Embedded::dataDecode( $attrs->{$key} );
$f =~ s/\$$key\b/$av/g;
}
}
Expand Down

0 comments on commit cdb81af

Please sign in to comment.