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