1<?php 2/** 3 * DokuWiki Actions 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); 10 require_once(DOKU_INC.'inc/template.php'); 11 12 13/** 14 * Call the needed action handlers 15 * 16 * @author Andreas Gohr <andi@splitbrain.org> 17 */ 18function act_dispatch(){ 19 global $INFO; 20 global $ACT; 21 global $ID; 22 global $QUERY; 23 global $lang; 24 global $conf; 25 26 // give plugins an opportunity to process the action 27 $evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT); 28 if ($evt->advise_before()) { 29 30 //sanitize $ACT 31 $ACT = act_clean($ACT); 32 33 //check if searchword was given - else just show 34 $s = cleanID($QUERY); 35 if($ACT == 'search' && empty($s)){ 36 $ACT = 'show'; 37 } 38 39 //login stuff 40 if(in_array($ACT,array('login','logout'))) 41 $ACT = act_auth($ACT); 42 43 //check if user is asking to (un)subscribe a page 44 if($ACT == 'subscribe' || $ACT == 'unsubscribe') 45 $ACT = act_subscription($ACT); 46 47 //check permissions 48 $ACT = act_permcheck($ACT); 49 50 //register 51 if($ACT == 'register' && register()){ 52 $ACT = 'login'; 53 } 54 55 if ($ACT == 'resendpwd' && act_resendpwd()) { 56 $ACT = 'login'; 57 } 58 59 //update user profile 60 if (($ACT == 'profile') && updateprofile()) { 61 msg($lang['profchanged'],1); 62 $ACT = 'show'; 63 } 64 65 //save 66 if($ACT == 'save') 67 $ACT = act_save($ACT); 68 69 //draft deletion 70 if($ACT == 'draftdel') 71 $ACT = act_draftdel($ACT); 72 73 //draft saving on preview 74 if($ACT == 'preview') 75 $ACT = act_draftsave($ACT); 76 77 //edit 78 if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){ 79 $ACT = act_edit($ACT); 80 }else{ 81 unlock($ID); //try to unlock 82 } 83 84 //handle export 85 if(substr($ACT,0,7) == 'export_') 86 $ACT = act_export($ACT); 87 88 //display some infos 89 if($ACT == 'check'){ 90 check(); 91 $ACT = 'show'; 92 } 93 94 //handle admin tasks 95 if($ACT == 'admin'){ 96 // retrieve admin plugin name from $_REQUEST['page'] 97 if (!empty($_REQUEST['page'])) { 98 $pluginlist = plugin_list('admin'); 99 if (in_array($_REQUEST['page'], $pluginlist)) { 100 // attempt to load the plugin 101 if ($plugin =& plugin_load('admin',$_REQUEST['page']) !== NULL) 102 $plugin->handle(); 103 } 104 } 105 } 106 107 // check permissions again - the action may have changed 108 $ACT = act_permcheck($ACT); 109 } // end event ACTION_ACT_PREPROCESS default action 110 $evt->advise_after(); 111 unset($evt); 112 113 114 //call template FIXME: all needed vars available? 115 $headers[] = 'Content-Type: text/html; charset=utf-8'; 116 trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders'); 117 118 include(template('main.php')); 119 // output for the commands is now handled in inc/templates.php 120 // in function tpl_content() 121} 122 123function act_sendheaders($headers) { 124 foreach ($headers as $hdr) header($hdr); 125} 126 127/** 128 * Sanitize the action command 129 * 130 * Add all allowed commands here. 131 * 132 * @author Andreas Gohr <andi@splitbrain.org> 133 */ 134function act_clean($act){ 135 global $lang; 136 global $conf; 137 138 // check if the action was given as array key 139 if(is_array($act)){ 140 list($act) = array_keys($act); 141 } 142 143 //handle localized buttons 144 if($act == $lang['btn_save']) $act = 'save'; 145 if($act == $lang['btn_preview']) $act = 'preview'; 146 if($act == $lang['btn_cancel']) $act = 'show'; 147 if($act == $lang['btn_recover']) $act = 'recover'; 148 if($act == $lang['btn_draftdel']) $act = 'draftdel'; 149 150 151 //remove all bad chars 152 $act = strtolower($act); 153 $act = preg_replace('/[^a-z_]+/','',$act); 154 155 if($act == 'export_html') $act = 'export_xhtml'; 156 if($act == 'export_htmlbody') $act = 'export_xhtmlbody'; 157 158 // check if action is disabled 159 if(!actionOK($act)){ 160 msg('Command disabled: '.htmlspecialchars($act),-1); 161 return 'show'; 162 } 163 164 //disable all acl related commands if ACL is disabled 165 if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin', 166 'subscribe','unsubscribe','profile', 167 'resendpwd',))){ 168 msg('Command unavailable: '.htmlspecialchars($act),-1); 169 return 'show'; 170 } 171 172 if(!in_array($act,array('login','logout','register','save','edit','draft', 173 'preview','search','show','check','index','revisions', 174 'diff','recent','backlink','admin','subscribe', 175 'unsubscribe','profile','resendpwd','recover', 176 'draftdel',)) && substr($act,0,7) != 'export_' ) { 177 msg('Command unknown: '.htmlspecialchars($act),-1); 178 return 'show'; 179 } 180 return $act; 181} 182 183/** 184 * Run permissionchecks 185 * 186 * @author Andreas Gohr <andi@splitbrain.org> 187 */ 188function act_permcheck($act){ 189 global $INFO; 190 global $conf; 191 192 if(in_array($act,array('save','preview','edit','recover'))){ 193 if($INFO['exists']){ 194 if($act == 'edit'){ 195 //the edit function will check again and do a source show 196 //when no AUTH_EDIT available 197 $permneed = AUTH_READ; 198 }else{ 199 $permneed = AUTH_EDIT; 200 } 201 }else{ 202 $permneed = AUTH_CREATE; 203 } 204 }elseif(in_array($act,array('login','search','recent','profile'))){ 205 $permneed = AUTH_NONE; 206 }elseif($act == 'register'){ 207 $permneed = AUTH_NONE; 208 }elseif($act == 'resendpwd'){ 209 $permneed = AUTH_NONE; 210 }elseif($act == 'admin'){ 211 $permneed = AUTH_ADMIN; 212 }else{ 213 $permneed = AUTH_READ; 214 } 215 if($INFO['perm'] >= $permneed) return $act; 216 217 return 'denied'; 218} 219 220/** 221 * Handle 'draftdel' 222 * 223 * Deletes the draft for the current page and user 224 */ 225function act_draftdel($act){ 226 global $INFO; 227 @unlink($INFO['draft']); 228 $INFO['draft'] = null; 229 return 'show'; 230} 231 232/** 233 * Saves a draft on preview 234 * 235 * @todo this currently duplicates code from ajax.php :-/ 236 */ 237function act_draftsave($act){ 238 global $INFO; 239 global $ID; 240 global $conf; 241 if($conf['usedraft'] && $_POST['wikitext']){ 242 $draft = array('id' => $ID, 243 'prefix' => $_POST['prefix'], 244 'text' => $_POST['wikitext'], 245 'suffix' => $_POST['suffix'], 246 'date' => $_POST['date'], 247 'client' => $INFO['client'], 248 ); 249 $cname = getCacheName($draft['client'].$ID,'.draft'); 250 if(io_saveFile($cname,serialize($draft))){ 251 $INFO['draft'] = $cname; 252 } 253 } 254 return $act; 255} 256 257/** 258 * Handle 'save' 259 * 260 * Checks for spam and conflicts and saves the page. 261 * Does a redirect to show the page afterwards or 262 * returns a new action. 263 * 264 * @author Andreas Gohr <andi@splitbrain.org> 265 */ 266function act_save($act){ 267 global $ID; 268 global $DATE; 269 global $PRE; 270 global $TEXT; 271 global $SUF; 272 global $SUM; 273 274 //spam check 275 if(checkwordblock()) 276 return 'wordblock'; 277 //conflict check //FIXME use INFO 278 if($DATE != 0 && @filemtime(wikiFN($ID)) > $DATE ) 279 return 'conflict'; 280 281 //save it 282 saveWikiText($ID,con($PRE,$TEXT,$SUF,1),$SUM,$_REQUEST['minor']); //use pretty mode for con 283 //unlock it 284 unlock($ID); 285 286 //delete draft 287 act_draftdel($act); 288 289 //show it 290 session_write_close(); 291 header("Location: ".wl($ID,'',true)); 292 exit(); 293} 294 295/** 296 * Handle 'login', 'logout' 297 * 298 * @author Andreas Gohr <andi@splitbrain.org> 299 */ 300function act_auth($act){ 301 global $ID; 302 global $INFO; 303 304 //already logged in? 305 if($_SERVER['REMOTE_USER'] && $act=='login') 306 return 'show'; 307 308 //handle logout 309 if($act=='logout'){ 310 $lockedby = checklock($ID); //page still locked? 311 if($lockedby == $_SERVER['REMOTE_USER']) 312 unlock($ID); //try to unlock 313 314 // do the logout stuff 315 auth_logoff(); 316 317 // rebuild info array 318 $INFO = pageinfo(); 319 320 return 'login'; 321 } 322 323 return $act; 324} 325 326/** 327 * Handle 'edit', 'preview' 328 * 329 * @author Andreas Gohr <andi@splitbrain.org> 330 */ 331function act_edit($act){ 332 global $ID; 333 global $INFO; 334 335 //check if locked by anyone - if not lock for my self 336 $lockedby = checklock($ID); 337 if($lockedby) return 'locked'; 338 339 lock($ID); 340 return $act; 341} 342 343/** 344 * Handle 'edit', 'preview' 345 * 346 * @author Andreas Gohr <andi@splitbrain.org> 347 */ 348function act_export($act){ 349 global $ID; 350 global $REV; 351 352 // no renderer for this 353 if($act == 'export_raw'){ 354 header('Content-Type: text/plain; charset=utf-8'); 355 print rawWiki($ID,$REV); 356 exit; 357 } 358 359 // html export #FIXME what about the template's style? 360 if($act == 'export_xhtml'){ 361 global $conf; 362 global $lang; 363 header('Content-Type: text/html; charset=utf-8'); 364 ptln('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'); 365 ptln(' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'); 366 ptln('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"'); 367 ptln(' lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">'); 368 ptln('<head>'); 369 ptln(' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'); 370 ptln(' <title>'.$ID.'</title>'); 371 tpl_metaheaders(); 372 ptln('</head>'); 373 ptln('<body>'); 374 ptln('<div class="dokuwiki export">'); 375 print p_wiki_xhtml($ID,$REV,false); 376 ptln('</div>'); 377 ptln('</body>'); 378 ptln('</html>'); 379 exit; 380 } 381 382 // html body only 383 if($act == 'export_xhtmlbody'){ 384 print p_wiki_xhtml($ID,$REV,false); 385 exit; 386 } 387 388 // try to run renderer #FIXME use cached instructions 389 $mode = substr($act,7); 390 $text = p_render($mode,p_get_instructions(rawWiki($ID,$REV)),$info); 391 if(!is_null($text)){ 392 print $text; 393 exit; 394 } 395 396 397 398 return 'show'; 399} 400 401/** 402 * Handle 'subscribe', 'unsubscribe' 403 * 404 * @author Steven Danz <steven-danz@kc.rr.com> 405 * @todo localize 406 */ 407function act_subscription($act){ 408 global $ID; 409 global $INFO; 410 global $lang; 411 412 $file=metaFN($ID,'.mlist'); 413 if ($act=='subscribe' && !$INFO['subscribed']){ 414 if ($INFO['userinfo']['mail']){ 415 if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) { 416 $INFO['subscribed'] = true; 417 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1); 418 } else { 419 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1); 420 } 421 } else { 422 msg($lang['subscribe_noaddress']); 423 } 424 } elseif ($act=='unsubscribe' && $INFO['subscribed']){ 425 if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) { 426 $INFO['subscribed'] = false; 427 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1); 428 } else { 429 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1); 430 } 431 } 432 433 return 'show'; 434} 435 436//Setup VIM: ex: et ts=2 enc=utf-8 : 437