3 * Performs fuzz-style testing of MediaWiki's parser and forms.
5 * Copyright © 2006 Nick Jenkins
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * http://www.gnu.org/copyleft/gpl.html
23 * @ingroup Maintenance
24 * @author Nick Jenkins ( http://nickj.org/ ).
30 Performs fuzz-style testing of MediaWiki's parser and forms.
33 - Generate lots of nasty wiki text.
34 - Ask the Parser to render that wiki text to HTML, or ask MediaWiki's forms
35 to deal with that wiki text.
36 - Check MediaWiki's output for problems.
41 - To help find security issues, or potential security issues.
43 What type of problems are being checked for:
45 - Errors or interesting warnings from Tidy.
46 - PHP errors / warnings / notices.
47 - MediaWiki internal errors.
48 - Very slow responses.
49 - No response from apache.
50 - Optionally checking for malformed HTML using the W3C validator.
53 Many of the wikiFuzz class methods are a modified PHP port,
54 of a "shameless" Python port, of LCAMTUF'S MANGELME:
55 - http://www.securiteam.com/tools/6Z00N1PBFK.html
56 - http://www.securityfocus.com/archive/1/378632/2004-10-15/2004-10-21/0
59 There's an XviD video discussing this fuzz tester. You can get it from:
60 http://files.nickj.org/MediaWiki/Fuzz-Testing-MediaWiki-xvid.avi
63 To run this, you will need:
64 - Command-line PHP5, with PHP-curl enabled (not all installations have this
65 enabled - try "apt-get install php5-curl" if you're on Debian to install).
66 - the Tidy standalone executable. ("apt-get install tidy").
69 - If you want to run the curl scripts, you'll need standalone curl installed
70 ("apt-get install curl")
71 - For viewing the W3C validator output on a command line, the "html2text"
72 program may be useful ("apt-get install html2text")
74 Saving tests and test results:
75 Any of the fuzz tests which find problems are saved for later review.
76 In order to help track down problems, tests are saved in a number of
77 different formats. The default filename extensions and their meanings are:
78 - ".test.php" : PHP script that reproduces just that one problem using PHP-Curl.
79 - ".curl.sh" : Shell script that reproduces that problem using standalone curl.
80 - ".data.bin" : The serialized PHP data so that this script can re-run the test.
81 - ".info.txt" : A human-readable text file with details of the field contents.
83 Wiki configuration for testing:
84 You should make some additions to LocalSettings.php in order to catch the most
85 errors. Note this configuration is for **TESTING PURPOSES ONLY**, and is IN NO
86 WAY, SHAPE, OR FORM suitable for deployment on a hostile network. That said,
87 personally I find these additions to be the most helpful for testing purposes:
89 // --------- Start ---------
90 // Everyone can do everything. Very useful for testing, yet useless for deployment.
91 $wgGroupPermissions['*']['autoconfirmed'] = true;
92 $wgGroupPermissions['*']['block'] = true;
93 $wgGroupPermissions['*']['bot'] = true;
94 $wgGroupPermissions['*']['delete'] = true;
95 $wgGroupPermissions['*']['deletedhistory'] = true;
96 $wgGroupPermissions['*']['deleterevision'] = true;
97 $wgGroupPermissions['*']['editinterface'] = true;
98 $wgGroupPermissions['*']['hiderevision'] = true;
99 $wgGroupPermissions['*']['import'] = true;
100 $wgGroupPermissions['*']['importupload'] = true;
101 $wgGroupPermissions['*']['minoredit'] = true;
102 $wgGroupPermissions['*']['move'] = true;
103 $wgGroupPermissions['*']['patrol'] = true;
104 $wgGroupPermissions['*']['protect'] = true;
105 $wgGroupPermissions['*']['proxyunbannable'] = true;
106 $wgGroupPermissions['*']['renameuser'] = true;
107 $wgGroupPermissions['*']['reupload'] = true;
108 $wgGroupPermissions['*']['reupload-shared'] = true;
109 $wgGroupPermissions['*']['rollback'] = true;
110 $wgGroupPermissions['*']['siteadmin'] = true;
111 $wgGroupPermissions['*']['trackback'] = true;
112 $wgGroupPermissions['*']['unwatchedpages'] = true;
113 $wgGroupPermissions['*']['upload'] = true;
114 $wgGroupPermissions['*']['userrights'] = true;
115 $wgGroupPermissions['*']['renameuser'] = true;
116 $wgGroupPermissions['*']['makebot'] = true;
117 $wgGroupPermissions['*']['makesysop'] = true;
119 // Enable weird and wonderful options:
120 // Increase default error reporting level.
121 error_reporting (E_ALL); // At a later date could be increased to E_ALL | E_STRICT
122 $wgBlockOpenProxies = true; // Some block pages require this to be true in order to test.
123 $wgEnableUploads = true; // enable uploads.
124 //$wgUseTrackbacks = true; // enable trackbacks; However this breaks the viewPageTest, so currently disabled.
125 $wgDBerrorLog = "/root/mediawiki-db-error-log.txt"; // log DB errors, replace with suitable path.
126 $wgShowSQLErrors = true; // Show SQL errors (instead of saying the query was hidden).
127 $wgShowExceptionDetails = true; // want backtraces.
128 $wgEnableAPI = true; // enable API.
129 $wgEnableWriteAPI = true; // enable API.
131 // Install & enable Parser Hook extensions to increase code coverage. E.g.:
132 require_once("extensions/ParserFunctions/ParserFunctions.php");
133 require_once("extensions/Cite/Cite.php");
134 require_once("extensions/inputbox/inputbox.php");
135 require_once("extensions/Sort/Sort.php");
136 require_once("extensions/wikihiero/wikihiero.php");
137 require_once("extensions/CharInsert/CharInsert.php");
138 require_once("extensions/FixedImage/FixedImage.php");
140 // Install & enable Special Page extensions to increase code coverage. E.g.:
141 require_once("extensions/Cite/SpecialCite.php");
142 require_once("extensions/Filepath/SpecialFilepath.php");
143 require_once("extensions/Makebot/Makebot.php");
144 require_once("extensions/Makesysop/SpecialMakesysop.php");
145 require_once("extensions/Renameuser/SpecialRenameuser.php");
146 require_once("extensions/LinkSearch/LinkSearch.php");
147 // --------- End ---------
149 If you want to try E_STRICT error logging, add this to the above:
150 // --------- Start ---------
151 error_reporting (E_ALL | E_STRICT);
152 set_error_handler( 'error_handler' );
153 function error_handler ($type, $message, $file=__FILE__, $line=__LINE__) {
154 if ($message == "var: Deprecated. Please use the public/private/protected modifiers") return;
155 print "<br />\n<b>Strict Standards:</b> Type: <b>$type</b>: $message in <b>$file</b> on line <b>$line</b><br />\n";
157 // --------- End ---------
159 Also add/change this in LocalSettings.php:
160 // --------- Start ---------
161 $wgEnableProfileInfo = true;
162 $wgDBserver = "localhost"; // replace with DB server hostname
163 // --------- End ---------
166 Run with "php fuzz-tester.php".
167 To see the various command-line options, run "php fuzz-tester.php --help".
168 To stop the script, press Ctrl-C.
171 - If requested, first any previously failed tests will be rerun.
172 - Then new tests will be generated and run. Any tests that fail will be saved,
173 and a brief message about why they failed will be printed on the console.
174 - The console will show the number of tests run, time run, number of tests
175 failed, number of tests being done per minute, and the name of the current test.
178 Some known things that could improve this script:
179 - Logging in with cookie jar storage needed for some tests (as there are some
180 pages that cannot be tested without being logged in, and which are currently
181 untested - e.g. Special:Emailuser, Special:Preferences, adding to Watchist).
182 - Testing of Timeline extension (I cannot test as ploticus has/had issues on
187 // ///////////////////////// COMMAND LINE HELP ////////////////////////////////////
189 // This is a command line script, load MediaWiki env (gives command line options);
190 require_once( dirname( __FILE__
) . '/commandLine.inc' );
192 // if the user asked for an explanation of command line options.
193 if ( isset( $options["help"] ) ) {
195 MediaWiki $wgVersion fuzz tester
196 Usage: php {$_SERVER["SCRIPT_NAME"]} [--quiet] [--base-url=<url-to-test-wiki>]
197 [--directory=<failed-test-path>] [--include-binary]
198 [--w3c-validate] [--delete-passed-retests] [--help]
199 [--user=<username>] [--password=<password>]
200 [--rerun-failed-tests] [--max-errors=<int>]
201 [--max-runtime=<num-minutes>]
202 [--specific-test=<test-name>]
205 --quiet : Hides passed tests, shows only failed tests.
206 --base-url : URL to a wiki on which to run the tests.
207 The "http://" is optional and can be omitted.
208 --directory : Full path to directory for storing failed tests.
209 Will be created if it does not exist.
210 --include-binary : Includes non-alphanumeric characters in the tests.
211 --w3c-validate : Validates pages using the W3C's web validator.
212 Slow. Currently many pages fail validation.
213 --user : Login name of a valid user on your test wiki.
214 --password : Password for the valid user on your test wiki.
215 --delete-passed-retests : Will delete retests that now pass.
216 Requires --rerun-failed-tests to be meaningful.
217 --rerun-failed-tests : Whether to rerun any previously failed tests.
218 --max-errors : Maximum number of errors to report before exiting.
219 Does not include errors from --rerun-failed-tests
220 --max-runtime : Maximum runtime, in minutes, to run before exiting.
221 Only applies to new tests, not --rerun-failed-tests
222 --specific-test : Runs only the specified fuzz test.
223 Only applies to new tests, not --rerun-failed-tests
224 --keep-passed-tests : Saves all test files, even those that pass.
225 --help : Show this help message.
228 If you wanted to fuzz test a nightly MediaWiki checkout using cron for 1 hour,
229 and only wanted to be informed of errors, and did not want to redo previously
230 failed tests, and wanted a maximum of 100 errors, then you could do:
231 php {$_SERVER["SCRIPT_NAME"]} --quiet --max-errors=100 --max-runtime=60
240 // if we got command line options, check they look valid.
241 $validOptions = array ( "quiet", "base-url", "directory", "include-binary",
242 "w3c-validate", "user", "password", "delete-passed-retests",
243 "rerun-failed-tests", "max-errors",
244 "max-runtime", "specific-test", "keep-passed-tests", "help" );
245 if ( !empty( $options ) ) {
246 $unknownArgs = array_diff ( array_keys( $options ), $validOptions );
247 foreach ( $unknownArgs as $invalidArg ) {
248 print "Ignoring invalid command-line option: --$invalidArg\n";
253 // /////////////////////////// CONFIGURATION ////////////////////////////////////
255 // URL to some wiki on which we can run our tests.
256 if ( !empty( $options["base-url"] ) ) {
257 define( "WIKI_BASE_URL", $options["base-url"] );
259 define( "WIKI_BASE_URL", $wgServer . $wgScriptPath . '/' );
262 // The directory name where we store the output.
263 // Example for Windows: "c:\\temp\\wiki-fuzz"
264 if ( !empty( $options["directory"] ) ) {
265 define( "DIRECTORY", $options["directory"] );
267 define( "DIRECTORY", "{$wgUploadDirectory}/fuzz-tests" );
270 // Should our test fuzz data include binary strings?
271 define( "INCLUDE_BINARY", isset( $options["include-binary"] ) );
273 // Whether we want to validate HTML output on the web.
274 // At the moment very few generated pages will validate, so not recommended.
275 define( "VALIDATE_ON_WEB", isset( $options["w3c-validate"] ) );
276 // URL to use to validate our output:
277 define( "VALIDATOR_URL", "http://validator.w3.org/check" );
279 // Location of Tidy standalone executable.
280 define( "PATH_TO_TIDY", "/usr/bin/tidy" );
282 // The name of a user who has edited on your wiki. Used
283 // when testing the Special:Contributions and Special:Userlogin page.
284 if ( !empty( $options["user"] ) ) {
285 define( "USER_ON_WIKI", $options["user"] );
287 define( "USER_ON_WIKI", "nickj" );
290 // The password of the above user. Used when testing the login page,
291 // and to do this we sometimes need to login successfully.
292 if ( !empty( $options["password"] ) ) {
293 define( "USER_PASSWORD", $options["password"] );
295 // And no, this is not a valid password on any public wiki.
296 define( "USER_PASSWORD", "nickj" );
299 // If we have a test that failed, and then we run it again, and it passes,
300 // do you want to delete it or keep it?
301 define( "DELETE_PASSED_RETESTS", isset( $options["delete-passed-retests"] ) );
303 // Do we want to rerun old saved tests at script startup?
304 // Set to true to help catch regressions, or false if you only want new stuff.
305 define( "RERUN_OLD_TESTS", isset( $options["rerun-failed-tests"] ) );
307 // File where the database errors are logged. Should be defined in LocalSettings.php.
308 define( "DB_ERROR_LOG_FILE", $wgDBerrorLog );
310 // Run in chatty mode (all output, default), or run in quiet mode (only prints out details of failed tests)?
311 define( "QUIET", isset( $options["quiet"] ) );
313 // Keep all test files, even those that pass. Potentially useful to tracking input that causes something
314 // unusual to happen, if you don't know what "unusual" is until later.
315 define( "KEEP_PASSED_TESTS", isset( $options["keep-passed-tests"] ) );
317 // The maximum runtime, if specified.
318 if ( !empty( $options["max-runtime"] ) && intval( $options["max-runtime"] ) > 0 ) {
319 define( "MAX_RUNTIME", intval( $options["max-runtime"] ) );
322 // The maximum number of problems to find, if specified. Excludes retest errors.
323 if ( !empty( $options["max-errors"] ) && intval( $options["max-errors"] ) > 0 ) {
324 define( "MAX_ERRORS", intval( $options["max-errors"] ) );
327 // if the user has requested a specific test (instead of all tests), and the test they asked for looks valid.
328 if ( !empty( $options["specific-test"] ) ) {
329 if ( class_exists( $options["specific-test"] ) && get_parent_class( $options["specific-test"] ) == "pageTest" ) {
330 define( "SPECIFIC_TEST", $options["specific-test"] );
333 print "Ignoring invalid --specific-test\n";
337 // Define the file extensions we'll use:
338 define( "PHP_TEST" , ".test.php" );
339 define( "CURL_TEST", ".curl.sh" );
340 define( "DATA_FILE", ".data.bin" );
341 define( "INFO_FILE", ".info.txt" );
342 define( "HTML_FILE", ".wiki_preview.html" );
344 // If it goes wrong, we want to know about it.
345 error_reporting( E_ALL | E_STRICT
);
347 // ////////////// A CLASS THAT GENERATES RANDOM NASTY WIKI & HTML STRINGS //////////////////////
351 // Only some HTML tags are understood with params by MediaWiki, the rest are ignored.
352 // List the tags that accept params below, as well as what those params are.
353 public static $data = array(
354 "B" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
355 "CAPTION" => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
356 "CENTER" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title" ),
357 "DIV" => array( "CLASS", "STYLE", "ID", "align", "lang", "dir", "title" ),
358 "FONT" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "face", "size", "color" ),
359 "H1" => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
360 "H2" => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
361 "HR" => array( "STYLE", "CLASS", "ID", "WIDTH", "lang", "dir", "title", "size", "noshade" ),
362 "LI" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "value" ),
363 "TABLE" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "BORDER", "CELLPADDING",
364 "CELLSPACING", "lang", "dir", "title", "summary", "frame", "rules" ),
365 "TD" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
366 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
367 "dir", "title", "char", "charoff" ),
368 "TH" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
369 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
370 "dir", "title", "char", "charoff" ),
371 "TR" => array( "CLASS", "STYLE", "ID", "BGCOLOR", "ALIGN", "VALIGN", "lang", "dir", "title", "char", "charoff" ),
372 "UL" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "type" ),
373 "P" => array( "style", "class", "id", "align", "lang", "dir", "title" ),
374 "blockquote" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "cite" ),
375 "span" => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
376 "code" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
377 "tt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
378 "small" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
379 "big" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
380 "s" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
381 "u" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
382 "del" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
383 "ins" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
384 "sub" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
385 "sup" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
386 "ol" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "start" ),
387 "br" => array( "CLASS", "ID", "STYLE", "title", "clear" ),
388 "cite" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
389 "var" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
390 "dl" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
391 "ruby" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
392 "rt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
393 "rp" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
394 "dt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
395 "dl" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
396 "em" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
397 "strong" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
398 "i" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
399 "thead" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ),
400 "tfoot" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ),
401 "tbody" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ),
402 "colgroup" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width' ),
403 "col" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width' ),
404 "pre" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "width" ),
406 // extension tags that accept parameters:
407 "sort" => array( "order", "class" ),
408 "ref" => array( "name" ),
409 "categorytree" => array( "hideroot", "mode", "style" ),
410 "chemform" => array( "link", "wikilink", "query" ),
411 "section" => array( "begin", "new" ),
413 // older MW transclusion.
414 "transclude" => array( "page" ),
417 // The types of the HTML that we will be testing were defined above
418 // Note: this needs to be initialized later to be equal to: array_keys(wikiFuzz::$data);
419 // as such, it also needs to also be publicly modifiable.
420 public static $types;
423 // Some attribute values.
424 static private $other = array( "&", "=", ":", "?", "\"", "\n", "%n%n%n%n%n%n%n%n%n%n%n%n", "\\" );
425 static private $ints = array(
427 "0", "-1", "127", "-7897", "89000", "808080", "90928345",
430 // Different ways of saying: '
431 "'", // Long UTF-8 Unicode encoding
432 "'", // dec version.
433 "'", // hex version.
434 "§", // malformed hex variant, MSB not zero.
436 // Different ways of saying: "
437 """, // Long UTF-8 Unicode encoding
439 """, // hex version.
440 "¢", // malformed hex variant, MSB not zero.
442 // Different ways of saying: <
444 "<", // Long UTF-8 Unicode encoding without semicolon (Mediawiki wants the colon)
445 "<", // Long UTF-8 Unicode encoding with semicolon
447 "<", // hex version.
448 "¼", // malformed hex variant, MSB not zero.
449 "<", // mid-length hex version
450 "<", // slightly longer hex version, with capital "X"
452 // Different ways of saying: >
454 ">", // Long UTF-8 Unicode encoding
456 ">", // hex version.
457 "¾", // malformed variant, MSB not zero.
459 // Different ways of saying: [
460 "[", // Long UTF-8 Unicode encoding
462 "[", // hex version.
464 // Different ways of saying: {{
465 "{{", // Long UTF-8 Unicode encoding
467 "{{", // hex version.
469 // Different ways of saying: |
470 "|", // Long UTF-8 Unicode encoding
472 "|", // hex version.
473 "ü", // malformed hex variant, MSB not zero.
475 // a "lignature" - http://www.robinlionheart.com/stds/html4/spchars#ligature
480 // Defines various wiki-related bits of syntax, that can potentially cause
481 // MediaWiki to do something other than just print that literal text.
482 static private $ext = array(
483 // links, templates, parameters.
484 "[[", "]]", "{{", "}}", "|", "[", "]", "{{{", "}}}", "|]]",
495 "=", "==", "===", "====", "=====", "======",
497 // lists (ordered and unordered) and indentation.
498 "\n*", "*", "\n:", ":",
501 // definition lists (dl, dt, dd), newline, and newline with pre, and a tab.
504 // Whitespace: newline, tab, space.
507 // Some XSS attack vectors from http://ha.ckers.org/xss.html
510 "
", // carriage return
511 "\0", // null character
512 "  ", // spaces and meta characters
513 "'';!--\"<XSS>=&{()}", // compact injection of XSS & SQL tester
515 // various NULL fields
523 // signature, redirect, bold, italics.
524 "~~~~", "#REDIRECT [[", "'''", "''",
532 // tag start and tag end.
535 // implicit link creation on URIs.
571 // misc stuff to throw at the Parser.
594 "<!--MWTEMPLATESECTION=",
597 // implicit link creation on booknum, RFC, and PubMed ID usage (both with and without IDs)
610 '__NOTITLECONVERT__',
611 '__NOCONTENTCONVERT__',
617 "__NEWSECTIONLINK__",
620 // more magic words / internal templates.
663 "{{INT:{{LC:contribs-showhideminor}}|",
665 "{{INT:googlesearch|",
668 "{{CONTENTLANGUAGE}}",
669 "{{PAGESINNAMESPACE:}}",
674 "{{#special:emailuser",
677 // Some raw link for magic words.
682 "{{NUMBEROFARTICLES:R",
686 "{{NUMBEROFADMINS:R",
695 // internal Math "extension":
699 // Parser extension functions:
709 // references table for the Cite extension.
712 // Internal Parser tokens - try inserting some of these.
713 "UNIQ25f46b0524f13e67NOPARSE",
714 "UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002",
715 "\x07UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002-QINU",
717 // Inputbox extension:
718 "<inputbox>\ntype=search\nsearchbuttonlabel=\n",
721 // charInsert extension:
725 // wikiHiero extension:
733 // FixedImage extension.
736 // Timeline extension: currently untested.
742 // an external image to test the external image displaying code
743 "http://debian.org/Pics/debian.png",
745 // LabeledSectionTransclusion extension.
755 ** Randomly returns one element of the input array.
757 static public function chooseInput( array $input ) {
758 $randindex = wikiFuzz
::randnum( count( $input ) - 1 );
759 return $input[$randindex];
762 // Max number of parameters for HTML attributes.
763 static private $maxparams = 10;
766 ** Returns random number between finish and start.
768 static public function randnum( $finish, $start = 0 ) {
769 return mt_rand( $start, $finish );
773 ** Returns a mix of random text and random wiki syntax.
775 static private function randstring() {
778 for ( $i = 0; $i < 40; $i++
) {
779 $what = wikiFuzz
::randnum( 1 );
781 if ( $what == 0 ) { // include some random wiki syntax
782 $which = wikiFuzz
::randnum( count( wikiFuzz
::$ext ) - 1 );
783 $thestring .= wikiFuzz
::$ext[$which];
785 else { // include some random text
786 $char = INCLUDE_BINARY
788 // "&#" . wikiFuzz::randnum(255) . ";"
790 ?
"&#x" . str_pad( dechex( wikiFuzz
::randnum( 255 ) ), wikiFuzz
::randnum( 2, 7 ), "0", STR_PAD_LEFT
) . ";"
791 // A truly binary version:
792 // ? chr(wikiFuzz::randnum(0,255))
793 : chr( wikiFuzz
::randnum( 126, 32 ) );
795 $length = wikiFuzz
::randnum( 8 );
796 $thestring .= str_repeat ( $char, $length );
803 ** Returns either random text, or random wiki syntax, or random data from "ints",
804 ** or random data from "other".
806 static private function makestring() {
807 $what = wikiFuzz
::randnum( 2 );
809 return wikiFuzz
::randstring();
811 elseif ( $what == 1 ) {
812 return wikiFuzz
::$ints[wikiFuzz
::randnum( count( wikiFuzz
::$ints ) - 1 )];
815 return wikiFuzz
::$other[wikiFuzz
::randnum( count( wikiFuzz
::$other ) - 1 )];
821 ** Strips out the stuff that Mediawiki balks at in a page's title.
822 ** Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
824 static public function makeTitleSafe( $str ) {
825 $legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
826 return preg_replace_callback(
827 "/([^$legalTitleChars])/",
829 // single quotes are essential here,
830 // or alternative escape all $ as \$
832 'return sprintf( "\\x%02x", ord( $matches[1] ) );'
838 ** Returns a string of fuzz text.
840 static private function loop() {
841 switch ( wikiFuzz
::randnum( 3 ) ) {
842 case 1: // an opening tag, with parameters.
844 $i = wikiFuzz
::randnum( count( wikiFuzz
::$types ) - 1 );
845 $t = wikiFuzz
::$types[$i];
846 $arr = wikiFuzz
::$data[$t];
847 $string .= "<" . $t . " ";
848 $num_params = min( wikiFuzz
::$maxparams, count( $arr ) );
849 for ( $z = 0; $z < $num_params; $z++
) {
850 $badparam = $arr[wikiFuzz
::randnum( count( $arr ) - 1 )];
851 $badstring = wikiFuzz
::makestring();
852 $string .= $badparam . "=" . wikiFuzz
::getRandQuote() . $badstring . wikiFuzz
::getRandQuote() . " ";
856 case 2: // a closing tag.
857 $i = wikiFuzz
::randnum( count( wikiFuzz
::$types ) - 1 );
858 return "</" . wikiFuzz
::$types[$i] . ">";
859 case 3: // a random string, between tags.
860 return wikiFuzz
::makeString();
862 return ""; // catch-all, should never be called.
866 ** Returns one of the three styles of random quote: ', ", and nothing.
868 static private function getRandQuote() {
869 switch ( wikiFuzz
::randnum( 3 ) ) {
871 case 2 : return "\"";
877 ** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
879 static public function makeFuzz( $maxtypes = 2 ) {
881 for ( $k = 0; $k < $maxtypes; $k++
) {
882 $page .= wikiFuzz
::loop();
889 // ////// MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM ///////
892 ** A page test has just these things:
893 ** 1) Form parameters.
894 ** 2) the URL we are going to test those parameters on.
895 ** 3) Any cookies required for the test.
896 ** 4) Whether Tidy should validate the page. Defaults to true, but can be turned off.
897 ** Declared abstract because it should be extended by a class
898 ** that supplies these parameters.
900 abstract class pageTest
{
903 protected $cookie = "";
904 protected $tidyValidate = true;
906 public function getParams() {
907 return $this->params
;
910 public function getPagePath() {
911 return $this->pagePath
;
914 public function getCookie() {
915 return $this->cookie
;
918 public function tidyValidate() {
919 return $this->tidyValidate
;
925 ** a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
927 class editPageTest
extends pageTest
{
928 function __construct() {
929 $this->pagePath
= "index.php?title=WIKIFUZZ";
931 $this->params
= array (
932 "action" => "submit",
933 "wpMinoredit" => wikiFuzz
::makeFuzz( 2 ),
934 "wpPreview" => wikiFuzz
::makeFuzz( 2 ),
935 "wpSection" => wikiFuzz
::makeFuzz( 2 ),
936 "wpEdittime" => wikiFuzz
::makeFuzz( 2 ),
937 "wpSummary" => wikiFuzz
::makeFuzz( 2 ),
938 "wpScrolltop" => wikiFuzz
::makeFuzz( 2 ),
939 "wpStarttime" => wikiFuzz
::makeFuzz( 2 ),
940 "wpAutoSummary" => wikiFuzz
::makeFuzz( 2 ),
941 "wpTextbox1" => wikiFuzz
::makeFuzz( 40 ) // the main wiki text, need lots of this.
944 // sometimes we don't want to specify certain parameters.
945 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpSection"] );
946 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpEdittime"] );
947 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpSummary"] );
948 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpScrolltop"] );
949 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpStarttime"] );
950 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpAutoSummary"] );
951 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpTextbox1"] );
957 ** a page test for "Special:Listusers".
959 class listusersTest
extends pageTest
{
960 function __construct() {
961 $this->pagePath
= "index.php?title=Special:Listusers";
963 $this->params
= array (
964 "title" => wikiFuzz
::makeFuzz( 2 ),
965 "group" => wikiFuzz
::makeFuzz( 2 ),
966 "username" => wikiFuzz
::makeFuzz( 2 ),
967 "Go" => wikiFuzz
::makeFuzz( 2 ),
968 "limit" => wikiFuzz
::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
969 "offset" => wikiFuzz
::chooseInput( array( "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz
::makeFuzz( 2 ) ) )
976 ** a page test for "Special:Search".
978 class searchTest
extends pageTest
{
979 function __construct() {
980 $this->pagePath
= "index.php?title=Special:Search";
982 $this->params
= array (
983 "action" => "index.php?title=Special:Search",
984 "ns0" => wikiFuzz
::makeFuzz( 2 ),
985 "ns1" => wikiFuzz
::makeFuzz( 2 ),
986 "ns2" => wikiFuzz
::makeFuzz( 2 ),
987 "ns3" => wikiFuzz
::makeFuzz( 2 ),
988 "ns4" => wikiFuzz
::makeFuzz( 2 ),
989 "ns5" => wikiFuzz
::makeFuzz( 2 ),
990 "ns6" => wikiFuzz
::makeFuzz( 2 ),
991 "ns7" => wikiFuzz
::makeFuzz( 2 ),
992 "ns8" => wikiFuzz
::makeFuzz( 2 ),
993 "ns9" => wikiFuzz
::makeFuzz( 2 ),
994 "ns10" => wikiFuzz
::makeFuzz( 2 ),
995 "ns11" => wikiFuzz
::makeFuzz( 2 ),
996 "ns12" => wikiFuzz
::makeFuzz( 2 ),
997 "ns13" => wikiFuzz
::makeFuzz( 2 ),
998 "ns14" => wikiFuzz
::makeFuzz( 2 ),
999 "ns15" => wikiFuzz
::makeFuzz( 2 ),
1000 "redirs" => wikiFuzz
::makeFuzz( 2 ),
1001 "search" => wikiFuzz
::makeFuzz( 2 ),
1002 "offset" => wikiFuzz
::chooseInput( array( "", "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz
::makeFuzz( 2 ) ) ),
1003 "fulltext" => wikiFuzz
::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz
::makeFuzz( 2 ) ) ),
1004 "searchx" => wikiFuzz
::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz
::makeFuzz( 2 ) ) )
1011 ** a page test for "Special:Recentchanges".
1013 class recentchangesTest
extends pageTest
{
1014 function __construct() {
1015 $this->pagePath
= "index.php?title=Special:Recentchanges";
1017 $this->params
= array (
1018 "action" => wikiFuzz
::makeFuzz( 2 ),
1019 "title" => wikiFuzz
::makeFuzz( 2 ),
1020 "namespace" => wikiFuzz
::chooseInput( range( -1, 15 ) ),
1021 "Go" => wikiFuzz
::makeFuzz( 2 ),
1022 "invert" => wikiFuzz
::chooseInput( array( "-1", "---'----------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1023 "hideanons" => wikiFuzz
::chooseInput( array( "-1", "------'-------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1024 'limit' => wikiFuzz
::chooseInput( array( "0", "-1", "---------'----0", "+1", "81340909772349234", wikiFuzz
::makeFuzz( 2 ) ) ),
1025 "days" => wikiFuzz
::chooseInput( array( "-1", "----------'---0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1026 "hideminor" => wikiFuzz
::chooseInput( array( "-1", "-----------'--0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1027 "hidebots" => wikiFuzz
::chooseInput( array( "-1", "---------'----0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1028 "hideliu" => wikiFuzz
::chooseInput( array( "-1", "-------'------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1029 "hidepatrolled" => wikiFuzz
::chooseInput( array( "-1", "-----'--------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1030 "hidemyself" => wikiFuzz
::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1031 'categories_any' => wikiFuzz
::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1032 'categories' => wikiFuzz
::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1033 'feed' => wikiFuzz
::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) )
1040 ** a page test for "Special:Prefixindex".
1042 class prefixindexTest
extends pageTest
{
1043 function __construct() {
1044 $this->pagePath
= "index.php?title=Special:Prefixindex";
1046 $this->params
= array (
1047 "title" => "Special:Prefixindex",
1048 "namespace" => wikiFuzz
::randnum( -10, 101 ),
1049 "Go" => wikiFuzz
::makeFuzz( 2 )
1052 // sometimes we want 'prefix', sometimes we want 'from', and sometimes we want nothing.
1053 if ( wikiFuzz
::randnum( 3 ) == 0 ) {
1054 $this->params
["prefix"] = wikiFuzz
::chooseInput( array( "-1", "-----'--------0", "+++--+1",
1055 wikiFuzz
::randnum( -10, 8134 ), wikiFuzz
::makeFuzz( 2 ) ) );
1057 if ( wikiFuzz
::randnum( 3 ) == 0 ) {
1058 $this->params
["from"] = wikiFuzz
::chooseInput( array( "-1", "-----'--------0", "+++--+1",
1059 wikiFuzz
::randnum( -10, 8134 ), wikiFuzz
::makeFuzz( 2 ) ) );
1066 ** a page test for "Special:MIMEsearch".
1068 class mimeSearchTest
extends pageTest
{
1069 function __construct() {
1070 $this->pagePath
= "index.php?title=Special:MIMEsearch";
1072 $this->params
= array (
1073 "action" => "index.php?title=Special:MIMEsearch",
1074 "mime" => wikiFuzz
::makeFuzz( 3 ),
1075 'limit' => wikiFuzz
::chooseInput( array( "0", "-1", "-------'------0", "+1", "81342321351235325", wikiFuzz
::makeFuzz( 2 ) ) ),
1076 'offset' => wikiFuzz
::chooseInput( array( "0", "-1", "-----'--------0", "+1", "81341231235365252234324", wikiFuzz
::makeFuzz( 2 ) ) )
1083 ** a page test for "Special:Log".
1085 class specialLogTest
extends pageTest
{
1086 function __construct() {
1087 $this->pagePath
= "index.php?title=Special:Log";
1089 $this->params
= array (
1090 "type" => wikiFuzz
::chooseInput( array( "", wikiFuzz
::makeFuzz( 2 ) ) ),
1091 "par" => wikiFuzz
::makeFuzz( 2 ),
1092 "user" => wikiFuzz
::makeFuzz( 2 ),
1093 "page" => wikiFuzz
::makeFuzz( 2 ),
1094 "from" => wikiFuzz
::makeFuzz( 2 ),
1095 "until" => wikiFuzz
::makeFuzz( 2 ),
1096 "title" => wikiFuzz
::makeFuzz( 2 )
1103 ** a page test for "Special:Userlogin", with a successful login.
1105 class successfulUserLoginTest
extends pageTest
{
1106 function __construct() {
1107 $this->pagePath
= "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . wikiFuzz
::makeFuzz( 2 );
1109 $this->params
= array (
1110 "wpName" => USER_ON_WIKI
,
1111 // sometimes real password, sometimes not:
1112 'wpPassword' => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ), USER_PASSWORD
) ),
1113 'wpRemember' => wikiFuzz
::makeFuzz( 2 )
1116 $this->cookie
= "wikidb_session=" . wikiFuzz
::chooseInput( array( "1" , wikiFuzz
::makeFuzz( 2 ) ) );
1122 ** a page test for "Special:Userlogin".
1124 class userLoginTest
extends pageTest
{
1125 function __construct() {
1127 $this->pagePath
= "index.php?title=Special:Userlogin";
1129 $this->params
= array (
1130 'wpRetype' => wikiFuzz
::makeFuzz( 2 ),
1131 'wpRemember' => wikiFuzz
::makeFuzz( 2 ),
1132 'wpRealName' => wikiFuzz
::makeFuzz( 2 ),
1133 'wpPassword' => wikiFuzz
::makeFuzz( 2 ),
1134 'wpName' => wikiFuzz
::makeFuzz( 2 ),
1135 'wpMailmypassword' => wikiFuzz
::makeFuzz( 2 ),
1136 'wpLoginattempt' => wikiFuzz
::makeFuzz( 2 ),
1137 'wpEmail' => wikiFuzz
::makeFuzz( 2 ),
1138 'wpDomain' => wikiFuzz
::chooseInput( array( "", "local", wikiFuzz
::makeFuzz( 2 ) ) ),
1139 'wpCreateaccountMail' => wikiFuzz
::chooseInput( array( "", wikiFuzz
::makeFuzz( 2 ) ) ),
1140 'wpCreateaccount' => wikiFuzz
::chooseInput( array( "", wikiFuzz
::makeFuzz( 2 ) ) ),
1141 'wpCookieCheck' => wikiFuzz
::chooseInput( array( "", wikiFuzz
::makeFuzz( 2 ) ) ),
1142 'type' => wikiFuzz
::chooseInput( array( "signup", "login", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1143 'returnto' => wikiFuzz
::makeFuzz( 2 ),
1144 'action' => wikiFuzz
::chooseInput( array( "", "submitlogin", wikiFuzz
::makeFuzz( 2 ) ) )
1147 $this->cookie
= "wikidb_session=" . wikiFuzz
::chooseInput( array( "1" , wikiFuzz
::makeFuzz( 2 ) ) );
1153 ** a page test for "Special:Ipblocklist" (also includes unblocking)
1155 class ipblocklistTest
extends pageTest
{
1156 function __construct() {
1157 $this->pagePath
= "index.php?title=Special:Ipblocklist";
1159 $this->params
= array (
1160 'wpUnblockAddress' => wikiFuzz
::makeFuzz( 2 ),
1161 'ip' => wikiFuzz
::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz
::makeFuzz( 2 ),
1162 // something like an IP address, sometimes invalid:
1163 ( wikiFuzz
::randnum( 300, -20 ) . "." . wikiFuzz
::randnum( 300, -20 ) . "."
1164 . wikiFuzz
::randnum( 300, -20 ) . "." . wikiFuzz
::randnum( 300, -20 ) ) ) ),
1165 'id' => wikiFuzz
::makeFuzz( 2 ),
1166 'wpUnblockReason' => wikiFuzz
::makeFuzz( 2 ),
1167 'action' => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ), "success", "submit", "unblock" ) ),
1168 'wpEditToken' => wikiFuzz
::makeFuzz( 2 ),
1169 'wpBlock' => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ), "" ) ),
1170 'limit' => wikiFuzz
::chooseInput( array( "0", "-1", "--------'-----0", "+1",
1171 "09700982312351132098234", wikiFuzz
::makeFuzz( 2 ) ) ),
1172 'offset' => wikiFuzz
::chooseInput( array( "0", "-1", "------'-------0", "+1",
1173 "09700980982341535324234234", wikiFuzz
::makeFuzz( 2 ) ) )
1176 // sometimes we don't want to specify certain parameters.
1177 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["action"] );
1178 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["ip"] );
1179 if ( wikiFuzz
::randnum( 2 ) == 0 ) unset( $this->params
["id"] );
1180 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["wpUnblockAddress"] );
1186 ** a page test for "Special:Newimages".
1188 class newImagesTest
extends pageTest
{
1189 function __construct() {
1190 $this->pagePath
= "index.php?title=Special:Newimages";
1192 $this->params
= array (
1193 'hidebots' => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ), "1", "", "-1" ) ),
1194 'wpIlMatch' => wikiFuzz
::makeFuzz( 2 ),
1195 'until' => wikiFuzz
::makeFuzz( 2 ),
1196 'from' => wikiFuzz
::makeFuzz( 2 )
1199 // sometimes we don't want to specify certain parameters.
1200 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["until"] );
1201 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["from"] );
1207 ** a page test for the "Special:Imagelist" page.
1209 class imagelistTest
extends pageTest
{
1210 function __construct() {
1211 $this->pagePath
= "index.php?title=Special:Imagelist";
1213 $this->params
= array (
1214 'sort' => wikiFuzz
::chooseInput( array( "bysize", "byname" , "bydate", wikiFuzz
::makeFuzz( 2 ) ) ),
1215 'limit' => wikiFuzz
::chooseInput( array( "0", "-1", "--------'-----0", "+1", "09700982312351132098234", wikiFuzz
::makeFuzz( 2 ) ) ),
1216 'offset' => wikiFuzz
::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz
::makeFuzz( 2 ) ) ),
1217 'wpIlMatch' => wikiFuzz
::makeFuzz( 2 )
1224 ** a page test for "Special:Export".
1226 class specialExportTest
extends pageTest
{
1227 function __construct() {
1228 $this->pagePath
= "index.php?title=Special:Export";
1230 $this->params
= array (
1231 'action' => wikiFuzz
::chooseInput( array( "submit", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1232 'pages' => wikiFuzz
::makeFuzz( 2 ),
1233 'curonly' => wikiFuzz
::chooseInput( array( "", "0", "-1", wikiFuzz
::makeFuzz( 2 ) ) ),
1234 'listauthors' => wikiFuzz
::chooseInput( array( "", "0", "-1", wikiFuzz
::makeFuzz( 2 ) ) ),
1235 'history' => wikiFuzz
::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz
::makeFuzz( 2 ) ) ),
1239 // For the time being, need to disable "submit" action as Tidy barfs on MediaWiki's XML export.
1240 if ( $this->params
['action'] == 'submit' ) $this->params
['action'] = '';
1242 // Sometimes remove the history field.
1243 if ( wikiFuzz
::randnum( 2 ) == 0 ) unset( $this->params
["history"] );
1245 // page does not produce HTML.
1246 $this->tidyValidate
= false;
1252 ** a page test for "Special:Booksources".
1254 class specialBooksourcesTest
extends pageTest
{
1255 function __construct() {
1256 $this->pagePath
= "index.php?title=Special:Booksources";
1258 $this->params
= array (
1259 'go' => wikiFuzz
::makeFuzz( 2 ),
1260 // ISBN codes have to contain some semi-numeric stuff or will be ignored:
1261 'isbn' => "0X0" . wikiFuzz
::makeFuzz( 2 )
1268 ** a page test for "Special:Allpages".
1270 class specialAllpagesTest
extends pageTest
{
1271 function __construct() {
1272 $this->pagePath
= "index.php?title=Special%3AAllpages";
1274 $this->params
= array (
1275 'from' => wikiFuzz
::makeFuzz( 2 ),
1276 'namespace' => wikiFuzz
::chooseInput( range( -1, 15 ) ),
1277 'go' => wikiFuzz
::makeFuzz( 2 )
1284 ** a page test for the page History.
1286 class pageHistoryTest
extends pageTest
{
1287 function __construct() {
1288 $this->pagePath
= "index.php?title=Main_Page&action=history";
1290 $this->params
= array (
1291 'limit' => wikiFuzz
::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1292 'offset' => wikiFuzz
::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz
::makeFuzz( 2 ) ) ),
1293 "go" => wikiFuzz
::chooseInput( array( "first", "last", wikiFuzz
::makeFuzz( 2 ) ) ),
1294 "dir" => wikiFuzz
::chooseInput( array( "prev", "next", wikiFuzz
::makeFuzz( 2 ) ) ),
1295 "diff" => wikiFuzz
::chooseInput( array( "-1", "--------'-----0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1296 "oldid" => wikiFuzz
::chooseInput( array( "prev", "-1", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1297 "feed" => wikiFuzz
::makeFuzz( 2 )
1304 ** a page test for the Special:Contributions".
1306 class contributionsTest
extends pageTest
{
1307 function __construct() {
1308 $this->pagePath
= "index.php?title=Special:Contributions/" . USER_ON_WIKI
;
1310 $this->params
= array (
1311 'target' => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ), "newbies", USER_ON_WIKI
) ),
1312 'namespace' => wikiFuzz
::chooseInput( array( -1, 15, 1, wikiFuzz
::makeFuzz( 2 ) ) ),
1313 'offset' => wikiFuzz
::chooseInput( array( "0", "-1", "------'-------0", "+1", "982342131232131231241", wikiFuzz
::makeFuzz( 2 ) ) ),
1314 'bot' => wikiFuzz
::chooseInput( array( "", "-1", "0", "1", wikiFuzz
::makeFuzz( 2 ) ) ),
1315 'go' => wikiFuzz
::chooseInput( array( "-1", 'prev', 'next', wikiFuzz
::makeFuzz( 2 ) ) )
1322 ** a page test for viewing a normal page, whilst posting various params.
1324 class viewPageTest
extends pageTest
{
1325 function __construct() {
1326 $this->pagePath
= "index.php?title=Main_Page";
1328 $this->params
= array (
1329 "useskin" => wikiFuzz
::chooseInput( array( "chick", "cologneblue", "myskin",
1330 "nostalgia", "simple", "standard", wikiFuzz
::makeFuzz( 2 ) ) ),
1331 "uselang" => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ),
1332 "ab", "af", "an", "ar", "arc", "as", "ast", "av", "ay", "az", "ba",
1333 "bat-smg", "be", "bg", "bm", "bn", "bo", "bpy", "br", "bs", "ca",
1334 "ce", "cs", "csb", "cv", "cy", "da", "de", "dv", "dz", "el", "en",
1335 "eo", "es", "et", "eu", "fa", "fi", "fo", "fr", "fur", "fy", "ga",
1336 "gn", "gsw", "gu", "he", "hi", "hr", "hu", "ia", "id", "ii", "is",
1337 "it", "ja", "jv", "ka", "km", "kn", "ko", "ks", "ku", "kv", "la",
1338 "li", "lo", "lt", "lv", "mk", "ml", "ms", "nah", "nap", "nds",
1339 "nds-nl", "nl", "nn", "no", "non", "nv", "oc", "or", "os", "pa",
1340 "pl", "pms", "ps", "pt", "pt-br", "qu", "rmy", "ro", "ru", "sc",
1341 "sd", "sk", "sl", "sq", "sr", "sr-ec", "sr-el",
1342 "su", "sv", "ta", "te", "th", "tr", "tt", "ty", "tyv", "udm",
1343 "ug", "uk", "ur", "utf8", "vec", "vi", "wa", "xal", "yi", "za",
1344 "zh", "zh-cn", "zh-hk", "zh-sg", "zh-tw", "zh-tw" ) ),
1345 "returnto" => wikiFuzz
::makeFuzz( 2 ),
1346 "feed" => wikiFuzz
::chooseInput( array( "atom", "rss", wikiFuzz
::makeFuzz( 2 ) ) ),
1347 "rcid" => wikiFuzz
::makeFuzz( 2 ),
1348 "action" => wikiFuzz
::chooseInput( array( "view", "raw", "render", wikiFuzz
::makeFuzz( 2 ), "markpatrolled" ) ),
1349 "printable" => wikiFuzz
::makeFuzz( 2 ),
1350 "oldid" => wikiFuzz
::makeFuzz( 2 ),
1351 "redirect" => wikiFuzz
::makeFuzz( 2 ),
1352 "diff" => wikiFuzz
::makeFuzz( 2 ),
1353 "search" => wikiFuzz
::makeFuzz( 2 ),
1354 "rdfrom" => wikiFuzz
::makeFuzz( 2 ), // things from Article.php from here on:
1355 "token" => wikiFuzz
::makeFuzz( 2 ),
1356 "tbid" => wikiFuzz
::makeFuzz( 2 ),
1357 "action" => wikiFuzz
::chooseInput( array( "purge", wikiFuzz
::makeFuzz( 2 ) ) ),
1358 "wpReason" => wikiFuzz
::makeFuzz( 2 ),
1359 "wpEditToken" => wikiFuzz
::makeFuzz( 2 ),
1360 "from" => wikiFuzz
::makeFuzz( 2 ),
1361 "bot" => wikiFuzz
::makeFuzz( 2 ),
1362 "summary" => wikiFuzz
::makeFuzz( 2 ),
1363 "direction" => wikiFuzz
::chooseInput( array( "next", "prev", wikiFuzz
::makeFuzz( 2 ) ) ),
1364 "section" => wikiFuzz
::makeFuzz( 2 ),
1365 "preload" => wikiFuzz
::makeFuzz( 2 ),
1369 // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
1370 if ( $this->params
["feed"] == "atom" ) { unset( $this->params
["feed"] ); }
1371 else if ( $this->params
["feed"] == "rss" ) { unset( $this->params
["feed"] ); }
1373 // Raw pages cannot really be validated
1374 if ( $this->params
["action"] == "raw" ) unset( $this->params
["action"] );
1376 // sometimes we don't want to specify certain parameters.
1377 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["rcid"] );
1378 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["diff"] );
1379 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["rdfrom"] );
1380 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["oldid"] );
1382 // usually don't want action == purge.
1383 if ( wikiFuzz
::randnum( 6 ) > 1 ) unset( $this->params
["action"] );
1389 ** a page test for "Special:Allmessages".
1391 class specialAllmessagesTest
extends pageTest
{
1392 function __construct() {
1393 $this->pagePath
= "index.php?title=Special:Allmessages";
1395 // only really has one parameter
1396 $this->params
= array (
1397 "ot" => wikiFuzz
::chooseInput( array( "php", "html", wikiFuzz
::makeFuzz( 2 ) ) )
1403 ** a page test for "Special:Newpages".
1405 class specialNewpages
extends pageTest
{
1406 function __construct() {
1407 $this->pagePath
= "index.php?title=Special:Newpages";
1409 $this->params
= array (
1410 "namespace" => wikiFuzz
::chooseInput( range( -1, 15 ) ),
1411 "feed" => wikiFuzz
::chooseInput( array( "atom", "rss", wikiFuzz
::makeFuzz( 2 ) ) ),
1412 'limit' => wikiFuzz
::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134", wikiFuzz
::makeFuzz( 2 ) ) ),
1413 'offset' => wikiFuzz
::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz
::makeFuzz( 2 ) ) )
1416 // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
1417 if ( $this->params
["feed"] == "atom" ) { unset( $this->params
["feed"] ); }
1418 else if ( $this->params
["feed"] == "rss" ) { unset( $this->params
["feed"] ); }
1423 ** a page test for "redirect.php"
1425 class redirectTest
extends pageTest
{
1426 function __construct() {
1427 $this->pagePath
= "redirect.php";
1429 $this->params
= array (
1430 "wpDropdown" => wikiFuzz
::makeFuzz( 2 )
1433 // sometimes we don't want to specify certain parameters.
1434 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpDropdown"] );
1440 ** a page test for "Special:Confirmemail"
1442 class confirmEmail
extends pageTest
{
1443 function __construct() {
1444 // sometimes we send a bogus confirmation code, and sometimes we don't.
1445 $this->pagePath
= "index.php?title=Special:Confirmemail" . wikiFuzz
::chooseInput( array( "", "/" . wikiFuzz
::makeTitleSafe( wikiFuzz
::makeFuzz( 1 ) ) ) );
1447 $this->params
= array (
1448 "token" => wikiFuzz
::makeFuzz( 2 )
1455 ** a page test for "Special:Watchlist"
1456 ** Note: this test would be better if we were logged in.
1458 class watchlistTest
extends pageTest
{
1459 function __construct() {
1460 $this->pagePath
= "index.php?title=Special:Watchlist";
1462 $this->params
= array (
1463 "remove" => wikiFuzz
::chooseInput( array( "Remove checked items from watchlist", wikiFuzz
::makeFuzz( 2 ) ) ),
1464 'days' => wikiFuzz
::chooseInput( array( 0, -1, -230, "--", 3, 9, wikiFuzz
::makeFuzz( 2 ) ) ),
1465 'hideOwn' => wikiFuzz
::chooseInput( array( "", "0", "1", wikiFuzz
::makeFuzz( 2 ) ) ),
1466 'hideBots' => wikiFuzz
::chooseInput( array( "", "0", "1", wikiFuzz
::makeFuzz( 2 ) ) ),
1467 'namespace' => wikiFuzz
::chooseInput( array( "", "0", "1", wikiFuzz
::makeFuzz( 2 ) ) ),
1468 'action' => wikiFuzz
::chooseInput( array( "submit", "clear", wikiFuzz
::makeFuzz( 2 ) ) ),
1469 'id[]' => wikiFuzz
::makeFuzz( 2 ),
1470 'edit' => wikiFuzz
::makeFuzz( 2 ),
1471 'token' => wikiFuzz
::chooseInput( array( "", "1243213", wikiFuzz
::makeFuzz( 2 ) ) )
1474 // sometimes we specifiy "reset", and sometimes we don't.
1475 if ( wikiFuzz
::randnum( 3 ) == 0 ) $this->params
["reset"] = wikiFuzz
::chooseInput( array( "", "0", "1", wikiFuzz
::makeFuzz( 2 ) ) );
1481 ** a page test for "Special:Blockme"
1483 class specialBlockmeTest
extends pageTest
{
1484 function __construct() {
1485 $this->pagePath
= "index.php?title=Special:Blockme";
1487 $this->params
= array ( );
1489 // sometimes we specify "ip", and sometimes we don't.
1490 if ( wikiFuzz
::randnum( 1 ) == 0 ) {
1491 $this->params
["ip"] = wikiFuzz
::chooseInput( array( "10.12.41.213", wikiFuzz
::randnum( -10, 8134 ), wikiFuzz
::makeFuzz( 2 ) ) );
1498 ** a page test for "Special:Movepage"
1500 class specialMovePage
extends pageTest
{
1501 function __construct() {
1502 $this->pagePath
= "index.php?title=Special:Movepage";
1504 $this->params
= array (
1505 "action" => wikiFuzz
::chooseInput( array( "success", "submit", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1506 'wpEditToken' => wikiFuzz
::chooseInput( array( '', 0, 34987987, wikiFuzz
::makeFuzz( 2 ) ) ),
1507 'target' => wikiFuzz
::chooseInput( array( "x", wikiFuzz
::makeTitleSafe( wikiFuzz
::makeFuzz( 2 ) ) ) ),
1508 'wpOldTitle' => wikiFuzz
::chooseInput( array( "z", wikiFuzz
::makeTitleSafe( wikiFuzz
::makeFuzz( 2 ) ), wikiFuzz
::makeFuzz( 2 ) ) ),
1509 'wpNewTitle' => wikiFuzz
::chooseInput( array( "y", wikiFuzz
::makeTitleSafe( wikiFuzz
::makeFuzz( 2 ) ), wikiFuzz
::makeFuzz( 2 ) ) ),
1510 'wpReason' => wikiFuzz
::chooseInput( array( wikiFuzz
::makeFuzz( 2 ) ) ),
1511 'wpMovetalk' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1512 'wpDeleteAndMove' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1513 'wpConfirm' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1514 'talkmoved' => wikiFuzz
::chooseInput( array( "1", wikiFuzz
::makeFuzz( 2 ), "articleexists", 'notalkpage' ) ),
1515 'oldtitle' => wikiFuzz
::makeFuzz( 2 ),
1516 'newtitle' => wikiFuzz
::makeFuzz( 2 ),
1517 'wpMovetalk' => wikiFuzz
::chooseInput( array( "1", "0", wikiFuzz
::makeFuzz( 2 ) ) )
1520 // sometimes we don't want to specify certain parameters.
1521 if ( wikiFuzz
::randnum( 2 ) == 0 ) unset( $this->params
["wpEditToken"] );
1522 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["target"] );
1523 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["wpNewTitle"] );
1524 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpReason"] );
1525 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpOldTitle"] );
1531 ** a page test for "Special:Undelete"
1533 class specialUndelete
extends pageTest
{
1534 function __construct() {
1535 $this->pagePath
= "index.php?title=Special:Undelete";
1537 $this->params
= array (
1538 "action" => wikiFuzz
::chooseInput( array( "submit", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1539 'wpEditToken' => wikiFuzz
::chooseInput( array( '', 0, 34987987, wikiFuzz
::makeFuzz( 2 ) ) ),
1540 'target' => wikiFuzz
::chooseInput( array( "x", wikiFuzz
::makeTitleSafe( wikiFuzz
::makeFuzz( 2 ) ) ) ),
1541 'timestamp' => wikiFuzz
::chooseInput( array( "125223", wikiFuzz
::makeFuzz( 2 ) ) ),
1542 'file' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1543 'restore' => wikiFuzz
::chooseInput( array( "0", "1", wikiFuzz
::makeFuzz( 2 ) ) ),
1544 'preview' => wikiFuzz
::chooseInput( array( "0", "1", wikiFuzz
::makeFuzz( 2 ) ) ),
1545 'wpComment' => wikiFuzz
::makeFuzz( 2 )
1548 // sometimes we don't want to specify certain parameters.
1549 if ( wikiFuzz
::randnum( 2 ) == 0 ) unset( $this->params
["wpEditToken"] );
1550 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["target"] );
1551 if ( wikiFuzz
::randnum( 1 ) == 0 ) unset( $this->params
["restore"] );
1552 if ( wikiFuzz
::randnum( 1 ) == 0 ) unset( $this->params
["preview"] );
1558 ** a page test for "Special:Unlockdb"
1560 class specialUnlockdb
extends pageTest
{
1561 function __construct() {
1562 $this->pagePath
= "index.php?title=Special:Unlockdb";
1564 $this->params
= array (
1565 "action" => wikiFuzz
::chooseInput( array( "submit", "success", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1566 'wpEditToken' => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1567 'wpLockConfirm' => wikiFuzz
::chooseInput( array( "0", "1", wikiFuzz
::makeFuzz( 2 ) ) )
1570 // sometimes we don't want to specify certain parameters.
1571 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpEditToken"] );
1572 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["action"] );
1573 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpLockConfirm"] );
1579 ** a page test for "Special:Lockdb"
1581 class specialLockdb
extends pageTest
{
1582 function __construct() {
1583 $this->pagePath
= "index.php?title=Special:Lockdb";
1585 $this->params
= array (
1586 "action" => wikiFuzz
::chooseInput( array( "submit", "success", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1587 'wpEditToken' => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1588 'wpLockReason' => wikiFuzz
::makeFuzz( 2 ),
1589 'wpLockConfirm' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) )
1592 // sometimes we don't want to specify certain parameters.
1593 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpEditToken"] );
1594 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["action"] );
1595 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpLockConfirm"] );
1601 ** a page test for "Special:Userrights"
1603 class specialUserrights
extends pageTest
{
1604 function __construct() {
1605 $this->pagePath
= "index.php?title=Special:Userrights";
1607 $this->params
= array (
1608 'wpEditToken' => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1609 'user-editname' => wikiFuzz
::chooseInput( array( "Nickj2", "Nickj2\n<xyz>", wikiFuzz
::makeFuzz( 2 ) ) ),
1610 'ssearchuser' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1611 'saveusergroups' => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ), "Save User Groups" ),
1612 'member[]' => wikiFuzz
::chooseInput( array( "0", "bot", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1613 "available[]" => wikiFuzz
::chooseInput( array( "0", "sysop", "bureaucrat", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) )
1616 // sometimes we don't want to specify certain parameters.
1617 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
['ssearchuser'] );
1618 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
['saveusergroups'] );
1624 ** a test for page protection and unprotection.
1626 class pageProtectionForm
extends pageTest
{
1627 function __construct() {
1628 $this->pagePath
= "index.php?title=Main_Page";
1630 $this->params
= array (
1631 "action" => "protect",
1632 'wpEditToken' => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1633 "mwProtect-level-edit" => wikiFuzz
::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz
::makeFuzz( 2 ) ) ),
1634 "mwProtect-level-move" => wikiFuzz
::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz
::makeFuzz( 2 ) ) ),
1635 "mwProtectUnchained" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1636 'mwProtect-reason' => wikiFuzz
::chooseInput( array( "because it was there", wikiFuzz
::makeFuzz( 2 ) ) )
1640 // sometimes we don't want to specify certain parameters.
1641 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["mwProtectUnchained"] );
1642 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
['mwProtect-reason'] );
1648 ** a page test for "Special:Blockip".
1650 class specialBlockip
extends pageTest
{
1651 function __construct() {
1652 $this->pagePath
= "index.php?title=Special:Blockip";
1654 $this->params
= array (
1655 "action" => wikiFuzz
::chooseInput( array( "submit", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1656 'wpEditToken' => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1657 "wpBlockAddress" => wikiFuzz
::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz
::makeFuzz( 2 ),
1658 // something like an IP address, sometimes invalid:
1659 ( wikiFuzz
::randnum( 300, -20 ) . "." . wikiFuzz
::randnum( 300, -20 ) . "."
1660 . wikiFuzz
::randnum( 300, -20 ) . "." . wikiFuzz
::randnum( 300, -20 ) ) ) ),
1661 "ip" => wikiFuzz
::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz
::makeFuzz( 2 ),
1662 // something like an IP address, sometimes invalid:
1663 ( wikiFuzz
::randnum( 300, -20 ) . "." . wikiFuzz
::randnum( 300, -20 ) . "."
1664 . wikiFuzz
::randnum( 300, -20 ) . "." . wikiFuzz
::randnum( 300, -20 ) ) ) ),
1665 "wpBlockOther" => wikiFuzz
::chooseInput( array( '', 'Nickj2', wikiFuzz
::makeFuzz( 2 ) ) ),
1666 "wpBlockExpiry" => wikiFuzz
::chooseInput( array( "other", "2 hours", "1 day", "3 days", "1 week", "2 weeks",
1667 "1 month", "3 months", "6 months", "1 year", "infinite", wikiFuzz
::makeFuzz( 2 ) ) ),
1668 "wpBlockReason" => wikiFuzz
::chooseInput( array( "because it was there", wikiFuzz
::makeFuzz( 2 ) ) ),
1669 "wpAnonOnly" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1670 "wpCreateAccount" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1671 "wpBlock" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) )
1674 // sometimes we don't want to specify certain parameters.
1675 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpBlockOther"] );
1676 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpBlockExpiry"] );
1677 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpBlockReason"] );
1678 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpAnonOnly"] );
1679 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpCreateAccount"] );
1680 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["wpBlockAddress"] );
1681 if ( wikiFuzz
::randnum( 4 ) == 0 ) unset( $this->params
["ip"] );
1687 ** a test for the imagepage.
1689 class imagepageTest
extends pageTest
{
1690 function __construct() {
1691 $this->pagePath
= "index.php?title=Image:Small-email.png";
1693 $this->params
= array (
1694 "image" => wikiFuzz
::chooseInput( array( "Small-email.png", wikiFuzz
::makeFuzz( 2 ) ) ),
1695 "wpReason" => wikiFuzz
::makeFuzz( 2 ),
1696 "oldimage" => wikiFuzz
::chooseInput( array( "Small-email.png", wikiFuzz
::makeFuzz( 2 ) ) ),
1697 "wpEditToken" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1700 // sometimes we don't want to specify certain parameters.
1701 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["image"] );
1702 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpReason"] );
1703 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["oldimage"] );
1704 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpEditToken"] );
1710 ** a test for page deletion form.
1712 class pageDeletion
extends pageTest
{
1713 function __construct() {
1714 $this->pagePath
= "index.php?title=Main_Page&action=delete";
1716 $this->params
= array (
1717 "wpEditToken" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1718 "wpReason" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1719 "wpConfirm" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1722 // sometimes we don't want to specify certain parameters.
1723 if ( wikiFuzz
::randnum( 5 ) == 0 ) unset( $this->params
["wpReason"] );
1724 if ( wikiFuzz
::randnum( 5 ) == 0 ) unset( $this->params
["wpEditToken"] );
1725 if ( wikiFuzz
::randnum( 5 ) == 0 ) unset( $this->params
["wpConfirm"] );
1732 ** a test for Revision Deletion.
1734 class specialRevisionDelete
extends pageTest
{
1735 function __construct() {
1736 $this->pagePath
= "index.php?title=Special:Revisiondelete";
1738 $this->params
= array (
1739 "target" => wikiFuzz
::chooseInput( array( "Main Page", wikiFuzz
::makeFuzz( 2 ) ) ),
1740 "oldid" => wikiFuzz
::makeFuzz( 2 ),
1741 "oldid[]" => wikiFuzz
::makeFuzz( 2 ),
1742 "wpReason" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1743 "revdelete-hide-text" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1744 "revdelete-hide-comment" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1745 "revdelete-hide-user" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1746 "revdelete-hide-restricted" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1749 // sometimes we don't want to specify certain parameters.
1750 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["target"] );
1751 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["oldid"] );
1752 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["oldid[]"] );
1753 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["wpReason"] );
1754 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["revdelete-hide-text"] );
1755 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["revdelete-hide-comment"] );
1756 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["revdelete-hide-user"] );
1757 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["revdelete-hide-restricted"] );
1763 ** a test for Special:Import.
1765 class specialImport
extends pageTest
{
1766 function __construct() {
1767 $this->pagePath
= "index.php?title=Special:Import";
1769 $this->params
= array (
1770 "action" => "submit",
1771 "source" => wikiFuzz
::chooseInput( array( "upload", "interwiki", wikiFuzz
::makeFuzz( 2 ) ) ),
1772 "MAX_FILE_SIZE" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1773 "xmlimport" => wikiFuzz
::chooseInput( array( "/var/www/hosts/mediawiki/wiki/AdminSettings.php", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1774 "namespace" => wikiFuzz
::chooseInput( array( wikiFuzz
::randnum( 30, -6 ), wikiFuzz
::makeFuzz( 2 ) ) ),
1775 "interwiki" => wikiFuzz
::makeFuzz( 2 ),
1776 "interwikiHistory" => wikiFuzz
::makeFuzz( 2 ),
1777 "frompage" => wikiFuzz
::makeFuzz( 2 ),
1780 // sometimes we don't want to specify certain parameters.
1781 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["action"] );
1782 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["source"] );
1783 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["MAX_FILE_SIZE"] );
1784 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["xmlimport"] );
1785 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["interwiki"] );
1786 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["interwikiHistory"] );
1787 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["frompage"] );
1789 // Note: Need to do a file upload to fully test this Special page.
1795 ** a test for thumb.php
1797 class thumbTest
extends pageTest
{
1798 function __construct() {
1799 $this->pagePath
= "thumb.php";
1801 $this->params
= array (
1802 "f" => wikiFuzz
::chooseInput( array( "..", "\\", "small-email.png", wikiFuzz
::makeFuzz( 2 ) ) ),
1803 "w" => wikiFuzz
::chooseInput( array( "80", wikiFuzz
::randnum( 6000, -200 ), wikiFuzz
::makeFuzz( 2 ) ) ),
1804 "r" => wikiFuzz
::chooseInput( array( "0", wikiFuzz
::makeFuzz( 2 ) ) ),
1807 // sometimes we don't want to specify certain parameters.
1808 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["f"] );
1809 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["w"] );
1810 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["r"] );
1816 ** a test for trackback.php
1818 class trackbackTest
extends pageTest
{
1819 function __construct() {
1820 $this->pagePath
= "trackback.php";
1822 $this->params
= array (
1823 "url" => wikiFuzz
::makeFuzz( 2 ),
1824 "blog_name" => wikiFuzz
::chooseInput( array( "80", wikiFuzz
::randnum( 6000, -200 ), wikiFuzz
::makeFuzz( 2 ) ) ),
1825 "article" => wikiFuzz
::chooseInput( array( "Main Page", wikiFuzz
::makeFuzz( 2 ) ) ),
1826 "title" => wikiFuzz
::chooseInput( array( "Main Page", wikiFuzz
::makeFuzz( 2 ) ) ),
1827 "excerpt" => wikiFuzz
::makeFuzz( 2 ),
1830 // sometimes we don't want to specify certain parameters.
1831 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["title"] );
1832 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["excerpt"] );
1834 // page does not produce HTML.
1835 $this->tidyValidate
= false;
1841 ** a test for profileinfo.php
1843 class profileInfo
extends pageTest
{
1844 function __construct() {
1845 $this->pagePath
= "profileinfo.php";
1847 $this->params
= array (
1848 "expand" => wikiFuzz
::makeFuzz( 2 ),
1849 "sort" => wikiFuzz
::chooseInput( array( "time", "count", "name", wikiFuzz
::makeFuzz( 2 ) ) ),
1850 "filter" => wikiFuzz
::chooseInput( array( "Main Page", wikiFuzz
::makeFuzz( 2 ) ) ),
1853 // sometimes we don't want to specify certain parameters.
1854 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["sort"] );
1855 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["filter"] );
1861 ** a test for Special:Cite (extension Special page).
1863 class specialCite
extends pageTest
{
1864 function __construct() {
1865 $this->pagePath
= "index.php?title=Special:Cite";
1867 $this->params
= array (
1868 "page" => wikiFuzz
::chooseInput( array( "\" onmouseover=\"alert(1);\"", "Main Page", wikiFuzz
::makeFuzz( 2 ) ) ),
1869 "id" => wikiFuzz
::chooseInput( array( "-1", "0", "------'-------0", "+1", "-9823412312312412435", wikiFuzz
::makeFuzz( 2 ) ) ),
1872 // sometimes we don't want to specify certain parameters.
1873 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["page"] );
1874 if ( wikiFuzz
::randnum( 6 ) == 0 ) unset( $this->params
["id"] );
1880 ** a test for Special:Filepath (extension Special page).
1882 class specialFilepath
extends pageTest
{
1883 function __construct() {
1884 $this->pagePath
= "index.php?title=Special:Filepath";
1886 $this->params
= array (
1887 "file" => wikiFuzz
::chooseInput( array( "Small-email.png", "Small-email.png" . wikiFuzz
::makeFuzz( 1 ), wikiFuzz
::makeFuzz( 2 ) ) ),
1894 ** a test for Special:Makebot (extension Special page).
1896 class specialMakebot
extends pageTest
{
1897 function __construct() {
1898 $this->pagePath
= "index.php?title=Special:Makebot";
1900 $this->params
= array (
1901 "username" => wikiFuzz
::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz
::makeFuzz( 1 ) ) ),
1902 "dosearch" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1903 "grant" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1904 "comment" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1905 "token" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1908 // sometimes we don't want to specify certain parameters.
1909 if ( wikiFuzz
::randnum( 2 ) == 0 ) unset( $this->params
["dosearch"] );
1910 if ( wikiFuzz
::randnum( 2 ) == 0 ) unset( $this->params
["grant"] );
1911 if ( wikiFuzz
::randnum( 5 ) == 0 ) unset( $this->params
["token"] );
1917 ** a test for Special:Makesysop (extension Special page).
1919 class specialMakesysop
extends pageTest
{
1920 function __construct() {
1921 $this->pagePath
= "index.php?title=Special:Makesysop";
1923 $this->params
= array (
1924 "wpMakesysopUser" => wikiFuzz
::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz
::makeFuzz( 1 ) ) ),
1925 "action" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1926 "wpMakesysopSubmit" => wikiFuzz
::chooseInput( array( "0", "1", "++--34234", wikiFuzz
::makeFuzz( 2 ) ) ),
1927 "wpEditToken" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1928 "wpSetBureaucrat" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1931 // sometimes we don't want to specify certain parameters.
1932 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["wpMakesysopSubmit"] );
1933 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["wpEditToken"] );
1934 if ( wikiFuzz
::randnum( 3 ) == 0 ) unset( $this->params
["wpSetBureaucrat"] );
1940 ** a test for Special:Renameuser (extension Special page).
1942 class specialRenameuser
extends pageTest
{
1943 function __construct() {
1944 $this->pagePath
= "index.php?title=Special:Renameuser";
1946 $this->params
= array (
1947 "oldusername" => wikiFuzz
::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz
::makeFuzz( 1 ) ) ),
1948 "newusername" => wikiFuzz
::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz
::makeFuzz( 1 ) ) ),
1949 "token" => wikiFuzz
::chooseInput( array( "20398702394", "", wikiFuzz
::makeFuzz( 2 ) ) ),
1956 ** a test for Special:Linksearch (extension Special page).
1958 class specialLinksearch
extends pageTest
{
1959 function __construct() {
1960 $this->pagePath
= "index.php?title=Special%3ALinksearch";
1962 $this->params
= array (
1963 "target" => wikiFuzz
::makeFuzz( 2 ),
1966 // sometimes we don't want to specify certain parameters.
1967 if ( wikiFuzz
::randnum( 10 ) == 0 ) unset( $this->params
["target"] );
1973 ** a test for Special:CategoryTree (extension Special page).
1975 class specialCategoryTree
extends pageTest
{
1976 function __construct() {
1977 $this->pagePath
= "index.php?title=Special:CategoryTree";
1979 $this->params
= array (
1980 "target" => wikiFuzz
::makeFuzz( 2 ),
1981 "from" => wikiFuzz
::makeFuzz( 2 ),
1982 "until" => wikiFuzz
::makeFuzz( 2 ),
1983 "showas" => wikiFuzz
::makeFuzz( 2 ),
1984 "mode" => wikiFuzz
::chooseInput( array( "pages", "categories", "all", wikiFuzz
::makeFuzz( 2 ) ) ),
1987 // sometimes we do want to specify certain parameters.
1988 if ( wikiFuzz
::randnum( 5 ) == 0 ) $this->params
["notree"] = wikiFuzz
::chooseInput( array( "1", 0, "", wikiFuzz
::makeFuzz( 2 ) ) );
1994 ** a test for "Special:Chemicalsources" (extension Special page).
1996 class specialChemicalsourcesTest
extends pageTest
{
1997 function __construct() {
1998 $this->pagePath
= "index.php?title=Special:Chemicalsources";
2000 // choose an input format to use.
2001 $format = wikiFuzz
::chooseInput(
2019 // values for different formats usually start with either letters or numbers.
2020 switch ( $format ) {
2021 case 'Name' : $value = "A"; break;
2024 case 'Formula': $value = "C"; break;
2025 default : $value = "0"; break;
2028 // and then we append the fuzz input.
2029 $this->params
= array ( $format => $value . wikiFuzz
::makeFuzz( 2 ) );
2035 ** A test for api.php (programmatic interface to MediaWiki in XML/JSON/RSS/etc formats).
2036 ** Quite involved to test because there are lots of options/parameters, and because
2037 ** for a lot of the functionality if all the parameters don't make sense then it just
2038 ** returns the help screen - so currently a lot of the tests aren't actually doing much
2039 ** because something wasn't right in the query.
2041 ** @todo: Incomplete / unfinished; Runs too fast (suggests not much testing going on).
2043 class api
extends pageTest
{
2046 private static function loginMode() {
2047 $arr = array ( "lgname" => wikiFuzz
::makeFuzz( 2 ),
2048 "lgpassword" => wikiFuzz
::makeFuzz( 2 ),
2050 // sometimes we want to specify the extra "lgdomain" parameter.
2051 if ( wikiFuzz
::randnum( 3 ) == 0 ) {
2052 $arr["lgdomain"] = wikiFuzz
::chooseInput( array( "1", 0, "", wikiFuzz
::makeFuzz( 2 ) ) );
2058 // API OpenSearch mode.
2059 private static function opensearchMode() {
2060 return array ( "search" => wikiFuzz
::makeFuzz( 2 ) );
2063 // API watchlist feed mode.
2064 private static function feedwatchlistMode() {
2065 // FIXME: add "wikiFuzz::makeFuzz(2)" as possible value below?
2066 return array ( "feedformat" => wikiFuzz
::chooseInput( array( "rss", "atom" ) ) );
2070 private static function queryMode() {
2071 // FIXME: add "wikiFuzz::makeFuzz(2)" as possible params for the elements below?
2072 // Suspect this will stuff up the tests more, but need to check.
2074 // FIXME: More titles.
2075 "titles" => wikiFuzz
::chooseInput( array( "Main Page" ) ),
2076 // FIXME: More pageids.
2078 "prop" => wikiFuzz
::chooseInput( array( "info", "revisions", "watchlist" ) ),
2079 "list" => wikiFuzz
::chooseInput( array( "allpages", "logevents", "watchlist", "usercontribs", "recentchanges", "backlinks", "embeddedin", "imagelinks" ) ),
2080 "meta" => wikiFuzz
::chooseInput( array( "siteinfo" ) ),
2081 "generator" => wikiFuzz
::chooseInput( array( "allpages", "logevents", "watchlist", "info", "revisions" ) ),
2082 "siprop" => wikiFuzz
::chooseInput( array( "general", "namespaces", "general|namespaces" ) ),
2085 // Add extra parameters based on what list choice we got.
2086 switch ( $params["list"] ) {
2087 case "usercontribs" : self
::addListParams ( $params, "uc", array( "limit", "start", "end", "user", "dir" ) ); break;
2088 case "allpages" : self
::addListParams ( $params, "ap", array( "from", "prefix", "namespace", "filterredir", "limit" ) ); break;
2089 case "watchlist" : self
::addListParams ( $params, "wl", array( "allrev", "start", "end", "namespace", "dir", "limit", "prop" ) ); break;
2090 case "logevents" : self
::addListParams ( $params, "le", array( "limit", "type", "start", "end", "user", "dir" ) ); break;
2091 case "recentchanges": self
::addListParams ( $params, "rc", array( "limit", "prop", "show", "namespace", "start", "end", "dir" ) ); break;
2092 case "backlinks" : self
::addListParams ( $params, "bl", array( "continue", "namespace", "redirect", "limit" ) ); break;
2093 case "embeddedin" : self
::addListParams ( $params, "ei", array( "continue", "namespace", "redirect", "limit" ) ); break;
2094 case "imagelinks" : self
::addListParams ( $params, "il", array( "continue", "namespace", "redirect", "limit" ) ); break;
2097 if ( $params["prop"] == "revisions" ) {
2098 self
::addListParams ( $params, "rv", array( "prop", "limit", "startid", "endid", "end", "dir" ) );
2101 // Sometimes we want redirects, sometimes we don't.
2102 if ( wikiFuzz
::randnum( 3 ) == 0 ) {
2103 $params["redirects"] = wikiFuzz
::chooseInput( array( "1", 0, "", wikiFuzz
::makeFuzz( 2 ) ) );
2109 // Adds all the elements to the array, using the specified prefix.
2110 private static function addListParams( &$array, $prefix, $elements ) {
2111 foreach ( $elements as $element ) {
2112 $array[$prefix . $element] = self
::getParamDetails( $element );
2116 // For a given element name, returns the data for that element.
2117 private static function getParamDetails( $element ) {
2118 switch ( $element ) {
2123 case 'limit' : return wikiFuzz
::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", "320742734234235", "20060230121212", wikiFuzz
::randnum( 9000, -100 ), wikiFuzz
::makeFuzz( 2 ) ) );
2124 case 'dir' : return wikiFuzz
::chooseInput( array( "newer", "older", wikiFuzz
::makeFuzz( 2 ) ) );
2125 case 'user' : return wikiFuzz
::chooseInput( array( USER_ON_WIKI
, wikiFuzz
::makeFuzz( 2 ) ) );
2126 case 'namespace' : return wikiFuzz
::chooseInput( array( -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 200000, wikiFuzz
::makeFuzz( 2 ) ) );
2127 case 'filterredir': return wikiFuzz
::chooseInput( array( "all", "redirects", "nonredirectsallpages", wikiFuzz
::makeFuzz( 2 ) ) );
2128 case 'allrev' : return wikiFuzz
::chooseInput( array( "1", 0, "", wikiFuzz
::makeFuzz( 2 ) ) );
2129 case 'prop' : return wikiFuzz
::chooseInput( array( "user", "comment", "timestamp", "patrol", "flags", "user|user|comment|flags", wikiFuzz
::makeFuzz( 2 ) ) );
2130 case 'type' : return wikiFuzz
::chooseInput( array( "block", "protect", "rights", "delete", "upload", "move", "import", "renameuser", "newusers", "makebot", wikiFuzz
::makeFuzz( 2 ) ) );
2131 case 'hide' : return wikiFuzz
::chooseInput( array( "minor", "bots", "anons", "liu", "liu|bots|", wikiFuzz
::makeFuzz( 2 ) ) );
2132 case 'show' : return wikiFuzz
::chooseInput( array( 'minor', '!minor', 'bot', '!bot', 'anon', '!anon', wikiFuzz
::makeFuzz( 2 ) ) );
2133 default : return wikiFuzz
::makeFuzz( 2 );
2138 function __construct() {
2139 $this->pagePath
= "api.php";
2141 $modes = array ( "help",
2146 $action = wikiFuzz
::chooseInput( array_merge ( $modes, array( wikiFuzz
::makeFuzz( 2 ) ) ) );
2148 switch ( $action ) {
2149 case "login" : $this->params
= self
::loginMode();
2151 case "opensearch" : $this->params
= self
::opensearchMode();
2153 case "feedwatchlist" : $this->params
= self
::feedwatchlistMode();
2155 case "query" : $this->params
= self
::queryMode();
2158 default : // Do something random - "Crazy Ivan" mode.
2159 $random_mode = wikiFuzz
::chooseInput( $modes ) . "Mode";
2160 // There is no "helpMode".
2161 if ( $random_mode == "helpMode" ) $random_mode = "queryMode";
2162 $this->params
= self
::$random_mode();
2166 // Save the selected action.
2167 $this->params
["action"] = $action;
2170 // FIXME: need to get this cookie dynamically set, rather than hard-coded.
2171 $this->cookie
= "wikidbUserID=10001; wikidbUserName=Test; wikidb_session=178df0fe68c75834643af65dec9ec98a; wikidbToken=1adc6753d62c44aec950c024d7ae0540";
2174 $this->params
["format"] = wikiFuzz
::chooseInput( array( "json", "jsonfm", "php", "phpfm",
2175 "wddx", "wddxfm", "xml", "xmlfm",
2176 "yaml", "yamlfm", "raw", "rawfm",
2177 wikiFuzz
::makeFuzz( 2 ) ) );
2179 // Page does not produce HTML (sometimes).
2180 $this->tidyValidate
= false;
2186 ** a page test for the GeSHi extension.
2188 class GeSHi_Test
extends pageTest
{
2190 private function getGeSHiContent() {
2191 return "<source lang=\"" . $this->getLang() . "\" "
2192 . ( wikiFuzz
::randnum( 2 ) == 0 ?
"line " : "" )
2193 . ( wikiFuzz
::randnum( 2 ) == 0 ?
"strict " : "" )
2194 . "start=" . wikiFuzz
::chooseInput( array( wikiFuzz
::randnum( -6000, 6000 ), wikiFuzz
::makeFuzz( 2 ) ) )
2196 . wikiFuzz
::makeFuzz( 2 )
2200 private function getLang() {
2201 return wikiFuzz
::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp",
2202 "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl",
2203 "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas",
2204 "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty",
2205 "sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikiFuzz
::makeFuzz( 1 ) ) );
2208 function __construct() {
2209 $this->pagePath
= "index.php?title=WIKIFUZZ";
2211 $this->params
= array (
2212 "action" => "submit",
2213 "wpMinoredit" => "test",
2214 "wpPreview" => "test",
2215 "wpSection" => "test",
2216 "wpEdittime" => "test",
2217 "wpSummary" => "test",
2218 "wpScrolltop" => "test",
2219 "wpStarttime" => "test",
2220 "wpAutoSummary" => "test",
2221 "wpTextbox1" => $this->getGeSHiContent() // the main wiki text, contains fake GeSHi content.
2228 ** selects a page test to run.
2230 function selectPageTest( $count ) {
2232 // if the user only wants a specific test, then only ever give them that.
2233 if ( defined( "SPECIFIC_TEST" ) ) {
2234 $testType = SPECIFIC_TEST
;
2235 return new $testType ();
2238 // Some of the time we test Special pages, the remaining
2239 // time we test using the standard edit page.
2240 switch ( $count %
100 ) {
2241 case 0 : return new successfulUserLoginTest();
2242 case 1 : return new listusersTest();
2243 case 2 : return new searchTest();
2244 case 3 : return new recentchangesTest();
2245 case 4 : return new prefixindexTest();
2246 case 5 : return new mimeSearchTest();
2247 case 6 : return new specialLogTest();
2248 case 7 : return new userLoginTest();
2249 case 8 : return new ipblocklistTest();
2250 case 9 : return new newImagesTest();
2251 case 10: return new imagelistTest();
2252 case 11: return new specialExportTest();
2253 case 12: return new specialBooksourcesTest();
2254 case 13: return new specialAllpagesTest();
2255 case 14: return new pageHistoryTest();
2256 case 15: return new contributionsTest();
2257 case 16: return new viewPageTest();
2258 case 17: return new specialAllmessagesTest();
2259 case 18: return new specialNewpages();
2260 case 19: return new searchTest();
2261 case 20: return new redirectTest();
2262 case 21: return new confirmEmail();
2263 case 22: return new watchlistTest();
2264 case 23: return new specialBlockmeTest();
2265 case 24: return new specialUndelete();
2266 case 25: return new specialMovePage();
2267 case 26: return new specialUnlockdb();
2268 case 27: return new specialLockdb();
2269 case 28: return new specialUserrights();
2270 case 29: return new pageProtectionForm();
2271 case 30: return new specialBlockip();
2272 case 31: return new imagepageTest();
2273 case 32: return new pageDeletion();
2274 case 33: return new specialRevisionDelete();
2275 case 34: return new specialImport();
2276 case 35: return new thumbTest();
2277 case 36: return new trackbackTest();
2278 case 37: return new profileInfo();
2279 case 38: return new specialCite();
2280 case 39: return new specialFilepath();
2281 case 40: return new specialMakebot();
2282 case 41: return new specialMakesysop();
2283 case 42: return new specialRenameuser();
2284 case 43: return new specialLinksearch();
2285 case 44: return new specialCategoryTree();
2286 case 45: return new api();
2287 case 45: return new specialChemicalsourcesTest();
2288 default: return new editPageTest();
2293 // ///////////////////// SAVING OUTPUT /////////////////////////
2296 ** Utility function for saving a file. Currently has no error checking.
2298 function saveFile( $data, $name ) {
2299 file_put_contents( $name, $data );
2304 ** Returns a test as an experimental GET-to-POST URL.
2305 ** This doesn't seem to always work though, and sometimes the output is too long
2306 ** to be a valid GET URL, so we also save in other formats.
2308 function getAsURL( pageTest
$test ) {
2309 $used_question_mark = ( strpos( $test->getPagePath(), "?" ) !== false );
2310 $retval = "http://get-to-post.nickj.org/?" . WIKI_BASE_URL
. $test->getPagePath();
2311 foreach ( $test->getParams() as $param => $value ) {
2312 if ( !$used_question_mark ) {
2314 $used_question_mark = true;
2319 $retval .= $param . "=" . urlencode( $value );
2326 ** Saves a plain-text human-readable version of a test.
2328 function saveTestAsText( pageTest
$test, $filename ) {
2329 $str = "Test: " . $test->getPagePath();
2330 foreach ( $test->getParams() as $param => $value ) {
2331 $str .= "\n$param: $value";
2333 $str .= "\nGet-to-post URL: " . getAsURL( $test ) . "\n";
2334 saveFile( $str, $filename );
2339 ** Saves a test as a standalone basic PHP script that shows this one problem.
2340 ** Resulting script requires PHP-Curl be installed in order to work.
2342 function saveTestAsPHP( pageTest
$test, $filename ) {
2344 . "\$params = " . var_export( escapeForCurl( $test->getParams() ), true ) . ";\n"
2345 . "\$ch = curl_init();\n"
2346 . "curl_setopt(\$ch, CURLOPT_POST, 1);\n"
2347 . "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \$params );\n"
2348 . "curl_setopt(\$ch, CURLOPT_URL, " . var_export( WIKI_BASE_URL
. $test->getPagePath(), true ) . ");\n"
2349 . "curl_setopt(\$ch, CURLOPT_RETURNTRANSFER,1);\n"
2350 . ( $test->getCookie() ?
"curl_setopt(\$ch, CURLOPT_COOKIE, " . var_export( $test->getCookie(), true ) . ");\n" : "" )
2351 . "\$result=curl_exec(\$ch);\n"
2352 . "curl_close (\$ch);\n"
2353 . "print \$result;\n"
2355 saveFile( $str, $filename );
2360 ** Escapes a value so that it can be used on the command line by Curl.
2361 ** Specifically, "<" and "@" need to be escaped if they are the first character,
2362 ** otherwise curl interprets these as meaning that we want to insert a file.
2364 function escapeForCurl( array $input_params ) {
2365 $output_params = array();
2366 foreach ( $input_params as $param => $value ) {
2367 if ( strlen( $value ) > 0 && ( $value[0] == "@" ||
$value[0] == "<" ) ) {
2368 $value = "\\" . $value;
2370 $output_params[$param] = $value;
2372 return $output_params;
2377 ** Saves a test as a standalone CURL shell script that shows this one problem.
2378 ** Resulting script requires standalone Curl be installed in order to work.
2380 function saveTestAsCurl( pageTest
$test, $filename ) {
2381 $str = "#!/bin/bash\n"
2382 . "curl --silent --include --globoff \\\n"
2383 . ( $test->getCookie() ?
" --cookie " . escapeshellarg( $test->getCookie() ) . " \\\n" : "" );
2384 foreach ( escapeForCurl( $test->getParams() ) as $param => $value ) {
2385 $str .= " -F " . escapeshellarg( $param ) . "=" . escapeshellarg( $value ) . " \\\n";
2387 $str .= " " . escapeshellarg( WIKI_BASE_URL
. $test->getPagePath() ); // beginning space matters.
2389 saveFile( $str, $filename );
2390 chmod( $filename, 0755 ); // make executable
2395 ** Saves the internal data structure to file.
2397 function saveTestData ( pageTest
$test, $filename ) {
2398 saveFile( serialize( $test ), $filename );
2403 ** saves a test in the various formats.
2405 function saveTest( pageTest
$test, $testname ) {
2406 $base_name = DIRECTORY
. "/" . $testname;
2407 saveTestAsText( $test, $base_name . INFO_FILE
);
2408 saveTestAsPHP ( $test, $base_name . PHP_TEST
);
2409 saveTestAsCurl( $test, $base_name . CURL_TEST
);
2410 saveTestData ( $test, $base_name . DATA_FILE
);
2414 // ////////////////// MEDIAWIKI OUTPUT /////////////////////////
2417 ** Asks MediaWiki for the HTML output of a test.
2419 function wikiTestOutput( pageTest
$test ) {
2423 // specify the cookie, if required.
2424 if ( $test->getCookie() ) curl_setopt( $ch, CURLOPT_COOKIE
, $test->getCookie() );
2425 curl_setopt( $ch, CURLOPT_POST
, 1 ); // save form using a POST
2427 $params = escapeForCurl( $test->getParams() );
2428 curl_setopt( $ch, CURLOPT_POSTFIELDS
, $params ); // load the POST variables
2430 curl_setopt( $ch, CURLOPT_URL
, WIKI_BASE_URL
. $test->getPagePath() ); // set url to post to
2431 curl_setopt( $ch, CURLOPT_RETURNTRANSFER
, 1 ); // return into a variable
2433 $result = curl_exec ( $ch );
2435 // if we encountered an error, then say so, and return an empty string.
2436 if ( curl_error( $ch ) ) {
2437 print "\nCurl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch );
2447 // ////////////////// HTML VALIDATION /////////////////////////
2450 ** Asks the validator whether this is valid HTML, or not.
2452 function validateHTML( $text ) {
2454 $params = array ( "fragment" => $text );
2458 curl_setopt( $ch, CURLOPT_POST
, 1 ); // save form using a POST
2459 curl_setopt( $ch, CURLOPT_POSTFIELDS
, $params ); // load the POST variables
2460 curl_setopt( $ch, CURLOPT_URL
, VALIDATOR_URL
); // set url to post to
2461 curl_setopt( $ch, CURLOPT_RETURNTRANSFER
, 1 ); // return into a variable
2463 $result = curl_exec ( $ch );
2465 // if we encountered an error, then log it, and exit.
2466 if ( curl_error( $ch ) ) {
2467 trigger_error( "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) );
2468 print "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) . " - exiting.\n";
2474 $valid = ( strpos( $result, "Failed validation" ) === false ?
true : false );
2476 return array( $valid, $result );
2481 ** Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
2483 function tidyCheckFile( $name ) {
2484 $file = DIRECTORY
. "/" . $name;
2485 $command = PATH_TO_TIDY
. " -output /tmp/out.html -quiet $file 2>&1";
2488 // Look for the most interesting Tidy errors and warnings.
2489 if ( strpos( $x, "end of file while parsing attributes" ) !== false
2490 ||
strpos( $x, "attribute with missing trailing quote mark" ) !== false
2491 ||
strpos( $x, "missing '>' for end of tag" ) !== false
2492 ||
strpos( $x, "Error:" ) !== false ) {
2493 print "\nTidy found something - view details with: $command";
2502 ** Returns whether or not an database error log file has changed in size since
2503 ** the last time this was run. This is used to tell if a test caused a DB error.
2505 function dbErrorLogged() {
2508 // first time running this function
2509 if ( !isset( $filesize ) ) {
2510 // create log if it does not exist
2511 if ( !file_exists( DB_ERROR_LOG_FILE
) ) {
2512 saveFile( "", DB_ERROR_LOG_FILE
);
2514 $filesize = filesize( DB_ERROR_LOG_FILE
);
2518 $newsize = filesize( DB_ERROR_LOG_FILE
);
2519 // if the log has grown, then assume the current test caused it.
2520 if ( $newsize != $filesize ) {
2521 $filesize = $newsize;
2528 // //////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
2531 ** takes a page test, and runs it and tests it for problems in the output.
2532 ** Returns: False on finding a problem, or True on no problems being found.
2534 function runWikiTest( pageTest
$test, &$testname, $can_overwrite = false ) {
2536 // by default don't overwrite a previous test of the same name.
2537 while ( ! $can_overwrite && file_exists( DIRECTORY
. "/" . $testname . DATA_FILE
) ) {
2538 $testname .= "-" . mt_rand( 0, 9 );
2541 $filename = DIRECTORY
. "/" . $testname . DATA_FILE
;
2543 // Store the time before and after, to find slow pages.
2544 $before = microtime( true );
2546 // Get MediaWiki to give us the output of this test.
2547 $wiki_preview = wikiTestOutput( $test );
2549 $after = microtime( true );
2551 // if we received no response, then that's interesting.
2552 if ( $wiki_preview == "" ) {
2553 print "\nNo response received for: $filename";
2557 // save output HTML to file.
2558 $html_file = DIRECTORY
. "/" . $testname . HTML_FILE
;
2559 saveFile( $wiki_preview, $html_file );
2561 // if there were PHP errors in the output, then that's interesting too.
2562 if ( strpos( $wiki_preview, "<b>Warning</b>: " ) !== false
2563 ||
strpos( $wiki_preview, "<b>Fatal error</b>: " ) !== false
2564 ||
strpos( $wiki_preview, "<b>Notice</b>: " ) !== false
2565 ||
strpos( $wiki_preview, "<b>Error</b>: " ) !== false
2566 ||
strpos( $wiki_preview, "<b>Strict Standards:</b>" ) !== false
2568 $error = substr( $wiki_preview, strpos( $wiki_preview, "</b>:" ) +
7, 50 );
2569 // Avoid probable PHP bug with bad session ids; http://bugs.php.net/bug.php?id=38224
2570 if ( $error != "Unknown: The session id contains illegal character" ) {
2571 print "\nPHP error/warning/notice in HTML output: $html_file ; $error";
2576 // if there was a MediaWiki Backtrace message in the output, then that's also interesting.
2577 if ( strpos( $wiki_preview, "Backtrace:" ) !== false ) {
2578 print "\nInternal MediaWiki error in HTML output: $html_file";
2582 // if there was a Parser error comment in the output, then that's potentially interesting.
2583 if ( strpos( $wiki_preview, "!-- ERR" ) !== false ) {
2584 print "\nParser Error comment in HTML output: $html_file";
2588 // if a database error was logged, then that's definitely interesting.
2589 if ( dbErrorLogged() ) {
2590 print "\nDatabase Error logged for: $filename";
2596 if ( VALIDATE_ON_WEB
) {
2597 list ( $valid, $validator_output ) = validateHTML( $wiki_preview );
2598 if ( !$valid ) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY
. "/" . $testname . ".validator_output.html";
2601 // Get tidy to check the page, unless we already know it produces non-XHTML output.
2602 if ( $test->tidyValidate() ) {
2603 $valid = tidyCheckFile( $testname . HTML_FILE
) && $valid;
2606 // if it took more than 2 seconds to render, then it may be interesting too. (Possible DoS attack?)
2607 if ( ( $after - $before ) >= 2 ) {
2608 print "\nParticularly slow to render (" . round( $after - $before, 2 ) . " seconds): $filename";
2613 // Remove temp HTML file if test was valid:
2614 unlink( $html_file );
2615 } elseif ( VALIDATE_ON_WEB
) {
2616 saveFile( $validator_output, DIRECTORY
. "/" . $testname . ".validator_output.html" );
2623 // ///////////////// RERUNNING OLD TESTS ///////////////////
2626 ** We keep our failed tests so that they can be rerun.
2627 ** This function does that retesting.
2629 function rerunPreviousTests() {
2630 print "Retesting previously found problems.\n";
2632 $dir_contents = scandir ( DIRECTORY
);
2634 // sort file into the order a normal person would use.
2635 natsort ( $dir_contents );
2637 foreach ( $dir_contents as $file ) {
2639 // if file is not a test, then skip it.
2640 // Note we need to escape any periods or will be treated as "any character".
2642 if ( !preg_match( "/(.*)" . str_replace( ".", "\.", DATA_FILE
) . "$/", $file, $matches ) ) continue;
2645 $full_path = DIRECTORY
. "/" . $file;
2646 $test = unserialize( file_get_contents( $full_path ) );
2648 // if this is not a valid test, then skip it.
2649 if ( ! $test instanceof pageTest
) {
2650 print "\nSkipping invalid test - $full_path";
2654 // The date format is in Apache log format, which makes it easier to locate
2655 // which retest caused which error in the Apache logs (only happens usually if
2656 // apache segfaults).
2657 if ( !QUIET
) print "[" . date ( "D M d H:i:s Y" ) . "] Retesting $file (" . get_class( $test ) . ")";
2660 $testname = $matches[1];
2661 $valid = runWikiTest( $test, $testname, true );
2664 saveTest( $test, $testname );
2666 print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
2672 if ( !QUIET
) print "\r";
2673 if ( DELETE_PASSED_RETESTS
) {
2674 $prefix = DIRECTORY
. "/" . $testname;
2675 if ( is_file( $prefix . DATA_FILE
) ) unlink( $prefix . DATA_FILE
);
2676 if ( is_file( $prefix . PHP_TEST
) ) unlink( $prefix . PHP_TEST
);
2677 if ( is_file( $prefix . CURL_TEST
) ) unlink( $prefix . CURL_TEST
);
2678 if ( is_file( $prefix . INFO_FILE
) ) unlink( $prefix . INFO_FILE
);
2683 print "\nDone retesting.\n";
2687 // //////////////////// MAIN LOOP ////////////////////////
2690 // first check whether CURL is installed, because sometimes it's not.
2691 if ( ! function_exists( 'curl_init' ) ) {
2692 die( "Could not find 'curl_init' function. Is the curl extension compiled into PHP?\n" );
2695 // Initialization of types. wikiFuzz doesn't have a constructor because we want to
2696 // access it staticly and not have any globals.
2697 wikiFuzz
::$types = array_keys( wikiFuzz
::$data );
2699 // Make directory if doesn't exist
2700 if ( !is_dir( DIRECTORY
) ) {
2701 mkdir ( DIRECTORY
, 0700 );
2703 // otherwise, we first retest the things that we have found in previous runs
2704 else if ( RERUN_OLD_TESTS
) {
2705 rerunPreviousTests();
2709 $start_time = date( "U" );
2712 print "Beginning main loop. Results are stored in the " . DIRECTORY
. " directory.\n";
2713 print "Press CTRL+C to stop testing.\n";
2716 for ( $count = 0; true; $count++
) {
2718 // spinning progress indicator.
2719 switch( $count %
4 ) {
2720 case '0': print "\r/"; break;
2721 case '1': print "\r-"; break;
2722 case '2': print "\r\\"; break;
2723 case '3': print "\r|"; break;
2728 // generate a page test to run.
2729 $test = selectPageTest( $count );
2731 $mins = ( date( "U" ) - $start_time ) / 60;
2732 if ( !QUIET
&& $mins > 0 ) {
2733 print ". $num_errors poss errors. "
2734 . floor( $mins ) . " mins. "
2735 . round ( $count / $mins, 0 ) . " tests/min. "
2736 . get_class( $test ); // includes the current test name.
2739 // run this test against MediaWiki, and see if the output was valid.
2741 $valid = runWikiTest( $test, $testname, false );
2743 // save the failed test
2746 print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
2750 saveTest( $test, $testname );
2752 } else if ( KEEP_PASSED_TESTS
) {
2753 // print current time, with microseconds (matches "strace" format), and the test name.
2754 print " " . date( "H:i:s." ) . substr( current( explode( " ", microtime() ) ), 2 ) . " " . $testname;
2755 saveTest( $test, $testname );
2758 // stop if we have reached max number of errors.
2759 if ( defined( "MAX_ERRORS" ) && $num_errors >= MAX_ERRORS
) {
2763 // stop if we have reached max number of mins runtime.
2764 if ( defined( "MAX_RUNTIME" ) && $mins >= MAX_RUNTIME
) {