/usr/share/perl5/IkiWiki/Plugin/graphviz.pm is in ikiwiki 3.20120202ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | #!/usr/bin/perl
# graphviz plugin for ikiwiki: render graphviz source as an image.
# Josh Triplett
package IkiWiki::Plugin::graphviz;
use warnings;
use strict;
use IkiWiki 3.00;
use IPC::Open2;
sub import {
hook(type => "getsetup", id => "graphviz", call => \&getsetup);
hook(type => "needsbuild", id => "version", call => \&needsbuild);
hook(type => "preprocess", id => "graph", call => \&graph, scan => 1);
}
sub getsetup () {
return
plugin => {
safe => 1,
rebuild => undef,
section => "widget",
},
}
my %graphviz_programs = (
"dot" => 1, "neato" => 1, "fdp" => 1, "twopi" => 1, "circo" => 1
);
sub needsbuild {
my $needsbuild=shift;
foreach my $page (keys %pagestate) {
if (exists $pagestate{$page}{graph} &&
exists $pagesources{$page} &&
grep { $_ eq $pagesources{$page} } @$needsbuild) {
# remove state, will be re-added if
# the graph is still there during the rebuild
delete $pagestate{$page}{graph};
}
}
return $needsbuild;
}
sub render_graph (\%) {
my %params = %{(shift)};
my $src = "charset=\"utf-8\";\n";
$src .= "ratio=compress;\nsize=\"".($params{width}+0).", ".($params{height}+0)."\";\n"
if defined $params{width} and defined $params{height};
$src .= $params{src};
$src .= "}\n";
# Use the sha1 of the graphviz code as part of its filename,
# and as a unique identifier for its imagemap.
eval q{use Digest::SHA};
error($@) if $@;
my $sha=IkiWiki::possibly_foolish_untaint(Digest::SHA::sha1_hex($params{type}.$src));
$src = "$params{type} graph$sha {\n".$src;
my $dest=$params{page}."/graph-".$sha.".png";
will_render($params{page}, $dest);
my $map=$pagestate{$params{destpage}}{graph}{$sha};
if (! -e "$config{destdir}/$dest" || ! defined $map) {
# Use ikiwiki's function to create the image file, this makes
# sure needed subdirs are there and does some sanity checking.
writefile($dest, $config{destdir}, "");
my $pid;
my $sigpipe=0;
$SIG{PIPE}=sub { $sigpipe=1 };
$pid=open2(*IN, *OUT, "$params{prog} -Tpng -o '$config{destdir}/$dest' -Tcmapx");
# open2 doesn't respect "use open ':utf8'"
binmode (IN, ':utf8');
binmode (OUT, ':utf8');
print OUT $src;
close OUT;
local $/ = undef;
$map=$pagestate{$params{destpage}}{graph}{$sha}=<IN>;
close IN;
waitpid $pid, 0;
$SIG{PIPE}="DEFAULT";
error gettext("failed to run graphviz") if ($sigpipe || $?);
}
return "<img src=\"".urlto($dest, $params{destpage}).
"\" usemap=\"#graph$sha\" />\n".
$map;
}
sub graph (@) {
my %params=@_;
# Support wikilinks in the graph source.
my $src=$params{src};
$src="" unless defined $src;
$src=IkiWiki::linkify($params{page}, $params{destpage}, $params{src});
return unless defined wantarray; # scan mode short-circuit
if ($src ne $params{src}) {
# linkify makes html links, but graphviz wants plain
# urls. This is, frankly a hack: Process source as html,
# throw out everything inside tags that is not a href.
my $s;
my $nested=0;
use HTML::Parser;
error $@ if $@;
my $p=HTML::Parser->new(api_version => 3);
$p->handler(start => sub {
my %attrs=%{shift()};
if (exists $attrs{href}) {
if ($s=~/href\s*=\s*"$/) {
$s.=$attrs{href};
}
elsif ($s=~/href\s*=\s*$/) {
$s.="\"$attrs{href}\"";
}
else {
$s.="href=\"$attrs{href}\"";
}
}
$nested++;
}, "attr");
$p->handler(end => sub {
$nested--;
});
$p->handler(default => sub {
$s.=join("", @_) unless $nested;
}, "text");
$p->parse($src);
$p->eof;
$params{src}=$s;
}
else {
$params{src}=$src;
}
$params{type} = "digraph" unless defined $params{type};
$params{prog} = "dot" unless defined $params{prog};
error gettext("prog not a valid graphviz program") unless $graphviz_programs{$params{prog}};
return render_graph(%params);
}
1
|