Index: branches/REL1_17/phase3/includes/upload/UploadFromUrl.php |
— | — | @@ -97,41 +97,62 @@ |
98 | 98 | protected function makeTemporaryFile() { |
99 | 99 | return tempnam( wfTempDir(), 'URL' ); |
100 | 100 | } |
| 101 | + |
101 | 102 | /** |
102 | | - * Save the result of a HTTP request to the temporary file |
| 103 | + * Callback: save a chunk of the result of a HTTP request to the temporary file |
103 | 104 | * |
104 | | - * @param $req MWHttpRequest |
105 | | - * @return Status |
| 105 | + * @param $req mixed |
| 106 | + * @param $buffer string |
| 107 | + * @return int number of bytes handled |
106 | 108 | */ |
107 | | - private function saveTempFile( $req ) { |
108 | | - if ( $this->mTempPath === false ) { |
109 | | - return Status::newFatal( 'tmp-create-error' ); |
| 109 | + public function saveTempFileChunk( $req, $buffer ) { |
| 110 | + $nbytes = fwrite( $this->mTmpHandle, $buffer ); |
| 111 | + |
| 112 | + if ( $nbytes == strlen( $buffer ) ) { |
| 113 | + $this->mFileSize += $nbytes; |
| 114 | + } else { |
| 115 | + // Well... that's not good! |
| 116 | + fclose( $this->mTmpHandle ); |
| 117 | + $this->mTmpHandle = false; |
110 | 118 | } |
111 | | - if ( file_put_contents( $this->mTempPath, $req->getContent() ) === false ) { |
112 | | - return Status::newFatal( 'tmp-write-error' ); |
113 | | - } |
114 | 119 | |
115 | | - $this->mFileSize = filesize( $this->mTempPath ); |
| 120 | + return $nbytes; |
| 121 | + } |
116 | 122 | |
117 | | - return Status::newGood(); |
118 | | - } |
119 | 123 | /** |
120 | 124 | * Download the file, save it to the temporary file and update the file |
121 | 125 | * size and set $mRemoveTempFile to true. |
122 | 126 | */ |
123 | 127 | protected function reallyFetchFile() { |
| 128 | + if ( $this->mTempPath === false ) { |
| 129 | + return Status::newFatal( 'tmp-create-error' ); |
| 130 | + } |
| 131 | + |
| 132 | + // Note the temporary file should already be created by makeTemporaryFile() |
| 133 | + $this->mTmpHandle = fopen( $this->mTempPath, 'wb' ); |
| 134 | + if ( !$this->mTmpHandle ) { |
| 135 | + return Status::newFatal( 'tmp-create-error' ); |
| 136 | + } |
| 137 | + |
| 138 | + $this->mRemoveTempFile = true; |
| 139 | + $this->mFileSize = 0; |
| 140 | + |
124 | 141 | $req = MWHttpRequest::factory( $this->mUrl ); |
| 142 | + $req->setCallback( array( $this, 'saveTempFileChunk' ) ); |
125 | 143 | $status = $req->execute(); |
126 | 144 | |
127 | | - if ( !$status->isOk() ) { |
128 | | - return $status; |
| 145 | + if ( $this->mTmpHandle ) { |
| 146 | + // File got written ok... |
| 147 | + fclose( $this->mTmpHandle ); |
| 148 | + $this->mTmpHandle = null; |
| 149 | + } else { |
| 150 | + // We encountered a write error during the download... |
| 151 | + return Status::newFatal( 'tmp-write-error' ); |
129 | 152 | } |
130 | 153 | |
131 | | - $status = $this->saveTempFile( $req ); |
132 | | - if ( !$status->isGood() ) { |
| 154 | + if ( !$status->isOk() ) { |
133 | 155 | return $status; |
134 | 156 | } |
135 | | - $this->mRemoveTempFile = true; |
136 | 157 | |
137 | 158 | return $status; |
138 | 159 | } |
Index: branches/REL1_17/phase3/includes/LogEventsList.php |
— | — | @@ -482,8 +482,7 @@ |
483 | 483 | # Fall back to a blue contributions link |
484 | 484 | $revert = $this->skin->userToolLinks( 1, $title->getDBkey() ); |
485 | 485 | } |
486 | | - $ts = wfTimestamp( TS_UNIX, $row->log_timestamp ); |
487 | | - if( $ts < '20080129000000' ) { |
| 486 | + if( wfTimestamp( TS_MW, $row->log_timestamp ) < '20080129000000' ) { |
488 | 487 | # Suppress $comment from old entries (before 2008-01-29), |
489 | 488 | # not needed and can contain incorrect links |
490 | 489 | $comment = ''; |
Index: branches/REL1_17/phase3/includes/installer/Installer.php |
— | — | @@ -1143,7 +1143,13 @@ |
1144 | 1144 | break; |
1145 | 1145 | } |
1146 | 1146 | |
1147 | | - $text = Http::get( $url . $file, array( 'timeout' => 3 ) ); |
| 1147 | + try { |
| 1148 | + $text = Http::get( $url . $file, array( 'timeout' => 3 ) ); |
| 1149 | + } |
| 1150 | + catch( MWException $e ) { |
| 1151 | + // Http::get throws with allow_url_fopen = false and no curl extension. |
| 1152 | + $text = null; |
| 1153 | + } |
1148 | 1154 | unlink( $dir . $file ); |
1149 | 1155 | |
1150 | 1156 | if ( $text == 'exec' ) { |
Property changes on: branches/REL1_17/phase3/includes/installer/Installer.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1151 | 1157 | Merged /trunk/phase3/includes/installer/Installer.php:r88492,88870-88871,89003,89108,89114-89115,89129,89532,89653 |
Index: branches/REL1_17/phase3/includes/installer/DatabaseInstaller.php |
— | — | @@ -186,11 +186,6 @@ |
187 | 187 | $updater = DatabaseUpdater::newForDB( $this->db ); |
188 | 188 | $extensionUpdates = $updater->getNewExtensions(); |
189 | 189 | |
190 | | - // No extensions need tables (or haven't updated to new installer support) |
191 | | - if( !count( $extensionUpdates ) ) { |
192 | | - return $status; |
193 | | - } |
194 | | - |
195 | 190 | $ourExtensions = array_map( 'strtolower', $this->getVar( '_Extensions' ) ); |
196 | 191 | |
197 | 192 | foreach( $ourExtensions as $ext ) { |
Property changes on: branches/REL1_17/phase3/includes/installer/DatabaseInstaller.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
198 | 193 | Merged /trunk/phase3/includes/installer/DatabaseInstaller.php:r88492,88870-88871,89003,89108,89114-89115,89129,89532,89653 |
Index: branches/REL1_17/phase3/includes/installer/CliInstaller.php |
— | — | @@ -88,7 +88,7 @@ |
89 | 89 | * Main entry point. |
90 | 90 | */ |
91 | 91 | public function execute() { |
92 | | - $vars = $this->getExistingLocalSettings(); |
| 92 | + $vars = Installer::getExistingLocalSettings(); |
93 | 93 | if( $vars ) { |
94 | 94 | $this->showStatusMessage( |
95 | 95 | Status::newFatal( "config-localsettings-cli-upgrade" ) |
Property changes on: branches/REL1_17/phase3/includes/installer/CliInstaller.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
96 | 96 | Merged /trunk/phase3/includes/installer/CliInstaller.php:r88492,88870-88871,89003,89108,89114-89115,89129,89532,89653 |
Index: branches/REL1_17/phase3/includes/media/SVGMetadataExtractor.php |
— | — | @@ -35,6 +35,7 @@ |
36 | 36 | class SVGReader { |
37 | 37 | const DEFAULT_WIDTH = 512; |
38 | 38 | const DEFAULT_HEIGHT = 512; |
| 39 | + const NS_SVG = 'http://www.w3.org/2000/svg'; |
39 | 40 | |
40 | 41 | private $reader = null; |
41 | 42 | private $mDebug = false; |
— | — | @@ -101,9 +102,9 @@ |
102 | 103 | $keepReading = $this->reader->read(); |
103 | 104 | } |
104 | 105 | |
105 | | - if ( !$this->qualifiedNameEquals( $this->reader->name, 'svg', 'svg' ) ) { |
| 106 | + if ( $this->reader->localName != 'svg' || $this->reader->namespaceURI != self::NS_SVG ) { |
106 | 107 | throw new MWException( "Expected <svg> tag, got ". |
107 | | - $this->reader->name ); |
| 108 | + $this->reader->localName . " in NS " . $this->reader->namespaceURI ); |
108 | 109 | } |
109 | 110 | $this->debug( "<svg> tag is correct." ); |
110 | 111 | $this->handleSVGAttribs(); |
— | — | @@ -111,18 +112,19 @@ |
112 | 113 | $exitDepth = $this->reader->depth; |
113 | 114 | $keepReading = $this->reader->read(); |
114 | 115 | while ( $keepReading ) { |
115 | | - $tag = $this->reader->name; |
| 116 | + $tag = $this->reader->localName; |
116 | 117 | $type = $this->reader->nodeType; |
| 118 | + $isSVG = ($this->reader->namespaceURI == self::NS_SVG); |
117 | 119 | |
118 | 120 | $this->debug( "$tag" ); |
119 | 121 | |
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 ) { |
121 | 123 | break; |
122 | | - } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'title' ) ) { |
| 124 | + } elseif ( $isSVG && $tag == 'title' ) { |
123 | 125 | $this->readField( $tag, 'title' ); |
124 | | - } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'desc' ) ) { |
| 126 | + } elseif ( $isSVG && $tag == 'desc' ) { |
125 | 127 | $this->readField( $tag, 'description' ); |
126 | | - } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'metadata' ) && $type == XmlReader::ELEMENT ) { |
| 128 | + } elseif ( $isSVG && $tag == 'metadata' && $type == XmlReader::ELEMENT ) { |
127 | 129 | $this->readXml( $tag, 'metadata' ); |
128 | 130 | } elseif ( $tag !== '#text' ) { |
129 | 131 | $this->debug( "Unhandled top-level XML tag $tag" ); |
— | — | @@ -153,7 +155,7 @@ |
154 | 156 | } |
155 | 157 | $keepReading = $this->reader->read(); |
156 | 158 | while( $keepReading ) { |
157 | | - if( $this->reader->name == $name && $this->reader->nodeType == XmlReader::END_ELEMENT ) { |
| 159 | + if( $this->reader->localName == $name && $this->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::END_ELEMENT ) { |
158 | 160 | break; |
159 | 161 | } elseif( $this->reader->nodeType == XmlReader::TEXT ){ |
160 | 162 | $this->metadata[$metafield] = trim( $this->reader->value ); |
— | — | @@ -173,7 +175,7 @@ |
174 | 176 | return; |
175 | 177 | } |
176 | 178 | // TODO: find and store type of xml snippet. metadata['metadataType'] = "rdf" |
177 | | - $this->metadata[$metafield] = $this->reader->readInnerXML(); |
| 179 | + $this->metadata[$metafield] = trim( $this->reader->readInnerXML() ); |
178 | 180 | $this->reader->next(); |
179 | 181 | } |
180 | 182 | |
— | — | @@ -190,21 +192,16 @@ |
191 | 193 | $exitDepth = $this->reader->depth; |
192 | 194 | $keepReading = $this->reader->read(); |
193 | 195 | while( $keepReading ) { |
194 | | - if( $this->reader->name == $name && $this->reader->depth <= $exitDepth |
| 196 | + if( $this->reader->localName == $name && $this->reader->depth <= $exitDepth |
195 | 197 | && $this->reader->nodeType == XmlReader::END_ELEMENT ) { |
196 | 198 | break; |
197 | | - } elseif ( $this->reader->nodeType == XmlReader::ELEMENT ) { |
198 | | - switch( $this->reader->name ) { |
| 199 | + } elseif ( $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::ELEMENT ) { |
| 200 | + switch( $this->reader->localName ) { |
199 | 201 | case 'animate': |
200 | | - case 'svg:animate': |
201 | 202 | case 'set': |
202 | | - case 'svg:set': |
203 | 203 | case 'animateMotion': |
204 | | - case 'svg:animateMotion': |
205 | 204 | case 'animateColor': |
206 | | - case 'svg:animateColor': |
207 | 205 | case 'animateTransform': |
208 | | - case 'svg:animateTransform': |
209 | 206 | $this->debug( "HOUSTON WE HAVE ANIMATION" ); |
210 | 207 | $this->metadata['animated'] = true; |
211 | 208 | break; |
— | — | @@ -313,22 +310,4 @@ |
314 | 311 | return floatval( $length ); |
315 | 312 | } |
316 | 313 | } |
317 | | - |
318 | | - /** |
319 | | - * XML namespace check |
320 | | - * |
321 | | - * Check if a read node name matches the expected nodeName |
322 | | - * @param $qualifiedName as read by XMLReader |
323 | | - * @param $prefix the namespace prefix that you expect for this element, defaults to svg namespace |
324 | | - * @param $localName the localName part of the element that you want to match |
325 | | - * |
326 | | - * @return boolean |
327 | | - */ |
328 | | - private function qualifiedNameEquals( $qualifiedName, $prefix="svg", $localName ) { |
329 | | - if( ($qualifiedName == $localName && $prefix == "svg" ) || |
330 | | - $qualifiedName == ($prefix . ":" . $localName) ) { |
331 | | - return true; |
332 | | - } |
333 | | - return false; |
334 | | - } |
335 | 314 | } |
Index: branches/REL1_17/phase3/includes/HttpFunctions.php |
— | — | @@ -307,11 +307,26 @@ |
308 | 308 | } |
309 | 309 | |
310 | 310 | /** |
311 | | - * Set the callback |
| 311 | + * Set a read callback to accept data read from the HTTP request. |
| 312 | + * By default, data is appended to an internal buffer which can be |
| 313 | + * retrieved through $req->getContent(). |
312 | 314 | * |
| 315 | + * To handle data as it comes in -- especially for large files that |
| 316 | + * would not fit in memory -- you can instead set your own callback, |
| 317 | + * in the form function($resource, $buffer) where the first parameter |
| 318 | + * is the low-level resource being read (implementation specific), |
| 319 | + * and the second parameter is the data buffer. |
| 320 | + * |
| 321 | + * You MUST return the number of bytes handled in the buffer; if fewer |
| 322 | + * bytes are reported handled than were passed to you, the HTTP fetch |
| 323 | + * will be aborted. |
| 324 | + * |
313 | 325 | * @param $callback Callback |
314 | 326 | */ |
315 | 327 | public function setCallback( $callback ) { |
| 328 | + if ( !is_callable( $callback ) ) { |
| 329 | + throw new MWException( 'Invalid MwHttpRequest callback' ); |
| 330 | + } |
316 | 331 | $this->callback = $callback; |
317 | 332 | } |
318 | 333 | |
Index: branches/REL1_17/phase3/includes/specials/SpecialUserlogin.php |
— | — | @@ -148,7 +148,7 @@ |
149 | 149 | global $wgOut; |
150 | 150 | |
151 | 151 | if ( $this->mEmail == '' ) { |
152 | | - $this->mainLoginForm( wfMsgExt( 'noemailcreate', array( 'parsemag', 'escape' ), $this->mName ) ); |
| 152 | + $this->mainLoginForm( wfMsgExt( 'noemailcreate', array( 'parsemag', 'escape' ) ) ); |
153 | 153 | return; |
154 | 154 | } |
155 | 155 | |