Merge commit 'upstream/master' into prv/po
authorintrigeri <intrigeri@boum.org>
Sat, 17 Jan 2009 13:01:53 +0000 (14:01 +0100)
committerintrigeri <intrigeri@boum.org>
Sat, 17 Jan 2009 13:01:53 +0000 (14:01 +0100)
Conflicts:

IkiWiki/Plugin/editpage.pm
IkiWiki/Plugin/skeleton.pm.example
doc/plugins/write.mdwn
t/syntax.t

1  2 
IkiWiki/Plugin/editpage.pm
IkiWiki/Plugin/skeleton.pm.example
doc/plugins/write.mdwn
t/syntax.t

index 91d125a5ca1ca30e836706a6e5e2aa43df6eced2,bba52e4fd322e8bbad5f63a13198ff5f491cdef5..658d664af38d76b330ae9c27b74e77e5f28172a6
@@@ -78,36 -78,45 +78,72 @@@ sub check_canedit ($$$;$) 
                        }
                }
        });
-       return $canedit;
+       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;
                        showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
                        exit;
                }
+                       
+               my $message="";
+               if (defined $form->field('comments') &&
+                   length $form->field('comments')) {
+                       $message=$form->field('comments');
+               }
                
                my $content=$form->field('editcontent');
 +              check_cansave($page, $content, $q, $session);
+               check_content(content => $content, page => $page,
+                       cgi => $q, session => $session,
+                       subject => $message);
                run_hooks(editcontent => sub {
                        $content=shift->(
                                content => $content,
                
                my $conflict;
                if ($config{rcs}) {
-                       my $message="";
-                       if (defined $form->field('comments') &&
-                           length $form->field('comments')) {
-                               $message=$form->field('comments');
-                       }
-                       
                        if (! $exists) {
                                rcs_add($file);
                        }
index 0bd5edeef748b328cfd869c2104860a1c0b6794f,ea7d6e47f576b3cb04ffeb79d9471fdab1cfa9b1..30c8dbd5c82d06dde62bc7a219fbcbf77bd64177
@@@ -30,7 -30,7 +30,8 @@@ sub import 
        hook(type => "auth", id => "skeleton", call => \&auth);
        hook(type => "sessioncgi", id => "skeleton", call => \&sessioncgi);
        hook(type => "canedit", id => "skeleton", call => \&canedit);
 +      hook(type => "cansave", id => "skeleton", call => \&cansave);
+       hook(type => "checkcontent", id => "skeleton", call => \&checkcontent);
        hook(type => "editcontent", id => "skeleton", call => \&editcontent);
        hook(type => "formbuilder_setup", id => "skeleton", call => \&formbuilder_setup);
        hook(type => "formbuilder", id => "skeleton", call => \&formbuilder);
@@@ -181,29 -181,10 +182,36 @@@ sub canedit ($$$) 
        debug("skeleton plugin running in canedit");
  }
  
++<<<<<<< HEAD:IkiWiki/Plugin/skeleton.pm.example
 +sub cansave ($$$$) {
 +      my $page=shift;
 +      my $content=shift;
 +      my $cgi=shift;
 +      my $session=shift;
 +
 +      debug("skeleton plugin running in cansave");
 +}
 +
 +sub canremove ($$$) {
 +      my $page=shift;
 +      my $cgi=shift;
 +      my $session=shift;
 +
 +      debug("skeleton plugin running in canremove");
 +}
 +
 +sub canrename ($$$) {
 +      my $page=shift;
 +      my $cgi=shift;
 +      my $session=shift;
 +
 +      debug("skeleton plugin running in canrename");
++=======
+ sub checkcontent (@) {
+       my %params=@_;
+       debug("skeleton plugin running in checkcontent");
++>>>>>>> upstream/master:IkiWiki/Plugin/skeleton.pm.example
  }
  
  sub editcontent ($$$) {
diff --combined doc/plugins/write.mdwn
index 4db02b532557addd28922fcf4c26ce1eda458586,99eea3d1696b3240647b439edae4d8768ddf1033..ef14f18dbb13fe81b0f85d1fcb2e85fd6fa63db1
@@@ -303,7 -303,7 +303,7 @@@ can check if the session object has a "
  
  ### canedit
  
-       hook(type => "canedit", id => "foo", call => \&pagelocked);
+       hook(type => "canedit", id => "foo", call => \&canedit);
  
  This hook can be used to implement arbitrary access methods to control when
  a page can be edited using the web interface (commits from revision control
@@@ -321,41 -321,26 +321,61 @@@ This hook should avoid directly redirec
  since it's sometimes used to test to see which pages in a set of pages a
  user can edit.
  
 +### cansave
 +
 +      hook(type => "cansave", id => "foo", call => \&cansave);
 +
 +This hook can be used to implement arbitrary access methods to control
 +when a page being edited can be saved using the web interface (commits
 +from revision control bypass it).
 +
 +When a page is about to be saved, each registered cansave hook is
 +called in turn, and passed the page name, the edited content, a CGI
 +object and a session object.
 +
 +The return value of a cansave hook is interpreted the same as for the
 +canedit hook.
 +
 +### canremove
 +
 +      hook(type => "canremove", id => "foo", call => \&canremove);
 +
 +This hook can be used to implement arbitrary access methods to control when
 +a page can be removed using the web interface (commits from revision control
 +bypass it). It works exactly like the `canedit` hook.
 +
 +### canrename
 +
 +      hook(type => "canrename", id => "foo", call => \&canrename);
 +
 +This hook can be used to implement arbitrary access methods to control when
 +a page can be renamed using the web interface (commits from revision control
 +bypass it). It works exactly like the `canedit` and `canremove` hook,
 +but is passed:
 +* a CGI object
 +* a session object
 +* the named parameters `src`, `srcfile`, `dest` and `destfile`.
 +
+ ### checkcontent
+       
+       hook(type => "checkcontent", id => "foo", call => \&checkcontent);
+ This hook is called to check the content a user has entered on a page,
+ before it is saved, and decide if it should be allowed.
+ It is passed named parameters: `content`, `page`, `cgi`, and `session`. If
+ the content the user has entered is a comment, it may also be passed some
+ additional parameters: `author`, `url`, and `subject`. The `subject`
+ parameter may also be filled with the user's comment about the change.
+ Note: When the user edits an existing wiki page, the passed `content` will
+ include only the lines that they added to the page, or modified.
+ The hook should return `undef` on success. If the content is disallowed, it
+ should return a message stating what the problem is, or a function
+ that can be run to perform whatever action is necessary to allow the user
+ to post the content.
  ### editcontent
  
        hook(type => "editcontent", id => "foo", call => \&editcontent);
@@@ -395,29 -380,14 +415,29 @@@ This hook is called whenever ikiwiki no
  the state is saved. The function can save other state, modify values before
  they're saved, etc.
  
 -### renamepage
 +### renamelink
  
 -      hook(type => "renamepage", id => "foo", call => \&renamepage);
 +      hook(type => "renamelink", id => "foo", call => \&renamelink);
  
  This hook is called by the [[plugins/rename]] plugin when it renames
 -something. The hook is passed named parameters: `page`, `oldpage`,
 -`newpage`, and `content`, and should try to modify the content to reflect
 -the name change. For example, by converting links to point to the new page.
 +something, once per page linking to the renamed page's old location.
 +The hook is passed named parameters: `page`, `oldpage`, `newpage`, and
 +`content`, and should try to modify the content of `page` to reflect
 +the name change. For example, by converting links to point to the
 +new page.
 +
 +### rename
 +
 +      hook(type => "rename", id => "foo", call => \&renamepages);
 +
 +When a page or set of pages is renamed, the referenced function is
 +called, and is passed:
 +
 +* a reference to an array of hashes with keys: `src`, `srcfile`,
 +  `dest`, `destfile`, `required`. Such a hook function can modify
 +  the array.
 +* a CGI object
 +* a session object
  
  ### getsetup
  
@@@ -555,10 -525,6 +575,10 @@@ the id can be controled by the user
  Logs a debugging message. These are supressed unless verbose mode is turned
  on.
  
 +#### `warning($)`
 +
 +Logs a warning message.
 +
  #### `error($;$)`
  
  Aborts with an error message. If the second parameter is passed, it is a
diff --combined t/syntax.t
index 8c96d1d848014e9145739515e974f0b5aac271ac,9d5cbc3739d168b9362cbfb91620a9f624e3a918..ddb0da073c9c4dddd7389f4d7cabc2b29a8fa948
@@@ -5,8 -5,8 +5,8 @@@ use Test::More
  
  my @progs="ikiwiki.in";
  my @libs="IkiWiki.pm";
- # monotone, external, amazon_s3 skipped since they need perl modules
- push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v monotone.pm | grep -v external.pm | grep -v amazon_s3.pm | grep -v po.pm`;
 -# monotone, external, blogspam, amazon_s3 skipped since they need perl modules
 -push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v monotone.pm | grep -v external.pm | grep -v blogspam.pm | grep -v amazon_s3.pm`;
++# monotone, external, blogspam, amazon_s3, po skipped since they need perl modules
++push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v monotone.pm | grep -v external.pm | grep -v blogspam.pm | grep -v amazon_s3.pm | grep -v po.pm`;
  push @libs, 'IkiWiki/Plugin/skeleton.pm.example';
  
  plan(tests => (@progs + @libs));