Index: branches/wmf/1.19wmf1/tests/phpunit/includes/PathRouterTest.php |
— | — | @@ -125,6 +125,16 @@ |
126 | 126 | } |
127 | 127 | |
128 | 128 | /** |
| 129 | + * Test to ensure that matches are not made if a parameter expects nonexistent input |
| 130 | + */ |
| 131 | + public function testFail() { |
| 132 | + $router = new PathRouter; |
| 133 | + $router->add( "/wiki/$1", array( 'title' => "$1$2" ) ); |
| 134 | + $matches = $router->parse( "/wiki/A" ); |
| 135 | + $this->assertEquals( array(), $matches ); |
| 136 | + } |
| 137 | + |
| 138 | + /** |
129 | 139 | * Test to ensure weight of paths is handled correctly |
130 | 140 | */ |
131 | 141 | public function testWeight() { |
— | — | @@ -172,12 +182,30 @@ |
173 | 183 | $this->assertEquals( $matches, array( 'title' => "Title_With Space" ) ); |
174 | 184 | } |
175 | 185 | |
| 186 | + public function dataRegexpChars() { |
| 187 | + return array( |
| 188 | + array( "$" ), |
| 189 | + array( "$1" ), |
| 190 | + array( "\\" ), |
| 191 | + array( "\\$1" ), |
| 192 | + ); |
| 193 | + } |
| 194 | + |
176 | 195 | /** |
| 196 | + * Make sure the router doesn't break on special characters like $ used in regexp replacements |
| 197 | + * @dataProvider dataRegexpChars |
| 198 | + */ |
| 199 | + public function testRegexpChars( $char ) { |
| 200 | + $matches = $this->basicRouter->parse( "/wiki/$char" ); |
| 201 | + $this->assertEquals( $matches, array( 'title' => "$char" ) ); |
| 202 | + } |
| 203 | + |
| 204 | + /** |
177 | 205 | * Make sure the router handles characters like +&() properly |
178 | 206 | */ |
179 | 207 | public function testCharacters() { |
180 | | - $matches = $this->basicRouter->parse( "/wiki/Plus+And&Stuff()" ); |
181 | | - $this->assertEquals( $matches, array( 'title' => "Plus+And&Stuff()" ) ); |
| 208 | + $matches = $this->basicRouter->parse( "/wiki/Plus+And&Dollar\\Stuff();[]{}*" ); |
| 209 | + $this->assertEquals( $matches, array( 'title' => "Plus+And&Dollar\\Stuff();[]{}*" ) ); |
182 | 210 | } |
183 | 211 | |
184 | 212 | /** |
Property changes on: branches/wmf/1.19wmf1/tests/phpunit/includes/PathRouterTest.php |
___________________________________________________________________ |
Added: svn:mergeinfo |
185 | 213 | Merged /branches/JSTesting/tests/phpunit/includes/PathRouterTest.php:r100352-107913 |
186 | 214 | Merged /branches/REL1_15/phase3/tests/phpunit/includes/PathRouterTest.php:r51646 |
187 | 215 | Merged /branches/wmf/1.18wmf1/tests/phpunit/includes/PathRouterTest.php:r97508 |
188 | 216 | Merged /branches/REL1_17/phase3/tests/phpunit/includes/PathRouterTest.php:r81445,81448 |
189 | 217 | Merged /branches/sqlite/tests/phpunit/includes/PathRouterTest.php:r58211-58321 |
190 | 218 | Merged /trunk/phase3/tests/phpunit/includes/PathRouterTest.php:r111002,111029,111034,111062,111067,111076,111085,111128,111144,111251,111397,111571,111574,111597,112313 |
191 | 219 | Merged /branches/new-installer/phase3/tests/phpunit/includes/PathRouterTest.php:r43664-66004 |
Index: branches/wmf/1.19wmf1/includes/PathRouter.php |
— | — | @@ -278,20 +278,14 @@ |
279 | 279 | } elseif ( isset( $paramData['pattern'] ) ) { |
280 | 280 | // For patterns we have to make value replacements on the string |
281 | 281 | $value = $paramData['pattern']; |
282 | | - // For each $# match replace any $# within the value |
283 | | - foreach ( $m as $matchKey => $matchValue ) { |
284 | | - if ( preg_match( '/^par\d+$/u', $matchKey ) ) { |
285 | | - $n = intval( substr( $matchKey, 3 ) ); |
286 | | - $value = str_replace( '$' . $n, rawurldecode( $matchValue ), $value ); |
287 | | - } |
288 | | - } |
289 | | - // If a key was set replace any $key within the value |
| 282 | + $replacer = new PathRouterPatternReplacer; |
| 283 | + $replacer->params = $m; |
290 | 284 | if ( isset( $pattern->key ) ) { |
291 | | - $value = str_replace( '$key', $pattern->key, $value ); |
| 285 | + $replacer->key = $pattern->key; |
292 | 286 | } |
293 | | - if ( preg_match( '/\$(\d+|key)/u', $value ) ) { |
294 | | - // Still contains $# or $key patterns after replacement |
295 | | - // Seams like we don't have all the data, abort |
| 287 | + $value = $replacer->replace( $value ); |
| 288 | + if ( $value === false ) { |
| 289 | + // Pattern required data that wasn't available, abort |
296 | 290 | return null; |
297 | 291 | } |
298 | 292 | } |
— | — | @@ -317,3 +311,41 @@ |
318 | 312 | } |
319 | 313 | |
320 | 314 | } |
| 315 | + |
| 316 | +class PathRouterPatternReplacer { |
| 317 | + |
| 318 | + public $key, $params, $error; |
| 319 | + |
| 320 | + /** |
| 321 | + * Replace keys inside path router patterns with text. |
| 322 | + * We do this inside of a replacement callback because after replacement we can't tell the |
| 323 | + * difference between a $1 that was not replaced and a $1 that was part of |
| 324 | + * the content a $1 was replaced with. |
| 325 | + */ |
| 326 | + public function replace( $value ) { |
| 327 | + $this->error = false; |
| 328 | + $value = preg_replace_callback( '/\$(\d+|key)/u', array( $this, 'callback' ), $value ); |
| 329 | + if ( $this->error ) { |
| 330 | + return false; |
| 331 | + } |
| 332 | + return $value; |
| 333 | + } |
| 334 | + |
| 335 | + protected function callback( $m ) { |
| 336 | + if ( $m[1] == "key" ) { |
| 337 | + if ( is_null( $this->key ) ) { |
| 338 | + $this->error = true; |
| 339 | + return ''; |
| 340 | + } |
| 341 | + return $this->key; |
| 342 | + } else { |
| 343 | + $d = $m[1]; |
| 344 | + if ( !isset( $this->params["par$d"] ) ) { |
| 345 | + $this->error = true; |
| 346 | + return ''; |
| 347 | + } |
| 348 | + return rawurldecode( $this->params["par$d"] ); |
| 349 | + } |
| 350 | + } |
| 351 | + |
| 352 | +} |
\ No newline at end of file |
Property changes on: branches/wmf/1.19wmf1/includes/PathRouter.php |
___________________________________________________________________ |
Added: svn:mergeinfo |
321 | 353 | Merged /branches/new-installer/phase3/includes/PathRouter.php:r43664-66004 |
322 | 354 | Merged /branches/wmf-deployment/includes/PathRouter.php:r53381 |
323 | 355 | Merged /branches/JSTesting/includes/PathRouter.php:r100352-107913 |
324 | 356 | Merged /branches/REL1_15/phase3/includes/PathRouter.php:r51646 |
325 | 357 | Merged /branches/wmf/1.18wmf1/includes/PathRouter.php:r97508 |
326 | 358 | Merged /branches/sqlite/includes/PathRouter.php:r58211-58321 |
327 | 359 | Merged /trunk/phase3/includes/PathRouter.php:r111029,111034,111067,111085,111128,111144,111251,111397,111571,111574,111597,112313 |
Index: branches/wmf/1.19wmf1/includes/AutoLoader.php |
— | — | @@ -162,6 +162,7 @@ |
163 | 163 | 'Pager' => 'includes/Pager.php', |
164 | 164 | 'PasswordError' => 'includes/User.php', |
165 | 165 | 'PathRouter' => 'includes/PathRouter.php', |
| 166 | + 'PathRouterPatternReplacer' => 'includes/PathRouter.php', |
166 | 167 | 'PermissionsError' => 'includes/Exception.php', |
167 | 168 | 'PhpHttpRequest' => 'includes/HttpFunctions.php', |
168 | 169 | 'PoolCounter' => 'includes/PoolCounter.php', |
Property changes on: branches/wmf/1.19wmf1/includes/AutoLoader.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
169 | 170 | Merged /trunk/phase3/includes/AutoLoader.php:r112313 |
170 | 171 | Merged /branches/wmf/1.19wmf1/includes/AutoLoader.php:r112313 |