r90710 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r90709‎ | r90710 | r90711 >
Date:10:54, 24 June 2011
Author:nad
Status:deferred (Comments)
Tags:
Comment:
major changes to make it compatible with the new 1.17 LoadBalancer and LBFactory
Modified paths:
  • /trunk/extensions/SimpleSecurity/SimpleSecurity.php (modified) (history)
  • /trunk/extensions/SimpleSecurity/SimpleSecurity_body.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SimpleSecurity/SimpleSecurity_body.php
@@ -14,6 +14,13 @@
1515
1616
1717 function __construct() {
 18+ global $wgExtensionFunctions;
 19+
 20+ # Put SimpleSecurity's setup function before all others
 21+ array_unshift( $wgExtensionFunctions, array( $this, 'setup' ) );
 22+ }
 23+
 24+ function setup() {
1825 global $wgParser, $wgHooks, $wgLogTypes, $wgLogNames, $wgLogHeaders, $wgLogActions,
1926 $wgSecurityMagicIf, $wgSecurityMagicGroup, $wgSecurityExtraActions, $wgSecurityExtraGroups,
2027 $wgRestrictionTypes, $wgRestrictionLevels, $wgGroupPermissions,
@@ -37,9 +44,7 @@
3845 $wgLogHeaders['security'] = 'securitylogpagetext';
3946 $wgLogActions['security/deny'] = 'securitylogentry';
4047
41 - # Load messages
42 -
43 -
 48+ # Each extra action is also a restriction type
4449 foreach ( $wgSecurityExtraActions as $k => $v ) {
4550 $wgRestrictionTypes[] = $k;
4651 }
@@ -68,6 +73,9 @@
6974 $wgGroupPermissions[$k][$k] = true; # members of $k must be allowed to perform $k
7075 $wgGroupPermissions['sysop'][$k] = true; # sysops must be allowed to perform $k as well
7176 }
 77+
 78+ $db = &wfGetDB( DB_SLAVE );
 79+
7280 }
7381
7482
@@ -372,34 +380,103 @@
373381 }
374382 }
375383
376 -
377384 /**
378 - * Updates passed LoadBalancer's DB servers to secure class
 385+ * Add hooks into the database classes query() and fetchObject() methods
379386 */
380 - static function updateLB( &$lb ) {
381 - $lb->closeAll();
382 - $serverCount = $lb->getServerCount();
383 - for ( $i = 0; $i < $serverCount; $i++ ) {
384 - $server = $lb->getServerInfo( $i );
385 - $sever['type'] = 'SimpleSecurity';
386 - $lb->setServerInfo ( $i, $server );
 387+ static function applyDatabaseHook() {
 388+ global $wgDBtype, $wgLBFactoryConf;
 389+
 390+ # Create a new "Database_SimpleSecurity" database class with hooks into its query() and fetchObject() methods
 391+ # - hooks are added in a sub-class of the database type specified in $wgDBtype
 392+ # - query method is overriden to ensure that old_id field is returned for all queries which read old_text field
 393+ # - only SELECT statements are ever patched
 394+ # - fetchObject method is overridden to validate row content based on old_id
 395+ $oldClass = ucfirst( $wgDBtype );
 396+ eval( "class Database_SimpleSecurity extends Database{$oldClass}" . ' {
 397+ public function query( $sql, $fname = "", $tempIgnore = false ) {
 398+ $patched = preg_replace_callback( "/(?<=SELECT ).+?(?= FROM)/", array("SimpleSecurity", "patchSQL"), $sql, 1 );
 399+ return parent::query( $patched, $fname, $tempIgnore );
 400+ }
 401+ function fetchObject( $res ) {
 402+ global $wgSimpleSecurity;
 403+ $row = parent::fetchObject( $res );
 404+ if( isset( $row->old_text ) ) $wgSimpleSecurity->validateRow( $row );
 405+ return $row;
 406+ }
 407+ }' );
 408+
 409+ # Make sure our new LBFactory is used which in turn uses our LoadBalancer and Database classes
 410+ $wgLBFactoryConf = array( 'class' => 'LBFactory_SimpleSecurity' );
 411+
 412+ }
 413+
 414+}
 415+
 416+/**
 417+ * Create a new class based on LoadBalancer which opens connections to our new hooked database class
 418+ */
 419+class LoadBalancer_SimpleSecurity extends LoadBalancer {
 420+
 421+ function reallyOpenConnection( $server, $dbNameOverride = false ) {
 422+ if( !is_array( $server ) ) {
 423+ throw new MWException( 'You must update your load-balancing configuration. See DefaultSettings.php entry for $wgDBservers.' );
387424 }
 425+ $host = $server['host'];
 426+ $dbname = $server['dbname'];
 427+ if ( $dbNameOverride !== false ) {
 428+ $server['dbname'] = $dbname = $dbNameOverride;
 429+ }
 430+ wfDebug( "Connecting to $host $dbname...\n" );
 431+ $db = new Database_SimpleSecurity(
 432+ isset( $server['host'] ) ? $server['host'] : false,
 433+ isset( $server['user'] ) ? $server['user'] : false,
 434+ isset( $server['password'] ) ? $server['password'] : false,
 435+ isset( $server['dbname'] ) ? $server['dbname'] : false,
 436+ isset( $server['flags'] ) ? $server['flags'] : 0,
 437+ isset( $server['tableprefix'] ) ? $server['tableprefix'] : 'get from global'
 438+ );
 439+ if ( $db->isOpen() ) {
 440+ wfDebug( "Connected to $host $dbname.\n" );
 441+ } else {
 442+ wfDebug( "Connection failed to $host $dbname.\n" );
 443+ }
 444+ $db->setLBInfo( $server );
 445+ if ( isset( $server['fakeSlaveLag'] ) ) {
 446+ $db->setFakeSlaveLag( $server['fakeSlaveLag'] );
 447+ }
 448+ if ( isset( $server['fakeMaster'] ) ) {
 449+ $db->setFakeMaster( true );
 450+ }
 451+ return $db;
388452 }
389453
 454+}
390455
391 - /**
392 - * Hack to ensure proper search class is used
393 - * - $wgDBtype determines search class unless already defined in $wgSearchType
394 - * - just copied method from SearchEngine::create()
395 - */
396 - static function fixSearchType() {
397 - global $wgDBtype, $wgSearchType;
398 - if ( $wgSearchType ) return;
399 - elseif ( $wgDBtype == 'mysql' ) $wgSearchType = 'SearchMySQL';
400 - elseif ( $wgDBtype == 'postgres' ) $wgSearchType = 'SearchPostgres';
401 - elseif ( $wgDBtype == 'sqlite' ) $wgSearchType = 'SearchSqlite';
402 - elseif ( $wgDBtype == 'oracle' ) $wgSearchType = 'SearchOracle';
403 - elseif ( $wgDBtype == 'ibm_db2' ) $wgSearchType = 'SearchIBM_DB2';
404 - else $wgSearchType = 'SearchEngineDummy';
 456+/**
 457+ * Create a new LBFactory class based on LBFactory_Simple which uses our new LoadBalancer class
 458+ */
 459+class LBFactory_SimpleSecurity extends LBFactory_Simple {
 460+
 461+ function newMainLB( $wiki = false ) {
 462+ global $wgDBservers, $wgMasterWaitTimeout;
 463+ if ( $wgDBservers ) {
 464+ $servers = $wgDBservers;
 465+ } else {
 466+ global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype, $wgDebugDumpSql;
 467+ $servers = array(array(
 468+ 'host' => $wgDBserver,
 469+ 'user' => $wgDBuser,
 470+ 'password' => $wgDBpassword,
 471+ 'dbname' => $wgDBname,
 472+ 'type' => $wgDBtype,
 473+ 'load' => 1,
 474+ 'flags' => ($wgDebugDumpSql ? DBO_DEBUG : 0) | DBO_DEFAULT
 475+ ));
 476+ }
 477+ return new LoadBalancer_SimpleSecurity( array(
 478+ 'servers' => $servers,
 479+ 'masterWaitTimeout' => $wgMasterWaitTimeout
 480+ ));
405481 }
 482+
406483 }
Index: trunk/extensions/SimpleSecurity/SimpleSecurity.php
@@ -1,29 +1,29 @@
22 <?php
 3+if( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
 4+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' );
35 /**
46 * SimpleSecurity extension
57 * - Extends the MediaWiki article protection to allow restricting viewing of article content
68 * - Also adds #ifusercan and #ifgroup parser functions for rendering restriction-based content
79 *
810 * See http://www.mediawiki.org/Extension:SimpleSecurity for installation and usage details
9 - * See http://www.organicdesign.co.nz/Extension_talk:SimpleSecurity.php for development notes and disucssion
 11+ * See http://www.organicdesign.co.nz/Extension:SimpleSecurity.php for development notes and disucssion
1012 *
11 - * Version 4.0 - Oct 2007 - new version for modern MediaWiki's using DatabaseFetchHook
 13+ * Version 4.0 - Oct 2007 - new version for MediaWiki 1.12+ using DatabaseFetchHook
1214 * Version 4.1 - Jun 2008 - development funded for a slimmed down functional version
1315 * Version 4.2 - Aug 2008 - fattened up a bit again - $wgPageRestrictions and security info added in again
1416 * Version 4.3 - Mar 2009 - bug fixes and split out to separate class and i18n files
1517 * Version 4.5 - Sep 2010 - File security started again - by Josh Adams
 18+ * Version 5.0 - Jun 2011 - major changes to the DB hooking method to handle changes in MediaWiki 1.17
1619 *
1720 * @file
1821 * @ingroup Extensions
1922 * @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad]
20 - * @copyright © 2007 Aran Dunkley
 23+ * @copyright © 2007-2011 Aran Dunkley
2124 * @license GNU General Public Licence 2.0 or later
2225 */
 26+define( 'SIMPLESECURITY_VERSION', '5.0.0, 2011-06-24' );
2327
24 -if ( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
25 -
26 -define( 'SIMPLESECURITY_VERSION', '4.5.1, 2010-10-16' );
27 -
2828 # Load the SimpleSecurity class and messages
2929 $dir = dirname( __FILE__ ) . '/';
3030 $wgExtensionMessagesFiles['SimpleSecurity'] = $dir . 'SimpleSecurity.i18n.php';
@@ -55,10 +55,9 @@
5656 # protection to apply to all instances of that record type
5757 $wgSecurityProtectRecords = true;
5858
 59+# Don;t use the DB hook by default since it's voodoo
 60+if( !isset( $wgSecurityUseDBHook ) ) $wgSecurityUseDBHook = false;
5961
60 -# Put SimpleSecurity's setup function before all others
61 -array_unshift( $wgExtensionFunctions, 'wfSetupSimpleSecurity' );
62 -
6362 $wgHooks['LanguageGetMagic'][] = 'wfSimpleSecurityLanguageGetMagic';
6463 $wgExtensionCredits['parserhook'][] = array(
6564 'path' => __FILE__,
@@ -67,54 +66,16 @@
6867 'url' => "http://www.mediawiki.org/wiki/Extension:SimpleSecurity",
6968 'version' => SIMPLESECURITY_VERSION,
7069 'descriptionmsg' => 'security-desc',
71 -
7270 );
73 -
7471 $wgHooks['MessagesPreLoad'][] = 'wfSimpleSecurityMessagesPreLoad';
7572
76 -# SearchEngine is based on $wgDBtype so must be set before it gets changed to DatabaseSimpleSecurity
77 -# - this may be paranoid now since $wgDBtype is changed back after LoadBalancer has initialised
78 -SimpleSecurity::fixSearchType();
 73+# Instantiate the SimpleSecurity singleton now that the environment is prepared
 74+$wgSimpleSecurity = new SimpleSecurity();
7975
80 -# If the database class already exists, add the DB hook now, otherwise wait until extension setup
81 -if ( !isset( $wgSecurityUseDBHook ) ) $wgSecurityUseDBHook = false;
82 -if ( $wgSecurityUseDBHook && class_exists( 'Database' ) ) wfSimpleSecurityDBHook();
 76+# If using the DBHook, apply it now (must be done from the root scope since it creates classes)
 77+if( $wgSecurityUseDBHook ) SimpleSecurity::applyDatabaseHook();
8378
8479 /**
85 - * Hook into Database::query and Database::fetchObject of database instances
86 - * - this can't be executed from within a method because PHP doesn't like nested class definitions
87 - * - it needs an eval because the class statement isn't allowed to contain strings
88 - * - the hooks aren't called if $wgSimpleSecurity doesn't exist yet
89 - * - hooks are added in a sub-class of the database type specified in $wgDBtype called DatabaseSimpleSecurity
90 - * - $wgDBtype is changed so that new DB instances are based on the sub-class
91 - * - query method is overriden to ensure that old_id field is returned for all queries which read old_text field
92 - * - only SELECT statements are ever patched
93 - * - fetchObject method is overridden to validate row content based on old_id
94 - */
95 -function wfSimpleSecurityDBHook() {
96 - global $wgDBtype, $wgSecurityUseDBHook, $wgOldDBtype;
97 - $wgOldDBtype = $wgDBtype;
98 - $oldClass = ucfirst( $wgDBtype );
99 - $wgDBtype = 'SimpleSecurity';
100 - eval( "class Database{$wgDBtype} extends Database{$oldClass}" . ' {
101 - public function query($sql, $fname = "", $tempIgnore = false) {
102 - global $wgSimpleSecurity;
103 - $count = false;
104 - if (is_object($wgSimpleSecurity))
105 - $patched = preg_replace_callback("/(?<=SELECT ).+?(?= FROM)/", array("SimpleSecurity", "patchSQL"), $sql, 1, $count);
106 - return parent::query($count ? $patched : $sql, $fname, $tempIgnore);
107 - }
108 - function fetchObject($res) {
109 - global $wgSimpleSecurity;
110 - $row = parent::fetchObject($res);
111 - if (is_object($wgSimpleSecurity) && isset($row->old_text)) $wgSimpleSecurity->validateRow($row);
112 - return $row;
113 - }
114 - }' );
115 - $wgSecurityUseDBHook = false;
116 -}
117 -
118 -/**
11980 * Register magic words
12081 */
12182 function wfSimpleSecurityLanguageGetMagic( &$magicWords, $langCode = 0 ) {
@@ -127,34 +88,34 @@
12889 function wfSimpleSecurityMessagesPreLoad( $title, &$text ) {
12990 global $wgSecurityExtraActions, $wgSecurityExtraGroups;
13091
131 - if ( substr( $title, 0, 12 ) == 'Restriction-' ) {
 92+ if( substr( $title, 0, 12 ) == 'Restriction-' ) {
13293 $key = substr( $title, 12 );
133 - if ( isset( $wgSecurityExtraActions[$key] ) ) {
 94+ if( isset( $wgSecurityExtraActions[$key] ) ) {
13495 $text = empty( $wgSecurityExtraActions[$key] ) ? ucfirst( $key ) : $wgSecurityExtraActions[$key];
13596 }
13697 return true;
137 - } elseif ( substr( $title, 0, 14 ) == 'Protect-level-' ) {
 98+ } elseif( substr( $title, 0, 14 ) == 'Protect-level-' ) {
13899 $key = substr( $title, 14 );
139100 $type = 'level';
140 - } elseif ( substr( $title, 0, 6 ) == 'Right-' ) {
 101+ } elseif( substr( $title, 0, 6 ) == 'Right-' ) {
141102 $key = substr( $title, 6 );
142103 $type = 'right';
143104 } else {
144105 return true;
145106 }
146107
147 - if ( isset( $wgSecurityExtraGroups[$key] ) ) {
 108+ if( isset( $wgSecurityExtraGroups[$key] ) ) {
148109 $name = empty( $wgSecurityExtraGroups[$key] ) ? ucfirst( $key ) : $wgSecurityExtraGroups[$key];
149110 } else {
150111 $lower = array_map( 'strtolower', $wgSecurityExtraGroups );
151112 $nkey = array_search( strtolower( $key ), $lower, true );
152 - if ( !is_numeric( $nkey ) ) {
 113+ if( !is_numeric( $nkey ) ) {
153114 return true;
154115 }
155116 $name = ucfirst( $wgSecurityExtraGroups[$nkey] );
156117 }
157118
158 - if ( $type == 'level' ) {
 119+ if( $type == 'level' ) {
159120 $text = $name;
160121 } else {
161122 $text = wfMsg( 'security-restricttogroup', $name );
@@ -163,28 +124,4 @@
164125 return true;
165126 }
166127
167 -/**
168 - * Called from $wgExtensionFunctions array when initialising extensions
169 - */
170 -function wfSetupSimpleSecurity() {
171 - global $wgSimpleSecurity, $wgSecurityUseDBHook, $wgLoadBalancer, $wgDBtype, $wgOldDBtype;
172128
173 - # Instantiate the SimpleSecurity singleton now that the environment is prepared
174 - $wgSimpleSecurity = new SimpleSecurity();
175 -
176 - # If the DB hook couldn't be set up early, do it now
177 - # - but now the LoadBalancer exists and must have its DB types changed
178 - if ( $wgSecurityUseDBHook ) {
179 - wfSimpleSecurityDBHook();
180 - if ( function_exists( 'wfGetLBFactory' ) ) wfGetLBFactory()->forEachLB( array( 'SimpleSecurity', 'updateLB' ) );
181 - elseif ( is_object( $wgLoadBalancer ) ) SimpleSecurity::updateLB( $wgLoadBalancer );
182 - else die( "Can't hook in to Database class!" );
183 - }
184 -
185 - # Request a DB connection to ensure the LoadBalancer is initialised,
186 - # then change back to old DBtype since it won't be used for making connections again but can affect other operations
187 - # such as $wgContLang->stripForSearch which is called by SearchMySQL::parseQuery
188 - wfGetDB( DB_MASTER );
189 - $wgDBtype = $wgOldDBtype;
190 -}
191 -

Comments

#Comment by Nikerabbit (talk | contribs)   12:17, 24 June 2011

Every global must be initialised before it is read:

+if( !isset( $wgSecurityUseDBHook ) ) $wgSecurityUseDBHook = false;

I'd also avoid file level code.

What is the point of assigning to variable which is never read?

+$db = &wfGetDB( DB_SLAVE );

Status & tagging log