Werdna has uploaded a new change for review.
https://gerrit.wikimedia.org/r/99035
Change subject: Abstract out DbStorage superclass from BasicDbStorage and
RevisionStorage.
......................................................................
Abstract out DbStorage superclass from BasicDbStorage and RevisionStorage.
Also make sure that RevisionStorage has the security improvements from 64bf13a
Change-Id: Ia00a6f96f3ac23085f43b5f6bfc8bae88b8e21b0
---
M Flow.php
M includes/Data/ObjectManager.php
M includes/Data/RevisionStorage.php
3 files changed, 81 insertions(+), 65 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow
refs/changes/35/99035/1
diff --git a/Flow.php b/Flow.php
index 20d349c..a39f6e7 100755
--- a/Flow.php
+++ b/Flow.php
@@ -104,6 +104,7 @@
$wgAutoloadClasses['Flow\Data\BoardHistoryStorage'] = $dir .
'includes/Data/BoardHistoryStorage.php';
$wgAutoloadClasses['Flow\Data\BoardHistoryIndex'] = $dir .
'includes/Data/BoardHistoryStorage.php';
$wgAutoloadClasses['Flow\Data\ObjectStorage'] = $dir .
'includes/Data/ObjectManager.php';
+$wgAutoloadClasses['Flow\Data\DbStorage'] = $dir .
'includes/Data/ObjectManager.php';
$wgAutoloadClasses['Flow\Data\BasicDbStorage'] = $dir .
'includes/Data/ObjectManager.php';
$wgAutoloadClasses['Flow\Data\ObjectMapper'] = $dir .
'includes/Data/ObjectManager.php';
$wgAutoloadClasses['Flow\Data\BasicObjectMapper'] = $dir .
'includes/Data/ObjectManager.php';
@@ -119,6 +120,7 @@
$wgAutoloadClasses['Flow\Data\PostRevisionRecentChanges'] = $dir .
'includes/Data/RecentChanges.php';
$wgAutoloadClasses['Flow\Data\HeaderRecentChanges'] = $dir .
'includes/Data/RecentChanges.php';
$wgAutoloadClasses['Flow\Data\Merger'] = $dir .
'includes/Data/RevisionStorage.php';
+$wgAutoloadClasses['Flow\Data\RawSql'] = $dir .
'includes/Data/ObjectManager.php';
$wgAutoloadClasses['Flow\RecentChanges\Formatter'] = $dir .
'includes/RecentChanges/Formatter.php';
$wgAutoloadClasses['Flow\Log\Logger'] = $dir . 'includes/Log/Logger.php';
$wgAutoloadClasses['Flow\Log\Formatter'] = $dir . 'includes/Log/Formatter.php';
diff --git a/includes/Data/ObjectManager.php b/includes/Data/ObjectManager.php
index d42360d..f38ab68 100644
--- a/includes/Data/ObjectManager.php
+++ b/includes/Data/ObjectManager.php
@@ -602,18 +602,87 @@
}
/**
+ * Base class for all WritableObjectStorage implementers
+ * which use a database as the backing store.
+ *
+ * Includes some utility methods for database management and
+ * SQL security.
+ */
+abstract class DbStorage implements WritableObjectStorage {
+ protected $dbFactory;
+
+ public function __construct( DbFactory $dbFactory ) {
+ $this->dbFactory = $dbFactory;
+ }
+
+ /**
+ * At the moment, does three things:
+ * 1. Finds UUID objects and returns their database representation.
+ * 2. Checks for unarmoured raw SQL and errors out if it exists.
+ * 3. Finds armoured raw SQL and expands it out.
+ * @param [type] $data [description]
+ * @return [type] [description]
+ */
+ protected function preprocessSqlArray( $data ) {
+ // Assuming that all databases have the same escaping settings.
+ $db = $this->dbFactory->getDB( DB_SLAVE );
+
+ $data = UUID::convertUUIDs( $data );
+
+ foreach( $data as $key => $value ) {
+ if ( $value instanceof RawSql ) {
+ $data[$key] = $value->getSql( $db );
+ } elseif ( is_numeric( $key ) ) {
+ throw new \MWException( "Unescaped raw SQL
found in " . __METHOD__ );
+ } elseif ( ! preg_match( '/^[A-Za-z0-9\._]+$/', $key )
) {
+ throw new \MWException( "Dangerous SQL field
name '$key' found in " . __METHOD__ );
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Internal security function which checks a row object
+ * (for inclusion as a condition or a row for insert/update)
+ * for any numeric keys (= raw SQL), or field names with
+ * potentially unsafe characters.
+ * @param array $row The row to check.
+ * @return boolean True if raw SQL is found
+ */
+ protected function hasUnescapedSQL( array $row ) {
+ foreach( $row as $key => $value ) {
+ if ( $value instanceof RawSql ) {
+ // Specifically allowed SQL
+ continue;
+ }
+
+ if ( is_numeric( $key ) ) {
+ return true;
+ }
+
+ if ( ! preg_match( '/^[A-Za-z0-9\._]+$/', $key ) ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
+/**
* Standard backing store for data model with no special cases which is stored
* in a single table in mysql.
*
* Doesn't support updating primary key value yet
* Doesn't support auto-increment pk yet
*/
-class BasicDbStorage implements WritableObjectStorage {
+class BasicDbStorage extends DbStorage {
public function __construct( DbFactory $dbFactory, $table, array
$primaryKey ) {
if ( !$primaryKey ) {
throw new \MWException( 'PK required' );
}
- $this->dbFactory = $dbFactory;
+ parent::__construct( $dbFactory );
$this->table = $table;
$this->primaryKey = $primaryKey;
}
@@ -739,60 +808,6 @@
public function getPrimaryKeyColumns() {
return $this->primaryKey;
- }
-
- /**
- * At the moment, does three things:
- * 1. Finds UUID objects and returns their database representation.
- * 2. Checks for unarmoured raw SQL and errors out if it exists.
- * 3. Finds armoured raw SQL and expands it out.
- * @param [type] $data [description]
- * @return [type] [description]
- */
- protected function preprocessSqlArray( $data ) {
- // Assuming that all databases have the same escaping settings.
- $db = $this->dbFactory->getDB( DB_SLAVE );
-
- $data = UUID::convertUUIDs( $data );
-
- foreach( $data as $key => $value ) {
- if ( $value instanceof RawSql ) {
- $data[$key] = $value->getSql( $db );
- } elseif ( is_numeric( $key ) ) {
- throw new \MWException( "Unescaped raw SQL
found in " . __METHOD__ );
- } elseif ( ! preg_match( '/^[A-Za-z0-9\._]+$/', $key )
) {
- throw new \MWException( "Dangerous SQL field
name '$key' found in " . __METHOD__ );
- }
- }
-
- return $data;
- }
-
- /**
- * Internal security function which checks a row object
- * (for inclusion as a condition or a row for insert/update)
- * for any numeric keys (= raw SQL), or field names with
- * potentially unsafe characters.
- * @param array $row The row to check.
- * @return boolean True if raw SQL is found
- */
- protected function hasUnescapedSQL( array $row ) {
- foreach( $row as $key => $value ) {
- if ( $value instanceof RawSql ) {
- // Specifically allowed SQL
- continue;
- }
-
- if ( is_numeric( $key ) ) {
- return true;
- }
-
- if ( ! preg_match( '/^[A-Za-z0-9\._]+$/', $key ) ) {
- return true;
- }
- }
-
- return false;
}
}
diff --git a/includes/Data/RevisionStorage.php
b/includes/Data/RevisionStorage.php
index d9bd218..f85db8f 100644
--- a/includes/Data/RevisionStorage.php
+++ b/includes/Data/RevisionStorage.php
@@ -9,7 +9,7 @@
use ExternalStore;
use User;
-abstract class RevisionStorage implements WritableObjectStorage {
+abstract class RevisionStorage extends DbStorage {
static protected $allowedUpdateColumns = array(
'rev_mod_state',
'rev_mod_user_id',
@@ -17,7 +17,6 @@
'rev_mod_timestamp',
'rev_mod_reason',
);
- protected $dbFactory;
protected $externalStores;
abstract protected function joinTable();
@@ -29,7 +28,7 @@
abstract protected function removeRelated( array $row );
public function __construct( DbFactory $dbFactory, $externalStore ) {
- $this->dbFactory = $dbFactory;
+ parent::__construct( $dbFactory );
$this->externalStore = $externalStore;
}
@@ -48,7 +47,7 @@
$res = $dbr->select(
array( $this->joinTable(), 'rev' => 'flow_revision' ),
'*',
- UUID::convertUUIDs( $attributes ),
+ $this->preprocessSqlArray( $attributes ),
__METHOD__,
$options,
array( 'rev' => array( 'JOIN', $this->joinField() . ' =
rev_id' ) )
@@ -133,7 +132,7 @@
$res = $dbr->select(
$this->joinTable(),
array( $joinField => "MAX( {$this->joinField()} )" ),
- $this->buildCompositeInCondition( $dbr,
$duplicator->getUniqueQueries() ),
+ $this->preprocessSqlArray(
$this->buildCompositeInCondition( $dbr, $duplicator->getUniqueQueries() ) ),
__METHOD__,
array( 'GROUP BY' => $keys )
);
@@ -244,7 +243,7 @@
$dbw = $this->dbFactory->getDB( DB_MASTER );
$res = $dbw->insert(
'flow_revision',
- $rev,
+ $this->preprocessSqlArray( $rev ),
__METHOD__
);
if ( !$res ) {
@@ -286,7 +285,7 @@
$dbw = $this->dbFactory->getDB( DB_MASTER );
$res = $dbw->update(
'flow_revision',
- $rev,
+ $this->preprocessSqlArray( $rev ),
array( 'rev_id' => $old['rev_id'] ),
__METHOD__
);
@@ -367,7 +366,7 @@
$dbw = $this->dbFactory->getDB( DB_MASTER );
$res = $dbw->insert(
$this->joinTable(),
- UUID::convertUUIDs( $tree ),
+ $this->preprocessSqlArray( $tree ),
__METHOD__
);
@@ -424,7 +423,7 @@
protected function insertRelated( array $row, array $header ) {
$res = $this->dbFactory->getDB( DB_MASTER )->insert(
$this->joinTable(),
- $header,
+ $this->preprocessSqlArray( $header ),
__METHOD__
);
if ( !$res ) {
--
To view, visit https://gerrit.wikimedia.org/r/99035
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia00a6f96f3ac23085f43b5f6bfc8bae88b8e21b0
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Werdna <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits