r92330 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r92329‎ | r92330 | r92331 >
Date:22:56, 15 July 2011
Author:reedy
Status:deferred
Tags:
Comment:
Modified paths:
  • /branches/REL1_18/phase3/includes/Block.php (modified) (history)
  • /branches/REL1_18/phase3/includes/FileDeleteForm.php (modified) (history)
  • /branches/REL1_18/phase3/includes/HttpFunctions.php (modified) (history)
  • /branches/REL1_18/phase3/includes/LogEventsList.php (modified) (history)
  • /branches/REL1_18/phase3/includes/MessageBlobStore.php (modified) (history)
  • /branches/REL1_18/phase3/includes/User.php (modified) (history)
  • /branches/REL1_18/phase3/includes/media/SVGMetadataExtractor.php (modified) (history)
  • /branches/REL1_18/phase3/includes/upload/UploadFromUrl.php (modified) (history)
  • /branches/REL1_18/phase3/tests/phpunit/includes/BlockTest.php (modified) (history)

Diff [purge]

Index: branches/REL1_18/phase3/tests/phpunit/includes/BlockTest.php
@@ -48,5 +48,38 @@
4949
5050 }
5151
 52+ /**
 53+ * This is the method previously used to load block info in CheckUser etc
 54+ * passing an empty value (empty string, null, etc) as the ip parameter bypasses IP lookup checks.
 55+ *
 56+ * This stopped working with r84475 and friends: regression being fixed for bug 29116.
 57+ *
 58+ * @dataProvider dataBug29116
 59+ */
 60+ function testBug29116LoadWithEmptyIp( $vagueTarget ) {
 61+ $block = new Block();
 62+ $block->load( $vagueTarget, 'UTBlockee' );
 63+ $this->assertTrue( $this->block->equals( Block::newFromTarget('UTBlockee', $vagueTarget) ), "Block->load() returns the same block as the one that was made when given empty ip param " . var_export( $vagueTarget, true ) );
 64+ }
 65+
 66+ /**
 67+ * CheckUser since being changed to use Block::newFromTarget started failing
 68+ * because the new function didn't accept empty strings like Block::load()
 69+ * had. Regression bug 29116.
 70+ *
 71+ * @dataProvider dataBug29116
 72+ */
 73+ function testBug29116NewFromTargetWithEmptyIp( $vagueTarget ) {
 74+ $block = Block::newFromTarget('UTBlockee', $vagueTarget);
 75+ $this->assertTrue( $this->block->equals( $block ), "newFromTarget() returns the same block as the one that was made when given empty vagueTarget param " . var_export( $vagueTarget, true ) );
 76+ }
 77+
 78+ function dataBug29116() {
 79+ return array(
 80+ array( null ),
 81+ array( '' ),
 82+ array( false )
 83+ );
 84+ }
5285 }
5386
Index: branches/REL1_18/phase3/includes/upload/UploadFromUrl.php
@@ -105,41 +105,62 @@
106106 protected function makeTemporaryFile() {
107107 return tempnam( wfTempDir(), 'URL' );
108108 }
 109+
109110 /**
110 - * Save the result of a HTTP request to the temporary file
 111+ * Callback: save a chunk of the result of a HTTP request to the temporary file
111112 *
112 - * @param $req MWHttpRequest
113 - * @return Status
 113+ * @param $req mixed
 114+ * @param $buffer string
 115+ * @return int number of bytes handled
114116 */
115 - private function saveTempFile( $req ) {
116 - if ( $this->mTempPath === false ) {
117 - return Status::newFatal( 'tmp-create-error' );
 117+ public function saveTempFileChunk( $req, $buffer ) {
 118+ $nbytes = fwrite( $this->mTmpHandle, $buffer );
 119+
 120+ if ( $nbytes == strlen( $buffer ) ) {
 121+ $this->mFileSize += $nbytes;
 122+ } else {
 123+ // Well... that's not good!
 124+ fclose( $this->mTmpHandle );
 125+ $this->mTmpHandle = false;
118126 }
119 - if ( file_put_contents( $this->mTempPath, $req->getContent() ) === false ) {
120 - return Status::newFatal( 'tmp-write-error' );
121 - }
122127
123 - $this->mFileSize = filesize( $this->mTempPath );
 128+ return $nbytes;
 129+ }
124130
125 - return Status::newGood();
126 - }
127131 /**
128132 * Download the file, save it to the temporary file and update the file
129133 * size and set $mRemoveTempFile to true.
130134 */
131135 protected function reallyFetchFile() {
 136+ if ( $this->mTempPath === false ) {
 137+ return Status::newFatal( 'tmp-create-error' );
 138+ }
 139+
 140+ // Note the temporary file should already be created by makeTemporaryFile()
 141+ $this->mTmpHandle = fopen( $this->mTempPath, 'wb' );
 142+ if ( !$this->mTmpHandle ) {
 143+ return Status::newFatal( 'tmp-create-error' );
 144+ }
 145+
 146+ $this->mRemoveTempFile = true;
 147+ $this->mFileSize = 0;
 148+
132149 $req = MWHttpRequest::factory( $this->mUrl );
 150+ $req->setCallback( array( $this, 'saveTempFileChunk' ) );
133151 $status = $req->execute();
134152
135 - if ( !$status->isOk() ) {
136 - return $status;
 153+ if ( $this->mTmpHandle ) {
 154+ // File got written ok...
 155+ fclose( $this->mTmpHandle );
 156+ $this->mTmpHandle = null;
 157+ } else {
 158+ // We encountered a write error during the download...
 159+ return Status::newFatal( 'tmp-write-error' );
137160 }
138161
139 - $status = $this->saveTempFile( $req );
140 - if ( !$status->isGood() ) {
 162+ if ( !$status->isOk() ) {
141163 return $status;
142164 }
143 - $this->mRemoveTempFile = true;
144165
145166 return $status;
146167 }
Index: branches/REL1_18/phase3/includes/User.php
@@ -134,6 +134,7 @@
135135 'suppressredirect',
136136 'suppressrevision',
137137 'trackback',
 138+ 'unblockself',
138139 'undelete',
139140 'unwatchedpages',
140141 'upload',
Index: branches/REL1_18/phase3/includes/LogEventsList.php
@@ -503,8 +503,7 @@
504504 # Fall back to a blue contributions link
505505 $revert = $this->skin->userToolLinks( 1, $title->getDBkey() );
506506 }
507 - $ts = wfTimestamp( TS_UNIX, $row->log_timestamp );
508 - if( $ts < '20080129000000' ) {
 507+ if( wfTimestamp( TS_MW, $row->log_timestamp ) < '20080129000000' ) {
509508 # Suppress $comment from old entries (before 2008-01-29),
510509 # not needed and can contain incorrect links
511510 $comment = '';
Index: branches/REL1_18/phase3/includes/media/SVGMetadataExtractor.php
@@ -35,6 +35,7 @@
3636 class SVGReader {
3737 const DEFAULT_WIDTH = 512;
3838 const DEFAULT_HEIGHT = 512;
 39+ const NS_SVG = 'http://www.w3.org/2000/svg';
3940
4041 private $reader = null;
4142 private $mDebug = false;
@@ -101,9 +102,9 @@
102103 $keepReading = $this->reader->read();
103104 }
104105
105 - if ( !$this->qualifiedNameEquals( $this->reader->name, 'svg', 'svg' ) ) {
 106+ if ( $this->reader->localName != 'svg' || $this->reader->namespaceURI != self::NS_SVG ) {
106107 throw new MWException( "Expected <svg> tag, got ".
107 - $this->reader->name );
 108+ $this->reader->localName . " in NS " . $this->reader->namespaceURI );
108109 }
109110 $this->debug( "<svg> tag is correct." );
110111 $this->handleSVGAttribs();
@@ -111,18 +112,19 @@
112113 $exitDepth = $this->reader->depth;
113114 $keepReading = $this->reader->read();
114115 while ( $keepReading ) {
115 - $tag = $this->reader->name;
 116+ $tag = $this->reader->localName;
116117 $type = $this->reader->nodeType;
 118+ $isSVG = ($this->reader->namespaceURI == self::NS_SVG);
117119
118120 $this->debug( "$tag" );
119121
120 - if ( $this->qualifiedNameEquals( $tag, 'svg', 'svg' ) && $type == XmlReader::END_ELEMENT && $this->reader->depth <= $exitDepth ) {
 122+ if ( $isSVG && $tag == 'svg' && $type == XmlReader::END_ELEMENT && $this->reader->depth <= $exitDepth ) {
121123 break;
122 - } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'title' ) ) {
 124+ } elseif ( $isSVG && $tag == 'title' ) {
123125 $this->readField( $tag, 'title' );
124 - } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'desc' ) ) {
 126+ } elseif ( $isSVG && $tag == 'desc' ) {
125127 $this->readField( $tag, 'description' );
126 - } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'metadata' ) && $type == XmlReader::ELEMENT ) {
 128+ } elseif ( $isSVG && $tag == 'metadata' && $type == XmlReader::ELEMENT ) {
127129 $this->readXml( $tag, 'metadata' );
128130 } elseif ( $tag !== '#text' ) {
129131 $this->debug( "Unhandled top-level XML tag $tag" );
@@ -155,7 +157,7 @@
156158 }
157159 $keepReading = $this->reader->read();
158160 while( $keepReading ) {
159 - if( $this->reader->name == $name && $this->reader->nodeType == XmlReader::END_ELEMENT ) {
 161+ if( $this->reader->localName == $name && $this->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::END_ELEMENT ) {
160162 break;
161163 } elseif( $this->reader->nodeType == XmlReader::TEXT ){
162164 $this->metadata[$metafield] = trim( $this->reader->value );
@@ -175,7 +177,7 @@
176178 return;
177179 }
178180 // TODO: find and store type of xml snippet. metadata['metadataType'] = "rdf"
179 - $this->metadata[$metafield] = $this->reader->readInnerXML();
 181+ $this->metadata[$metafield] = trim( $this->reader->readInnerXML() );
180182 $this->reader->next();
181183 }
182184
@@ -195,21 +197,16 @@
196198 $exitDepth = $this->reader->depth;
197199 $keepReading = $this->reader->read();
198200 while( $keepReading ) {
199 - if( $this->reader->name == $name && $this->reader->depth <= $exitDepth
 201+ if( $this->reader->localName == $name && $this->reader->depth <= $exitDepth
200202 && $this->reader->nodeType == XmlReader::END_ELEMENT ) {
201203 break;
202 - } elseif ( $this->reader->nodeType == XmlReader::ELEMENT ) {
203 - switch( $this->reader->name ) {
 204+ } elseif ( $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::ELEMENT ) {
 205+ switch( $this->reader->localName ) {
204206 case 'animate':
205 - case 'svg:animate':
206207 case 'set':
207 - case 'svg:set':
208208 case 'animateMotion':
209 - case 'svg:animateMotion':
210209 case 'animateColor':
211 - case 'svg:animateColor':
212210 case 'animateTransform':
213 - case 'svg:animateTransform':
214211 $this->debug( "HOUSTON WE HAVE ANIMATION" );
215212 $this->metadata['animated'] = true;
216213 break;
@@ -318,22 +315,4 @@
319316 return floatval( $length );
320317 }
321318 }
322 -
323 - /**
324 - * XML namespace check
325 - *
326 - * Check if a read node name matches the expected nodeName
327 - * @param $qualifiedName as read by XMLReader
328 - * @param $prefix the namespace prefix that you expect for this element, defaults to svg namespace
329 - * @param $localName the localName part of the element that you want to match
330 - *
331 - * @return boolean
332 - */
333 - private function qualifiedNameEquals( $qualifiedName, $prefix="svg", $localName ) {
334 - if( ($qualifiedName == $localName && $prefix == "svg" ) ||
335 - $qualifiedName == ($prefix . ":" . $localName) ) {
336 - return true;
337 - }
338 - return false;
339 - }
340319 }
Index: branches/REL1_18/phase3/includes/FileDeleteForm.php
@@ -131,7 +131,6 @@
132132 $status = $file->delete( $reason, $suppress );
133133 if( $status->ok ) {
134134 $dbw->commit();
135 - wfRunHooks( 'ArticleDeleteComplete', array( &$article, &$wgUser, $reason, $id ) );
136135 } else {
137136 $dbw->rollback();
138137 }
Index: branches/REL1_18/phase3/includes/HttpFunctions.php
@@ -316,11 +316,26 @@
317317 }
318318
319319 /**
320 - * Set the callback
 320+ * Set a read callback to accept data read from the HTTP request.
 321+ * By default, data is appended to an internal buffer which can be
 322+ * retrieved through $req->getContent().
321323 *
 324+ * To handle data as it comes in -- especially for large files that
 325+ * would not fit in memory -- you can instead set your own callback,
 326+ * in the form function($resource, $buffer) where the first parameter
 327+ * is the low-level resource being read (implementation specific),
 328+ * and the second parameter is the data buffer.
 329+ *
 330+ * You MUST return the number of bytes handled in the buffer; if fewer
 331+ * bytes are reported handled than were passed to you, the HTTP fetch
 332+ * will be aborted.
 333+ *
322334 * @param $callback Callback
323335 */
324336 public function setCallback( $callback ) {
 337+ if ( !is_callable( $callback ) ) {
 338+ throw new MWException( 'Invalid MwHttpRequest callback' );
 339+ }
325340 $this->callback = $callback;
326341 }
327342
Index: branches/REL1_18/phase3/includes/Block.php
@@ -184,7 +184,7 @@
185185 * 2) A rangeblock encompasing the given IP (smallest first)
186186 * 3) An autoblock on the given IP
187187 * @param $vagueTarget User|String also search for blocks affecting this target. Doesn't
188 - * make any sense to use TYPE_AUTO / TYPE_ID here
 188+ * make any sense to use TYPE_AUTO / TYPE_ID here. Leave blank to skip IP lookups.
189189 * @return Bool whether a relevant block was found
190190 */
191191 protected function newLoad( $vagueTarget = null ) {
@@ -198,7 +198,8 @@
199199 $conds = array( 'ipb_address' => array() );
200200 }
201201
202 - if( $vagueTarget !== null ){
 202+ # Be aware that the != '' check is explicit, since empty values will be passed by some callers.
 203+ if( $vagueTarget != ''){
203204 list( $target, $type ) = self::parseTarget( $vagueTarget );
204205 switch( $type ) {
205206 case self::TYPE_USER:
@@ -962,7 +963,7 @@
963964 * 1.2.3.4 will not select 1.2.0.0/16 or even 1.2.3.4/32)
964965 * @param $vagueTarget String|User|Int as above, but we will search for *any* block which
965966 * affects that target (so for an IP address, get ranges containing that IP; and also
966 - * get any relevant autoblocks)
 967+ * get any relevant autoblocks). Leave empty or blank to skip IP-based lookups.
967968 * @param $fromMaster Bool whether to use the DB_MASTER database
968969 * @return Block|null (null if no relevant block could be found). The target and type
969970 * of the returned Block will refer to the actual block which was found, which might
@@ -973,8 +974,9 @@
974975 if( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ){
975976 return Block::newFromID( $target );
976977
977 - } elseif( $target === null && $vagueTarget === null ){
 978+ } elseif( $target === null && $vagueTarget == '' ){
978979 # We're not going to find anything useful here
 980+ # Be aware that the == '' check is explicit, since empty values will be passed by some callers.
979981 return null;
980982
981983 } elseif( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE, null ) ) ) {
Index: branches/REL1_18/phase3/includes/MessageBlobStore.php
@@ -117,49 +117,37 @@
118118 }
119119
120120 /**
121 - * Update all message blobs for a given module.
 121+ * Update the message blob for a given module in a given language
122122 *
123123 * @param $name String: module name
124124 * @param $module ResourceLoaderModule object
125 - * @param $lang String: language code (optional)
126 - * @return Mixed: if $lang is set, the new message blob for that language is
127 - * returned if present. Otherwise, null is returned.
 125+ * @param $lang String: language code
 126+ * @return String Regenerated message blob, or null if there was no blob for the given module/language pair
128127 */
129 - public static function updateModule( $name, ResourceLoaderModule $module, $lang = null ) {
130 - $retval = null;
131 -
132 - // Find all existing blobs for this module
 128+ public static function updateModule( $name, ResourceLoaderModule $module, $lang ) {
133129 $dbw = wfGetDB( DB_MASTER );
134 - $res = $dbw->select( 'msg_resource',
135 - array( 'mr_lang', 'mr_blob' ),
136 - array( 'mr_resource' => $name ),
 130+ $row = $dbw->selectRow( 'msg_resource', 'mr_blob',
 131+ array( 'mr_resource' => $name, 'mr_lang' => $lang ),
137132 __METHOD__
138133 );
139 -
140 - // Build the new msg_resource rows
141 - $newRows = array();
142 - $now = $dbw->timestamp();
143 - // Save the last-processed old and new blobs for later
144 - $oldBlob = $newBlob = null;
145 -
146 - foreach ( $res as $row ) {
147 - $oldBlob = $row->mr_blob;
148 - $newBlob = self::generateMessageBlob( $module, $row->mr_lang );
149 -
150 - if ( $row->mr_lang === $lang ) {
151 - $retval = $newBlob;
152 - }
153 - $newRows[] = array(
154 - 'mr_resource' => $name,
155 - 'mr_lang' => $row->mr_lang,
156 - 'mr_blob' => $newBlob,
157 - 'mr_timestamp' => $now
158 - );
 134+ if ( !$row ) {
 135+ return null;
159136 }
160137
 138+ // Save the old and new blobs for later
 139+ $oldBlob = $row->mr_blob;
 140+ $newBlob = self::generateMessageBlob( $module, $lang );
 141+
 142+ $newRow = array(
 143+ 'mr_resource' => $name,
 144+ 'mr_lang' => $lang,
 145+ 'mr_blob' => $newBlob,
 146+ 'mr_timestamp' => $dbw->timestamp()
 147+ );
 148+
161149 $dbw->replace( 'msg_resource',
162150 array( array( 'mr_resource', 'mr_lang' ) ),
163 - $newRows, __METHOD__
 151+ $newRow, __METHOD__
164152 );
165153
166154 // Figure out which messages were added and removed
@@ -192,7 +180,7 @@
193181 );
194182 }
195183
196 - return $retval;
 184+ return $newBlob;
197185 }
198186
199187 /**

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r88750* (bug 29116) Fix regression breaking CheckUser extension...brion21:04, 24 May 2011
r88870Reverting r82307 (bug 27465) as initial step to recommitting a cleaner fix.brion23:57, 25 May 2011
r88871* (bug 27465) Fix metadata extraction for SVG files using unusual namespace n...brion23:59, 25 May 2011
r89003* (bug 29174) Fix regression in upload-by-URL: files larger than PHP memory l...brion22:31, 27 May 2011
r89005Refactor MessageBlobStore::updateModule() to remove the multi-language update...catrope22:42, 27 May 2011
r89114Fix a regression from r63144: "Fixed bizarre $time comparison (compared displ...raymond15:43, 29 May 2011
r89115Followup r89114: Ctrl-S is your friend...raymond15:45, 29 May 2011
r89129Fix for r89114: handle other DBMSesaaron19:18, 29 May 2011
r89293'unblockself' right was never added to User::$mCoreRights...reedy21:44, 1 June 2011
r89345Fix regression in r84638, causing ArticleDeleteComplete to be called twice on...catrope15:42, 2 June 2011

Status & tagging log