plugin => {
safe => 1,
rebuild => 1,
+ section => "core",
},
}
# Back to ikiwiki namespace for the rest, this code is very much
# internal to ikiwiki even though it's separated into a plugin,
-# and other plugins use the functions below.
+# and other plugins use the function below.
package IkiWiki;
-sub check_canedit ($$$;$) {
- my $page=shift;
- my $q=shift;
- my $session=shift;
- my $nonfatal=shift;
-
- my $canedit;
- run_hooks(canedit => sub {
- return if defined $canedit;
- my $ret=shift->($page, $q, $session);
- if (defined $ret) {
- if ($ret eq "") {
- $canedit=1;
- }
- elsif (ref $ret eq 'CODE') {
- $ret->() unless $nonfatal;
- $canedit=0;
- }
- elsif (defined $ret) {
- error($ret) unless $nonfatal;
- $canedit=0;
- }
- }
- });
- return defined $canedit ? $canedit : 1;
-}
-
-sub check_content (@) {
- my %params=@_;
-
- return 1 if ! exists $hooks{checkcontent}; # optimisation
-
- if (exists $pagesources{$params{page}}) {
- my @diff;
- my %old=map { $_ => 1 }
- split("\n", readfile(srcfile($pagesources{$params{page}})));
- foreach my $line (split("\n", $params{content})) {
- push @diff, $line if ! exists $old{$_};
- }
- $params{content}=join("\n", @diff);
- }
-
- my $ok;
- run_hooks(checkcontent => sub {
- return if defined $ok;
- my $ret=shift->(%params);
- if (defined $ret) {
- if ($ret eq "") {
- $ok=1;
- }
- elsif (ref $ret eq 'CODE') {
- $ret->();
- $ok=0;
- }
- elsif (defined $ret) {
- error($ret);
- }
- }
-
- });
- return defined $ok ? $ok : 1;
-}
-
-sub check_cansave ($$$$) {
- my $page=shift;
- my $content=shift;
- my $q=shift;
- my $session=shift;
-
- my $cansave;
- run_hooks(cansave => sub {
- return if defined $cansave;
- my $ret=shift->($page, $content, $q, $session);
- if (defined $ret) {
- if ($ret eq "") {
- $cansave=1;
- }
- elsif (ref $ret eq 'CODE') {
- $ret->();
- $cansave=0;
- }
- else {
- error($ret);
- $cansave=0;
- }
- }
- });
- return $cansave;
-}
-
sub cgi_editpage ($$) {
my $q=shift;
my $session=shift;
decode_cgi_utf8($q);
- my @fields=qw(do rcsinfo subpage from page type editcontent comments);
+ my @fields=qw(do rcsinfo subpage from page type editcontent editmessage);
my @buttons=("Save Page", "Preview", "Cancel");
eval q{use CGI::FormBuilder};
error($@) if $@;
required => [qw{editcontent}],
javascript => 0,
params => $q,
- action => $config{cgiurl},
+ action => IkiWiki::cgiurl(),
header => 0,
table => 0,
- template => scalar template_params("editpage.tmpl"),
+ template => { template("editpage.tmpl") },
);
decode_form_utf8($form);
# This untaint is safe because we check file_pruned and
# wiki_file_regexp.
my ($page)=$form->field('page')=~/$config{wiki_file_regexp}/;
+ if (! defined $page) {
+ error(gettext("bad page name"));
+ }
$page=possibly_foolish_untaint($page);
- my $absolute=($page =~ s#^/+##);
+ my $absolute=($page =~ s#^/+##); # absolute name used to force location
if (! defined $page || ! length $page ||
- file_pruned($page, $config{srcdir})) {
+ file_pruned($page)) {
error(gettext("bad page name"));
}
- my $baseurl = urlto($page, undef, 1);
+ my $baseurl = urlto($page);
my $from;
if (defined $form->field('from')) {
# favor the type of linking page
$type=pagetype($pagesources{$from});
}
- $type=$config{default_pageext} unless defined $type;
+ $type=$config{default_pageext}
+ if ! defined $type || $type=~/^_/; # not internal type
$file=newpagefile($page, $type);
if (! $form->submitted) {
$form->field(name => "rcsinfo", value => "", force => 1);
$form->field(name => "subpage", type => 'hidden');
$form->field(name => "page", value => $page, force => 1);
$form->field(name => "type", value => $type, force => 1);
- $form->field(name => "comments", type => "text", size => 80);
+ $form->field(name => "editmessage", type => "text", size => 80);
$form->field(name => "editcontent", type => "textarea", rows => 20,
cols => 80);
$form->tmpl_param("can_commit", $config{rcs});
- $form->tmpl_param("indexlink", indexlink());
$form->tmpl_param("helponformattinglink",
htmllink($page, $page, "ikiwiki/formatting",
noimageinline => 1,
linktext => "FormattingHelp"));
+ my $previewing=0;
if ($form->submitted eq "Cancel") {
if ($form->field("do") eq "create" && defined $from) {
- redirect($q, urlto($from, undef, 1));
+ redirect($q, urlto($from));
}
elsif ($form->field("do") eq "create") {
- redirect($q, $config{url});
+ redirect($q, baseurl(undef));
}
else {
- redirect($q, urlto($page, undef, 1));
+ redirect($q, $baseurl);
}
exit;
}
elsif ($form->submitted eq "Preview") {
+ $previewing=1;
+
my $new=not exists $pagesources{$page};
- if ($new) {
- # temporarily record its type
- $pagesources{$page}=$page.".".$type;
- }
+ # temporarily record its type
+ $pagesources{$page}=$page.".".$type if $new;
my %wasrendered=map { $_ => 1 } @{$renderedfiles{$page}};
my $content=$form->field('editcontent');
});
$form->tmpl_param("page_preview", $preview);
- if ($new) {
- delete $pagesources{$page};
- }
-
# Previewing may have created files on disk.
# Keep a list of these to be deleted later.
my %previews = map { $_ => 1 } @{$wikistate{editpage}{previews}};
foreach my $f (@{$renderedfiles{$page}}) {
$previews{$f}=1 unless $wasrendered{$f};
}
+
+ # Throw out any other state changes made during previewing,
+ # and save the previews list.
+ loadindex();
@{$wikistate{editpage}{previews}} = keys %previews;
- $renderedfiles{$page}=[keys %wasrendered];
saveindex();
}
elsif ($form->submitted eq "Save Page") {
my $best_loc;
if (! defined $from || ! length $from ||
$from ne $form->field('from') ||
- file_pruned($from, $config{srcdir}) ||
- $from=~/^\// ||
+ file_pruned($from) ||
$absolute ||
$form->submitted) {
@page_locs=$best_loc=$page;
+ unshift @page_locs, lc($page)
+ if ! $form->submitted && lc($page) ne $page;
+ }
+ elsif (lc $page eq lc $config{discussionpage}) {
+ @page_locs=$best_loc=$page="$from/".lc($page);
}
else {
my $dir=$from."/";
$dir=~s![^/]+/+$!!;
- if ((defined $form->field('subpage') && length $form->field('subpage')) ||
- $page eq gettext('discussion')) {
+ if ((defined $form->field('subpage') &&
+ length $form->field('subpage'))) {
$best_loc="$from/$page";
}
else {
$best_loc=$dir.$page;
}
+ my $mixedcase=lc($page) ne $page;
+
+ push @page_locs, $dir.lc($page) if $mixedcase;
push @page_locs, $dir.$page;
- push @page_locs, "$from/$page";
+ push @page_locs, $from."/".lc($page) if $mixedcase;
+ push @page_locs, $from."/".$page;
while (length $dir) {
$dir=~s![^/]+/+$!!;
+ push @page_locs, $dir.lc($page) if $mixedcase;
push @page_locs, $dir.$page;
}
-
- push @page_locs, "$config{userdir}/$page"
- if length $config{userdir};
+
+ my $userpage=IkiWiki::userpage($page);
+ push @page_locs, $userpage
+ if ! grep { $_ eq $userpage } @page_locs;
}
@page_locs = grep {
if (! @page_locs) {
# hmm, someone else made the page in the
# meantime?
- if ($form->submitted eq "Preview") {
+ if ($previewing) {
# let them go ahead with the edit
# and resolve the conflict at save
# time
@page_locs=$page;
}
else {
- redirect($q, urlto($page, undef, 1));
+ redirect($q, $baseurl);
exit;
}
}
check_canedit($_, $q, $session, 1)
} @page_locs;
if (! @editable_locs) {
- # let it throw an error this time
- map { check_canedit($_, $q, $session) } @page_locs;
+ # now let it throw an error, or prompt for
+ # login
+ map { check_canedit($_, $q, $session) }
+ ($best_loc, @page_locs);
}
my @page_types;
if (exists $hooks{htmlize}) {
- @page_types=grep { !/^_/ }
- keys %{$hooks{htmlize}};
+ foreach my $key (grep { !/^_/ } keys %{$hooks{htmlize}}) {
+ push @page_types, [$key, $hooks{htmlize}{$key}{longname} || $key];
+ }
}
+ @page_types=sort @page_types;
$form->tmpl_param("page_select", 1);
$form->field(name => "page", type => 'select',
value => $best_loc);
$form->field(name => "type", type => 'select',
options => \@page_types);
- $form->title(sprintf(gettext("creating %s"), pagetitle($page)));
+ $form->title(sprintf(gettext("creating %s"), pagetitle(basename($page))));
}
elsif ($form->field("do") eq "edit") {
$form->tmpl_param("page_select", 0);
$form->field(name => "page", type => 'hidden');
$form->field(name => "type", type => 'hidden');
- $form->title(sprintf(gettext("editing %s"), pagetitle($page)));
+ $form->title(sprintf(gettext("editing %s"), pagetitle(basename($page))));
}
- showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
+ showform($form, \@buttons, $session, $q, page => $page);
}
else {
# save page
$form->field(name => "page", type => 'hidden');
$form->field(name => "type", type => 'hidden');
$form->title(sprintf(gettext("editing %s"), $page));
- showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
+ showform($form, \@buttons, $session, $q,
+ page => $page);
exit;
}
elsif ($form->field("do") eq "create" && $exists) {
value => readfile("$config{srcdir}/$file").
"\n\n\n".$form->field("editcontent"),
force => 1);
- showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
+ showform($form, \@buttons, $session, $q,
+ page => $page);
exit;
}
my $message="";
- if (defined $form->field('comments') &&
- length $form->field('comments')) {
- $message=$form->field('comments');
+ if (defined $form->field('editmessage') &&
+ length $form->field('editmessage')) {
+ $message=$form->field('editmessage');
}
my $content=$form->field('editcontent');
- check_cansave($page, $content, $q, $session);
check_content(content => $content, page => $page,
cgi => $q, session => $session,
subject => $message);
$form->field(name => "type", type => 'hidden');
$form->title(sprintf(gettext("editing %s"), $page));
showform($form, \@buttons, $session, $q,
- forcebaseurl => $baseurl);
+ page => $page);
exit;
}
# signaling to it that it should not try to
# do anything.
disable_commit_hook();
- $conflict=rcs_commit($file, $message,
- $form->field("rcsinfo"),
- $session->param("name"), $ENV{REMOTE_ADDR});
+ $conflict=rcs_commit(
+ file => $file,
+ message => $message,
+ token => $form->field("rcsinfo"),
+ session => $session,
+ );
enable_commit_hook();
rcs_update();
}
$form->field(name => "type", type => 'hidden');
$form->title(sprintf(gettext("editing %s"), $page));
showform($form, \@buttons, $session, $q,
- forcebaseurl => $baseurl);
+ page => $page);
}
else {
# The trailing question mark tries to avoid broken
# caches and get the most recent version of the page.
- redirect($q, urlto($page, undef, 1)."?updated");
+ redirect($q, $baseurl."?updated");
}
}