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 ($_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 //disable all acl related commands if ACL is disabled 159 if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin', 160 'subscribe','unsubscribe','profile', 161 'resendpwd',))){ 162 msg('Command unavailable: '.htmlspecialchars($act),-1); 163 return 'show'; 164 } 165 166 if(!in_array($act,array('login','logout','register','save','edit','draft', 167 'preview','search','show','check','index','revisions', 168 'diff','recent','backlink','admin','subscribe', 169 'unsubscribe','profile','resendpwd','recover', 170 'draftdel',)) && substr($act,0,7) != 'export_' ) { 171 msg('Command unknown: '.htmlspecialchars($act),-1); 172 return 'show'; 173 } 174 return $act; 175} 176 177/** 178 * Run permissionchecks 179 * 180 * @author Andreas Gohr <andi@splitbrain.org> 181 */ 182function act_permcheck($act){ 183 global $INFO; 184 global $conf; 185 186 if(in_array($act,array('save','preview','edit','recover'))){ 187 if($INFO['exists']){ 188 if($act == 'edit'){ 189 //the edit function will check again and do a source show 190 //when no AUTH_EDIT available 191 $permneed = AUTH_READ; 192 }else{ 193 $permneed = AUTH_EDIT; 194 } 195 }else{ 196 $permneed = AUTH_CREATE; 197 } 198 }elseif(in_array($act,array('login','search','recent','profile'))){ 199 $permneed = AUTH_NONE; 200 }elseif($act == 'register'){ 201 if ($conf['openregister']){ 202 $permneed = AUTH_NONE; 203 }else{ 204 $permneed = AUTH_ADMIN; 205 } 206 }elseif($act == 'resendpwd'){ 207 if ($conf['resendpasswd']) { 208 $permneed = AUTH_NONE; 209 }else{ 210 $permneed = AUTH_ADMIN+1; // shouldn't get here if $conf['resendpasswd'] is off 211 } 212 }elseif($act == 'admin'){ 213 $permneed = AUTH_ADMIN; 214 }else{ 215 $permneed = AUTH_READ; 216 } 217 if($INFO['perm'] >= $permneed) return $act; 218 219 return 'denied'; 220} 221 222/** 223 * Handle 'draftdel' 224 * 225 * Deletes the draft for the current page and user 226 */ 227function act_draftdel($act){ 228 global $INFO; 229 @unlink($INFO['draft']); 230 $INFO['draft'] = null; 231 return 'show'; 232} 233 234/** 235 * Saves a draft on preview 236 * 237 * @todo this currently duplicates code from ajax.php :-/ 238 */ 239function act_draftsave($act){ 240 global $INFO; 241 global $ID; 242 global $conf; 243 if($conf['usedraft'] && $_POST['wikitext']){ 244 $draft = array('id' => $ID, 245 'prefix' => $_POST['prefix'], 246 'text' => $_POST['wikitext'], 247 'suffix' => $_POST['suffix'], 248 'date' => $_POST['date'], 249 'client' => $INFO['client'], 250 ); 251 $cname = getCacheName($draft['client'].$ID,'.draft'); 252 if(io_saveFile($cname,serialize($draft))){ 253 $INFO['draft'] = $cname; 254 } 255 } 256 return $act; 257} 258 259/** 260 * Handle 'save' 261 * 262 * Checks for spam and conflicts and saves the page. 263 * Does a redirect to show the page afterwards or 264 * returns a new action. 265 * 266 * @author Andreas Gohr <andi@splitbrain.org> 267 */ 268function act_save($act){ 269 global $ID; 270 global $DATE; 271 global $PRE; 272 global $TEXT; 273 global $SUF; 274 global $SUM; 275 276 //spam check 277 if(checkwordblock()) 278 return 'wordblock'; 279 //conflict check //FIXME use INFO 280 if($DATE != 0 && @filemtime(wikiFN($ID)) > $DATE ) 281 return 'conflict'; 282 283 //save it 284 saveWikiText($ID,con($PRE,$TEXT,$SUF,1),$SUM,$_REQUEST['minor']); //use pretty mode for con 285 //unlock it 286 unlock($ID); 287 288 //delete draft 289 act_draftdel($act); 290 291 //show it 292 session_write_close(); 293 header("Location: ".wl($ID,'',true)); 294 exit(); 295} 296 297/** 298 * Handle 'login', 'logout' 299 * 300 * @author Andreas Gohr <andi@splitbrain.org> 301 */ 302function act_auth($act){ 303 global $ID; 304 global $INFO; 305 306 //already logged in? 307 if($_SERVER['REMOTE_USER'] && $act=='login') 308 return 'show'; 309 310 //handle logout 311 if($act=='logout'){ 312 $lockedby = checklock($ID); //page still locked? 313 if($lockedby == $_SERVER['REMOTE_USER']) 314 unlock($ID); //try to unlock 315 316 // do the logout stuff 317 auth_logoff(); 318 319 // rebuild info array 320 $INFO = pageinfo(); 321 322 return 'login'; 323 } 324 325 return $act; 326} 327 328/** 329 * Handle 'edit', 'preview' 330 * 331 * @author Andreas Gohr <andi@splitbrain.org> 332 */ 333function act_edit($act){ 334 global $ID; 335 global $INFO; 336 337 //check if locked by anyone - if not lock for my self 338 $lockedby = checklock($ID); 339 if($lockedby) return 'locked'; 340 341 lock($ID); 342 return $act; 343} 344 345/** 346 * Handle 'edit', 'preview' 347 * 348 * @author Andreas Gohr <andi@splitbrain.org> 349 */ 350function act_export($act){ 351 global $ID; 352 global $REV; 353 354 // no renderer for this 355 if($act == 'export_raw'){ 356 header('Content-Type: text/plain; charset=utf-8'); 357 print rawWiki($ID,$REV); 358 exit; 359 } 360 361 // html export #FIXME what about the template's style? 362 if($act == 'export_xhtml'){ 363 global $conf; 364 global $lang; 365 header('Content-Type: text/html; charset=utf-8'); 366 ptln('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'); 367 ptln(' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'); 368 ptln('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"'); 369 ptln(' lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">'); 370 ptln('<head>'); 371 ptln(' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'); 372 ptln(' <title>'.$ID.'</title>'); 373 tpl_metaheaders(); 374 ptln('</head>'); 375 ptln('<body>'); 376 ptln('<div class="dokuwiki export">'); 377 print p_wiki_xhtml($ID,$REV,false); 378 ptln('</div>'); 379 ptln('</body>'); 380 ptln('</html>'); 381 exit; 382 } 383 384 // html body only 385 if($act == 'export_xhtmlbody'){ 386 print p_wiki_xhtml($ID,$REV,false); 387 exit; 388 } 389 390 // try to run renderer #FIXME use cached instructions 391 $mode = substr($act,7); 392 $text = p_render($mode,p_get_instructions(rawWiki($ID,$REV)),$info); 393 if(!is_null($text)){ 394 print $text; 395 exit; 396 } 397 398 399 400 return 'show'; 401} 402 403/** 404 * Handle 'subscribe', 'unsubscribe' 405 * 406 * @author Steven Danz <steven-danz@kc.rr.com> 407 * @todo localize 408 */ 409function act_subscription($act){ 410 global $ID; 411 global $INFO; 412 global $lang; 413 414 $file=metaFN($ID,'.mlist'); 415 if ($act=='subscribe' && !$INFO['subscribed']){ 416 if ($INFO['userinfo']['mail']){ 417 if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) { 418 $INFO['subscribed'] = true; 419 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1); 420 } else { 421 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1); 422 } 423 } else { 424 msg($lang['subscribe_noaddress']); 425 } 426 } elseif ($act=='unsubscribe' && $INFO['subscribed']){ 427 if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) { 428 $INFO['subscribed'] = false; 429 msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1); 430 } else { 431 msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1); 432 } 433 } 434 435 return 'show'; 436} 437 438//Setup VIM: ex: et ts=2 enc=utf-8 : 439