diff --git a/doc/bugs.mdwn b/doc/bugs.mdwn index e052763f1..53c82a00c 100644 --- a/doc/bugs.mdwn +++ b/doc/bugs.mdwn @@ -6,3 +6,5 @@ back to Foo/Baz. * Foo/Bar/Baz shows up as Bar/Baz in the linkbacks on page Foo/Bar. Should show as just Baz there. +* If I try to do a web commit, to a svn+ssh repo, it fails with + "Host key verification failed." diff --git a/doc/security.mdwn b/doc/security.mdwn index 7b056fd6c..1521a5f46 100644 --- a/doc/security.mdwn +++ b/doc/security.mdwn @@ -1,4 +1,4 @@ -Let's do an ikiwiki security analysis.. +Let's do an ikiwiki security analysis.. ok If you are using ikiwiki to render pages that only you can edit, do not generate any wrappers, and do not use the cgi, then there are no more diff --git a/doc/todo.mdwn b/doc/todo.mdwn index b7b23ef56..ef3600d43 100644 --- a/doc/todo.mdwn +++ b/doc/todo.mdwn @@ -1,17 +1,10 @@ ## online page editing -To support editing pages in a web browser, a CGI script is needed that -pulls the page out of [[Subversion]], presents it to the user for editing, -and then commits the changed page back to [[Subversion]]. - -Due to [[WikiSpam]], this will probably also need to incorporate a user -registration system. So there will need to be a script that handles logins -and registrations, sets a cookie, and the page editor can refuse to edit -pages for users who arn't logged in, and include a not of who made the -change in the svn log. - -If possible I'd prefer to use someone else's generic web user registration -and login system, if one exists. +* Missing support for preview, cancel. +* Missing conflict detection. +* Missing commit message box. +* No support for web user tracking/login yet. +* Doesn't svn commit yet. ## [[RecentChanges]] diff --git a/ikiwiki b/ikiwiki index 8ba324961..5efca6c7f 100755 --- a/ikiwiki +++ b/ikiwiki @@ -23,6 +23,7 @@ my $wikiname="wiki"; my $default_pagetype=".mdwn"; my $cgi=0; my $url=""; +my $svn=1; sub usage { die "usage: ikiwiki [options] source dest\n"; @@ -322,7 +323,7 @@ sub saveindex () { close OUT; } -sub update () { +sub rcs_update () { if (-d "$srcdir/.svn") { if (system("svn", "update", "--quiet", $srcdir) != 0) { warn("svn update failed\n"); @@ -330,6 +331,27 @@ sub update () { } } +sub rcs_commit ($) { + my $message=shift; + + if (-d "$srcdir/.svn") { + if (system("svn", "commit", "--quiet", "-m", + possibly_foolish_untaint($message), $srcdir) != 0) { + warn("svn commit failed\n"); + } + } +} + +sub rcs_ad ($) { + my $file=shift; + + if (-d "$srcdir/.svn") { + if (system("svn", "add", "--quiet", $file) != 0) { + warn("svn add failed\n"); + } + } +} + sub prune ($) { my $file=shift; @@ -466,7 +488,7 @@ FILE: foreach my $file (@files) { # Generates a C wrapper program for running ikiwiki in a specific way. # The wrapper may be safely made suid. sub gen_wrapper ($$) { - my ($offline, $rebuild)=@_; + my ($svn, $rebuild)=@_; eval {use Cwd 'abs_path'}; $srcdir=abs_path($srcdir); @@ -479,13 +501,13 @@ sub gen_wrapper ($$) { my $call=qq{"$this", "$this", "$srcdir", "$destdir", "--wikiname=$wikiname"}; $call.=', "--verbose"' if $verbose; $call.=', "--rebuild"' if $rebuild; - $call.=', "--offline"' if $offline; + $call.=', "--nosvn"' if !$svn; $call.=', "--cgi"' if $cgi; $call.=', "--url='.$url.'"' if $url; - # For CGI we need all these environment variables. - my @envsave=qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI - CONTENT_TYPE CONTENT_LENGTH GATEWAY_INTERFACE}; + my @envsave; + push @envsave, qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI + CONTENT_TYPE CONTENT_LENGTH GATEWAY_INTERFACE} if $cgi; my $envsave=""; foreach my $var (@envsave) { $envsave.=<<"EOF" @@ -507,17 +529,13 @@ extern char **environ; int main (void) { /* Sanitize environment. */ - if ($cgi) { - char *s; - char *newenviron[$#envsave+2]; - int i=0; - $envsave; - newenviron[i]=NULL; - environ=newenviron; - } - else { - clearenv(); - } + char *s; + char *newenviron[$#envsave+3]; + int i=0; + $envsave; + newenviron[i++]="HOME=$ENV{HOME}"; + newenviron[i]=NULL; + environ=newenviron; execl($call, NULL); perror("failed to run $this"); @@ -568,19 +586,21 @@ sub cgi () { -default => $content, -rows => 20, -columns => 80), - $q->p, + $q->br, + "$ENV{HOME} Optional comment about this change", + $q->br, + $q->textfield(-name => "comments", -size => 80), + $q->br, $q->submit("Save Changes"), - # TODO: Cancel button returns to page. - # TODO: Preview button. - # TODO: Commit message field. - # TODO: Conflict prevention. $q->end_form, $q->end_html; } elsif ($do eq 'save') { my $file=$page.$default_pagetype; + my $newfile=1; if (exists $pagesources{lc($page)}) { $file=$pagesources{lc($page)}; + $newfile=0; } my $content=$q->param('content'); @@ -588,6 +608,23 @@ sub cgi () { $content=~s/\r/\n/g; writefile("$srcdir/$file", $content); + my $message="web commit from $ENV{REMOTE_ADDR}"; + if (defined $q->param('comments')) { + $message.="\n".$q->param('comments'); + } + + if ($svn) { + if ($newfile) { + rcs_add($file); + } + # presumably the commit will trigger an update + # of the wiki + rcs_commit($message); + } + else { + refresh(); + } + print $q->redirect("$url/".htmlpage($page)); } else { @@ -596,7 +633,6 @@ sub cgi () { } my $rebuild=0; -my $offline=0; my $wrapper=0; if (grep /^-/, @ARGV) { eval {use Getopt::Long}; @@ -605,7 +641,7 @@ if (grep /^-/, @ARGV) { "verbose|v" => \$verbose, "rebuild" => \$rebuild, "wrapper" => \$wrapper, - "offline" => \$offline, + "svn!" => \$svn, "cgi" => \$cgi, "url=s" => \$url, ) || usage(); @@ -618,7 +654,7 @@ if ($cgi && ! length $url) { error("Must specify url to wiki with --url when using --cgi"); } -gen_wrapper($offline, $rebuild) if $wrapper; +gen_wrapper($svn, $rebuild) if $wrapper; memoize('pagename'); memoize('bestlink'); loadindex() unless $rebuild; @@ -626,7 +662,7 @@ if ($cgi) { cgi(); } else { - update() unless $offline; + rcs_update() if $svn; refresh(); saveindex(); }