Index: trunk/phase3/includes/OutputPage.php |
— | — | @@ -2522,6 +2522,9 @@ |
2523 | 2523 | ksort( $query ); |
2524 | 2524 | |
2525 | 2525 | $url = wfAppendQuery( $wgLoadScript, $query ); |
| 2526 | + // Prevent the IE6 extension check from being triggered (bug 28840) |
| 2527 | + // by appending a character that's invalid in Windows extensions ('*') |
| 2528 | + $url .= '&*'; |
2526 | 2529 | if ( $useESI && $wgResourceLoaderUseESI ) { |
2527 | 2530 | $esi = Xml::element( 'esi:include', array( 'src' => $url ) ); |
2528 | 2531 | if ( $only == ResourceLoaderModule::TYPE_STYLES ) { |
— | — | @@ -2532,9 +2535,9 @@ |
2533 | 2536 | } else { |
2534 | 2537 | // Automatically select style/script elements |
2535 | 2538 | if ( $only === ResourceLoaderModule::TYPE_STYLES ) { |
2536 | | - $link = Html::linkedStyle( wfAppendQuery( $wgLoadScript, $query ) ); |
| 2539 | + $link = Html::linkedStyle( $url ); |
2537 | 2540 | } else { |
2538 | | - $link = Html::linkedScript( wfAppendQuery( $wgLoadScript, $query ) ); |
| 2541 | + $link = Html::linkedScript( $url ); |
2539 | 2542 | } |
2540 | 2543 | } |
2541 | 2544 | |
Index: trunk/phase3/includes/WebRequest.php |
— | — | @@ -785,17 +785,10 @@ |
786 | 786 | public function isPathInfoBad() { |
787 | 787 | global $wgScriptExtension; |
788 | 788 | |
789 | | - if ( isset( $_SERVER['QUERY_STRING'] ) |
790 | | - && preg_match( '/\.[^\\/:*?"<>|%]+(#|\?|$)/i', $_SERVER['QUERY_STRING'] ) ) |
| 789 | + if ( isset( $_SERVER['QUERY_STRING'] ) ) |
791 | 790 | { |
792 | 791 | // Bug 28235 |
793 | | - // Block only Internet Explorer, and requests with missing UA |
794 | | - // headers that could be IE users behind a privacy proxy. |
795 | | - if ( !isset( $_SERVER['HTTP_USER_AGENT'] ) |
796 | | - || preg_match( '/; *MSIE/', $_SERVER['HTTP_USER_AGENT'] ) ) |
797 | | - { |
798 | | - return true; |
799 | | - } |
| 792 | + return strval( self::findIE6Extension( $_SERVER['QUERY_STRING'] ) ) !== ''; |
800 | 793 | } |
801 | 794 | |
802 | 795 | if ( !isset( $_SERVER['PATH_INFO'] ) ) { |
— | — | @@ -809,6 +802,69 @@ |
810 | 803 | $ext = substr( $pi, $dotPos ); |
811 | 804 | return !in_array( $ext, array( $wgScriptExtension, '.php', '.php5' ) ); |
812 | 805 | } |
| 806 | + |
| 807 | + /** |
| 808 | + * Determine what extension IE6 will infer from a certain query string. |
| 809 | + * If the URL has an extension before the question mark, IE6 will use |
| 810 | + * that and ignore the query string, but per the comment at |
| 811 | + * isPathInfoBad() we don't have a reliable way to determine the URL, |
| 812 | + * so isPathInfoBad() just passes in the query string for $url. |
| 813 | + * All entry points have safe extensions (php, php5) anyway, so |
| 814 | + * checking the query string is possibly overly paranoid but never |
| 815 | + * insecure. |
| 816 | + * |
| 817 | + * The criteria for finding an extension are as follows: |
| 818 | + * * a possible extension is a dot followed by one or more characters not in <>\"/:|?.# |
| 819 | + * * if we find a possible extension followed by the end of the string or a #, that's our extension |
| 820 | + * * if we find a possible extension followed by a ?, that's our extension |
| 821 | + * ** UNLESS it's exe, dll or cgi, in which case we ignore it and continue searching for another possible extension |
| 822 | + * * if we find a possible extension followed by a dot or another illegal character, we ignore it and continue searching |
| 823 | + * |
| 824 | + * @param $url string URL |
| 825 | + * @return mixed Detected extension (string), or false if none found |
| 826 | + */ |
| 827 | + public static function findIE6Extension( $url ) { |
| 828 | + $remaining = $url; |
| 829 | + while ( $remaining !== '' ) { |
| 830 | + // Skip ahead to the next dot |
| 831 | + $pos = strcspn( $remaining, '.' ); |
| 832 | + if ( $pos === strlen( $remaining ) || $remaining[$pos] === '#' ) { |
| 833 | + // End of string, we're done |
| 834 | + return false; |
| 835 | + } |
| 836 | + |
| 837 | + // We found a dot. Skip past it |
| 838 | + $remaining = substr( $remaining, $pos + 1 ); |
| 839 | + // Check for illegal characters in our prospective extension, |
| 840 | + // or for another dot, or for a hash sign |
| 841 | + $pos = strcspn( $remaining, "<>\\\"/:|?*.#" ); |
| 842 | + if ( $pos === strlen( $remaining ) ) { |
| 843 | + // No illegal character or next dot or hash |
| 844 | + // We have our extension |
| 845 | + return $remaining; |
| 846 | + } |
| 847 | + if ( $remaining[$pos] === '#' ) { |
| 848 | + // We've found a legal extension followed by a hash |
| 849 | + // Trim the hash and everything after it, then return that |
| 850 | + return substr( $remaining, 0, $pos ); |
| 851 | + } |
| 852 | + if ( $remaining[$pos] === '?' ) { |
| 853 | + // We've found a legal extension followed by a question mark |
| 854 | + // If the extension is NOT exe, dll or cgi, return it |
| 855 | + $extension = substr( $remaining, 0, $pos ); |
| 856 | + if ( strcasecmp( $extension, 'exe' ) && strcasecmp( $extension, 'dll' ) && |
| 857 | + strcasecmp( $extension, 'cgi' ) ) |
| 858 | + { |
| 859 | + return $extension; |
| 860 | + } |
| 861 | + // Else continue looking |
| 862 | + } |
| 863 | + // We found an illegal character or another dot |
| 864 | + // Skip to that character and continue the loop |
| 865 | + $remaining = substr( $remaining, $pos ); |
| 866 | + } |
| 867 | + return false; |
| 868 | + } |
813 | 869 | |
814 | 870 | /** |
815 | 871 | * Parse the Accept-Language header sent by the client into an array |
Index: trunk/phase3/includes/resourceloader/ResourceLoader.php |
— | — | @@ -736,8 +736,7 @@ |
737 | 737 | * Convert an array of module names to a packed query string. |
738 | 738 | * |
739 | 739 | * For example, array( 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ) |
740 | | - * becomes 'foo!bar,baz|bar!baz,quux' |
741 | | - * The ! is for IE6 being stupid with extensions. |
| 740 | + * becomes 'foo.bar,baz|bar.baz,quux' |
742 | 741 | * @param $modules array of module names (strings) |
743 | 742 | * @return string Packed query string |
744 | 743 | */ |
— | — | @@ -756,7 +755,7 @@ |
757 | 756 | $arr[] = $p . implode( ',', $suffixes ); |
758 | 757 | } |
759 | 758 | $str = implode( '|', $arr ); |
760 | | - return str_replace( ".", "!", $str ); # bug 28840 |
| 759 | + return $str; |
761 | 760 | } |
762 | 761 | |
763 | 762 | /** |
Index: trunk/phase3/includes/resourceloader/ResourceLoaderContext.php |
— | — | @@ -67,13 +67,12 @@ |
68 | 68 | /** |
69 | 69 | * Expand a string of the form jquery.foo,bar|jquery.ui.baz,quux to |
70 | 70 | * an array of module names like array( 'jquery.foo', 'jquery.bar', |
71 | | - * 'jquery.ui.baz', 'jquery.ui.quux' ) Also translating ! to . |
| 71 | + * 'jquery.ui.baz', 'jquery.ui.quux' ) |
72 | 72 | * @param $modules String Packed module name list |
73 | 73 | * @return array of module names |
74 | 74 | */ |
75 | 75 | public static function expandModuleNames( $modules ) { |
76 | 76 | $retval = array(); |
77 | | - $modules = str_replace( "!", ".", $modules ); # bug 28840 - IE is stupid. |
78 | 77 | $exploded = explode( '|', $modules ); |
79 | 78 | foreach ( $exploded as $group ) { |
80 | 79 | if ( strpos( $group, ',' ) === false ) { |
Index: trunk/phase3/resources/mediawiki/mediawiki.js |
— | — | @@ -626,7 +626,7 @@ |
627 | 627 | var p = prefix === '' ? '' : prefix + '.'; |
628 | 628 | arr.push( p + moduleMap[prefix].join( ',' ) ); |
629 | 629 | } |
630 | | - return arr.join( '|' ).replace( /\./g, '!' ); |
| 630 | + return arr.join( '|' ); |
631 | 631 | } |
632 | 632 | |
633 | 633 | /** |
— | — | @@ -780,7 +780,8 @@ |
781 | 781 | // Asynchronously append a script tag to the end of the body |
782 | 782 | for ( var r = 0; r < requests.length; r++ ) { |
783 | 783 | requests[r] = sortQuery( requests[r] ); |
784 | | - var src = mw.config.get( 'wgLoadScript' ) + '?' + $.param( requests[r] ); |
| 784 | + // Append &* to avoid triggering the IE6 extension check |
| 785 | + var src = mw.config.get( 'wgLoadScript' ) + '?' + $.param( requests[r] ) + '&*'; |
785 | 786 | addScript( src ); |
786 | 787 | } |
787 | 788 | }; |