Index: branches/REL1_18/phase3/RELEASE-NOTES-1.18 |
— | — | @@ -224,8 +224,6 @@ |
225 | 225 | * If an edit summary exceeds 250 bytes and is truncated, add an ellipse. |
226 | 226 | * (bug 26638) Database error pages display correctly in RTL languages. |
227 | 227 | * (bug 26187) Confirmrecreate no longer parses the edit summary. |
228 | | -* (bug 25506) Exception is thrown if OutputPage::parse is called inside a tag |
229 | | - hook, which would reset parser state. |
230 | 228 | * (bug 26208) Mark directionality of some interlanguage links. |
231 | 229 | * (bug 26034) Make the "View / Read" tab in content_navigation style tabs remain |
232 | 230 | selected when the action is "purge". |
— | — | @@ -431,6 +429,8 @@ |
432 | 430 | * $wgSVGMaxSize is now applied to the smaller of width or height, making very wide pano/timeline/diagram SVGs renderable at saner sizes |
433 | 431 | * (bug 30074) Moving user JS subpages resulted in JS errors because |
434 | 432 | #REDIRECT [[Foo]] is invalid JS |
| 433 | +* (bug 30335) Fix for HTMLForms using GET breaking when non-friendly URLs |
| 434 | + are used |
435 | 435 | |
436 | 436 | === API changes in 1.18 === |
437 | 437 | * BREAKING CHANGE: action=watch now requires POST and token. |
Property changes on: branches/REL1_18/phase3/RELEASE-NOTES-1.18 |
___________________________________________________________________ |
Modified: svn:mergeinfo |
438 | 438 | Merged /trunk/phase3/RELEASE-NOTES-1.18:r94277,94517,94738,95023,95072-95073,95327,95422,95426,95601 |
Index: branches/REL1_18/phase3/tests/phpunit/includes/MWNamespaceTest.php |
— | — | @@ -12,16 +12,10 @@ |
13 | 13 | */ |
14 | 14 | class MWNamespaceTest extends MediaWikiTestCase { |
15 | 15 | /** |
16 | | - * @var MWNamespace |
17 | | - */ |
18 | | - protected $object; |
19 | | - |
20 | | - /** |
21 | 16 | * Sets up the fixture, for example, opens a network connection. |
22 | 17 | * This method is called before a test is executed. |
23 | 18 | */ |
24 | 19 | protected function setUp() { |
25 | | - $this->object = new MWNamespace; |
26 | 20 | } |
27 | 21 | |
28 | 22 | /** |
— | — | @@ -87,27 +81,35 @@ |
88 | 82 | * the function testGetTalkExceptions() |
89 | 83 | */ |
90 | 84 | public function testGetTalk() { |
91 | | - $this->assertEquals( MWNamespace::getTalk( NS_MAIN), NS_TALK ); |
| 85 | + $this->assertEquals( NS_TALK, MWNamespace::getTalk( NS_MAIN ) ); |
92 | 86 | } |
93 | 87 | |
94 | 88 | /** |
95 | 89 | * Exceptions with getTalk() |
96 | | - * NS_MEDIA and NS_SPECIAL do not have talk pages. MediaWiki raise an exception for them. |
| 90 | + * NS_MEDIA does not have talk pages. MediaWiki raise an exception for them. |
97 | 91 | * @expectedException MWException |
98 | 92 | */ |
99 | | - public function testGetTalkExceptions() { |
| 93 | + public function testGetTalkExceptionsForNsMedia() { |
100 | 94 | $this->assertNull( MWNamespace::getTalk( NS_MEDIA ) ); |
| 95 | + } |
| 96 | + |
| 97 | + /** |
| 98 | + * Exceptions with getTalk() |
| 99 | + * NS_SPECIAL does not have talk pages. MediaWiki raise an exception for them. |
| 100 | + * @expectedException MWException |
| 101 | + */ |
| 102 | + public function testGetTalkExceptionsForNsSpecial() { |
101 | 103 | $this->assertNull( MWNamespace::getTalk( NS_SPECIAL ) ); |
102 | 104 | } |
103 | 105 | |
104 | 106 | /** |
105 | | - * Regular getAssociated() calls |
| 107 | + * Regular getAssociated() calls |
106 | 108 | * Namespaces without an associated page (NS_MEDIA, NS_SPECIAL) are tested in |
107 | 109 | * the function testGetAssociatedExceptions() |
108 | 110 | */ |
109 | 111 | public function testGetAssociated() { |
110 | | - $this->assertEquals( MWNamespace::getAssociated( NS_MAIN ), NS_TALK ); |
111 | | - $this->assertEquals( MWNamespace::getAssociated( NS_TALK ), NS_MAIN ); |
| 112 | + $this->assertEquals( NS_TALK, MWNamespace::getAssociated( NS_MAIN ) ); |
| 113 | + $this->assertEquals( NS_MAIN, MWNamespace::getAssociated( NS_TALK ) ); |
112 | 114 | |
113 | 115 | } |
114 | 116 | |
— | — | @@ -120,6 +122,7 @@ |
121 | 123 | public function testGetAssociatedExceptionsForNsMedia() { |
122 | 124 | $this->assertNull( MWNamespace::getAssociated( NS_MEDIA ) ); |
123 | 125 | } |
| 126 | + |
124 | 127 | /** |
125 | 128 | * @expectedException MWException |
126 | 129 | */ |
— | — | @@ -131,11 +134,11 @@ |
132 | 135 | */ |
133 | 136 | public function testGetSubject() { |
134 | 137 | // Special namespaces are their own subjects |
135 | | - $this->assertEquals( MWNamespace::getSubject( NS_MEDIA ), NS_MEDIA ); |
136 | | - $this->assertEquals( MWNamespace::getSubject( NS_SPECIAL ), NS_SPECIAL ); |
| 138 | + $this->assertEquals( NS_MEDIA, MWNamespace::getSubject( NS_MEDIA ) ); |
| 139 | + $this->assertEquals( NS_SPECIAL, MWNamespace::getSubject( NS_SPECIAL ) ); |
137 | 140 | |
138 | | - $this->assertEquals( MWNamespace::getSubject( NS_TALK ), NS_MAIN ); |
139 | | - $this->assertEquals( MWNamespace::getSubject( NS_USER_TALK ), NS_USER ); |
| 141 | + $this->assertEquals( NS_MAIN, MWNamespace::getSubject( NS_TALK ) ); |
| 142 | + $this->assertEquals( NS_USER, MWNamespace::getSubject( NS_USER_TALK ) ); |
140 | 143 | } |
141 | 144 | |
142 | 145 | /** |
— | — | @@ -225,7 +228,7 @@ |
226 | 229 | * Similar to testIsContent() but alters the $wgContentNamespaces |
227 | 230 | * global variable. |
228 | 231 | */ |
229 | | - public function testIsContentWithAdditionsInWgContentNamespaces() { |
| 232 | + public function testIsContentWithAdditionsInWgContentNamespaces() { |
230 | 233 | // NS_MAIN is a content namespace per DefaultSettings.php |
231 | 234 | // and per function definition. |
232 | 235 | $this->assertTrue( MWNamespace::isContent( NS_MAIN ) ); |
— | — | @@ -271,15 +274,26 @@ |
272 | 275 | $this->assertFalse( MWNamespace::hasSubpages( NS_SPECIAL ) ); |
273 | 276 | |
274 | 277 | // namespaces without subpages |
| 278 | + # save up global |
275 | 279 | global $wgNamespacesWithSubpages; |
276 | | - if( array_key_exists( NS_MAIN, $wgNamespacesWithSubpages ) |
277 | | - && $wgNamespacesWithSubpages[NS_MAIN] === true |
278 | | - ) { |
279 | | - $this->markTestSkipped( "Main namespace has subpages enabled" ); |
280 | | - } else { |
281 | | - $this->assertFalse( MWNamespace::hasSubpages( NS_MAIN ) ); |
| 280 | + $saved = null; |
| 281 | + if( array_key_exists( NS_MAIN, $wgNamespacesWithSubpages ) ) { |
| 282 | + $saved = $wgNamespacesWithSubpages[NS_MAIN]; |
| 283 | + unset( $wgNamespacesWithSubpages[NS_MAIN] ); |
282 | 284 | } |
283 | 285 | |
| 286 | + $this->assertFalse( MWNamespace::hasSubpages( NS_MAIN ) ); |
| 287 | + |
| 288 | + $wgNamespacesWithSubpages[NS_MAIN] = true; |
| 289 | + $this->assertTrue( MWNamespace::hasSubpages( NS_MAIN ) ); |
| 290 | + $wgNamespacesWithSubpages[NS_MAIN] = false; |
| 291 | + $this->assertFalse( MWNamespace::hasSubpages( NS_MAIN ) ); |
| 292 | + |
| 293 | + # restore global |
| 294 | + if( $saved !== null ) { |
| 295 | + $wgNamespacesWithSubpages[NS_MAIN] = $saved; |
| 296 | + } |
| 297 | + |
284 | 298 | // Some namespaces with subpages |
285 | 299 | $this->assertTrue( MWNamespace::hasSubpages( NS_TALK ) ); |
286 | 300 | $this->assertTrue( MWNamespace::hasSubpages( NS_USER ) ); |
— | — | @@ -290,8 +304,8 @@ |
291 | 305 | */ |
292 | 306 | public function testGetContentNamespaces() { |
293 | 307 | $this->assertEquals( |
| 308 | + array( NS_MAIN ), |
294 | 309 | MWNamespace::getcontentNamespaces(), |
295 | | - array( NS_MAIN), |
296 | 310 | '$wgContentNamespaces is an array with only NS_MAIN by default' |
297 | 311 | ); |
298 | 312 | |
— | — | @@ -299,37 +313,37 @@ |
300 | 314 | |
301 | 315 | # test !is_array( $wgcontentNamespaces ) |
302 | 316 | $wgContentNamespaces = ''; |
303 | | - $this->assertEquals( MWNamespace::getcontentNamespaces(), NS_MAIN ); |
| 317 | + $this->assertEquals( NS_MAIN, MWNamespace::getcontentNamespaces() ); |
304 | 318 | $wgContentNamespaces = false; |
305 | | - $this->assertEquals( MWNamespace::getcontentNamespaces(), NS_MAIN ); |
| 319 | + $this->assertEquals( NS_MAIN, MWNamespace::getcontentNamespaces() ); |
306 | 320 | $wgContentNamespaces = null; |
307 | | - $this->assertEquals( MWNamespace::getcontentNamespaces(), NS_MAIN ); |
| 321 | + $this->assertEquals( NS_MAIN, MWNamespace::getcontentNamespaces() ); |
308 | 322 | $wgContentNamespaces = 5; |
309 | | - $this->assertEquals( MWNamespace::getcontentNamespaces(), NS_MAIN ); |
| 323 | + $this->assertEquals( NS_MAIN, MWNamespace::getcontentNamespaces() ); |
310 | 324 | |
311 | | - # test $wgContentNamespaces === array() |
| 325 | + # test $wgContentNamespaces === array() |
312 | 326 | $wgContentNamespaces = array(); |
313 | | - $this->assertEquals( MWNamespace::getcontentNamespaces(), NS_MAIN ); |
| 327 | + $this->assertEquals( NS_MAIN, MWNamespace::getcontentNamespaces() ); |
314 | 328 | |
315 | 329 | # test !in_array( NS_MAIN, $wgContentNamespaces ) |
316 | 330 | $wgContentNamespaces = array( NS_USER, NS_CATEGORY ); |
317 | 331 | $this->assertEquals( |
318 | | - MWNamespace::getcontentNamespaces(), |
319 | 332 | array( NS_MAIN, NS_USER, NS_CATEGORY ), |
| 333 | + MWNamespace::getcontentNamespaces(), |
320 | 334 | 'NS_MAIN is forced in wgContentNamespaces even if unwanted' |
321 | 335 | ); |
322 | 336 | |
323 | 337 | # test other cases, return $wgcontentNamespaces as is |
324 | 338 | $wgContentNamespaces = array( NS_MAIN ); |
325 | 339 | $this->assertEquals( |
326 | | - MWNamespace::getcontentNamespaces(), |
327 | | - array( NS_MAIN ) |
| 340 | + array( NS_MAIN ), |
| 341 | + MWNamespace::getcontentNamespaces() |
328 | 342 | ); |
329 | 343 | |
330 | 344 | $wgContentNamespaces = array( NS_MAIN, NS_USER, NS_CATEGORY ); |
331 | 345 | $this->assertEquals( |
332 | | - MWNamespace::getcontentNamespaces(), |
333 | | - array( NS_MAIN, NS_USER, NS_CATEGORY ) |
| 346 | + array( NS_MAIN, NS_USER, NS_CATEGORY ), |
| 347 | + MWNamespace::getcontentNamespaces() |
334 | 348 | ); |
335 | 349 | |
336 | 350 | } |
— | — | @@ -440,7 +454,7 @@ |
441 | 455 | $this->assertFalse( MWNamespace::hasGenderDistinction( NS_SPECIAL ) ); |
442 | 456 | $this->assertFalse( MWNamespace::hasGenderDistinction( NS_MAIN ) ); |
443 | 457 | $this->assertFalse( MWNamespace::hasGenderDistinction( NS_TALK ) ); |
444 | | - |
| 458 | + |
445 | 459 | } |
446 | 460 | } |
447 | 461 | |
Index: branches/REL1_18/phase3/includes/GlobalFunctions.php |
— | — | @@ -598,6 +598,26 @@ |
599 | 599 | } |
600 | 600 | |
601 | 601 | /** |
| 602 | + * Check whether a given URL has a domain that occurs in a given set of domains |
| 603 | + * @param $url string URL |
| 604 | + * @param $domains array Array of domains (strings) |
| 605 | + * @return bool True if the host part of $url ends in one of the strings in $domains |
| 606 | + */ |
| 607 | +function wfMatchesDomainList( $url, $domains ) { |
| 608 | + $bits = wfParseUrl( $url ); |
| 609 | + if ( is_array( $bits ) && isset( $bits['host'] ) ) { |
| 610 | + foreach ( (array)$domains as $domain ) { |
| 611 | + // FIXME: This gives false positives. http://nds-nl.wikipedia.org will match nl.wikipedia.org |
| 612 | + // We should use something that interprets dots instead |
| 613 | + if ( substr( $bits['host'], -strlen( $domain ) ) === $domain ) { |
| 614 | + return true; |
| 615 | + } |
| 616 | + } |
| 617 | + } |
| 618 | + return false; |
| 619 | +} |
| 620 | + |
| 621 | +/** |
602 | 622 | * Sends a line to the debug log if enabled or, optionally, to a comment in output. |
603 | 623 | * In normal operation this is a NOP. |
604 | 624 | * |
Property changes on: branches/REL1_18/phase3/includes/GlobalFunctions.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
605 | 625 | Merged /trunk/phase3/includes/GlobalFunctions.php:r94277,94517,94738,95023,95072-95073,95327,95422,95426,95601 |
Index: branches/REL1_18/phase3/includes/parser/Parser.php |
— | — | @@ -1584,23 +1584,12 @@ |
1585 | 1585 | */ |
1586 | 1586 | function getExternalLinkAttribs( $url = false ) { |
1587 | 1587 | $attribs = array(); |
1588 | | - global $wgNoFollowLinks, $wgNoFollowNsExceptions; |
| 1588 | + global $wgNoFollowLinks, $wgNoFollowNsExceptions, $wgNoFollowDomainExceptions; |
1589 | 1589 | $ns = $this->mTitle->getNamespace(); |
1590 | | - if ( $wgNoFollowLinks && !in_array( $ns, $wgNoFollowNsExceptions ) ) { |
| 1590 | + if ( $wgNoFollowLinks && !in_array( $ns, $wgNoFollowNsExceptions ) && |
| 1591 | + !wfMatchesDomainList( $url, $wgNoFollowDomainExceptions ) ) |
| 1592 | + { |
1591 | 1593 | $attribs['rel'] = 'nofollow'; |
1592 | | - |
1593 | | - global $wgNoFollowDomainExceptions; |
1594 | | - if ( $wgNoFollowDomainExceptions ) { |
1595 | | - $bits = wfParseUrl( $url ); |
1596 | | - if ( is_array( $bits ) && isset( $bits['host'] ) ) { |
1597 | | - foreach ( $wgNoFollowDomainExceptions as $domain ) { |
1598 | | - if ( substr( $bits['host'], -strlen( $domain ) ) == $domain ) { |
1599 | | - unset( $attribs['rel'] ); |
1600 | | - break; |
1601 | | - } |
1602 | | - } |
1603 | | - } |
1604 | | - } |
1605 | 1594 | } |
1606 | 1595 | if ( $this->mOptions->getExternalLinkTarget() ) { |
1607 | 1596 | $attribs['target'] = $this->mOptions->getExternalLinkTarget(); |
Index: branches/REL1_18/phase3/includes/HTMLForm.php |
— | — | @@ -429,12 +429,18 @@ |
430 | 430 | * @return String HTML. |
431 | 431 | */ |
432 | 432 | function getHiddenFields() { |
| 433 | + global $wgUsePathInfo; |
| 434 | + |
433 | 435 | $html = ''; |
434 | 436 | if( $this->getMethod() == 'post' ){ |
435 | 437 | $html .= Html::hidden( 'wpEditToken', $this->getUser()->editToken(), array( 'id' => 'wpEditToken' ) ) . "\n"; |
436 | 438 | $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n"; |
437 | 439 | } |
438 | 440 | |
| 441 | + if ( !$wgUsePathInfo && $this->getMethod() == 'get' ) { |
| 442 | + $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n"; |
| 443 | + } |
| 444 | + |
439 | 445 | foreach ( $this->mHiddenFields as $data ) { |
440 | 446 | list( $value, $attribs ) = $data; |
441 | 447 | $html .= Html::hidden( $attribs['name'], $value, $attribs ) . "\n"; |
Index: branches/REL1_18/phase3/includes/OutputPage.php |
— | — | @@ -1500,13 +1500,6 @@ |
1501 | 1501 | * @return String: HTML |
1502 | 1502 | */ |
1503 | 1503 | public function parse( $text, $linestart = true, $interface = false, $language = null ) { |
1504 | | - // Check one for one common cause for parser state resetting |
1505 | | - $callers = wfGetAllCallers( 10 ); |
1506 | | - if ( strpos( $callers, 'Parser::extensionSubstitution' ) !== false ) { |
1507 | | - throw new MWException( "wfMsg* function with parsing cannot be used " . |
1508 | | - "inside a tag hook. Should use parser->recursiveTagParse() instead" ); |
1509 | | - } |
1510 | | - |
1511 | 1504 | global $wgParser; |
1512 | 1505 | |
1513 | 1506 | if( is_null( $this->getTitle() ) ) { |
Property changes on: branches/REL1_18/phase3/includes/OutputPage.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1514 | 1507 | Merged /trunk/phase3/includes/OutputPage.php:r94277,94517,94738,95023,95072-95073,95327,95422,95426,95601 |
Index: branches/REL1_18/phase3/includes/installer/Installer.php |
— | — | @@ -332,12 +332,14 @@ |
333 | 333 | $this->settings[$var] = $GLOBALS[$var]; |
334 | 334 | } |
335 | 335 | |
| 336 | + $compiledDBs = array(); |
336 | 337 | foreach ( self::getDBTypes() as $type ) { |
337 | 338 | $installer = $this->getDBInstaller( $type ); |
338 | 339 | |
339 | 340 | if ( !$installer->isCompiled() ) { |
340 | 341 | continue; |
341 | 342 | } |
| 343 | + $compiledDBs[] = $type; |
342 | 344 | |
343 | 345 | $defaults = $installer->getGlobalDefaults(); |
344 | 346 | |
— | — | @@ -349,6 +351,7 @@ |
350 | 352 | } |
351 | 353 | } |
352 | 354 | } |
| 355 | + $this->setVar( '_CompiledDBs', $compiledDBs ); |
353 | 356 | |
354 | 357 | $this->parserTitle = Title::newFromText( 'Installer' ); |
355 | 358 | $this->parserOptions = new ParserOptions; // language will be wrong :( |
— | — | @@ -621,19 +624,13 @@ |
622 | 625 | protected function envCheckDB() { |
623 | 626 | global $wgLang; |
624 | 627 | |
625 | | - $compiledDBs = array(); |
626 | 628 | $allNames = array(); |
627 | 629 | |
628 | 630 | foreach ( self::getDBTypes() as $name ) { |
629 | | - if ( $this->getDBInstaller( $name )->isCompiled() ) { |
630 | | - $compiledDBs[] = $name; |
631 | | - } |
632 | | - $allNames[] = wfMsg( 'config-type-' . $name ); |
| 631 | + $allNames[] = wfMsg( "config-type-$name" ); |
633 | 632 | } |
634 | 633 | |
635 | | - $this->setVar( '_CompiledDBs', $compiledDBs ); |
636 | | - |
637 | | - if ( !$compiledDBs ) { |
| 634 | + if ( !$this->getVar( '_CompiledDBs' ) ) { |
638 | 635 | $this->showError( 'config-no-db', $wgLang->commaList( $allNames ) ); |
639 | 636 | // @todo FIXME: This only works for the web installer! |
640 | 637 | return false; |
Index: branches/REL1_18/phase3/includes/media/SVGMetadataExtractor.php |
— | — | @@ -55,7 +55,7 @@ |
56 | 56 | $size = filesize( $source ); |
57 | 57 | if ( $size === false ) { |
58 | 58 | throw new MWException( "Error getting filesize of SVG." ); |
59 | | - } |
| 59 | + } |
60 | 60 | |
61 | 61 | if ( $size > $wgSVGMetadataCutoff ) { |
62 | 62 | $this->debug( "SVG is $size bytes, which is bigger than $wgSVGMetadataCutoff. Truncating." ); |
— | — | @@ -157,7 +157,7 @@ |
158 | 158 | } |
159 | 159 | $keepReading = $this->reader->read(); |
160 | 160 | while( $keepReading ) { |
161 | | - if( $this->reader->localName == $name && $this->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::END_ELEMENT ) { |
| 161 | + if( $this->reader->localName == $name && $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::END_ELEMENT ) { |
162 | 162 | break; |
163 | 163 | } elseif( $this->reader->nodeType == XmlReader::TEXT ){ |
164 | 164 | $this->metadata[$metafield] = trim( $this->reader->value ); |
Index: branches/REL1_18/phase3/includes/Skin.php |
— | — | @@ -1255,24 +1255,13 @@ |
1256 | 1256 | |
1257 | 1257 | if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $link ) ) { |
1258 | 1258 | $href = $link; |
1259 | | - //Parser::getExternalLinkAttribs won't work here because of the Namespace things |
1260 | | - global $wgNoFollowLinks; |
1261 | | - if ( $wgNoFollowLinks ) { |
| 1259 | + |
| 1260 | + // Parser::getExternalLinkAttribs won't work here because of the Namespace things |
| 1261 | + global $wgNoFollowLinks, $wgNoFollowDomainExceptions; |
| 1262 | + if ( $wgNoFollowLinks && !wfMatchesDomainList( $href, $wgNoFollowDomainExceptions ) ) { |
1262 | 1263 | $extraAttribs['rel'] = 'nofollow'; |
1263 | | - |
1264 | | - global $wgNoFollowDomainExceptions; |
1265 | | - if ( $wgNoFollowDomainExceptions ) { |
1266 | | - $bits = wfParseUrl( $url ); |
1267 | | - if ( is_array( $bits ) && isset( $bits['host'] ) ) { |
1268 | | - foreach ( $wgNoFollowDomainExceptions as $domain ) { |
1269 | | - if ( substr( $bits['host'], -strlen( $domain ) ) == $domain ) { |
1270 | | - unset( $extraAttribs['rel'] ); |
1271 | | - break; |
1272 | | - } |
1273 | | - } |
1274 | | - } |
1275 | | - } |
1276 | 1264 | } |
| 1265 | + |
1277 | 1266 | global $wgExternalLinkTarget; |
1278 | 1267 | if ( $wgExternalLinkTarget) { |
1279 | 1268 | $extraAttribs['target'] = $wgExternalLinkTarget; |
Property changes on: branches/REL1_18/phase3/includes |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1280 | 1269 | Merged /trunk/phase3/includes:r94277,94517,94738,95023,95072-95073,95327,95422,95426,95601 |
Property changes on: branches/REL1_18/phase3 |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1281 | 1270 | Merged /trunk/phase3:r94277,94517,94738,95023,95072-95073,95327,95422,95426,95601 |