default_value = $default_value;
}
function sanify ($value) {
return (string) $value;
}
}
class _UserPreference_numeric extends _UserPreference
{
function _UserPreference_numeric ($default, $minval = false, $maxval = false) {
$this->_UserPreference((double) $default);
$this->_minval = (double) $minval;
$this->_maxval = (double) $maxval;
}
function sanify ($value) {
$value = (double) $value;
if ($this->_minval !== false && $value < $this->_minval)
$value = $this->_minval;
if ($this->_maxval !== false && $value > $this->_maxval)
$value = $this->_maxval;
return $value;
}
}
class _UserPreference_int extends _UserPreference_numeric
{
function _UserPreference_int ($default, $minval = false, $maxval = false) {
$this->_UserPreference_numeric((int) $default, (int)$minval, (int)$maxval);
}
function sanify ($value) {
return (int) parent::sanify((int)$value);
}
}
class _UserPreference_bool extends _UserPreference
{
function _UserPreference_bool ($default = false) {
$this->_UserPreference((bool) $default);
}
function sanify ($value) {
if (is_array($value)) {
/* This allows for constructs like:
*
*
*
*
* (If the checkbox is not checked, only the hidden input gets sent.
* If the checkbox is sent, both inputs get sent.)
*/
foreach ($value as $val) {
if ($val)
return true;
}
return false;
}
return (bool) $value;
}
}
$UserPreferences = array('editWidth' => new _UserPreference_int(80, 30, 150),
'editHeight' => new _UserPreference_int(22, 5, 80),
'timeOffset' => new _UserPreference_numeric(0, -26, 26),
'relativeDates' => new _UserPreference_bool(),
'userid' => new _UserPreference(''));
class UserPreferences {
function UserPreferences ($saved_prefs = false) {
$this->_prefs = array();
if (isa($saved_prefs, 'UserPreferences')) {
foreach ($saved_prefs->_prefs as $name => $value)
$this->set($name, $value);
}
}
function _getPref ($name) {
global $UserPreferences;
if (!isset($UserPreferences[$name])) {
trigger_error("$name: unknown preference", E_USER_NOTICE);
return false;
}
return $UserPreferences[$name];
}
function get ($name) {
if (isset($this->_prefs[$name]))
return $this->_prefs[$name];
if (!($pref = $this->_getPref($name)))
return false;
return $pref->default_value;
}
function set ($name, $value) {
if (!($pref = $this->_getPref($name)))
return false;
$this->_prefs[$name] = $pref->sanify($value);
}
}
class WikiRequest extends Request {
function WikiRequest () {
$this->Request();
// Normalize args...
$this->setArg('pagename', $this->_deducePagename());
$this->setArg('action', $this->_deduceAction());
// Restore auth state
$this->_user = new WikiUser($this->getSessionVar('wiki_user'));
// Restore saved preferences
if (!($prefs = $this->getCookieVar('WIKI_PREFS2')))
$prefs = $this->getSessionVar('wiki_prefs');
$this->_prefs = new UserPreferences($prefs);
}
// This really maybe should be part of the constructor, but since it
// may involve HTML/template output, the global $request really needs
// to be initialized before we do this stuff.
function updateAuthAndPrefs () {
// Handle preference updates, an authentication requests, if any.
if ($new_prefs = $this->getArg('pref')) {
$this->setArg('pref', false);
foreach ($new_prefs as $key => $val)
$this->_prefs->set($key, $val);
}
// Handle authentication request, if any.
if ($auth_args = $this->getArg('auth')) {
$this->setArg('auth', false);
$this->_handleAuthRequest($auth_args); // possible NORETURN
}
elseif ( ! $this->_user->isSignedIn() ) {
// If not auth request, try to sign in as saved user.
if (($saved_user = $this->getPref('userid')) != false)
$this->_signIn($saved_user);
}
// Save preferences
$this->setSessionVar('wiki_prefs', $this->_prefs);
$this->setCookieVar('WIKI_PREFS2', $this->_prefs, 365);
// Ensure user has permissions for action
$require_level = $this->requiredAuthority($this->getArg('action'));
if (! $this->_user->hasAuthority($require_level))
$this->_notAuthorized($require_level); // NORETURN
}
function getUser () {
return $this->_user;
}
function getPrefs () {
return $this->_prefs;
}
// Convenience function:
function getPref ($key) {
return $this->_prefs->get($key);
}
function getDbh () {
if (!isset($this->_dbi)) {
$this->_dbi = WikiDB::open($GLOBALS['DBParams']);
}
return $this->_dbi;
}
/**
* Get requested page from the page database.
*
* This is a convenience function.
*/
function getPage () {
if (!isset($this->_dbi))
$this->getDbh();
return $this->_dbi->getPage($this->getArg('pagename'));
}
function _handleAuthRequest ($auth_args) {
if (!is_array($auth_args))
return;
// Ignore password unless POSTed.
if (!$this->isPost())
unset($auth_args['password']);
$user = WikiUser::AuthCheck($auth_args);
if (isa($user, 'WikiUser')) {
// Successful login (or logout.)
$this->_setUser($user);
}
elseif ($user) {
// Login attempt failed.
$fail_message = $user;
// If no password was submitted, it's not really
// a failure --- just need to prompt for password...
if (!isset($auth_args['password']))
$fail_message = false;
WikiUser::PrintLoginForm($this, $auth_args, $fail_message);
$this->finish(); //NORETURN
}
else {
// Login request cancelled.
}
}
/**
* Attempt to sign in (bogo-login).
*
* Fails silently.
*
* @param $userid string Userid to attempt to sign in as.
* @access private
*/
function _signIn ($userid) {
$user = WikiUser::AuthCheck(array('userid' => $userid));
if (isa($user, 'WikiUser'))
$this->_setUser($user); // success!
}
function _setUser ($user) {
$this->_user = $user;
$this->setSessionVar('wiki_user', $user);
// Save userid to prefs..
$this->_prefs->set('userid',
$user->isSignedIn() ? $user->getId() : '');
}
function _notAuthorized ($require_level) {
// User does not have required authority. Prompt for login.
$what = HTML::em($this->getArg('action'));
if ($require_level >= WIKIAUTH_FORBIDDEN) {
$this->finish(fmt("Action %s is disallowed on this wiki", $what));
}
elseif ($require_level == WIKIAUTH_BOGO)
$msg = fmt("You must sign in to %s this wiki", $what);
elseif ($require_level == WIKIAUTH_USER)
$msg = fmt("You must log in to %s this wiki", $what);
else
$msg = fmt("You must be an administrator to %s this wiki", $what);
WikiUser::PrintLoginForm($this, compact('require_level'), $msg);
$this->finish(); // NORETURN
}
function requiredAuthority ($action) {
// FIXME: clean up.
switch ($action) {
case 'browse':
case 'viewsource':
case 'diff':
return WIKIAUTH_ANON;
case 'zip':
if (defined('ZIPDUMP_AUTH') && ZIPDUMP_AUTH)
return WIKIAUTH_ADMIN;
return WIKIAUTH_ANON;
case 'edit':
if (defined('REQUIRE_SIGNIN_BEFORE_EDIT') && REQUIRE_SIGNIN_BEFORE_EDIT)
return WIKIAUTH_BOGO;
return WIKIAUTH_ANON;
// return WIKIAUTH_BOGO;
case 'upload':
case 'dumpserial':
case 'dumphtml':
case 'loadfile':
case 'remove':
case 'lock':
case 'unlock':
return WIKIAUTH_ADMIN;
default:
// Temp workaround for french single-word action page 'Historique'
$singleWordActionPages = array("Historique", "Info");
if (in_array($action, $singleWordActionPages))
return WIKIAUTH_ANON; // ActionPage.
global $WikiNameRegexp;
if (preg_match("/$WikiNameRegexp\Z/A", $action))
return WIKIAUTH_ANON; // ActionPage.
else
return WIKIAUTH_ADMIN;
}
}
function possiblyDeflowerVirginWiki () {
if ($this->getArg('action') != 'browse')
return;
if ($this->getArg('pagename') != HomePage)
return;
$page = $this->getPage();
$current = $page->getCurrentRevision();
if ($current->getVersion() > 0)
return; // Homepage exists.
include('lib/loadsave.php');
SetupWiki($this);
$this->finish(); // NORETURN
}
function handleAction () {
$action = $this->getArg('action');
$method = "action_$action";
if (method_exists($this, $method)) {
$this->{$method}();
}
elseif ($this->isActionPage($action)) {
$this->actionpage($action);
}
else {
$this->finish(fmt("%s: Bad action", $action));
}
}
function finish ($errormsg = false) {
static $in_exit = 0;
if ($in_exit)
exit(); // just in case CloseDataBase calls us
$in_exit = true;
if (!empty($this->_dbi))
$this->_dbi->close();
unset($this->_dbi);
global $ErrorManager;
$ErrorManager->flushPostponedErrors();
if (!empty($errormsg)) {
PrintXML(HTML::br(),
HTML::hr(),
HTML::h2(_("Fatal PhpWiki Error")),
$errormsg);
// HACK:
echo "\n