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