Index: trunk/extensions/ExtensionDistributor/ExtensionDistributor_body.php |
— | — | @@ -1,13 +1,18 @@ |
2 | 2 | <?php |
3 | 3 | |
| 4 | +/** |
| 5 | + * Special page that allows users to download extensions as tar archives. |
| 6 | + * |
| 7 | + * @author Tim Starling |
| 8 | + */ |
4 | 9 | class ExtensionDistributorPage extends SpecialPage { |
5 | | - var $extensionList; // cached list of extensions |
| 10 | + protected $extensionList; // cached list of extensions |
6 | 11 | |
7 | | - function __construct() { |
| 12 | + public function __construct() { |
8 | 13 | parent::__construct( 'ExtensionDistributor' ); |
9 | 14 | } |
10 | 15 | |
11 | | - function execute( $subpage ) { |
| 16 | + public function execute( $subpage ) { |
12 | 17 | global $wgExtDistTarDir, $wgExtDistWorkingCopy, $wgOut, $wgRequest; |
13 | 18 | |
14 | 19 | $this->setHeaders(); |
— | — | @@ -19,9 +24,11 @@ |
20 | 25 | |
21 | 26 | if ( $subpage ) { |
22 | 27 | $parts = explode( '/', $subpage, 2 ); |
| 28 | + |
23 | 29 | if ( count( $parts ) == 1 ) { |
24 | 30 | $parts[] = false; |
25 | 31 | } |
| 32 | + |
26 | 33 | list( $extension, $version ) = $parts; |
27 | 34 | } else { |
28 | 35 | $extension = $wgRequest->getVal( 'extdist_extension' ); |
— | — | @@ -53,7 +60,7 @@ |
54 | 61 | $this->doDownload( $extension, $version ); |
55 | 62 | } |
56 | 63 | |
57 | | - function getExtensionList() { |
| 64 | + protected function getExtensionList() { |
58 | 65 | global $wgExtDistWorkingCopy, $wgExtDistBranches; |
59 | 66 | |
60 | 67 | if ( isset( $this->extensionList ) ) { |
— | — | @@ -61,36 +68,46 @@ |
62 | 69 | } |
63 | 70 | |
64 | 71 | $this->extensionList = array(); |
| 72 | + |
65 | 73 | foreach ( $wgExtDistBranches as $branchPath => $branch ) { |
66 | 74 | $wc = "$wgExtDistWorkingCopy/$branchPath/extensions"; |
67 | 75 | $dir = opendir( $wc ); |
| 76 | + |
68 | 77 | if ( !$dir ) { |
69 | 78 | return false; |
70 | 79 | } |
71 | 80 | |
72 | 81 | $this->extensionList[$branchPath] = array(); |
| 82 | + |
73 | 83 | while ( false !== ( $file = readdir( $dir ) ) ) { |
74 | 84 | if ( substr( $file, 0, 1 ) == '.' ) { |
75 | 85 | continue; |
76 | 86 | } |
| 87 | + |
77 | 88 | if ( !is_dir( "$wc/$file" ) ) { |
78 | 89 | continue; |
79 | 90 | } |
| 91 | + |
80 | 92 | if ( file_exists( "$wc/$file/NO-DIST" ) ) { |
81 | 93 | continue; |
82 | 94 | } |
| 95 | + |
83 | 96 | $this->extensionList[$branchPath][] = $file; |
84 | 97 | } |
| 98 | + |
85 | 99 | natcasesort( $this->extensionList[$branchPath] ); |
86 | 100 | } |
| 101 | + |
87 | 102 | return $this->extensionList; |
88 | 103 | } |
89 | 104 | |
90 | | - function getBranchName( $path ) { |
| 105 | + protected function getBranchName( $path ) { |
91 | 106 | global $wgExtDistBranches; |
| 107 | + |
92 | 108 | if ( !isset( $wgExtDistBranches[$path] ) ) { |
93 | 109 | return false; |
94 | 110 | } |
| 111 | + |
95 | 112 | if ( isset( $wgExtDistBranches[$path]['msgName'] ) ) { |
96 | 113 | return wfMsg( $wgExtDistBranches[$path]['msgName'] ); |
97 | 114 | } else { |
— | — | @@ -98,14 +115,16 @@ |
99 | 116 | } |
100 | 117 | } |
101 | 118 | |
102 | | - function showExtensionSelector() { |
| 119 | + protected function showExtensionSelector() { |
103 | 120 | global $wgOut; |
104 | 121 | |
105 | 122 | $extensions = $this->getExtensionList(); |
| 123 | + |
106 | 124 | if ( $extensions === false ) { |
107 | 125 | $wgOut->addWikiMsg( 'extdist-wc-missing' ); |
108 | 126 | return; |
109 | 127 | } |
| 128 | + |
110 | 129 | if ( !$extensions['trunk'] ) { |
111 | 130 | $wgOut->addWikiMsg( 'extdist-wc-empty' ); |
112 | 131 | return; |
— | — | @@ -131,11 +150,13 @@ |
132 | 151 | ); |
133 | 152 | } |
134 | 153 | |
135 | | - function showVersionSelector( $extensionName ) { |
| 154 | + protected function showVersionSelector( $extensionName ) { |
136 | 155 | global $wgOut, $wgExtDistBranches; |
| 156 | + |
137 | 157 | $extensions = $this->getExtensionList(); |
138 | 158 | |
139 | 159 | $versions = array(); |
| 160 | + |
140 | 161 | foreach ( $wgExtDistBranches as $branchPath => $branch ) { |
141 | 162 | if ( !in_array( $extensionName, $extensions[$branchPath] ) ) { |
142 | 163 | continue; |
— | — | @@ -146,6 +167,7 @@ |
147 | 168 | } else { |
148 | 169 | $branchName = $branch['name']; |
149 | 170 | } |
| 171 | + |
150 | 172 | $versions[$branchPath] = $branchName; |
151 | 173 | } |
152 | 174 | |
— | — | @@ -171,6 +193,7 @@ |
172 | 194 | |
173 | 195 | $selected++; |
174 | 196 | } |
| 197 | + |
175 | 198 | $wgOut->addHTML( |
176 | 199 | Xml::closeElement( 'select' ) . ' ' . |
177 | 200 | Xml::submitButton( wfMsg( 'extdist-submit-version' ), array( 'name' => 'extdist_submit' ) ) . |
— | — | @@ -178,7 +201,7 @@ |
179 | 202 | ); |
180 | 203 | } |
181 | 204 | |
182 | | - function doDownload( $extension, $version ) { |
| 205 | + protected function doDownload( $extension, $version ) { |
183 | 206 | global $wgExtDistWorkingCopy, $wgExtDistTarDir, $wgExtDistBranches, |
184 | 207 | $wgOut, $wgExtDistTarUrl, $wgExtDistRemoteClient; |
185 | 208 | |
— | — | @@ -187,18 +210,19 @@ |
188 | 211 | } else { |
189 | 212 | $rev = $this->updateAndGetRevisionLocal( $extension, $version ); |
190 | 213 | } |
| 214 | + |
191 | 215 | if ( $rev === false ) { |
192 | 216 | // Error already displayed |
193 | 217 | return; |
194 | 218 | } |
195 | 219 | |
196 | | - // Determine tar name |
| 220 | + // Determine tar name. |
197 | 221 | $cleanName = str_replace( '/', '_', $extension ); |
198 | 222 | $versionName = $wgExtDistBranches[$version]['tarLabel']; |
199 | 223 | $tarName = "$cleanName-$versionName-r$rev.tar.gz"; |
200 | 224 | $tarFile = "$wgExtDistTarDir/$tarName"; |
201 | 225 | |
202 | | - // Create it if it doesn't exist |
| 226 | + // Create the archive if it doesn't exist. |
203 | 227 | if ( !file_exists( $tarFile ) ) { |
204 | 228 | // Does the tar file need ExtensionFunctions.php? |
205 | 229 | $dir = "$wgExtDistWorkingCopy/$version/extensions/$extension"; |
— | — | @@ -207,15 +231,17 @@ |
208 | 232 | wfShellExec( "grep -q '\bExtensionFunctions' " . $files, $retval ); |
209 | 233 | $needEF = !$retval; |
210 | 234 | |
211 | | - // Create the archive |
| 235 | + // Create the archive. |
212 | 236 | $cmd = 'tar -czf ' . wfEscapeShellArg( $tarFile ) . |
213 | 237 | ' --exclude \'*/.svn*\'' . |
214 | 238 | ' -C ' . wfEscapeShellArg( "$wgExtDistWorkingCopy/$version/extensions" ) . |
215 | 239 | ' ' . wfEscapeShellArg( $extension ) . |
216 | 240 | ( $needEF ? ' ExtensionFunctions.php' : '' ) . |
217 | 241 | ' 2>&1'; |
| 242 | + |
218 | 243 | $retval = - 1; |
219 | 244 | $result = wfShellExec( $cmd, $retval ); |
| 245 | + |
220 | 246 | if ( $retval ) { |
221 | 247 | $wgOut->addWikiMsg( 'extdist-tar-error', $retval ); |
222 | 248 | $wgOut->addHTML( '<pre>' . htmlspecialchars( $result ) . '</pre>' ); |
— | — | @@ -236,13 +262,17 @@ |
237 | 263 | header( 'Refresh: 5;' . $url ); |
238 | 264 | } |
239 | 265 | |
240 | | - function updateAndGetRevisionLocal( $extension, $version ) { |
| 266 | + protected function updateAndGetRevisionLocal( $extension, $version ) { |
241 | 267 | global $wgExtDistWorkingCopy, $wgOut; |
| 268 | + |
242 | 269 | // svn up |
243 | 270 | $dir = "$wgExtDistWorkingCopy/$version/extensions/$extension"; |
| 271 | + |
244 | 272 | $cmd = "svn up --non-interactive " . wfEscapeShellArg( $dir ) . " 2>&1"; |
245 | 273 | $retval = - 1; |
| 274 | + |
246 | 275 | $result = wfShellExec( $cmd, $retval ); |
| 276 | + |
247 | 277 | if ( $retval ) { |
248 | 278 | $wgOut->addWikiMsg( 'extdist-svn-error', $result ); |
249 | 279 | return false; |
— | — | @@ -252,6 +282,7 @@ |
253 | 283 | $cmd = "svn info --non-interactive --xml " . wfEscapeShellArg( $dir ); |
254 | 284 | $retval = - 1; |
255 | 285 | $result = wfShellExec( $cmd, $retval ); |
| 286 | + |
256 | 287 | if ( $retval ) { |
257 | 288 | $wgOut->addWikiMsg( 'extdist-svn-error', $result ); |
258 | 289 | return false; |
— | — | @@ -259,6 +290,7 @@ |
260 | 291 | |
261 | 292 | $sx = new SimpleXMLElement( $result ); |
262 | 293 | $rev = $sx->entry->commit['revision']; |
| 294 | + |
263 | 295 | if ( !$rev || strpos( $rev, '/' ) !== false || strpos( $rev, "\000" ) !== false ) { |
264 | 296 | $wgOut->addWikiMsg( 'extdist-svn-parse-error', $result ); |
265 | 297 | return false; |
— | — | @@ -267,12 +299,16 @@ |
268 | 300 | return $rev; |
269 | 301 | } |
270 | 302 | |
271 | | - function updateAndGetRevisionRemote( $extension, $version ) { |
| 303 | + protected function updateAndGetRevisionRemote( $extension, $version ) { |
272 | 304 | global $wgExtDistRemoteClient, $wgOut; |
| 305 | + |
273 | 306 | $cmd = json_encode( array( 'extension' => $extension, 'version' => $version ) ); |
274 | 307 | $cmd = str_replace( "\000", '', $cmd ); |
| 308 | + |
275 | 309 | list( $host, $port ) = explode( ':', $wgExtDistRemoteClient, 2 ); |
| 310 | + |
276 | 311 | $sock = fsockopen( $host, $port ); |
| 312 | + |
277 | 313 | if ( !$sock ) { |
278 | 314 | $wgOut->addWikiMsg( 'extdist-no-remote' ); |
279 | 315 | return false; |
— | — | @@ -285,15 +321,19 @@ |
286 | 322 | fclose( $sock ); |
287 | 323 | |
288 | 324 | $response = json_decode( $encResponse ); |
| 325 | + |
289 | 326 | if ( isset( $response->error ) ) { |
290 | 327 | $info = isset( $response->errorInfo ) ? $response->errorInfo : ''; |
291 | 328 | $wgOut->addWikiMsg( $response->error, $info ); |
292 | 329 | return false; |
293 | 330 | } |
| 331 | + |
294 | 332 | if ( !isset( $response->revision ) ) { |
295 | 333 | $wgOut->addWikiMsg( 'extdist-remote-invalid-response' ); |
296 | 334 | return false; |
297 | 335 | } |
| 336 | + |
298 | 337 | return $response->revision; |
299 | 338 | } |
300 | | -} |
| 339 | + |
| 340 | +} |
\ No newline at end of file |