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();
394 //get section name when coming from section edit
395 if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
396 $check = false; //Byref
397 $opts['fragment'] = sectionID($match[0], $check);
400 trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
403 function act_redirect_execute($opts){
404 $go = wl($opts['id'],'',true);
405 if(isset($opts['fragment'])) $go .= '#'.$opts['fragment'];
412 * Handle 'login', 'logout'
414 * @author Andreas Gohr <andi@splitbrain.org>
416 function act_auth($act){
421 if(isset($_SERVER['REMOTE_USER']) && $act=='login'){
427 $lockedby = checklock($ID); //page still locked?
428 if($lockedby == $_SERVER['REMOTE_USER'])
429 unlock($ID); //try to unlock
431 // do the logout stuff
434 // rebuild info array
437 act_redirect($ID,'login');
444 * Handle 'edit', 'preview'
446 * @author Andreas Gohr <andi@splitbrain.org>
448 function act_edit($act){
452 //check if locked by anyone - if not lock for my self
453 $lockedby = checklock($ID);
454 if($lockedby) return 'locked';
461 * Export a wiki page for various formats
463 * Triggers ACTION_EXPORT_POSTPROCESS
466 * data['id'] -- page id
467 * data['mode'] -- requested export mode
468 * data['headers'] -- export headers
469 * data['output'] -- export output
471 * @author Andreas Gohr <andi@splitbrain.org>
472 * @author Michael Klier <chi@chimeric.de>
474 function act_export($act){
485 // search engines: never cache exported docs! (Google only currently)
486 $headers['X-Robots-Tag'] = 'noindex';
488 $mode = substr($act,7);
491 $headers['Content-Type'] = 'text/plain; charset=utf-8';
492 $headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
493 $output = rawWiki($ID,$REV);
496 $pre .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' . DOKU_LF
;
497 $pre .= ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . DOKU_LF
;
498 $pre .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"' . DOKU_LF
;
499 $pre .= ' lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">' . DOKU_LF
;
500 $pre .= '<head>' . DOKU_LF
;
501 $pre .= ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . DOKU_LF
;
502 $pre .= ' <title>'.$ID.'</title>' . DOKU_LF
;
507 $pre .= ob_get_clean();
509 $pre .= '</head>' . DOKU_LF
;
510 $pre .= '<body>' . DOKU_LF
;
511 $pre .= '<div class="dokuwiki export">' . DOKU_LF
;
514 $pre .= tpl_toc(true);
516 $headers['Content-Type'] = 'text/html; charset=utf-8';
517 $output = p_wiki_xhtml($ID,$REV,false);
519 $post .= '</div>' . DOKU_LF
;
520 $post .= '</body>' . DOKU_LF
;
521 $post .= '</html>' . DOKU_LF
;
524 $headers['Content-Type'] = 'text/html; charset=utf-8';
525 $output = p_wiki_xhtml($ID,$REV,false);
528 $output = p_cached_output(wikiFN($ID,$REV), $mode);
529 $headers = p_get_metadata($ID,"format $mode");
533 // prepare event data
536 $data['mode'] = $mode;
537 $data['headers'] = $headers;
538 $data['output'] =& $output;
540 trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
542 if(!empty($data['output'])){
543 if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
544 header("$key: $val");
546 print $pre.$data['output'].$post;
553 * Handle page 'subscribe', 'unsubscribe'
555 * @author Steven Danz <steven-danz@kc.rr.com>
558 function act_subscription($act){
563 $file=metaFN($ID,'.mlist');
564 if ($act=='subscribe' && !$INFO['subscribed']){
565 if ($INFO['userinfo']['mail']){
566 if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
567 $INFO['subscribed'] = true;
568 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
570 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
573 msg($lang['subscribe_noaddress']);
575 } elseif ($act=='unsubscribe' && $INFO['subscribed']){
576 if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
577 $INFO['subscribed'] = false;
578 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
580 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
588 * Handle namespace 'subscribe', 'unsubscribe'
591 function act_subscriptionns($act){
597 $file = metaFN(getNS($ID),'.mlist');
600 $file = metaFN(getNS($ID),'/.mlist');
604 // reuse strings used to display the status of the subscribe action
605 $act_msg = rtrim($act, 'ns');
607 if ($act=='subscribens' && !$INFO['subscribedns']){
608 if ($INFO['userinfo']['mail']){
609 if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
610 $INFO['subscribedns'] = true;
611 msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
613 msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
616 msg($lang['subscribe_noaddress']);
618 } elseif ($act=='unsubscribens' && $INFO['subscribedns']){
619 if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
620 $INFO['subscribedns'] = false;
621 msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
623 msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
630 //Setup VIM: ex: et ts=2 enc=utf-8 :