diff options
author | intrigeri <intrigeri@boum.org> | 2009-01-01 23:10:16 +0100 |
---|---|---|
committer | intrigeri <intrigeri@boum.org> | 2009-01-01 23:12:08 +0100 |
commit | c821cee108257e0d124c2b7516017af4be334463 (patch) | |
tree | a491f910ce7d905771063dc1b144b9dd8af59646 | |
parent | 4ee7f6314891489d6f42120e97f2c1c393d6093f (diff) |
po(cansave): check PO validity using new isvalidpo function
... because Po4a's parser does not care about malformed PO data.
Use gettext's msgfmt program instead.
Signed-off-by: intrigeri <intrigeri@boum.org>
-rw-r--r-- | IkiWiki/Plugin/po.pm | 47 | ||||
-rw-r--r-- | doc/plugins/po.mdwn | 4 |
2 files changed, 49 insertions, 2 deletions
diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm index 35e7c13ff..8f11a5f5a 100644 --- a/IkiWiki/Plugin/po.pm +++ b/IkiWiki/Plugin/po.pm @@ -388,11 +388,12 @@ sub cansave ($$$$) { my ($page, $content, $cgi, $session) = (shift, shift, shift, shift); if (istranslation($page)) { - if (defined po_to_markup($page, $content, "nonfatal")) { + my $res = isvalidpo($content); + if ($res) { return undef; } else { - return "Could not parse this page's content; is this valid gettext?"; + return "$res"; } } return undef; @@ -942,6 +943,48 @@ sub po_to_markup ($$;$) { return $content; } +# returns a SuccessReason or FailReason object +sub isvalidpo ($) { + my $content = shift; + + # NB: we don't use po_to_markup here, since Po4a parser does + # not mind invalid PO content + $content = '' unless defined $content; + $content = decode_utf8(encode_utf8($content)); + + # There are incompatibilities between some File::Temp versions + # (including 0.18, bundled with Lenny's perl-modules package) + # and others (e.g. 0.20, previously present in the archive as + # a standalone package): under certain circumstances, some + # return a relative filename, whereas others return an absolute one; + # we here use this module in a way that is at least compatible + # with 0.18 and 0.20. Beware, hit'n'run refactorers! + my $infile = new File::Temp(TEMPLATE => "ikiwiki-po-isvalidpo.XXXXXXXXXX", + DIR => File::Spec->tmpdir, + UNLINK => 1)->filename; + + sub failure ($) { + my $msg = '[po/isvalidpo:'.$page.'] ' . shift; + unlink $infile; + return IkiWiki::FailReason->new("$msg"); + } + + writefile(basename($infile), File::Spec->tmpdir, $content) + or return failure("failed to write $infile"); + + my $res = (system("msgfmt", "--check", $infile) == 0); + + # Unlinking should happen automatically, thanks to File::Temp, + # but it does not work here, probably because of the way writefile() + # and Locale::Po4a::write() work. + unlink $infile; + + if ($res) { + return IkiWiki::SuccessReason->new("valid gettext data"); + } + return IkiWiki::FailReason->new("invalid gettext data"); +} + # ,---- # | PageSpec's # `---- diff --git a/doc/plugins/po.mdwn b/doc/plugins/po.mdwn index c150092bf..a32d66af1 100644 --- a/doc/plugins/po.mdwn +++ b/doc/plugins/po.mdwn @@ -399,6 +399,10 @@ use in our case, I suggest we define `ENV{COLUMNS}` before loading `refreshpofiles()` runs this external program. A po4a developer answered he does "not expect any security issues from it". +### msgfmt + +`isvalidpo()` runs this external program. Its security should be checked. + ### Fuzzing input I was not able to find any public information about gettext or po4a |