5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Andreas Gohr <andi@splitbrain.org>
9 if(!defined('DOKU_INC')) die('meh.');
10 require_once(DOKU_INC
.'inc/template.php');
14 * Call the needed action handlers
16 * @author Andreas Gohr <andi@splitbrain.org>
17 * @triggers ACTION_ACT_PREPROCESS
18 * @triggers ACTION_HEADERS_SEND
20 function act_dispatch(){
31 // give plugins an opportunity to process the action
32 $evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT);
33 if ($evt->advise_before()) {
36 $ACT = act_clean($ACT);
38 //check if searchword was given - else just show
40 if($ACT == 'search' && empty($s)){
45 if(in_array($ACT,array('login','logout'))){
46 $ACT = act_auth($ACT);
49 //check if user is asking to (un)subscribe a page
50 if($ACT == 'subscribe' ||
$ACT == 'unsubscribe')
51 $ACT = act_subscription($ACT);
53 //check if user is asking to (un)subscribe a namespace
54 if($ACT == 'subscribens' ||
$ACT == 'unsubscribens')
55 $ACT = act_subscriptionns($ACT);
58 $ACT = act_permcheck($ACT);
62 if($ACT == 'register' && $_POST['save'] && register()){
66 if ($ACT == 'resendpwd' && act_resendpwd()) {
71 if ($ACT == 'profile') {
72 if(!$_SERVER['REMOTE_USER']) {
76 msg($lang['profchanged'],1);
84 if(checkSecurityToken()){
85 $ACT = act_revert($ACT);
93 if(checkSecurityToken()){
94 $ACT = act_save($ACT);
100 //cancel conflicting edit
105 if($ACT == 'draftdel')
106 $ACT = act_draftdel($ACT);
108 //draft saving on preview
109 if($ACT == 'preview')
110 $ACT = act_draftsave($ACT);
113 if(($ACT == 'edit' ||
$ACT == 'preview') && $INFO['editable']){
114 $ACT = act_edit($ACT);
116 unlock($ID); //try to unlock
120 if(substr($ACT,0,7) == 'export_')
121 $ACT = act_export($ACT);
131 // retrieve admin plugin name from $_REQUEST['page']
132 if (!empty($_REQUEST['page'])) {
133 $pluginlist = plugin_list('admin');
134 if (in_array($_REQUEST['page'], $pluginlist)) {
135 // attempt to load the plugin
136 if ($plugin =& plugin_load('admin',$_REQUEST['page']) !== NULL)
142 // check permissions again - the action may have changed
143 $ACT = act_permcheck($ACT);
144 } // end event ACTION_ACT_PREPROCESS default action
145 $evt->advise_after();
148 // when action 'show', the intial not 'show' and POST, do a redirect
149 if($ACT == 'show' && $preact != 'show' && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){
150 act_redirect($ID,$preact);
153 //call template FIXME: all needed vars available?
154 $headers[] = 'Content-Type: text/html; charset=utf-8';
155 trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
157 include(template('main.php'));
158 // output for the commands is now handled in inc/templates.php
159 // in function tpl_content()
162 function act_sendheaders($headers) {
163 foreach ($headers as $hdr) header($hdr);
167 * Sanitize the action command
169 * Add all allowed commands here.
171 * @author Andreas Gohr <andi@splitbrain.org>
173 function act_clean($act){
177 // check if the action was given as array key
179 list($act) = array_keys($act);
182 //remove all bad chars
183 $act = strtolower($act);
184 $act = preg_replace('/[^1-9a-z_]+/','',$act);
186 if($act == 'export_html') $act = 'export_xhtml';
187 if($act == 'export_htmlbody') $act = 'export_xhtmlbody';
189 // check if action is disabled
191 msg('Command disabled: '.htmlspecialchars($act),-1);
195 //disable all acl related commands if ACL is disabled
196 if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
197 'subscribe','unsubscribe','profile','revert',
198 'resendpwd','subscribens','unsubscribens',))){
199 msg('Command unavailable: '.htmlspecialchars($act),-1);
203 if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
204 'preview','search','show','check','index','revisions',
205 'diff','recent','backlink','admin','subscribe','revert',
206 'unsubscribe','profile','resendpwd','recover','wordblock',
207 'draftdel','subscribens','unsubscribens',)) && substr($act,0,7) != 'export_' ) {
208 msg('Command unknown: '.htmlspecialchars($act),-1);
215 * Run permissionchecks
217 * @author Andreas Gohr <andi@splitbrain.org>
219 function act_permcheck($act){
223 if(in_array($act,array('save','preview','edit','recover'))){
226 //the edit function will check again and do a source show
227 //when no AUTH_EDIT available
228 $permneed = AUTH_READ
;
230 $permneed = AUTH_EDIT
;
233 $permneed = AUTH_CREATE
;
235 }elseif(in_array($act,array('login','search','recent','profile'))){
236 $permneed = AUTH_NONE
;
237 }elseif($act == 'revert'){
238 $permneed = AUTH_ADMIN
;
239 if($INFO['ismanager']) $permneed = AUTH_EDIT
;
240 }elseif($act == 'register'){
241 $permneed = AUTH_NONE
;
242 }elseif($act == 'resendpwd'){
243 $permneed = AUTH_NONE
;
244 }elseif($act == 'admin'){
245 if($INFO['ismanager']){
246 // if the manager has the needed permissions for a certain admin
247 // action is checked later
248 $permneed = AUTH_READ
;
250 $permneed = AUTH_ADMIN
;
253 $permneed = AUTH_READ
;
255 if($INFO['perm'] >= $permneed) return $act;
263 * Deletes the draft for the current page and user
265 function act_draftdel($act){
267 @unlink
($INFO['draft']);
268 $INFO['draft'] = null;
273 * Saves a draft on preview
275 * @todo this currently duplicates code from ajax.php :-/
277 function act_draftsave($act){
281 if($conf['usedraft'] && $_POST['wikitext']){
282 $draft = array('id' => $ID,
283 'prefix' => $_POST['prefix'],
284 'text' => $_POST['wikitext'],
285 'suffix' => $_POST['suffix'],
286 'date' => $_POST['date'],
287 'client' => $INFO['client'],
289 $cname = getCacheName($draft['client'].$ID,'.draft');
290 if(io_saveFile($cname,serialize($draft))){
291 $INFO['draft'] = $cname;
300 * Checks for spam and conflicts and saves the page.
301 * Does a redirect to show the page afterwards or
302 * returns a new action.
304 * @author Andreas Gohr <andi@splitbrain.org>
306 function act_save($act){
317 //conflict check //FIXME use INFO
318 if($DATE != 0 && @filemtime
(wikiFN($ID)) > $DATE )
322 saveWikiText($ID,con($PRE,$TEXT,$SUF,1),$SUM,$_REQUEST['minor']); //use pretty mode for con
328 session_write_close();
330 // when done, show page
335 * Revert to a certain revision
337 * @author Andreas Gohr <andi@splitbrain.org>
339 function act_revert($act){
344 // when no revision is given, delete current one
345 // FIXME this feature is not exposed in the GUI currently
347 $sum = $lang['deleted'];
349 $text = rawWiki($ID,$REV);
350 if(!$text) return 'show'; //something went wrong
351 $sum = $lang['restored'];
355 if(checkwordblock($Text))
358 saveWikiText($ID,$text,$sum,false);
363 session_write_close();
365 // when done, show current page
366 $_SERVER['REQUEST_METHOD'] = 'post'; //should force a redirect
372 * Do a redirect after receiving post data
374 * Tries to add the section id as hash mark after section editing
376 function act_redirect($id,$preact){
381 //are there any undisplayed messages? keep them in session for display
383 if(isset($MSG) && count($MSG)){
384 //reopen session, store data and close session again
386 $_SESSION[DOKU_COOKIE
]['msg'] = $MSG;
387 session_write_close();
390 //get section name when coming from section edit
391 if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
393 $title = sectionID($match[0],$check);
398 'fragment' => $title,
401 trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
404 function act_redirect_execute($opts){
405 $go = wl($opts['id'],'',true);
406 if($opts['fragment']) $go .= '#'.$opts['fragment'];
413 * Handle 'login', 'logout'
415 * @author Andreas Gohr <andi@splitbrain.org>
417 function act_auth($act){
422 if($_SERVER['REMOTE_USER'] && $act=='login'){
428 $lockedby = checklock($ID); //page still locked?
429 if($lockedby == $_SERVER['REMOTE_USER'])
430 unlock($ID); //try to unlock
432 // do the logout stuff
435 // rebuild info array
438 act_redirect($ID,'login');
445 * Handle 'edit', 'preview'
447 * @author Andreas Gohr <andi@splitbrain.org>
449 function act_edit($act){
453 //check if locked by anyone - if not lock for my self
454 $lockedby = checklock($ID);
455 if($lockedby) return 'locked';
462 * Export a wiki page for various formats
464 * Triggers ACTION_EXPORT_POSTPROCESS
467 * data['id'] -- page id
468 * data['mode'] -- requested export mode
469 * data['headers'] -- export headers
470 * data['output'] -- export output
472 * @author Andreas Gohr <andi@splitbrain.org>
473 * @author Michael Klier <chi@chimeric.de>
475 function act_export($act){
486 // search engines: never cache exported docs! (Google only currently)
487 $headers['X-Robots-Tag'] = 'noindex';
489 $mode = substr($act,7);
492 $headers['Content-Type'] = 'text/plain; charset=utf-8';
493 $headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
494 $output = rawWiki($ID,$REV);
497 $pre .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' . DOKU_LF
;
498 $pre .= ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . DOKU_LF
;
499 $pre .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"' . DOKU_LF
;
500 $pre .= ' lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">' . DOKU_LF
;
501 $pre .= '<head>' . DOKU_LF
;
502 $pre .= ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . DOKU_LF
;
503 $pre .= ' <title>'.$ID.'</title>' . DOKU_LF
;
508 $pre .= ob_get_clean();
510 $pre .= '</head>' . DOKU_LF
;
511 $pre .= '<body>' . DOKU_LF
;
512 $pre .= '<div class="dokuwiki export">' . DOKU_LF
;
515 $pre .= tpl_toc(true);
517 $headers['Content-Type'] = 'text/html; charset=utf-8';
518 $output = p_wiki_xhtml($ID,$REV,false);
520 $post .= '</div>' . DOKU_LF
;
521 $post .= '</body>' . DOKU_LF
;
522 $post .= '</html>' . DOKU_LF
;
525 $headers['Content-Type'] = 'text/html; charset=utf-8';
526 $output = p_wiki_xhtml($ID,$REV,false);
529 $output = p_cached_output(wikiFN($ID,$REV), $mode);
530 $headers = p_get_metadata($ID,"format $mode");
534 // prepare event data
537 $data['mode'] = $mode;
538 $data['headers'] = $headers;
539 $data['output'] =& $output;
541 trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
543 if(!empty($data['output'])){
544 if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
545 header("$key: $val");
547 print $pre.$data['output'].$post;
554 * Handle page 'subscribe', 'unsubscribe'
556 * @author Steven Danz <steven-danz@kc.rr.com>
559 function act_subscription($act){
564 $file=metaFN($ID,'.mlist');
565 if ($act=='subscribe' && !$INFO['subscribed']){
566 if ($INFO['userinfo']['mail']){
567 if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
568 $INFO['subscribed'] = true;
569 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
571 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
574 msg($lang['subscribe_noaddress']);
576 } elseif ($act=='unsubscribe' && $INFO['subscribed']){
577 if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
578 $INFO['subscribed'] = false;
579 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
581 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
589 * Handle namespace 'subscribe', 'unsubscribe'
592 function act_subscriptionns($act){
598 $file = metaFN(getNS($ID),'.mlist');
601 $file = metaFN(getNS($ID),'/.mlist');
605 // reuse strings used to display the status of the subscribe action
606 $act_msg = rtrim($act, 'ns');
608 if ($act=='subscribens' && !$INFO['subscribedns']){
609 if ($INFO['userinfo']['mail']){
610 if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
611 $INFO['subscribedns'] = true;
612 msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
614 msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
617 msg($lang['subscribe_noaddress']);
619 } elseif ($act=='unsubscribens' && $INFO['subscribedns']){
620 if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
621 $INFO['subscribedns'] = false;
622 msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
624 msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
631 //Setup VIM: ex: et ts=2 enc=utf-8 :