* Fix a forkbomb in various calls to IPC::Open2, which has a highly
[ikiwiki.git] / IkiWiki / Plugin / rst.pm
1 #!/usr/bin/perl
2 # Very simple reStructuredText processor.
3 #
4 # This plugin calls python and requires python-docutils to transform the text
5 # into html.
6 #
7 # Its main problem is that it does not support ikiwiki's WikiLinks nor
8 # Preprocessor Directives.
9 #
10 # Probably Wikilinks and Preprocessor Directives should support a list of
11 # extensions to process (i.e. the linkify function could be transformed into
12 # reStructuredText instead of HTML using a hook on rst.py instead of the
13 # current linkify function)
14 #
15 # by Sergio Talens-Oliag <sto@debian.org>
16
17 package IkiWiki::Plugin::rst;
18
19 use warnings;
20 use strict;
21 use IkiWiki;
22 use IPC::Open2;
23
24 # Simple python script, maybe it should be implemented using an external script.
25 # The settings_overrides are given to avoid potential security risks when
26 # reading external files or if raw html is included on rst pages.
27 my $pyCmnd = "
28 from docutils.core import publish_string;
29 from sys import stdin;
30 html = publish_string(stdin.read(), writer_name='html', 
31        settings_overrides = { 'halt_level': 6, 
32                               'file_insertion_enabled': 0,
33                               'raw_enabled': 0 }
34 );
35 print html[html.find('<body>')+6:html.find('</body>')].strip();
36 ";
37
38 sub import { #{{{
39         hook(type => "htmlize", id => "rst", call => \&htmlize);
40 } # }}}
41
42 sub htmlize (@) { #{{{
43         my %params=@_;
44         my $content=$params{content};
45
46         my $pid;
47         my $sigpipe=0;
48         $SIG{PIPE}=sub { $sigpipe=1 };
49         $pid=open2(*IN, *OUT, "python", "-c",  $pyCmnd);
50         
51         # open2 doesn't respect "use open ':utf8'"
52         binmode (IN, ':utf8');
53         binmode (OUT, ':utf8');
54         
55         print OUT $content;
56         close OUT;
57
58         local $/ = undef;
59         my $ret=<IN>;
60         close IN;
61         waitpid $pid, 0;
62
63         return $content if $sigpipe;
64         $SIG{PIPE}="DEFAULT";
65
66         return $ret;
67 } # }}}
68
69 1