2 // PukiWiki - Yet another WikiWikiWeb clone.
4 // Copyright 2001-2022 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
7 // Edit plugin (cmd=edit)
9 // Remove #freeze written by hand
10 define('PLUGIN_EDIT_FREEZE_REGEX', '/^(?:#freeze(?!\w)\s*)+/im');
12 function plugin_edit_action()
14 global $vars, $_title_edit;
16 if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
18 // Create initial pages
19 plugin_edit_setup_initial_pages();
21 $page = isset($vars['page']) ? $vars['page'] : '';
22 check_editable($page, true, true);
23 check_readable($page, true, true);
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();
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));
41 function ensure_valid_page_name_length($page)
46 if (is_pagename_bytes_within_soft_limit($page)) {
49 if (page_exists_in_history($page)) {
50 if (is_pagename_bytes_within_hard_limit($page)) {
53 die_message('Page name too long (hard limit): ' . htmlsc($page));
57 die_message('Page name too long: ' . htmlsc($page));
65 * Preview with template
67 function plugin_edit_preview_with_template()
71 $page = isset($vars['page']) ? $vars['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));
78 $msg = preg_replace('/^(\*{1,3}.*)\[#[A-Za-z][\w-]+\](.*)$/m', '$1$2', $msg);
81 return plugin_edit_preview($msg);
87 * @param msg preview target
89 function plugin_edit_preview($msg)
92 global $_title_preview, $_msg_preview, $_msg_preview_delete;
94 $page = isset($vars['page']) ? $vars['page'] : '';
96 $msg = preg_replace(PLUGIN_EDIT_FREEZE_REGEX, '', $msg);
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));
103 $postdata = @join('', get_source($page)) . "\n\n" . $postdata;
107 $body = $_msg_preview . '<br />' . "\n";
108 if ($postdata === '')
109 $body .= '<strong>' . $_msg_preview_delete . '</strong>';
110 $body .= '<br />' . "\n";
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";
118 $body .= edit_form($page, $msg, $vars['digest'], FALSE);
120 return array('msg'=>$_title_preview, 'body'=>$body);
123 // Inline: Show edit (or unfreeze text) link
124 function plugin_edit_inline()
126 static $usage = '&edit(pagename#anchor[[,noicon],nolabel])[{label}];';
128 global $vars, $fixed_heading_anchor_edit;
130 if (PKWK_READONLY) return ''; // Show nothing
133 $args = func_get_args();
135 // {label}. Strip anchor tags only
136 $s_label = strip_htmltag(array_pop($args), FALSE);
138 $page = array_shift($args);
139 if ($page === NULL) $page = '';
140 $_noicon = $_nolabel = FALSE;
141 foreach($args as $arg){
142 switch(strtolower($arg)){
144 case 'nolabel': $_nolabel = TRUE; break;
145 case 'noicon' : $_noicon = TRUE; break;
146 default : return $usage;
150 // Separate a page-name and a fixed anchor
151 list($s_page, $id, $editable) = anchor_explode($page, TRUE);
154 if ($s_page == '') $s_page = isset($vars['page']) ? $vars['page'] : '';
157 $isfreeze = is_freeze($s_page);
158 $ispage = is_page($s_page);
160 // Paragraph edit enabled or not
161 $short = htmlsc('Edit');
162 if ($fixed_heading_anchor_edit && $editable && $ispage && ! $isfreeze) {
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"';
171 // Normal editing / unfreeze
174 $title = 'Unfreeze %s';
175 $icon = 'unfreeze.png';
180 $title = htmlsc(sprintf($title, $s_page));
181 $icon = '<img src="' . IMAGE_DIR . $icon .
182 '" width="20" height="20" alt="' .
183 $short . '" title="' . $title . '" />';
186 if ($_noicon) $icon = ''; // No more icon
189 $s_label = ''; // No label with an icon
191 $s_label = $short; // Short label without an icon
194 if ($s_label == '') $s_label = $title; // Rich label with an icon
198 $script = get_base_uri();
200 $url = $script . '?cmd=unfreeze&page=' . rawurlencode($s_page);
202 $s_id = ($id == '') ? '' : '&id=' . $id;
203 $url = $script . '?cmd=edit&page=' . rawurlencode($s_page) . $s_id;
205 $atag = '<a' . $class . ' href="' . $url . '" title="' . $title . '">';
206 static $atags = '</a>';
210 return $atag . $icon . $s_label . $atags;
212 // Dangling edit link
213 return '<span class="noexists">' . $atag . $icon . $atags .
214 $s_label . $atag . '?' . $atags . '</span>';
218 // Write, add, or insert new comment
219 function plugin_edit_write()
222 global $_title_collided, $_msg_collided_auto, $_msg_collided, $_title_deleted;
223 global $notimeupdate, $_msg_invalidpass, $do_update_diff_table;
225 $page = isset($vars['page']) ? $vars['page'] : '';
226 $add = isset($vars['add']) ? $vars['add'] : '';
227 $digest = isset($vars['digest']) ? $vars['digest'] : '';
229 ensure_valid_page_name_length($page);
230 $vars['msg'] = preg_replace(PLUGIN_EDIT_FREEZE_REGEX, '', $vars['msg']);
231 $msg = & $vars['msg']; // Reference
235 // Collision Detection
236 $oldpagesrc = join('', get_source($page));
237 $oldpagemd5 = md5($oldpagesrc);
238 if ($digest !== $oldpagemd5) {
239 $vars['digest'] = $oldpagemd5; // Reset
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);
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);
255 if (isset($vars['add_top']) && $vars['add_top']) {
256 $postdata = $msg . "\n\n" . @join('', get_source($page));
258 $postdata = @join('', get_source($page)) . "\n\n" . $msg;
262 $postdata = & $msg; // Reference
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);
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);
282 page_write($page, $postdata, $notimeupdate != 0 && $notimestamp);
284 header('Location: ' . get_page_uri($page, PKWK_URI_ROOT));
288 // Cancel (Back to the page / Escape edit page)
289 function plugin_edit_cancel()
293 header('Location: ' . get_page_uri($vars['page'], PKWK_URI_ROOT));
298 * Setup initial pages
300 function plugin_edit_setup_initial_pages()
302 global $autoalias, $no_autoticketlinkname;
304 // Related: Rename plugin
305 if (exist_plugin('rename') && function_exists('plugin_rename_setup_initial_pages')) {
306 plugin_rename_setup_initial_pages();
308 // AutoTicketLinkName page
309 if (! $no_autoticketlinkname) {
310 init_autoticketlink_def_page();
312 // AutoAliasName page
314 init_autoalias_def_page();