Delete fuzz-tester.php
authorChad Horohoe <chadh@wikimedia.org>
Tue, 5 Nov 2013 16:11:17 +0000 (08:11 -0800)
committerBartosz Dziewoński <matma.rex@gmail.com>
Fri, 22 Nov 2013 19:12:29 +0000 (19:12 +0000)
It is unmaintained, not up to coding standards, and as far as I can tell
not actually used by anyone or anything.

Fuzz testing in and of itself may be useful and if someone is interested
they can write some code that's from this decade.

Change-Id: Iecde41daca95d1655fb8767a1e775cbb732184e9

maintenance/fuzz-tester.php [deleted file]

diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php
deleted file mode 100644 (file)
index 548bb2f..0000000
+++ /dev/null
@@ -1,2692 +0,0 @@
-<?php
-/**
- * Performs fuzz-style testing of MediaWiki's parser and forms.
- *
- * Copyright © 2006 Nick Jenkins
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Nick Jenkins ( http://nickj.org/ ).
-
-
-Started: 18 May 2006.
-
-Description:
-  Performs fuzz-style testing of MediaWiki's parser and forms.
-
-How:
-  - Generate lots of nasty wiki text.
-  - Ask the Parser to render that wiki text to HTML, or ask MediaWiki's forms
-       to deal with that wiki text.
-  - Check MediaWiki's output for problems.
-  - Repeat.
-
-Why:
-  - To help find bugs.
-  - To help find security issues, or potential security issues.
-
-What type of problems are being checked for:
-  - Unclosed tags.
-  - Errors or interesting warnings from Tidy.
-  - PHP errors / warnings / notices.
-  - MediaWiki internal errors.
-  - Very slow responses.
-  - No response from apache.
-  - Optionally checking for malformed HTML using the W3C validator.
-
-Background:
-  Many of the wikiFuzz class methods are a modified PHP port,
-  of a "shameless" Python port, of LCAMTUF'S MANGELME:
-  - http://www.securiteam.com/tools/6Z00N1PBFK.html
-  - http://www.securityfocus.com/archive/1/378632/2004-10-15/2004-10-21/0
-
-Video:
-  There's an XviD video discussing this fuzz tester. You can get it from:
-  http://files.nickj.org/MediaWiki/Fuzz-Testing-MediaWiki-xvid.avi
-
-Requirements:
-  To run this, you will need:
-  - Command-line PHP5, with PHP-curl enabled (not all installations have this
-       enabled - try "apt-get install php5-curl" if you're on Debian to install).
-  - the Tidy standalone executable. ("apt-get install tidy").
-
-Optional:
-  - If you want to run the curl scripts, you'll need standalone curl installed
-       ("apt-get install curl")
-  - For viewing the W3C validator output on a command line, the "html2text"
-       program may be useful ("apt-get install html2text")
-
-Saving tests and test results:
-  Any of the fuzz tests which find problems are saved for later review.
-  In order to help track down problems, tests are saved in a number of
-  different formats. The default filename extensions and their meanings are:
-  - ".test.php" : PHP script that reproduces just that one problem using PHP-Curl.
-  - ".curl.sh"  : Shell script that reproduces that problem using standalone curl.
-  - ".data.bin" : The serialized PHP data so that this script can re-run the test.
-  - ".info.txt" : A human-readable text file with details of the field contents.
-
-Wiki configuration for testing:
-  You should make some additions to LocalSettings.php in order to catch the most
-  errors. Note this configuration is for **TESTING PURPOSES ONLY**, and is IN NO
-  WAY, SHAPE, OR FORM suitable for deployment on a hostile network. That said,
-  personally I find these additions to be the most helpful for testing purposes:
-
-  // --------- Start ---------
-  // Everyone can do everything. Very useful for testing, yet useless for deployment.
-  $wgGroupPermissions['*']['autoconfirmed']   = true;
-  $wgGroupPermissions['*']['block']           = true;
-  $wgGroupPermissions['*']['bot']             = true;
-  $wgGroupPermissions['*']['delete']          = true;
-  $wgGroupPermissions['*']['deletedhistory']  = true;
-  $wgGroupPermissions['*']['deleterevision']  = true;
-  $wgGroupPermissions['*']['editinterface']   = true;
-  $wgGroupPermissions['*']['hiderevision']    = true;
-  $wgGroupPermissions['*']['import']          = true;
-  $wgGroupPermissions['*']['importupload']    = true;
-  $wgGroupPermissions['*']['minoredit']       = true;
-  $wgGroupPermissions['*']['move']            = true;
-  $wgGroupPermissions['*']['patrol']          = true;
-  $wgGroupPermissions['*']['protect']         = true;
-  $wgGroupPermissions['*']['proxyunbannable'] = true;
-  $wgGroupPermissions['*']['renameuser']      = true;
-  $wgGroupPermissions['*']['reupload']        = true;
-  $wgGroupPermissions['*']['reupload-shared'] = true;
-  $wgGroupPermissions['*']['rollback']        = true;
-  $wgGroupPermissions['*']['siteadmin']       = true;
-  $wgGroupPermissions['*']['unwatchedpages']  = true;
-  $wgGroupPermissions['*']['upload']          = true;
-  $wgGroupPermissions['*']['userrights']      = true;
-  $wgGroupPermissions['*']['renameuser']      = true;
-  $wgGroupPermissions['*']['makebot']         = true;
-  $wgGroupPermissions['*']['makesysop']       = true;
-
-  // Enable weird and wonderful options:
-                                                         // Increase default error reporting level.
-  error_reporting (E_ALL);    // At a later date could be increased to E_ALL | E_STRICT
-  $wgEnableUploads = true;    // enable uploads.
-  $wgDBerrorLog = "/root/mediawiki-db-error-log.txt";  // log DB errors, replace with suitable path.
-  $wgShowSQLErrors = true;    // Show SQL errors (instead of saying the query was hidden).
-  $wgShowExceptionDetails = true;  // want backtraces.
-  $wgEnableAPI = true;        // enable API.
-  $wgEnableWriteAPI = true;   // enable API.
-
-  // Install & enable Parser Hook extensions to increase code coverage. E.g.:
-  require_once "extensions/ParserFunctions/ParserFunctions.php";
-  require_once "extensions/Cite/Cite.php";
-  require_once "extensions/inputbox/inputbox.php";
-  require_once "extensions/Sort/Sort.php";
-  require_once "extensions/wikihiero/wikihiero.php";
-  require_once "extensions/CharInsert/CharInsert.php";
-  require_once "extensions/FixedImage/FixedImage.php";
-
-  // Install & enable Special Page extensions to increase code coverage. E.g.:
-  require_once "extensions/Cite/SpecialCite.php";
-  require_once "extensions/Renameuser/SpecialRenameuser.php";
-  // --------- End ---------
-
-  If you want to try E_STRICT error logging, add this to the above:
-  // --------- Start ---------
-  error_reporting (E_ALL | E_STRICT);
-  set_error_handler( 'error_handler' );
-  function error_handler ($type, $message, $file=__FILE__, $line=__LINE__) {
-        if ($message == "var: Deprecated. Please use the public/private/protected modifiers") return;
-        print "<br />\n<b>Strict Standards:</b> Type: <b>$type</b>:  $message in <b>$file</b> on line <b>$line</b><br />\n";
-  }
-  // --------- End ---------
-
-  Also add/change this in LocalSettings.php:
-  // --------- Start ---------
-  $wgEnableProfileInfo = true;
-  $wgDBserver = "localhost"; // replace with DB server hostname
-  // --------- End ---------
-
-Usage:
-  Run with "php fuzz-tester.php".
-  To see the various command-line options, run "php fuzz-tester.php --help".
-  To stop the script, press Ctrl-C.
-
-Console output:
-  - If requested, first any previously failed tests will be rerun.
-  - Then new tests will be generated and run. Any tests that fail will be saved,
-       and a brief message about why they failed will be printed on the console.
-  - The console will show the number of tests run, time run, number of tests
-       failed, number of tests being done per minute, and the name of the current test.
-
-TODO:
-  Some known things that could improve this script:
-  - Logging in with cookie jar storage needed for some tests (as there are some
-       pages that cannot be tested without being logged in, and which are currently
-       untested - e.g. Special:Emailuser, Special:Preferences, adding to Watchist).
-  - Testing of Timeline extension (I cannot test as ploticus has/had issues on
-       my architecture).
-
-*/
-
-// ///////////////////////// COMMAND LINE HELP ////////////////////////////////////
-
-// This is a command line script, load MediaWiki env (gives command line options);
-require_once __DIR__ . '/commandLine.inc';
-
-// if the user asked for an explanation of command line options.
-if ( isset( $options["help"] ) ) {
-       print <<<ENDS
-MediaWiki $wgVersion fuzz tester
-Usage: php {$_SERVER["SCRIPT_NAME"]} [--quiet] [--base-url=<url-to-test-wiki>]
-                                                  [--directory=<failed-test-path>] [--include-binary]
-                                                  [--w3c-validate] [--delete-passed-retests] [--help]
-                                                  [--user=<username>] [--password=<password>]
-                                                  [--rerun-failed-tests] [--max-errors=<int>]
-                                                  [--max-runtime=<num-minutes>]
-                                                  [--specific-test=<test-name>]
-
-Options:
-  --quiet                 : Hides passed tests, shows only failed tests.
-  --base-url              : URL to a wiki on which to run the tests.
-                                                       The "http://" is optional and can be omitted.
-  --directory             : Full path to directory for storing failed tests.
-                                                       Will be created if it does not exist.
-  --include-binary        : Includes non-alphanumeric characters in the tests.
-  --w3c-validate          : Validates pages using the W3C's web validator.
-                                                       Slow. Currently many pages fail validation.
-  --user                  : Login name of a valid user on your test wiki.
-  --password              : Password for the valid user on your test wiki.
-  --delete-passed-retests : Will delete retests that now pass.
-                                                       Requires --rerun-failed-tests to be meaningful.
-  --rerun-failed-tests    : Whether to rerun any previously failed tests.
-  --max-errors            : Maximum number of errors to report before exiting.
-                                                       Does not include errors from --rerun-failed-tests
-  --max-runtime           : Maximum runtime, in minutes, to run before exiting.
-                                                       Only applies to new tests, not --rerun-failed-tests
-  --specific-test         : Runs only the specified fuzz test.
-                                                       Only applies to new tests, not --rerun-failed-tests
-  --keep-passed-tests     : Saves all test files, even those that pass.
-  --help                  : Show this help message.
-
-Example:
-  If you wanted to fuzz test a nightly MediaWiki checkout using cron for 1 hour,
-  and only wanted to be informed of errors, and did not want to redo previously
-  failed tests, and wanted a maximum of 100 errors, then you could do:
-  php {$_SERVER["SCRIPT_NAME"]} --quiet --max-errors=100 --max-runtime=60
-
-
-ENDS;
-
-       exit( 0 );
-}
-
-
-// if we got command line options, check they look valid.
-$validOptions = array ( "quiet", "base-url", "directory", "include-binary",
-               "w3c-validate", "user", "password", "delete-passed-retests",
-               "rerun-failed-tests", "max-errors",
-               "max-runtime", "specific-test", "keep-passed-tests", "help" );
-if ( !empty( $options ) ) {
-       $unknownArgs = array_diff ( array_keys( $options ), $validOptions );
-       foreach ( $unknownArgs as $invalidArg ) {
-               print "Ignoring invalid command-line option: --$invalidArg\n";
-       }
-}
-
-
-// /////////////////////////// CONFIGURATION ////////////////////////////////////
-
-// URL to some wiki on which we can run our tests.
-if ( !empty( $options["base-url"] ) ) {
-       define( "WIKI_BASE_URL", $options["base-url"] );
-} else {
-       define( "WIKI_BASE_URL", $wgServer . $wgScriptPath . '/' );
-}
-
-// The directory name where we store the output.
-// Example for Windows: "c:\\temp\\wiki-fuzz"
-if ( !empty( $options["directory"] ) ) {
-       define( "DIRECTORY", $options["directory"] );
-} else {
-       define( "DIRECTORY", "{$wgUploadDirectory}/fuzz-tests" );
-}
-
-// Should our test fuzz data include binary strings?
-define( "INCLUDE_BINARY",  isset( $options["include-binary"] ) );
-
-// Whether we want to validate HTML output on the web.
-// At the moment very few generated pages will validate, so not recommended.
-define( "VALIDATE_ON_WEB", isset( $options["w3c-validate"] ) );
-// URL to use to validate our output:
-define( "VALIDATOR_URL",  "http://validator.w3.org/check" );
-
-// Location of Tidy standalone executable.
-define( "PATH_TO_TIDY",  "/usr/bin/tidy" );
-
-// The name of a user who has edited on your wiki. Used
-// when testing the Special:Contributions and Special:Userlogin page.
-if ( !empty( $options["user"] ) ) {
-       define( "USER_ON_WIKI", $options["user"] );
-} else {
-       define( "USER_ON_WIKI", "nickj" );
-}
-
-// The password of the above user. Used when testing the login page,
-// and to do this we sometimes need to login successfully.
-if ( !empty( $options["password"] ) ) {
-       define( "USER_PASSWORD", $options["password"] );
-} else {
-       // And no, this is not a valid password on any public wiki.
-       define( "USER_PASSWORD", "nickj" );
-}
-
-// If we have a test that failed, and then we run it again, and it passes,
-// do you want to delete it or keep it?
-define( "DELETE_PASSED_RETESTS", isset( $options["delete-passed-retests"] ) );
-
-// Do we want to rerun old saved tests at script startup?
-// Set to true to help catch regressions, or false if you only want new stuff.
-define( "RERUN_OLD_TESTS", isset( $options["rerun-failed-tests"] ) );
-
-// File where the database errors are logged. Should be defined in LocalSettings.php.
-define( "DB_ERROR_LOG_FILE", $wgDBerrorLog );
-
-// Run in chatty mode (all output, default), or run in quiet mode (only prints out details of failed tests)?
-define( "QUIET", isset( $options["quiet"] ) );
-
-// Keep all test files, even those that pass. Potentially useful to tracking input that causes something
-// unusual to happen, if you don't know what "unusual" is until later.
-define( "KEEP_PASSED_TESTS", isset( $options["keep-passed-tests"] ) );
-
-// The maximum runtime, if specified.
-if ( !empty( $options["max-runtime"] ) && intval( $options["max-runtime"] ) > 0 ) {
-       define( "MAX_RUNTIME", intval( $options["max-runtime"] ) );
-}
-
-// The maximum number of problems to find, if specified. Excludes retest errors.
-if ( !empty( $options["max-errors"] ) && intval( $options["max-errors"] ) > 0 ) {
-       define( "MAX_ERRORS", intval( $options["max-errors"] ) );
-}
-
-// if the user has requested a specific test (instead of all tests), and the test they asked for looks valid.
-if ( !empty( $options["specific-test"] ) ) {
-       if ( class_exists( $options["specific-test"] ) && get_parent_class( $options["specific-test"] ) == "pageTest" ) {
-               define( "SPECIFIC_TEST", $options["specific-test"] );
-       }
-       else {
-               print "Ignoring invalid --specific-test\n";
-       }
-}
-
-// Define the file extensions we'll use:
-define( "PHP_TEST" , ".test.php" );
-define( "CURL_TEST", ".curl.sh" );
-define( "DATA_FILE", ".data.bin" );
-define( "INFO_FILE", ".info.txt" );
-define( "HTML_FILE", ".wiki_preview.html" );
-
-// If it goes wrong, we want to know about it.
-error_reporting( E_ALL | E_STRICT );
-
-// //////////////  A CLASS THAT GENERATES RANDOM NASTY WIKI & HTML STRINGS  //////////////////////
-
-class wikiFuzz {
-
-       // Only some HTML tags are understood with params by MediaWiki, the rest are ignored.
-       // List the tags that accept params below, as well as what those params are.
-       public static $data = array(
-                       "B"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "CAPTION"    => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
-                       "CENTER"     => array( "CLASS", "STYLE", "ID", "lang", "dir", "title" ),
-                       "DIV"        => array( "CLASS", "STYLE", "ID", "align", "lang", "dir", "title" ),
-                       "FONT"       => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "face", "size", "color" ),
-                       "H1"         => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
-                       "H2"         => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
-                       "HR"         => array( "STYLE", "CLASS", "ID", "WIDTH", "lang", "dir", "title", "size", "noshade" ),
-                       "LI"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "value" ),
-                       "TABLE"      => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "BORDER", "CELLPADDING",
-                                                                  "CELLSPACING", "lang", "dir", "title", "summary", "frame", "rules" ),
-                       "TD"         => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
-                                                                 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
-                                                                 "dir", "title", "char", "charoff" ),
-                       "TH"         => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
-                                                                 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
-                                                                 "dir", "title", "char", "charoff" ),
-                       "TR"         => array( "CLASS", "STYLE", "ID", "BGCOLOR", "ALIGN", "VALIGN", "lang", "dir", "title", "char", "charoff" ),
-                       "UL"         => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "type" ),
-                       "P"          => array( "style", "class", "id", "align", "lang", "dir", "title" ),
-                       "blockquote" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "cite" ),
-                       "span"       => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
-                       "code"       => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "tt"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "small"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "big"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "s"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "u"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "del"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
-                       "ins"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
-                       "sub"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "sup"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "ol"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "start" ),
-                       "br"         => array( "CLASS", "ID", "STYLE", "title", "clear" ),
-                       "cite"       => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "var"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "ruby"       => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "rt"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "rp"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "dt"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "dl"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "em"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "strong"     => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "i"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "thead"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign' ),
-                       "tfoot"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign' ),
-                       "tbody"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign' ),
-                       "colgroup"   => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign', 'span', 'width' ),
-                       "col"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign', 'span', 'width' ),
-                       "pre"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "width" ),
-
-                       // extension tags that accept parameters:
-                       "sort"         => array( "order", "class" ),
-                       "ref"          => array( "name" ),
-                       "categorytree" => array( "hideroot", "mode", "style" ),
-                       "chemform"     => array( "link", "wikilink", "query" ),
-                       "section"      => array( "begin", "new" ),
-
-                       // older MW transclusion.
-                       "transclude"   => array( "page" ),
-                               );
-
-       // The types of the HTML that we will be testing were defined above
-       // Note: this needs to be initialized later to be equal to: array_keys(wikiFuzz::$data);
-       // as such, it also needs to also be publicly modifiable.
-       public static $types;
-
-
-       // Some attribute values.
-       static private $other = array( "&", "=", ":", "?", "\"", "\n", "%n%n%n%n%n%n%n%n%n%n%n%n", "\\" );
-       static private $ints  = array(
-                       // various numbers
-                       "0", "-1", "127", "-7897", "89000", "808080", "90928345",
-                       "0xfffffff", "ffff",
-
-                       // Different ways of saying: '
-                       "&#0000039;", // Long UTF-8 Unicode encoding
-                       "&#39;",  // dec version.
-                       "&#x27;", // hex version.
-                       "&#xA7;", // malformed hex variant, MSB not zero.
-
-                       // Different ways of saying: "
-                       "&#0000034;", // Long UTF-8 Unicode encoding
-                       "&#34;",
-                       "&#x22;", // hex version.
-                       "&#xA2;", // malformed hex variant, MSB not zero.
-
-                       // Different ways of saying: <
-                       "<",
-                       "&#0000060",  // Long UTF-8 Unicode encoding without semicolon (Mediawiki wants the colon)
-                       "&#0000060;", // Long UTF-8 Unicode encoding with semicolon
-                       "&#60;",
-                       "&#x3C;",     // hex version.
-                       "&#xBC;",     // malformed hex variant, MSB not zero.
-                       "&#x0003C;",  // mid-length hex version
-                       "&#X00003C;", // slightly longer hex version, with capital "X"
-
-                       // Different ways of saying: >
-                       ">",
-                       "&#0000062;", // Long UTF-8 Unicode encoding
-                       "&#62;",
-                       "&#x3E;",     // hex version.
-                       "&#xBE;",     // malformed variant, MSB not zero.
-
-                       // Different ways of saying: [
-                       "&#0000091;", // Long UTF-8 Unicode encoding
-                       "&#91;",
-                       "&#x5B;",     // hex version.
-
-                       // Different ways of saying: {{
-                       "&#0000123;&#0000123;", // Long UTF-8 Unicode encoding
-                       "&#123;&#123;",
-                       "&#x7B;&#x7B;",         // hex version.
-
-                       // Different ways of saying: |
-                       "&#0000124;", // Long UTF-8 Unicode encoding
-                       "&#124;",
-                       "&#x7C;",     // hex version.
-                       "&#xFC;",     // malformed hex variant, MSB not zero.
-
-                       // a "lignature" - http://www.robinlionheart.com/stds/html4/spchars#ligature
-                       // &#8204; == &zwnj;
-                       "&#8204;"
-                               );
-
-       // Defines various wiki-related bits of syntax, that can potentially cause
-       // MediaWiki to do something other than just print that literal text.
-       static private $ext = array(
-                       // links, templates, parameters.
-                       "[[", "]]", "{{", "}}", "|", "[", "]", "{{{", "}}}", "|]]",
-
-                       // wiki tables.
-                       "\n{|", "\n|}",
-                       "!",
-                       "\n!",
-                       "!!",
-                       "||",
-                       "\n|-", "| ", "\n|",
-
-                       // section headings.
-                       "=", "==", "===", "====", "=====", "======",
-
-                       // lists (ordered and unordered) and indentation.
-                       "\n*", "*", "\n:", ":",
-                       "\n#", "#",
-
-                       // definition lists (dl, dt, dd), newline, and newline with pre, and a tab.
-                       "\n;", ";", "\n ",
-
-                       // Whitespace: newline, tab, space.
-                       "\n", "\t", " ",
-
-                       // Some XSS attack vectors from http://ha.ckers.org/xss.html
-                       "&#x09;", // tab
-                       "&#x0A;", // newline
-                       "&#x0D;", // carriage return
-                       "\0",     // null character
-                       " &#14; ", // spaces and meta characters
-                       "'';!--\"<XSS>=&{()}", // compact injection of XSS & SQL tester
-
-                       // various NULL fields
-                       "%00",
-                       "&#00;",
-                       "\0",
-
-                       // horizontal rule.
-                       "-----", "\n-----",
-
-                       // signature, redirect, bold, italics.
-                       "~~~~", "#REDIRECT [[", "'''", "''",
-
-                       // comments.
-                       "<!--", "-->",
-
-                       // quotes.
-                       "\"", "'",
-
-                       // tag start and tag end.
-                       "<", ">",
-
-                       // implicit link creation on URIs.
-                       "http://",
-                       "https://",
-                       "ftp://",
-                       "irc://",
-                       "news:",
-                       'gopher://',
-                       'telnet://',
-                       'nntp://',
-                       'worldwind://',
-                       'mailto:',
-
-                       // images.
-                       "[[image:",
-                       ".gif",
-                       ".png",
-                       ".jpg",
-                       ".jpeg",
-                       'thumbnail=',
-                       'thumbnail',
-                       'thumb=',
-                       'thumb',
-                       'right',
-                       'none',
-                       'left',
-                       'framed',
-                       'frame',
-                       'enframed',
-                       'centre',
-                       'center',
-                       "Image:",
-                       "[[:Image",
-                       'px',
-                       'upright=',
-                       'border',
-
-                       // misc stuff to throw at the Parser.
-                       '%08X',
-                       '/',
-                       ":x{|",
-                       "\n|+",
-                       "<noinclude>",
-                       "</noinclude>",
-                       " \302\273",
-                       " :",
-                       " !",
-                       " ;",
-                       "\302\253",
-                       "[[category:",
-                       "?=",
-                       "(",
-                       ")",
-                       "]]]",
-                       "../",
-                       "{{{{",
-                       "}}}}",
-                       "[[Special:",
-                       "<includeonly>",
-                       "</includeonly>",
-                       "<!--MWTEMPLATESECTION=",
-                       '<!--MWTOC-->',
-
-                       // implicit link creation on booknum, RFC, and PubMed ID usage (both with and without IDs)
-                       "ISBN 2",
-                       "RFC 000",
-                       "PMID 000",
-                       "ISBN ",
-                       "RFC ",
-                       "PMID ",
-
-                       // magic words:
-                       '__NOTOC__',
-                       '__FORCETOC__',
-                       '__NOEDITSECTION__',
-                       '__START__',
-                       '__NOTITLECONVERT__',
-                       '__NOCONTENTCONVERT__',
-                       '__END__',
-                       '__TOC__',
-                       '__NOTC__',
-                       '__NOCC__',
-                       "__FORCETOC__",
-                       "__NEWSECTIONLINK__",
-                       "__NOGALLERY__",
-
-                       // more magic words / internal templates.
-                       '{{PAGENAME}}',
-                       '{{PAGENAMEE}}',
-                       '{{NAMESPACE}}',
-                       "{{MSG:",
-                       "}}",
-                       "{{MSGNW:",
-                       "}}",
-                       "{{INT:",
-                       "}}",
-                       '{{SITENAME}}',
-                       "{{NS:",
-                       "}}",
-                       "{{LOCALURL:",
-                       "}}",
-                       "{{LOCALURLE:",
-                       "}}",
-                       "{{SCRIPTPATH}}",
-                       "{{GRAMMAR:gentiv|",
-                       "}}",
-                       "{{REVISIONID}}",
-                       "{{SUBPAGENAME}}",
-                       "{{SUBPAGENAMEE}}",
-                       "{{ns:0}}",
-                       "{{fullurle:",
-                       "}}",
-                       "{{subst::",
-                       "}}",
-                       "{{UCFIRST:",
-                       "}}",
-                       "{{UC:",
-                       '{{SERVERNAME}}',
-                       '{{SERVER}}',
-                       "{{RAW:",
-                       "}}",
-                       "{{PLURAL:",
-                       "}}",
-                       "{{LCFIRST:",
-                       "}}",
-                       "{{LC:",
-                       "}}",
-                       '{{CURRENTWEEK}}',
-                       '{{CURRENTDOW}}',
-                       "{{INT:{{LC:contribs-showhideminor}}|",
-                       "}}",
-                       "{{INT:googlesearch|",
-                       "}}",
-                        "{{ROOTPAGENAME}}",
-                       "{{BASEPAGENAME}}",
-                       "{{CONTENTLANGUAGE}}",
-                       "{{PAGESINNAMESPACE:}}",
-                       "{{#language:",
-                       "}}",
-                       "{{#special:",
-                       "}}",
-                       "{{#special:emailuser",
-                       "}}",
-
-                       // Some raw link for magic words.
-                       "{{NUMBEROFPAGES:R",
-                       "}}",
-                       "{{NUMBEROFUSERS:R",
-                       "}}",
-                       "{{NUMBEROFARTICLES:R",
-                       "}}",
-                       "{{NUMBEROFFILES:R",
-                       "}}",
-                       "{{NUMBEROFADMINS:R",
-                       "}}",
-                       "{{padleft:",
-                       "}}",
-                       "{{padright:",
-                       "}}",
-                       "{{DEFAULTSORT:",
-                       "}}",
-
-                       // internal Math "extension":
-                       "<math>",
-                       "</math>",
-
-                       // Parser extension functions:
-                       "{{#expr:",
-                       "{{#if:",
-                       "{{#ifeq:",
-                       "{{#ifexist:",
-                       "{{#ifexpr:",
-                       "{{#switch:",
-                       "{{#time:",
-                       "}}",
-
-                       // references table for the Cite extension.
-                       "<references/>",
-
-                       // Internal Parser tokens - try inserting some of these.
-                       "UNIQ25f46b0524f13e67NOPARSE",
-                       "UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002",
-                       "\x07UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002-QINU",
-
-                       // Inputbox extension:
-                       "<inputbox>\ntype=search\nsearchbuttonlabel=\n",
-                       "</inputbox>",
-
-                       // charInsert extension:
-                       "<charInsert>",
-                       "</charInsert>",
-
-                       // wikiHiero extension:
-                       "<hiero>",
-                       "</hiero>",
-
-                       // Image gallery:
-                       "<gallery>",
-                       "</gallery>",
-
-                       // FixedImage extension.
-                       "<fundraising/>",
-
-                       // Timeline extension: currently untested.
-
-                       // Nowiki:
-                       "<nOwIkI>",
-                       "</nowiki>",
-
-                       // an external image to test the external image displaying code
-                       "http://debian.org/Pics/debian.png",
-
-                       // LabeledSectionTransclusion extension.
-                       "{{#lstx:",
-                       "}}",
-                       "{{#lst:",
-                       "}}",
-                       "{{#lst:Main Page|",
-                       "}}"
-                       );
-
-       /**
-        ** Randomly returns one element of the input array.
-        */
-       public static function chooseInput( array $input ) {
-               $randindex = wikiFuzz::randnum( count( $input ) - 1 );
-               return $input[$randindex];
-       }
-
-       // Max number of parameters for HTML attributes.
-       static private $maxparams = 10;
-
-       /**
-        * Returns random number between finish and start.
-        * @param $finish
-        * @param $start int
-        * @return int
-        */
-       public static function randnum( $finish, $start = 0 ) {
-               return mt_rand( $start, $finish );
-       }
-
-       /**
-        * Returns a mix of random text and random wiki syntax.
-        * @return string
-        */
-       private static function randstring() {
-               $thestring = "";
-
-               for ( $i = 0; $i < 40; $i++ ) {
-                       $what = wikiFuzz::randnum( 1 );
-
-                       if ( $what == 0 ) { // include some random wiki syntax
-                               $which = wikiFuzz::randnum( count( wikiFuzz::$ext ) - 1 );
-                               $thestring .= wikiFuzz::$ext[$which];
-                       }
-                       else { // include some random text
-                               $char = INCLUDE_BINARY
-                                       // Decimal version:
-                                       // "&#" . wikiFuzz::randnum(255) . ";"
-                                       // Hex version:
-                                       ? "&#x" . str_pad( dechex( wikiFuzz::randnum( 255 ) ), wikiFuzz::randnum( 2, 7 ), "0", STR_PAD_LEFT ) . ";"
-                                       // A truly binary version:
-                                       // ? chr(wikiFuzz::randnum(0,255))
-                                       : chr( wikiFuzz::randnum( 126, 32 ) );
-
-                               $length = wikiFuzz::randnum( 8 );
-                               $thestring .= str_repeat ( $char, $length );
-                       }
-               }
-               return $thestring;
-       }
-
-       /**
-        * Returns either random text, or random wiki syntax, or random data from "ints",
-        *        or random data from "other".
-        * @return string
-        */
-       private static function makestring() {
-               $what = wikiFuzz::randnum( 2 );
-               if ( $what == 0 ) {
-                       return wikiFuzz::randstring();
-               } elseif ( $what == 1 ) {
-                       return wikiFuzz::$ints[wikiFuzz::randnum( count( wikiFuzz::$ints ) - 1 )];
-               } else {
-                       return wikiFuzz::$other[wikiFuzz::randnum( count( wikiFuzz::$other ) - 1 )];
-               }
-       }
-
-       /**
-        * Returns the matched character slash-escaped as in a C string
-        * Helper for makeTitleSafe callback
-        * @param $matches
-        * @return string
-        */
-       private static function stringEscape( $matches ) {
-               return sprintf( "\\x%02x", ord( $matches[1] ) );
-       }
-
-       /**
-        ** Strips out the stuff that Mediawiki balks at in a page's title.
-        **        Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
-        * @param $str string
-        * @return string
-        */
-       public static function makeTitleSafe( $str ) {
-               $legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
-               return preg_replace_callback(
-                               "/([^$legalTitleChars])/", 'wikiFuzz::stringEscape',
-                               $str );
-       }
-
-       /**
-        ** Returns a string of fuzz text.
-        * @return string
-        */
-       private static function loop() {
-               switch ( wikiFuzz::randnum( 3 ) ) {
-                       case 1: // an opening tag, with parameters.
-                               $string = "";
-                               $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 );
-                               $t = wikiFuzz::$types[$i];
-                               $arr = wikiFuzz::$data[$t];
-                               $string .= "<" . $t . " ";
-                               $num_params = min( wikiFuzz::$maxparams, count( $arr ) );
-                               for ( $z = 0; $z < $num_params; $z++ ) {
-                                       $badparam = $arr[wikiFuzz::randnum( count( $arr ) - 1 )];
-                                       $badstring = wikiFuzz::makestring();
-                                       $string .= $badparam . "=" . wikiFuzz::getRandQuote() . $badstring . wikiFuzz::getRandQuote() . " ";
-                               }
-                               $string .= ">\n";
-                               return $string;
-                       case 2: // a closing tag.
-                               $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 );
-                               return "</" . wikiFuzz::$types[$i] . ">";
-                       case 3: // a random string, between tags.
-                               return wikiFuzz::makeString();
-               }
-               return "";    // catch-all, should never be called.
-       }
-
-       /**
-        * Returns one of the three styles of random quote: ', ", and nothing.
-        * @return string
-        */
-       private static function getRandQuote() {
-               switch ( wikiFuzz::randnum( 3 ) ) {
-                       case 1 : return "'";
-                       case 2 : return "\"";
-                       default: return "";
-               }
-       }
-
-       /**
-        ** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
-        * @param $maxtypes int
-        * @return string
-        */
-       public static function makeFuzz( $maxtypes = 2 ) {
-               $page = "";
-               for ( $k = 0; $k < $maxtypes; $k++ ) {
-                       $page .= wikiFuzz::loop();
-               }
-               return $page;
-       }
-}
-
-
-// //////   MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM  ///////
-
-/**
- ** A page test has just these things:
- **        1) Form parameters.
- **        2) the URL we are going to test those parameters on.
- **        3) Any cookies required for the test.
- **        4) Whether Tidy should validate the page. Defaults to true, but can be turned off.
- **        Declared abstract because it should be extended by a class
- **        that supplies these parameters.
- */
-abstract class pageTest {
-       protected $params;
-       protected $pagePath;
-       protected $cookie = "";
-       protected $tidyValidate = true;
-
-       public function getParams() {
-               return $this->params;
-       }
-
-       public function getPagePath() {
-               return $this->pagePath;
-       }
-
-       public function getCookie() {
-               return $this->cookie;
-       }
-
-       public function tidyValidate() {
-               return $this->tidyValidate;
-       }
-}
-
-
-/**
- ** a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
- */
-class editPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=WIKIFUZZ";
-
-               $this->params = array (
-                               "action"        => "submit",
-                               "wpMinoredit"   => wikiFuzz::makeFuzz( 2 ),
-                               "wpPreview"     => wikiFuzz::makeFuzz( 2 ),
-                               "wpSection"     => wikiFuzz::makeFuzz( 2 ),
-                               "wpEdittime"    => wikiFuzz::makeFuzz( 2 ),
-                               "wpSummary"     => wikiFuzz::makeFuzz( 2 ),
-                               "wpScrolltop"   => wikiFuzz::makeFuzz( 2 ),
-                               "wpStarttime"   => wikiFuzz::makeFuzz( 2 ),
-                               "wpAutoSummary" => wikiFuzz::makeFuzz( 2 ),
-                               "wpTextbox1"    => wikiFuzz::makeFuzz( 40 )  // the main wiki text, need lots of this.
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSection"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEdittime"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSummary"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpScrolltop"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpStarttime"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpAutoSummary"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpTextbox1"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Listusers".
- */
-class listusersTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Listusers";
-
-               $this->params = array (
-                               "title"        => wikiFuzz::makeFuzz( 2 ),
-                               "group"        => wikiFuzz::makeFuzz( 2 ),
-                               "username"     => wikiFuzz::makeFuzz( 2 ),
-                               "Go"           => wikiFuzz::makeFuzz( 2 ),
-                               "limit"        => wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "offset"       => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Search".
- */
-class searchTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Search";
-
-               $this->params = array (
-                               "action"        => "index.php?title=Special:Search",
-                               "ns0"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns1"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns2"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns3"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns4"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns5"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns6"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns7"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns8"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns9"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns10"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns11"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns12"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns13"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns14"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns15"          => wikiFuzz::makeFuzz( 2 ),
-                               "redirs"        => wikiFuzz::makeFuzz( 2 ),
-                               "search"        => wikiFuzz::makeFuzz( 2 ),
-                               "offset"        => wikiFuzz::chooseInput( array( "", "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "fulltext"      => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "searchx"       => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) )
-                                       );
-       }
-}
-
-
-/**
- ** a page test for "Special:Recentchanges".
- */
-class recentchangesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Recentchanges";
-
-               $this->params = array (
-                               "action"        => wikiFuzz::makeFuzz( 2 ),
-                               "title"         => wikiFuzz::makeFuzz( 2 ),
-                               "namespace"     => wikiFuzz::chooseInput( range( -1, 15 ) ),
-                               "Go"            => wikiFuzz::makeFuzz( 2 ),
-                               "invert"        => wikiFuzz::chooseInput( array( "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hideanons"     => wikiFuzz::chooseInput( array( "-1", "------'-------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'limit'         => wikiFuzz::chooseInput( array( "0", "-1", "---------'----0", "+1", "81340909772349234",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               "days"          => wikiFuzz::chooseInput( array( "-1", "----------'---0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hideminor"     => wikiFuzz::chooseInput( array( "-1", "-----------'--0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hidebots"      => wikiFuzz::chooseInput( array( "-1", "---------'----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hideliu"       => wikiFuzz::chooseInput( array( "-1", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hidepatrolled" => wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hidemyself"    => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'categories_any' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'categories'    => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'feed'          => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Prefixindex".
- */
-class prefixindexTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Prefixindex";
-
-               $this->params = array (
-                               "title"         => "Special:Prefixindex",
-                               "namespace"     => wikiFuzz::randnum( 101, -10 ),
-                               "Go"            => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we want 'prefix', sometimes we want 'from', and sometimes we want nothing.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $this->params["prefix"] = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1",
-                                                                                                wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) );
-               }
-               if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $this->params["from"]   = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1",
-                                                                                               wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) );
-               }
-       }
-}
-
-
-/**
- ** a page test for "Special:MIMEsearch".
- */
-class mimeSearchTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:MIMEsearch";
-
-               $this->params = array (
-                               "action"        => "index.php?title=Special:MIMEsearch",
-                               "mime"          => wikiFuzz::makeFuzz( 3 ),
-                               'limit'         => wikiFuzz::chooseInput( array( "0", "-1", "-------'------0", "+1", "81342321351235325",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'        => wikiFuzz::chooseInput( array( "0", "-1", "-----'--------0", "+1", "81341231235365252234324",  wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Log".
- */
-class specialLogTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Log";
-
-               $this->params = array (
-                               "type"        => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "par"         => wikiFuzz::makeFuzz( 2 ),
-                               "user"        => wikiFuzz::makeFuzz( 2 ),
-                               "page"        => wikiFuzz::makeFuzz( 2 ),
-                               "from"        => wikiFuzz::makeFuzz( 2 ),
-                               "until"       => wikiFuzz::makeFuzz( 2 ),
-                               "title"       => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Userlogin", with a successful login.
- */
-class successfulUserLoginTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . wikiFuzz::makeFuzz( 2 );
-
-               $this->params = array (
-                               "wpName"          => USER_ON_WIKI,
-                               // sometimes real password, sometimes not:
-                               'wpPassword'      => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), USER_PASSWORD ) ),
-                               'wpRemember'      => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               $this->cookie = "wikidb_session=" .  wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-
-/**
- ** a page test for "Special:Userlogin".
- */
-class userLoginTest extends pageTest {
-       function __construct() {
-
-               $this->pagePath = "index.php?title=Special:Userlogin";
-
-               $this->params = array (
-                               'wpRetype'        => wikiFuzz::makeFuzz( 2 ),
-                               'wpRemember'      => wikiFuzz::makeFuzz( 2 ),
-                               'wpRealName'      => wikiFuzz::makeFuzz( 2 ),
-                               'wpPassword'      => wikiFuzz::makeFuzz( 2 ),
-                               'wpName'          => wikiFuzz::makeFuzz( 2 ),
-                               'wpMailmypassword' => wikiFuzz::makeFuzz( 2 ),
-                               'wpLoginattempt'  => wikiFuzz::makeFuzz( 2 ),
-                               'wpEmail'         => wikiFuzz::makeFuzz( 2 ),
-                               'wpDomain'        => wikiFuzz::chooseInput( array( "", "local", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpCreateaccountMail' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpCreateaccount' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpCookieCheck'   => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'type'            => wikiFuzz::chooseInput( array( "signup", "login", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'returnto'        => wikiFuzz::makeFuzz( 2 ),
-                               'action'          => wikiFuzz::chooseInput( array( "", "submitlogin", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               $this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-
-/**
- ** a page test for "Special:Ipblocklist" (also includes unblocking)
- */
-class ipblocklistTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Ipblocklist";
-
-               $this->params = array (
-                               'wpUnblockAddress' => wikiFuzz::makeFuzz( 2 ),
-                               'ip'              => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
-                                                                        // something like an IP address, sometimes invalid:
-                                                                        ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
-                                                                          . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
-                               'id'              => wikiFuzz::makeFuzz( 2 ),
-                               'wpUnblockReason' => wikiFuzz::makeFuzz( 2 ),
-                               'action'          => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "success", "submit", "unblock" ) ),
-                               'wpEditToken'     => wikiFuzz::makeFuzz( 2 ),
-                               'wpBlock'         => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "" ) ),
-                               'limit'           => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1",
-                                                                                                "09700982312351132098234",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'          => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1",
-                                                                                                "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["ip"] );
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["id"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpUnblockAddress"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Newimages".
- */
-class newImagesTest extends  pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Newimages";
-
-               $this->params = array (
-                               'hidebots'  => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "1", "", "-1" ) ),
-                               'wpIlMatch' => wikiFuzz::makeFuzz( 2 ),
-                               'until'     => wikiFuzz::makeFuzz( 2 ),
-                               'from'      => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["until"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["from"] );
-       }
-}
-
-
-/**
- ** a page test for the "Special:Imagelist" page.
- */
-class imagelistTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Imagelist";
-
-               $this->params = array (
-                               'sort'      => wikiFuzz::chooseInput( array( "bysize", "byname" , "bydate", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'limit'     => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "09700982312351132098234",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpIlMatch' => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Export".
- */
-class specialExportTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Export";
-
-               $this->params = array (
-                               'action'      => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'pages'       => wikiFuzz::makeFuzz( 2 ),
-                               'curonly'     => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'listauthors' => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'history'     => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ),
-
-                               );
-
-               // For the time being, need to disable "submit" action as Tidy barfs on MediaWiki's XML export.
-               if ( $this->params['action'] == 'submit' ) $this->params['action'] = '';
-
-               // Sometimes remove the history field.
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["history"] );
-
-               // page does not produce HTML.
-               $this->tidyValidate = false;
-       }
-}
-
-
-/**
- ** a page test for "Special:Booksources".
- */
-class specialBooksourcesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Booksources";
-
-               $this->params = array (
-                               'go'    => wikiFuzz::makeFuzz( 2 ),
-                               // ISBN codes have to contain some semi-numeric stuff or will be ignored:
-                               'isbn'  => "0X0" . wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Allpages".
- */
-class specialAllpagesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special%3AAllpages";
-
-               $this->params = array (
-                               'from'      => wikiFuzz::makeFuzz( 2 ),
-                               'namespace' => wikiFuzz::chooseInput( range( -1, 15 ) ),
-                               'go'        => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for the page History.
- */
-class pageHistoryTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page&action=history";
-
-               $this->params = array (
-                               'limit'     => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "go"        => wikiFuzz::chooseInput( array( "first", "last", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "dir"       => wikiFuzz::chooseInput( array( "prev", "next", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "diff"      => wikiFuzz::chooseInput( array( "-1", "--------'-----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "oldid"     => wikiFuzz::chooseInput( array( "prev", "-1", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "feed"      => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for the Special:Contributions".
- */
-class contributionsTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Contributions/" . USER_ON_WIKI;
-
-               $this->params = array (
-                               'target'    => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "newbies", USER_ON_WIKI ) ),
-                               'namespace' => wikiFuzz::chooseInput( array( -1, 15, 1, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "982342131232131231241", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'bot'       => wikiFuzz::chooseInput( array( "", "-1", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'go'        => wikiFuzz::chooseInput( array( "-1", 'prev', 'next', wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for viewing a normal page, whilst posting various params.
- */
-class viewPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page";
-
-               $this->params = array (
-                               "useskin"        => wikiFuzz::chooseInput( array( "chick", "cologneblue", "myskin",
-                                                                               "nostalgia", "simple", "standard", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "uselang"        => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ),
-                                               "ab", "af", "an", "ar", "arc", "as", "ast", "av", "ay", "az", "ba",
-                                               "bat-smg", "be", "bg", "bm", "bn", "bo", "bpy", "br", "bs", "ca",
-                                               "ce", "cs", "csb", "cv", "cy", "da", "de", "dv", "dz", "el", "en",
-                                               "eo", "es", "et", "eu", "fa", "fi", "fo", "fr", "fur", "fy", "ga",
-                                               "gn", "gsw", "gu", "he", "hi", "hr", "hu", "ia", "id", "ii", "is",
-                                               "it", "ja", "jv", "ka", "km", "kn", "ko", "ks", "ku", "kv", "la",
-                                               "li", "lo", "lt", "lv", "mk", "ml", "ms", "nah", "nap", "nds",
-                                               "nds-nl", "nl", "nn", "no", "non", "nv", "oc", "or", "os", "pa",
-                                               "pl", "pms", "ps", "pt", "pt-br", "qu", "rmy", "ro", "ru", "sc",
-                                               "sd", "sk", "sl", "sq", "sr", "sr-ec", "sr-el",
-                                               "su", "sv", "ta", "te", "th", "tr", "tt", "ty", "tyv", "udm",
-                                               "ug", "uk", "ur", "utf8", "vec", "vi", "wa", "xal", "yi", "za",
-                                               "zh", "zh-cn", "zh-hk", "zh-sg", "zh-tw", "zh-tw" ) ),
-                               "returnto"       => wikiFuzz::makeFuzz( 2 ),
-                               "feed"           => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "rcid"           => wikiFuzz::makeFuzz( 2 ),
-                               "action"         => wikiFuzz::chooseInput( array( "view", "raw", "render", wikiFuzz::makeFuzz( 2 ), "markpatrolled" ) ),
-                               "printable"      => wikiFuzz::makeFuzz( 2 ),
-                               "oldid"          => wikiFuzz::makeFuzz( 2 ),
-                               "redirect"       => wikiFuzz::makeFuzz( 2 ),
-                               "diff"           => wikiFuzz::makeFuzz( 2 ),
-                               "search"         => wikiFuzz::makeFuzz( 2 ),
-                               "rdfrom"         => wikiFuzz::makeFuzz( 2 ),  // things from Article.php from here on:
-                               "token"          => wikiFuzz::makeFuzz( 2 ),
-                               "tbid"           => wikiFuzz::makeFuzz( 2 ),
-                               // @todo FIXME: Duplicate array key.
-                               "action"         => wikiFuzz::chooseInput( array( "purge", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpReason"       => wikiFuzz::makeFuzz( 2 ),
-                               "wpEditToken"    => wikiFuzz::makeFuzz( 2 ),
-                               "from"           => wikiFuzz::makeFuzz( 2 ),
-                               "bot"            => wikiFuzz::makeFuzz( 2 ),
-                               "summary"        => wikiFuzz::makeFuzz( 2 ),
-                               "direction"      => wikiFuzz::chooseInput( array( "next", "prev", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "section"        => wikiFuzz::makeFuzz( 2 ),
-                               "preload"        => wikiFuzz::makeFuzz( 2 ),
-
-                               );
-
-               // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
-               if ( $this->params["feed"] == "atom" )     { unset( $this->params["feed"] ); }
-               elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); }
-
-               // Raw pages cannot really be validated
-               if ( $this->params["action"] == "raw" ) unset( $this->params["action"] );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rcid"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["diff"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rdfrom"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["oldid"] );
-
-               // usually don't want action == purge.
-               if ( wikiFuzz::randnum( 6 ) > 1 ) unset( $this->params["action"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Allmessages".
- */
-class specialAllmessagesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Allmessages";
-
-               // only really has one parameter
-               $this->params = array (
-                               "ot"     => wikiFuzz::chooseInput( array( "php", "html", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-/**
- ** a page test for "Special:Newpages".
- */
-class specialNewpagesPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Newpages";
-
-               $this->params = array (
-                               "namespace" => wikiFuzz::chooseInput( range( -1, 15 ) ),
-                               "feed"      => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'limit'     => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
-               if ( $this->params["feed"] == "atom" )     { unset( $this->params["feed"] ); }
-               elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); }
-       }
-}
-
-/**
- ** a page test for "redirect.php"
- */
-class redirectTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "redirect.php";
-
-               $this->params = array (
-                               "wpDropdown" => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpDropdown"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Confirmemail"
- */
-class confirmEmail extends pageTest {
-       function __construct() {
-               // sometimes we send a bogus confirmation code, and sometimes we don't.
-               $this->pagePath = "index.php?title=Special:Confirmemail" . wikiFuzz::chooseInput( array( "", "/" . wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 1 ) ) ) );
-
-               $this->params = array (
-                               "token" => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Watchlist"
- **        Note: this test would be better if we were logged in.
- */
-class watchlistTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Watchlist";
-
-               $this->params = array (
-                               "remove"   => wikiFuzz::chooseInput( array( "Remove checked items from watchlist", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'days'     => wikiFuzz::chooseInput( array( 0, -1, -230, "--", 3, 9, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'hideOwn'  => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'hideBots' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'namespace' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'action'   => wikiFuzz::chooseInput( array( "submit", "clear", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'id[]'     => wikiFuzz::makeFuzz( 2 ),
-                               'edit'     => wikiFuzz::makeFuzz( 2 ),
-                               'token'    => wikiFuzz::chooseInput( array( "", "1243213", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we specifiy "reset", and sometimes we don't.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) $this->params["reset"] = wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-/**
- ** a page test for "Special:Movepage"
- */
-class specialMovePage extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Movepage";
-
-               $this->params = array (
-                               "action"      => wikiFuzz::chooseInput( array( "success", "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'target'      => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ),
-                               'wpOldTitle'  => wikiFuzz::chooseInput( array( "z", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpNewTitle'  => wikiFuzz::chooseInput( array( "y", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpReason'    => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpMovetalk'  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpDeleteAndMove'  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpConfirm'   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'talkmoved'   => wikiFuzz::chooseInput( array( "1", wikiFuzz::makeFuzz( 2 ), "articleexists", 'notalkpage' ) ),
-                               'oldtitle'    => wikiFuzz::makeFuzz( 2 ),
-                               'newtitle'    => wikiFuzz::makeFuzz( 2 ),
-                               'wpMovetalk'  => wikiFuzz::chooseInput( array( "1", "0", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpNewTitle"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpOldTitle"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Undelete"
- */
-class specialUndeletePageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Undelete";
-
-               $this->params = array (
-                               "action"      => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'target'      => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ),
-                               'timestamp'   => wikiFuzz::chooseInput( array( "125223", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'file'        => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'restore'     => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'preview'     => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpComment'   => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["target"] );
-               if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["restore"] );
-               if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["preview"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Unlockdb"
- */
-class specialUnlockdbPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Unlockdb";
-
-               $this->params = array (
-                               "action"        => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken'   => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Lockdb"
- */
-class specialLockdbPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Lockdb";
-
-               $this->params = array (
-                               "action"       => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken'  => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpLockReason' => wikiFuzz::makeFuzz( 2 ),
-                               'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Userrights"
- */
-class specialUserrights extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Userrights";
-
-               $this->params = array (
-                               'wpEditToken'   => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'user-editname' => wikiFuzz::chooseInput( array( "Nickj2", "Nickj2\n<xyz>", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'ssearchuser'   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'saveusergroups' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ), "Save User Groups" ),
-                               'member[]'      => wikiFuzz::chooseInput( array( "0", "bot", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "available[]"   => wikiFuzz::chooseInput( array( "0", "sysop", "bureaucrat", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['ssearchuser'] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['saveusergroups'] );
-       }
-}
-
-
-/**
- ** a test for page protection and unprotection.
- */
-class pageProtectionForm extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page";
-
-               $this->params = array (
-                               "action"               => "protect",
-                               'wpEditToken'          => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "mwProtect-level-edit" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ),
-                               "mwProtect-level-move" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ),
-                               "mwProtectUnchained"   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'mwProtect-reason'     => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["mwProtectUnchained"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['mwProtect-reason'] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Blockip".
- */
-class specialBlockip extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Blockip";
-
-               $this->params = array (
-                               "action"          => wikiFuzz::chooseInput( array( "submit", "",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken'     => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlockAddress"  => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
-                                                                         // something like an IP address, sometimes invalid:
-                                                                        ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
-                                                                         . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
-                               "ip"              => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
-                                                                         // something like an IP address, sometimes invalid:
-                                                                        ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
-                                                                         . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
-                               "wpBlockOther"    => wikiFuzz::chooseInput( array( '', 'Nickj2', wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlockExpiry"   => wikiFuzz::chooseInput( array( "other", "2 hours", "1 day", "3 days", "1 week", "2 weeks",
-                                                                                 "1 month", "3 months", "6 months", "1 year", "infinite", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlockReason"   => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpAnonOnly"      => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpCreateAccount" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlock"         => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockOther"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockExpiry"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockReason"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpAnonOnly"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpCreateAccount"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockAddress"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["ip"] );
-       }
-}
-
-
-/**
- ** a test for the imagepage.
- */
-class imagepageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Image:Small-email.png";
-
-               $this->params = array (
-                               "image"         => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpReason"      => wikiFuzz::makeFuzz( 2 ),
-                               "oldimage"      => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpEditToken"   => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["image"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldimage"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEditToken"] );
-       }
-}
-
-
-/**
- ** a test for page deletion form.
- */
-class pageDeletion extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page&action=delete";
-
-               $this->params = array (
-                               "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpReason"    => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpConfirm"   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpConfirm"] );
-       }
-}
-
-
-
-/**
- ** a test for Revision Deletion.
- */
-class specialRevisionDeletePageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Revisiondelete";
-
-               $this->params = array (
-                               "target"               => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "oldid"                => wikiFuzz::makeFuzz( 2 ),
-                               "oldid[]"              => wikiFuzz::makeFuzz( 2 ),
-                               "wpReason"             => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-text"  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-comment" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-user"  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-restricted" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid[]"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-text"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-comment"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-user"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-restricted"] );
-       }
-}
-
-
-/**
- ** a test for Special:Import.
- */
-class specialImportPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Import";
-
-               $this->params = array (
-                               "action"         => "submit",
-                               "source"         => wikiFuzz::chooseInput( array( "upload", "interwiki", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "MAX_FILE_SIZE"  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "xmlimport"      => wikiFuzz::chooseInput( array( "/var/www/hosts/mediawiki/wiki/AdminSettings.php", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "namespace"      => wikiFuzz::chooseInput( array( wikiFuzz::randnum( 30, -6 ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               "interwiki"      => wikiFuzz::makeFuzz( 2 ),
-                               "interwikiHistory" => wikiFuzz::makeFuzz( 2 ),
-                               "frompage"       => wikiFuzz::makeFuzz( 2 ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["source"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["MAX_FILE_SIZE"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["xmlimport"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwiki"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwikiHistory"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["frompage"] );
-
-               // Note: Need to do a file upload to fully test this Special page.
-       }
-}
-
-
-/**
- ** a test for thumb.php
- */
-class thumbTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "thumb.php";
-
-               $this->params = array (
-                               "f"  => wikiFuzz::chooseInput( array( "..", "\\", "small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "w"  => wikiFuzz::chooseInput( array( "80", wikiFuzz::randnum( 6000, -200 ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               "r"  => wikiFuzz::chooseInput( array( "0", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["f"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["w"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["r"] );
-       }
-}
-
-/**
- ** a test for profileinfo.php
- */
-class profileInfo extends pageTest {
-       function __construct() {
-               $this->pagePath = "profileinfo.php";
-
-               $this->params = array (
-                               "expand"  => wikiFuzz::makeFuzz( 2 ),
-                               "sort"    => wikiFuzz::chooseInput( array( "time", "count", "name", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "filter"  => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["sort"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["filter"] );
-       }
-}
-
-
-/**
- ** a test for Special:Cite (extension Special page).
- */
-class specialCitePageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Cite";
-
-               $this->params = array (
-                               "page"    => wikiFuzz::chooseInput( array( "\" onmouseover=\"alert(1);\"", "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "id"      => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "-9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["page"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["id"] );
-       }
-}
-
-
-/**
- ** a test for Special:Filepath (extension Special page).
- */
-class specialFilepathPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Filepath";
-
-               $this->params = array (
-                               "file"    => wikiFuzz::chooseInput( array( "Small-email.png", "Small-email.png" . wikiFuzz::makeFuzz( 1 ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-       }
-}
-
-
-/**
- ** a test for Special:Renameuser (extension Special page).
- */
-class specialRenameuserPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Renameuser";
-
-               $this->params = array (
-                               "oldusername"   => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
-                               "newusername"   => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
-                               "token"         => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-       }
-}
-
-
-/**
- ** a test for Special:Linksearch (extension Special page).
- */
-class specialLinksearch extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special%3ALinksearch";
-
-               $this->params = array (
-                               "target" => wikiFuzz::makeFuzz( 2 ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 10 ) == 0 ) unset( $this->params["target"] );
-       }
-}
-
-
-/**
- ** a test for Special:CategoryTree (extension Special page).
- */
-class specialCategoryTree extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:CategoryTree";
-
-               $this->params = array (
-                               "target" => wikiFuzz::makeFuzz( 2 ),
-                               "from"   => wikiFuzz::makeFuzz( 2 ),
-                               "until"  => wikiFuzz::makeFuzz( 2 ),
-                               "showas" => wikiFuzz::makeFuzz( 2 ),
-                               "mode"   => wikiFuzz::chooseInput( array( "pages", "categories", "all", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we do want to specify certain parameters.
-               if ( wikiFuzz::randnum( 5 ) == 0 ) $this->params["notree"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-
-/**
- ** a test for "Special:Chemicalsources" (extension Special page).
- */
-class specialChemicalsourcesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Chemicalsources";
-
-               // choose an input format to use.
-               $format =  wikiFuzz::chooseInput(
-                                       array(  'go',
-                                                       'CAS',
-                                                       'EINECS',
-                                                       'CHEBI',
-                                                       'PubChem',
-                                                       'SMILES',
-                                                       'InChI',
-                                                       'ATCCode',
-                                                       'KEGG',
-                                                       'RTECS',
-                                                       'ECNumber',
-                                                       'DrugBank',
-                                                       'Formula',
-                                                       'Name'
-                                                )
-                                       );
-
-               // values for different formats usually start with either letters or numbers.
-               switch ( $format ) {
-                       case 'Name'   : $value = "A"; break;
-                       case 'InChI'  :
-                       case 'SMILES' :
-                       case 'Formula': $value = "C"; break;
-                       default       : $value = "0"; break;
-               }
-
-               // and then we append the fuzz input.
-               $this->params = array ( $format => $value . wikiFuzz::makeFuzz( 2 ) );
-       }
-}
-
-
-/**
- ** A test for api.php (programmatic interface to MediaWiki in XML/JSON/RSS/etc formats).
- ** Quite involved to test because there are lots of options/parameters, and because
- ** for a lot of the functionality if all the parameters don't make sense then it just
- ** returns the help screen - so currently a lot of the tests aren't actually doing much
- ** because something wasn't right in the query.
- **
- ** @todo Incomplete / unfinished; Runs too fast (suggests not much testing going on).
- */
-class api extends pageTest {
-
-       // API login mode.
-       private static function loginMode() {
-               $arr =  array ( "lgname"        => wikiFuzz::makeFuzz( 2 ),
-                                               "lgpassword"    => wikiFuzz::makeFuzz( 2 ),
-                                          );
-               // sometimes we want to specify the extra "lgdomain" parameter.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $arr["lgdomain"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-               }
-
-               return $arr;
-       }
-
-       // API OpenSearch mode.
-       private static function opensearchMode() {
-               return array ( "search"        => wikiFuzz::makeFuzz( 2 ) );
-       }
-
-       // API watchlist feed mode.
-       private static function feedwatchlistMode() {
-               // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible value below?
-               return array ( "feedformat"    => wikiFuzz::chooseInput( array( "rss", "atom" ) ) );
-       }
-
-       // API query mode.
-       private static function queryMode() {
-               // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible params for the elements below?
-               //        Suspect this will stuff up the tests more, but need to check.
-               $params = array (
-                                        // @todo FIXME: More titles.
-                                        "titles"        => wikiFuzz::chooseInput( array( "Main Page" ) ),
-                                        // @todo FIXME: More pageids.
-                                        "pageids"       => 1,
-                                        "prop"          => wikiFuzz::chooseInput( array( "info", "revisions", "watchlist" ) ),
-                                        "list"          => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "usercontribs", "recentchanges", "backlinks", "embeddedin", "imagelinks" ) ),
-                                        "meta"          => wikiFuzz::chooseInput( array( "siteinfo" ) ),
-                                        "generator"     => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "info", "revisions" ) ),
-                                        "siprop"        => wikiFuzz::chooseInput( array( "general", "namespaces", "general|namespaces" ) ),
-                                  );
-
-                // Add extra parameters based on what list choice we got.
-                switch ( $params["list"] ) {
-                       case "usercontribs" : self::addListParams ( $params, "uc", array( "limit", "start", "end", "user", "dir" ) ); break;
-                       case "allpages"     : self::addListParams ( $params, "ap", array( "from", "prefix", "namespace", "filterredir", "limit" ) ); break;
-                       case "watchlist"    : self::addListParams ( $params, "wl", array( "allrev", "start", "end", "namespace", "dir", "limit", "prop" ) ); break;
-                       case "logevents"    : self::addListParams ( $params, "le", array( "limit", "type", "start", "end", "user", "dir" ) ); break;
-                       case "recentchanges": self::addListParams ( $params, "rc", array( "limit", "prop", "show", "namespace", "start", "end", "dir" ) ); break;
-                       case "backlinks"    : self::addListParams ( $params, "bl", array( "continue", "namespace", "redirect", "limit" ) ); break;
-                       case "embeddedin"   : self::addListParams ( $params, "ei", array( "continue", "namespace", "redirect", "limit" ) ); break;
-                       case "imagelinks"   : self::addListParams ( $params, "il", array( "continue", "namespace", "redirect", "limit" ) ); break;
-                }
-
-                if ( $params["prop"] == "revisions" ) {
-                       self::addListParams ( $params, "rv", array( "prop", "limit", "startid", "endid", "end", "dir" ) );
-                }
-
-                // Sometimes we want redirects, sometimes we don't.
-                if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $params["redirects"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-                }
-
-                return $params;
-       }
-
-       // Adds all the elements to the array, using the specified prefix.
-       private static function addListParams( &$array, $prefix, $elements ) {
-               foreach ( $elements as $element ) {
-                       $array[$prefix . $element] = self::getParamDetails( $element );
-               }
-       }
-
-       // For a given element name, returns the data for that element.
-       private static function getParamDetails( $element ) {
-               switch ( $element ) {
-                       case 'startid'    :
-                       case 'endid'      :
-                       case 'start'      :
-                       case 'end'        :
-                       case 'limit'      : return wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", "320742734234235", "20060230121212", wikiFuzz::randnum( 9000, -100 ), wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'dir'        : return wikiFuzz::chooseInput( array( "newer", "older", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'user'       : return wikiFuzz::chooseInput( array( USER_ON_WIKI, wikiFuzz::makeFuzz( 2 ) ) );
-                       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 ) ) );
-                       case 'filterredir': return wikiFuzz::chooseInput( array( "all", "redirects", "nonredirectsallpages", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'allrev'     : return wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'prop'       : return wikiFuzz::chooseInput( array( "user", "comment", "timestamp", "patrol", "flags", "user|user|comment|flags", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'type'       : return wikiFuzz::chooseInput( array( "block", "protect", "rights", "delete", "upload", "move", "import", "renameuser", "newusers", "makebot", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'hide'       : return wikiFuzz::chooseInput( array( "minor", "bots", "anons", "liu", "liu|bots|", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'show'       : return wikiFuzz::chooseInput( array( 'minor', '!minor', 'bot', '!bot', 'anon', '!anon', wikiFuzz::makeFuzz( 2 ) ) );
-                       default           : return wikiFuzz::makeFuzz( 2 );
-               }
-       }
-
-       // Entry point.
-       function __construct() {
-               $this->pagePath = "api.php";
-
-               $modes = array ( "help",
-                                               "login",
-                                               "opensearch",
-                                               "feedwatchlist",
-                                               "query" );
-               $action = wikiFuzz::chooseInput( array_merge ( $modes, array( wikiFuzz::makeFuzz( 2 ) ) ) );
-
-               switch ( $action ) {
-                       case "login"         : $this->params = self::loginMode();
-                                                                  break;
-                       case "opensearch"    : $this->params = self::opensearchMode();
-                                                                  break;
-                       case "feedwatchlist" : $this->params = self::feedwatchlistMode();
-                                                                  break;
-                       case "query"         : $this->params = self::queryMode();
-                                                                  break;
-                       case "help"         :
-                       default             :  // Do something random - "Crazy Ivan" mode.
-                                                                  $random_mode = wikiFuzz::chooseInput( $modes ) . "Mode";
-                                                                  // There is no "helpMode".
-                                                                  if ( $random_mode == "helpMode" ) $random_mode = "queryMode";
-                                                                  $this->params = self::$random_mode();
-                                                                  break;
-               }
-
-               // Save the selected action.
-               $this->params["action"] = $action;
-
-               // Set the cookie:
-               // @todo FIXME: Need to get this cookie dynamically set, rather than hard-coded.
-               $this->cookie = "wikidbUserID=10001; wikidbUserName=Test; wikidb_session=178df0fe68c75834643af65dec9ec98a; wikidbToken=1adc6753d62c44aec950c024d7ae0540";
-
-               // Output format
-               $this->params["format"] = wikiFuzz::chooseInput( array( "json", "jsonfm", "php", "phpfm",
-                                                                                                                          "wddx", "wddxfm", "xml", "xmlfm",
-                                                                                                                          "yaml", "yamlfm", "raw", "rawfm",
-                                                                                                                          wikiFuzz::makeFuzz( 2 ) ) );
-
-               // Page does not produce HTML (sometimes).
-               $this->tidyValidate = false;
-       }
-}
-
-
-/**
- ** a page test for the GeSHi extension.
- */
-class GeSHi_Test extends pageTest {
-
-       private function getGeSHiContent() {
-               return "<source lang=\"" . $this->getLang() . "\" "
-                          . ( wikiFuzz::randnum( 2 ) == 0 ? "line " : "" )
-                          . ( wikiFuzz::randnum( 2 ) == 0 ? "strict " : "" )
-                          . "start=" . wikiFuzz::chooseInput( array( wikiFuzz::randnum( 6000, -6000 ), wikiFuzz::makeFuzz( 2 ) ) )
-                          . ">"
-                          . wikiFuzz::makeFuzz( 2 )
-                          . "</source>";
-       }
-
-       private function getLang() {
-       return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp",
-                               "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl",
-                               "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas",
-                               "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty",
-                               "sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikiFuzz::makeFuzz( 1 ) ) );
-       }
-
-       function __construct() {
-               $this->pagePath = "index.php?title=WIKIFUZZ";
-
-               $this->params = array (
-                               "action"        => "submit",
-                               "wpMinoredit"   => "test",
-                               "wpPreview"     => "test",
-                               "wpSection"     => "test",
-                               "wpEdittime"    => "test",
-                               "wpSummary"     => "test",
-                               "wpScrolltop"   => "test",
-                               "wpStarttime"   => "test",
-                               "wpAutoSummary" => "test",
-                               "wpTextbox1"    => $this->getGeSHiContent() // the main wiki text, contains fake GeSHi content.
-                               );
-       }
-}
-
-/**
- ** selects a page test to run.
- * @param $count
- * @return \api|\confirmEmail|\contributionsTest|\editPageTest|\imagelistTest|\imagepageTest|\ipblocklistTest|\listusersTest|\mimeSearchTest|\newImagesTest|\pageDeletion|\pageHistoryTest|\pageProtectionForm|\prefixindexTest|\profileInfo|\recentchangesTest|\redirectTest|\searchTest|\specialAllmessagesTest|\specialAllpagesTest|\specialBlockip|\specialBooksourcesTest|\specialCategoryTree|\specialChemicalsourcesTest|\specialCitePageTest|\specialExportTest|\specialFilepathPageTest|\specialImportPageTest|\specialLinksearch|\specialLockdbPageTest|\specialLogTest|\specialMovePage|\specialNewpagesPageTest|\specialRenameuserPageTest|\specialRevisionDeletePageTest|\specialUndeletePageTest|\specialUnlockdbPageTest|\specialUserrights|\successfulUserLoginTest|\thumbTest|\userLoginTest|\viewPageTest|\watchlistTest
- */
-function selectPageTest( $count ) {
-
-       // if the user only wants a specific test, then only ever give them that.
-       if ( defined( "SPECIFIC_TEST" ) ) {
-               $testType = SPECIFIC_TEST;
-               return new $testType ();
-       }
-
-       // Some of the time we test Special pages, the remaining
-       // time we test using the standard edit page.
-       switch ( $count % 100 ) {
-               case 0 : return new successfulUserLoginTest();
-               case 1 : return new listusersTest();
-               case 2 : return new searchTest();
-               case 3 : return new recentchangesTest();
-               case 4 : return new prefixindexTest();
-               case 5 : return new mimeSearchTest();
-               case 6 : return new specialLogTest();
-               case 7 : return new userLoginTest();
-               case 8 : return new ipblocklistTest();
-               case 9 : return new newImagesTest();
-               case 10: return new imagelistTest();
-               case 11: return new specialExportTest();
-               case 12: return new specialBooksourcesTest();
-               case 13: return new specialAllpagesTest();
-               case 14: return new pageHistoryTest();
-               case 15: return new contributionsTest();
-               case 16: return new viewPageTest();
-               case 17: return new specialAllmessagesTest();
-               case 18: return new specialNewpagesPageTest();
-               case 19: return new searchTest();
-               case 20: return new redirectTest();
-               case 21: return new confirmEmail();
-               case 22: return new watchlistTest();
-               case 24: return new specialUndeletePageTest();
-               case 25: return new specialMovePage();
-               case 26: return new specialUnlockdbPageTest();
-               case 27: return new specialLockdbPageTest();
-               case 28: return new specialUserrights();
-               case 29: return new pageProtectionForm();
-               case 30: return new specialBlockip();
-               case 31: return new imagepageTest();
-               case 32: return new pageDeletion();
-               case 33: return new specialRevisionDeletePageTest();
-               case 34: return new specialImportPageTest();
-               case 35: return new thumbTest();
-               case 37: return new profileInfo();
-               case 38: return new specialCitePageTest();
-               case 39: return new specialFilepathPageTest();
-               case 40: return new specialRenameuserPageTest();
-               case 41: return new specialLinksearch();
-               case 42: return new specialCategoryTree();
-               case 43: return new api();
-               case 44: return new specialChemicalsourcesTest();
-               default: return new editPageTest();
-       }
-}
-
-
-// /////////////////////  SAVING OUTPUT  /////////////////////////
-
-/**
- ** Utility function for saving a file. Currently has no error checking.
- */
-function saveFile( $data, $name ) {
-       file_put_contents( $name, $data );
-}
-
-/**
- ** Returns a test as an experimental GET-to-POST URL.
- **        This doesn't seem to always work though, and sometimes the output is too long
- **        to be a valid GET URL, so we also save in other formats.
- * @param $test pageTest
- * @return string
- */
-function getAsURL( pageTest $test ) {
-       $used_question_mark = ( strpos( $test->getPagePath(), "?" ) !== false );
-       $retval = "http://get-to-post.nickj.org/?" . WIKI_BASE_URL . $test->getPagePath();
-       foreach ( $test->getParams() as $param => $value ) {
-               if ( !$used_question_mark ) {
-                       $retval .= "?";
-                       $used_question_mark = true;
-               }
-               else {
-                       $retval .= "&";
-               }
-               $retval .= $param . "=" . urlencode( $value );
-       }
-       return $retval;
-}
-
-
-/**
- ** Saves a plain-text human-readable version of a test.
- */
-function saveTestAsText( pageTest $test, $filename ) {
-       $str = "Test: " . $test->getPagePath();
-       foreach ( $test->getParams() as $param => $value ) {
-               $str .= "\n$param: $value";
-       }
-       $str .= "\nGet-to-post URL: " . getAsURL( $test ) . "\n";
-       saveFile( $str, $filename );
-}
-
-
-/**
- ** Saves a test as a standalone basic PHP script that shows this one problem.
- **        Resulting script requires PHP-Curl be installed in order to work.
- */
-function saveTestAsPHP( pageTest $test, $filename ) {
-       $str = "<?php\n"
-               . "\$params = " . var_export( escapeForCurl( $test->getParams() ), true ) . ";\n"
-               . "\$ch = curl_init();\n"
-               . "curl_setopt(\$ch, CURLOPT_POST, 1);\n"
-               . "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \$params );\n"
-               . "curl_setopt(\$ch, CURLOPT_URL, " . var_export( WIKI_BASE_URL . $test->getPagePath(), true ) . ");\n"
-               . "curl_setopt(\$ch, CURLOPT_RETURNTRANSFER,1);\n"
-               .  ( $test->getCookie() ? "curl_setopt(\$ch, CURLOPT_COOKIE, " . var_export( $test->getCookie(), true ) . ");\n" : "" )
-               . "\$result=curl_exec(\$ch);\n"
-               . "curl_close (\$ch);\n"
-               . "print \$result;\n"
-               . "\n";
-       saveFile( $str, $filename );
-}
-
-/**
- * Escapes a value so that it can be used on the command line by Curl.
- *        Specifically, "<" and "@" need to be escaped if they are the first character,
- *        otherwise  curl interprets these as meaning that we want to insert a file.
- * @param $input_params array
- * @return array
- */
-function escapeForCurl( array $input_params ) {
-       $output_params = array();
-       foreach ( $input_params as $param => $value ) {
-               if ( strlen( $value ) > 0 && ( $value[0] == "@" || $value[0] == "<" ) ) {
-                       $value = "\\" . $value;
-               }
-               $output_params[$param] = $value;
-       }
-       return $output_params;
-}
-
-
-/**
- ** Saves a test as a standalone CURL shell script that shows this one problem.
- **        Resulting script requires standalone Curl be installed in order to work.
- */
-function saveTestAsCurl( pageTest $test, $filename ) {
-       $str = "#!/bin/bash\n"
-               . "curl --silent --include --globoff \\\n"
-               . ( $test->getCookie() ? " --cookie " . escapeshellarg( $test->getCookie() ) . " \\\n" : "" );
-       foreach ( escapeForCurl( $test->getParams() ) as $param => $value ) {
-               $str .= " -F " . escapeshellarg( $param ) . "=" . escapeshellarg( $value ) . " \\\n";
-       }
-       $str .= " " . escapeshellarg( WIKI_BASE_URL . $test->getPagePath() ); // beginning space matters.
-       $str .= "\n";
-       saveFile( $str, $filename );
-       chmod( $filename, 0755 ); // make executable
-}
-
-
-/**
- ** Saves the internal data structure to file.
- */
-function saveTestData ( pageTest $test, $filename ) {
-       saveFile( serialize( $test ),  $filename );
-}
-
-
-/**
- ** saves a test in the various formats.
- */
-function saveTest( pageTest $test, $testname ) {
-       $base_name = DIRECTORY . "/" . $testname;
-       saveTestAsText( $test, $base_name . INFO_FILE );
-       saveTestAsPHP ( $test, $base_name . PHP_TEST );
-       saveTestAsCurl( $test, $base_name . CURL_TEST );
-       saveTestData  ( $test, $base_name . DATA_FILE );
-}
-
-// ////////////////// MEDIAWIKI OUTPUT /////////////////////////
-
-/**
- * Asks MediaWiki for the HTML output of a test.
- * @param $test pageTest
- * @return string
- */
-function wikiTestOutput( pageTest $test ) {
-
-       $ch = curl_init();
-
-       // specify the cookie, if required.
-       if ( $test->getCookie() ) {
-               curl_setopt( $ch, CURLOPT_COOKIE, $test->getCookie() );
-       }
-       curl_setopt( $ch, CURLOPT_POST, 1 );                          // save form using a POST
-
-       $params = escapeForCurl( $test->getParams() );
-       curl_setopt( $ch, CURLOPT_POSTFIELDS, $params );             // load the POST variables
-
-       curl_setopt( $ch, CURLOPT_URL, WIKI_BASE_URL . $test->getPagePath() );  // set url to post to
-       curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );                 // return into a variable
-
-       $result = curl_exec ( $ch );
-
-       // if we encountered an error, then say so, and return an empty string.
-       if ( curl_error( $ch ) ) {
-               print "\nCurl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch );
-               $result = "";
-       }
-
-       curl_close ( $ch );
-
-       return $result;
-}
-
-
-// ////////////////// HTML VALIDATION /////////////////////////
-
-/**
- * Asks the validator whether this is valid HTML, or not.
- * @param $text string
- * @return array
- */
-function validateHTML( $text ) {
-
-       $params = array ( "fragment"   => $text );
-
-       $ch = curl_init();
-
-       curl_setopt( $ch, CURLOPT_POST, 1 );                    // save form using a POST
-       curl_setopt( $ch, CURLOPT_POSTFIELDS, $params );        // load the POST variables
-       curl_setopt( $ch, CURLOPT_URL, VALIDATOR_URL );         // set url to post to
-       curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );           // return into a variable
-
-       $result = curl_exec ( $ch );
-
-       // if we encountered an error, then log it, and exit.
-       if ( curl_error( $ch ) ) {
-               trigger_error( "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) );
-               print "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) . " - exiting.\n";
-               exit( 1 );
-       }
-
-       curl_close ( $ch );
-
-       $valid = ( strpos( $result, "Failed validation" ) === false );
-
-       return array( $valid, $result );
-}
-
-/**
- * Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
- * @param $name
- * @return bool
- */
-function tidyCheckFile( $name ) {
-       $file = DIRECTORY . "/" . $name;
-       $command = PATH_TO_TIDY . " -output /tmp/out.html -quiet $file 2>&1";
-       $x = `$command`;
-
-       // Look for the most interesting Tidy errors and warnings.
-       if (   strpos( $x, "end of file while parsing attributes" ) !== false
-                       || strpos( $x, "attribute with missing trailing quote mark" ) !== false
-                       || strpos( $x, "missing '>' for end of tag" ) !== false
-                       || strpos( $x, "Error:" ) !== false ) {
-               print "\nTidy found something - view details with: $command";
-               return false;
-       } else {
-               return true;
-       }
-}
-
-/**
- ** Returns whether or not an database error log file has changed in size since
- **        the last time this was run. This is used to tell if a test caused a DB error.
- * @return bool
- */
-function dbErrorLogged() {
-       static $filesize;
-
-       // first time running this function
-       if ( !isset( $filesize ) ) {
-               // create log if it does not exist
-               if ( DB_ERROR_LOG_FILE && !file_exists( DB_ERROR_LOG_FILE ) ) {
-                       saveFile( '', DB_ERROR_LOG_FILE );
-               }
-               $filesize = filesize( DB_ERROR_LOG_FILE );
-               return false;
-       }
-
-       $newsize = filesize( DB_ERROR_LOG_FILE );
-       // if the log has grown, then assume the current test caused it.
-       if ( $newsize != $filesize ) {
-               $filesize = $newsize;
-               return true;
-       }
-
-       return false;
-}
-
-// //////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
-
-/**
- * takes a page test, and runs it and tests it for problems in the output.
- *        Returns: False on finding a problem, or True on no problems being found.
- * @param $test pageTest
- * @param $testname
- * @param $can_overwrite bool
- * @return bool
- */
-function runWikiTest( pageTest $test, &$testname, $can_overwrite = false ) {
-
-       // by default don't overwrite a previous test of the same name.
-       while ( ! $can_overwrite && file_exists( DIRECTORY . "/" . $testname . DATA_FILE ) ) {
-               $testname .= "-" . mt_rand( 0, 9 );
-       }
-
-       $filename = DIRECTORY . "/" . $testname . DATA_FILE;
-
-       // Store the time before and after, to find slow pages.
-       $before = microtime( true );
-
-       // Get MediaWiki to give us the output of this test.
-       $wiki_preview = wikiTestOutput( $test );
-
-       $after = microtime( true );
-
-       // if we received no response, then that's interesting.
-       if ( $wiki_preview == "" ) {
-               print "\nNo response received for: $filename";
-               return false;
-       }
-
-       // save output HTML to file.
-       $html_file = DIRECTORY . "/" . $testname . HTML_FILE;
-       saveFile( $wiki_preview,  $html_file );
-
-       // if there were PHP errors in the output, then that's interesting too.
-       if (       strpos( $wiki_preview, "<b>Warning</b>: "        ) !== false
-                       || strpos( $wiki_preview, "<b>Fatal error</b>: "    ) !== false
-                       || strpos( $wiki_preview, "<b>Notice</b>: "         ) !== false
-                       || strpos( $wiki_preview, "<b>Error</b>: "          ) !== false
-                       || strpos( $wiki_preview, "<b>Strict Standards:</b>" ) !== false
-                       ) {
-               $error = substr( $wiki_preview, strpos( $wiki_preview, "</b>:" ) + 7, 50 );
-               // Avoid probable PHP bug with bad session ids; http://bugs.php.net/bug.php?id=38224
-               if ( $error != "Unknown: The session id contains illegal character" ) {
-                       print "\nPHP error/warning/notice in HTML output: $html_file ; $error";
-                       return false;
-               }
-       }
-
-       // if there was a MediaWiki Backtrace message in the output, then that's also interesting.
-       if ( strpos( $wiki_preview, "Backtrace:" ) !== false ) {
-               print "\nInternal MediaWiki error in HTML output: $html_file";
-               return false;
-       }
-
-       // if there was a Parser error comment in the output, then that's potentially interesting.
-       if ( strpos( $wiki_preview, "!-- ERR" ) !== false ) {
-               print "\nParser Error comment in HTML output: $html_file";
-               return false;
-       }
-
-       // if a database error was logged, then that's definitely interesting.
-       if ( dbErrorLogged() ) {
-               print "\nDatabase Error logged for: $filename";
-               return false;
-       }
-
-       // validate result
-       $valid = true;
-       if ( VALIDATE_ON_WEB ) {
-               list ( $valid, $validator_output ) = validateHTML( $wiki_preview );
-               if ( !$valid ) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY . "/" . $testname . ".validator_output.html";
-       }
-
-       // Get tidy to check the page, unless we already know it produces non-(X)HTML output.
-       if ( $test->tidyValidate() ) {
-               $valid = tidyCheckFile( $testname . HTML_FILE ) && $valid;
-       }
-
-       // if it took more than 2 seconds to render, then it may be interesting too. (Possible DoS attack?)
-       if ( ( $after - $before ) >= 2 ) {
-               print "\nParticularly slow to render (" . round( $after - $before, 2 ) . " seconds): $filename";
-               return false;
-       }
-
-       if ( $valid ) {
-               // Remove temp HTML file if test was valid:
-               unlink( $html_file );
-       } elseif ( VALIDATE_ON_WEB ) {
-               saveFile( $validator_output,   DIRECTORY . "/" . $testname . ".validator_output.html" );
-       }
-
-       return $valid;
-}
-
-
-// ///////////////// RERUNNING OLD TESTS ///////////////////
-
-/**
- ** We keep our failed tests so that they can be rerun.
- **        This function does that retesting.
- */
-function rerunPreviousTests() {
-       print "Retesting previously found problems.\n";
-
-       $dir_contents = scandir ( DIRECTORY );
-
-       // sort file into the order a normal person would use.
-       natsort ( $dir_contents );
-
-       foreach ( $dir_contents as $file ) {
-
-               // if file is not a test, then skip it.
-               // Note we need to escape any periods or will be treated as "any character".
-               $matches = array();
-               if ( !preg_match( "/(.*)" . str_replace( ".", "\.", DATA_FILE ) . "$/", $file, $matches ) ) continue;
-
-               // reload the test.
-               $full_path = DIRECTORY . "/" . $file;
-               $test = unserialize( file_get_contents( $full_path ) );
-
-               // if this is not a valid test, then skip it.
-               if ( ! $test instanceof pageTest ) {
-                       print "\nSkipping invalid test - $full_path";
-                       continue;
-               }
-
-               // The date format is in Apache log format, which makes it easier to locate
-               // which retest caused which error in the Apache logs (only happens usually if
-               // apache segfaults).
-               if ( !QUIET ) print "[" . date ( "D M d H:i:s Y" ) . "] Retesting $file (" . get_class( $test ) . ")";
-
-               // run test
-               $testname = $matches[1];
-               $valid = runWikiTest( $test, $testname, true );
-
-               if ( !$valid ) {
-                       saveTest( $test, $testname );
-                       if ( QUIET ) {
-                               print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
-                       } else {
-                               print "\n";
-                       }
-               }
-               else {
-                       if ( !QUIET ) print "\r";
-                       if ( DELETE_PASSED_RETESTS ) {
-                               $prefix = DIRECTORY . "/" . $testname;
-                               if ( is_file( $prefix . DATA_FILE ) ) unlink( $prefix . DATA_FILE );
-                               if ( is_file( $prefix . PHP_TEST ) ) unlink( $prefix . PHP_TEST );
-                               if ( is_file( $prefix . CURL_TEST ) ) unlink( $prefix . CURL_TEST );
-                               if ( is_file( $prefix . INFO_FILE ) ) unlink( $prefix . INFO_FILE );
-                       }
-               }
-       }
-
-       print "\nDone retesting.\n";
-}
-
-
-// ////////////////////  MAIN LOOP  ////////////////////////
-
-
-// first check whether CURL is installed, because sometimes it's not.
-if ( ! function_exists( 'curl_init' ) ) {
-       die( "Could not find 'curl_init' function. Is the curl extension compiled into PHP?\n" );
-}
-
-// Initialization of types. wikiFuzz doesn't have a constructor because we want to
-// access it staticly and not have any globals.
-wikiFuzz::$types = array_keys( wikiFuzz::$data );
-
-// Make directory if doesn't exist
-if ( !is_dir( DIRECTORY ) ) {
-       mkdir ( DIRECTORY, 0700 );
-}
-// otherwise, we first retest the things that we have found in previous runs
-elseif ( RERUN_OLD_TESTS ) {
-       rerunPreviousTests();
-}
-
-// main loop.
-$start_time = date( "U" );
-$num_errors = 0;
-if ( !QUIET ) {
-       print "Beginning main loop. Results are stored in the " . DIRECTORY . " directory.\n";
-       print "Press CTRL+C to stop testing.\n";
-}
-
-for ( $count = 0; true; $count++ ) {
-       if ( !QUIET ) {
-               // spinning progress indicator.
-               switch( $count % 4 ) {
-                       case '0': print "\r/";  break;
-                       case '1': print "\r-";  break;
-                       case '2': print "\r\\"; break;
-                       case '3': print "\r|";  break;
-               }
-               print " $count";
-       }
-
-       // generate a page test to run.
-       $test = selectPageTest( $count );
-
-       $mins = ( date( "U" ) - $start_time ) / 60;
-       if ( !QUIET && $mins > 0 ) {
-               print ".  $num_errors poss errors. "
-                       . floor( $mins ) . " mins. "
-                       . round ( $count / $mins, 0 ) . " tests/min. "
-                       . get_class( $test ); // includes the current test name.
-       }
-
-       // run this test against MediaWiki, and see if the output was valid.
-       $testname = $count;
-       $valid = runWikiTest( $test, $testname, false );
-
-       // save the failed test
-       if ( ! $valid ) {
-               if ( QUIET ) {
-                       print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
-               } else {
-                       print "\n";
-               }
-               saveTest( $test, $testname );
-               $num_errors += 1;
-       } elseif ( KEEP_PASSED_TESTS ) {
-               // print current time, with microseconds (matches "strace" format), and the test name.
-               print " " . date( "H:i:s." ) . substr( current( explode( " ", microtime() ) ), 2 ) . " " . $testname;
-               saveTest( $test, $testname );
-       }
-
-       // stop if we have reached max number of errors.
-       if ( defined( "MAX_ERRORS" ) && $num_errors >= MAX_ERRORS ) {
-               break;
-       }
-
-       // stop if we have reached max number of mins runtime.
-       if ( defined( "MAX_RUNTIME" ) && $mins >= MAX_RUNTIME ) {
-               break;
-       }
-}