Complex classes like WikiRequest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WikiRequest, and based on these observations, apply Extract Interface, too.
1 | <?php //-*-php-*- |
||
48 | class WikiRequest extends Request { |
||
49 | // var $_dbi; |
||
50 | |||
51 | function WikiRequest () { |
||
52 | $this->_dbi = WikiDB::open($GLOBALS['DBParams']); |
||
53 | // first mysql request costs [958ms]! [670ms] is mysql_connect() |
||
54 | |||
55 | if (in_array('File', $this->_dbi->getAuthParam('USER_AUTH_ORDER'))) { |
||
56 | // force our local copy, until the pear version is fixed. |
||
57 | include_once(dirname(__FILE__)."/pear/File_Passwd.php"); |
||
58 | } |
||
59 | if (ENABLE_USER_NEW) { |
||
60 | // Preload all necessary userclasses. Otherwise session => __PHP_Incomplete_Class_Name |
||
61 | // There's no way to demand-load it later. This way it's much slower, but needs slightly |
||
62 | // less memory than loading all. |
||
63 | if (ALLOW_BOGO_LOGIN) |
||
64 | include_once("lib/WikiUser/BogoLogin.php"); |
||
65 | // UserPreferences POST Update doesn't reach this. |
||
66 | foreach ($GLOBALS['USER_AUTH_ORDER'] as $method) { |
||
67 | include_once("lib/WikiUser/$method.php"); |
||
68 | if ($method == 'Db') |
||
69 | switch( DATABASE_TYPE ) { |
||
70 | case 'SQL' : include_once("lib/WikiUser/PearDb.php"); break; |
||
71 | case 'ADODB': include_once("lib/WikiUser/AdoDb.php"); break; |
||
72 | case 'PDO' : include_once("lib/WikiUser/PdoDb.php"); break; |
||
73 | } |
||
74 | } |
||
75 | unset($method); |
||
76 | } |
||
77 | if (USE_DB_SESSION) { |
||
78 | include_once('lib/DbSession.php'); |
||
79 | $dbi =& $this->_dbi; |
||
80 | $this->_dbsession = new DbSession($dbi, $dbi->getParam('prefix') |
||
81 | . $dbi->getParam('db_session_table')); |
||
82 | } |
||
83 | |||
84 | // Fixme: Does pear reset the error mask to 1? We have to find the culprit |
||
85 | //$x = error_reporting(); |
||
86 | |||
87 | $this->version = phpwiki_version(); |
||
88 | $this->Request(); // [90ms] |
||
89 | |||
90 | // Normalize args... |
||
91 | $this->setArg('pagename', $this->_deducePagename()); |
||
92 | $this->setArg('action', $this->_deduceAction()); |
||
93 | |||
94 | if ((DEBUG & _DEBUG_SQL) or (time() % 50 == 0)) { |
||
95 | if ($this->_dbi->_backend->optimize()) { |
||
|
|||
96 | // Codendi: don't show this message... |
||
97 | //trigger_error(_("Optimizing database"), E_USER_NOTICE); |
||
98 | } |
||
99 | } |
||
100 | |||
101 | // Restore auth state. This doesn't check for proper authorization! |
||
102 | $userid = $this->_deduceUsername(); |
||
103 | if (ENABLE_USER_NEW) { |
||
104 | if (isset($this->_user) and |
||
105 | !empty($this->_user->_authhow) and |
||
106 | $this->_user->_authhow == 'session') |
||
107 | { |
||
108 | // users might switch in a session between the two objects. |
||
109 | // restore old auth level here or in updateAuthAndPrefs? |
||
110 | //$user = $this->getSessionVar('wiki_user'); |
||
111 | // revive db handle, because these don't survive sessions |
||
112 | if (isset($this->_user) and |
||
113 | ( ! isa($this->_user, WikiUserClassname()) |
||
114 | or (strtolower(get_class($this->_user)) == '_passuser'))) |
||
115 | { |
||
116 | $this->_user = WikiUser($userid, $this->_user->_prefs); |
||
117 | } |
||
118 | // revive other db handle |
||
119 | if (isset($this->_user->_prefs->_method) |
||
120 | and ($this->_user->_prefs->_method == 'SQL' |
||
121 | or $this->_user->_prefs->_method == 'ADODB' |
||
122 | or $this->_user->_prefs->_method == 'PDO' |
||
123 | or $this->_user->_prefs->_method == 'HomePage')) { |
||
124 | $this->_user->_HomePagehandle = $this->getPage($userid); |
||
125 | } |
||
126 | // need to update the lockfile filehandle |
||
127 | if ( isa($this->_user, '_FilePassUser') |
||
128 | and $this->_user->_file->lockfile |
||
129 | and !$this->_user->_file->fplock ) |
||
130 | { |
||
131 | //$level = $this->_user->_level; |
||
132 | $this->_user = UpgradeUser($this->_user, |
||
133 | new _FilePassUser($userid, |
||
134 | $this->_user->_prefs, |
||
135 | $this->_user->_file->filename)); |
||
136 | //$this->_user->_level = $level; |
||
137 | } |
||
138 | $this->_prefs = & $this->_user->_prefs; |
||
139 | } else { |
||
140 | $user = WikiUser($userid); |
||
141 | $this->_user = & $user; |
||
142 | $this->_prefs = & $this->_user->_prefs; |
||
143 | } |
||
144 | } else { |
||
145 | $this->_user = new WikiUser($this, $userid); |
||
146 | $this->_prefs = $this->_user->getPreferences(); |
||
147 | } |
||
148 | } |
||
149 | |||
150 | function initializeLang () { |
||
151 | // check non-default pref lang |
||
152 | $_lang = @$this->_prefs->_prefs['lang']; |
||
153 | if (isset($_lang->lang) and $_lang->lang != $GLOBALS['LANG']) { |
||
154 | $user_lang = $_lang->lang; |
||
155 | //check changed LANG and THEME inside a session. |
||
156 | // (e.g. by using another baseurl) |
||
157 | if (isset($this->_user->_authhow) and $this->_user->_authhow == 'session') |
||
158 | $user_lang = $GLOBALS['LANG']; |
||
159 | update_locale($user_lang); |
||
160 | FindLocalizedButtonFile(".",'missing_ok','reinit'); |
||
161 | } |
||
162 | } |
||
163 | |||
164 | function initializeTheme () { |
||
165 | global $WikiTheme; |
||
166 | |||
167 | // Load non-default theme |
||
168 | $_theme = @$this->_prefs->_prefs['theme']; |
||
169 | if ($_theme and isset($_theme->theme)) |
||
170 | $user_theme = $_theme->theme; |
||
171 | else |
||
172 | $user_theme = $this->getPref('theme'); |
||
173 | //check changed LANG and THEME inside a session. |
||
174 | // (e.g. by using another baseurl) |
||
175 | if (isset($this->_user->_authhow) |
||
176 | and $this->_user->_authhow == 'session' |
||
177 | and !isset($_theme->theme) |
||
178 | and defined('THEME') |
||
179 | and $user_theme != THEME) |
||
180 | { |
||
181 | include_once("themes/" . THEME . "/themeinfo.php"); |
||
182 | } |
||
183 | if (empty($WikiTheme) and isset($user_theme)) { |
||
184 | if (strcspn($user_theme,"./\x00]") != strlen($user_theme)) { |
||
185 | trigger_error(sprintf("invalid theme '%s': Invalid characters detected", $user_theme), |
||
186 | E_USER_WARNING); |
||
187 | $user_theme = "default"; |
||
188 | } |
||
189 | include_once("themes/$user_theme/themeinfo.php"); |
||
190 | } |
||
191 | if (empty($WikiTheme) and defined('THEME')) |
||
192 | include_once("themes/" . THEME . "/themeinfo.php"); |
||
193 | if (empty($WikiTheme)) |
||
194 | include_once("themes/default/themeinfo.php"); |
||
195 | assert(!empty($WikiTheme)); |
||
196 | } |
||
197 | |||
198 | // This really maybe should be part of the constructor, but since it |
||
199 | // may involve HTML/template output, the global $request really needs |
||
200 | // to be initialized before we do this stuff. |
||
201 | // [50ms]: 36ms if wikidb_page::exists |
||
202 | function updateAuthAndPrefs () { |
||
203 | |||
204 | if (isset($this->_user) and (!isa($this->_user, WikiUserClassname()))) { |
||
205 | $this->_user = false; |
||
206 | } |
||
207 | // Handle authentication request, if any. |
||
208 | if ($auth_args = $this->getArg('auth')) { |
||
209 | $this->setArg('auth', false); |
||
210 | $this->_handleAuthRequest($auth_args); // possible NORETURN |
||
211 | } |
||
212 | elseif ( ! $this->_user |
||
213 | or (isa($this->_user, WikiUserClassname()) |
||
214 | and ! $this->_user->isSignedIn())) { |
||
215 | // If not auth request, try to sign in as saved user. |
||
216 | if (($saved_user = $this->getPref('userid')) != false) { |
||
217 | $this->_signIn($saved_user); |
||
218 | } |
||
219 | } |
||
220 | |||
221 | $action = $this->getArg('action'); |
||
222 | |||
223 | // Save preferences in session and cookie |
||
224 | if ((defined('WIKI_XMLRPC') and !WIKI_XMLRPC) or $action != 'xmlrpc') { |
||
225 | if (isset($this->_user)) { |
||
226 | if (!isset($this->_user->_authhow) or $this->_user->_authhow != 'session') { |
||
227 | $this->_user->setPreferences($this->_prefs, true); |
||
228 | } |
||
229 | } |
||
230 | $this->setSessionVar('wiki_user', $this->_user); |
||
231 | } |
||
232 | |||
233 | // Ensure user has permissions for action |
||
234 | // HACK ALERT: We may not set the request arg to create, |
||
235 | // since the pageeditor has an ugly logic for action == create. |
||
236 | if ($action == 'edit' or $action == 'create') { |
||
237 | $page = $this->getPage(); |
||
238 | if (! $page->exists() ) |
||
239 | $action = 'create'; |
||
240 | else |
||
241 | $action = 'edit'; |
||
242 | } |
||
243 | if (0) { |
||
244 | $require_level = $this->requiredAuthority($action); |
||
245 | if (! $this->_user->hasAuthority($require_level)) |
||
246 | $this->_notAuthorized($require_level); // NORETURN |
||
247 | } else { |
||
248 | // novatrope patch to let only _AUTHENTICATED view pages. |
||
249 | // If there's not enough authority or forbidden, ask for a password, |
||
250 | // unless it's explicitly unobtainable. Some bad magic though. |
||
251 | if ($this->requiredAuthorityForAction($action) == WIKIAUTH_UNOBTAINABLE) { |
||
252 | $require_level = $this->requiredAuthority($action); |
||
253 | $this->_notAuthorized($require_level); // NORETURN |
||
254 | } |
||
255 | } |
||
256 | } |
||
257 | |||
258 | function & getUser () { |
||
259 | if (isset($this->_user)) |
||
260 | return $this->_user; |
||
261 | else |
||
262 | return $GLOBALS['ForbiddenUser']; |
||
263 | } |
||
264 | |||
265 | function & getGroup () { |
||
266 | if (isset($this->_user) and isset($this->_user->_group)) |
||
267 | return $this->_user->_group; |
||
268 | else { |
||
269 | // Debug Strict: Only variable references should be returned by reference |
||
270 | $this->_user->_group = WikiGroup::getGroup(); |
||
271 | return $this->_user->_group; |
||
272 | } |
||
273 | } |
||
274 | |||
275 | function & getPrefs () { |
||
278 | |||
279 | // Convenience function: |
||
280 | function getPref ($key) { |
||
281 | if (isset($this->_prefs)) { |
||
282 | return $this->_prefs->get($key); |
||
283 | } |
||
284 | } |
||
285 | function & getDbh () { |
||
288 | |||
289 | /** |
||
290 | * Get requested page from the page database. |
||
291 | * By default it will grab the page requested via the URL |
||
292 | * |
||
293 | * This is a convenience function. |
||
294 | * @param string $pagename Name of page to get. |
||
295 | * @return WikiDB_Page Object with methods to pull data from |
||
296 | * database for the page requested. |
||
297 | */ |
||
298 | function getPage ($pagename = false) { |
||
299 | //if (!isset($this->_dbi)) $this->getDbh(); |
||
300 | if (!$pagename) |
||
301 | $pagename = $this->getArg('pagename'); |
||
302 | return $this->_dbi->getPage($pagename); |
||
303 | } |
||
304 | |||
305 | /** Get URL for POST actions. |
||
306 | * |
||
307 | * Officially, we should just use SCRIPT_NAME (or some such), |
||
308 | * but that causes problems when we try to issue a redirect, e.g. |
||
309 | * after saving a page. |
||
310 | * |
||
311 | * Some browsers (at least NS4 and Mozilla 0.97 won't accept |
||
312 | * a redirect from a page to itself.) |
||
313 | * |
||
314 | * So, as a HACK, we include pagename and action as query args in |
||
315 | * the URL. (These should be ignored when we receive the POST |
||
316 | * request.) |
||
317 | */ |
||
318 | function getPostURL ($pagename=false) { |
||
319 | global $HTTP_GET_VARS; |
||
320 | |||
321 | if ($pagename === false) |
||
322 | $pagename = $this->getArg('pagename'); |
||
323 | $action = $this->getArg('action'); |
||
324 | if (!empty($HTTP_GET_VARS['start_debug'])) // zend ide support |
||
325 | return WikiURL($pagename, array('action' => $action, 'start_debug' => 1)); |
||
326 | else |
||
327 | return WikiURL($pagename, array('action' => $action)); |
||
328 | } |
||
329 | |||
330 | function _handleAuthRequest ($auth_args) { |
||
331 | if (!is_array($auth_args)) |
||
332 | return; |
||
333 | |||
334 | // Ignore password unless POST'ed. |
||
335 | if (!$this->isPost()) |
||
336 | unset($auth_args['passwd']); |
||
337 | |||
338 | $olduser = $this->_user; |
||
339 | $user = $this->_user->AuthCheck($auth_args); |
||
340 | if (isa($user, WikiUserClassname())) { |
||
341 | // Successful login (or logout.) |
||
342 | $this->_setUser($user); |
||
343 | } |
||
344 | elseif (is_string($user)) { |
||
345 | // Login attempt failed. |
||
346 | $fail_message = $user; |
||
347 | $auth_args['pass_required'] = true; |
||
348 | // if clicked just on to the "sign in as:" button dont print invalid username. |
||
349 | if (!empty($auth_args['login']) and empty($auth_args['userid'])) |
||
350 | $fail_message = ''; |
||
351 | // If no password was submitted, it's not really |
||
352 | // a failure --- just need to prompt for password... |
||
353 | if (!ALLOW_USER_PASSWORDS |
||
354 | and ALLOW_BOGO_LOGIN |
||
355 | and !isset($auth_args['passwd'])) |
||
356 | { |
||
357 | $fail_message = false; |
||
358 | } |
||
359 | $olduser->PrintLoginForm($this, $auth_args, $fail_message, 'newpage'); |
||
360 | $this->finish(); //NORETURN |
||
361 | } |
||
362 | else { |
||
363 | // Login request cancelled. |
||
364 | } |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Attempt to sign in (bogo-login). |
||
369 | * |
||
370 | * Fails silently. |
||
371 | * |
||
372 | * @param $userid string Userid to attempt to sign in as. |
||
373 | * @access private |
||
374 | */ |
||
375 | function _signIn ($userid) { |
||
376 | if (ENABLE_USER_NEW) { |
||
377 | if (! $this->_user ) |
||
378 | $this->_user = new _BogoUser($userid); |
||
379 | // FIXME: is this always false? shouldn't we try passuser first? |
||
380 | if (! $this->_user ) |
||
381 | $this->_user = new _PassUser($userid); |
||
382 | } |
||
383 | $user = $this->_user->AuthCheck(array('userid' => $userid)); |
||
384 | if (isa($user, WikiUserClassname())) { |
||
385 | $this->_setUser($user); // success! |
||
386 | } |
||
387 | } |
||
388 | |||
389 | // login or logout or restore state |
||
390 | function _setUser (&$user) { |
||
391 | $this->_user =& $user; |
||
392 | if (defined('MAIN_setUser')) return; // don't set cookies twice |
||
393 | $this->setCookieVar('WIKI_ID', $user->getAuthenticatedId(), |
||
394 | COOKIE_EXPIRATION_DAYS, COOKIE_DOMAIN); |
||
395 | if ($user->isSignedIn()) |
||
396 | $user->_authhow = 'signin'; |
||
397 | |||
398 | // Save userid to prefs.. |
||
399 | if ( empty($this->_user->_prefs)) { |
||
400 | $this->_user->_prefs = $this->_user->getPreferences(); |
||
401 | $this->_prefs =& $this->_user->_prefs; |
||
402 | } |
||
403 | $this->_user->_group = $this->getGroup(); |
||
404 | $this->setSessionVar('wiki_user', $user); |
||
405 | $this->_prefs->set('userid', |
||
406 | $user->isSignedIn() ? $user->getId() : ''); |
||
407 | $this->initializeTheme(); |
||
408 | define('MAIN_setUser', true); |
||
409 | } |
||
410 | |||
411 | /* Permission system */ |
||
412 | function getLevelDescription($level) { |
||
428 | |||
429 | function _notAuthorized ($require_level) { |
||
430 | // Display the authority message in the Wiki's default |
||
431 | // language, in case it is not english. |
||
432 | // |
||
433 | // Note that normally a user will not see such an error once |
||
434 | // logged in, unless the admin has altered the default |
||
435 | // disallowed wikiactions. In that case we should probably |
||
436 | // check the user's language prefs too at this point; this |
||
437 | // would be a situation which is not really handled with the |
||
438 | // current code. |
||
439 | if (empty($GLOBALS['LANG'])) |
||
440 | update_locale(DEFAULT_LANGUAGE); |
||
441 | |||
442 | // User does not have required authority. Prompt for login. |
||
443 | $what = $this->getActionDescription($this->getArg('action')); |
||
444 | $pass_required = ($require_level >= WIKIAUTH_USER); |
||
445 | if ($require_level == WIKIAUTH_UNOBTAINABLE) { |
||
446 | global $DisabledActions; |
||
447 | if ($DisabledActions and in_array($action, $DisabledActions)) { |
||
448 | $msg = fmt("%s is disallowed on this wiki.", |
||
449 | $this->getDisallowedActionDescription($this->getArg('action'))); |
||
450 | $this->finish(); |
||
451 | return; |
||
452 | } |
||
453 | // Is the reason a missing ACL or just wrong user or password? |
||
454 | if (class_exists('PagePermission')) { |
||
455 | $user =& $this->_user; |
||
456 | $status = $user->isAuthenticated() ? _("authenticated") : _("not authenticated"); |
||
457 | $msg = fmt("%s %s %s is disallowed on this wiki for %s user '%s' (level: %s).", |
||
458 | _("Missing PagePermission:"), |
||
459 | action2access($this->getArg('action')), |
||
460 | $this->getArg('pagename'), |
||
461 | $status, $user->getId(), $this->getLevelDescription($user->_level)); |
||
462 | // TODO: add link to action=setacl |
||
463 | $user->PrintLoginForm($this, compact('pass_required'), $msg); |
||
464 | $this->finish(); |
||
465 | return; |
||
466 | } else { |
||
467 | $msg = fmt("%s is disallowed on this wiki.", |
||
468 | $this->getDisallowedActionDescription($this->getArg('action'))); |
||
469 | $this->_user->PrintLoginForm($this, compact('require_level','pass_required'), $msg); |
||
470 | $this->finish(); |
||
471 | return; |
||
472 | } |
||
473 | } |
||
474 | elseif ($require_level == WIKIAUTH_BOGO) |
||
475 | $msg = fmt("You must sign in to %s.", $what); |
||
476 | elseif ($require_level == WIKIAUTH_USER) |
||
477 | $msg = fmt("You must log in to %s.", $what); |
||
478 | elseif ($require_level == WIKIAUTH_ANON) |
||
479 | $msg = fmt("Access for you is forbidden to %s.", $what); |
||
480 | else |
||
481 | $msg = fmt("You must be an administrator to %s.", $what); |
||
482 | |||
483 | $this->_user->PrintLoginForm($this, compact('require_level','pass_required'), $msg); |
||
484 | $this->finish(); // NORETURN |
||
485 | } |
||
486 | |||
487 | // Fixme: for PagePermissions we'll need other strings, |
||
488 | // relevant to the requested page, not just for the action on the whole wiki. |
||
489 | function getActionDescription($action) { |
||
490 | static $actionDescriptions; |
||
491 | if (! $actionDescriptions) { |
||
492 | $actionDescriptions |
||
493 | = array('browse' => _("view this page"), |
||
494 | 'diff' => _("diff this page"), |
||
495 | 'dumphtml' => _("dump html pages"), |
||
496 | 'dumpserial' => _("dump serial pages"), |
||
497 | 'edit' => _("edit this page"), |
||
498 | 'revert' => _("revert to a previous version of this page"), |
||
499 | 'create' => _("create this page"), |
||
500 | 'loadfile' => _("load files into this wiki"), |
||
501 | 'lock' => _("lock this page"), |
||
502 | 'remove' => _("remove this page"), |
||
503 | 'unlock' => _("unlock this page"), |
||
504 | 'upload' => _("upload a zip dump"), |
||
505 | 'verify' => _("verify the current action"), |
||
506 | 'viewsource' => _("view the source of this page"), |
||
507 | 'xmlrpc' => _("access this wiki via XML-RPC"), |
||
508 | 'soap' => _("access this wiki via SOAP"), |
||
509 | 'zip' => _("download a zip dump from this wiki"), |
||
510 | 'ziphtml' => _("download an html zip dump from this wiki") |
||
511 | ); |
||
512 | } |
||
513 | if (in_array($action, array_keys($actionDescriptions))) |
||
514 | return $actionDescriptions[$action]; |
||
515 | else |
||
516 | return $action; |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | TODO: check against these cases: |
||
521 | if ($DisabledActions and in_array($action, $DisabledActions)) |
||
522 | return WIKIAUTH_UNOBTAINABLE; |
||
523 | |||
524 | if (ENABLE_PAGEPERM and class_exists("PagePermission")) { |
||
525 | return requiredAuthorityForPage($action); |
||
526 | |||
527 | => Browsing pages is disallowed on this wiki for authenticated user 'rurban' (level: BOGO). |
||
528 | */ |
||
529 | function getDisallowedActionDescription($action) { |
||
530 | static $disallowedActionDescriptions; |
||
531 | |||
532 | if (! $disallowedActionDescriptions) { |
||
533 | $disallowedActionDescriptions |
||
534 | = array('browse' => _("Browsing pages"), |
||
535 | 'diff' => _("Diffing pages"), |
||
536 | 'dumphtml' => _("Dumping html pages"), |
||
537 | 'dumpserial' => _("Dumping serial pages"), |
||
538 | 'edit' => _("Editing pages"), |
||
539 | 'revert' => _("Reverting to a previous version of pages"), |
||
540 | 'create' => _("Creating pages"), |
||
541 | 'loadfile' => _("Loading files"), |
||
542 | 'lock' => _("Locking pages"), |
||
543 | 'remove' => _("Removing pages"), |
||
544 | 'unlock' => _("Unlocking pages"), |
||
545 | 'upload' => _("Uploading zip dumps"), |
||
546 | 'verify' => _("Verify the current action"), |
||
547 | 'viewsource' => _("Viewing the source of pages"), |
||
548 | 'xmlrpc' => _("XML-RPC access"), |
||
549 | 'soap' => _("SOAP access"), |
||
550 | 'zip' => _("Downloading zip dumps"), |
||
551 | 'ziphtml' => _("Downloading html zip dumps") |
||
552 | ); |
||
553 | } |
||
554 | if (in_array($action, array_keys($disallowedActionDescriptions))) |
||
555 | return $disallowedActionDescriptions[$action]; |
||
556 | else |
||
557 | return $action; |
||
558 | } |
||
559 | |||
560 | function requiredAuthority ($action) { |
||
580 | |||
581 | function requiredAuthorityForAction ($action) { |
||
582 | global $DisabledActions; |
||
583 | |||
584 | if ($DisabledActions and in_array($action, $DisabledActions)) |
||
585 | return WIKIAUTH_UNOBTAINABLE; |
||
586 | |||
587 | if (ENABLE_PAGEPERM and class_exists("PagePermission")) { |
||
588 | return requiredAuthorityForPage($action); |
||
589 | } else { |
||
590 | // FIXME: clean up. |
||
591 | switch ($action) { |
||
592 | case 'browse': |
||
593 | case 'viewsource': |
||
594 | case 'diff': |
||
595 | case 'select': |
||
596 | case 'xmlrpc': |
||
597 | case 'search': |
||
598 | case 'pdf': |
||
599 | case 'captcha': |
||
600 | return WIKIAUTH_ANON; |
||
601 | |||
602 | case 'zip': |
||
603 | case 'ziphtml': |
||
604 | if (defined('ZIPDUMP_AUTH') && ZIPDUMP_AUTH) |
||
605 | return WIKIAUTH_ADMIN; |
||
606 | return WIKIAUTH_ANON; |
||
607 | |||
608 | case 'edit': |
||
609 | case 'revert': |
||
610 | case 'soap': |
||
611 | case 'upload': |
||
612 | if (defined('REQUIRE_SIGNIN_BEFORE_EDIT') && REQUIRE_SIGNIN_BEFORE_EDIT) |
||
613 | return WIKIAUTH_BOGO; |
||
614 | return WIKIAUTH_ANON; |
||
615 | // return WIKIAUTH_BOGO; |
||
616 | |||
617 | case 'create': |
||
618 | $page = $this->getPage(); |
||
619 | $current = $page->getCurrentRevision(); |
||
620 | if ($current->hasDefaultContents()) |
||
621 | return $this->requiredAuthorityForAction('edit'); |
||
622 | return $this->requiredAuthorityForAction('browse'); |
||
623 | |||
624 | case 'dumpserial': |
||
625 | case 'dumphtml': |
||
626 | case 'loadfile': |
||
627 | case 'remove': |
||
628 | case 'lock': |
||
629 | case 'unlock': |
||
630 | case 'upgrade': |
||
631 | case 'chown': |
||
632 | case 'setacl': |
||
633 | case 'rename': |
||
634 | return WIKIAUTH_ADMIN; |
||
635 | |||
636 | /* authcheck occurs only in the plugin. |
||
637 | required actionpage RateIt */ |
||
638 | /* |
||
639 | case 'rate': |
||
640 | case 'delete_rating': |
||
641 | // Perhaps this should be WIKIAUTH_USER |
||
642 | return WIKIAUTH_BOGO; |
||
643 | */ |
||
644 | |||
645 | default: |
||
646 | global $WikiNameRegexp; |
||
647 | if (preg_match("/$WikiNameRegexp\Z/A", $action)) |
||
648 | return WIKIAUTH_ANON; // ActionPage. |
||
649 | else |
||
650 | return WIKIAUTH_ADMIN; |
||
651 | } |
||
652 | } |
||
653 | } |
||
654 | /* End of Permission system */ |
||
655 | |||
656 | function possiblyDeflowerVirginWiki () { |
||
671 | |||
672 | // [574ms] mainly template:printexpansion: 393ms and template::expandsubtemplate [100+70+60ms] |
||
673 | function handleAction () { |
||
674 | $action = $this->getArg('action'); |
||
675 | if ($this->isPost() and !$this->_user->isAdmin() and $action != 'browse') { |
||
676 | $page = $this->getPage(); |
||
677 | if ( $page->get('moderation') ) { |
||
678 | require_once("lib/WikiPlugin.php"); |
||
679 | $loader = new WikiPluginLoader(); |
||
680 | $plugin = $loader->getPlugin("ModeratedPage"); |
||
681 | if ($plugin->handler($this, $page)) { |
||
682 | $CONTENT = HTML::div |
||
683 | ( |
||
684 | array('class' => 'wiki-edithelp'), |
||
685 | fmt("%s: action forwarded to a moderator.", |
||
686 | $action), |
||
687 | HTML::br(), |
||
688 | _("This action requires moderator approval. Please be patient.")); |
||
689 | if (!empty($plugin->_tokens['CONTENT'])) |
||
690 | $plugin->_tokens['CONTENT']->pushContent |
||
691 | ( |
||
692 | HTML::br(), |
||
693 | _("You must wait for moderator approval.")); |
||
694 | else |
||
695 | $plugin->_tokens['CONTENT'] = $CONTENT; |
||
696 | require_once("lib/Template.php"); |
||
697 | $title = WikiLink($page->getName()); |
||
698 | $title->pushContent(' : ', WikiLink(_("ModeratedPage"))); |
||
699 | GeneratePage(Template('browse', $plugin->_tokens), |
||
700 | $title, |
||
701 | $page->getCurrentRevision()); |
||
702 | $this->finish(); |
||
703 | } |
||
704 | } |
||
705 | } |
||
706 | $method = "action_$action"; |
||
707 | if (method_exists($this, $method)) { |
||
708 | $this->{$method}(); |
||
709 | } |
||
710 | elseif ($page = $this->findActionPage($action)) { |
||
711 | $this->actionpage($page); |
||
712 | } |
||
713 | else { |
||
714 | $this->finish(fmt("%s: Bad action", $action)); |
||
715 | } |
||
716 | } |
||
717 | |||
718 | function finish ($errormsg = false) { |
||
719 | static $in_exit = 0; |
||
720 | |||
721 | if ($in_exit) |
||
722 | exit(); // just in case CloseDataBase calls us |
||
723 | $in_exit = true; |
||
724 | |||
725 | global $ErrorManager; |
||
726 | $ErrorManager->flushPostponedErrors(); |
||
727 | |||
728 | if (!empty($errormsg)) { |
||
729 | PrintXML(HTML::br(), |
||
730 | HTML::hr(), |
||
731 | HTML::h2(_("Fatal PhpWiki Error")), |
||
732 | $errormsg); |
||
733 | // HACK: |
||
734 | echo "\n</body></html>"; |
||
735 | } |
||
736 | if (is_object($this->_user)) { |
||
737 | $this->_user->page = $this->getArg('pagename'); |
||
738 | $this->_user->action = $this->getArg('action'); |
||
739 | unset($this->_user->_HomePagehandle); |
||
740 | unset($this->_user->_auth_dbi); |
||
741 | } |
||
742 | Request::finish(); |
||
743 | exit; |
||
744 | } |
||
745 | |||
746 | /** |
||
747 | * Generally pagename is rawurlencoded for older browsers or mozilla. |
||
748 | * Typing a pagename into the IE bar will utf-8 encode it, so we have to |
||
749 | * fix that with fixTitleEncoding(). |
||
750 | * If USE_PATH_INFO = true, the pagename is stripped from the "/DATA_PATH/PageName&arg=value" line. |
||
751 | * If false, we support either "/index.php?pagename=PageName&arg=value", |
||
752 | * or the first arg (1.2.x style): "/index.php?PageName&arg=value" |
||
753 | */ |
||
754 | function _deducePagename () { |
||
755 | if (trim(rawurldecode($this->getArg('pagename')))) |
||
756 | return fixTitleEncoding(rawurldecode($this->getArg('pagename'))); |
||
757 | |||
758 | if (USE_PATH_INFO) { |
||
759 | $pathinfo = $this->get('PATH_INFO'); |
||
760 | if (empty($pathinfo)) { // fix for CGI |
||
761 | $path = $this->get('REQUEST_URI'); |
||
762 | $script = $this->get('SCRIPT_NAME'); |
||
763 | $pathinfo = substr($path,strlen($script)); |
||
764 | $pathinfo = preg_replace('/\?.+$/','',$pathinfo); |
||
765 | } |
||
766 | $tail = substr($pathinfo, strlen(PATH_INFO_PREFIX)); |
||
767 | |||
768 | if (trim($tail) != '' and $pathinfo == PATH_INFO_PREFIX . $tail) { |
||
769 | return fixTitleEncoding($tail); |
||
770 | } |
||
771 | } |
||
772 | elseif ($this->isPost()) { |
||
773 | /* |
||
774 | * In general, for security reasons, HTTP_GET_VARS should be ignored |
||
775 | * on POST requests, but we make an exception here (only for pagename). |
||
776 | * |
||
777 | * The justification for this hack is the following |
||
778 | * asymmetry: When POSTing with USE_PATH_INFO set, the |
||
779 | * pagename can (and should) be communicated through the |
||
780 | * request URL via PATH_INFO. When POSTing with |
||
781 | * USE_PATH_INFO off, this cannot be done --- the only way |
||
782 | * to communicate the pagename through the URL is via |
||
783 | * QUERY_ARGS (HTTP_GET_VARS). |
||
784 | */ |
||
785 | global $HTTP_GET_VARS; |
||
786 | if (isset($HTTP_GET_VARS['pagename']) and trim($HTTP_GET_VARS['pagename'])) { |
||
787 | return fixTitleEncoding(rawurldecode($HTTP_GET_VARS['pagename'])); |
||
788 | } |
||
789 | } |
||
790 | |||
791 | /* |
||
792 | * Support for PhpWiki 1.2 style requests. |
||
793 | * Strip off "&" args (?PageName&action=...&start_debug,...) |
||
794 | */ |
||
795 | $query_string = $this->get('QUERY_STRING'); |
||
796 | if (trim(rawurldecode($query_string)) and preg_match('/^([^&=]+)(&.+)?$/', $query_string, $m)) { |
||
797 | return fixTitleEncoding(rawurldecode($m[1])); |
||
798 | } |
||
799 | |||
800 | return fixTitleEncoding(HOME_PAGE); |
||
801 | } |
||
802 | |||
803 | function _deduceAction () { |
||
804 | if (!($action = $this->getArg('action'))) { |
||
805 | // TODO: improve this SOAP.php hack by letting SOAP use index.php |
||
806 | // or any other virtual url as with xmlrpc |
||
807 | if (defined('WIKI_SOAP') and WIKI_SOAP) |
||
808 | return 'soap'; |
||
809 | // Detect XML-RPC requests. |
||
810 | if ($this->isPost() |
||
811 | && $this->get('CONTENT_TYPE') == 'text/xml' |
||
812 | && strstr($GLOBALS['HTTP_RAW_POST_DATA'], '<methodCall>') |
||
813 | ) |
||
814 | { |
||
815 | return 'xmlrpc'; |
||
816 | } |
||
817 | return 'browse'; // Default if no action specified. |
||
818 | } |
||
819 | |||
820 | if (method_exists($this, "action_$action")) |
||
821 | return $action; |
||
822 | |||
823 | // Allow for, e.g. action=LikePages |
||
824 | if ($this->isActionPage($action)) |
||
825 | return $action; |
||
826 | |||
827 | // Handle untranslated actionpages in non-english |
||
828 | // (people playing with switching languages) |
||
829 | if (0 and $GLOBALS['LANG'] != 'en') { |
||
830 | require_once("lib/plugin/_WikiTranslation.php"); |
||
831 | $trans = new WikiPlugin__WikiTranslation(); |
||
832 | $en_action = $trans->translate($action,'en',$GLOBALS['LANG']); |
||
833 | if ($this->isActionPage($en_action)) |
||
834 | return $en_action; |
||
835 | } |
||
836 | |||
837 | trigger_error("$action: Unknown action", E_USER_NOTICE); |
||
838 | return 'browse'; |
||
839 | } |
||
840 | |||
841 | function _deduceUsername() { |
||
842 | global $HTTP_SERVER_VARS, $HTTP_ENV_VARS; |
||
843 | |||
844 | if (!empty($this->args['auth']) and !empty($this->args['auth']['userid'])) |
||
845 | return $this->args['auth']['userid']; |
||
846 | |||
847 | // Codendi specific |
||
848 | return user_getname(); |
||
849 | |||
850 | if ($user = $this->getSessionVar('wiki_user')) { |
||
851 | // switched auth between sessions. |
||
852 | // Note: There's no way to demandload a missing class-definition |
||
853 | // afterwards! (Stupid php) |
||
854 | if (isa($user, WikiUserClassname())) { |
||
855 | $this->_user = $user; |
||
856 | $this->_user->_authhow = 'session'; |
||
857 | return ENABLE_USER_NEW ? $user->UserName() : $this->_user; |
||
858 | } |
||
859 | } |
||
860 | |||
861 | // Sessions override http auth |
||
862 | if (!empty($HTTP_SERVER_VARS['PHP_AUTH_USER'])) |
||
863 | return $HTTP_SERVER_VARS['PHP_AUTH_USER']; |
||
864 | // pubcookie et al |
||
865 | if (!empty($HTTP_SERVER_VARS['REMOTE_USER'])) |
||
866 | return $HTTP_SERVER_VARS['REMOTE_USER']; |
||
867 | if (!empty($HTTP_ENV_VARS['REMOTE_USER'])) |
||
868 | return $HTTP_ENV_VARS['REMOTE_USER']; |
||
869 | |||
870 | if ($userid = $this->getCookieVar('WIKI_ID')) { |
||
871 | if (!empty($userid) and substr($userid,0,2) != 's:') { |
||
872 | $this->_user->authhow = 'cookie'; |
||
873 | return $userid; |
||
874 | } |
||
875 | } |
||
876 | |||
877 | if ($this->getArg('action') == 'xmlrpc') { // how about SOAP? |
||
878 | // wiki.putPage has special otional userid/passwd arguments. check that later. |
||
879 | $userid = ''; |
||
880 | if (isset($HTTP_SERVER_VARS['REMOTE_USER'])) |
||
881 | $userid = $HTTP_SERVER_VARS['REMOTE_USER']; |
||
882 | elseif (isset($HTTP_SERVER_VARS['REMOTE_ADDR'])) |
||
883 | $userid = $HTTP_SERVER_VARS['REMOTE_ADDR']; |
||
884 | elseif (isset($HTTP_ENV_VARS['REMOTE_ADDR'])) |
||
885 | $userid = $HTTP_ENV_VARS['REMOTE_ADDR']; |
||
886 | elseif (isset($GLOBALS['REMOTE_ADDR'])) |
||
887 | $userid = $GLOBALS['REMOTE_ADDR']; |
||
888 | return $userid; |
||
889 | } |
||
890 | |||
891 | return false; |
||
892 | } |
||
893 | |||
894 | function _isActionPage ($pagename) { |
||
906 | |||
907 | function findActionPage ($action) { |
||
908 | static $cache; |
||
909 | |||
910 | // check for translated version, as per users preferred language |
||
911 | // (or system default in case it is not en) |
||
912 | $translation = gettext($action); |
||
913 | |||
914 | if (isset($cache) and isset($cache[$translation])) |
||
915 | return $cache[$translation]; |
||
916 | |||
917 | // check for cached translated version |
||
918 | if ($this->_isActionPage($translation)) |
||
919 | return $cache[$action] = $translation; |
||
920 | |||
921 | // Allow for, e.g. action=LikePages |
||
922 | if (!isWikiWord($action)) |
||
923 | return $cache[$action] = false; |
||
924 | |||
925 | // check for translated version (default language) |
||
926 | global $LANG; |
||
927 | if ($LANG != "en") { |
||
928 | require_once("lib/WikiPlugin.php"); |
||
929 | require_once("lib/plugin/_WikiTranslation.php"); |
||
930 | $trans = new WikiPlugin__WikiTranslation(); |
||
931 | $trans->lang = $LANG; |
||
932 | $default = $trans->translate_to_en($action, $LANG); |
||
933 | if ($this->_isActionPage($default)) |
||
934 | return $cache[$action] = $default; |
||
935 | } else { |
||
936 | $default = $translation; |
||
937 | } |
||
938 | |||
939 | // check for english version |
||
940 | if ($action != $translation and $action != $default) { |
||
941 | if ($this->_isActionPage($action)) |
||
942 | return $cache[$action] = $action; |
||
943 | } |
||
944 | |||
945 | trigger_error("$action: Cannot find action page", E_USER_NOTICE); |
||
946 | return $cache[$action] = false; |
||
947 | } |
||
948 | |||
949 | function isActionPage ($pagename) { |
||
952 | |||
953 | function action_browse () { |
||
954 | $this->buffer_output(); |
||
955 | include_once("lib/display.php"); |
||
956 | displayPage($this); |
||
957 | } |
||
958 | |||
959 | function action_verify () { |
||
962 | |||
963 | function actionpage ($action) { |
||
964 | $this->buffer_output(); |
||
965 | include_once("lib/display.php"); |
||
966 | actionPage($this, $action); |
||
967 | } |
||
968 | |||
969 | function adminActionSubpage ($subpage) { |
||
970 | $page = _("PhpWikiAdministration")."/".$subpage; |
||
971 | $action = $this->findActionPage($page); |
||
972 | if ($action) { |
||
973 | $this->setArg('s',$this->getArg('pagename')); |
||
974 | $this->setArg('verify',1); |
||
975 | $this->setArg('action',$action); |
||
976 | $this->actionpage($action); |
||
977 | } else { |
||
978 | trigger_error($page.": Cannot find action page", E_USER_WARNING); |
||
979 | } |
||
980 | } |
||
981 | |||
982 | function action_chown () { |
||
985 | |||
986 | function action_setacl () { |
||
989 | |||
990 | function action_rename () { |
||
993 | |||
994 | function action_dump () { |
||
995 | $action = $this->findActionPage(_("PageDump")); |
||
996 | if ($action) { |
||
997 | $this->actionpage($action); |
||
998 | } else { |
||
999 | // redirect to action=upgrade if admin? |
||
1000 | trigger_error(_("PageDump").": Cannot find action page", E_USER_WARNING); |
||
1001 | } |
||
1002 | } |
||
1003 | |||
1004 | function action_diff () { |
||
1005 | $this->buffer_output(); |
||
1006 | include_once "lib/diff.php"; |
||
1007 | showDiff($this); |
||
1008 | } |
||
1009 | |||
1010 | function action_search () { |
||
1011 | // This is obsolete: reformulate URL and redirect. |
||
1012 | // FIXME: this whole section should probably be deleted. |
||
1013 | if ($this->getArg('searchtype') == 'full') { |
||
1014 | $search_page = _("FullTextSearch"); |
||
1015 | } |
||
1016 | else { |
||
1017 | $search_page = _("TitleSearch"); |
||
1018 | } |
||
1019 | $this->redirect(WikiURL($search_page, |
||
1020 | array('s' => $this->getArg('searchterm')), |
||
1021 | 'absolute_url')); |
||
1022 | } |
||
1023 | |||
1024 | function action_edit () { |
||
1046 | |||
1047 | function action_create () { |
||
1050 | |||
1051 | function action_viewsource () { |
||
1052 | $this->buffer_output(); |
||
1053 | include "lib/editpage.php"; |
||
1054 | $e = new PageEditor ($this); |
||
1055 | $e->viewSource(); |
||
1056 | } |
||
1057 | |||
1058 | function action_lock () { |
||
1059 | $page = $this->getPage(); |
||
1060 | $page->set('locked', true); |
||
1061 | $this->_dbi->touch(); |
||
1062 | // check ModeratedPage hook |
||
1063 | if ($moderated = $page->get('moderated')) { |
||
1064 | require_once("lib/WikiPlugin.php"); |
||
1065 | $plugin = WikiPluginLoader::getPlugin("ModeratedPage"); |
||
1066 | if ($retval = $plugin->lock_check($this, $page, $moderated)) |
||
1067 | $this->setArg('errormsg', $retval); |
||
1068 | } |
||
1069 | // check if a link to ModeratedPage exists |
||
1070 | elseif ($action_page = $page->existLink(_("ModeratedPage"))) { |
||
1071 | require_once("lib/WikiPlugin.php"); |
||
1072 | $plugin = WikiPluginLoader::getPlugin("ModeratedPage"); |
||
1073 | if ($retval = $plugin->lock_add($this, $page, $action_page)) |
||
1074 | $this->setArg('errormsg', $retval); |
||
1075 | } |
||
1076 | $this->action_browse(); |
||
1077 | } |
||
1078 | |||
1079 | function action_unlock () { |
||
1080 | $page = $this->getPage(); |
||
1081 | $page->set('locked', false); |
||
1082 | $this->_dbi->touch(); |
||
1083 | $this->action_browse(); |
||
1084 | } |
||
1085 | |||
1086 | function action_remove () { |
||
1087 | // This check is now redundant. |
||
1088 | //$user->requireAuth(WIKIAUTH_ADMIN); |
||
1089 | $pagename = $this->getArg('pagename'); |
||
1090 | if (strstr($pagename, _("PhpWikiAdministration"))) { |
||
1091 | $this->action_browse(); |
||
1092 | } else { |
||
1093 | include('lib/removepage.php'); |
||
1094 | RemovePage($this); |
||
1095 | } |
||
1096 | } |
||
1097 | |||
1098 | function action_xmlrpc () { |
||
1099 | include_once("lib/XmlRpcServer.php"); |
||
1100 | $xmlrpc = new XmlRpcServer($this); |
||
1101 | $xmlrpc->service(); |
||
1102 | } |
||
1103 | |||
1104 | function action_revert () { |
||
1108 | |||
1109 | function action_zip () { |
||
1110 | include_once("lib/loadsave.php"); |
||
1111 | MakeWikiZip($this); |
||
1112 | // I don't think it hurts to add cruft at the end of the zip file. |
||
1113 | //echo "\n========================================================\n"; |
||
1114 | //echo "PhpWiki " . PHPWIKI_VERSION . " source:\n$GLOBALS[RCS_IDS]\n"; |
||
1115 | } |
||
1116 | |||
1117 | function action_ziphtml () { |
||
1118 | include_once("lib/loadsave.php"); |
||
1119 | MakeWikiZipHtml($this); |
||
1120 | // I don't think it hurts to add cruft at the end of the zip file. |
||
1121 | echo "\n========================================================\n"; |
||
1122 | echo "PhpWiki " . PHPWIKI_VERSION . " source:\n$GLOBALS[RCS_IDS]\n"; |
||
1123 | } |
||
1124 | |||
1125 | function action_dumpserial () { |
||
1129 | |||
1130 | function action_dumphtml () { |
||
1134 | |||
1135 | function action_upload () { |
||
1139 | |||
1140 | function action_upgrade () { |
||
1141 | include_once("lib/loadsave.php"); |
||
1142 | include_once("lib/upgrade.php"); |
||
1143 | DoUpgrade($this); |
||
1144 | } |
||
1145 | |||
1146 | function action_loadfile () { |
||
1150 | |||
1151 | function action_pdf () { |
||
1155 | |||
1156 | function action_captcha () { |
||
1157 | include_once "lib/Captcha.php"; |
||
1158 | $captcha = new Captcha(); |
||
1159 | $captcha->image ( $captcha->captchaword() ); |
||
1160 | } |
||
1161 | |||
1162 | } |
||
1163 | |||
1164 | //FIXME: deprecated with ENABLE_PAGEPERM (?) |
||
1165 | function is_safe_action ($action) { |
||
1166 | global $request; |
||
1167 | return $request->requiredAuthorityForAction($action) < WIKIAUTH_ADMIN; |
||
1168 | } |
||
1169 | |||
1170 | function validateSessionPath() { |
||
1171 | // Try to defer any session.save_path PHP errors before any html |
||
1172 | // is output, which causes some versions of IE to display a blank |
||
1173 | // page (due to its strict mode while parsing a page?). |
||
1174 | if (! is_writeable(ini_get('session.save_path'))) { |
||
1175 | $tmpdir = (defined('SESSION_SAVE_PATH') and SESSION_SAVE_PATH) ? SESSION_SAVE_PATH : '/tmp'; |
||
1176 | if (!is_writeable($tmpdir)) |
||
1177 | $tmpdir = '/tmp'; |
||
1178 | trigger_error |
||
1179 | (sprintf(_("%s is not writable."), |
||
1180 | _("The session.save_path directory")) |
||
1181 | . "\n" |
||
1182 | . sprintf(_("Please ensure that %s is writable, or redefine %s in config/config.ini."), |
||
1183 | sprintf(_("the session.save_path directory '%s'"), |
||
1184 | ini_get('session.save_path')), |
||
1185 | 'SESSION_SAVE_PATH') |
||
1186 | . "\n" |
||
1187 | . sprintf(_("Attempting to use the directory '%s' instead."), |
||
1188 | $tmpdir) |
||
1189 | , E_USER_NOTICE); |
||
1190 | if (! is_writeable($tmpdir)) { |
||
1191 | trigger_error |
||
1192 | (sprintf(_("%s is not writable."), $tmpdir) |
||
1858 | ?> |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.