Skip to content

Commit

Permalink
Merge branch 'm26_MDL-39810_IE_Compatibility_View_Does_Not_Recognize_…
Browse files Browse the repository at this point in the history
…JSON_RFC4627_MIME_Type' of https://github.com/scara/moodle
  • Loading branch information
Damyon Wiese committed Oct 29, 2013
2 parents d3428bc + bc242bb commit afb5f28
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 11 deletions.
89 changes: 78 additions & 11 deletions lib/classes/useragent.php
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,13 @@ public static function is_ie() {
}

/**
* Checks the user agent is IE and that the version is equal to or greater than that specified.
* Checks the user agent is IE and returns its main properties:
* - browser version;
* - whether running in compatibility view.
*
* @param string|int $version A version to check for, returns true if its equal to or greater than that specified.
* @return bool
* @return bool|array False if not IE, otherwise an associative array of properties.
*/
public static function check_ie_version($version = null) {
public static function check_ie_properties() {
// Internet Explorer.
$useragent = self::get_user_agent_string();
if ($useragent === false) {
Expand All @@ -490,12 +491,6 @@ public static function check_ie_version($version = null) {
// Reject Opera.
return false;
}
// In case of IE we have to deal with BC of the version parameter.
if (is_null($version)) {
$version = 5.5; // Anything older is not considered a browser at all!
}
// IE uses simple versions, let's cast it to float to simplify the logic here.
$version = round($version, 1);
// See: http://www.useragentstring.com/pages/Internet%20Explorer/.
if (preg_match("/MSIE ([0-9\.]+)/", $useragent, $match)) {
$browser = $match[1];
Expand All @@ -505,13 +500,62 @@ public static function check_ie_version($version = null) {
} else {
return false;
}
$compat_view = false;
// IE8 and later versions may pretend to be IE7 for intranet sites, use Trident version instead,
// the Trident should always describe the capabilities of IE in any emulation mode.
if ($browser === '7.0' and preg_match("/Trident\/([0-9\.]+)/", $useragent, $match)) {
$compat_view = true;
$browser = $match[1] + 4; // NOTE: Hopefully this will work also for future IE versions.
}
$browser = round($browser, 1);
return ($browser >= $version);
return array(
'version' => $browser,
'compatview' => $compat_view
);
}

/**
* Checks the user agent is IE and that the version is equal to or greater than that specified.
*
* @param string|int $version A version to check for, returns true if its equal to or greater than that specified.
* @return bool
*/
public static function check_ie_version($version = null) {
// Internet Explorer.
$properties = self::check_ie_properties();
if (!is_array($properties)) {
return false;
}
// In case of IE we have to deal with BC of the version parameter.
if (is_null($version)) {
$version = 5.5; // Anything older is not considered a browser at all!
}
// IE uses simple versions, let's cast it to float to simplify the logic here.
$version = round($version, 1);
return ($properties['version'] >= $version);
}

/**
* Checks the user agent is IE and that IE is running under Compatibility View setting.
*
* @return bool true if internet explorer runs in Compatibility View mode.
*/
public static function check_ie_compatibility_view() {
// IE User Agent string when in Compatibility View:
// - IE 8: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; ...)".
// - IE 9: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; ...)".
// - IE 10: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; ...)".
// - IE 11: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; ...)".
// Refs:
// - http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx.
// - http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx.
// - http://blogs.msdn.com/b/ie/archive/2011/04/15/the-ie10-user-agent-string.aspx.
// - http://msdn.microsoft.com/en-us/library/ie/hh869301%28v=vs.85%29.aspx.
$properties = self::check_ie_properties();
if (!is_array($properties)) {
return false;
}
return $properties['compatview'];
}

/**
Expand Down Expand Up @@ -832,4 +876,27 @@ public static function supports_svg() {
}
return $instance->supportssvg;
}

/**
* Returns true if the user agent supports the MIME media type for JSON text, as defined in RFC 4627.
*
* @return bool
*/
public static function supports_json_contenttype() {
// Modern browsers other than IE correctly supports 'application/json' media type.
if (!self::is_ie()) {
return true;
}

// IE8+ supports 'application/json' media type, when NOT in Compatibility View mode.
// Refs:
// - http://blogs.msdn.com/b/ie/archive/2008/09/10/native-json-in-ie8.aspx;
// - MDL-39810: issues when using 'text/plain' in Compatibility View for the body of an HTTP POST response.
if (self::check_ie_version(8) && !self::check_ie_compatibility_view()) {
return true;
}

// This browser does not support json.
return false;
}
}
6 changes: 6 additions & 0 deletions lib/outputrenderers.php
Original file line number Diff line number Diff line change
Expand Up @@ -3485,6 +3485,12 @@ public function header() {
// unfortunately YUI iframe upload does not support application/json
if (!empty($_FILES)) {
@header('Content-type: text/plain; charset=utf-8');
if (!core_useragent::supports_json_contenttype()) {
@header('X-Content-Type-Options: nosniff');
}
} else if (!core_useragent::supports_json_contenttype()) {
@header('Content-type: text/plain; charset=utf-8');
@header('X-Content-Type-Options: nosniff');
} else {
@header('Content-type: application/json; charset=utf-8');
}
Expand Down
21 changes: 21 additions & 0 deletions lib/tests/useragent_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class core_useragent_testcase extends basic_testcase {
'11.0' => array(
'Windows 8.1' => 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0)'
),
'11.0i' => array(
'Windows 8.1' => ' Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)'
),
),
'Firefox' => array(
'1.0.6' => array(
Expand Down Expand Up @@ -218,13 +221,15 @@ public function test_check_browser_version() {
$this->assertTrue(core_useragent::is_ie());
$this->assertTrue(core_useragent::check_ie_version());
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertFalse(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('7.0'));

core_useragent::instance(true, $this->user_agents['MSIE']['5.0']['Windows 98']);
$this->assertFalse(core_useragent::is_ie());
$this->assertFalse(core_useragent::check_ie_version());
$this->assertTrue(core_useragent::check_ie_version(0));
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertFalse(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('7.0'));

core_useragent::instance(true, $this->user_agents['MSIE']['9.0']['Windows 7']);
Expand All @@ -233,6 +238,7 @@ public function test_check_browser_version() {
$this->assertTrue(core_useragent::check_ie_version(0));
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertTrue(core_useragent::check_ie_version('9.0'));
$this->assertFalse(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('10'));

core_useragent::instance(true, $this->user_agents['MSIE']['9.0i']['Windows 7']);
Expand All @@ -241,6 +247,7 @@ public function test_check_browser_version() {
$this->assertTrue(core_useragent::check_ie_version(0));
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertTrue(core_useragent::check_ie_version('9.0'));
$this->assertTrue(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('10'));

core_useragent::instance(true, $this->user_agents['MSIE']['10.0']['Windows 8']);
Expand All @@ -250,6 +257,7 @@ public function test_check_browser_version() {
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertTrue(core_useragent::check_ie_version('9.0'));
$this->assertTrue(core_useragent::check_ie_version('10'));
$this->assertFalse(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('11'));

core_useragent::instance(true, $this->user_agents['MSIE']['10.0i']['Windows 8']);
Expand All @@ -259,6 +267,7 @@ public function test_check_browser_version() {
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertTrue(core_useragent::check_ie_version('9.0'));
$this->assertTrue(core_useragent::check_ie_version('10'));
$this->assertTrue(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('11'));

core_useragent::instance(true, $this->user_agents['MSIE']['11.0']['Windows 8.1']);
Expand All @@ -269,6 +278,18 @@ public function test_check_browser_version() {
$this->assertTrue(core_useragent::check_ie_version('9.0'));
$this->assertTrue(core_useragent::check_ie_version('10'));
$this->assertTrue(core_useragent::check_ie_version('11'));
$this->assertFalse(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('12'));

core_useragent::instance(true, $this->user_agents['MSIE']['11.0i']['Windows 8.1']);
$this->assertTrue(core_useragent::is_ie());
$this->assertTrue(core_useragent::check_ie_version());
$this->assertTrue(core_useragent::check_ie_version(0));
$this->assertTrue(core_useragent::check_ie_version('5.0'));
$this->assertTrue(core_useragent::check_ie_version('9.0'));
$this->assertTrue(core_useragent::check_ie_version('10'));
$this->assertTrue(core_useragent::check_ie_version('11'));
$this->assertTrue(core_useragent::check_ie_compatibility_view());
$this->assertFalse(core_useragent::check_ie_version('12'));

core_useragent::instance(true, $this->user_agents['Firefox']['2.0']['Windows XP']);
Expand Down

0 comments on commit afb5f28

Please sign in to comment.