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