From b169f58b8e23ce1ea594008af2a1d6bca7ccacb1 Mon Sep 17 00:00:00 2001 From: rurban Date: Tue, 6 Apr 2004 20:00:11 +0000 Subject: [PATCH] Cleanup of special PageList column types Added support of plugin and theme specific Pagelist Types Added support for theme specific UserPreferences Added session support for ip-based throttling sql table schema change: ALTER TABLE session ADD sess_ip CHAR(15); Enhanced postgres schema Added DB_Session_dba support git-svn-id: svn://svn.code.sf.net/p/phpwiki/code/trunk@3245 96ab9672-09ca-45d6-a79d-3d69d39ca109 --- lib/DbSession.php | 163 ++++++++++++++++++++++++--- lib/DbaDatabase.php | 4 +- lib/PageList.php | 77 ++++++------- lib/Theme.php | 37 +++++- lib/WikiDB/ADODB.php | 12 +- lib/WikiDB/adodb/adodb-mysql.inc.php | 65 +++++++---- lib/WikiDB/adodb/adodb.inc.php | 75 ++++++------ lib/WikiDB/backend/ADODB_mysql.php | 9 +- lib/WikiDB/backend/dba.php | 6 +- lib/WikiPlugin.php | 16 ++- lib/WikiUser.php | 9 +- lib/WikiUserNew.php | 65 ++++++++--- lib/plugin/RateIt.php | 18 ++- lib/plugin/UserPreferences.php | 17 ++- lib/plugin/WikiAdminRename.php | 35 +++++- schemas/mysql.sql | 9 +- schemas/psql.sql | 30 ++++- schemas/sqlite.sql | 18 ++- themes/default/themeinfo.php | 23 +++- themes/wikilens/themeinfo.php | 72 +++++++++++- 20 files changed, 595 insertions(+), 165 deletions(-) diff --git a/lib/DbSession.php b/lib/DbSession.php index 60cca75bc..1edb10809 100644 --- a/lib/DbSession.php +++ b/lib/DbSession.php @@ -1,4 +1,4 @@ -_connected) + if (0 and $this->_connected) $this->_dbh->disconnect(); } @@ -174,6 +174,7 @@ extends DB_Session $dbh = &$this->_connect(); $table = $this->_table; $qid = $dbh->quote($id); + $qip = $dbh->quote($GLOBALS['HTTP_SERVER_VARS']['REMOTE_ADDR']); $time = time(); // postgres can't handle binary data in a TEXT field. @@ -182,13 +183,13 @@ extends DB_Session $qdata = $dbh->quote($sess_data); $res = $dbh->query("UPDATE $table" - . " SET sess_data=$qdata, sess_date=$time" + . " SET sess_data=$qdata, sess_date=$time, sess_ip=$qip" . " WHERE sess_id=$qid"); if ($dbh->affectedRows() == 0) $res = $dbh->query("INSERT INTO $table" - . " (sess_id, sess_data, sess_date)" - . " VALUES ($qid, $qdata, $time)"); + . " (sess_id, sess_data, sess_date, sess_ip)" + . " VALUES ($qid, $qdata, $time, $qip)"); $this->_disconnect(); return ! DB::isError($res); @@ -233,30 +234,32 @@ extends DB_Session } // WhoIsOnline support + // TODO: ip-accesstime dynamic blocking API function currentSessions() { $sessions = array(); $dbh = &$this->_connect(); $table = $this->_table; - $res = $this->query("SELECT sess_data,sess_date FROM $table ORDER BY sess_date DESC"); + $res = $this->query("SELECT sess_data,sess_date,sess_ip FROM $table ORDER BY sess_date DESC"); if (DB::isError($res) || empty($res)) return $sessions; while ($row = $res->fetchRow()) { $data = $row['sess_data']; $date = $row['sess_date']; + $ip = $row['sess_ip']; if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data)) $data = base64_decode($data); // session_data contains the + "|" + // we need just the wiki_user object (might be array as well) $user = strstr($data,"wiki_user|"); $sessions[] = array('wiki_user' => substr($user,10), // from "O:" onwards - 'date' => $date); + 'date' => $date, + 'ip' => $ip); } $this->_disconnect(); return $sessions; } } - // self-written adodb-sessions class DB_Session_ADODB extends DB_Session @@ -302,7 +305,7 @@ extends DB_Session } function _disconnect() { - if (!$this->_dbh) + if (0 and $this->_dbh) $this->_dbh->close(); } @@ -379,6 +382,7 @@ extends DB_Session $dbh = &$this->_connect(); $table = $this->_table; $qid = $dbh->quote($id); + $qip = $dbh->quote($GLOBALS['HTTP_SERVER_VARS']['REMOTE_ADDR']); $time = time(); // postgres can't handle binary data in a TEXT field. @@ -386,14 +390,14 @@ extends DB_Session $sess_data = base64_encode($sess_data); $qdata = $dbh->quote($sess_data); $res = $dbh->query("UPDATE $table" - . " SET sess_data=$qdata, sess_date=$time" + . " SET sess_data=$qdata, sess_date=$time, sess_ip=$qip" . " WHERE sess_id=$qid"); // Warning: This works only only adodb_mysql! // The parent class adodb needs ->AffectedRows() if (!$dbh->_AffectedRows()) $res = $dbh->query("INSERT INTO $table" - . " (sess_id, sess_data, sess_date)" - . " VALUES ($qid, $qdata, $time)"); + . " (sess_id, sess_data, sess_date, sess_ip)" + . " VALUES ($qid, $qdata, $time, $qip)"); $this->_disconnect(); return ! $res->EOF; } @@ -436,32 +440,161 @@ extends DB_Session return true; } - // WhoIsOnline support + // WhoIsOnline support. + // TODO: ip-accesstime dynamic blocking API function currentSessions() { $sessions = array(); $dbh = &$this->_connect(); $table = $this->_table; - $rs = $this->query("SELECT sess_data,sess_date FROM $table ORDER BY sess_date DESC"); + $rs = $this->query("SELECT sess_data,sess_date,sess_ip FROM $table ORDER BY sess_date DESC"); if ($rs->EOF) { return $sessions; } while ($row = $rs->fetchRow()) { $data = $row['sess_data']; $date = $row['sess_date']; + $ip = $row['sess_ip']; if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data)) $data = base64_decode($data); // session_data contains the + "|" + // we need just the wiki_user object (might be array as well) $user = strstr($data,"wiki_user|"); $sessions[] = array('wiki_user' => substr($user,10), // from "O:" onwards - 'date' => $date); + 'date' => $date, + 'ip' => $ip); } $this->_disconnect(); return $sessions; } +} + +/** DBA Sessions + * session: + * Index: session_id + * Values: date : IP : data + */ +class DB_Session_dba +extends DB_Session +{ + var $_backend_type = "dba"; + + function DB_Session_dba ($dbh, $table) { + $this->_dbh = &$dbh; + ini_set('session.save_handler','user'); + session_module_name('user'); // new style + session_set_save_handler(array(&$this, 'open'), + array(&$this, 'close'), + array(&$this, 'read'), + array(&$this, 'write'), + array(&$this, 'destroy'), + array(&$this, 'gc')); + return $this; + } + + function quote($str) { return $str; } + function query($sql) { return false; } + + function _connect() { + global $DBParams; + $dbh = &$this->_dbh; + if (!$dbh) { + $directory = '/tmp'; + $prefix = 'wiki_'; + $dba_handler = 'gdbm'; + $timeout = 20; + extract($DBParams); + $dbfile = "$directory/$prefix" . 'session' . '.' . $dba_handler; + $dbh = new DbaDatabase($dbfile, false, $dba_handler); + $dbh->set_timeout($timeout); + if (!$dbh->open('c')) { + trigger_error(sprintf(_("%s: Can't open dba database"), $dbfile), E_USER_ERROR); + global $request; + $request->finish(fmt("%s: Can't open dba database", $dbfile)); + } + $this->_dbh = &$dbh; + } + return $dbh; + } + + function _disconnect() { + if (0 and isset($this->_dbh)) + $this->_dbh->close(); + } + + function open ($save_path, $session_name) { + $dbh = &$this->_connect(); + $dbh->open(); + } + + function close() { + $dbh = &$this->_connect(); + $dbh->close(); + } + + function read ($id) { + $dbh = &$this->_connect(); + $result = $dbh->get($id); + if (!$result) { + return false; + } + list(,,$packed) = explode(':', $result, 3); + $data = unserialize($packed); + $this->_disconnect(); + return $data; + } + + function write ($id, $sess_data) { + $dbh = &$this->_connect(); + $time = time(); + $ip = $GLOBALS['HTTP_SERVER_VARS']['REMOTE_ADDR']; + $dbh->set($id,$time.':'.$ip.':'.$sess_data); + $this->_disconnect(); + return true; + } + + function destroy ($id) { + $dbh = &$this->_connect(); + $dbh->delete($id); + $this->_disconnect(); + return true; + } + function gc ($maxlifetime) { + $dbh = &$this->_connect(); + $threshold = time() - $maxlifetime; + for ($id = $dbh->firstkey(); $id !== false; $id = $dbh->nextkey()) { + $result = $dbh->get($id); + list($date,,) = explode(':', $result, 3); + //$dbh->query("DELETE FROM $table WHERE sess_date < $threshold"); + if ($date < $threshold) + $dbh->delete($id); + } + $this->_disconnect(); + return true; + } + + // WhoIsOnline support. + // TODO: ip-accesstime dynamic blocking API + function currentSessions() { + $sessions = array(); + $dbh = &$this->_connect(); + for ($id = $dbh->firstkey(); $id !== false; $id = $dbh->nextkey()) { + $result = $dbh->get($id); + list($date,$ip,$packed) = explode(':', $result, 3); + $data = unserialize($packed); + // session_data contains the + "|" + + // we need just the wiki_user object (might be array as well) + $user = strstr($data,"wiki_user|"); + $sessions[] = array('wiki_user' => substr($user,10), // from "O:" onwards + 'date' => $date, + 'ip' => $ip); + } + $this->_disconnect(); + return $sessions; + } } + // Local Variables: // mode: php // tab-width: 8 diff --git a/lib/DbaDatabase.php b/lib/DbaDatabase.php index 94daa5b20..d4c579cbe 100644 --- a/lib/DbaDatabase.php +++ b/lib/DbaDatabase.php @@ -1,4 +1,4 @@ -_file, $mode, $this->_handler)) < 1) { if (--$watchdog <= 0) diff --git a/lib/PageList.php b/lib/PageList.php index f7f6b5986..52debf1c4 100644 --- a/lib/PageList.php +++ b/lib/PageList.php @@ -1,4 +1,4 @@ -getArg('admin_rename'); - $value = str_replace($post_args['from'], $post_args['to'],$page_handle->getName()); - $div = HTML::div(" => ",HTML::input(array('type' => 'text', - 'name' => 'rename[]', - 'value' => $value))); - $new_page = $GLOBALS['request']->getPage($value); - if ($new_page->exists()) { - $div->setAttr('class','error'); - $div->setAttr('title',_("This page already exists")); - } - return $div; - } -}; // Output is hardcoded to limit of first 50 bytes. Otherwise // on very large Wikis this will fail if used with AllPages @@ -395,17 +379,10 @@ class _PageList_Column_acl extends _PageList_Column { } } }; -// TODO: only if RateIt is used -class _PageList_Column_rating extends _PageList_Column { - function _getValue ($page_handle, &$revision_handle) { - static $prefix = 0; - $loader = new WikiPluginLoader(); - $args = "pagename=".$page_handle->_pagename; - $args .= " small=1"; - $args .= " imgPrefix=".$prefix++; - return $loader->expandPi('<'."?plugin RateIt $args ?".'>',$GLOBALS['request'],$page_handle); - } -}; + +// DONE: only if RateIt is used +// class _PageList_Column_rating extends _PageList_Column +// moved to theme/wikilens/themeinfo.php class _PageList_Column_pagename extends _PageList_Column_base { var $_field = 'pagename'; @@ -439,6 +416,11 @@ class PageList { var $_sortby = array(); function PageList ($columns = false, $exclude = false, $options = false) { + // let plugins predefine only certain objects, such its own custom pagelist columns + if (!empty($options) and !empty($options['types'])) { + $this->_types = $options['types']; + unset($options['types']); + } $this->_initAvailableColumns(); $symbolic_columns = array( @@ -674,25 +656,30 @@ class PageList { //////////////////// // private //////////////////// - //Performance Fixme: Initialize only the requested objects + /** Plugin and theme hooks: + * If the pageList is initialized with $options['types'] these types are also initialized, + * overriding the standard types. + */ function _initAvailableColumns() { - if (!empty($this->_types)) - return; - - $this->_types = + global $customPageListColumns; + $standard_types = array( 'content' => new _PageList_Column_content('rev:content', _("Content")), + // new: plugin specific column types initialised by the relevant plugins + /* 'hi_content' // with highlighted search for SearchReplace => new _PageList_Column_content('rev:hi_content', _("Content")), 'remove' => new _PageList_Column_remove('remove', _("Remove")), + // initialised by the plugin 'renamed_pagename' => new _PageList_Column_renamed_pagename('rename', _("Rename to")), 'perm' => new _PageList_Column_perm('perm', _("Permission")), 'acl' => new _PageList_Column_acl('acl', _("ACL")), + */ 'checkbox' => new _PageList_Column_checkbox('p', _("Select")), 'pagename' @@ -723,17 +710,27 @@ class PageList { _("Minor Edit"), _("minor")), 'markup' => new _PageList_Column('rev:markup', _("Markup")), + // 'rating' initialised by the wikilens theme hook: addPageListColumn + /* 'rating' => new _PageList_Column_rating('rating', _("Rate")), + */ ); + if (empty($this->_types)) + $this->_types = array(); + // add plugin specific pageList columns, initialized by $options['types'] + $this->_types = array_merge($standard_types, $this->_types); + // add theme specific pageList columns + if (!empty($customPageListColumns)) + $this->_types = array_merge($this->_types, $customPageListColumns); } function _addColumn ($column) { - - $this->_initAvailableColumns(); - + if (isset($this->_columns_seen[$column])) return false; // Already have this one. + if (!isset($this->_types[$column])) + $this->_initAvailableColumns(); $this->_columns_seen[$column] = true; if (strstr($column, ':')) diff --git a/lib/Theme.php b/lib/Theme.php index aef65a2da..bb03c0431 100644 --- a/lib/Theme.php +++ b/lib/Theme.php @@ -1,4 +1,4 @@ - * * This file is part of PhpWiki. @@ -1023,6 +1023,36 @@ class Theme { } return $out; } + + /** + * Custom UserPreferences: + * A list of name => _UserPreference class pairs. + * Rationale: Certain themes should be able to extend the predefined list + * of preferences. Display/editing is done in the theme specific userprefs.tmpl + * but storage/sanification/update/... must be extended to the Get/SetPreferences methods. + * These values are just ignored if another theme is used. + */ + function customUserPreferences($array) { + global $customUserPreferenceColumns; // FIXME: really a global? + if (empty($customUserPreferenceColumns)) $customUserPreferenceColumns = array(); + //array('wikilens' => new _UserPreference_wikilens()); + foreach ($array as $field => $prefobj) { + $customUserPreferenceColumns[$field] = $prefobj; + } + } + + /** addPageListColumn(array('rating' => new _PageList_Column_rating('rating', _("Rate")))) + * Register custom PageList types for special themes, like + * 'rating' for wikilens + */ + function addPageListColumn ($array) { + global $customPageListColumns; + if (empty($customPageListColumns)) $customPageListColumns = array(); + foreach ($array as $column => $obj) { + $customPageListColumns[$column] = $obj; + } + } + }; @@ -1226,6 +1256,11 @@ class RelatedExternalLinksBox extends SidebarBox { // $Log: not supported by cvs2svn $ +// Revision 1.81 2004/04/01 15:57:10 rurban +// simplified Sidebar theme: table, not absolute css positioning +// added the new box methods. +// remaining problems: large left margin, how to override _autosplitWikiWords in Template only +// // Revision 1.80 2004/03/30 02:14:03 rurban // fixed yet another Prefs bug // added generic PearDb_iter diff --git a/lib/WikiDB/ADODB.php b/lib/WikiDB/ADODB.php index 739af8e3b..76c1c6476 100644 --- a/lib/WikiDB/ADODB.php +++ b/lib/WikiDB/ADODB.php @@ -1,17 +1,21 @@ -metaColumnsSQL) { - global $ADODB_FETCH_MODE; + global $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE; $ADODB_FETCH_MODE = ADODB_FETCH_NUM; @@ -179,7 +185,8 @@ class ADODB_mysql extends ADOConnection { } // parameters use PostgreSQL convention, not MySQL - function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $arg3=false,$secs=0) + function &SelectLimit($sql,$nrows=-1,$offset=-1, + $inputarr=false, $arg3=false,$secs=0) { $offsetStr =($offset>=0) ? "$offset," : ''; @@ -191,7 +198,8 @@ class ADODB_mysql extends ADOConnection { // returns queryID or false function _query($sql,$inputarr) { - global $ADODB_COUNTRECS; + global $ADODB_COUNTRECS; + if($ADODB_COUNTRECS) return mysql_query($sql,$this->_connectionID); else return mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6 } @@ -262,9 +270,9 @@ class ADODB_mysql extends ADOConnection { } -/*-------------------------------------------------------------------------------------- +/*------------------------------------------------------------------------------ Class Name: Recordset ---------------------------------------------------------------------------------------*/ +------------------------------------------------------------------------------*/ class ADORecordSet_mysql extends ADORecordSet{ @@ -297,14 +305,19 @@ class ADORecordSet_mysql extends ADORecordSet{ if ($fieldOffset != -1) { $o = @mysql_fetch_field($this->_queryID, $fieldOffset); $f = @mysql_field_flags($this->_queryID,$fieldOffset); - $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); // suggested by: Jim Nicholson (jnich@att.com) - //$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable + // suggested by: Jim Nicholson (jnich@att.com) + $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); + // mysql returns the max length less spaces -- so it is unrealiable + //$o->max_length = -1; $o->binary = (strpos($f,'binary')!== false); } - else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */ + /* The $fieldOffset argument is not provided thus its -1 */ + else if ($fieldOffset == -1) { $o = @mysql_fetch_field($this->_queryID); - $o->max_length = @mysql_field_len($this->_queryID); // suggested by: Jim Nicholson (jnich@att.com) - //$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable + // suggested by: Jim Nicholson (jnich@att.com) + $o->max_length = @mysql_field_len($this->_queryID); + // mysql returns the max length less spaces -- so it is unrealiable + //$o->max_length = -1; } return $o; @@ -429,4 +442,12 @@ class ADORecordSet_mysql extends ADORecordSet{ } } +// For emacs users +// Local Variables: +// mode: php +// tab-width: 4 +// c-basic-offset: 4 +// c-hanging-comment-ender-p: nil +// indent-tabs-mode: nil +// End: ?> diff --git a/lib/WikiDB/adodb/adodb.inc.php b/lib/WikiDB/adodb/adodb.inc.php index 4402f0de9..331539703 100644 --- a/lib/WikiDB/adodb/adodb.inc.php +++ b/lib/WikiDB/adodb/adodb.inc.php @@ -1,5 +1,4 @@ Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;

'); @@ -42,9 +47,9 @@ */ if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__)); - //============================================================================================== - // GLOBAL VARIABLES - //============================================================================================== +//============================================================================== +// GLOBAL VARIABLES +//============================================================================== GLOBAL $ADODB_vers, // database version @@ -53,9 +58,9 @@ $ADODB_CACHE_DIR, // directory to cache recordsets $ADODB_FETCH_MODE; // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default... - //============================================================================================== - // GLOBAL SETUP - //============================================================================================== +//============================================================================== +// GLOBAL SETUP +//============================================================================== $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT; @@ -67,9 +72,9 @@ die("Illegal \$ADODB_CACHE_DIR"); } - //============================================================================================== - // CHANGE NOTHING BELOW UNLESS YOU ARE CODING - //============================================================================================== +//============================================================================== +// CHANGE NOTHING BELOW UNLESS YOU ARE CODING +//============================================================================== // Initialize random number generator for randomizing cache flushes @@ -92,9 +97,9 @@ */ $ADODB_COUNTRECS = true; - //============================================================================================== - // CLASS ADOFieldObject - //============================================================================================== +//============================================================================== +// CLASS ADOFieldObject +//============================================================================== /** * Helper class for FetchFields -- holds info on a column @@ -115,9 +120,9 @@ } - //============================================================================================== - // CLASS ADOConnection - //============================================================================================== +//============================================================================== +// CLASS ADOConnection +//============================================================================== /** * Connection object. For connecting to databases, and executing queries. @@ -1117,9 +1122,9 @@ - //============================================================================================== - // CLASS ADOFetchObj - //============================================================================================== +//============================================================================== +// CLASS ADOFetchObj +//============================================================================== /** * Internal placeholder for record objects. Used by ADORecordSet->FetchObj(). @@ -1127,9 +1132,9 @@ class ADOFetchObj { }; - //============================================================================================== - // CLASS ADORecordSet_empty - //============================================================================================== +//============================================================================== +// CLASS ADORecordSet_empty +//============================================================================== /** * Lightweight recordset when there are no records to be returned @@ -1146,9 +1151,9 @@ function Close(){return true;} } - //============================================================================================== - // CLASS ADORecordSet - //============================================================================================== +//============================================================================== +// CLASS ADORecordSet +//============================================================================== /** * RecordSet class that represents the dataset returned by the database. @@ -1884,9 +1889,9 @@ } } // end class ADORecordSet - //============================================================================================== - // CLASS ADORecordSet_array - //============================================================================================== +//============================================================================== +// CLASS ADORecordSet_array +//============================================================================== /** * This class encapsulates the concept of a recordset created in memory @@ -2022,9 +2027,9 @@ } // ADORecordSet_array - //============================================================================================== - // HELPER FUNCTIONS - //============================================================================================== +//============================================================================== +// HELPER FUNCTIONS +//============================================================================== /** * Synonym for ADOLoadCode. diff --git a/lib/WikiDB/backend/ADODB_mysql.php b/lib/WikiDB/backend/ADODB_mysql.php index 6e89d9a8a..9ef74a1b8 100644 --- a/lib/WikiDB/backend/ADODB_mysql.php +++ b/lib/WikiDB/backend/ADODB_mysql.php @@ -1,8 +1,15 @@ _pi); return HTML::div(array('class' => 'disabled-plugin'), $html); } + + // TODO: Not really needed, since our plugins generally initialize their own + // PageList object, which accepts options['types']. + // Register custom PageList types for special plugins, like + // 'hi_content' for WikiAdminSearcheplace, 'renamed_pagename' for WikiAdminRename, ... + function addPageListColumn ($array) { + global $customPageListColumns; + if (empty($customPageListColumns)) $customPageListColumns = array(); + foreach ($array as $column => $obj) { + $customPageListColumns[$column] = $obj; + } + } } class WikiPluginLoader { diff --git a/lib/WikiUser.php b/lib/WikiUser.php index 3fd23c53d..1bdc0cb1a 100644 --- a/lib/WikiUser.php +++ b/lib/WikiUser.php @@ -1,5 +1,5 @@ homepage()); + } + // create user by checking his homepage function createUser ($pref, $createDefaultHomepage = true) { if ($this->exists()) @@ -717,6 +721,9 @@ class UserPreferences { } // $Log: not supported by cvs2svn $ +// Revision 1.50 2004/02/26 01:32:03 rurban +// fixed session login with old WikiUser object. strangely, the errormask gets corruoted to 1, Pear??? +// // Revision 1.49 2004/02/15 21:34:37 rurban // PageList enhanced and improved. // fixed new WikiAdmin... plugins diff --git a/lib/WikiUserNew.php b/lib/WikiUserNew.php index da1a79b36..3a7b89cc2 100644 --- a/lib/WikiUserNew.php +++ b/lib/WikiUserNew.php @@ -1,5 +1,5 @@ /themeinfo.php must provide CustomUserPreferences: + * A list of name => _UserPreference class pairs. */ define('WIKIAUTH_FORBIDDEN', -1); // Completely not allowed. @@ -643,21 +653,25 @@ extends _WikiUser $packed = $prefs->store(); $unpacked = $prefs->unpack($packed); if (count($unpacked)) { - global $request; foreach (array('_method','_select','_update') as $param) { if (!empty($this->_prefs->{$param})) $prefs->{$param} = $this->_prefs->{$param}; } $this->_prefs = $prefs; - $request->_prefs =& $this->_prefs; - $request->_user->_prefs =& $this->_prefs; - if (isset($request->_user->_auth_dbi)) { - $user = $request->_user; - unset($user->_auth_dbi); - $request->setSessionVar('wiki_user', $user); - } else { - //$request->setSessionVar('wiki_prefs', $this->_prefs); - $request->setSessionVar('wiki_user', $request->_user); + //FIXME! The following must be done in $request->_setUser(), not here, + // to be able to iterate over multiple users, without tampering the current user. + if (0) { + global $request; + $request->_prefs =& $this->_prefs; + $request->_user->_prefs =& $this->_prefs; + if (isset($request->_user->_auth_dbi)) { + $user = $request->_user; + unset($user->_auth_dbi); + $request->setSessionVar('wiki_user', $user); + } else { + //$request->setSessionVar('wiki_prefs', $this->_prefs); + $request->setSessionVar('wiki_user', $request->_user); + } } } return $updated; @@ -1387,6 +1401,7 @@ extends _DbPassUser * @tables: pref */ { + var $_authmethod = 'PearDb'; function _PearDbPassUser($UserName='',$prefs=false) { global $DBAuthParams; if (!$this->_prefs and isa($this,"_PearDbPassUser")) { @@ -1432,9 +1447,10 @@ extends _DbPassUser function setPreferences($prefs, $id_only=false) { // if the prefs are changed if (_AnonUser::setPreferences($prefs, 1)) { - global $request; - $user = $request->_user; + //global $request; + //$user = $request->_user; //unset($user->_auth_dbi); + // this must be done in $request->_setUser, not here! //$request->setSessionVar('wiki_user', $user); $this->getAuthDbh(); $packed = $this->_prefs->store(); @@ -1572,6 +1588,7 @@ extends _DbPassUser * @tables: user */ { + var $_authmethod = 'AdoDb'; function _AdoDbPassUser($UserName='',$prefs=false) { if (!$this->_prefs and isa($this,"_AdoDbPassUser")) { if ($prefs) $this->_prefs = $prefs; @@ -1619,8 +1636,8 @@ extends _DbPassUser if (_AnonUser::setPreferences($prefs, 1)) { global $request; $packed = $this->_prefs->store(); - $user = $request->_user; - unset($user->_auth_dbi); + //$user = $request->_user; + //unset($user->_auth_dbi); if (!$id_only and isset($this->_prefs->_update)) { $this->getAuthDbh(); $dbh = &$this->_auth_dbi; @@ -1975,6 +1992,7 @@ extends _PassUser } function userExists() { + $this->_authmethod = 'File'; if (isset($this->_file->users[$this->_userid])) return true; @@ -2405,6 +2423,12 @@ class UserPreferences TIMEOFFSET_MAX_HOURS), 'relativeDates' => new _UserPreference_bool() ); + // add custom theme-specific pref types: + // FIXME: on theme changes the wiki_user session pref object will fail. + // We will silently ignore this. + if (!empty($customUserPreferenceColumns)) + $this->_prefs = array_merge($this->_prefs,$customUserPreferenceColumns); + if (isset($this->_method) and $this->_method == 'SQL') { //unset($this->_prefs['userid']); unset($this->_prefs['passwd']); @@ -2663,6 +2687,13 @@ extends UserPreferences // $Log: not supported by cvs2svn $ +// Revision 1.47 2004/04/02 15:06:55 rurban +// fixed a nasty ADODB_mysql session update bug +// improved UserPreferences layout (tabled hints) +// fixed UserPreferences auth handling +// improved auth stability +// improved old cookie handling: fixed deletion of old cookies with paths +// // Revision 1.46 2004/04/01 06:29:51 rurban // better wording // RateIt also for ADODB diff --git a/lib/plugin/RateIt.php b/lib/plugin/RateIt.php index c7c434d97..75cdcc869 100644 --- a/lib/plugin/RateIt.php +++ b/lib/plugin/RateIt.php @@ -1,5 +1,5 @@ to enable rating on this page * Note: The wikilens theme must be enabled, to enable this plugin! * Or use a sidebar based theme with the box method. @@ -99,7 +109,7 @@ extends WikiPlugin } function getVersion() { return preg_replace("/[Revision: $]/", '', - "\$Revision: 1.3 $"); + "\$Revision: 1.4 $"); } function RatingWidgetJavascript() { @@ -736,6 +746,10 @@ function deleteRating(actionImg, page, dimension) { // $Log: not supported by cvs2svn $ +// Revision 1.3 2004/04/01 06:29:51 rurban +// better wording +// RateIt also for ADODB +// // Revision 1.2 2004/03/31 06:22:22 rurban // shorter javascript, // added prediction buttons and display logic, diff --git a/lib/plugin/UserPreferences.php b/lib/plugin/UserPreferences.php index 7e9ea0910..0824b7777 100644 --- a/lib/plugin/UserPreferences.php +++ b/lib/plugin/UserPreferences.php @@ -1,5 +1,5 @@ UserName(); if (// ((defined('ALLOW_BOGO_LOGIN') && ALLOW_BOGO_LOGIN && $user->isSignedIn()) || - $user->isAuthenticated() and !empty($userid)) + $user->isAuthenticated() and !empty($userid)) { $pref = $user->getPreferences(); //trigger_error("DEBUG: reading prefs from getPreferences".print_r($pref)); @@ -113,6 +116,7 @@ extends WikiPlugin if (!$num) { $errmsg .= " " ._("No changes."); } else { + $request->_setUser($user); $pref = $user->_prefs; $errmsg .= sprintf(_("%d UserPreferences fields successfully updated."), $num); } @@ -166,6 +170,13 @@ extends WikiPlugin }; // $Log: not supported by cvs2svn $ +// Revision 1.23 2004/04/02 15:06:56 rurban +// fixed a nasty ADODB_mysql session update bug +// improved UserPreferences layout (tabled hints) +// fixed UserPreferences auth handling +// improved auth stability +// improved old cookie handling: fixed deletion of old cookies with paths +// // Revision 1.22 2004/03/24 19:39:03 rurban // php5 workaround code (plus some interim debugging code in XmlElement) // php5 doesn't work yet with the current XmlElement class constructors, diff --git a/lib/plugin/WikiAdminRename.php b/lib/plugin/WikiAdminRename.php index 1864648be..946408176 100644 --- a/lib/plugin/WikiAdminRename.php +++ b/lib/plugin/WikiAdminRename.php @@ -1,5 +1,5 @@ or called via WikiAdminSelect - * Author: Reini Urban + * @author: Reini Urban * * KNOWN ISSUES: * Currently we must be Admin. @@ -45,7 +45,7 @@ extends WikiPlugin_WikiAdminSelect function getVersion() { return preg_replace("/[Revision: $]/", '', - "\$Revision: 1.9 $"); + "\$Revision: 1.10 $"); } function getDefaultArguments() { @@ -136,7 +136,13 @@ extends WikiPlugin_WikiAdminSelect if ($next_action == 'verify') { $args['info'] = "checkbox,pagename,renamed_pagename"; } - $pagelist = new PageList_Selectable($args['info'], $exclude); + $pagelist = new PageList_Selectable + ( + $args['info'], $exclude, + array('types' => + array('renamed_pagename' + => new _PageList_Column_renamed_pagename('rename', _("Rename to")), + ))); $pagelist->addPageList($pages); $header = HTML::p(); @@ -190,10 +196,29 @@ extends WikiPlugin_WikiAdminSelect $header->pushContent(HTML::p()); return $header; } - } +// moved from lib/PageList.php +class _PageList_Column_renamed_pagename extends _PageList_Column { + function _getValue ($page_handle, &$revision_handle) { + $post_args = $GLOBALS['request']->getArg('admin_rename'); + $value = str_replace($post_args['from'], $post_args['to'],$page_handle->getName()); + $div = HTML::div(" => ",HTML::input(array('type' => 'text', + 'name' => 'rename[]', + 'value' => $value))); + $new_page = $GLOBALS['request']->getPage($value); + if ($new_page->exists()) { + $div->setAttr('class','error'); + $div->setAttr('title',_("This page already exists")); + } + return $div; + } +}; + // $Log: not supported by cvs2svn $ +// Revision 1.9 2004/03/12 13:31:43 rurban +// enforce PagePermissions, errormsg if not Admin +// // Revision 1.8 2004/03/01 13:48:46 rurban // rename fix // p[] consistency fix diff --git a/schemas/mysql.sql b/schemas/mysql.sql index b3e3d7ec8..7928bcd3d 100644 --- a/schemas/mysql.sql +++ b/schemas/mysql.sql @@ -1,4 +1,4 @@ --- $Id: mysql.sql,v 1.8 2004-03-10 15:41:27 rurban Exp $ +-- $Id: mysql.sql,v 1.9 2004-04-06 20:00:11 rurban Exp $ drop table if exists page; CREATE TABLE page ( @@ -47,11 +47,14 @@ CREATE TABLE link ( drop table if exists session; CREATE TABLE session ( - sess_id VARCHAR(32) NOT NULL DEFAULT '', + sess_id CHAR(32) NOT NULL DEFAULT '', sess_data BLOB NOT NULL, sess_date INT UNSIGNED NOT NULL, + sess_ip CHAR(15) NOT NULL, PRIMARY KEY (sess_id) -); + INDEX (sess_date), + INDEX (sess_ip) +) TYPE=heap; -- Optional DB Auth and Prefs -- For these tables below the default table prefix must be used diff --git a/schemas/psql.sql b/schemas/psql.sql index 2e09a51e7..6f7358cf1 100644 --- a/schemas/psql.sql +++ b/schemas/psql.sql @@ -1,4 +1,4 @@ --- $Id: psql.sql,v 1.5 2004-04-01 15:57:20 rurban Exp $ +-- $Id: psql.sql,v 1.6 2004-04-06 20:00:11 rurban Exp $ \set QUIET @@ -57,9 +57,11 @@ \set session_tbl :prefix 'session' \set sess_id :prefix 'sess_id' -\set sess_data :prefix 'sess_data' \set sess_date :prefix 'sess_date' +\set sess_ip :prefix 'sess_ip' +\set pref_tbl :prefix 'pref' +\set pref_id :prefix 'pref_id' \echo Dropping :page_tbl DROP TABLE :page_tbl; @@ -128,12 +130,29 @@ CREATE INDEX :link_to ON :link_tbl (linkto); DROP TABLE :session_tbl; \echo Creating :session_tbl CREATE TABLE :session_tbl ( - sess_id VARCHAR(32) NOT NULL DEFAULT '', - sess_data TEXT NOT NULL, - sess_date INT + sess_id CHAR(32) NOT NULL DEFAULT '', + sess_data TEXT NOT NULL, + sess_date INT + sess_ip CHAR(15) NOT NULL, ); CREATE UNIQUE INDEX :sess_id ON :session_tbl (sess_id); +CREATE INDEX :sess_date ON :session_tbl (sess_date); +CREATE INDEX :sess_ip ON :session_tbl (sess_ip); + +-- Optional DB Auth and Prefs +-- For these tables below the default table prefix must be used +-- in the DBAuthParam SQL statements also. + +\echo Dropping :pref_tbl +DROP TABLE :pref_tbl; +\echo Creating :pref_tbl +CREATE TABLE :pref_tbl ( + userid CHAR(48) NOT NULL, + prefs TEXT NULL DEFAULT '', +); +CREATE UNIQUE INDEX :pref_id + ON :pref_tbl (userid); GRANT ALL ON :page_tbl TO :httpd_user; GRANT ALL ON :version_tbl TO :httpd_user; @@ -141,3 +160,4 @@ GRANT ALL ON :recent_tbl TO :httpd_user; GRANT ALL ON :nonempty_tbl TO :httpd_user; GRANT ALL ON :link_tbl TO :httpd_user; GRANT ALL ON :session_tbl TO :httpd_user; +GRANT ALL ON :pref_tbl TO :httpd_user; diff --git a/schemas/sqlite.sql b/schemas/sqlite.sql index b56e1aee3..ba9a78342 100644 --- a/schemas/sqlite.sql +++ b/schemas/sqlite.sql @@ -1,6 +1,6 @@ -- http://www.hezmatt.org/~mpalmer/sqlite-phpwiki/sqlite.sql --- $Id: sqlite.sql,v 1.1 2004-03-24 01:02:11 rurban Exp $ +-- $Id: sqlite.sql,v 1.2 2004-04-06 20:00:11 rurban Exp $ CREATE TABLE page ( id INT NOT NULL, @@ -46,8 +46,22 @@ CREATE INDEX linkfrom_index ON link (linkfrom); CREATE INDEX linkto_index ON link (linkto); CREATE TABLE session ( - sess_id varchar(32) not null default '', + sess_id char(32) not null default '', sess_data blob not null, sess_date INT UNSIGNED NOT NULL, + sess_ip char(15) not null, PRIMARY KEY (sess_id) ); + +CREATE INDEX sessdate_index ON session (sess_date); +CREATE INDEX sessip_index ON session (sess_ip); + +-- Optional DB Auth and Prefs +-- For these tables below the default table prefix must be used +-- in the DBAuthParam SQL statements also. + +CREATE TABLE pref ( + userid CHAR(48) BINARY NOT NULL UNIQUE, + prefs TEXT NULL DEFAULT '', + PRIMARY KEY (userid) +); diff --git a/themes/default/themeinfo.php b/themes/default/themeinfo.php index 992758aa4..b5f9e2c5f 100644 --- a/themes/default/themeinfo.php +++ b/themes/default/themeinfo.php @@ -1,5 +1,5 @@ setButtonSeparator("\n | "); //$Theme->setDateFormat("%B %d, %Y", false); +/** + * Custom UserPreferences: + * A list of name => _UserPreference class pairs. + * Rationale: Certain themes should be able to extend the predefined list + * of preferences. Display/editing is done in the theme specific userprefs.tmpl + * but storage/sanification/update/... must be extended to the Get/SetPreferences methods. + * See themes/wikilens/themeinfo.php + */ +//$Theme->customUserPreference(); + +/** + * Register custom PageList type and define custom PageList classes. + * Rationale: Certain themes should be able to extend the predefined list + * of pagelist types. E.g. certain plugins, like MostPopular might use + * info=pagename,hits,rating + * which displays the rating column whenever the wikilens theme is active. + * See themes/wikilens/themeinfo.php + */ +// +//$Theme->addPageListColumn(); + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // (c-file-style: "gnu") // Local Variables: diff --git a/themes/wikilens/themeinfo.php b/themes/wikilens/themeinfo.php index 92191f30c..097a7f268 100644 --- a/themes/wikilens/themeinfo.php +++ b/themes/wikilens/themeinfo.php @@ -1,5 +1,5 @@ setTimeFormat("%H:%M"); */ //$Theme->setDateFormat("%B %d, %Y", false); +/** + * Custom UserPreferences: + * A list of name => _UserPreference class pairs. + * Rationale: Certain themes should be able to extend the predefined list + * of preferences. Display/editing is done in the theme specific userprefs.tmpl + * but storage/sanification/update/... must be extended to the Get/SetPreferences methods. + */ + +class _UserPreference_recengine // recommendation engine method +extends _UserPreference +{ + var $valid_values = array('php','mysuggest','mymovielens','mycluto'); + var $default_value = 'php'; + + function sanify ($value) { + if (!in_array($value,$this->valid_values)) return $this->default_value; + else return $value; + } +} + +class _UserPreference_recalgo // recommendation engine algorithm +extends _UserPreference +{ + var $valid_values = array + ( + 'itemCos', // Item-based Top-N recommendation algorithm with cosine-based similarity function + 'itemProb', // Item-based Top-N recommendation algorithm with probability-based similarity function. + // This algorithms tends to outperform the rest. + 'userCos', // User-based Top-N recommendation algorithm with cosine-based similarity function. + 'bayes'); // Naïve Bayesian Classifier + var $default_value = 'itemProb'; + + function sanify ($value) { + if (!in_array($value,$this->valid_values)) return $this->default_value; + else return $value; + } +} + +class _UserPreference_recnnbr // recommendation engine key clustering, neighborhood size +extends _UserPreference_numeric{} + +$Theme->customUserPreferences(array( + 'recengine' => new _UserPreference_recengine(), + 'recalgo' => new _UserPreference_recalgo(), + //recnnbr: typically 15-30 for item-based, 40-80 for user-based algos + 'recnnbr' => new _UserPreference_recnnbr(10,14,80), + )); + +/** + * Custom PageList classes + * Rationale: Certain themes should be able to extend the predefined list + * of pagelist types. E.g. certain plugins, like MostPopular might use + * info=pagename,hits,rating + * which displays the rating column whenever the wikilens theme is active. + * Similarly as in certain plugins, like WikiAdminRename or _WikiTranslation + */ +class _PageList_Column_rating extends _PageList_Column { + function _getValue ($page_handle, &$revision_handle) { + static $prefix = 0; + $loader = new WikiPluginLoader(); + $args = "pagename=".$page_handle->_pagename; + $args .= " small=1"; + $args .= " imgPrefix=".$prefix++; + return $loader->expandPi('<'."?plugin RateIt $args ?".'>',$GLOBALS['request'],$page_handle); + } +}; + +// register custom PageList type +$Theme->addPageListColumn(array('rating' => new _PageList_Column_rating('rating', _("Rate")))); + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // (c-file-style: "gnu") -- 2.45.0