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