]> sipb.mit.edu Git - ikiwiki.git/blob - doc/patchqueue/move_page.mdwn
* Search in default location for templates as a fallback when templatedir is
[ikiwiki.git] / doc / patchqueue / move_page.mdwn
1 This is my first cut at a feature like that requested in [[todo/Moving_Pages]]. In case it gets mangled you can find it on [my site](http://www.betacantrips.com//attic/move.patch).
2
3 A bunch of obvious shortcomings exist: 
4
5 * I'm not sure all the untaints are safe.
6 * No precautions whatsoever are made to protect against race conditions or failures
7   in the rcs\_move function.
8 * movepage.tmpl doesn't exist yet.
9 * Some code is duplicated between cgi\_movepage and cgi\_editpage, as well
10   as rcs\_commit and rcs\_move.
11 * The user interface is pretty lame -- there's no handy select list full 
12   of possible places to move it or anything.
13 * I don't think I implemented cancelling.
14 * from is redundant with page.
15 * I don't think I called the right hook functions.
16 * No redirect pages like those mentioned on [[todo/Moving_Pages]] exist yet, 
17   so none are created.
18 * It's not possible to get there through the actions listed on the wiki page.
19   Instead you can select "Edit" and then change "edit" to "move" in the 
20   location bar.
21
22 Anyhow, here's the patch, for whatever good it does.
23
24     diff -urx .svn ikiwiki/IkiWiki/CGI.pm ikiwiki-new/IkiWiki/CGI.pm
25     --- ikiwiki/IkiWiki/CGI.pm  2007-01-04 03:52:47.000000000 -0800
26     +++ ikiwiki-new/IkiWiki/CGI.pm      2007-01-11 18:49:37.000000000 -0800
27     @@ -523,6 +523,97 @@
28         }
29      } #}}}
30      
31     +sub cgi_movepage($$) {
32     +   my $q = shift;
33     +   my $session = shift;
34     +   eval q{use CGI::FormBuilder};
35     +   error($@) if $@;
36     +   my @fields=qw(do from rcsinfo subpage page newname message); # subpage ignored so far
37     +   my @buttons=("Rename Page", "Cancel");
38     +
39     +   my $form = CGI::FormBuilder->new(
40     +           fields => \@fields,
41     +                header => 1,
42     +                charset => "utf-8",
43     +                method => 'POST',
44     +           action => $config{cgiurl},
45     +                template => (-e "$config{templatedir}/movepage.tmpl" ?
46     +                        {template_params("movepage.tpml")} : ""),
47     +   );
48     +   run_hooks(formbuilder_setup => sub {
49     +           shift->(form => $form, cgi => $q, session => $session);
50     +   });
51     +
52     +   decode_form_utf8($form);
53     +   
54     +   # This untaint is safe because if the page doesn't exist, bail.
55     +   my $page = $form->field('page');
56     +   $page = possibly_foolish_untaint($page);
57     +   if (! exists $pagesources{$page}) {
58     +           error("page does not exist");
59     +   }
60     +   my $file=$pagesources{$page};
61     +   my $type=pagetype($file);
62     +
63     +   my $from;
64     +   if (defined $form->field('from')) {
65     +           ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
66     +   }
67     +   
68     +   $form->field(name => "do", type => 'hidden');
69     +   $form->field(name => "from", type => 'hidden');
70     +   $form->field(name => "rcsinfo", type => 'hidden');
71     +   $form->field(name => "subpage", type => 'hidden');
72     +   $form->field(name => "page", value => $page, force => 1);
73     +   $form->field(name => "newname", type => "text", size => 80);
74     +   $form->field(name => "message", type => "text", size => 80);
75     +
76     +   if (! $form->submitted) {
77     +           $form->field(name => "rcsinfo", value => rcs_prepedit($file),
78     +                        force => 1);
79     +   }
80     +
81     +   if ($form->submitted eq "Cancel") {
82     +           redirect($q, "$config{url}/".htmlpage($from));
83     +           return;
84     +   }
85     +           
86     +   if (! $form->submitted || $form->submitted eq "Preview" || 
87     +       ! $form->validate) {
88     +           if ($form->field("do") eq "move"){
89     +                   page_locked($page, $session);
90     +                   $form->tmpl_param("page_select", 0);
91     +                   $form->field(name => "page", type => 'hidden');
92     +                   $form->field(name => "type", type => 'hidden');
93     +                   $form->title(sprintf(gettext("moving %s"), pagetitle($page)));
94     +                   if (! defined $form->field('newname') ||
95     +                       ! length $form->field('newname')) {
96     +                           $form->field(name => "newname", 
97     +                                        value => pagetitle($page), force => 1);
98     +                   }
99     +
100     +           }
101     +           print $form->render(submit => \@buttons);
102     +   }
103     +   else{
104     +           # This untaint is safe because titlepage removes any problematic
105     +           # characters.
106     +           my ($newname)=$form->field('newname');
107     +           $newname=titlepage(possibly_foolish_untaint($newname));
108     +           if (! defined $newname || ! length $newname || file_pruned($newname, $config{srcdir}) || $newname=~/^\//) {
109     +                   error("bad page name");
110     +           }
111     +           page_locked($page, $session);
112     +
113     +           my $newfile = $newname . ".$type";
114     +           my $message = $form->field('message');
115     +           unlockwiki();
116     +           rcs_move($file, $newfile, $message, $form->field("rcsinfo"), 
117     +                    $session->param("name"), $ENV{REMOTE_ADDR});
118     +           redirect($q, "$config{url}/".htmlpage($newname));
119     +   }
120     +}
121     +
122      sub cgi_getsession ($) { #{{{
123         my $q=shift;
124      
125     @@ -631,6 +722,9 @@
126         if ($do eq 'create' || $do eq 'edit') {
127                 cgi_editpage($q, $session);
128         }
129     +   elsif ($do eq 'move') {
130     +           cgi_movepage($q, $session);
131     +   }
132         elsif ($do eq 'prefs') {
133                 cgi_prefs($q, $session);
134         }
135     diff -urx .svn ikiwiki/IkiWiki/Rcs/svn.pm ikiwiki-new/IkiWiki/Rcs/svn.pm
136     --- ikiwiki/IkiWiki/Rcs/svn.pm      2006-12-28 17:50:46.000000000 -0800
137     +++ ikiwiki-new/IkiWiki/Rcs/svn.pm  2007-01-11 18:14:30.000000000 -0800
138     @@ -60,6 +60,34 @@
139         }
140      } #}}}
141      
142     +sub rcs_move ($$$$;$$) {
143     +   my $file=shift;
144     +   my $newname=shift;
145     +   my $message=shift;
146     +   my $rcstoken=shift;
147     +   my $user=shift;
148     +   my $ipaddr=shift;
149     +   if (defined $user) {
150     +           $message="web commit by $user".(length $message ? ": $message" : "");
151     +   }
152     +   elsif (defined $ipaddr) {
153     +           $message="web commit from $ipaddr".(length $message ? ": $message" : "");
154     +   }
155     +
156     +   chdir($config{srcdir}); # svn merge wants to be here
157     +
158     +   if (system("svn", "move", "--quiet", 
159     +              "$file", "$newname") != 0) {
160     +           return 1;
161     +   }
162     +   if (system("svn", "commit", "--quiet", 
163     +              "--encoding", "UTF-8", "-m",
164     +              possibly_foolish_untaint($message)) != 0) {
165     +           return 1;
166     +   }
167     +   return undef # success
168     +}
169     +
170      sub rcs_commit ($$$;$$) { #{{{
171         # Tries to commit the page; returns undef on _success_ and
172         # a version of the page with the rcs's conflict markers on failure.