OSDN Git Service

BugTrack/84 Limit page name length: 115 bytes(soft); 125 bytes(hard)
[pukiwiki/pukiwiki.git] / plugin / edit.inc.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone.
3 // edit.inc.php
4 // Copyright 2001-2022 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
6 //
7 // Edit plugin (cmd=edit)
8
9 // Remove #freeze written by hand
10 define('PLUGIN_EDIT_FREEZE_REGEX', '/^(?:#freeze(?!\w)\s*)+/im');
11
12 function plugin_edit_action()
13 {
14         global $vars, $_title_edit;
15
16         if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
17
18         // Create initial pages
19         plugin_edit_setup_initial_pages();
20
21         $page = isset($vars['page']) ? $vars['page'] : '';
22         check_editable($page, true, true);
23         check_readable($page, true, true);
24
25         if (isset($vars['preview'])) {
26                 return plugin_edit_preview($vars['msg']);
27         } else if (isset($vars['template'])) {
28                 return plugin_edit_preview_with_template();
29         } else if (isset($vars['write'])) {
30                 return plugin_edit_write();
31         } else if (isset($vars['cancel'])) {
32                 return plugin_edit_cancel();
33         }
34         ensure_valid_page_name_length($page);
35         $postdata = @join('', get_source($page));
36         if ($postdata === '') $postdata = auto_template($page);
37         $postdata = remove_author_info($postdata);
38         return array('msg'=>$_title_edit, 'body'=>edit_form($page, $postdata));
39 }
40
41 function ensure_valid_page_name_length($page)
42 {
43         if (is_page($page)) {
44                 // Continue
45         } else {
46                 if (is_pagename_bytes_within_soft_limit($page)) {
47                         // Continue
48                 } else {
49                         if (page_exists_in_history($page)) {
50                                 if (is_pagename_bytes_within_hard_limit($page)) {
51                                         // Continue
52                                 } else {
53                                         die_message('Page name too long (hard limit): ' . htmlsc($page));
54                                         exit;
55                                 }
56                         } else {
57                                 die_message('Page name too long: ' . htmlsc($page));
58                                 exit;
59                         }
60                 }
61         }
62 }
63
64 /**
65  * Preview with template
66  */
67 function plugin_edit_preview_with_template()
68 {
69         global $vars;
70         $msg = '';
71         $page = isset($vars['page']) ? $vars['page'] : '';
72         // Loading template
73         $template_page;
74         if (isset($vars['template_page']) && is_page($template_page = $vars['template_page'])) {
75                 if (is_page_readable($template_page)) {
76                         $msg = remove_author_info(get_source($vars['template_page'], TRUE, TRUE));
77                         // Cut fixed anchors
78                         $msg = preg_replace('/^(\*{1,3}.*)\[#[A-Za-z][\w-]+\](.*)$/m', '$1$2', $msg);
79                 }
80         }
81         return plugin_edit_preview($msg);
82 }
83
84 /**
85  * Preview
86  *
87  * @param msg preview target
88  */
89 function plugin_edit_preview($msg)
90 {
91         global $vars;
92         global $_title_preview, $_msg_preview, $_msg_preview_delete;
93
94         $page = isset($vars['page']) ? $vars['page'] : '';
95
96         $msg = preg_replace(PLUGIN_EDIT_FREEZE_REGEX, '', $msg);
97         $postdata = $msg;
98
99         if (isset($vars['add']) && $vars['add']) {
100                 if (isset($vars['add_top']) && $vars['add_top']) {
101                         $postdata  = $postdata . "\n\n" . @join('', get_source($page));
102                 } else {
103                         $postdata  = @join('', get_source($page)) . "\n\n" . $postdata;
104                 }
105         }
106
107         $body = $_msg_preview . '<br />' . "\n";
108         if ($postdata === '')
109                 $body .= '<strong>' . $_msg_preview_delete . '</strong>';
110         $body .= '<br />' . "\n";
111
112         if ($postdata) {
113                 $postdata = make_str_rules($postdata);
114                 $postdata = explode("\n", $postdata);
115                 $postdata = drop_submit(convert_html($postdata));
116                 $body .= '<div id="preview">' . $postdata . '</div>' . "\n";
117         }
118         $body .= edit_form($page, $msg, $vars['digest'], FALSE);
119
120         return array('msg'=>$_title_preview, 'body'=>$body);
121 }
122
123 // Inline: Show edit (or unfreeze text) link
124 function plugin_edit_inline()
125 {
126         static $usage = '&edit(pagename#anchor[[,noicon],nolabel])[{label}];';
127
128         global $vars, $fixed_heading_anchor_edit;
129
130         if (PKWK_READONLY) return ''; // Show nothing 
131
132         // Arguments
133         $args = func_get_args();
134
135         // {label}. Strip anchor tags only
136         $s_label = strip_htmltag(array_pop($args), FALSE);
137
138         $page = array_shift($args);
139         if ($page === NULL) $page = '';
140         $_noicon = $_nolabel = FALSE;
141         foreach($args as $arg){
142                 switch(strtolower($arg)){
143                 case ''       :                   break;
144                 case 'nolabel': $_nolabel = TRUE; break;
145                 case 'noicon' : $_noicon  = TRUE; break;
146                 default       : return $usage;
147                 }
148         }
149
150         // Separate a page-name and a fixed anchor
151         list($s_page, $id, $editable) = anchor_explode($page, TRUE);
152
153         // Default: This one
154         if ($s_page == '') $s_page = isset($vars['page']) ? $vars['page'] : '';
155
156         // $s_page fixed
157         $isfreeze = is_freeze($s_page);
158         $ispage   = is_page($s_page);
159
160         // Paragraph edit enabled or not
161         $short = htmlsc('Edit');
162         if ($fixed_heading_anchor_edit && $editable && $ispage && ! $isfreeze) {
163                 // Paragraph editing
164                 $id    = rawurlencode($id);
165                 $title = htmlsc(sprintf('Edit %s', $page));
166                 $icon = '<img src="' . IMAGE_DIR . 'paraedit.png' .
167                         '" width="9" height="9" alt="' .
168                         $short . '" title="' . $title . '" /> ';
169                 $class = ' class="anchor_super"';
170         } else {
171                 // Normal editing / unfreeze
172                 $id    = '';
173                 if ($isfreeze) {
174                         $title = 'Unfreeze %s';
175                         $icon  = 'unfreeze.png';
176                 } else {
177                         $title = 'Edit %s';
178                         $icon  = 'edit.png';
179                 }
180                 $title = htmlsc(sprintf($title, $s_page));
181                 $icon = '<img src="' . IMAGE_DIR . $icon .
182                         '" width="20" height="20" alt="' .
183                         $short . '" title="' . $title . '" />';
184                 $class = '';
185         }
186         if ($_noicon) $icon = ''; // No more icon
187         if ($_nolabel) {
188                 if (!$_noicon) {
189                         $s_label = '';     // No label with an icon
190                 } else {
191                         $s_label = $short; // Short label without an icon
192                 }
193         } else {
194                 if ($s_label == '') $s_label = $title; // Rich label with an icon
195         }
196
197         // URL
198         $script = get_base_uri();
199         if ($isfreeze) {
200                 $url   = $script . '?cmd=unfreeze&amp;page=' . rawurlencode($s_page);
201         } else {
202                 $s_id = ($id == '') ? '' : '&amp;id=' . $id;
203                 $url  = $script . '?cmd=edit&amp;page=' . rawurlencode($s_page) . $s_id;
204         }
205         $atag  = '<a' . $class . ' href="' . $url . '" title="' . $title . '">';
206         static $atags = '</a>';
207
208         if ($ispage) {
209                 // Normal edit link
210                 return $atag . $icon . $s_label . $atags;
211         } else {
212                 // Dangling edit link
213                 return '<span class="noexists">' . $atag . $icon . $atags .
214                         $s_label . $atag . '?' . $atags . '</span>';
215         }
216 }
217
218 // Write, add, or insert new comment
219 function plugin_edit_write()
220 {
221         global $vars;
222         global $_title_collided, $_msg_collided_auto, $_msg_collided, $_title_deleted;
223         global $notimeupdate, $_msg_invalidpass, $do_update_diff_table;
224
225         $page   = isset($vars['page'])   ? $vars['page']   : '';
226         $add    = isset($vars['add'])    ? $vars['add']    : '';
227         $digest = isset($vars['digest']) ? $vars['digest'] : '';
228
229         ensure_valid_page_name_length($page);
230         $vars['msg'] = preg_replace(PLUGIN_EDIT_FREEZE_REGEX, '', $vars['msg']);
231         $msg = & $vars['msg']; // Reference
232
233         $retvars = array();
234
235         // Collision Detection
236         $oldpagesrc = join('', get_source($page));
237         $oldpagemd5 = md5($oldpagesrc);
238         if ($digest !== $oldpagemd5) {
239                 $vars['digest'] = $oldpagemd5; // Reset
240
241                 $original = isset($vars['original']) ? $vars['original'] : '';
242                 $old_body = remove_author_info($oldpagesrc);
243                 list($postdata_input, $auto) = do_update_diff($old_body, $msg, $original);
244
245                 $retvars['msg' ] = $_title_collided;
246                 $retvars['body'] = ($auto ? $_msg_collided_auto : $_msg_collided) . "\n";
247                 $retvars['body'] .= $do_update_diff_table;
248                 $retvars['body'] .= edit_form($page, $postdata_input, $oldpagemd5, FALSE);
249                 return $retvars;
250         }
251
252         // Action?
253         if ($add) {
254                 // Add
255                 if (isset($vars['add_top']) && $vars['add_top']) {
256                         $postdata  = $msg . "\n\n" . @join('', get_source($page));
257                 } else {
258                         $postdata  = @join('', get_source($page)) . "\n\n" . $msg;
259                 }
260         } else {
261                 // Edit or Remove
262                 $postdata = & $msg; // Reference
263         }
264
265         // NULL POSTING, OR removing existing page
266         if ($postdata === '') {
267                 page_write($page, $postdata);
268                 $retvars['msg' ] = $_title_deleted;
269                 $retvars['body'] = str_replace('$1', htmlsc($page), $_title_deleted);
270                 return $retvars;
271         }
272
273         // $notimeupdate: Checkbox 'Do not change timestamp'
274         $notimestamp = isset($vars['notimestamp']) && $vars['notimestamp'] != '';
275         if ($notimeupdate > 1 && $notimestamp && ! pkwk_login($vars['pass'])) {
276                 // Enable only administrator & password error
277                 $retvars['body']  = '<p><strong>' . $_msg_invalidpass . '</strong></p>' . "\n";
278                 $retvars['body'] .= edit_form($page, $msg, $digest, FALSE);
279                 return $retvars;
280         }
281
282         page_write($page, $postdata, $notimeupdate != 0 && $notimestamp);
283         pkwk_headers_sent();
284         header('Location: ' . get_page_uri($page, PKWK_URI_ROOT));
285         exit;
286 }
287
288 // Cancel (Back to the page / Escape edit page)
289 function plugin_edit_cancel()
290 {
291         global $vars;
292         pkwk_headers_sent();
293         header('Location: ' . get_page_uri($vars['page'], PKWK_URI_ROOT));
294         exit;
295 }
296
297 /**
298  * Setup initial pages
299  */
300 function plugin_edit_setup_initial_pages()
301 {
302         global $autoalias, $no_autoticketlinkname;
303
304         // Related: Rename plugin
305         if (exist_plugin('rename') && function_exists('plugin_rename_setup_initial_pages')) {
306                 plugin_rename_setup_initial_pages();
307         }
308         // AutoTicketLinkName page
309         if (! $no_autoticketlinkname) {
310                 init_autoticketlink_def_page();
311         }
312         // AutoAliasName page
313         if ($autoalias) {
314                 init_autoalias_def_page();
315         }
316 }