+sub getsetup () {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => 0,
+ section => "web",
+ },
+ websetup_force_plugins => {
+ type => "string",
+ example => [],
+ description => "list of plugins that cannot be enabled/disabled via the web interface",
+ safe => 0,
+ rebuild => 0,
+ },
+ websetup_unsafe => {
+ type => "string",
+ example => [],
+ description => "list of additional setup field keys to treat as unsafe",
+ safe => 0,
+ rebuild => 0,
+ },
+ websetup_show_unsafe => {
+ type => "boolean",
+ example => 1,
+ description => "show unsafe settings, read-only, in web interface?",
+ safe => 0,
+ rebuild => 0,
+ },
+}
+
+sub checkconfig () {
+ if (! exists $config{websetup_show_unsafe}) {
+ $config{websetup_show_unsafe}=1;
+ }
+}
+
+sub formatexample ($$) {
+ my $example=shift;
+ my $value=shift;
+
+ if (defined $value && length $value) {
+ return "";
+ }
+ elsif (defined $example && ! ref $example && length $example) {
+ return "<br/ ><small>Example: <tt>$example</tt></small>";
+ }
+ else {
+ return "";
+ }
+}
+
+sub issafe ($) {
+ my $key=shift;
+
+ return ! grep { $_ eq $key } @{$config{websetup_unsafe}};
+}
+
+sub showfields ($$$@) {
+ my $form=shift;
+ my $plugin=shift;
+ my $enabled=shift;
+
+ my @show;
+ my %plugininfo;
+ while (@_) {
+ my $key=shift;
+ my %info=%{shift()};
+
+ if ($key eq 'plugin') {
+ %plugininfo=%info;
+ next;
+ }
+
+ # skip internal settings
+ next if defined $info{type} && $info{type} eq "internal";
+ # XXX hashes not handled yet
+ next if ref $config{$key} && ref $config{$key} eq 'HASH' || ref $info{example} eq 'HASH';
+ # maybe skip unsafe settings
+ next if ! ($config{websetup_show_unsafe} && $config{websetup_advanced}) &&
+ (! $info{safe} || ! issafe($key));
+ # maybe skip advanced settings
+ next if $info{advanced} && ! $config{websetup_advanced};
+ # these are handled specially, so don't show
+ next if $key eq 'add_plugins' || $key eq 'disable_plugins';
+
+ push @show, $key, \%info;
+ }
+
+ my $section=defined $plugin
+ ? sprintf(gettext("%s plugin:"), $plugininfo{section})." ".$plugin
+ : "main";
+ my %enabledfields;
+ my $shownfields=0;
+
+ my $plugin_forced=defined $plugin && (! $plugininfo{safe} ||
+ (exists $config{websetup_force_plugins} && grep { $_ eq $plugin } @{$config{websetup_force_plugins}}));
+ if ($plugin_forced && ! $enabled) {
+ # plugin is forced disabled, so skip its settings
+ @show=();
+ }
+
+ my $section_fieldset;
+ if (defined $plugin) {
+ # Define the combined fieldset for the plugin's section.
+ # This ensures that this fieldset comes first.
+ $section_fieldset=sprintf(gettext("%s plugins"), $plugininfo{section});
+ $form->field(name => "placeholder.$plugininfo{section}",
+ type => "hidden",
+ fieldset => $section_fieldset);
+ }
+
+ # show plugin toggle
+ if (defined $plugin && (! $plugin_forced || $config{websetup_advanced})) {
+ my $name="enable.$plugin";
+ $form->field(
+ name => $name,
+ label => "",
+ type => "checkbox",
+ fieldset => $section,
+ options => [ [ 1 => sprintf(gettext("enable %s?"), $plugin) ]]
+ );
+ if (! $form->submitted) {
+ $form->field(name => $name, value => $enabled);
+ }
+ if ($plugin_forced) {
+ $form->field(name => $name, disabled => 1);
+ }
+ else {
+ $enabledfields{$name}=[$name, \%plugininfo];
+ }
+ }
+
+ # show plugin settings
+ while (@show) {
+ my $key=shift @show;
+ my %info=%{shift @show};
+
+ my $description=$info{description};
+ if (exists $info{htmldescription}) {
+ $description=$info{htmldescription};
+ }
+ elsif (exists $info{link} && length $info{link}) {
+ if ($info{link} =~ /^\w+:\/\//) {
+ $description="<a href=\"$info{link}\">$description</a>";
+ }
+ else {
+ $description=htmllink("", "", $info{link}, noimageinline => 1, linktext => $description);
+ }
+ }
+
+ # multiple plugins can have the same field
+ my $name=defined $plugin ? $plugin.".".$key : $section.".".$key;
+
+ my $value=$config{$key};
+ if (! defined $value) {
+ $value="";
+ }
+
+ if (ref $value eq 'ARRAY' || ref $info{example} eq 'ARRAY') {
+ $value=[(ref $value eq 'ARRAY' ? map { Encode::encode_utf8($_) } @{$value} : "")];
+ push @$value, "", "" if $info{safe} && issafe($key); # blank items for expansion
+ }
+ else {
+ $value=Encode::encode_utf8($value);
+ }
+
+ if ($info{type} eq "string") {
+ $form->field(
+ name => $name,
+ label => $description,
+ comment => formatexample($info{example}, $value),
+ type => "text",
+ value => $value,
+ size => 60,
+ fieldset => $section,
+ );
+ }
+ elsif ($info{type} eq "pagespec") {
+ $form->field(
+ name => $name,
+ label => $description,
+ comment => formatexample($info{example}, $value),
+ type => "text",
+ value => $value,
+ size => 60,
+ validate => \&IkiWiki::pagespec_valid,
+ fieldset => $section,
+ );
+ }
+ elsif ($info{type} eq "integer") {
+ $form->field(
+ name => $name,
+ label => $description,
+ comment => formatexample($info{example}, $value),
+ type => "text",
+ value => $value,
+ size => 5,
+ validate => '/^[0-9]+$/',
+ fieldset => $section,
+ );
+ }
+ elsif ($info{type} eq "boolean") {
+ $form->field(
+ name => $name,
+ label => "",
+ type => "checkbox",
+ options => [ [ 1 => $description ] ],
+ fieldset => $section,
+ );
+ if (! $form->submitted ||
+ ($info{advanced} && $form->submitted eq 'Advanced Mode')) {
+ $form->field(name => $name, value => $value);
+ }
+ }
+
+ if (! $info{safe} || ! issafe($key)) {
+ $form->field(name => $name, disabled => 1);
+ }
+ else {
+ $enabledfields{$name}=[$key, \%info];
+ }
+ $shownfields++;
+ }
+
+ # if no fields were shown for the plugin, drop it into a combined
+ # fieldset for its section
+ if (defined $plugin && (! $plugin_forced || $config{websetup_advanced}) &&
+ ! $shownfields) {
+ $form->field(name => "enable.$plugin", fieldset => $section_fieldset);
+ }
+
+ return %enabledfields;
+}
+
+sub enable_plugin ($) {
+ my $plugin=shift;
+
+ $config{disable_plugins}=[grep { $_ ne $plugin } @{$config{disable_plugins}}];
+ push @{$config{add_plugins}}, $plugin;
+}
+
+sub disable_plugin ($) {
+ my $plugin=shift;
+
+ $config{add_plugins}=[grep { $_ ne $plugin } @{$config{add_plugins}}];
+ push @{$config{disable_plugins}}, $plugin;
+}
+
+sub showform ($$) {