MediaWiki
REL1_22
|
00001 <?php 00180 // ///////////////////////// COMMAND LINE HELP //////////////////////////////////// 00181 00182 // This is a command line script, load MediaWiki env (gives command line options); 00183 require_once __DIR__ . '/commandLine.inc'; 00184 00185 // if the user asked for an explanation of command line options. 00186 if ( isset( $options["help"] ) ) { 00187 print <<<ENDS 00188 MediaWiki $wgVersion fuzz tester 00189 Usage: php {$_SERVER["SCRIPT_NAME"]} [--quiet] [--base-url=<url-to-test-wiki>] 00190 [--directory=<failed-test-path>] [--include-binary] 00191 [--w3c-validate] [--delete-passed-retests] [--help] 00192 [--user=<username>] [--password=<password>] 00193 [--rerun-failed-tests] [--max-errors=<int>] 00194 [--max-runtime=<num-minutes>] 00195 [--specific-test=<test-name>] 00196 00197 Options: 00198 --quiet : Hides passed tests, shows only failed tests. 00199 --base-url : URL to a wiki on which to run the tests. 00200 The "http://" is optional and can be omitted. 00201 --directory : Full path to directory for storing failed tests. 00202 Will be created if it does not exist. 00203 --include-binary : Includes non-alphanumeric characters in the tests. 00204 --w3c-validate : Validates pages using the W3C's web validator. 00205 Slow. Currently many pages fail validation. 00206 --user : Login name of a valid user on your test wiki. 00207 --password : Password for the valid user on your test wiki. 00208 --delete-passed-retests : Will delete retests that now pass. 00209 Requires --rerun-failed-tests to be meaningful. 00210 --rerun-failed-tests : Whether to rerun any previously failed tests. 00211 --max-errors : Maximum number of errors to report before exiting. 00212 Does not include errors from --rerun-failed-tests 00213 --max-runtime : Maximum runtime, in minutes, to run before exiting. 00214 Only applies to new tests, not --rerun-failed-tests 00215 --specific-test : Runs only the specified fuzz test. 00216 Only applies to new tests, not --rerun-failed-tests 00217 --keep-passed-tests : Saves all test files, even those that pass. 00218 --help : Show this help message. 00219 00220 Example: 00221 If you wanted to fuzz test a nightly MediaWiki checkout using cron for 1 hour, 00222 and only wanted to be informed of errors, and did not want to redo previously 00223 failed tests, and wanted a maximum of 100 errors, then you could do: 00224 php {$_SERVER["SCRIPT_NAME"]} --quiet --max-errors=100 --max-runtime=60 00225 00226 00227 ENDS; 00228 00229 exit( 0 ); 00230 } 00231 00232 00233 // if we got command line options, check they look valid. 00234 $validOptions = array ( "quiet", "base-url", "directory", "include-binary", 00235 "w3c-validate", "user", "password", "delete-passed-retests", 00236 "rerun-failed-tests", "max-errors", 00237 "max-runtime", "specific-test", "keep-passed-tests", "help" ); 00238 if ( !empty( $options ) ) { 00239 $unknownArgs = array_diff ( array_keys( $options ), $validOptions ); 00240 foreach ( $unknownArgs as $invalidArg ) { 00241 print "Ignoring invalid command-line option: --$invalidArg\n"; 00242 } 00243 } 00244 00245 00246 // /////////////////////////// CONFIGURATION //////////////////////////////////// 00247 00248 // URL to some wiki on which we can run our tests. 00249 if ( !empty( $options["base-url"] ) ) { 00250 define( "WIKI_BASE_URL", $options["base-url"] ); 00251 } else { 00252 define( "WIKI_BASE_URL", $wgServer . $wgScriptPath . '/' ); 00253 } 00254 00255 // The directory name where we store the output. 00256 // Example for Windows: "c:\\temp\\wiki-fuzz" 00257 if ( !empty( $options["directory"] ) ) { 00258 define( "DIRECTORY", $options["directory"] ); 00259 } else { 00260 define( "DIRECTORY", "{$wgUploadDirectory}/fuzz-tests" ); 00261 } 00262 00263 // Should our test fuzz data include binary strings? 00264 define( "INCLUDE_BINARY", isset( $options["include-binary"] ) ); 00265 00266 // Whether we want to validate HTML output on the web. 00267 // At the moment very few generated pages will validate, so not recommended. 00268 define( "VALIDATE_ON_WEB", isset( $options["w3c-validate"] ) ); 00269 // URL to use to validate our output: 00270 define( "VALIDATOR_URL", "http://validator.w3.org/check" ); 00271 00272 // Location of Tidy standalone executable. 00273 define( "PATH_TO_TIDY", "/usr/bin/tidy" ); 00274 00275 // The name of a user who has edited on your wiki. Used 00276 // when testing the Special:Contributions and Special:Userlogin page. 00277 if ( !empty( $options["user"] ) ) { 00278 define( "USER_ON_WIKI", $options["user"] ); 00279 } else { 00280 define( "USER_ON_WIKI", "nickj" ); 00281 } 00282 00283 // The password of the above user. Used when testing the login page, 00284 // and to do this we sometimes need to login successfully. 00285 if ( !empty( $options["password"] ) ) { 00286 define( "USER_PASSWORD", $options["password"] ); 00287 } else { 00288 // And no, this is not a valid password on any public wiki. 00289 define( "USER_PASSWORD", "nickj" ); 00290 } 00291 00292 // If we have a test that failed, and then we run it again, and it passes, 00293 // do you want to delete it or keep it? 00294 define( "DELETE_PASSED_RETESTS", isset( $options["delete-passed-retests"] ) ); 00295 00296 // Do we want to rerun old saved tests at script startup? 00297 // Set to true to help catch regressions, or false if you only want new stuff. 00298 define( "RERUN_OLD_TESTS", isset( $options["rerun-failed-tests"] ) ); 00299 00300 // File where the database errors are logged. Should be defined in LocalSettings.php. 00301 define( "DB_ERROR_LOG_FILE", $wgDBerrorLog ); 00302 00303 // Run in chatty mode (all output, default), or run in quiet mode (only prints out details of failed tests)? 00304 define( "QUIET", isset( $options["quiet"] ) ); 00305 00306 // Keep all test files, even those that pass. Potentially useful to tracking input that causes something 00307 // unusual to happen, if you don't know what "unusual" is until later. 00308 define( "KEEP_PASSED_TESTS", isset( $options["keep-passed-tests"] ) ); 00309 00310 // The maximum runtime, if specified. 00311 if ( !empty( $options["max-runtime"] ) && intval( $options["max-runtime"] ) > 0 ) { 00312 define( "MAX_RUNTIME", intval( $options["max-runtime"] ) ); 00313 } 00314 00315 // The maximum number of problems to find, if specified. Excludes retest errors. 00316 if ( !empty( $options["max-errors"] ) && intval( $options["max-errors"] ) > 0 ) { 00317 define( "MAX_ERRORS", intval( $options["max-errors"] ) ); 00318 } 00319 00320 // if the user has requested a specific test (instead of all tests), and the test they asked for looks valid. 00321 if ( !empty( $options["specific-test"] ) ) { 00322 if ( class_exists( $options["specific-test"] ) && get_parent_class( $options["specific-test"] ) == "pageTest" ) { 00323 define( "SPECIFIC_TEST", $options["specific-test"] ); 00324 } 00325 else { 00326 print "Ignoring invalid --specific-test\n"; 00327 } 00328 } 00329 00330 // Define the file extensions we'll use: 00331 define( "PHP_TEST" , ".test.php" ); 00332 define( "CURL_TEST", ".curl.sh" ); 00333 define( "DATA_FILE", ".data.bin" ); 00334 define( "INFO_FILE", ".info.txt" ); 00335 define( "HTML_FILE", ".wiki_preview.html" ); 00336 00337 // If it goes wrong, we want to know about it. 00338 error_reporting( E_ALL | E_STRICT ); 00339 00340 // ////////////// A CLASS THAT GENERATES RANDOM NASTY WIKI & HTML STRINGS ////////////////////// 00341 00342 class wikiFuzz { 00343 00344 // Only some HTML tags are understood with params by MediaWiki, the rest are ignored. 00345 // List the tags that accept params below, as well as what those params are. 00346 public static $data = array( 00347 "B" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00348 "CAPTION" => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ), 00349 "CENTER" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title" ), 00350 "DIV" => array( "CLASS", "STYLE", "ID", "align", "lang", "dir", "title" ), 00351 "FONT" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "face", "size", "color" ), 00352 "H1" => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ), 00353 "H2" => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ), 00354 "HR" => array( "STYLE", "CLASS", "ID", "WIDTH", "lang", "dir", "title", "size", "noshade" ), 00355 "LI" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "value" ), 00356 "TABLE" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "BORDER", "CELLPADDING", 00357 "CELLSPACING", "lang", "dir", "title", "summary", "frame", "rules" ), 00358 "TD" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN", 00359 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang", 00360 "dir", "title", "char", "charoff" ), 00361 "TH" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN", 00362 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang", 00363 "dir", "title", "char", "charoff" ), 00364 "TR" => array( "CLASS", "STYLE", "ID", "BGCOLOR", "ALIGN", "VALIGN", "lang", "dir", "title", "char", "charoff" ), 00365 "UL" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "type" ), 00366 "P" => array( "style", "class", "id", "align", "lang", "dir", "title" ), 00367 "blockquote" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "cite" ), 00368 "span" => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ), 00369 "code" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00370 "tt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00371 "small" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00372 "big" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00373 "s" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00374 "u" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00375 "del" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ), 00376 "ins" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ), 00377 "sub" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00378 "sup" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00379 "ol" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "start" ), 00380 "br" => array( "CLASS", "ID", "STYLE", "title", "clear" ), 00381 "cite" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00382 "var" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00383 "ruby" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00384 "rt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00385 "rp" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00386 "dt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00387 "dl" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00388 "em" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00389 "strong" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00390 "i" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ), 00391 "thead" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ), 00392 "tfoot" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ), 00393 "tbody" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ), 00394 "colgroup" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width' ), 00395 "col" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width' ), 00396 "pre" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "width" ), 00397 00398 // extension tags that accept parameters: 00399 "sort" => array( "order", "class" ), 00400 "ref" => array( "name" ), 00401 "categorytree" => array( "hideroot", "mode", "style" ), 00402 "chemform" => array( "link", "wikilink", "query" ), 00403 "section" => array( "begin", "new" ), 00404 00405 // older MW transclusion. 00406 "transclude" => array( "page" ), 00407 ); 00408 00409 // The types of the HTML that we will be testing were defined above 00410 // Note: this needs to be initialized later to be equal to: array_keys(wikiFuzz::$data); 00411 // as such, it also needs to also be publicly modifiable. 00412 public static $types; 00413 00414 00415 // Some attribute values. 00416 static private $other = array( "&", "=", ":", "?", "\"", "\n", "%n%n%n%n%n%n%n%n%n%n%n%n", "\\" ); 00417 static private $ints = array( 00418 // various numbers 00419 "0", "-1", "127", "-7897", "89000", "808080", "90928345", 00420 "0xfffffff", "ffff", 00421 00422 // Different ways of saying: ' 00423 "'", // Long UTF-8 Unicode encoding 00424 "'", // dec version. 00425 "'", // hex version. 00426 "§", // malformed hex variant, MSB not zero. 00427 00428 // Different ways of saying: " 00429 """, // Long UTF-8 Unicode encoding 00430 """, 00431 """, // hex version. 00432 "¢", // malformed hex variant, MSB not zero. 00433 00434 // Different ways of saying: < 00435 "<", 00436 "<", // Long UTF-8 Unicode encoding without semicolon (Mediawiki wants the colon) 00437 "<", // Long UTF-8 Unicode encoding with semicolon 00438 "<", 00439 "<", // hex version. 00440 "¼", // malformed hex variant, MSB not zero. 00441 "<", // mid-length hex version 00442 "<", // slightly longer hex version, with capital "X" 00443 00444 // Different ways of saying: > 00445 ">", 00446 ">", // Long UTF-8 Unicode encoding 00447 ">", 00448 ">", // hex version. 00449 "¾", // malformed variant, MSB not zero. 00450 00451 // Different ways of saying: [ 00452 "[", // Long UTF-8 Unicode encoding 00453 "[", 00454 "[", // hex version. 00455 00456 // Different ways of saying: {{ 00457 "{{", // Long UTF-8 Unicode encoding 00458 "{{", 00459 "{{", // hex version. 00460 00461 // Different ways of saying: | 00462 "|", // Long UTF-8 Unicode encoding 00463 "|", 00464 "|", // hex version. 00465 "ü", // malformed hex variant, MSB not zero. 00466 00467 // a "lignature" - http://www.robinlionheart.com/stds/html4/spchars#ligature 00468 // ‌ == ‌ 00469 "‌" 00470 ); 00471 00472 // Defines various wiki-related bits of syntax, that can potentially cause 00473 // MediaWiki to do something other than just print that literal text. 00474 static private $ext = array( 00475 // links, templates, parameters. 00476 "[[", "]]", "{{", "}}", "|", "[", "]", "{{{", "}}}", "|]]", 00477 00478 // wiki tables. 00479 "\n{|", "\n|}", 00480 "!", 00481 "\n!", 00482 "!!", 00483 "||", 00484 "\n|-", "| ", "\n|", 00485 00486 // section headings. 00487 "=", "==", "===", "====", "=====", "======", 00488 00489 // lists (ordered and unordered) and indentation. 00490 "\n*", "*", "\n:", ":", 00491 "\n#", "#", 00492 00493 // definition lists (dl, dt, dd), newline, and newline with pre, and a tab. 00494 "\n;", ";", "\n ", 00495 00496 // Whitespace: newline, tab, space. 00497 "\n", "\t", " ", 00498 00499 // Some XSS attack vectors from http://ha.ckers.org/xss.html 00500 "	", // tab 00501 "
", // newline 00502 "
", // carriage return 00503 "\0", // null character 00504 "  ", // spaces and meta characters 00505 "'';!--\"<XSS>=&{()}", // compact injection of XSS & SQL tester 00506 00507 // various NULL fields 00508 "%00", 00509 "�", 00510 "\0", 00511 00512 // horizontal rule. 00513 "-----", "\n-----", 00514 00515 // signature, redirect, bold, italics. 00516 "~~~~", "#REDIRECT [[", "'''", "''", 00517 00518 // comments. 00519 "<!--", "-->", 00520 00521 // quotes. 00522 "\"", "'", 00523 00524 // tag start and tag end. 00525 "<", ">", 00526 00527 // implicit link creation on URIs. 00528 "http://", 00529 "https://", 00530 "ftp://", 00531 "irc://", 00532 "news:", 00533 'gopher://', 00534 'telnet://', 00535 'nntp://', 00536 'worldwind://', 00537 'mailto:', 00538 00539 // images. 00540 "[[image:", 00541 ".gif", 00542 ".png", 00543 ".jpg", 00544 ".jpeg", 00545 'thumbnail=', 00546 'thumbnail', 00547 'thumb=', 00548 'thumb', 00549 'right', 00550 'none', 00551 'left', 00552 'framed', 00553 'frame', 00554 'enframed', 00555 'centre', 00556 'center', 00557 "Image:", 00558 "[[:Image", 00559 'px', 00560 'upright=', 00561 'border', 00562 00563 // misc stuff to throw at the Parser. 00564 '%08X', 00565 '/', 00566 ":x{|", 00567 "\n|+", 00568 "<noinclude>", 00569 "</noinclude>", 00570 " \302\273", 00571 " :", 00572 " !", 00573 " ;", 00574 "\302\253", 00575 "[[category:", 00576 "?=", 00577 "(", 00578 ")", 00579 "]]]", 00580 "../", 00581 "{{{{", 00582 "}}}}", 00583 "[[Special:", 00584 "<includeonly>", 00585 "</includeonly>", 00586 "<!--MWTEMPLATESECTION=", 00587 '<!--MWTOC-->', 00588 00589 // implicit link creation on booknum, RFC, and PubMed ID usage (both with and without IDs) 00590 "ISBN 2", 00591 "RFC 000", 00592 "PMID 000", 00593 "ISBN ", 00594 "RFC ", 00595 "PMID ", 00596 00597 // magic words: 00598 '__NOTOC__', 00599 '__FORCETOC__', 00600 '__NOEDITSECTION__', 00601 '__START__', 00602 '__NOTITLECONVERT__', 00603 '__NOCONTENTCONVERT__', 00604 '__END__', 00605 '__TOC__', 00606 '__NOTC__', 00607 '__NOCC__', 00608 "__FORCETOC__", 00609 "__NEWSECTIONLINK__", 00610 "__NOGALLERY__", 00611 00612 // more magic words / internal templates. 00613 '{{PAGENAME}}', 00614 '{{PAGENAMEE}}', 00615 '{{NAMESPACE}}', 00616 "{{MSG:", 00617 "}}", 00618 "{{MSGNW:", 00619 "}}", 00620 "{{INT:", 00621 "}}", 00622 '{{SITENAME}}', 00623 "{{NS:", 00624 "}}", 00625 "{{LOCALURL:", 00626 "}}", 00627 "{{LOCALURLE:", 00628 "}}", 00629 "{{SCRIPTPATH}}", 00630 "{{GRAMMAR:gentiv|", 00631 "}}", 00632 "{{REVISIONID}}", 00633 "{{SUBPAGENAME}}", 00634 "{{SUBPAGENAMEE}}", 00635 "{{ns:0}}", 00636 "{{fullurle:", 00637 "}}", 00638 "{{subst::", 00639 "}}", 00640 "{{UCFIRST:", 00641 "}}", 00642 "{{UC:", 00643 '{{SERVERNAME}}', 00644 '{{SERVER}}', 00645 "{{RAW:", 00646 "}}", 00647 "{{PLURAL:", 00648 "}}", 00649 "{{LCFIRST:", 00650 "}}", 00651 "{{LC:", 00652 "}}", 00653 '{{CURRENTWEEK}}', 00654 '{{CURRENTDOW}}', 00655 "{{INT:{{LC:contribs-showhideminor}}|", 00656 "}}", 00657 "{{INT:googlesearch|", 00658 "}}", 00659 "{{ROOTPAGENAME}}", 00660 "{{BASEPAGENAME}}", 00661 "{{CONTENTLANGUAGE}}", 00662 "{{PAGESINNAMESPACE:}}", 00663 "{{#language:", 00664 "}}", 00665 "{{#special:", 00666 "}}", 00667 "{{#special:emailuser", 00668 "}}", 00669 00670 // Some raw link for magic words. 00671 "{{NUMBEROFPAGES:R", 00672 "}}", 00673 "{{NUMBEROFUSERS:R", 00674 "}}", 00675 "{{NUMBEROFARTICLES:R", 00676 "}}", 00677 "{{NUMBEROFFILES:R", 00678 "}}", 00679 "{{NUMBEROFADMINS:R", 00680 "}}", 00681 "{{padleft:", 00682 "}}", 00683 "{{padright:", 00684 "}}", 00685 "{{DEFAULTSORT:", 00686 "}}", 00687 00688 // internal Math "extension": 00689 "<math>", 00690 "</math>", 00691 00692 // Parser extension functions: 00693 "{{#expr:", 00694 "{{#if:", 00695 "{{#ifeq:", 00696 "{{#ifexist:", 00697 "{{#ifexpr:", 00698 "{{#switch:", 00699 "{{#time:", 00700 "}}", 00701 00702 // references table for the Cite extension. 00703 "<references/>", 00704 00705 // Internal Parser tokens - try inserting some of these. 00706 "UNIQ25f46b0524f13e67NOPARSE", 00707 "UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002", 00708 "\x07UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002-QINU", 00709 00710 // Inputbox extension: 00711 "<inputbox>\ntype=search\nsearchbuttonlabel=\n", 00712 "</inputbox>", 00713 00714 // charInsert extension: 00715 "<charInsert>", 00716 "</charInsert>", 00717 00718 // wikiHiero extension: 00719 "<hiero>", 00720 "</hiero>", 00721 00722 // Image gallery: 00723 "<gallery>", 00724 "</gallery>", 00725 00726 // FixedImage extension. 00727 "<fundraising/>", 00728 00729 // Timeline extension: currently untested. 00730 00731 // Nowiki: 00732 "<nOwIkI>", 00733 "</nowiki>", 00734 00735 // an external image to test the external image displaying code 00736 "http://debian.org/Pics/debian.png", 00737 00738 // LabeledSectionTransclusion extension. 00739 "{{#lstx:", 00740 "}}", 00741 "{{#lst:", 00742 "}}", 00743 "{{#lst:Main Page|", 00744 "}}" 00745 ); 00746 00750 public static function chooseInput( array $input ) { 00751 $randindex = wikiFuzz::randnum( count( $input ) - 1 ); 00752 return $input[$randindex]; 00753 } 00754 00755 // Max number of parameters for HTML attributes. 00756 static private $maxparams = 10; 00757 00764 public static function randnum( $finish, $start = 0 ) { 00765 return mt_rand( $start, $finish ); 00766 } 00767 00772 private static function randstring() { 00773 $thestring = ""; 00774 00775 for ( $i = 0; $i < 40; $i++ ) { 00776 $what = wikiFuzz::randnum( 1 ); 00777 00778 if ( $what == 0 ) { // include some random wiki syntax 00779 $which = wikiFuzz::randnum( count( wikiFuzz::$ext ) - 1 ); 00780 $thestring .= wikiFuzz::$ext[$which]; 00781 } 00782 else { // include some random text 00783 $char = INCLUDE_BINARY 00784 // Decimal version: 00785 // "&#" . wikiFuzz::randnum(255) . ";" 00786 // Hex version: 00787 ? "&#x" . str_pad( dechex( wikiFuzz::randnum( 255 ) ), wikiFuzz::randnum( 2, 7 ), "0", STR_PAD_LEFT ) . ";" 00788 // A truly binary version: 00789 // ? chr(wikiFuzz::randnum(0,255)) 00790 : chr( wikiFuzz::randnum( 126, 32 ) ); 00791 00792 $length = wikiFuzz::randnum( 8 ); 00793 $thestring .= str_repeat ( $char, $length ); 00794 } 00795 } 00796 return $thestring; 00797 } 00798 00804 private static function makestring() { 00805 $what = wikiFuzz::randnum( 2 ); 00806 if ( $what == 0 ) { 00807 return wikiFuzz::randstring(); 00808 } elseif ( $what == 1 ) { 00809 return wikiFuzz::$ints[wikiFuzz::randnum( count( wikiFuzz::$ints ) - 1 )]; 00810 } else { 00811 return wikiFuzz::$other[wikiFuzz::randnum( count( wikiFuzz::$other ) - 1 )]; 00812 } 00813 } 00814 00821 private static function stringEscape( $matches ) { 00822 return sprintf( "\\x%02x", ord( $matches[1] ) ); 00823 } 00824 00831 public static function makeTitleSafe( $str ) { 00832 $legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF"; 00833 return preg_replace_callback( 00834 "/([^$legalTitleChars])/", 'wikiFuzz::stringEscape', 00835 $str ); 00836 } 00837 00842 private static function loop() { 00843 switch ( wikiFuzz::randnum( 3 ) ) { 00844 case 1: // an opening tag, with parameters. 00845 $string = ""; 00846 $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 ); 00847 $t = wikiFuzz::$types[$i]; 00848 $arr = wikiFuzz::$data[$t]; 00849 $string .= "<" . $t . " "; 00850 $num_params = min( wikiFuzz::$maxparams, count( $arr ) ); 00851 for ( $z = 0; $z < $num_params; $z++ ) { 00852 $badparam = $arr[wikiFuzz::randnum( count( $arr ) - 1 )]; 00853 $badstring = wikiFuzz::makestring(); 00854 $string .= $badparam . "=" . wikiFuzz::getRandQuote() . $badstring . wikiFuzz::getRandQuote() . " "; 00855 } 00856 $string .= ">\n"; 00857 return $string; 00858 case 2: // a closing tag. 00859 $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 ); 00860 return "</" . wikiFuzz::$types[$i] . ">"; 00861 case 3: // a random string, between tags. 00862 return wikiFuzz::makeString(); 00863 } 00864 return ""; // catch-all, should never be called. 00865 } 00866 00871 private static function getRandQuote() { 00872 switch ( wikiFuzz::randnum( 3 ) ) { 00873 case 1 : return "'"; 00874 case 2 : return "\""; 00875 default: return ""; 00876 } 00877 } 00878 00884 public static function makeFuzz( $maxtypes = 2 ) { 00885 $page = ""; 00886 for ( $k = 0; $k < $maxtypes; $k++ ) { 00887 $page .= wikiFuzz::loop(); 00888 } 00889 return $page; 00890 } 00891 } 00892 00893 00894 // ////// MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM /////// 00895 00905 abstract class pageTest { 00906 protected $params; 00907 protected $pagePath; 00908 protected $cookie = ""; 00909 protected $tidyValidate = true; 00910 00911 public function getParams() { 00912 return $this->params; 00913 } 00914 00915 public function getPagePath() { 00916 return $this->pagePath; 00917 } 00918 00919 public function getCookie() { 00920 return $this->cookie; 00921 } 00922 00923 public function tidyValidate() { 00924 return $this->tidyValidate; 00925 } 00926 } 00927 00928 00932 class editPageTest extends pageTest { 00933 function __construct() { 00934 $this->pagePath = "index.php?title=WIKIFUZZ"; 00935 00936 $this->params = array ( 00937 "action" => "submit", 00938 "wpMinoredit" => wikiFuzz::makeFuzz( 2 ), 00939 "wpPreview" => wikiFuzz::makeFuzz( 2 ), 00940 "wpSection" => wikiFuzz::makeFuzz( 2 ), 00941 "wpEdittime" => wikiFuzz::makeFuzz( 2 ), 00942 "wpSummary" => wikiFuzz::makeFuzz( 2 ), 00943 "wpScrolltop" => wikiFuzz::makeFuzz( 2 ), 00944 "wpStarttime" => wikiFuzz::makeFuzz( 2 ), 00945 "wpAutoSummary" => wikiFuzz::makeFuzz( 2 ), 00946 "wpTextbox1" => wikiFuzz::makeFuzz( 40 ) // the main wiki text, need lots of this. 00947 ); 00948 00949 // sometimes we don't want to specify certain parameters. 00950 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSection"] ); 00951 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEdittime"] ); 00952 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSummary"] ); 00953 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpScrolltop"] ); 00954 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpStarttime"] ); 00955 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpAutoSummary"] ); 00956 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpTextbox1"] ); 00957 } 00958 } 00959 00960 00964 class listusersTest extends pageTest { 00965 function __construct() { 00966 $this->pagePath = "index.php?title=Special:Listusers"; 00967 00968 $this->params = array ( 00969 "title" => wikiFuzz::makeFuzz( 2 ), 00970 "group" => wikiFuzz::makeFuzz( 2 ), 00971 "username" => wikiFuzz::makeFuzz( 2 ), 00972 "Go" => wikiFuzz::makeFuzz( 2 ), 00973 "limit" => wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 00974 "offset" => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) ) 00975 ); 00976 } 00977 } 00978 00979 00983 class searchTest extends pageTest { 00984 function __construct() { 00985 $this->pagePath = "index.php?title=Special:Search"; 00986 00987 $this->params = array ( 00988 "action" => "index.php?title=Special:Search", 00989 "ns0" => wikiFuzz::makeFuzz( 2 ), 00990 "ns1" => wikiFuzz::makeFuzz( 2 ), 00991 "ns2" => wikiFuzz::makeFuzz( 2 ), 00992 "ns3" => wikiFuzz::makeFuzz( 2 ), 00993 "ns4" => wikiFuzz::makeFuzz( 2 ), 00994 "ns5" => wikiFuzz::makeFuzz( 2 ), 00995 "ns6" => wikiFuzz::makeFuzz( 2 ), 00996 "ns7" => wikiFuzz::makeFuzz( 2 ), 00997 "ns8" => wikiFuzz::makeFuzz( 2 ), 00998 "ns9" => wikiFuzz::makeFuzz( 2 ), 00999 "ns10" => wikiFuzz::makeFuzz( 2 ), 01000 "ns11" => wikiFuzz::makeFuzz( 2 ), 01001 "ns12" => wikiFuzz::makeFuzz( 2 ), 01002 "ns13" => wikiFuzz::makeFuzz( 2 ), 01003 "ns14" => wikiFuzz::makeFuzz( 2 ), 01004 "ns15" => wikiFuzz::makeFuzz( 2 ), 01005 "redirs" => wikiFuzz::makeFuzz( 2 ), 01006 "search" => wikiFuzz::makeFuzz( 2 ), 01007 "offset" => wikiFuzz::chooseInput( array( "", "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) ), 01008 "fulltext" => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) ), 01009 "searchx" => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) ) 01010 ); 01011 } 01012 } 01013 01014 01018 class recentchangesTest extends pageTest { 01019 function __construct() { 01020 $this->pagePath = "index.php?title=Special:Recentchanges"; 01021 01022 $this->params = array ( 01023 "action" => wikiFuzz::makeFuzz( 2 ), 01024 "title" => wikiFuzz::makeFuzz( 2 ), 01025 "namespace" => wikiFuzz::chooseInput( range( -1, 15 ) ), 01026 "Go" => wikiFuzz::makeFuzz( 2 ), 01027 "invert" => wikiFuzz::chooseInput( array( "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01028 "hideanons" => wikiFuzz::chooseInput( array( "-1", "------'-------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01029 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "---------'----0", "+1", "81340909772349234", wikiFuzz::makeFuzz( 2 ) ) ), 01030 "days" => wikiFuzz::chooseInput( array( "-1", "----------'---0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01031 "hideminor" => wikiFuzz::chooseInput( array( "-1", "-----------'--0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01032 "hidebots" => wikiFuzz::chooseInput( array( "-1", "---------'----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01033 "hideliu" => wikiFuzz::chooseInput( array( "-1", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01034 "hidepatrolled" => wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01035 "hidemyself" => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01036 'categories_any' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01037 'categories' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01038 'feed' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ) 01039 ); 01040 } 01041 } 01042 01043 01047 class prefixindexTest extends pageTest { 01048 function __construct() { 01049 $this->pagePath = "index.php?title=Special:Prefixindex"; 01050 01051 $this->params = array ( 01052 "title" => "Special:Prefixindex", 01053 "namespace" => wikiFuzz::randnum( 101, -10 ), 01054 "Go" => wikiFuzz::makeFuzz( 2 ) 01055 ); 01056 01057 // sometimes we want 'prefix', sometimes we want 'from', and sometimes we want nothing. 01058 if ( wikiFuzz::randnum( 3 ) == 0 ) { 01059 $this->params["prefix"] = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1", 01060 wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) ); 01061 } 01062 if ( wikiFuzz::randnum( 3 ) == 0 ) { 01063 $this->params["from"] = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1", 01064 wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) ); 01065 } 01066 } 01067 } 01068 01069 01073 class mimeSearchTest extends pageTest { 01074 function __construct() { 01075 $this->pagePath = "index.php?title=Special:MIMEsearch"; 01076 01077 $this->params = array ( 01078 "action" => "index.php?title=Special:MIMEsearch", 01079 "mime" => wikiFuzz::makeFuzz( 3 ), 01080 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "-------'------0", "+1", "81342321351235325", wikiFuzz::makeFuzz( 2 ) ) ), 01081 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "-----'--------0", "+1", "81341231235365252234324", wikiFuzz::makeFuzz( 2 ) ) ) 01082 ); 01083 } 01084 } 01085 01086 01090 class specialLogTest extends pageTest { 01091 function __construct() { 01092 $this->pagePath = "index.php?title=Special:Log"; 01093 01094 $this->params = array ( 01095 "type" => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ), 01096 "par" => wikiFuzz::makeFuzz( 2 ), 01097 "user" => wikiFuzz::makeFuzz( 2 ), 01098 "page" => wikiFuzz::makeFuzz( 2 ), 01099 "from" => wikiFuzz::makeFuzz( 2 ), 01100 "until" => wikiFuzz::makeFuzz( 2 ), 01101 "title" => wikiFuzz::makeFuzz( 2 ) 01102 ); 01103 } 01104 } 01105 01106 01110 class successfulUserLoginTest extends pageTest { 01111 function __construct() { 01112 $this->pagePath = "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . wikiFuzz::makeFuzz( 2 ); 01113 01114 $this->params = array ( 01115 "wpName" => USER_ON_WIKI, 01116 // sometimes real password, sometimes not: 01117 'wpPassword' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), USER_PASSWORD ) ), 01118 'wpRemember' => wikiFuzz::makeFuzz( 2 ) 01119 ); 01120 01121 $this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) ); 01122 } 01123 } 01124 01125 01129 class userLoginTest extends pageTest { 01130 function __construct() { 01131 01132 $this->pagePath = "index.php?title=Special:Userlogin"; 01133 01134 $this->params = array ( 01135 'wpRetype' => wikiFuzz::makeFuzz( 2 ), 01136 'wpRemember' => wikiFuzz::makeFuzz( 2 ), 01137 'wpRealName' => wikiFuzz::makeFuzz( 2 ), 01138 'wpPassword' => wikiFuzz::makeFuzz( 2 ), 01139 'wpName' => wikiFuzz::makeFuzz( 2 ), 01140 'wpMailmypassword' => wikiFuzz::makeFuzz( 2 ), 01141 'wpLoginattempt' => wikiFuzz::makeFuzz( 2 ), 01142 'wpEmail' => wikiFuzz::makeFuzz( 2 ), 01143 'wpDomain' => wikiFuzz::chooseInput( array( "", "local", wikiFuzz::makeFuzz( 2 ) ) ), 01144 'wpCreateaccountMail' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ), 01145 'wpCreateaccount' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ), 01146 'wpCookieCheck' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ), 01147 'type' => wikiFuzz::chooseInput( array( "signup", "login", "", wikiFuzz::makeFuzz( 2 ) ) ), 01148 'returnto' => wikiFuzz::makeFuzz( 2 ), 01149 'action' => wikiFuzz::chooseInput( array( "", "submitlogin", wikiFuzz::makeFuzz( 2 ) ) ) 01150 ); 01151 01152 $this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) ); 01153 } 01154 } 01155 01156 01160 class ipblocklistTest extends pageTest { 01161 function __construct() { 01162 $this->pagePath = "index.php?title=Special:Ipblocklist"; 01163 01164 $this->params = array ( 01165 'wpUnblockAddress' => wikiFuzz::makeFuzz( 2 ), 01166 'ip' => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ), 01167 // something like an IP address, sometimes invalid: 01168 ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "." 01169 . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ), 01170 'id' => wikiFuzz::makeFuzz( 2 ), 01171 'wpUnblockReason' => wikiFuzz::makeFuzz( 2 ), 01172 'action' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "success", "submit", "unblock" ) ), 01173 'wpEditToken' => wikiFuzz::makeFuzz( 2 ), 01174 'wpBlock' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "" ) ), 01175 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", 01176 "09700982312351132098234", wikiFuzz::makeFuzz( 2 ) ) ), 01177 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", 01178 "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ) 01179 ); 01180 01181 // sometimes we don't want to specify certain parameters. 01182 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] ); 01183 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["ip"] ); 01184 if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["id"] ); 01185 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpUnblockAddress"] ); 01186 } 01187 } 01188 01189 01193 class newImagesTest extends pageTest { 01194 function __construct() { 01195 $this->pagePath = "index.php?title=Special:Newimages"; 01196 01197 $this->params = array ( 01198 'hidebots' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "1", "", "-1" ) ), 01199 'wpIlMatch' => wikiFuzz::makeFuzz( 2 ), 01200 'until' => wikiFuzz::makeFuzz( 2 ), 01201 'from' => wikiFuzz::makeFuzz( 2 ) 01202 ); 01203 01204 // sometimes we don't want to specify certain parameters. 01205 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["until"] ); 01206 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["from"] ); 01207 } 01208 } 01209 01210 01214 class imagelistTest extends pageTest { 01215 function __construct() { 01216 $this->pagePath = "index.php?title=Special:Imagelist"; 01217 01218 $this->params = array ( 01219 'sort' => wikiFuzz::chooseInput( array( "bysize", "byname" , "bydate", wikiFuzz::makeFuzz( 2 ) ) ), 01220 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "09700982312351132098234", wikiFuzz::makeFuzz( 2 ) ) ), 01221 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ), 01222 'wpIlMatch' => wikiFuzz::makeFuzz( 2 ) 01223 ); 01224 } 01225 } 01226 01227 01231 class specialExportTest extends pageTest { 01232 function __construct() { 01233 $this->pagePath = "index.php?title=Special:Export"; 01234 01235 $this->params = array ( 01236 'action' => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ), 01237 'pages' => wikiFuzz::makeFuzz( 2 ), 01238 'curonly' => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ), 01239 'listauthors' => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ), 01240 'history' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ), 01241 01242 ); 01243 01244 // For the time being, need to disable "submit" action as Tidy barfs on MediaWiki's XML export. 01245 if ( $this->params['action'] == 'submit' ) $this->params['action'] = ''; 01246 01247 // Sometimes remove the history field. 01248 if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["history"] ); 01249 01250 // page does not produce HTML. 01251 $this->tidyValidate = false; 01252 } 01253 } 01254 01255 01259 class specialBooksourcesTest extends pageTest { 01260 function __construct() { 01261 $this->pagePath = "index.php?title=Special:Booksources"; 01262 01263 $this->params = array ( 01264 'go' => wikiFuzz::makeFuzz( 2 ), 01265 // ISBN codes have to contain some semi-numeric stuff or will be ignored: 01266 'isbn' => "0X0" . wikiFuzz::makeFuzz( 2 ) 01267 ); 01268 } 01269 } 01270 01271 01275 class specialAllpagesTest extends pageTest { 01276 function __construct() { 01277 $this->pagePath = "index.php?title=Special%3AAllpages"; 01278 01279 $this->params = array ( 01280 'from' => wikiFuzz::makeFuzz( 2 ), 01281 'namespace' => wikiFuzz::chooseInput( range( -1, 15 ) ), 01282 'go' => wikiFuzz::makeFuzz( 2 ) 01283 ); 01284 } 01285 } 01286 01287 01291 class pageHistoryTest extends pageTest { 01292 function __construct() { 01293 $this->pagePath = "index.php?title=Main_Page&action=history"; 01294 01295 $this->params = array ( 01296 'limit' => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01297 'offset' => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ), 01298 "go" => wikiFuzz::chooseInput( array( "first", "last", wikiFuzz::makeFuzz( 2 ) ) ), 01299 "dir" => wikiFuzz::chooseInput( array( "prev", "next", wikiFuzz::makeFuzz( 2 ) ) ), 01300 "diff" => wikiFuzz::chooseInput( array( "-1", "--------'-----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01301 "oldid" => wikiFuzz::chooseInput( array( "prev", "-1", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01302 "feed" => wikiFuzz::makeFuzz( 2 ) 01303 ); 01304 } 01305 } 01306 01307 01311 class contributionsTest extends pageTest { 01312 function __construct() { 01313 $this->pagePath = "index.php?title=Special:Contributions/" . USER_ON_WIKI; 01314 01315 $this->params = array ( 01316 'target' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "newbies", USER_ON_WIKI ) ), 01317 'namespace' => wikiFuzz::chooseInput( array( -1, 15, 1, wikiFuzz::makeFuzz( 2 ) ) ), 01318 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "982342131232131231241", wikiFuzz::makeFuzz( 2 ) ) ), 01319 'bot' => wikiFuzz::chooseInput( array( "", "-1", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ), 01320 'go' => wikiFuzz::chooseInput( array( "-1", 'prev', 'next', wikiFuzz::makeFuzz( 2 ) ) ) 01321 ); 01322 } 01323 } 01324 01325 01329 class viewPageTest extends pageTest { 01330 function __construct() { 01331 $this->pagePath = "index.php?title=Main_Page"; 01332 01333 $this->params = array ( 01334 "useskin" => wikiFuzz::chooseInput( array( "chick", "cologneblue", "myskin", 01335 "nostalgia", "simple", "standard", wikiFuzz::makeFuzz( 2 ) ) ), 01336 "uselang" => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), 01337 "ab", "af", "an", "ar", "arc", "as", "ast", "av", "ay", "az", "ba", 01338 "bat-smg", "be", "bg", "bm", "bn", "bo", "bpy", "br", "bs", "ca", 01339 "ce", "cs", "csb", "cv", "cy", "da", "de", "dv", "dz", "el", "en", 01340 "eo", "es", "et", "eu", "fa", "fi", "fo", "fr", "fur", "fy", "ga", 01341 "gn", "gsw", "gu", "he", "hi", "hr", "hu", "ia", "id", "ii", "is", 01342 "it", "ja", "jv", "ka", "km", "kn", "ko", "ks", "ku", "kv", "la", 01343 "li", "lo", "lt", "lv", "mk", "ml", "ms", "nah", "nap", "nds", 01344 "nds-nl", "nl", "nn", "no", "non", "nv", "oc", "or", "os", "pa", 01345 "pl", "pms", "ps", "pt", "pt-br", "qu", "rmy", "ro", "ru", "sc", 01346 "sd", "sk", "sl", "sq", "sr", "sr-ec", "sr-el", 01347 "su", "sv", "ta", "te", "th", "tr", "tt", "ty", "tyv", "udm", 01348 "ug", "uk", "ur", "utf8", "vec", "vi", "wa", "xal", "yi", "za", 01349 "zh", "zh-cn", "zh-hk", "zh-sg", "zh-tw", "zh-tw" ) ), 01350 "returnto" => wikiFuzz::makeFuzz( 2 ), 01351 "feed" => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ), 01352 "rcid" => wikiFuzz::makeFuzz( 2 ), 01353 "action" => wikiFuzz::chooseInput( array( "view", "raw", "render", wikiFuzz::makeFuzz( 2 ), "markpatrolled" ) ), 01354 "printable" => wikiFuzz::makeFuzz( 2 ), 01355 "oldid" => wikiFuzz::makeFuzz( 2 ), 01356 "redirect" => wikiFuzz::makeFuzz( 2 ), 01357 "diff" => wikiFuzz::makeFuzz( 2 ), 01358 "search" => wikiFuzz::makeFuzz( 2 ), 01359 "rdfrom" => wikiFuzz::makeFuzz( 2 ), // things from Article.php from here on: 01360 "token" => wikiFuzz::makeFuzz( 2 ), 01361 "tbid" => wikiFuzz::makeFuzz( 2 ), 01362 // @todo FIXME: Duplicate array key. 01363 "action" => wikiFuzz::chooseInput( array( "purge", wikiFuzz::makeFuzz( 2 ) ) ), 01364 "wpReason" => wikiFuzz::makeFuzz( 2 ), 01365 "wpEditToken" => wikiFuzz::makeFuzz( 2 ), 01366 "from" => wikiFuzz::makeFuzz( 2 ), 01367 "bot" => wikiFuzz::makeFuzz( 2 ), 01368 "summary" => wikiFuzz::makeFuzz( 2 ), 01369 "direction" => wikiFuzz::chooseInput( array( "next", "prev", wikiFuzz::makeFuzz( 2 ) ) ), 01370 "section" => wikiFuzz::makeFuzz( 2 ), 01371 "preload" => wikiFuzz::makeFuzz( 2 ), 01372 01373 ); 01374 01375 // Tidy does not know how to valid atom or rss, so exclude from testing for the time being. 01376 if ( $this->params["feed"] == "atom" ) { unset( $this->params["feed"] ); } 01377 elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); } 01378 01379 // Raw pages cannot really be validated 01380 if ( $this->params["action"] == "raw" ) unset( $this->params["action"] ); 01381 01382 // sometimes we don't want to specify certain parameters. 01383 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rcid"] ); 01384 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["diff"] ); 01385 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rdfrom"] ); 01386 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["oldid"] ); 01387 01388 // usually don't want action == purge. 01389 if ( wikiFuzz::randnum( 6 ) > 1 ) unset( $this->params["action"] ); 01390 } 01391 } 01392 01393 01397 class specialAllmessagesTest extends pageTest { 01398 function __construct() { 01399 $this->pagePath = "index.php?title=Special:Allmessages"; 01400 01401 // only really has one parameter 01402 $this->params = array ( 01403 "ot" => wikiFuzz::chooseInput( array( "php", "html", wikiFuzz::makeFuzz( 2 ) ) ) 01404 ); 01405 } 01406 } 01407 01411 class specialNewpagesPageTest extends pageTest { 01412 function __construct() { 01413 $this->pagePath = "index.php?title=Special:Newpages"; 01414 01415 $this->params = array ( 01416 "namespace" => wikiFuzz::chooseInput( range( -1, 15 ) ), 01417 "feed" => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ), 01418 'limit' => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ), 01419 'offset' => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ) 01420 ); 01421 01422 // Tidy does not know how to valid atom or rss, so exclude from testing for the time being. 01423 if ( $this->params["feed"] == "atom" ) { unset( $this->params["feed"] ); } 01424 elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); } 01425 } 01426 } 01427 01431 class redirectTest extends pageTest { 01432 function __construct() { 01433 $this->pagePath = "redirect.php"; 01434 01435 $this->params = array ( 01436 "wpDropdown" => wikiFuzz::makeFuzz( 2 ) 01437 ); 01438 01439 // sometimes we don't want to specify certain parameters. 01440 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpDropdown"] ); 01441 } 01442 } 01443 01444 01448 class confirmEmail extends pageTest { 01449 function __construct() { 01450 // sometimes we send a bogus confirmation code, and sometimes we don't. 01451 $this->pagePath = "index.php?title=Special:Confirmemail" . wikiFuzz::chooseInput( array( "", "/" . wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 1 ) ) ) ); 01452 01453 $this->params = array ( 01454 "token" => wikiFuzz::makeFuzz( 2 ) 01455 ); 01456 } 01457 } 01458 01459 01464 class watchlistTest extends pageTest { 01465 function __construct() { 01466 $this->pagePath = "index.php?title=Special:Watchlist"; 01467 01468 $this->params = array ( 01469 "remove" => wikiFuzz::chooseInput( array( "Remove checked items from watchlist", wikiFuzz::makeFuzz( 2 ) ) ), 01470 'days' => wikiFuzz::chooseInput( array( 0, -1, -230, "--", 3, 9, wikiFuzz::makeFuzz( 2 ) ) ), 01471 'hideOwn' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ), 01472 'hideBots' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ), 01473 'namespace' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ), 01474 'action' => wikiFuzz::chooseInput( array( "submit", "clear", wikiFuzz::makeFuzz( 2 ) ) ), 01475 'id[]' => wikiFuzz::makeFuzz( 2 ), 01476 'edit' => wikiFuzz::makeFuzz( 2 ), 01477 'token' => wikiFuzz::chooseInput( array( "", "1243213", wikiFuzz::makeFuzz( 2 ) ) ) 01478 ); 01479 01480 // sometimes we specifiy "reset", and sometimes we don't. 01481 if ( wikiFuzz::randnum( 3 ) == 0 ) $this->params["reset"] = wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ); 01482 } 01483 } 01484 01488 class specialMovePage extends pageTest { 01489 function __construct() { 01490 $this->pagePath = "index.php?title=Special:Movepage"; 01491 01492 $this->params = array ( 01493 "action" => wikiFuzz::chooseInput( array( "success", "submit", "", wikiFuzz::makeFuzz( 2 ) ) ), 01494 'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ), 01495 'target' => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ), 01496 'wpOldTitle' => wikiFuzz::chooseInput( array( "z", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ), 01497 'wpNewTitle' => wikiFuzz::chooseInput( array( "y", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ), 01498 'wpReason' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ) ) ), 01499 'wpMovetalk' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01500 'wpDeleteAndMove' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01501 'wpConfirm' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01502 'talkmoved' => wikiFuzz::chooseInput( array( "1", wikiFuzz::makeFuzz( 2 ), "articleexists", 'notalkpage' ) ), 01503 'oldtitle' => wikiFuzz::makeFuzz( 2 ), 01504 'newtitle' => wikiFuzz::makeFuzz( 2 ), 01505 'wpMovetalk' => wikiFuzz::chooseInput( array( "1", "0", wikiFuzz::makeFuzz( 2 ) ) ) 01506 ); 01507 01508 // sometimes we don't want to specify certain parameters. 01509 if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] ); 01510 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] ); 01511 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpNewTitle"] ); 01512 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpReason"] ); 01513 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpOldTitle"] ); 01514 } 01515 } 01516 01517 01521 class specialUndeletePageTest extends pageTest { 01522 function __construct() { 01523 $this->pagePath = "index.php?title=Special:Undelete"; 01524 01525 $this->params = array ( 01526 "action" => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ), 01527 'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ), 01528 'target' => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ), 01529 'timestamp' => wikiFuzz::chooseInput( array( "125223", wikiFuzz::makeFuzz( 2 ) ) ), 01530 'file' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01531 'restore' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ), 01532 'preview' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ), 01533 'wpComment' => wikiFuzz::makeFuzz( 2 ) 01534 ); 01535 01536 // sometimes we don't want to specify certain parameters. 01537 if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] ); 01538 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["target"] ); 01539 if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["restore"] ); 01540 if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["preview"] ); 01541 } 01542 } 01543 01544 01548 class specialUnlockdbPageTest extends pageTest { 01549 function __construct() { 01550 $this->pagePath = "index.php?title=Special:Unlockdb"; 01551 01552 $this->params = array ( 01553 "action" => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ), 01554 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01555 'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ) 01556 ); 01557 01558 // sometimes we don't want to specify certain parameters. 01559 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] ); 01560 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] ); 01561 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] ); 01562 } 01563 } 01564 01565 01569 class specialLockdbPageTest extends pageTest { 01570 function __construct() { 01571 $this->pagePath = "index.php?title=Special:Lockdb"; 01572 01573 $this->params = array ( 01574 "action" => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ), 01575 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01576 'wpLockReason' => wikiFuzz::makeFuzz( 2 ), 01577 'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ) 01578 ); 01579 01580 // sometimes we don't want to specify certain parameters. 01581 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] ); 01582 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] ); 01583 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] ); 01584 } 01585 } 01586 01587 01591 class specialUserrights extends pageTest { 01592 function __construct() { 01593 $this->pagePath = "index.php?title=Special:Userrights"; 01594 01595 $this->params = array ( 01596 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01597 'user-editname' => wikiFuzz::chooseInput( array( "Nickj2", "Nickj2\n<xyz>", wikiFuzz::makeFuzz( 2 ) ) ), 01598 'ssearchuser' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01599 'saveusergroups' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ), "Save User Groups" ), 01600 'member[]' => wikiFuzz::chooseInput( array( "0", "bot", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01601 "available[]" => wikiFuzz::chooseInput( array( "0", "sysop", "bureaucrat", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ) 01602 ); 01603 01604 // sometimes we don't want to specify certain parameters. 01605 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['ssearchuser'] ); 01606 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['saveusergroups'] ); 01607 } 01608 } 01609 01610 01614 class pageProtectionForm extends pageTest { 01615 function __construct() { 01616 $this->pagePath = "index.php?title=Main_Page"; 01617 01618 $this->params = array ( 01619 "action" => "protect", 01620 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01621 "mwProtect-level-edit" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ), 01622 "mwProtect-level-move" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ), 01623 "mwProtectUnchained" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01624 'mwProtect-reason' => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) ) 01625 ); 01626 01627 01628 // sometimes we don't want to specify certain parameters. 01629 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["mwProtectUnchained"] ); 01630 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['mwProtect-reason'] ); 01631 } 01632 } 01633 01634 01638 class specialBlockip extends pageTest { 01639 function __construct() { 01640 $this->pagePath = "index.php?title=Special:Blockip"; 01641 01642 $this->params = array ( 01643 "action" => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ), 01644 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01645 "wpBlockAddress" => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ), 01646 // something like an IP address, sometimes invalid: 01647 ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "." 01648 . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ), 01649 "ip" => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ), 01650 // something like an IP address, sometimes invalid: 01651 ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "." 01652 . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ), 01653 "wpBlockOther" => wikiFuzz::chooseInput( array( '', 'Nickj2', wikiFuzz::makeFuzz( 2 ) ) ), 01654 "wpBlockExpiry" => wikiFuzz::chooseInput( array( "other", "2 hours", "1 day", "3 days", "1 week", "2 weeks", 01655 "1 month", "3 months", "6 months", "1 year", "infinite", wikiFuzz::makeFuzz( 2 ) ) ), 01656 "wpBlockReason" => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) ), 01657 "wpAnonOnly" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01658 "wpCreateAccount" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01659 "wpBlock" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ) 01660 ); 01661 01662 // sometimes we don't want to specify certain parameters. 01663 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockOther"] ); 01664 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockExpiry"] ); 01665 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockReason"] ); 01666 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpAnonOnly"] ); 01667 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpCreateAccount"] ); 01668 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockAddress"] ); 01669 if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["ip"] ); 01670 } 01671 } 01672 01673 01677 class imagepageTest extends pageTest { 01678 function __construct() { 01679 $this->pagePath = "index.php?title=Image:Small-email.png"; 01680 01681 $this->params = array ( 01682 "image" => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ), 01683 "wpReason" => wikiFuzz::makeFuzz( 2 ), 01684 "oldimage" => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ), 01685 "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01686 ); 01687 01688 // sometimes we don't want to specify certain parameters. 01689 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["image"] ); 01690 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] ); 01691 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldimage"] ); 01692 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEditToken"] ); 01693 } 01694 } 01695 01696 01700 class pageDeletion extends pageTest { 01701 function __construct() { 01702 $this->pagePath = "index.php?title=Main_Page&action=delete"; 01703 01704 $this->params = array ( 01705 "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01706 "wpReason" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01707 "wpConfirm" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01708 ); 01709 01710 // sometimes we don't want to specify certain parameters. 01711 if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpReason"] ); 01712 if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpEditToken"] ); 01713 if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpConfirm"] ); 01714 } 01715 } 01716 01717 01718 01722 class specialRevisionDeletePageTest extends pageTest { 01723 function __construct() { 01724 $this->pagePath = "index.php?title=Special:Revisiondelete"; 01725 01726 $this->params = array ( 01727 "target" => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ), 01728 "oldid" => wikiFuzz::makeFuzz( 2 ), 01729 "oldid[]" => wikiFuzz::makeFuzz( 2 ), 01730 "wpReason" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01731 "revdelete-hide-text" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01732 "revdelete-hide-comment" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01733 "revdelete-hide-user" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01734 "revdelete-hide-restricted" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01735 ); 01736 01737 // sometimes we don't want to specify certain parameters. 01738 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] ); 01739 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid"] ); 01740 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid[]"] ); 01741 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] ); 01742 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-text"] ); 01743 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-comment"] ); 01744 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-user"] ); 01745 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-restricted"] ); 01746 } 01747 } 01748 01749 01753 class specialImportPageTest extends pageTest { 01754 function __construct() { 01755 $this->pagePath = "index.php?title=Special:Import"; 01756 01757 $this->params = array ( 01758 "action" => "submit", 01759 "source" => wikiFuzz::chooseInput( array( "upload", "interwiki", wikiFuzz::makeFuzz( 2 ) ) ), 01760 "MAX_FILE_SIZE" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01761 "xmlimport" => wikiFuzz::chooseInput( array( "/var/www/hosts/mediawiki/wiki/AdminSettings.php", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ), 01762 "namespace" => wikiFuzz::chooseInput( array( wikiFuzz::randnum( 30, -6 ), wikiFuzz::makeFuzz( 2 ) ) ), 01763 "interwiki" => wikiFuzz::makeFuzz( 2 ), 01764 "interwikiHistory" => wikiFuzz::makeFuzz( 2 ), 01765 "frompage" => wikiFuzz::makeFuzz( 2 ), 01766 ); 01767 01768 // sometimes we don't want to specify certain parameters. 01769 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["action"] ); 01770 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["source"] ); 01771 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["MAX_FILE_SIZE"] ); 01772 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["xmlimport"] ); 01773 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwiki"] ); 01774 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwikiHistory"] ); 01775 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["frompage"] ); 01776 01777 // Note: Need to do a file upload to fully test this Special page. 01778 } 01779 } 01780 01781 01785 class thumbTest extends pageTest { 01786 function __construct() { 01787 $this->pagePath = "thumb.php"; 01788 01789 $this->params = array ( 01790 "f" => wikiFuzz::chooseInput( array( "..", "\\", "small-email.png", wikiFuzz::makeFuzz( 2 ) ) ), 01791 "w" => wikiFuzz::chooseInput( array( "80", wikiFuzz::randnum( 6000, -200 ), wikiFuzz::makeFuzz( 2 ) ) ), 01792 "r" => wikiFuzz::chooseInput( array( "0", wikiFuzz::makeFuzz( 2 ) ) ), 01793 ); 01794 01795 // sometimes we don't want to specify certain parameters. 01796 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["f"] ); 01797 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["w"] ); 01798 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["r"] ); 01799 } 01800 } 01801 01805 class profileInfo extends pageTest { 01806 function __construct() { 01807 $this->pagePath = "profileinfo.php"; 01808 01809 $this->params = array ( 01810 "expand" => wikiFuzz::makeFuzz( 2 ), 01811 "sort" => wikiFuzz::chooseInput( array( "time", "count", "name", wikiFuzz::makeFuzz( 2 ) ) ), 01812 "filter" => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ), 01813 ); 01814 01815 // sometimes we don't want to specify certain parameters. 01816 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["sort"] ); 01817 if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["filter"] ); 01818 } 01819 } 01820 01821 01825 class specialCitePageTest extends pageTest { 01826 function __construct() { 01827 $this->pagePath = "index.php?title=Special:Cite"; 01828 01829 $this->params = array ( 01830 "page" => wikiFuzz::chooseInput( array( "\" onmouseover=\"alert(1);\"", "Main Page", wikiFuzz::makeFuzz( 2 ) ) ), 01831 "id" => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "-9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ), 01832 ); 01833 01834 // sometimes we don't want to specify certain parameters. 01835 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["page"] ); 01836 if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["id"] ); 01837 } 01838 } 01839 01840 01844 class specialFilepathPageTest extends pageTest { 01845 function __construct() { 01846 $this->pagePath = "index.php?title=Special:Filepath"; 01847 01848 $this->params = array ( 01849 "file" => wikiFuzz::chooseInput( array( "Small-email.png", "Small-email.png" . wikiFuzz::makeFuzz( 1 ), wikiFuzz::makeFuzz( 2 ) ) ), 01850 ); 01851 } 01852 } 01853 01854 01858 class specialRenameuserPageTest extends pageTest { 01859 function __construct() { 01860 $this->pagePath = "index.php?title=Special:Renameuser"; 01861 01862 $this->params = array ( 01863 "oldusername" => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ), 01864 "newusername" => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ), 01865 "token" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ), 01866 ); 01867 } 01868 } 01869 01870 01874 class specialLinksearch extends pageTest { 01875 function __construct() { 01876 $this->pagePath = "index.php?title=Special%3ALinksearch"; 01877 01878 $this->params = array ( 01879 "target" => wikiFuzz::makeFuzz( 2 ), 01880 ); 01881 01882 // sometimes we don't want to specify certain parameters. 01883 if ( wikiFuzz::randnum( 10 ) == 0 ) unset( $this->params["target"] ); 01884 } 01885 } 01886 01887 01891 class specialCategoryTree extends pageTest { 01892 function __construct() { 01893 $this->pagePath = "index.php?title=Special:CategoryTree"; 01894 01895 $this->params = array ( 01896 "target" => wikiFuzz::makeFuzz( 2 ), 01897 "from" => wikiFuzz::makeFuzz( 2 ), 01898 "until" => wikiFuzz::makeFuzz( 2 ), 01899 "showas" => wikiFuzz::makeFuzz( 2 ), 01900 "mode" => wikiFuzz::chooseInput( array( "pages", "categories", "all", wikiFuzz::makeFuzz( 2 ) ) ), 01901 ); 01902 01903 // sometimes we do want to specify certain parameters. 01904 if ( wikiFuzz::randnum( 5 ) == 0 ) $this->params["notree"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) ); 01905 } 01906 } 01907 01908 01912 class specialChemicalsourcesTest extends pageTest { 01913 function __construct() { 01914 $this->pagePath = "index.php?title=Special:Chemicalsources"; 01915 01916 // choose an input format to use. 01917 $format = wikiFuzz::chooseInput( 01918 array( 'go', 01919 'CAS', 01920 'EINECS', 01921 'CHEBI', 01922 'PubChem', 01923 'SMILES', 01924 'InChI', 01925 'ATCCode', 01926 'KEGG', 01927 'RTECS', 01928 'ECNumber', 01929 'DrugBank', 01930 'Formula', 01931 'Name' 01932 ) 01933 ); 01934 01935 // values for different formats usually start with either letters or numbers. 01936 switch ( $format ) { 01937 case 'Name' : $value = "A"; break; 01938 case 'InChI' : 01939 case 'SMILES' : 01940 case 'Formula': $value = "C"; break; 01941 default : $value = "0"; break; 01942 } 01943 01944 // and then we append the fuzz input. 01945 $this->params = array ( $format => $value . wikiFuzz::makeFuzz( 2 ) ); 01946 } 01947 } 01948 01949 01959 class api extends pageTest { 01960 01961 // API login mode. 01962 private static function loginMode() { 01963 $arr = array ( "lgname" => wikiFuzz::makeFuzz( 2 ), 01964 "lgpassword" => wikiFuzz::makeFuzz( 2 ), 01965 ); 01966 // sometimes we want to specify the extra "lgdomain" parameter. 01967 if ( wikiFuzz::randnum( 3 ) == 0 ) { 01968 $arr["lgdomain"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) ); 01969 } 01970 01971 return $arr; 01972 } 01973 01974 // API OpenSearch mode. 01975 private static function opensearchMode() { 01976 return array ( "search" => wikiFuzz::makeFuzz( 2 ) ); 01977 } 01978 01979 // API watchlist feed mode. 01980 private static function feedwatchlistMode() { 01981 // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible value below? 01982 return array ( "feedformat" => wikiFuzz::chooseInput( array( "rss", "atom" ) ) ); 01983 } 01984 01985 // API query mode. 01986 private static function queryMode() { 01987 // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible params for the elements below? 01988 // Suspect this will stuff up the tests more, but need to check. 01989 $params = array ( 01990 // @todo FIXME: More titles. 01991 "titles" => wikiFuzz::chooseInput( array( "Main Page" ) ), 01992 // @todo FIXME: More pageids. 01993 "pageids" => 1, 01994 "prop" => wikiFuzz::chooseInput( array( "info", "revisions", "watchlist" ) ), 01995 "list" => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "usercontribs", "recentchanges", "backlinks", "embeddedin", "imagelinks" ) ), 01996 "meta" => wikiFuzz::chooseInput( array( "siteinfo" ) ), 01997 "generator" => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "info", "revisions" ) ), 01998 "siprop" => wikiFuzz::chooseInput( array( "general", "namespaces", "general|namespaces" ) ), 01999 ); 02000 02001 // Add extra parameters based on what list choice we got. 02002 switch ( $params["list"] ) { 02003 case "usercontribs" : self::addListParams ( $params, "uc", array( "limit", "start", "end", "user", "dir" ) ); break; 02004 case "allpages" : self::addListParams ( $params, "ap", array( "from", "prefix", "namespace", "filterredir", "limit" ) ); break; 02005 case "watchlist" : self::addListParams ( $params, "wl", array( "allrev", "start", "end", "namespace", "dir", "limit", "prop" ) ); break; 02006 case "logevents" : self::addListParams ( $params, "le", array( "limit", "type", "start", "end", "user", "dir" ) ); break; 02007 case "recentchanges": self::addListParams ( $params, "rc", array( "limit", "prop", "show", "namespace", "start", "end", "dir" ) ); break; 02008 case "backlinks" : self::addListParams ( $params, "bl", array( "continue", "namespace", "redirect", "limit" ) ); break; 02009 case "embeddedin" : self::addListParams ( $params, "ei", array( "continue", "namespace", "redirect", "limit" ) ); break; 02010 case "imagelinks" : self::addListParams ( $params, "il", array( "continue", "namespace", "redirect", "limit" ) ); break; 02011 } 02012 02013 if ( $params["prop"] == "revisions" ) { 02014 self::addListParams ( $params, "rv", array( "prop", "limit", "startid", "endid", "end", "dir" ) ); 02015 } 02016 02017 // Sometimes we want redirects, sometimes we don't. 02018 if ( wikiFuzz::randnum( 3 ) == 0 ) { 02019 $params["redirects"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) ); 02020 } 02021 02022 return $params; 02023 } 02024 02025 // Adds all the elements to the array, using the specified prefix. 02026 private static function addListParams( &$array, $prefix, $elements ) { 02027 foreach ( $elements as $element ) { 02028 $array[$prefix . $element] = self::getParamDetails( $element ); 02029 } 02030 } 02031 02032 // For a given element name, returns the data for that element. 02033 private static function getParamDetails( $element ) { 02034 switch ( $element ) { 02035 case 'startid' : 02036 case 'endid' : 02037 case 'start' : 02038 case 'end' : 02039 case 'limit' : return wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", "320742734234235", "20060230121212", wikiFuzz::randnum( 9000, -100 ), wikiFuzz::makeFuzz( 2 ) ) ); 02040 case 'dir' : return wikiFuzz::chooseInput( array( "newer", "older", wikiFuzz::makeFuzz( 2 ) ) ); 02041 case 'user' : return wikiFuzz::chooseInput( array( USER_ON_WIKI, wikiFuzz::makeFuzz( 2 ) ) ); 02042 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 ) ) ); 02043 case 'filterredir': return wikiFuzz::chooseInput( array( "all", "redirects", "nonredirectsallpages", wikiFuzz::makeFuzz( 2 ) ) ); 02044 case 'allrev' : return wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) ); 02045 case 'prop' : return wikiFuzz::chooseInput( array( "user", "comment", "timestamp", "patrol", "flags", "user|user|comment|flags", wikiFuzz::makeFuzz( 2 ) ) ); 02046 case 'type' : return wikiFuzz::chooseInput( array( "block", "protect", "rights", "delete", "upload", "move", "import", "renameuser", "newusers", "makebot", wikiFuzz::makeFuzz( 2 ) ) ); 02047 case 'hide' : return wikiFuzz::chooseInput( array( "minor", "bots", "anons", "liu", "liu|bots|", wikiFuzz::makeFuzz( 2 ) ) ); 02048 case 'show' : return wikiFuzz::chooseInput( array( 'minor', '!minor', 'bot', '!bot', 'anon', '!anon', wikiFuzz::makeFuzz( 2 ) ) ); 02049 default : return wikiFuzz::makeFuzz( 2 ); 02050 } 02051 } 02052 02053 // Entry point. 02054 function __construct() { 02055 $this->pagePath = "api.php"; 02056 02057 $modes = array ( "help", 02058 "login", 02059 "opensearch", 02060 "feedwatchlist", 02061 "query" ); 02062 $action = wikiFuzz::chooseInput( array_merge ( $modes, array( wikiFuzz::makeFuzz( 2 ) ) ) ); 02063 02064 switch ( $action ) { 02065 case "login" : $this->params = self::loginMode(); 02066 break; 02067 case "opensearch" : $this->params = self::opensearchMode(); 02068 break; 02069 case "feedwatchlist" : $this->params = self::feedwatchlistMode(); 02070 break; 02071 case "query" : $this->params = self::queryMode(); 02072 break; 02073 case "help" : 02074 default : // Do something random - "Crazy Ivan" mode. 02075 $random_mode = wikiFuzz::chooseInput( $modes ) . "Mode"; 02076 // There is no "helpMode". 02077 if ( $random_mode == "helpMode" ) $random_mode = "queryMode"; 02078 $this->params = self::$random_mode(); 02079 break; 02080 } 02081 02082 // Save the selected action. 02083 $this->params["action"] = $action; 02084 02085 // Set the cookie: 02086 // @todo FIXME: Need to get this cookie dynamically set, rather than hard-coded. 02087 $this->cookie = "wikidbUserID=10001; wikidbUserName=Test; wikidb_session=178df0fe68c75834643af65dec9ec98a; wikidbToken=1adc6753d62c44aec950c024d7ae0540"; 02088 02089 // Output format 02090 $this->params["format"] = wikiFuzz::chooseInput( array( "json", "jsonfm", "php", "phpfm", 02091 "wddx", "wddxfm", "xml", "xmlfm", 02092 "yaml", "yamlfm", "raw", "rawfm", 02093 wikiFuzz::makeFuzz( 2 ) ) ); 02094 02095 // Page does not produce HTML (sometimes). 02096 $this->tidyValidate = false; 02097 } 02098 } 02099 02100 02104 class GeSHi_Test extends pageTest { 02105 02106 private function getGeSHiContent() { 02107 return "<source lang=\"" . $this->getLang() . "\" " 02108 . ( wikiFuzz::randnum( 2 ) == 0 ? "line " : "" ) 02109 . ( wikiFuzz::randnum( 2 ) == 0 ? "strict " : "" ) 02110 . "start=" . wikiFuzz::chooseInput( array( wikiFuzz::randnum( 6000, -6000 ), wikiFuzz::makeFuzz( 2 ) ) ) 02111 . ">" 02112 . wikiFuzz::makeFuzz( 2 ) 02113 . "</source>"; 02114 } 02115 02116 private function getLang() { 02117 return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp", 02118 "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl", 02119 "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas", 02120 "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty", 02121 "sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikiFuzz::makeFuzz( 1 ) ) ); 02122 } 02123 02124 function __construct() { 02125 $this->pagePath = "index.php?title=WIKIFUZZ"; 02126 02127 $this->params = array ( 02128 "action" => "submit", 02129 "wpMinoredit" => "test", 02130 "wpPreview" => "test", 02131 "wpSection" => "test", 02132 "wpEdittime" => "test", 02133 "wpSummary" => "test", 02134 "wpScrolltop" => "test", 02135 "wpStarttime" => "test", 02136 "wpAutoSummary" => "test", 02137 "wpTextbox1" => $this->getGeSHiContent() // the main wiki text, contains fake GeSHi content. 02138 ); 02139 } 02140 } 02141 02147 function selectPageTest( $count ) { 02148 02149 // if the user only wants a specific test, then only ever give them that. 02150 if ( defined( "SPECIFIC_TEST" ) ) { 02151 $testType = SPECIFIC_TEST; 02152 return new $testType (); 02153 } 02154 02155 // Some of the time we test Special pages, the remaining 02156 // time we test using the standard edit page. 02157 switch ( $count % 100 ) { 02158 case 0 : return new successfulUserLoginTest(); 02159 case 1 : return new listusersTest(); 02160 case 2 : return new searchTest(); 02161 case 3 : return new recentchangesTest(); 02162 case 4 : return new prefixindexTest(); 02163 case 5 : return new mimeSearchTest(); 02164 case 6 : return new specialLogTest(); 02165 case 7 : return new userLoginTest(); 02166 case 8 : return new ipblocklistTest(); 02167 case 9 : return new newImagesTest(); 02168 case 10: return new imagelistTest(); 02169 case 11: return new specialExportTest(); 02170 case 12: return new specialBooksourcesTest(); 02171 case 13: return new specialAllpagesTest(); 02172 case 14: return new pageHistoryTest(); 02173 case 15: return new contributionsTest(); 02174 case 16: return new viewPageTest(); 02175 case 17: return new specialAllmessagesTest(); 02176 case 18: return new specialNewpagesPageTest(); 02177 case 19: return new searchTest(); 02178 case 20: return new redirectTest(); 02179 case 21: return new confirmEmail(); 02180 case 22: return new watchlistTest(); 02181 case 24: return new specialUndeletePageTest(); 02182 case 25: return new specialMovePage(); 02183 case 26: return new specialUnlockdbPageTest(); 02184 case 27: return new specialLockdbPageTest(); 02185 case 28: return new specialUserrights(); 02186 case 29: return new pageProtectionForm(); 02187 case 30: return new specialBlockip(); 02188 case 31: return new imagepageTest(); 02189 case 32: return new pageDeletion(); 02190 case 33: return new specialRevisionDeletePageTest(); 02191 case 34: return new specialImportPageTest(); 02192 case 35: return new thumbTest(); 02193 case 37: return new profileInfo(); 02194 case 38: return new specialCitePageTest(); 02195 case 39: return new specialFilepathPageTest(); 02196 case 40: return new specialRenameuserPageTest(); 02197 case 41: return new specialLinksearch(); 02198 case 42: return new specialCategoryTree(); 02199 case 43: return new api(); 02200 case 44: return new specialChemicalsourcesTest(); 02201 default: return new editPageTest(); 02202 } 02203 } 02204 02205 02206 // ///////////////////// SAVING OUTPUT ///////////////////////// 02207 02211 function saveFile( $data, $name ) { 02212 file_put_contents( $name, $data ); 02213 } 02214 02222 function getAsURL( pageTest $test ) { 02223 $used_question_mark = ( strpos( $test->getPagePath(), "?" ) !== false ); 02224 $retval = "http://get-to-post.nickj.org/?" . WIKI_BASE_URL . $test->getPagePath(); 02225 foreach ( $test->getParams() as $param => $value ) { 02226 if ( !$used_question_mark ) { 02227 $retval .= "?"; 02228 $used_question_mark = true; 02229 } 02230 else { 02231 $retval .= "&"; 02232 } 02233 $retval .= $param . "=" . urlencode( $value ); 02234 } 02235 return $retval; 02236 } 02237 02238 02242 function saveTestAsText( pageTest $test, $filename ) { 02243 $str = "Test: " . $test->getPagePath(); 02244 foreach ( $test->getParams() as $param => $value ) { 02245 $str .= "\n$param: $value"; 02246 } 02247 $str .= "\nGet-to-post URL: " . getAsURL( $test ) . "\n"; 02248 saveFile( $str, $filename ); 02249 } 02250 02251 02256 function saveTestAsPHP( pageTest $test, $filename ) { 02257 $str = "<?php\n" 02258 . "\$params = " . var_export( escapeForCurl( $test->getParams() ), true ) . ";\n" 02259 . "\$ch = curl_init();\n" 02260 . "curl_setopt(\$ch, CURLOPT_POST, 1);\n" 02261 . "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \$params );\n" 02262 . "curl_setopt(\$ch, CURLOPT_URL, " . var_export( WIKI_BASE_URL . $test->getPagePath(), true ) . ");\n" 02263 . "curl_setopt(\$ch, CURLOPT_RETURNTRANSFER,1);\n" 02264 . ( $test->getCookie() ? "curl_setopt(\$ch, CURLOPT_COOKIE, " . var_export( $test->getCookie(), true ) . ");\n" : "" ) 02265 . "\$result=curl_exec(\$ch);\n" 02266 . "curl_close (\$ch);\n" 02267 . "print \$result;\n" 02268 . "\n"; 02269 saveFile( $str, $filename ); 02270 } 02271 02279 function escapeForCurl( array $input_params ) { 02280 $output_params = array(); 02281 foreach ( $input_params as $param => $value ) { 02282 if ( strlen( $value ) > 0 && ( $value[0] == "@" || $value[0] == "<" ) ) { 02283 $value = "\\" . $value; 02284 } 02285 $output_params[$param] = $value; 02286 } 02287 return $output_params; 02288 } 02289 02290 02295 function saveTestAsCurl( pageTest $test, $filename ) { 02296 $str = "#!/bin/bash\n" 02297 . "curl --silent --include --globoff \\\n" 02298 . ( $test->getCookie() ? " --cookie " . escapeshellarg( $test->getCookie() ) . " \\\n" : "" ); 02299 foreach ( escapeForCurl( $test->getParams() ) as $param => $value ) { 02300 $str .= " -F " . escapeshellarg( $param ) . "=" . escapeshellarg( $value ) . " \\\n"; 02301 } 02302 $str .= " " . escapeshellarg( WIKI_BASE_URL . $test->getPagePath() ); // beginning space matters. 02303 $str .= "\n"; 02304 saveFile( $str, $filename ); 02305 chmod( $filename, 0755 ); // make executable 02306 } 02307 02308 02312 function saveTestData ( pageTest $test, $filename ) { 02313 saveFile( serialize( $test ), $filename ); 02314 } 02315 02316 02320 function saveTest( pageTest $test, $testname ) { 02321 $base_name = DIRECTORY . "/" . $testname; 02322 saveTestAsText( $test, $base_name . INFO_FILE ); 02323 saveTestAsPHP ( $test, $base_name . PHP_TEST ); 02324 saveTestAsCurl( $test, $base_name . CURL_TEST ); 02325 saveTestData ( $test, $base_name . DATA_FILE ); 02326 } 02327 02328 // ////////////////// MEDIAWIKI OUTPUT ///////////////////////// 02329 02335 function wikiTestOutput( pageTest $test ) { 02336 02337 $ch = curl_init(); 02338 02339 // specify the cookie, if required. 02340 if ( $test->getCookie() ) { 02341 curl_setopt( $ch, CURLOPT_COOKIE, $test->getCookie() ); 02342 } 02343 curl_setopt( $ch, CURLOPT_POST, 1 ); // save form using a POST 02344 02345 $params = escapeForCurl( $test->getParams() ); 02346 curl_setopt( $ch, CURLOPT_POSTFIELDS, $params ); // load the POST variables 02347 02348 curl_setopt( $ch, CURLOPT_URL, WIKI_BASE_URL . $test->getPagePath() ); // set url to post to 02349 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); // return into a variable 02350 02351 $result = curl_exec ( $ch ); 02352 02353 // if we encountered an error, then say so, and return an empty string. 02354 if ( curl_error( $ch ) ) { 02355 print "\nCurl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ); 02356 $result = ""; 02357 } 02358 02359 curl_close ( $ch ); 02360 02361 return $result; 02362 } 02363 02364 02365 // ////////////////// HTML VALIDATION ///////////////////////// 02366 02372 function validateHTML( $text ) { 02373 02374 $params = array ( "fragment" => $text ); 02375 02376 $ch = curl_init(); 02377 02378 curl_setopt( $ch, CURLOPT_POST, 1 ); // save form using a POST 02379 curl_setopt( $ch, CURLOPT_POSTFIELDS, $params ); // load the POST variables 02380 curl_setopt( $ch, CURLOPT_URL, VALIDATOR_URL ); // set url to post to 02381 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); // return into a variable 02382 02383 $result = curl_exec ( $ch ); 02384 02385 // if we encountered an error, then log it, and exit. 02386 if ( curl_error( $ch ) ) { 02387 trigger_error( "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) ); 02388 print "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) . " - exiting.\n"; 02389 exit( 1 ); 02390 } 02391 02392 curl_close ( $ch ); 02393 02394 $valid = ( strpos( $result, "Failed validation" ) === false ); 02395 02396 return array( $valid, $result ); 02397 } 02398 02404 function tidyCheckFile( $name ) { 02405 $file = DIRECTORY . "/" . $name; 02406 $command = PATH_TO_TIDY . " -output /tmp/out.html -quiet $file 2>&1"; 02407 $x = `$command`; 02408 02409 // Look for the most interesting Tidy errors and warnings. 02410 if ( strpos( $x, "end of file while parsing attributes" ) !== false 02411 || strpos( $x, "attribute with missing trailing quote mark" ) !== false 02412 || strpos( $x, "missing '>' for end of tag" ) !== false 02413 || strpos( $x, "Error:" ) !== false ) { 02414 print "\nTidy found something - view details with: $command"; 02415 return false; 02416 } else { 02417 return true; 02418 } 02419 } 02420 02426 function dbErrorLogged() { 02427 static $filesize; 02428 02429 // first time running this function 02430 if ( !isset( $filesize ) ) { 02431 // create log if it does not exist 02432 if ( DB_ERROR_LOG_FILE && !file_exists( DB_ERROR_LOG_FILE ) ) { 02433 saveFile( '', DB_ERROR_LOG_FILE ); 02434 } 02435 $filesize = filesize( DB_ERROR_LOG_FILE ); 02436 return false; 02437 } 02438 02439 $newsize = filesize( DB_ERROR_LOG_FILE ); 02440 // if the log has grown, then assume the current test caused it. 02441 if ( $newsize != $filesize ) { 02442 $filesize = $newsize; 02443 return true; 02444 } 02445 02446 return false; 02447 } 02448 02449 // //////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION //////////////////////// 02450 02459 function runWikiTest( pageTest $test, &$testname, $can_overwrite = false ) { 02460 02461 // by default don't overwrite a previous test of the same name. 02462 while ( ! $can_overwrite && file_exists( DIRECTORY . "/" . $testname . DATA_FILE ) ) { 02463 $testname .= "-" . mt_rand( 0, 9 ); 02464 } 02465 02466 $filename = DIRECTORY . "/" . $testname . DATA_FILE; 02467 02468 // Store the time before and after, to find slow pages. 02469 $before = microtime( true ); 02470 02471 // Get MediaWiki to give us the output of this test. 02472 $wiki_preview = wikiTestOutput( $test ); 02473 02474 $after = microtime( true ); 02475 02476 // if we received no response, then that's interesting. 02477 if ( $wiki_preview == "" ) { 02478 print "\nNo response received for: $filename"; 02479 return false; 02480 } 02481 02482 // save output HTML to file. 02483 $html_file = DIRECTORY . "/" . $testname . HTML_FILE; 02484 saveFile( $wiki_preview, $html_file ); 02485 02486 // if there were PHP errors in the output, then that's interesting too. 02487 if ( strpos( $wiki_preview, "<b>Warning</b>: " ) !== false 02488 || strpos( $wiki_preview, "<b>Fatal error</b>: " ) !== false 02489 || strpos( $wiki_preview, "<b>Notice</b>: " ) !== false 02490 || strpos( $wiki_preview, "<b>Error</b>: " ) !== false 02491 || strpos( $wiki_preview, "<b>Strict Standards:</b>" ) !== false 02492 ) { 02493 $error = substr( $wiki_preview, strpos( $wiki_preview, "</b>:" ) + 7, 50 ); 02494 // Avoid probable PHP bug with bad session ids; http://bugs.php.net/bug.php?id=38224 02495 if ( $error != "Unknown: The session id contains illegal character" ) { 02496 print "\nPHP error/warning/notice in HTML output: $html_file ; $error"; 02497 return false; 02498 } 02499 } 02500 02501 // if there was a MediaWiki Backtrace message in the output, then that's also interesting. 02502 if ( strpos( $wiki_preview, "Backtrace:" ) !== false ) { 02503 print "\nInternal MediaWiki error in HTML output: $html_file"; 02504 return false; 02505 } 02506 02507 // if there was a Parser error comment in the output, then that's potentially interesting. 02508 if ( strpos( $wiki_preview, "!-- ERR" ) !== false ) { 02509 print "\nParser Error comment in HTML output: $html_file"; 02510 return false; 02511 } 02512 02513 // if a database error was logged, then that's definitely interesting. 02514 if ( dbErrorLogged() ) { 02515 print "\nDatabase Error logged for: $filename"; 02516 return false; 02517 } 02518 02519 // validate result 02520 $valid = true; 02521 if ( VALIDATE_ON_WEB ) { 02522 list ( $valid, $validator_output ) = validateHTML( $wiki_preview ); 02523 if ( !$valid ) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY . "/" . $testname . ".validator_output.html"; 02524 } 02525 02526 // Get tidy to check the page, unless we already know it produces non-(X)HTML output. 02527 if ( $test->tidyValidate() ) { 02528 $valid = tidyCheckFile( $testname . HTML_FILE ) && $valid; 02529 } 02530 02531 // if it took more than 2 seconds to render, then it may be interesting too. (Possible DoS attack?) 02532 if ( ( $after - $before ) >= 2 ) { 02533 print "\nParticularly slow to render (" . round( $after - $before, 2 ) . " seconds): $filename"; 02534 return false; 02535 } 02536 02537 if ( $valid ) { 02538 // Remove temp HTML file if test was valid: 02539 unlink( $html_file ); 02540 } elseif ( VALIDATE_ON_WEB ) { 02541 saveFile( $validator_output, DIRECTORY . "/" . $testname . ".validator_output.html" ); 02542 } 02543 02544 return $valid; 02545 } 02546 02547 02548 // ///////////////// RERUNNING OLD TESTS /////////////////// 02549 02554 function rerunPreviousTests() { 02555 print "Retesting previously found problems.\n"; 02556 02557 $dir_contents = scandir ( DIRECTORY ); 02558 02559 // sort file into the order a normal person would use. 02560 natsort ( $dir_contents ); 02561 02562 foreach ( $dir_contents as $file ) { 02563 02564 // if file is not a test, then skip it. 02565 // Note we need to escape any periods or will be treated as "any character". 02566 $matches = array(); 02567 if ( !preg_match( "/(.*)" . str_replace( ".", "\.", DATA_FILE ) . "$/", $file, $matches ) ) continue; 02568 02569 // reload the test. 02570 $full_path = DIRECTORY . "/" . $file; 02571 $test = unserialize( file_get_contents( $full_path ) ); 02572 02573 // if this is not a valid test, then skip it. 02574 if ( ! $test instanceof pageTest ) { 02575 print "\nSkipping invalid test - $full_path"; 02576 continue; 02577 } 02578 02579 // The date format is in Apache log format, which makes it easier to locate 02580 // which retest caused which error in the Apache logs (only happens usually if 02581 // apache segfaults). 02582 if ( !QUIET ) print "[" . date ( "D M d H:i:s Y" ) . "] Retesting $file (" . get_class( $test ) . ")"; 02583 02584 // run test 02585 $testname = $matches[1]; 02586 $valid = runWikiTest( $test, $testname, true ); 02587 02588 if ( !$valid ) { 02589 saveTest( $test, $testname ); 02590 if ( QUIET ) { 02591 print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------"; 02592 } else { 02593 print "\n"; 02594 } 02595 } 02596 else { 02597 if ( !QUIET ) print "\r"; 02598 if ( DELETE_PASSED_RETESTS ) { 02599 $prefix = DIRECTORY . "/" . $testname; 02600 if ( is_file( $prefix . DATA_FILE ) ) unlink( $prefix . DATA_FILE ); 02601 if ( is_file( $prefix . PHP_TEST ) ) unlink( $prefix . PHP_TEST ); 02602 if ( is_file( $prefix . CURL_TEST ) ) unlink( $prefix . CURL_TEST ); 02603 if ( is_file( $prefix . INFO_FILE ) ) unlink( $prefix . INFO_FILE ); 02604 } 02605 } 02606 } 02607 02608 print "\nDone retesting.\n"; 02609 } 02610 02611 02612 // //////////////////// MAIN LOOP //////////////////////// 02613 02614 02615 // first check whether CURL is installed, because sometimes it's not. 02616 if ( ! function_exists( 'curl_init' ) ) { 02617 die( "Could not find 'curl_init' function. Is the curl extension compiled into PHP?\n" ); 02618 } 02619 02620 // Initialization of types. wikiFuzz doesn't have a constructor because we want to 02621 // access it staticly and not have any globals. 02622 wikiFuzz::$types = array_keys( wikiFuzz::$data ); 02623 02624 // Make directory if doesn't exist 02625 if ( !is_dir( DIRECTORY ) ) { 02626 mkdir ( DIRECTORY, 0700 ); 02627 } 02628 // otherwise, we first retest the things that we have found in previous runs 02629 elseif ( RERUN_OLD_TESTS ) { 02630 rerunPreviousTests(); 02631 } 02632 02633 // main loop. 02634 $start_time = date( "U" ); 02635 $num_errors = 0; 02636 if ( !QUIET ) { 02637 print "Beginning main loop. Results are stored in the " . DIRECTORY . " directory.\n"; 02638 print "Press CTRL+C to stop testing.\n"; 02639 } 02640 02641 for ( $count = 0; true; $count++ ) { 02642 if ( !QUIET ) { 02643 // spinning progress indicator. 02644 switch( $count % 4 ) { 02645 case '0': print "\r/"; break; 02646 case '1': print "\r-"; break; 02647 case '2': print "\r\\"; break; 02648 case '3': print "\r|"; break; 02649 } 02650 print " $count"; 02651 } 02652 02653 // generate a page test to run. 02654 $test = selectPageTest( $count ); 02655 02656 $mins = ( date( "U" ) - $start_time ) / 60; 02657 if ( !QUIET && $mins > 0 ) { 02658 print ". $num_errors poss errors. " 02659 . floor( $mins ) . " mins. " 02660 . round ( $count / $mins, 0 ) . " tests/min. " 02661 . get_class( $test ); // includes the current test name. 02662 } 02663 02664 // run this test against MediaWiki, and see if the output was valid. 02665 $testname = $count; 02666 $valid = runWikiTest( $test, $testname, false ); 02667 02668 // save the failed test 02669 if ( ! $valid ) { 02670 if ( QUIET ) { 02671 print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------"; 02672 } else { 02673 print "\n"; 02674 } 02675 saveTest( $test, $testname ); 02676 $num_errors += 1; 02677 } elseif ( KEEP_PASSED_TESTS ) { 02678 // print current time, with microseconds (matches "strace" format), and the test name. 02679 print " " . date( "H:i:s." ) . substr( current( explode( " ", microtime() ) ), 2 ) . " " . $testname; 02680 saveTest( $test, $testname ); 02681 } 02682 02683 // stop if we have reached max number of errors. 02684 if ( defined( "MAX_ERRORS" ) && $num_errors >= MAX_ERRORS ) { 02685 break; 02686 } 02687 02688 // stop if we have reached max number of mins runtime. 02689 if ( defined( "MAX_RUNTIME" ) && $mins >= MAX_RUNTIME ) { 02690 break; 02691 } 02692 }