2 # Ikiwiki setup files can be perl files that 'use IkiWiki::Setup::foo',
3 # passing it some sort of configuration data. Or, they can contain
4 # the module name at the top, without the 'use', and the whole file is
5 # then fed into that module.
7 package IkiWiki
::Setup
;
12 use open qw{:utf8
:std
};
16 my $file=IkiWiki
::possibly_foolish_untaint
(shift);
19 $config{setupfile
}=File
::Spec
->rel2abs($file);
21 #translators: The first parameter is a filename, and the second
22 #translators: is a (probably not translated) error message.
23 open (IN
, $file) || error
(sprintf(gettext
("cannot read %s: %s"), $file, $!));
27 $content=<IN
> || error
("$file: $!");
31 if ($content=~/((?:use|require)\s+)?IkiWiki::Setup::(\w+)/) {
32 $config{setuptype
}=$2;
34 error
sprintf(gettext
("cannot load %s in safe mode"), $file)
37 eval IkiWiki
::possibly_foolish_untaint
($content);
38 error
("$file: ".$@
) if $@
;
41 eval qq{require IkiWiki
::Setup
::$config{setuptype
}};
43 "IkiWiki::Setup::$config{setuptype}"->loaddump(IkiWiki
::possibly_foolish_untaint
($content));
47 error
sprintf(gettext
("failed to parse %s"), $file);
52 my $file=IkiWiki
::possibly_foolish_untaint
(shift);
55 "Setup file for ikiwiki.",
57 "Passing this to ikiwiki --setup will make ikiwiki generate",
58 "wrappers and build the wiki.",
60 "Remember to re-run ikiwiki --setup any time you edit this file.",
63 # Fork because dumping setup requires loading all plugins.
66 eval qq{require IkiWiki
::Setup
::$config{setuptype
}};
68 my @dump="IkiWiki::Setup::$config{setuptype}"->gendump(@header);
70 open (OUT
, ">", $file) || die "$file: $!";
71 print OUT
"$_\n" foreach @dump;
78 exit($?
>> 8) if $?
>> 8;
84 # Merge setup into existing config and untaint.
87 if (exists $setup{add_plugins
} && exists $config{add_plugins
}) {
88 push @
{$setup{add_plugins
}}, @
{$config{add_plugins
}};
90 if (exists $setup{exclude
}) {
91 push @
{$config{wiki_file_prune_regexps
}}, $setup{exclude
};
93 foreach my $c (keys %setup) {
94 if (defined $setup{$c}) {
95 if (! ref $setup{$c} || ref $setup{$c} eq 'Regexp') {
96 $config{$c}=IkiWiki
::possibly_foolish_untaint
($setup{$c});
98 elsif (ref $setup{$c} eq 'ARRAY') {
99 if ($c eq 'wrappers') {
100 # backwards compatability code
101 $config{$c}=$setup{$c};
104 $config{$c}=[map { IkiWiki
::possibly_foolish_untaint
($_) } @
{$setup{$c}}]
107 elsif (ref $setup{$c} eq 'HASH') {
108 foreach my $key (keys %{$setup{$c}}) {
109 $config{$c}{$key}=IkiWiki
::possibly_foolish_untaint
($setup{$c}{$key});
118 if (length $config{cgi_wrapper
}) {
119 push @
{$config{wrappers
}}, {
121 wrapper
=> $config{cgi_wrapper
},
122 wrappermode
=> (defined $config{cgi_wrappermode
} ?
$config{cgi_wrappermode
} : "06755"),
127 sub disabled_plugins
(@
) {
128 # Handles running disable hooks of plugins that were enabled
129 # previously, but got disabled when a new setup file was loaded.
130 if (exists $config{setupfile
} && @_) {
131 # Fork a child to load the disabled plugins.
134 foreach my $plugin (@_) {
135 eval { IkiWiki
::loadplugin
($plugin, 1) };
136 if (exists $IkiWiki::hooks
{disable
}{$plugin}{call
}) {
137 eval { $IkiWiki::hooks
{disable
}{$plugin}{call
}->() };
149 # Gets all available setup data from all plugins. Returns an
150 # ordered list of [plugin, setup] pairs.
152 # disable logging to syslog while dumping, broken plugins may
154 my $syslog=$config{syslog
};
155 $config{syslog
}=undef;
157 # Load all plugins, so that all setup options are available.
158 my %original_loaded_plugins=%IkiWiki::loaded_plugins
;
159 my @plugins=IkiWiki
::listplugins
();
160 foreach my $plugin (@plugins) {
161 eval { IkiWiki
::loadplugin
($plugin, 1) };
162 if (exists $IkiWiki::hooks
{checkconfig
}{$plugin}{call
}) {
163 my @s=eval { $IkiWiki::hooks
{checkconfig
}{$plugin}{call
}->() };
166 %IkiWiki::loaded_plugins
=%original_loaded_plugins;
169 foreach my $plugin (@plugins) {
170 if (exists $IkiWiki::hooks
{getsetup
}{$plugin}{call
}) {
171 # use an array rather than a hash, to preserve order
172 my @s=eval { $IkiWiki::hooks
{getsetup
}{$plugin}{call
}->() };
175 # set default section value (note use of shared
176 # hashref between array and hash)
178 if (! exists $s{plugin
} || ! $s{plugin
}->{section
}) {
179 $s{plugin
}->{section
}="other";
182 # only the selected rcs plugin is included
183 if ($config{rcs
} && $plugin eq $config{rcs
}) {
184 $s{plugin
}->{section
}="core";
186 elsif ($s{plugin
}->{section
} eq "rcs") {
190 push @
{$sections{$s{plugin
}->{section
}}}, [ $plugin, \
@s ];
194 $config{syslog
}=$syslog;
196 return map { sort { $a->[0] cmp $b->[0] } @
{$sections{$_}} }
197 sort { # core first, other last, otherwise alphabetical
198 ($b eq "core") <=> ($a eq "core")
200 ($a eq "other") <=> ($b eq "other")
206 sub commented_dump
($$) {
213 # disable logging to syslog while dumping
214 $config{syslog
}=undef;
216 eval q{use Text::Wrap};
220 push @ret, commented_dumpvalues
($dumpline, $indent, \
%setup, IkiWiki
::getsetup
());
221 foreach my $pair (IkiWiki
::Setup
::getsetup
()) {
222 my $plugin=$pair->[0];
223 my $setup=$pair->[1];
225 my $section=$s{plugin
}->{section
};
226 push @
{$section_plugins{$section}}, $plugin;
227 if (@
{$section_plugins{$section}} == 1) {
228 push @ret, "", $indent.("#" x
70), "$indent# $section plugins",
230 wrap
("$indent# (", "$indent# ",
231 join(", ", @
{$section_plugins{$section}})).")"
236 my @values=commented_dumpvalues
($dumpline, $indent, \
%setup, @
{$setup});
238 push @ret, "", "$indent# $plugin plugin", @values;
242 return map { ref $_ ?
$_->() : $_ } @ret;
245 sub commented_dumpvalues
($$$@
) {
254 next if $key eq "plugin" || $info{type
} eq "internal";
256 push @ret, "$indent# ".$info{description
} if exists $info{description
};
258 if (exists $setup->{$key} && defined $setup->{$key}) {
259 push @ret, $dumpline->($key, $setup->{$key}, $info{type
}, "");
260 delete $setup->{$key};
262 elsif (exists $info{example
}) {
263 push @ret, $dumpline->($key, $info{example
}, $info{type
}, "#");
266 push @ret, $dumpline->($key, "", $info{type
}, "#");