e837985c65334eb636f12c06e0cbe062a7198932
[lhc/web/wiklou.git] / includes / specials / SpecialVersion.php
1 <?php
2
3 /**
4 * Give information about the version of MediaWiki, PHP, the DB and extensions
5 *
6 * @ingroup SpecialPage
7 *
8 * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
9 * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
10 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
11 */
12 class SpecialVersion extends SpecialPage {
13 private $firstExtOpened = true;
14
15 function __construct(){
16 parent::__construct( 'Version' );
17 }
18
19 /**
20 * main()
21 */
22 function execute( $par ) {
23 global $wgOut, $wgMessageCache, $wgSpecialVersionShowHooks, $wgContLang;
24 $wgMessageCache->loadAllMessages();
25
26 $this->setHeaders();
27 $this->outputHeader();
28
29 if( $wgContLang->isRTL() ) {
30 $wgOut->addHTML( '<div dir="rtl">' );
31 } else {
32 $wgOut->addHTML( '<div dir="ltr">' );
33 }
34 $text =
35 $this->MediaWikiCredits() .
36 $this->softwareInformation() .
37 $this->extensionCredits();
38 if ( $wgSpecialVersionShowHooks ) {
39 $text .= $this->wgHooks();
40 }
41 $wgOut->addWikiText( $text );
42 $wgOut->addHTML( $this->IPInfo() );
43 $wgOut->addHTML( '</div>' );
44 }
45
46 /**
47 * execuate command for output
48 * @param string command
49 * @return string output
50 */
51 static function execOutput( $cmd ) {
52 $out = array( $cmd );
53 exec( $cmd.' 2>&1', $out );
54 unset($out[0]);
55 return implode("\n", $out );
56 }
57
58 /**#@+
59 * @private
60 */
61
62 /**
63 * @return wiki text showing the license information
64 */
65 static function MediaWikiCredits() {
66 global $wgContLang;
67
68 $ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMsg( 'version-license' ) );
69
70 // This text is always left-to-right.
71 $ret .= '<div dir="ltr">';
72 $ret .= "__NOTOC__
73 This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
74 copyright © 2001-2009 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
75 Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason,
76 Niklas Laxström, Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor,
77 Aaron Schulz and others.
78
79 MediaWiki is free software; you can redistribute it and/or modify
80 it under the terms of the GNU General Public License as published by
81 the Free Software Foundation; either version 2 of the License, or
82 (at your option) any later version.
83
84 MediaWiki is distributed in the hope that it will be useful,
85 but WITHOUT ANY WARRANTY; without even the implied warranty of
86 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87 GNU General Public License for more details.
88
89 You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
90 along with this program; if not, write to the Free Software
91 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
92 or [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html read it online].
93 ";
94 $ret .= '</div>';
95
96 return str_replace( "\t\t", '', $ret ) . "\n";
97 }
98
99 /**
100 * @return wiki text showing the third party software versions (apache, php, mysql).
101 */
102 static function softwareInformation() {
103 global $wgUseImageMagick, $wgImageMagickConvertCommand, $wgDiff3, $wgDiff, $wgUseTeX;
104 global $wgAllowTitlesInSVG, $wgSVGConverter, $wgSVGConverters, $wgSVGConverterPath;
105 $dbr = wfGetDB( DB_SLAVE );
106
107 // Put the software in an array of form 'name' => 'version'. All messages should
108 // be loaded here, so feel free to use wfMsg*() in the 'name'. Raw HTML or wikimarkup
109 // can be used
110 $software = array();
111 $software['[http://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked();
112 $software['[http://www.php.net/ PHP]'] = phpversion() . " (" . php_sapi_name() . ")";
113 $software[$dbr->getSoftwareLink()] = $dbr->getServerVersion();
114
115 // Version information for diff3
116 if ( file_exists( trim( $wgDiff3, '"' ) ) ) {
117 $swDiff3Info = self::execOutput( $wgDiff3 . ' -v' );
118 $swDiff3Line = explode("\n",$swDiff3Info ,2);
119 $swDiff3Ver = $swDiff3Line[0];
120 $swDiff3Ver = str_replace( 'diff3 (GNU diffutils) ', '' , $swDiff3Ver);
121 $software['[http://www.gnu.org/software/diffutils/diffutils.html diff3]'] = $swDiff3Ver;
122 }
123
124 // Version information for diff
125 if ( file_exists( trim( $wgDiff, '"' ) ) ) {
126 $swDiffInfo = self::execOutput( $wgDiff . ' -v' );
127 $swDiffLine = explode("\n",$swDiffInfo ,2);
128 $swDiffVer = $swDiffLine[0];
129 $swDiffVer = str_replace( 'diff (GNU diffutils) ', '' , $swDiffVer);
130 $software['[http://www.gnu.org/software/diffutils/diffutils.html diff]'] = $swDiffVer;
131 }
132
133 // Look for ImageMagick's version, if did not found, try to find the GD library version
134 if ( $wgUseImageMagick ) {
135 if ( file_exists( trim( $wgImageMagickConvertCommand, '"' ) ) ) {
136 $swImageMagickInfo = self::execOutput( $wgImageMagickConvertCommand . ' -version' );
137 list( $head, $tail ) = explode( 'ImageMagick', $swImageMagickInfo );
138 list( $swImageMagickVer ) = explode('http://www.imagemagick.org', $tail );
139 $software['[http://www.imagemagick.org/ ImageMagick]'] = $swImageMagickVer;
140 }
141 } else {
142 if( function_exists( 'gd_info' ) ) {
143 $gdInfo = gd_info();
144 if ( strstr( $gdInfo['GD Version'], 'bundled' ) != false ) {
145 $gd_URL = 'http://www.php.net/gd';
146 }
147 else {
148 $gd_URL = 'http://www.libgd.org';
149 }
150 $software['[' . $gd_URL . ' GD library]'] = $gdInfo['GD Version'];
151 }
152 }
153
154 // Look for SVG converter and print the version info
155 if ( $wgAllowTitlesInSVG ) {
156 $swSVGConvName = $wgSVGConverter;
157 $haveSVGConvVer = false;
158 $pathVar = '$path/';
159 $binPath = '/usr/bin/';
160 $execPath = strtok(strstr($wgSVGConverters[$wgSVGConverter],$pathVar), ' ');
161 $execPath = substr_replace($execPath, '', 0, strlen($pathVar));
162 $execFullPath = trim($wgSVGConverterPath,'"') . $execPath;
163 $execBinPath = $binPath . $execPath;
164 if (strstr($execFullPath, ' ') != false) {
165 $execFullPath = '"' . $execFullPath . '"';
166 }
167 if ( !strcmp( $wgSVGConverter, 'ImageMagick') ) {
168 // Get version info for ImageMagick
169 if ( file_exists( $execBinPath ) )
170 $swSVGConvInfo = self::execOutput( $execBinPath . ' -version' );
171 else if ( file_exists( trim( $execFullPath, '"' ) ) || ( file_exists( trim( $execFullPath, '"' ) . '.exe' ) ) )
172 $swSVGConvInfo = self::execOutput( $execFullPath . ' -version' );
173 list( $head, $tail ) = explode( 'ImageMagick', $swSVGConvInfo );
174 list( $swSVGConvVer ) = explode('http://www.imagemagick.org', $tail );
175 $swSVGConvURL = 'http://www.imagemagick.org/';
176 $haveSVGConvVer = true;
177 } else if ( strstr ($execFullPath, 'rsvg') != false ) {
178 // Get version info for rsvg
179 if ( file_exists( $execBinPath ) )
180 $swSVGConvInfo = self::execOutput( $execBinPath . ' -v' );
181 else if ( file_exists( trim( $execFullPath, '"' ) ) || ( file_exists( trim( $execFullPath, '"' ) . '.exe' ) ) )
182 $swSVGConvInfo = self::execOutput( $execFullPath . ' -v' );
183 $swSVGConvLine = explode("\n",$swSVGConvInfo ,2);
184 $swSVGConvVer = $swSVGConvLine[0];
185 $swSVGConvURL = 'http://librsvg.sourceforge.net/';
186 $haveSVGConvVer = true;
187 } else if ( strstr ($execFullPath, 'inkscape') != false ) {
188 // Get version info for Inkscape
189 if ( file_exists( $execBinPath ) )
190 $swSVGConvInfo = self::execOutput( $execBinPath . ' -z -V' );
191 else if ( file_exists( trim( $execFullPath, '"' ) ) || ( file_exists( trim( $execFullPath, '"' ) . '.exe' ) ) )
192 $swSVGConvInfo = self::execOutput( $execFullPath . ' -z -V' );
193 $swSVGConvLine = explode("\n",$swSVGConvInfo ,2);
194 $swSVGConvVer = ltrim( $swSVGConvLine[0], 'Inkscape ' );
195 $swSVGConvURL = 'http://www.inkscape.org/';
196 $swSVGConvName = ucfirst( $wgSVGConverter );
197 $haveSVGConvVer = true;
198 }
199 if ( $haveSVGConvVer )
200 $software["[$swSVGConvURL $swSVGConvName]"] = $swSVGConvVer;
201 }
202
203 // Look for TeX support and print the software version info
204 if ( $wgUseTeX ) {
205 $binPath = '/usr/bin/';
206 $swMathName = Array(
207 'ocaml' => 'OCaml',
208 'gs' => 'Ghostscript',
209 'dvips' => 'Dvips',
210 'latex' => 'LaTeX',
211 'imagemagick' => 'ImageMagick',
212 );
213 $swMathNURL = Array(
214 'ocaml' => 'http://caml.inria.fr/',
215 'gs' => 'http://www.ghostscript.com/',
216 'dvips' => 'http://www.radicaleye.com/dvips.html',
217 'latex' => 'http://www.latex-project.org/',
218 'imagemagick' => 'http://www.imagemagick.org/',
219 );
220 $swMathExec = Array(
221 'ocaml' => 'ocamlc',
222 'gs' => 'gs',
223 'dvips' => 'dvips',
224 'latex' => 'latex',
225 'imagemagick' => 'convert',
226 );
227 $swMathParam = Array(
228 'ocaml' => '-version',
229 'gs' => '-v',
230 'dvips' => '-v',
231 'latex' => '-v',
232 'imagemagick' => '-version',
233 );
234 foreach ( $swMathExec as $swMath => $swMathCmd ) {
235 if ( file_exists( $binPath . $swMathCmd ) ) {
236 $swMathInfo = self::execOutput( $binPath . $swMathCmd . ' ' . $swMathParam[$swMath] );
237 $swMathLine = explode("\n",$swMathInfo ,2);
238 $swMathVerInfo = $swMathLine[0];
239 if ( !strcmp( $swMath, 'gs' ) )
240 $swMathVerInfo = str_replace( 'GPL Ghostscript ', '', $swMathVerInfo );
241 else if ( !strcmp( $swMath, 'dvips' ) ) {
242 $swMathVerParts = explode( ' ' , $swMathVerInfo );
243 $swMathVerInfo = $swMathVerParts[3];
244 } else if ( !strcmp( $swMath, 'imagemagick' ) ) {
245 list( $head, $tail ) = explode( 'ImageMagick', $swMathVerInfo );
246 list( $swMathVerInfo ) = explode('http://www.imagemagick.org', $tail );
247 }
248 $swMathVer[$swMath] = $swMathVerInfo;
249 $software["[$swMathURL $swMathName]"] = $swMathVer[$swMath];
250 }
251 }
252 }
253
254 // Allow a hook to add/remove items
255 wfRunHooks( 'SoftwareInfo', array( &$software ) );
256
257 $out = Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMsg( 'version-software' ) ) .
258 Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-software' ) ) .
259 "<tr>
260 <th>" . wfMsg( 'version-software-product' ) . "</th>
261 <th>" . wfMsg( 'version-software-version' ) . "</th>
262 </tr>\n";
263 foreach( $software as $name => $version ) {
264 $out .= "<tr>
265 <td>" . $name . "</td>
266 <td>" . $version . "</td>
267 </tr>\n";
268 }
269 return $out . Xml::closeElement( 'table' );
270 }
271
272 /**
273 * Return a string of the MediaWiki version with SVN revision if available
274 *
275 * @return mixed
276 */
277 public static function getVersion( $flags = '' ) {
278 global $wgVersion, $IP;
279 wfProfileIn( __METHOD__ );
280 $svn = self::getSvnRevision( $IP, false, false , false );
281 $svnCo = self::getSvnRevision( $IP, true, false , false );
282 if ( !$svn ) {
283 $version = $wgVersion;
284 } elseif( $flags === 'nodb' ) {
285 $version = "$wgVersion (r$svnCo)";
286 } else {
287 $version = $wgVersion . wfMsg( 'version-svn-revision', $svn, $svnCo );
288 }
289 wfProfileOut( __METHOD__ );
290 return $version;
291 }
292
293 /**
294 * Return a string of the MediaWiki version with a link to SVN revision if
295 * available
296 *
297 * @return mixed
298 */
299 public static function getVersionLinked() {
300 global $wgVersion, $IP;
301 wfProfileIn( __METHOD__ );
302 $svn = self::getSvnRevision( $IP, false, false, false );
303 $svnCo = self::getSvnRevision( $IP, true, false, false );
304 $svnDir = self::getSvnRevision( $IP, true, false, true );
305 $viewvcStart = 'http://svn.wikimedia.org/viewvc/mediawiki/';
306 $viewvcEnd = '/?pathrev=';
307 $viewvc = $viewvcStart . $svnDir . $viewvcEnd;
308 $version = $svn ? $wgVersion . " [{$viewvc}{$svnCo} " . wfMsg( 'version-svn-revision', $svn, $svnCo ) . ']' : $wgVersion;
309 wfProfileOut( __METHOD__ );
310 return $version;
311 }
312
313 /** Generate wikitext showing extensions name, URL, author and description */
314 function extensionCredits() {
315 global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunctions;
316
317 if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunctions ) )
318 return '';
319
320 $extensionTypes = array(
321 'specialpage' => wfMsg( 'version-specialpages' ),
322 'parserhook' => wfMsg( 'version-parserhooks' ),
323 'variable' => wfMsg( 'version-variables' ),
324 'media' => wfMsg( 'version-mediahandlers' ),
325 'other' => wfMsg( 'version-other' ),
326 );
327 wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
328
329 $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) .
330 Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-ext' ) );
331
332 foreach ( $extensionTypes as $type => $text ) {
333 if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) {
334 $out .= $this->openExtType( $text );
335
336 usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
337
338 foreach ( $wgExtensionCredits[$type] as $extension ) {
339 $version = null;
340 $subVersion = null;
341 $subVersionCo = null;
342 $viewvc = null;
343 if ( isset( $extension['path'] ) ) {
344 $subVersion = self::getSvnRevision(dirname($extension['path']), false, true, false);
345 $subVersionCo = self::getSvnRevision(dirname($extension['path']), true, true, false);
346 $subVersionDir = self::getSvnRevision(dirname($extension['path']), false, true, true);
347 if ($subVersionDir)
348 $viewvc = $subVersionDir . $subVersionCo;
349 }
350 if ( isset( $extension['version'] ) ) {
351 $version = $extension['version'];
352 }
353
354 $out .= $this->formatCredits(
355 isset ( $extension['name'] ) ? $extension['name'] : '',
356 $version,
357 $subVersion,
358 $subVersionCo,
359 $viewvc,
360 isset ( $extension['author'] ) ? $extension['author'] : '',
361 isset ( $extension['url'] ) ? $extension['url'] : null,
362 isset ( $extension['description'] ) ? $extension['description'] : '',
363 isset ( $extension['descriptionmsg'] ) ? $extension['descriptionmsg'] : null
364 );
365 }
366 }
367 }
368
369 if ( count( $wgExtensionFunctions ) ) {
370 $out .= $this->openExtType( wfMsg( 'version-extension-functions' ) );
371 $out .= '<tr><td colspan="4">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n";
372 }
373
374 if ( $cnt = count( $tags = $wgParser->getTags() ) ) {
375 for ( $i = 0; $i < $cnt; ++$i )
376 $tags[$i] = "&lt;{$tags[$i]}&gt;";
377 $out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ) );
378 $out .= '<tr><td colspan="4">' . $this->listToText( $tags ). "</td></tr>\n";
379 }
380
381 if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) {
382 $out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ) );
383 $out .= '<tr><td colspan="4">' . $this->listToText( $fhooks ) . "</td></tr>\n";
384 }
385
386 if ( count( $wgSkinExtensionFunctions ) ) {
387 $out .= $this->openExtType( wfMsg( 'version-skin-extension-functions' ) );
388 $out .= '<tr><td colspan="4">' . $this->listToText( $wgSkinExtensionFunctions ) . "</td></tr>\n";
389 }
390 $out .= Xml::closeElement( 'table' );
391 return $out;
392 }
393
394 /** Callback to sort extensions by type */
395 function compare( $a, $b ) {
396 global $wgLang;
397 if( $a['name'] === $b['name'] ) {
398 return 0;
399 } else {
400 return $wgLang->lc( $a['name'] ) > $wgLang->lc( $b['name'] )
401 ? 1
402 : -1;
403 }
404 }
405
406 function formatCredits( $name, $version = null, $subVersion = null, $subVersionCo = null, $subVersionURL = null, $author = null, $url = null, $description = null, $descriptionMsg = null ) {
407 $haveSubversion = $subVersion;
408 $extension = isset( $url ) ? "[$url $name]" : $name;
409 $version = isset( $version ) ? wfMsg( 'version-version', $version ) : '';
410 $subVersion = isset( $subVersion ) ? wfMsg( 'version-svn-revision', $subVersion, $subVersionCo ) : '';
411 $subVersion = isset( $subVersionURL ) ? "[$subVersionURL $subVersion]" : $subVersion;
412
413 # Look for a localized description
414 if( isset( $descriptionMsg ) ) {
415 $msg = wfMsg( $descriptionMsg );
416 if ( !wfEmptyMsg( $descriptionMsg, $msg ) && $msg != '' ) {
417 $description = $msg;
418 }
419 }
420
421 if ( $haveSubversion ) {
422 $extNameVer = "<tr>
423 <td><em>$extension $version</em></td>
424 <td><em>$subVersion</em></td>";
425 } else {
426 $extNameVer = "<tr>
427 <td colspan=\"2\"><em>$extension $version</em></td>";
428 }
429 $extDescAuthor = "<td>$description</td>
430 <td>" . $this->listToText( (array)$author ) . "</td>
431 </tr>\n";
432 return $ret = $extNameVer . $extDescAuthor;
433 return $ret;
434 }
435
436 /**
437 * @return string
438 */
439 function wgHooks() {
440 global $wgHooks;
441
442 if ( count( $wgHooks ) ) {
443 $myWgHooks = $wgHooks;
444 ksort( $myWgHooks );
445
446 $ret = Xml::element( 'h2', array( 'id' => 'mw-version-hooks' ), wfMsg( 'version-hooks' ) ) .
447 Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-hooks' ) ) .
448 "<tr>
449 <th>" . wfMsg( 'version-hook-name' ) . "</th>
450 <th>" . wfMsg( 'version-hook-subscribedby' ) . "</th>
451 </tr>\n";
452
453 foreach ( $myWgHooks as $hook => $hooks )
454 $ret .= "<tr>
455 <td>$hook</td>
456 <td>" . $this->listToText( $hooks ) . "</td>
457 </tr>\n";
458
459 $ret .= Xml::closeElement( 'table' );
460 return $ret;
461 } else
462 return '';
463 }
464
465 private function openExtType($text, $name = null) {
466 $opt = array( 'colspan' => 4 );
467 $out = '';
468
469 if(!$this->firstExtOpened) {
470 // Insert a spacing line
471 $out .= '<tr class="sv-space">' . Xml::element( 'td', $opt ) . "</tr>\n";
472 }
473 $this->firstExtOpened = false;
474
475 if($name) { $opt['id'] = "sv-$name"; }
476
477 $out .= "<tr>" . Xml::element( 'th', $opt, $text) . "</tr>\n";
478 return $out;
479 }
480
481 /**
482 * @return string
483 */
484 function IPInfo() {
485 $ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
486 return "<!-- visited from $ip -->\n" .
487 "<span style='display:none'>visited from $ip</span>";
488 }
489
490 /**
491 * @param array $list
492 * @return string
493 */
494 function listToText( $list ) {
495 $cnt = count( $list );
496
497 if ( $cnt == 1 ) {
498 // Enforce always returning a string
499 return (string)self::arrayToString( $list[0] );
500 } elseif ( $cnt == 0 ) {
501 return '';
502 } else {
503 global $wgLang;
504 sort( $list );
505 return $wgLang->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) );
506 }
507 }
508
509 /**
510 * @param mixed $list Will convert an array to string if given and return
511 * the paramater unaltered otherwise
512 * @return mixed
513 */
514 static function arrayToString( $list ) {
515 if( is_array( $list ) && count( $list ) == 1 )
516 $list = $list[0];
517 if( is_object( $list ) ) {
518 $class = get_class( $list );
519 return "($class)";
520 } elseif ( !is_array( $list ) ) {
521 return $list;
522 } else {
523 if( is_object( $list[0] ) )
524 $class = get_class( $list[0] );
525 else
526 $class = $list[0];
527 return "($class, {$list[1]})";
528 }
529 }
530
531 /**
532 * Retrieve the revision number of a Subversion working directory.
533 *
534 * @param String $dir Directory of the svn checkout
535 * @param Boolean $coRev optional to return value whether is Last Modified
536 * or Checkout revision number
537 * @param Boolean $extension optional to check the path whether is from
538 * Wikimedia SVN server or not
539 * @param Boolean $relPath optional to get the end part of the checkout path
540 * @return mixed revision number as int, end part of the checkout path,
541 * or false if not a SVN checkout
542 */
543 public static function getSvnRevision( $dir, $coRev = false, $extension = false, $relPath = false) {
544 // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
545 $entries = $dir . '/.svn/entries';
546
547 if( !file_exists( $entries ) ) {
548 return false;
549 }
550
551 $content = file( $entries );
552
553 // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
554 if( preg_match( '/^<\?xml/', $content[0] ) ) {
555 // subversion is release <= 1.3
556 if( !function_exists( 'simplexml_load_file' ) ) {
557 // We could fall back to expat... YUCK
558 return false;
559 }
560
561 // SimpleXml whines about the xmlns...
562 wfSuppressWarnings();
563 $xml = simplexml_load_file( $entries );
564 wfRestoreWarnings();
565
566 if( $xml ) {
567 foreach( $xml->entry as $entry ) {
568 if( $xml->entry[0]['name'] == '' ) {
569 // The directory entry should always have a revision marker.
570 if( $entry['revision'] ) {
571 return intval( $entry['revision'] );
572 }
573 }
574 }
575 }
576 return false;
577 } else {
578 // subversion is release 1.4 or above
579 if ($relPath) {
580 $endPath = strstr( $content[4], 'tags' );
581 if (!$endPath) {
582 $endPath = strstr( $content[4], 'branches' );
583 if (!$endPath) {
584 $endPath = strstr( $content[4], 'trunk' );
585 if (!$endPath)
586 return false;
587 }
588 }
589 $endPath = trim ( $endPath );
590 if ($extension) {
591 $wmSvnPath = 'svn.wikimedia.org/svnroot/mediawiki';
592 $isWMSvn = strstr($content[5],$wmSvnPath);
593 if (!strcmp($isWMSvn,null)) {
594 return false;
595 } else {
596 $viewvcStart = 'http://svn.wikimedia.org/viewvc/mediawiki/';
597 if (strstr( $content[4], 'trunk' ))
598 $viewvcEnd = '/?pathrev=';
599 else
600 // Avoids 404 error using pathrev when it does not found
601 $viewvcEnd = '/?revision=';
602 $viewvc = $viewvcStart . $endPath . $viewvcEnd;
603 return $viewvc;
604 }
605 }
606 return $endPath;
607 }
608 if ($coRev)
609 // get the directory checkout revsion number
610 return intval( $content[3]) ;
611 else
612 // get the directory last modified revision number
613 return intval( $content[10] );
614 }
615 }
616
617 /**#@-*/
618 }