Index: trunk/extensions/ExtensionDistributor/svn-invoker.php |
— | — | @@ -0,0 +1,95 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Subversion invoker for inetd |
| 6 | + */ |
| 7 | + |
| 8 | +if ( php_sapi_name() !== 'cli' ) { |
| 9 | + echo "This script can only be run from the command line\n"; |
| 10 | + exit( 1 ); |
| 11 | +} |
| 12 | + |
| 13 | +$wgExtDistWorkingCopy = '/home/wikipedia/ExtensionDistributor/mw-snapshot'; |
| 14 | +svnExecute(); |
| 15 | + |
| 16 | +function svnValidate( $s ) { |
| 17 | + if ( strpos( $s, '..' ) !== false ) { |
| 18 | + return false; |
| 19 | + } |
| 20 | + return true; |
| 21 | +} |
| 22 | + |
| 23 | +function svnShellExec( $cmd, &$retval ) { |
| 24 | + $retval = 1; // error by default? |
| 25 | + ob_start(); |
| 26 | + passthru( $cmd, $retval ); |
| 27 | + $output = ob_get_contents(); |
| 28 | + ob_end_clean(); |
| 29 | +} |
| 30 | + |
| 31 | +function svnError( $msg, $info = false ) { |
| 32 | + echo json_encode( array( 'error' => $msg, 'errorInfo' => $info ) ); |
| 33 | +} |
| 34 | + |
| 35 | +function svnExecute() { |
| 36 | + global $wgExtDistWorkingCopy; |
| 37 | + |
| 38 | + $encCommand = ''; |
| 39 | + $done = false; |
| 40 | + while ( !$done && STDIN && !feof( STDIN ) ) { |
| 41 | + $buf = fread( STDIN, 8192 ); |
| 42 | + $nullPos = strpos( $buf, "\000" ); |
| 43 | + if ( $nullPos !== false ) { |
| 44 | + $buf = substr( $buf, 0, $nullPos ); |
| 45 | + $done = true; |
| 46 | + } |
| 47 | + $encCommand .= $buf; |
| 48 | + } |
| 49 | + if ( !$encCommand ) { |
| 50 | + svnError( 'extdist-remote-error', "Invalid command." ); |
| 51 | + return; |
| 52 | + } |
| 53 | + |
| 54 | + $command = json_decode( $encCommand ); |
| 55 | + if ( !isset( $command->version ) || !isset( $command->extension ) ) { |
| 56 | + svnError( 'extdist-remote-error', "Missing version or extension parameter." ); |
| 57 | + return; |
| 58 | + } |
| 59 | + if ( !svnValidate( $command->version ) ) { |
| 60 | + svnError( 'extdist-remote-error', "Invalid version parameter" ); |
| 61 | + return; |
| 62 | + } elseif ( !svnValidate( $command->extension ) ) { |
| 63 | + svnError( 'extdist-remote-error', "Invalid extension parameter" ); |
| 64 | + return; |
| 65 | + } |
| 66 | + $version = $command->version; |
| 67 | + $extension = $command->extension; |
| 68 | + |
| 69 | + // svn up |
| 70 | + $dir = "$wgExtDistWorkingCopy/$version/extensions/$extension"; |
| 71 | + $cmd = "svn up --non-interactive " . escapeshellarg( $dir ) . " 2>&1"; |
| 72 | + $retval = -1; |
| 73 | + $result = svnShellExec( $cmd, $retval ); |
| 74 | + if ( $retval ) { |
| 75 | + svnError( 'extdist-svn-error', $result ); |
| 76 | + return; |
| 77 | + } |
| 78 | + |
| 79 | + // Determine last changed revision |
| 80 | + $cmd = "svn info --non-interactive --xml " . escapeshellarg( $dir ); |
| 81 | + $retval = -1; |
| 82 | + $result = svnShellExec( $cmd, $retval ); |
| 83 | + if ( $retval ) { |
| 84 | + svnError( 'extdist-svn-error', $result ); |
| 85 | + return; |
| 86 | + } |
| 87 | + |
| 88 | + $sx = new SimpleXMLElement( $result ); |
| 89 | + $rev = $sx->entry->commit['revision']; |
| 90 | + if ( !$rev || strpos( $rev, '/' ) !== false || strpos( $rev, "\000" ) !== false ) { |
| 91 | + svnError( 'extdist-svn-parse-error', $result ); |
| 92 | + return; |
| 93 | + } |
| 94 | + |
| 95 | + echo json_encode( array( 'revision' => $rev ) ); |
| 96 | +} |
Property changes on: trunk/extensions/ExtensionDistributor/svn-invoker.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 97 | + native |
Index: trunk/extensions/ExtensionDistributor/ExtensionDistributor_body.php |
— | — | @@ -173,37 +173,18 @@ |
174 | 174 | "</form>\n" |
175 | 175 | ); |
176 | 176 | } |
177 | | - |
| 177 | + |
178 | 178 | function doDownload( $extension, $version ) { |
179 | 179 | global $wgExtDistWorkingCopy, $wgExtDistTarDir, $wgExtDistBranches, |
180 | | - $wgOut, $wgExtDistTarUrl; |
181 | | - |
182 | | - // svn up |
183 | | - $dir = "$wgExtDistWorkingCopy/$version/extensions/$extension"; |
184 | | - $cmd = "svn up --non-interactive " . wfEscapeShellArg( $dir ) . " 2>&1"; |
185 | | - $retval = -1; |
186 | | - $result = wfShellExec( $cmd, $retval ); |
187 | | - if ( $retval ) { |
188 | | - $wgOut->addWikiMsg( 'extdist-svn-error', $retval ); |
189 | | - $wgOut->addHTML( '<pre>' . htmlspecialchars( $result ) . '</pre>' ); |
190 | | - return; |
191 | | - } |
| 180 | + $wgOut, $wgExtDistTarUrl, $wgExtDistRemoteClient; |
192 | 181 | |
193 | | - // Determine last changed revision |
194 | | - $cmd = "svn info --non-interactive --xml " . wfEscapeShellArg( $dir ); |
195 | | - $retval = -1; |
196 | | - $result = wfShellExec( $cmd, $retval ); |
197 | | - if ( $retval ) { |
198 | | - $wgOut->addWikiMsg( 'extdist-svn-error', $retval ); |
199 | | - $wgOut->addHTML( '<pre>' . htmlspecialchars( $result ) . '</pre>' ); |
200 | | - return; |
| 182 | + if ( $wgExtDistRemoteClient ) { |
| 183 | + $rev = $this->updateAndGetRevisionRemote( $extension, $version ); |
| 184 | + } else { |
| 185 | + $rev = $this->updateAndGetRevisionLocal( $extension, $version ); |
201 | 186 | } |
202 | | - |
203 | | - $sx = new SimpleXMLElement( $result ); |
204 | | - $rev = $sx->entry->commit['revision']; |
205 | | - if ( !$rev || strpos( $rev, '/' ) !== false || strpos( $rev, "\000" ) !== false ) { |
206 | | - $wgOut->addWikiMsg( 'extdist-svn-parse-error' ); |
207 | | - $wgOut->addHTML( '<pre>' . htmlspecialchars( $result ) . '</pre>' ); |
| 187 | + if ( $rev === false ) { |
| 188 | + // Error already displayed |
208 | 189 | return; |
209 | 190 | } |
210 | 191 | |
— | — | @@ -216,6 +197,7 @@ |
217 | 198 | // Create it if it doesn't exist |
218 | 199 | if ( !file_exists( $tarFile ) ) { |
219 | 200 | // Does the tar file need ExtensionFunctions.php? |
| 201 | + $dir = "$wgExtDistWorkingCopy/$version/extensions/$extension"; |
220 | 202 | $retval = -1; |
221 | 203 | $files = call_user_func_array( 'wfEscapeShellArg', glob( "$dir/*.php" ) ); |
222 | 204 | wfShellExec( "grep -q ExtensionFunctions " . $files, $retval ); |
— | — | @@ -249,4 +231,66 @@ |
250 | 232 | // Redirect to the file |
251 | 233 | header( 'Refresh: 5;' . $url ); |
252 | 234 | } |
| 235 | + |
| 236 | + function updateAndGetRevisionLocal( $extension, $version ) { |
| 237 | + global $wgExtDistWorkingCopy, $wgOut; |
| 238 | + // svn up |
| 239 | + $dir = "$wgExtDistWorkingCopy/$version/extensions/$extension"; |
| 240 | + $cmd = "svn up --non-interactive " . wfEscapeShellArg( $dir ) . " 2>&1"; |
| 241 | + $retval = -1; |
| 242 | + $result = wfShellExec( $cmd, $retval ); |
| 243 | + if ( $retval ) { |
| 244 | + $wgOut->addWikiMsg( 'extdist-svn-error', $result ); |
| 245 | + return false; |
| 246 | + } |
| 247 | + |
| 248 | + // Determine last changed revision |
| 249 | + $cmd = "svn info --non-interactive --xml " . wfEscapeShellArg( $dir ); |
| 250 | + $retval = -1; |
| 251 | + $result = wfShellExec( $cmd, $retval ); |
| 252 | + if ( $retval ) { |
| 253 | + $wgOut->addWikiMsg( 'extdist-svn-error', $result ); |
| 254 | + return false; |
| 255 | + } |
| 256 | + |
| 257 | + $sx = new SimpleXMLElement( $result ); |
| 258 | + $rev = $sx->entry->commit['revision']; |
| 259 | + if ( !$rev || strpos( $rev, '/' ) !== false || strpos( $rev, "\000" ) !== false ) { |
| 260 | + $wgOut->addWikiMsg( 'extdist-svn-parse-error', $result ); |
| 261 | + return false; |
| 262 | + } |
| 263 | + |
| 264 | + return $rev; |
| 265 | + } |
| 266 | + |
| 267 | + function updateAndGetRevisionRemote( $extension, $version ) { |
| 268 | + global $wgExtDistRemoteClient, $wgOut; |
| 269 | + $cmd = json_encode( array( 'extension' => $extension, 'version' => $version ) ); |
| 270 | + $cmd = str_replace( "\000", '', $cmd ); |
| 271 | + list( $host, $port ) = explode( ':', $wgExtDistRemoteClient, 2 ); |
| 272 | + $sock = fsockopen( $host, $port ); |
| 273 | + if ( !$sock ) { |
| 274 | + $wgOut->addWikiMsg( 'extdist-no-remote' ); |
| 275 | + return false; |
| 276 | + } |
| 277 | + |
| 278 | + fwrite( $sock, $cmd . "\000\000\000" ); |
| 279 | + $encReponse = ''; |
| 280 | + while ( $sock && !feof( $sock ) ) { |
| 281 | + $encResponse .= fread( $sock, 8192 ); |
| 282 | + } |
| 283 | + fclose( $sock ); |
| 284 | + |
| 285 | + $response = json_decode( $encResponse ); |
| 286 | + if ( isset( $response->error ) ) { |
| 287 | + $info = isset( $response->errorInfo ) ? $response->errorInfo : ''; |
| 288 | + $wgOut->addWikiMsg( $response->error, $info ); |
| 289 | + return false; |
| 290 | + } |
| 291 | + if ( !isset( $response->revision ) ) { |
| 292 | + $wgOut->addWikiMsg( 'extdist-remote-invalid-response' ); |
| 293 | + return false; |
| 294 | + } |
| 295 | + return $response->revision; |
| 296 | + } |
253 | 297 | } |
Index: trunk/extensions/ExtensionDistributor/ExtensionDistributor.i18n.php |
— | — | @@ -19,8 +19,11 @@ |
20 | 20 | Most extensions work across multiple versions of MediaWiki, so if your MediaWiki version is not here, or if you have a need for the latest extension features, try using the current version.', |
21 | 21 | 'extdist-no-versions' => 'The selected extension ($1) is not available in any version!', |
22 | 22 | 'extdist-submit-version' => 'Continue', |
23 | | - 'extdist-svn-error' => 'Subversion returned exit code $1:', |
24 | | - 'extdist-svn-parse-error' => 'Unable to process the XML from "svn info"', |
| 23 | + 'extdist-no-remote' => 'Unable to contact remote subversion client.', |
| 24 | + 'extdist-remote-error' => 'Error from remote subversion client: <pre>$1</pre>', |
| 25 | + 'extdist-remote-invalid-response' => 'Invalid response from remote subversion client.', |
| 26 | + 'extdist-svn-error' => 'Subversion encountered an error: <pre>$1</pre>', |
| 27 | + 'extdist-svn-parse-error' => 'Unable to process the XML from "svn info": <pre>$1</pre>', |
25 | 28 | 'extdist-tar-error' => 'Tar returned exit code $1:', |
26 | 29 | 'extdist-created' => "A snapshot of version <b>$2</b> of the <b>$1</b> extension for MediaWiki <b>$3</b> has been created. Your download should start automatically in 5 seconds. |
27 | 30 | |
Index: trunk/extensions/ExtensionDistributor/ExtensionDistributor.php |
— | — | @@ -39,6 +39,9 @@ |
40 | 40 | ), |
41 | 41 | ); |
42 | 42 | |
| 43 | +/** Remote socket for svn-invoker.php (optional) */ |
| 44 | +$wgExtDistRemoteClient = false; |
| 45 | + |
43 | 46 | /******************** |
44 | 47 | * Registration |
45 | 48 | */ |