From 16dccc2c48c7d0f2db6419710fd121d6dc6e4aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odin=20H=C3=B8rthe=20Omdal?= Date: Thu, 23 May 2013 12:20:48 +0200 Subject: [PATCH 1/3] cors: Add the Opera CORS tests --- cors/MANIFEST | 16 ++ cors/allow-headers.htm | 89 +++++++++++ cors/basic.htm | 71 +++++++++ cors/credentials-flag.htm | 112 +++++++++++++ cors/origin.htm | 119 ++++++++++++++ cors/preflight-cache.htm | 143 +++++++++++++++++ cors/redirect-origin.htm | 195 +++++++++++++++++++++++ cors/redirect-preflight-2.htm | 54 +++++++ cors/redirect-preflight.htm | 63 ++++++++ cors/redirect-userinfo.htm | 110 +++++++++++++ cors/remote-origin.htm | 122 ++++++++++++++ cors/request-headers.htm | 80 ++++++++++ cors/resources/.gitignore | 1 + cors/resources/checkandremovefromlog.php | 34 ++++ cors/resources/cors-cookie.php | 21 +++ cors/resources/cors-headers.php | 28 ++++ cors/resources/cors-makeheader.php | 59 +++++++ cors/resources/log.php | 27 ++++ cors/resources/preflight.php | 20 +++ cors/resources/remote-xhrer.html | 28 ++++ cors/resources/status.php | 40 +++++ cors/response-headers.htm | 103 ++++++++++++ cors/simple-requests.htm | 90 +++++++++++ cors/status-async.htm | 112 +++++++++++++ cors/status-preflight.htm | 62 +++++++ cors/status.htm | 80 ++++++++++ cors/support.js | 29 ++++ cors/testrunner.html | 8 + 28 files changed, 1916 insertions(+) create mode 100644 cors/MANIFEST create mode 100644 cors/allow-headers.htm create mode 100644 cors/basic.htm create mode 100644 cors/credentials-flag.htm create mode 100644 cors/origin.htm create mode 100644 cors/preflight-cache.htm create mode 100644 cors/redirect-origin.htm create mode 100644 cors/redirect-preflight-2.htm create mode 100644 cors/redirect-preflight.htm create mode 100644 cors/redirect-userinfo.htm create mode 100644 cors/remote-origin.htm create mode 100644 cors/request-headers.htm create mode 100644 cors/resources/.gitignore create mode 100755 cors/resources/checkandremovefromlog.php create mode 100755 cors/resources/cors-cookie.php create mode 100755 cors/resources/cors-headers.php create mode 100644 cors/resources/cors-makeheader.php create mode 100755 cors/resources/log.php create mode 100755 cors/resources/preflight.php create mode 100644 cors/resources/remote-xhrer.html create mode 100755 cors/resources/status.php create mode 100644 cors/response-headers.htm create mode 100644 cors/simple-requests.htm create mode 100644 cors/status-async.htm create mode 100644 cors/status-preflight.htm create mode 100644 cors/status.htm create mode 100644 cors/support.js create mode 100644 cors/testrunner.html diff --git a/cors/MANIFEST b/cors/MANIFEST new file mode 100644 index 00000000000000..3572eee7988d17 --- /dev/null +++ b/cors/MANIFEST @@ -0,0 +1,16 @@ +allow-headers.htm +basic.htm +credentials-flag.htm +origin.htm +preflight-cache.htm +redirect-origin.htm +redirect-preflight-2.htm +redirect-preflight.htm +redirect-userinfo.htm +remote-origin.htm +request-headers.htm +response-headers.htm +simple-requests.htm +status-async.htm +status-preflight.htm +status.htm diff --git a/cors/allow-headers.htm b/cors/allow-headers.htm new file mode 100644 index 00000000000000..aa1e69c6cb5f7c --- /dev/null +++ b/cors/allow-headers.htm @@ -0,0 +1,89 @@ + + +Access-Control-Allow-Headers handling + + + + +

Access-Control-Allow-Headers handling

+ +
+ + diff --git a/cors/basic.htm b/cors/basic.htm new file mode 100644 index 00000000000000..3499507c76fca9 --- /dev/null +++ b/cors/basic.htm @@ -0,0 +1,71 @@ + + +Basic CORS + + + + + + +
+ + diff --git a/cors/credentials-flag.htm b/cors/credentials-flag.htm new file mode 100644 index 00000000000000..6e83da69510b16 --- /dev/null +++ b/cors/credentials-flag.htm @@ -0,0 +1,112 @@ + +CORS - Access-Control-Allow-Credentials + + + + + + +

CORS - Access-Control-Allow-Credentials

+
+ diff --git a/cors/origin.htm b/cors/origin.htm new file mode 100644 index 00000000000000..1f89e4c86a59ef --- /dev/null +++ b/cors/origin.htm @@ -0,0 +1,119 @@ + + +Access-Control-Allow-Origin handling + + + + + + + +

Access-Control-Allow-Origin handling

+ +
+ + diff --git a/cors/preflight-cache.htm b/cors/preflight-cache.htm new file mode 100644 index 00000000000000..2f8b201267f661 --- /dev/null +++ b/cors/preflight-cache.htm @@ -0,0 +1,143 @@ + + +CORS - preflight cache + + + + + + +

Preflight cache

+ +
+ diff --git a/cors/redirect-origin.htm b/cors/redirect-origin.htm new file mode 100644 index 00000000000000..a9379a43249510 --- /dev/null +++ b/cors/redirect-origin.htm @@ -0,0 +1,195 @@ + + +CORS - redirect + + + + + + +

CORS redirect handling

+ +
+ + diff --git a/cors/redirect-preflight-2.htm b/cors/redirect-preflight-2.htm new file mode 100644 index 00000000000000..cf441bc60dca69 --- /dev/null +++ b/cors/redirect-preflight-2.htm @@ -0,0 +1,54 @@ + + +CORS - preflight after a redirect + + + + + + +

Preflight after redirect

+ +
+ diff --git a/cors/redirect-preflight.htm b/cors/redirect-preflight.htm new file mode 100644 index 00000000000000..e98b3107f8fedf --- /dev/null +++ b/cors/redirect-preflight.htm @@ -0,0 +1,63 @@ + + +CORS - redirect with preflight + + + + + + +

Redirect with preflight

+ +
+ diff --git a/cors/redirect-userinfo.htm b/cors/redirect-userinfo.htm new file mode 100644 index 00000000000000..58216467997aa0 --- /dev/null +++ b/cors/redirect-userinfo.htm @@ -0,0 +1,110 @@ + + +CORS - redirect with userinfo + + + + + + +

CORS userinfo redirect handling

+ +
+ + diff --git a/cors/remote-origin.htm b/cors/remote-origin.htm new file mode 100644 index 00000000000000..13fe68ecfcb8a0 --- /dev/null +++ b/cors/remote-origin.htm @@ -0,0 +1,122 @@ + + +Access-Control-Allow-Origin handling + + + + +

Access-Control-Allow-Origin handling

+ +
+ + diff --git a/cors/request-headers.htm b/cors/request-headers.htm new file mode 100644 index 00000000000000..335f5490a208c7 --- /dev/null +++ b/cors/request-headers.htm @@ -0,0 +1,80 @@ + + +CORS - request headers - Access-Control-Allow-Headers + + + + + + +

Request headers

+
+ diff --git a/cors/resources/.gitignore b/cors/resources/.gitignore new file mode 100644 index 00000000000000..7b987d03655fd0 --- /dev/null +++ b/cors/resources/.gitignore @@ -0,0 +1 @@ +logs.txt diff --git a/cors/resources/checkandremovefromlog.php b/cors/resources/checkandremovefromlog.php new file mode 100755 index 00000000000000..8cef887ff15364 --- /dev/null +++ b/cors/resources/checkandremovefromlog.php @@ -0,0 +1,34 @@ +$ident) + { + print "1"; + + unset($obj->$ident); + + $buffer = json_encode($obj); + + rewind($file); + ftruncate($file, 0); + fwrite($file, $buffer); + } + else + print "0"; + + fclose($file); +?> diff --git a/cors/resources/cors-cookie.php b/cors/resources/cors-cookie.php new file mode 100755 index 00000000000000..6fe109daaa5d2a --- /dev/null +++ b/cors/resources/cors-cookie.php @@ -0,0 +1,21 @@ + diff --git a/cors/resources/cors-makeheader.php b/cors/resources/cors-makeheader.php new file mode 100644 index 00000000000000..dfc91c9fd85624 --- /dev/null +++ b/cors/resources/cors-makeheader.php @@ -0,0 +1,59 @@ + 299) + { + header("Location: {$_GET['location']}", true, $code); + die("Redirecting"); + } +} + +foreach ($_SERVER as $name => $value) +{ + if (substr($name, 0, 5) == 'HTTP_') + { + $name = strtolower(str_replace('_', '-', substr($name, 5))); + $headers[$name] = $value; + } else if ($name == "CONTENT_TYPE") { + $headers["content-type"] = $value; + } else if ($name == "CONTENT_LENGTH") { + $headers["content-length"] = $value; + } +} + +$headers['get_value'] = isset($_GET['get_value']) ? $_GET['get_value'] : ''; + +if ($code) + header("HTTP/1.1 {$code} StatusText"); + +echo json_encode( $headers ); diff --git a/cors/resources/log.php b/cors/resources/log.php new file mode 100755 index 00000000000000..c5205105d5d803 --- /dev/null +++ b/cors/resources/log.php @@ -0,0 +1,27 @@ +$ident) + $obj->$ident = true; + + $buffer = json_encode($obj); + + rewind($file); + ftruncate($file, 0); + fwrite($file, $buffer); + fclose($file); +?> diff --git a/cors/resources/preflight.php b/cors/resources/preflight.php new file mode 100755 index 00000000000000..8547106312bd23 --- /dev/null +++ b/cors/resources/preflight.php @@ -0,0 +1,20 @@ + +Child helper + + + +The remote window diff --git a/cors/resources/status.php b/cors/resources/status.php new file mode 100755 index 00000000000000..b6cae2e5bc0457 --- /dev/null +++ b/cors/resources/status.php @@ -0,0 +1,40 @@ + $value) + $var[$i] = stripslashes($value); + return $var; + } + if(get_magic_quotes_gpc()) { + $_GET = stripslashes_recursive($_GET); + } + + // This should reasonably work for most response codes. + $code = isset($_GET['code']) && ctype_digit($_GET["code"]) ? $_GET["code"] : "200"; + $text = isset($_GET["text"]) ? $_GET["text"] : "OMG"; + + if (isset($_GET['preflight']) + && ctype_digit($_GET['preflight']) + && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') + $code = $_GET['preflight']; + + header("HTTP/1.1 " . $code . " " . $text); + + if (isset($_GET['type'])) + header("Content-Type:" . $_GET['type']); + if (isset($_GET["content"])) + echo $_GET['content']; +?> diff --git a/cors/response-headers.htm b/cors/response-headers.htm new file mode 100644 index 00000000000000..65037744fa3043 --- /dev/null +++ b/cors/response-headers.htm @@ -0,0 +1,103 @@ + + +CORS - Response headers + + + + + + +

Response headers

+
+ diff --git a/cors/simple-requests.htm b/cors/simple-requests.htm new file mode 100644 index 00000000000000..7cef0af7704b89 --- /dev/null +++ b/cors/simple-requests.htm @@ -0,0 +1,90 @@ + + +CORS - simple requests + + + + + + +

Simple requests

+

Simple requests shouldn't trigger preflight

+ +
+ diff --git a/cors/status-async.htm b/cors/status-async.htm new file mode 100644 index 00000000000000..872c47aaf97e16 --- /dev/null +++ b/cors/status-async.htm @@ -0,0 +1,112 @@ + + +CORS - status + + + + + + +

Status returned

+ +
+ diff --git a/cors/status-preflight.htm b/cors/status-preflight.htm new file mode 100644 index 00000000000000..96613060306f6f --- /dev/null +++ b/cors/status-preflight.htm @@ -0,0 +1,62 @@ + + +CORS - status after preflight + + + + + + +

Status after preflight

+ +
+ diff --git a/cors/status.htm b/cors/status.htm new file mode 100644 index 00000000000000..f8e08ba985554f --- /dev/null +++ b/cors/status.htm @@ -0,0 +1,80 @@ + + +CORS status + + + + + + + +

The returned status code in different scenarios

+ + + +
+   allowed  preflight  response  | status |
+   -------  ---------  --------  | ------ |
+ 1      no          x       400  |      0 |
+ 2      no        200         x  |      0 |
+ 3     yes          x       400  |    400 |
+ 4     yes        200       400  |    400 |
+ 5     yes        400         x  |      0 |
+
+ +
+ diff --git a/cors/support.js b/cors/support.js new file mode 100644 index 00000000000000..795f9a30da3886 --- /dev/null +++ b/cors/support.js @@ -0,0 +1,29 @@ +// For ignoring exception names (just for testing) +/* +_real_assert_throws = assert_throws; +function assert_throws(d, func, desc) { + try { + func(); + } catch(e) { + return true; + } + assert_unreached("Didn't throw!"); +} +*/ + +function dirname(path) { + return path.replace(/\/[^\/]*$/, '/') +} + +/* This subdomain should point to this same location */ +var SUBDOMAIN = 'www1' +var SUBDOMAIN2 = 'www2' +var PORT = '81' +var PORTS = '83' // w3c actually has no 'alternate' https port + +/* Changes http://example.com/abc/def/cool.htm to http://www1.example.com/abc/def/ */ +var CROSSDOMAIN = dirname(location.href) + .replace('://', '://' + SUBDOMAIN + '.') +var REMOTE_HOST = SUBDOMAIN + '.' + location.host +var REMOTE_PROTOCOL = location.protocol +var REMOTE_ORIGIN = REMOTE_PROTOCOL + '//' + REMOTE_HOST diff --git a/cors/testrunner.html b/cors/testrunner.html new file mode 100644 index 00000000000000..01d3a4c90e2faa --- /dev/null +++ b/cors/testrunner.html @@ -0,0 +1,8 @@ + + + +Web tests + + + +

From c03f38d2ea03c25db17d5277bda3b7a7639af349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odin=20H=C3=B8rthe=20Omdal?= Date: Fri, 30 Aug 2013 19:03:54 +0200 Subject: [PATCH 2/3] CORS: Use async XHR instead of sync for withCredentials --- cors/credentials-flag.htm | 111 ++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/cors/credentials-flag.htm b/cors/credentials-flag.htm index 6e83da69510b16..2f1f21185b6b81 100644 --- a/cors/credentials-flag.htm +++ b/cors/credentials-flag.htm @@ -18,72 +18,89 @@

CORS - Access-Control-Allow-Credentials

*/ // XXX Do some https tests here as well test(function () { - var id = new Date().getTime(), + var client = new XMLHttpRequest() + client.open('GET', CROSSDOMAIN, false) + assert_throws(null, function() { client.withCredentials = true; }, 'setting withCredentials') +}, 'Setting withCredentials on a sync XHR object should throw') + +async_test(function () { + var id = new Date().getTime() + '_1', client = new XMLHttpRequest() - client.open("GET", url + id, false) + client.open("GET", url + id, true) + client.onload = this.step_func(function() { + assert_equals(client.response, "NO_COOKIE") + client.open("GET", url + id, true) + client.onload = this.step_func(function() { + assert_equals(client.response, "NO_COOKIE") + this.done() + }) + client.send(null) + }) client.send(null) - assert_equals(client.response, "NO_COOKIE"); - client.open("GET", url + id, false) - client.send(null) - assert_equals(client.response, "NO_COOKIE") }, "Don't send cookie by default"); -test(function () { - var id = new Date().getTime(), +async_test(function () { + var id = new Date().getTime() + '_2', client = new XMLHttpRequest() - client.open("GET", url + id, false) - client.withCredentials = true - client.send(null) - assert_equals(client.response, "NO_COOKIE"); - - /* We have cookie, but the browser shouldn't send */ - client.open("GET", url + id, false) - client.withCredentials = false - client.send(null) - assert_equals(client.response, "NO_COOKIE") - - /* Reads and deletes the cookie */ - client.open("GET", url + id, false) + client.open("GET", url + id, true) client.withCredentials = true + client.onload = this.step_func(function() { + assert_equals(client.response, "NO_COOKIE"); + + /* We have cookie, but the browser shouldn't send */ + client.open("GET", url + id, true) + client.withCredentials = false + client.onload = this.step_func(function() { + assert_equals(client.response, "NO_COOKIE") + + /* Reads and deletes the cookie */ + client.open("GET", url + id, true) + client.withCredentials = true + client.onload = this.step_func(function() { + assert_equals(client.response, "COOKIE") + this.done() + }) + client.send(null) + }) + client.send(null) + }) client.send(null) - assert_equals(client.response, "COOKIE") }, "Don't send cookie part 2"); -test(function () { - var id = new Date().getTime(), +async_test(function () { + var id = new Date().getTime() + '_3', client = new XMLHttpRequest() /* Shouldn't set the response cookie */ - client.open("GET", url + id, false) + client.open("GET", url + id, true) client.withCredentials = false + client.onload = this.step_func(function() { + console.log(client.response + '_', client.response) + assert_equals(client.response, "NO_COOKIE", "first"); + + /* Sets the cookie */ + client.open("GET", url + id, true) + client.withCredentials = true + client.onload = this.step_func(function() { + assert_equals(client.response, "NO_COOKIE", "second") + + /* Reads and deletes the cookie */ + client.open("GET", url + id, true) + client.withCredentials = true + client.onload = this.step_func(function() { + assert_equals(client.response, "COOKIE", "third") + this.done() + }) + client.send(null) + }) + client.send(null) + }) client.send(null) - assert_equals(client.response, "NO_COOKIE"); - - /* Sets the cookie */ - client.open("GET", url + id, false) - client.withCredentials = true - client.send(null) - assert_equals(client.response, "NO_COOKIE") - - /* Reads and deletes the cookie */ - client.open("GET", url + id, false) - client.withCredentials = true - client.send(null) - assert_equals(client.response, "COOKIE") }, "Don't obey Set-Cookie when withCredentials=false"); function test_response_header(allow) { - test(function () { - var client = new XMLHttpRequest() - client.open('GET', - CROSSDOMAIN + 'resources/cors-makeheader.php?credentials=' + allow, - false) - client.withCredentials = true; - assert_throws(null, function() { client.send() }, 'send') - }, 'Access-Control-Allow-Credentials: ' + allow + ' should be disallowed (sync)') - var resp_test = async_test('Access-Control-Allow-Credentials: ' + allow + ' should be disallowed (async)') resp_test.step(function() { var client = new XMLHttpRequest() From e44df070f5adfb5e8a035f62eb32b434aa53735c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odin=20H=C3=B8rthe=20Omdal?= Date: Fri, 30 Aug 2013 19:09:24 +0200 Subject: [PATCH 3/3] CORS: Don't check response code on OPENED status --- cors/status-async.htm | 2 +- cors/status-preflight.htm | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cors/status-async.htm b/cors/status-async.htm index 872c47aaf97e16..6dddba1a0bdbff 100644 --- a/cors/status-async.htm +++ b/cors/status-async.htm @@ -63,7 +63,7 @@

Status returned

client.setRequestHeader('x-nonsimple', true) client.onreadystatechange = this.step_func(function() { - if (client.readyState < client.HEADERS_RECIEVED) + if (client.readyState < client.HEADERS_RECEIVED) return assert_equals(client.response, "", "response data") assert_equals(client.status, expect_code, "response status") diff --git a/cors/status-preflight.htm b/cors/status-preflight.htm index 96613060306f6f..42cc4f85e1c47c 100644 --- a/cors/status-preflight.htm +++ b/cors/status-preflight.htm @@ -23,6 +23,8 @@

Status after preflight

client.setRequestHeader('x-nonsimple', true) client.onreadystatechange = this.step_func(function() { + if (client.readyState < client.HEADERS_RECEIVED) + return assert_equals(client.response, "", "response data") assert_equals(client.status, code, "response status") if (client.readyState == client.DONE)