http://www.mediawiki.org/wiki/Special:Code/MediaWiki/90710
Revision: 90710
Author: nad
Date: 2011-06-24 10:54:37 +0000 (Fri, 24 Jun 2011)
Log Message:
-----------
major changes to make it compatible with the new 1.17 LoadBalancer and LBFactory
Modified Paths:
--------------
trunk/extensions/SimpleSecurity/SimpleSecurity.php
trunk/extensions/SimpleSecurity/SimpleSecurity_body.php
Modified: trunk/extensions/SimpleSecurity/SimpleSecurity.php
===================================================================
--- trunk/extensions/SimpleSecurity/SimpleSecurity.php 2011-06-24 10:38:51 UTC
(rev 90709)
+++ trunk/extensions/SimpleSecurity/SimpleSecurity.php 2011-06-24 10:54:37 UTC
(rev 90710)
@@ -1,29 +1,29 @@
<?php
+if( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
+if( version_compare( $wgVersion, '1.17.0' ) < 0 ) die( 'This version of
SimpleSecurity is for MediaWiki 1.17 or greater, please install SimpleSecurity
4.x which can be found at
http://svn.organicdesign.co.nz/listing.php?repname=extensions' );
/**
* SimpleSecurity extension
* - Extends the MediaWiki article protection to allow restricting viewing of
article content
* - Also adds #ifusercan and #ifgroup parser functions for rendering
restriction-based content
*
* See http://www.mediawiki.org/Extension:SimpleSecurity for installation and
usage details
- * See http://www.organicdesign.co.nz/Extension_talk:SimpleSecurity.php for
development notes and disucssion
+ * See http://www.organicdesign.co.nz/Extension:SimpleSecurity.php for
development notes and disucssion
*
- * Version 4.0 - Oct 2007 - new version for modern MediaWiki's using
DatabaseFetchHook
+ * Version 4.0 - Oct 2007 - new version for MediaWiki 1.12+ using
DatabaseFetchHook
* Version 4.1 - Jun 2008 - development funded for a slimmed down functional
version
* Version 4.2 - Aug 2008 - fattened up a bit again - $wgPageRestrictions and
security info added in again
* Version 4.3 - Mar 2009 - bug fixes and split out to separate class and i18n
files
* Version 4.5 - Sep 2010 - File security started again - by Josh Adams
+ * Version 5.0 - Jun 2011 - major changes to the DB hooking method to handle
changes in MediaWiki 1.17
*
* @file
* @ingroup Extensions
* @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad]
- * @copyright © 2007 Aran Dunkley
+ * @copyright © 2007-2011 Aran Dunkley
* @license GNU General Public Licence 2.0 or later
*/
+define( 'SIMPLESECURITY_VERSION', '5.0.0, 2011-06-24' );
-if ( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.'
);
-
-define( 'SIMPLESECURITY_VERSION', '4.5.1, 2010-10-16' );
-
# Load the SimpleSecurity class and messages
$dir = dirname( __FILE__ ) . '/';
$wgExtensionMessagesFiles['SimpleSecurity'] = $dir . 'SimpleSecurity.i18n.php';
@@ -55,10 +55,9 @@
# protection to apply to all instances of that record type
$wgSecurityProtectRecords = true;
+# Don;t use the DB hook by default since it's voodoo
+if( !isset( $wgSecurityUseDBHook ) ) $wgSecurityUseDBHook = false;
-# Put SimpleSecurity's setup function before all others
-array_unshift( $wgExtensionFunctions, 'wfSetupSimpleSecurity' );
-
$wgHooks['LanguageGetMagic'][] = 'wfSimpleSecurityLanguageGetMagic';
$wgExtensionCredits['parserhook'][] = array(
'path' => __FILE__,
@@ -67,54 +66,16 @@
'url' =>
"http://www.mediawiki.org/wiki/Extension:SimpleSecurity",
'version' => SIMPLESECURITY_VERSION,
'descriptionmsg' => 'security-desc',
-
);
-
$wgHooks['MessagesPreLoad'][] = 'wfSimpleSecurityMessagesPreLoad';
-# SearchEngine is based on $wgDBtype so must be set before it gets changed to
DatabaseSimpleSecurity
-# - this may be paranoid now since $wgDBtype is changed back after
LoadBalancer has initialised
-SimpleSecurity::fixSearchType();
+# Instantiate the SimpleSecurity singleton now that the environment is prepared
+$wgSimpleSecurity = new SimpleSecurity();
-# If the database class already exists, add the DB hook now, otherwise wait
until extension setup
-if ( !isset( $wgSecurityUseDBHook ) ) $wgSecurityUseDBHook = false;
-if ( $wgSecurityUseDBHook && class_exists( 'Database' ) )
wfSimpleSecurityDBHook();
+# If using the DBHook, apply it now (must be done from the root scope since it
creates classes)
+if( $wgSecurityUseDBHook ) SimpleSecurity::applyDatabaseHook();
/**
- * Hook into Database::query and Database::fetchObject of database instances
- * - this can't be executed from within a method because PHP doesn't like
nested class definitions
- * - it needs an eval because the class statement isn't allowed to contain
strings
- * - the hooks aren't called if $wgSimpleSecurity doesn't exist yet
- * - hooks are added in a sub-class of the database type specified in
$wgDBtype called DatabaseSimpleSecurity
- * - $wgDBtype is changed so that new DB instances are based on the sub-class
- * - query method is overriden to ensure that old_id field is returned for all
queries which read old_text field
- * - only SELECT statements are ever patched
- * - fetchObject method is overridden to validate row content based on old_id
- */
-function wfSimpleSecurityDBHook() {
- global $wgDBtype, $wgSecurityUseDBHook, $wgOldDBtype;
- $wgOldDBtype = $wgDBtype;
- $oldClass = ucfirst( $wgDBtype );
- $wgDBtype = 'SimpleSecurity';
- eval( "class Database{$wgDBtype} extends Database{$oldClass}" . ' {
- public function query($sql, $fname = "", $tempIgnore = false) {
- global $wgSimpleSecurity;
- $count = false;
- if (is_object($wgSimpleSecurity))
- $patched = preg_replace_callback("/(?<=SELECT
).+?(?= FROM)/", array("SimpleSecurity", "patchSQL"), $sql, 1, $count);
- return parent::query($count ? $patched : $sql, $fname,
$tempIgnore);
- }
- function fetchObject($res) {
- global $wgSimpleSecurity;
- $row = parent::fetchObject($res);
- if (is_object($wgSimpleSecurity) &&
isset($row->old_text)) $wgSimpleSecurity->validateRow($row);
- return $row;
- }
- }' );
- $wgSecurityUseDBHook = false;
-}
-
-/**
* Register magic words
*/
function wfSimpleSecurityLanguageGetMagic( &$magicWords, $langCode = 0 ) {
@@ -127,34 +88,34 @@
function wfSimpleSecurityMessagesPreLoad( $title, &$text ) {
global $wgSecurityExtraActions, $wgSecurityExtraGroups;
- if ( substr( $title, 0, 12 ) == 'Restriction-' ) {
+ if( substr( $title, 0, 12 ) == 'Restriction-' ) {
$key = substr( $title, 12 );
- if ( isset( $wgSecurityExtraActions[$key] ) ) {
+ if( isset( $wgSecurityExtraActions[$key] ) ) {
$text = empty( $wgSecurityExtraActions[$key] ) ?
ucfirst( $key ) : $wgSecurityExtraActions[$key];
}
return true;
- } elseif ( substr( $title, 0, 14 ) == 'Protect-level-' ) {
+ } elseif( substr( $title, 0, 14 ) == 'Protect-level-' ) {
$key = substr( $title, 14 );
$type = 'level';
- } elseif ( substr( $title, 0, 6 ) == 'Right-' ) {
+ } elseif( substr( $title, 0, 6 ) == 'Right-' ) {
$key = substr( $title, 6 );
$type = 'right';
} else {
return true;
}
- if ( isset( $wgSecurityExtraGroups[$key] ) ) {
+ if( isset( $wgSecurityExtraGroups[$key] ) ) {
$name = empty( $wgSecurityExtraGroups[$key] ) ? ucfirst( $key )
: $wgSecurityExtraGroups[$key];
} else {
$lower = array_map( 'strtolower', $wgSecurityExtraGroups );
$nkey = array_search( strtolower( $key ), $lower, true );
- if ( !is_numeric( $nkey ) ) {
+ if( !is_numeric( $nkey ) ) {
return true;
}
$name = ucfirst( $wgSecurityExtraGroups[$nkey] );
}
- if ( $type == 'level' ) {
+ if( $type == 'level' ) {
$text = $name;
} else {
$text = wfMsg( 'security-restricttogroup', $name );
@@ -163,28 +124,4 @@
return true;
}
-/**
- * Called from $wgExtensionFunctions array when initialising extensions
- */
-function wfSetupSimpleSecurity() {
- global $wgSimpleSecurity, $wgSecurityUseDBHook, $wgLoadBalancer,
$wgDBtype, $wgOldDBtype;
- # Instantiate the SimpleSecurity singleton now that the environment is
prepared
- $wgSimpleSecurity = new SimpleSecurity();
-
- # If the DB hook couldn't be set up early, do it now
- # - but now the LoadBalancer exists and must have its DB types changed
- if ( $wgSecurityUseDBHook ) {
- wfSimpleSecurityDBHook();
- if ( function_exists( 'wfGetLBFactory' ) )
wfGetLBFactory()->forEachLB( array( 'SimpleSecurity', 'updateLB' ) );
- elseif ( is_object( $wgLoadBalancer ) )
SimpleSecurity::updateLB( $wgLoadBalancer );
- else die( "Can't hook in to Database class!" );
- }
-
- # Request a DB connection to ensure the LoadBalancer is initialised,
- # then change back to old DBtype since it won't be used for making
connections again but can affect other operations
- # such as $wgContLang->stripForSearch which is called by
SearchMySQL::parseQuery
- wfGetDB( DB_MASTER );
- $wgDBtype = $wgOldDBtype;
-}
-
Modified: trunk/extensions/SimpleSecurity/SimpleSecurity_body.php
===================================================================
--- trunk/extensions/SimpleSecurity/SimpleSecurity_body.php 2011-06-24
10:38:51 UTC (rev 90709)
+++ trunk/extensions/SimpleSecurity/SimpleSecurity_body.php 2011-06-24
10:54:37 UTC (rev 90710)
@@ -14,6 +14,13 @@
function __construct() {
+ global $wgExtensionFunctions;
+
+ # Put SimpleSecurity's setup function before all others
+ array_unshift( $wgExtensionFunctions, array( $this, 'setup' ) );
+ }
+
+ function setup() {
global $wgParser, $wgHooks, $wgLogTypes, $wgLogNames,
$wgLogHeaders, $wgLogActions,
$wgSecurityMagicIf, $wgSecurityMagicGroup,
$wgSecurityExtraActions, $wgSecurityExtraGroups,
$wgRestrictionTypes, $wgRestrictionLevels,
$wgGroupPermissions,
@@ -37,9 +44,7 @@
$wgLogHeaders['security'] = 'securitylogpagetext';
$wgLogActions['security/deny'] = 'securitylogentry';
- # Load messages
-
-
+ # Each extra action is also a restriction type
foreach ( $wgSecurityExtraActions as $k => $v ) {
$wgRestrictionTypes[] = $k;
}
@@ -68,6 +73,9 @@
$wgGroupPermissions[$k][$k] = true; # members of
$k must be allowed to perform $k
$wgGroupPermissions['sysop'][$k] = true; # sysops must
be allowed to perform $k as well
}
+
+ $db = &wfGetDB( DB_SLAVE );
+
}
@@ -372,34 +380,103 @@
}
}
-
/**
- * Updates passed LoadBalancer's DB servers to secure class
+ * Add hooks into the database classes query() and fetchObject() methods
*/
- static function updateLB( &$lb ) {
- $lb->closeAll();
- $serverCount = $lb->getServerCount();
- for ( $i = 0; $i < $serverCount; $i++ ) {
- $server = $lb->getServerInfo( $i );
- $sever['type'] = 'SimpleSecurity';
- $lb->setServerInfo ( $i, $server );
+ static function applyDatabaseHook() {
+ global $wgDBtype, $wgLBFactoryConf;
+
+ # Create a new "Database_SimpleSecurity" database class with
hooks into its query() and fetchObject() methods
+ # - hooks are added in a sub-class of the database type
specified in $wgDBtype
+ # - query method is overriden to ensure that old_id field is
returned for all queries which read old_text field
+ # - only SELECT statements are ever patched
+ # - fetchObject method is overridden to validate row content
based on old_id
+ $oldClass = ucfirst( $wgDBtype );
+ eval( "class Database_SimpleSecurity extends
Database{$oldClass}" . ' {
+ public function query( $sql, $fname = "", $tempIgnore =
false ) {
+ $patched = preg_replace_callback( "/(?<=SELECT
).+?(?= FROM)/", array("SimpleSecurity", "patchSQL"), $sql, 1 );
+ return parent::query( $patched, $fname,
$tempIgnore );
+ }
+ function fetchObject( $res ) {
+ global $wgSimpleSecurity;
+ $row = parent::fetchObject( $res );
+ if( isset( $row->old_text ) )
$wgSimpleSecurity->validateRow( $row );
+ return $row;
+ }
+ }' );
+
+ # Make sure our new LBFactory is used which in turn uses our
LoadBalancer and Database classes
+ $wgLBFactoryConf = array( 'class' => 'LBFactory_SimpleSecurity'
);
+
+ }
+
+}
+
+/**
+ * Create a new class based on LoadBalancer which opens connections to our new
hooked database class
+ */
+class LoadBalancer_SimpleSecurity extends LoadBalancer {
+
+ function reallyOpenConnection( $server, $dbNameOverride = false ) {
+ if( !is_array( $server ) ) {
+ throw new MWException( 'You must update your
load-balancing configuration. See DefaultSettings.php entry for $wgDBservers.'
);
}
+ $host = $server['host'];
+ $dbname = $server['dbname'];
+ if ( $dbNameOverride !== false ) {
+ $server['dbname'] = $dbname = $dbNameOverride;
+ }
+ wfDebug( "Connecting to $host $dbname...\n" );
+ $db = new Database_SimpleSecurity(
+ isset( $server['host'] ) ? $server['host'] : false,
+ isset( $server['user'] ) ? $server['user'] : false,
+ isset( $server['password'] ) ? $server['password'] :
false,
+ isset( $server['dbname'] ) ? $server['dbname'] : false,
+ isset( $server['flags'] ) ? $server['flags'] : 0,
+ isset( $server['tableprefix'] ) ?
$server['tableprefix'] : 'get from global'
+ );
+ if ( $db->isOpen() ) {
+ wfDebug( "Connected to $host $dbname.\n" );
+ } else {
+ wfDebug( "Connection failed to $host $dbname.\n" );
+ }
+ $db->setLBInfo( $server );
+ if ( isset( $server['fakeSlaveLag'] ) ) {
+ $db->setFakeSlaveLag( $server['fakeSlaveLag'] );
+ }
+ if ( isset( $server['fakeMaster'] ) ) {
+ $db->setFakeMaster( true );
+ }
+ return $db;
}
+}
- /**
- * Hack to ensure proper search class is used
- * - $wgDBtype determines search class unless already defined in
$wgSearchType
- * - just copied method from SearchEngine::create()
- */
- static function fixSearchType() {
- global $wgDBtype, $wgSearchType;
- if ( $wgSearchType ) return;
- elseif ( $wgDBtype == 'mysql' ) $wgSearchType =
'SearchMySQL';
- elseif ( $wgDBtype == 'postgres' ) $wgSearchType =
'SearchPostgres';
- elseif ( $wgDBtype == 'sqlite' ) $wgSearchType =
'SearchSqlite';
- elseif ( $wgDBtype == 'oracle' ) $wgSearchType =
'SearchOracle';
- elseif ( $wgDBtype == 'ibm_db2' ) $wgSearchType =
'SearchIBM_DB2';
- else $wgSearchType =
'SearchEngineDummy';
+/**
+ * Create a new LBFactory class based on LBFactory_Simple which uses our new
LoadBalancer class
+ */
+class LBFactory_SimpleSecurity extends LBFactory_Simple {
+
+ function newMainLB( $wiki = false ) {
+ global $wgDBservers, $wgMasterWaitTimeout;
+ if ( $wgDBservers ) {
+ $servers = $wgDBservers;
+ } else {
+ global $wgDBserver, $wgDBuser, $wgDBpassword,
$wgDBname, $wgDBtype, $wgDebugDumpSql;
+ $servers = array(array(
+ 'host' => $wgDBserver,
+ 'user' => $wgDBuser,
+ 'password' => $wgDBpassword,
+ 'dbname' => $wgDBname,
+ 'type' => $wgDBtype,
+ 'load' => 1,
+ 'flags' => ($wgDebugDumpSql ? DBO_DEBUG : 0) |
DBO_DEFAULT
+ ));
+ }
+ return new LoadBalancer_SimpleSecurity( array(
+ 'servers' => $servers,
+ 'masterWaitTimeout' => $wgMasterWaitTimeout
+ ));
}
+
}
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs