]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/main.php
fixed USE_DB_SESSION = false
[SourceForge/phpwiki.git] / lib / main.php
1 <?php
2 rcs_id('$Id: main.php,v 1.75 2002-09-09 15:35:32 rurban Exp $');
3
4 define ('DEBUG', 1);
5 define ('USE_PREFS_IN_PAGE', true);
6
7 include "lib/config.php";
8 include "lib/stdlib.php";
9 require_once('lib/Request.php');
10 require_once("lib/WikiUser.php");
11 require_once('lib/WikiDB.php');
12
13 if (defined('USE_DB_SESSION') and USE_DB_SESSION and 
14     $DBParams['dbtype']=='SQL' and $DBParams['db_session_table']) {
15     require_once('lib/DB_Session.php');
16 } else {
17     define('USE_DB_SESSION','false');
18 }
19
20 class WikiRequest extends Request {
21
22     function WikiRequest () {
23         $this->Request();
24         if (USE_DB_SESSION) {
25             $dbi = $this->getDbh();
26             new DB_Session($GLOBALS['DBParams']['db_session_table']);
27         }
28         $this->session = new Request_SessionVars;
29
30         // Normalize args...
31         $this->setArg('pagename', $this->_deducePagename());
32         $this->setArg('action', $this->_deduceAction());
33
34         // Restore auth state
35         $this->_user = new WikiUser($this->_deduceUsername());
36         $this->_deduceUsername();
37         // WikiDB Auth later
38         // $this->_user = new WikiDB_User($this->getSessionVar('wiki_user'), $this->getAuthDbh());
39         $this->_prefs = $this->_user->getPreferences();
40     }
41
42     // This really maybe should be part of the constructor, but since it
43     // may involve HTML/template output, the global $request really needs
44     // to be initialized before we do this stuff.
45     function updateAuthAndPrefs () {
46         global $Theme;
47         // Handle preference updates, an authentication requests, if any.
48         if ($new_prefs = $this->getArg('pref')) {
49             $this->setArg('pref', false);
50             if ($this->isPost() and !empty($new_prefs['passwd']) and 
51                 ($new_prefs['passwd2'] != $new_prefs['passwd'])) {
52                 $this->_prefs->set('passwd','');
53                 // $this->_prefs->set('passwd2',''); // This is not stored anyway
54                 include_once("themes/" . THEME . "/themeinfo.php");
55                 return false;
56             }
57             foreach ($new_prefs as $key => $val) {
58                 if ($key == 'passwd') {
59                   $val = crypt('passwd');
60                 }
61                 $this->_prefs->set($key, $val);
62             }
63         }
64
65         // Handle authentication request, if any.
66         if ($auth_args = $this->getArg('auth')) {
67             $this->setArg('auth', false);
68             include_once("themes/" . THEME . "/themeinfo.php");
69             $this->_handleAuthRequest($auth_args); // possible NORETURN
70         }
71         elseif ( ! $this->_user->isSignedIn() ) {
72             // If not auth request, try to sign in as saved user.
73             if (($saved_user = $this->getPref('userid')) != false) {
74                 include_once("themes/" . THEME . "/themeinfo.php");
75                 $this->_signIn($saved_user);
76             }
77         }
78
79         // Save preferences in session and cookie
80         $id_only = true;
81         $this->_user->setPreferences($this->_prefs, $id_only);
82         /*
83         if ($theme = $this->getPref('theme') ) {
84             // Load user-defined theme
85             include_once("themes/$theme/themeinfo.php");
86         } else {
87             // site theme
88             include_once("themes/" . THEME . "/themeinfo.php");
89         }
90         */
91         if (empty($Theme)) {
92             include_once("themes/" . THEME . "/themeinfo.php");
93         }
94         if (empty($Theme)) {
95             include_once("themes/default/themeinfo.php");
96         }
97         assert(!empty($Theme));
98
99         // Ensure user has permissions for action
100         $require_level = $this->requiredAuthority($this->getArg('action'));
101         if (! $this->_user->hasAuthority($require_level))
102             $this->_notAuthorized($require_level); // NORETURN
103     }
104
105     function getUser () {
106         return $this->_user;
107     }
108
109     function getPrefs () {
110         return $this->_prefs;
111     }
112
113     // Convenience function:
114     function getPref ($key) {
115         return $this->_prefs->get($key);
116     }
117
118     function getDbh () {
119         if (!isset($this->_dbi)) {
120             // needs PHP 4.1. better use $this->_user->...
121             $this->_dbi = WikiDB::open($GLOBALS['DBParams']);
122         }
123         return $this->_dbi;
124     }
125
126     function getAuthDbh () {
127         global $DBParams, $DBAuthParams;
128         if (!isset($this->_auth_dbi)) {
129             if ($DBParams['dbtype'] == 'dba' or empty($DBAuthParams['auth_dsn']))
130                 $this->_auth_dbi = $this->getDbh(); // use phpwiki database 
131             elseif ($DBAuthParams['auth_dsn'] == $DBParams['dsn'])
132                 $this->_auth_dbi = $this->getDbh(); // same phpwiki database 
133             else // use external database 
134                 // needs PHP 4.1. better use $this->_user->...
135                 $this->_auth_dbi = WikiDB_User::open($DBAuthParams);
136         }
137         return $this->_auth_dbi;
138     }
139
140     /**
141      * Get requested page from the page database.
142      *
143      * This is a convenience function.
144      */
145     function getPage () {
146         if (!isset($this->_dbi))
147             $this->getDbh();
148         return $this->_dbi->getPage($this->getArg('pagename'));
149     }
150
151     function _handleAuthRequest ($auth_args) {
152         if (!is_array($auth_args))
153             return;
154
155         // Ignore password unless POST'ed.
156         if (!$this->isPost())
157             unset($auth_args['passwd']);
158
159         $user = $this->_user->AuthCheck($auth_args);
160
161         if (isa($user, 'WikiUser')) {
162             // Successful login (or logout.)
163             $this->_setUser($user);
164         }
165         elseif ($user) {
166             // Login attempt failed.
167             $fail_message = $user;
168             $auth_args['pass_required'] = true;
169             // If no password was submitted, it's not really
170             // a failure --- just need to prompt for password...
171             if (!isset($auth_args['passwd'])) {
172                  //$auth_args['pass_required'] = false;
173                  $fail_message = false;
174             }
175             $this->_user->PrintLoginForm($this, $auth_args, $fail_message);
176             $this->finish();    //NORETURN
177         }
178         else {
179             // Login request cancelled.
180         }
181     }
182
183     /**
184      * Attempt to sign in (bogo-login).
185      *
186      * Fails silently.
187      *
188      * @param $userid string Userid to attempt to sign in as.
189      * @access private
190      */
191     function _signIn ($userid) {
192         $user = $this->_user->AuthCheck(array('userid' => $userid));
193         if (isa($user, 'WikiUser')) {
194             $this->_setUser($user); // success!
195         }
196     }
197
198     function _setUser ($user) {
199         $this->_user = $user;
200         $this->setCookieVar('WIKI_ID', $user->_userid, 365);
201         $this->setSessionVar('wiki_user', $user);
202         if ($user->isSignedIn())
203             $user->_authhow = 'signin';
204
205         // Save userid to prefs..
206         $this->_prefs->set('userid',
207                            $user->isSignedIn() ? $user->getId() : '');
208     }
209
210     function _notAuthorized ($require_level) {
211         // User does not have required authority.  Prompt for login.
212         $what = $this->getActionDescription($this->getArg('action'));
213
214         if ($require_level >= WIKIAUTH_FORBIDDEN) {
215             $this->finish(fmt("%s is disallowed on this wiki.",
216                               $this->getDisallowedActionDescription($this->getArg('action'))));
217         }
218         elseif ($require_level == WIKIAUTH_BOGO)
219             $msg = fmt("You must sign in to %s.", $what);
220         elseif ($require_level == WIKIAUTH_USER)
221             $msg = fmt("You must log in to %s.", $what);
222         else
223             $msg = fmt("You must be an administrator to %s.", $what);
224         $pass_required = ($require_level >= WIKIAUTH_USER);
225
226         $this->_user->PrintLoginForm($this, compact('require_level','pass_required'), $msg);
227         $this->finish();    // NORETURN
228     }
229
230     function getActionDescription($action) {
231         static $actionDescriptions;
232         if (! $actionDescriptions) {
233             $actionDescriptions
234             = array('browse'     => _("browse pages in this wiki"),
235                     'diff'       => _("diff pages in this wiki"),
236                     'dumphtml'   => _("dump html pages from this wiki"),
237                     'dumpserial' => _("dump serial pages from this wiki"),
238                     'edit'       => _("edit pages in this wiki"),
239                     'loadfile'   => _("load files into this wiki"),
240                     'lock'       => _("lock pages in this wiki"),
241                     'remove'     => _("remove pages from this wiki"),
242                     'unlock'     => _("unlock pages in this wiki"),
243                     'upload'     => _("upload a zip dump to this wiki"),
244                     'verify'     => _("verify the current action"),
245                     'viewsource' => _("view the source of pages in this wiki"),
246                     'zip'        => _("download a zip dump from this wiki"),
247                     'ziphtml'    => _("download an html zip dump from this wiki")
248                     );
249         }
250         if (in_array($action, array_keys($actionDescriptions)))
251             return $actionDescriptions[$action];
252         else
253             return $action;
254     }
255     function getDisallowedActionDescription($action) {
256         static $disallowedActionDescriptions;
257         if (! $disallowedActionDescriptions) {
258             $disallowedActionDescriptions
259             = array('browse'     => _("Browsing pages"),
260                     'diff'       => _("Diffing pages"),
261                     'dumphtml'   => _("Dumping html pages"),
262                     'dumpserial' => _("Dumping serial pages"),
263                     'edit'       => _("Editing pages"),
264                     'loadfile'   => _("Loading files"),
265                     'lock'       => _("Locking pages"),
266                     'remove'     => _("Removing pages"),
267                     'unlock'     => _("Unlocking pages"),
268                     'upload'     => _("Uploading zip dumps"),
269                     'verify'     => _("Verify the current action"),
270                     'viewsource' => _("Viewing the source of pages"),
271                     'zip'        => _("Downloading zip dumps"),
272                     'ziphtml'    => _("Downloading html zip dumps")
273                     );
274         }
275         if (in_array($action, array_keys($disallowedActionDescriptions)))
276             return $disallowedActionDescriptions[$action];
277         else
278             return $action;
279     }
280
281     function requiredAuthority ($action) {
282         // FIXME: clean up. 
283         // Todo: Check individual page permissions instead.
284         switch ($action) {
285             case 'browse':
286             case 'viewsource':
287             case 'diff':
288             case 'select':
289                 return WIKIAUTH_ANON;
290
291             case 'zip':
292                 if (defined('ZIPDUMP_AUTH') && ZIPDUMP_AUTH)
293                     return WIKIAUTH_ADMIN;
294                 return WIKIAUTH_ANON;
295
296             case 'ziphtml':
297                 if (defined('ZIPDUMP_AUTH') && ZIPDUMP_AUTH)
298                     return WIKIAUTH_ADMIN;
299                 return WIKIAUTH_ANON;
300
301             case 'edit':
302                 if (defined('REQUIRE_SIGNIN_BEFORE_EDIT') && REQUIRE_SIGNIN_BEFORE_EDIT)
303                     return WIKIAUTH_BOGO;
304                 return WIKIAUTH_ANON;
305                 // return WIKIAUTH_BOGO;
306
307             case 'upload':
308             case 'dumpserial':
309             case 'dumphtml':
310             case 'loadfile':
311             case 'remove':
312             case 'lock':
313             case 'unlock':
314                 return WIKIAUTH_ADMIN;
315             default:
316                 // Temp workaround for french single-word action pages 'Historique'
317                 // Some of this make sense as SubPage actions or buttons.
318                 $singleWordActionPages = 
319                     array("Historique", "Info",
320                           _("Preferences"), _("Administration"), 
321                           _("Today"), _("Help"));
322                 if (in_array($action, $singleWordActionPages))
323                     return WIKIAUTH_ANON; // ActionPage.
324                 global $WikiNameRegexp;
325                 if (preg_match("/$WikiNameRegexp\Z/A", $action))
326                     return WIKIAUTH_ANON; // ActionPage.
327                 else
328                     return WIKIAUTH_ADMIN;
329         }
330     }
331
332     function possiblyDeflowerVirginWiki () {
333         if ($this->getArg('action') != 'browse')
334             return;
335         if ($this->getArg('pagename') != HOME_PAGE)
336             return;
337
338         $page = $this->getPage();
339         $current = $page->getCurrentRevision();
340         if ($current->getVersion() > 0)
341             return;             // Homepage exists.
342
343         include('lib/loadsave.php');
344         SetupWiki($this);
345         $this->finish();        // NORETURN
346     }
347
348     function handleAction () {
349         $action = $this->getArg('action');
350         $method = "action_$action";
351         if (method_exists($this, $method)) {
352             $this->{$method}();
353         }
354         elseif ($this->isActionPage($action)) {
355             $this->actionpage($action);
356         }
357         else {
358             $this->finish(fmt("%s: Bad action", $action));
359         }
360     }
361
362
363     function finish ($errormsg = false) {
364         static $in_exit = 0;
365
366         if ($in_exit)
367             exit();        // just in case CloseDataBase calls us
368         $in_exit = true;
369
370         if (!empty($this->_dbi))
371             $this->_dbi->close();
372         unset($this->_dbi);
373
374
375         global $ErrorManager;
376         $ErrorManager->flushPostponedErrors();
377
378         if (!empty($errormsg)) {
379             PrintXML(HTML::br(),
380                      HTML::hr(),
381                      HTML::h2(_("Fatal PhpWiki Error")),
382                      $errormsg);
383             // HACK:
384             echo "\n</body></html>";
385         }
386
387         Request::finish();
388         exit;
389     }
390
391     function _deducePagename () {
392         if ($this->getArg('pagename'))
393             return $this->getArg('pagename');
394
395         if (USE_PATH_INFO) {
396             $pathinfo = $this->get('PATH_INFO');
397             $tail = substr($pathinfo, strlen(PATH_INFO_PREFIX));
398
399             if ($tail && $pathinfo == PATH_INFO_PREFIX . $tail) {
400                 return $tail;
401             }
402         }
403
404         $query_string = $this->get('QUERY_STRING');
405         if (preg_match('/^[^&=]+$/', $query_string)) {
406             return urldecode($query_string);
407         }
408
409         return HOME_PAGE;
410     }
411
412     function _deduceAction () {
413         if (!($action = $this->getArg('action')))
414             return 'browse';
415
416         if (method_exists($this, "action_$action"))
417             return $action;
418
419         // Allow for, e.g. action=LikePages
420         if ($this->isActionPage($action))
421             return $action;
422
423         // Check for _('PhpWikiAdministration').'/'._('Remove') actions
424         $pagename = $this->getArg('pagename');
425         if (strstr($pagename,_('PhpWikiAdministration')))
426             return $action;
427
428         trigger_error("$action: Unknown action", E_USER_NOTICE);
429         return 'browse';
430     }
431
432     function _deduceUsername () {
433         if ($userid = $this->getSessionVar('wiki_user')) {
434             if (!empty($this->_user))
435                 $this->_user->_authhow = 'session';
436             return $userid;
437         }
438         if ($userid = $this->getCookieVar('WIKI_ID')) {
439             if (!empty($this->_user))
440                 $this->_user->authhow = 'cookie';
441             return $userid;
442         }
443         return false;
444     }
445     
446     function isActionPage ($pagename) {
447         if (isSubPage($pagename)) 
448             $subpagename = subPageSlice($pagename,-1); // last element
449         else 
450             $subpagename = $pagename;
451         // Temp workaround for french single-word action page 'Historique'
452         $singleWordActionPages = array("Historique", "Info", _('Preferences'));
453         if (! in_array($subpagename, $singleWordActionPages)) {
454             // Allow for, e.g. action=LikePages
455             global $WikiNameRegexp;
456             if (!preg_match("/$WikiNameRegexp\\Z/A", $subpagename))
457                 return false;
458         }
459         $dbi = $this->getDbh();
460         $page = $dbi->getPage($pagename);
461         $rev = $page->getCurrentRevision();
462         // FIXME: more restrictive check for sane plugin?
463         if (strstr($rev->getPackedContent(), '<?plugin'))
464             return true;
465         trigger_error("$pagename: Does not appear to be an 'action page'", E_USER_NOTICE);
466         return false;
467     }
468
469     function action_browse () {
470         $this->compress_output();
471         include_once("lib/display.php");
472         displayPage($this);
473     }
474
475     function action_verify () {
476         $this->action_browse();
477     }
478
479     function actionpage ($action) {
480         $this->compress_output();
481         include_once("lib/display.php");
482         actionPage($this, $action);
483     }
484
485     function action_diff () {
486         $this->compress_output();
487         include_once "lib/diff.php";
488         showDiff($this);
489     }
490
491     function action_search () {
492         // This is obsolete: reformulate URL and redirect.
493         // FIXME: this whole section should probably be deleted.
494         if ($this->getArg('searchtype') == 'full') {
495             $search_page = _("FullTextSearch");
496         }
497         else {
498             $search_page = _("TitleSearch");
499         }
500         $this->redirect(WikiURL($search_page,
501                                 array('s' => $this->getArg('searchterm')),
502                                 'absolute_url'));
503     }
504
505     function action_edit () {
506         $this->compress_output();
507         include "lib/editpage.php";
508         $e = new PageEditor ($this);
509         $e->editPage();
510     }
511
512     function action_viewsource () {
513         $this->compress_output();
514         include "lib/editpage.php";
515         $e = new PageEditor ($this);
516         $e->viewSource();
517     }
518
519     function action_lock () {
520         $page = $this->getPage();
521         $page->set('locked', true);
522         $this->action_browse();
523     }
524
525     function action_unlock () {
526         // FIXME: This check is redundant.
527         //$user->requireAuth(WIKIAUTH_ADMIN);
528         $page = $this->getPage();
529         $page->set('locked', false);
530         $this->action_browse();
531     }
532
533     function action_remove () {
534         // FIXME: This check is redundant.
535         //$user->requireAuth(WIKIAUTH_ADMIN);
536         $pagename = $this->getArg('pagename');
537         if (strstr($pagename,_('PhpWikiAdministration'))) {
538             $this->action_browse();
539         } else {
540             include('lib/removepage.php');
541             RemovePage($this);
542         }
543     }
544
545
546     function action_upload () {
547         include_once("lib/loadsave.php");
548         LoadPostFile($this);
549     }
550
551     function action_zip () {
552         include_once("lib/loadsave.php");
553         MakeWikiZip($this);
554         // I don't think it hurts to add cruft at the end of the zip file.
555         echo "\n========================================================\n";
556         echo "PhpWiki " . PHPWIKI_VERSION . " source:\n$GLOBALS[RCS_IDS]\n";
557     }
558
559     function action_ziphtml () {
560         include_once("lib/loadsave.php");
561         MakeWikiZipHtml($this);
562         // I don't think it hurts to add cruft at the end of the zip file.
563         echo "\n========================================================\n";
564         echo "PhpWiki " . PHPWIKI_VERSION . " source:\n$GLOBALS[RCS_IDS]\n";
565     }
566
567     function action_dumpserial () {
568         include_once("lib/loadsave.php");
569         DumpToDir($this);
570     }
571
572     function action_dumphtml () {
573         include_once("lib/loadsave.php");
574         DumpHtmlToDir($this);
575     }
576
577     function action_loadfile () {
578         include_once("lib/loadsave.php");
579         LoadFileOrDir($this);
580     }
581 }
582
583 //FIXME: deprecated
584 function is_safe_action ($action) {
585     return WikiRequest::requiredAuthority($action) < WIKIAUTH_ADMIN;
586 }
587
588
589 function main () {
590     global $request;
591
592     $request = new WikiRequest();
593     $request->updateAuthAndPrefs();
594
595     /* FIXME: is this needed anymore?
596         if (USE_PATH_INFO && ! $request->get('PATH_INFO')
597             && ! preg_match(',/$,', $request->get('REDIRECT_URL'))) {
598             $request->redirect(SERVER_URL
599                                . preg_replace('/(\?|$)/', '/\1',
600                                               $request->get('REQUEST_URI'),
601                                               1));
602             exit;
603         }
604     */
605
606     // Enable the output of most of the warning messages.
607     // The warnings will screw up zip files though.
608     global $ErrorManager;
609     if (substr($request->getArg('action'), 0, 3) != 'zip') {
610         $ErrorManager->setPostponedErrorMask(E_NOTICE|E_USER_NOTICE);
611         //$ErrorManager->setPostponedErrorMask(0);
612     }
613
614     //FIXME:
615     //if ($user->is_authenticated())
616     //  $LogEntry->user = $user->getId();
617
618     $request->possiblyDeflowerVirginWiki();
619 if(defined('WIKI_XMLRPC')) return;
620     $request->handleAction();
621 if (defined('DEBUG') and DEBUG>1) phpinfo(INFO_VARIABLES);
622     $request->finish();
623 }
624
625 // Used for debugging purposes
626 function getmicrotime(){
627     list($usec, $sec) = explode(" ", microtime());
628     return ((float)$usec + (float)$sec);
629 }
630 if (defined('DEBUG')) $GLOBALS['debugclock'] = getmicrotime();
631
632 main();
633
634
635 // Local Variables:
636 // mode: php
637 // tab-width: 8
638 // c-basic-offset: 4
639 // c-hanging-comment-ender-p: nil
640 // indent-tabs-mode: nil
641 // End:
642 ?>