From b2bd2e93f01979df1a25e6f349022103bc20339a Mon Sep 17 00:00:00 2001 From: Amitai Schlair Date: Thu, 10 Sep 2009 17:34:52 -0400 Subject: [PATCH] Revivify unixauth and rsync plugins (and hook needed by rsync) lost in the last merge. I should really put each feature on its own git branch. --- IkiWiki/Plugin/rsync.pm | 45 +++++++++ IkiWiki/Plugin/unixauth.pm | 195 +++++++++++++++++++++++++++++++++++++ IkiWiki/Render.pm | 1 + 3 files changed, 241 insertions(+) create mode 100644 IkiWiki/Plugin/rsync.pm create mode 100644 IkiWiki/Plugin/unixauth.pm diff --git a/IkiWiki/Plugin/rsync.pm b/IkiWiki/Plugin/rsync.pm new file mode 100644 index 000000000..3f049457b --- /dev/null +++ b/IkiWiki/Plugin/rsync.pm @@ -0,0 +1,45 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::rsync; + +use warnings; +use strict; +use IkiWiki 3.00; + +sub import { + hook(type => "getsetup", id => "rsync", call => \&getsetup); + hook(type => "checkconfig", id => "rsync", call => \&checkconfig); + hook(type => "postrefresh", id => "rsync", call => \&postrefresh); +} + +sub getsetup () { + return + plugin => { + safe => 0, + rebuild => 0, + }, + rsync_command => { + type => "string", + example => "rsync -qa --delete /path/to/destdir/ user\@host:/path/to/docroot/", + description => "unattended command to upload regenerated pages", + safe => 0, + rebuild => 0, + }, +} + +sub checkconfig { + if (! exists $config{rsync_command} || + ! defined $config{rsync_command}) { + error("Must specify rsync_command"); + } +} + +sub postrefresh () { + system $config{rsync_command}; + if ($? == -1) { + error("failed to execute rsync_command: $!"); + } elsif ($? != 0) { + error(sprintf("rsync_command exited %d", $? >> 8)); + } +} + +1 diff --git a/IkiWiki/Plugin/unixauth.pm b/IkiWiki/Plugin/unixauth.pm new file mode 100644 index 000000000..4f0cb4dd2 --- /dev/null +++ b/IkiWiki/Plugin/unixauth.pm @@ -0,0 +1,195 @@ +#!/usr/bin/perl +# Ikiwiki unixauth authentication. +package IkiWiki::Plugin::unixauth; + +use warnings; +use strict; +use IkiWiki 2.00; + +sub import { + hook(type => "getsetup", id => "unixauth", call => \&getsetup); + hook(type => "formbuilder_setup", id => "unixauth", + call => \&formbuilder_setup); + hook(type => "formbuilder", id => "unixauth", + call => \&formbuilder); + hook(type => "sessioncgi", id => "unixauth", call => \&sessioncgi); +} + +sub getsetup () { + return + unixauth_type => { + type => "string", + example => "checkpassword", + description => "type of authenticator; can be 'checkpassword' or 'pwauth'", + safe => 0, + rebuild => 1, + }, + unixauth_command => { + type => "string", + example => "/path/to/checkpassword", + description => "full path and any arguments", + safe => 0, + rebuild => 1, + }, + unixauth_requiressl => { + type => "boolean", + example => "1", + description => "require SSL? strongly recommended", + safe => 0, + rebuild => 1, + }, + plugin => { + description => "Unix user authentication", + safe => 0, + rebuild => 1, + }, +} + +# Checks if a string matches a user's password, and returns true or false. +sub checkpassword ($$;$) { + my $user=shift; + my $password=shift; + my $field=shift || "password"; + + # It's very important that the user not be allowed to log in with + # an empty password! + if (! length $password) { + return 0; + } + + my $ret=0; + if (! exists $config{unixauth_type}) { + # admin needs to carefully think over his configuration + return 0; + } + elsif ($config{unixauth_type} eq "checkpassword") { + open UNIXAUTH, "|$config{unixauth_command} true 3<&0" or die("Could not run $config{unixauth_type}"); + print UNIXAUTH "$user\0$password\0Y123456\0"; + close UNIXAUTH; + $ret=!($?>>8); + } + elsif ($config{unixauth_type} eq "pwauth") { + open UNIXAUTH, "|$config{unixauth_command}" or die("Could not run $config{unixauth_type}"); + print UNIXAUTH "$user\n$password\n"; + close UNIXAUTH; + $ret=!($?>>8); + } + else { + # no such authentication type + return 0; + } + + if ($ret) { + my $userinfo=IkiWiki::userinfo_retrieve(); + if (! length $user || ! defined $userinfo || + ! exists $userinfo->{$user} || ! ref $userinfo->{$user}) { + IkiWiki::userinfo_setall($user, { + 'email' => '', + 'regdate' => time, + }); + } + } + + return $ret; +} + +sub formbuilder_setup (@) { + my %params=@_; + + my $form=$params{form}; + my $session=$params{session}; + my $cgi=$params{cgi}; + + # if not under SSL, die before even showing a login form, + # unless the admin explicitly says it's fine + if (! exists $config{unixauth_requiressl}) { + $config{unixauth_requiressl} = 1; + } + if ($config{unixauth_requiressl}) { + if ((! $config{sslcookie}) || (! exists $ENV{'HTTPS'})) { + die("SSL required to login. Contact your administrator.
"); + } + } + + if ($form->title eq "signin") { + $form->field(name => "name", required => 0); + $form->field(name => "password", type => "password", required => 0); + + if ($form->submitted) { + my $submittype=$form->submitted; + # Set required fields based on how form was submitted. + my %required=( + "Login" => [qw(name password)], + ); + foreach my $opt (@{$required{$submittype}}) { + $form->field(name => $opt, required => 1); + } + + # Validate password against name for Login. + if ($submittype eq "Login") { + $form->field( + name => "password", + validate => sub { + checkpassword($form->field("name"), shift); + }, + ); + } + + # XXX is this reachable? looks like no + elsif ($submittype eq "Login") { + $form->field( + name => "name", + validate => sub { + my $name=shift; + length $name && + IkiWiki::userinfo_get($name, "regdate"); + }, + ); + } + } + else { + # First time settings. + $form->field(name => "name"); + if ($session->param("name")) { + $form->field(name => "name", value => $session->param("name")); + } + } + } + elsif ($form->title eq "preferences") { + $form->field(name => "name", disabled => 1, + value => $session->param("name"), force => 1, + fieldset => "login"); + $form->field(name => "password", disabled => 1, type => "password", + fieldset => "login"), + } +} + +sub formbuilder (@) { + my %params=@_; + + my $form=$params{form}; + my $session=$params{session}; + my $cgi=$params{cgi}; + my $buttons=$params{buttons}; + + if ($form->title eq "signin") { + if ($form->submitted && $form->validate) { + if ($form->submitted eq 'Login') { + $session->param("name", $form->field("name")); + IkiWiki::cgi_postsignin($cgi, $session); + } + } + } + elsif ($form->title eq "preferences") { + if ($form->submitted eq "Save Preferences" && $form->validate) { + my $user_name=$form->field('name'); + } + } +} + +sub sessioncgi ($$) { + my $q=shift; + my $session=shift; +} + +1 diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 246c2260d..5953b3fee 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -554,6 +554,7 @@ sub refresh () { if (%rendered) { run_hooks(change => sub { shift->(keys %rendered) }); } + run_hooks(postrefresh => sub { shift->() }); } sub commandline_render () { -- 2.39.5