summaryrefslogtreecommitdiffstats
path: root/tests/lib/AppFramework/Http/RequestTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/AppFramework/Http/RequestTest.php')
-rw-r--r--tests/lib/AppFramework/Http/RequestTest.php1453
1 files changed, 1453 insertions, 0 deletions
diff --git a/tests/lib/AppFramework/Http/RequestTest.php b/tests/lib/AppFramework/Http/RequestTest.php
new file mode 100644
index 00000000000..ddc2403d866
--- /dev/null
+++ b/tests/lib/AppFramework/Http/RequestTest.php
@@ -0,0 +1,1453 @@
+<?php
+/**
+ * @copyright 2013 Thomas Tanghus (thomas@tanghus.net)
+ * @copyright 2015 Lukas Reschke lukas@owncloud.com
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\AppFramework\Http;
+
+use OC\AppFramework\Http\Request;
+use OC\Security\CSRF\CsrfToken;
+use OC\Security\CSRF\CsrfTokenManager;
+use OCP\Security\ISecureRandom;
+use OCP\IConfig;
+
+/**
+ * Class RequestTest
+ *
+ * @package OC\AppFramework\Http
+ */
+class RequestTest extends \Test\TestCase {
+ /** @var string */
+ protected $stream = 'fakeinput://data';
+ /** @var ISecureRandom */
+ protected $secureRandom;
+ /** @var IConfig */
+ protected $config;
+ /** @var CsrfTokenManager */
+ protected $csrfTokenManager;
+
+ protected function setUp() {
+ parent::setUp();
+
+ if (in_array('fakeinput', stream_get_wrappers())) {
+ stream_wrapper_unregister('fakeinput');
+ }
+ stream_wrapper_register('fakeinput', 'Test\AppFramework\Http\RequestStream');
+
+ $this->secureRandom = $this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock();
+ $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock();
+ $this->csrfTokenManager = $this->getMockBuilder('\OC\Security\CSRF\CsrfTokenManager')
+ ->disableOriginalConstructor()->getMock();
+ }
+
+ protected function tearDown() {
+ stream_wrapper_unregister('fakeinput');
+ parent::tearDown();
+ }
+
+ public function testRequestAccessors() {
+ $vars = array(
+ 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
+ 'method' => 'GET',
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ // Countable
+ $this->assertSame(2, count($request));
+ // Array access
+ $this->assertSame('Joey', $request['nickname']);
+ // "Magic" accessors
+ $this->assertSame('Joey', $request->{'nickname'});
+ $this->assertTrue(isset($request['nickname']));
+ $this->assertTrue(isset($request->{'nickname'}));
+ $this->assertFalse(isset($request->{'flickname'}));
+ // Only testing 'get', but same approach for post, files etc.
+ $this->assertSame('Joey', $request->get['nickname']);
+ // Always returns null if variable not set.
+ $this->assertSame(null, $request->{'flickname'});
+
+ }
+
+ // urlParams has precedence over POST which has precedence over GET
+ public function testPrecedence() {
+ $vars = array(
+ 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
+ 'post' => array('name' => 'Jane Doe', 'nickname' => 'Janey'),
+ 'urlParams' => array('user' => 'jw', 'name' => 'Johnny Weissmüller'),
+ 'method' => 'GET'
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame(3, count($request));
+ $this->assertSame('Janey', $request->{'nickname'});
+ $this->assertSame('Johnny Weissmüller', $request->{'name'});
+ }
+
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testImmutableArrayAccess() {
+ $vars = array(
+ 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
+ 'method' => 'GET'
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $request['nickname'] = 'Janey';
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testImmutableMagicAccess() {
+ $vars = array(
+ 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
+ 'method' => 'GET'
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $request->{'nickname'} = 'Janey';
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testGetTheMethodRight() {
+ $vars = array(
+ 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
+ 'method' => 'GET',
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $request->post;
+ }
+
+ public function testTheMethodIsRight() {
+ $vars = array(
+ 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
+ 'method' => 'GET',
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('GET', $request->method);
+ $result = $request->get;
+ $this->assertSame('John Q. Public', $result['name']);
+ $this->assertSame('Joey', $result['nickname']);
+ }
+
+ public function testJsonPost() {
+ global $data;
+ $data = '{"name": "John Q. Public", "nickname": "Joey"}';
+ $vars = array(
+ 'method' => 'POST',
+ 'server' => array('CONTENT_TYPE' => 'application/json; utf-8')
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('POST', $request->method);
+ $result = $request->post;
+ $this->assertSame('John Q. Public', $result['name']);
+ $this->assertSame('Joey', $result['nickname']);
+ $this->assertSame('Joey', $request->params['nickname']);
+ $this->assertSame('Joey', $request['nickname']);
+ }
+
+ public function testNotJsonPost() {
+ global $data;
+ $data = 'this is not valid json';
+ $vars = array(
+ 'method' => 'POST',
+ 'server' => array('CONTENT_TYPE' => 'application/json; utf-8')
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertEquals('POST', $request->method);
+ $result = $request->post;
+ // ensure there's no error attempting to decode the content
+ }
+
+ public function testPatch() {
+ global $data;
+ $data = http_build_query(array('name' => 'John Q. Public', 'nickname' => 'Joey'), '', '&');
+
+ $vars = array(
+ 'method' => 'PATCH',
+ 'server' => array('CONTENT_TYPE' => 'application/x-www-form-urlencoded'),
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('PATCH', $request->method);
+ $result = $request->patch;
+
+ $this->assertSame('John Q. Public', $result['name']);
+ $this->assertSame('Joey', $result['nickname']);
+ }
+
+ public function testJsonPatchAndPut() {
+ global $data;
+
+ // PUT content
+ $data = '{"name": "John Q. Public", "nickname": "Joey"}';
+ $vars = array(
+ 'method' => 'PUT',
+ 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'),
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('PUT', $request->method);
+ $result = $request->put;
+
+ $this->assertSame('John Q. Public', $result['name']);
+ $this->assertSame('Joey', $result['nickname']);
+
+ // PATCH content
+ $data = '{"name": "John Q. Public", "nickname": null}';
+ $vars = array(
+ 'method' => 'PATCH',
+ 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'),
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('PATCH', $request->method);
+ $result = $request->patch;
+
+ $this->assertSame('John Q. Public', $result['name']);
+ $this->assertSame(null, $result['nickname']);
+ }
+
+ public function testPutStream() {
+ global $data;
+ $data = file_get_contents(__DIR__ . '/../../../data/testimage.png');
+
+ $vars = array(
+ 'put' => $data,
+ 'method' => 'PUT',
+ 'server' => array('CONTENT_TYPE' => 'image/png'),
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('PUT', $request->method);
+ $resource = $request->put;
+ $contents = stream_get_contents($resource);
+ $this->assertSame($data, $contents);
+
+ try {
+ $resource = $request->put;
+ } catch(\LogicException $e) {
+ return;
+ }
+ $this->fail('Expected LogicException.');
+
+ }
+
+
+ public function testSetUrlParameters() {
+ $vars = array(
+ 'post' => array(),
+ 'method' => 'POST',
+ 'urlParams' => array('id' => '2'),
+ );
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $newParams = array('id' => '3', 'test' => 'test2');
+ $request->setUrlParameters($newParams);
+ $this->assertSame('test2', $request->getParam('test'));
+ $this->assertEquals('3', $request->getParam('id'));
+ $this->assertEquals('3', $request->getParams()['id']);
+ }
+
+ public function testGetIdWithModUnique() {
+ $vars = [
+ 'server' => [
+ 'UNIQUE_ID' => 'GeneratedUniqueIdByModUnique'
+ ],
+ ];
+
+ $request = new Request(
+ $vars,
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('GeneratedUniqueIdByModUnique', $request->getId());
+ }
+
+ public function testGetIdWithoutModUnique() {
+ $this->secureRandom->expects($this->once())
+ ->method('generate')
+ ->with('20')
+ ->will($this->returnValue('GeneratedByOwnCloudItself'));
+
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('GeneratedByOwnCloudItself', $request->getId());
+ }
+
+ public function testGetIdWithoutModUniqueStable() {
+ $request = new Request(
+ [],
+ \OC::$server->getSecureRandom(),
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+ $firstId = $request->getId();
+ $secondId = $request->getId();
+ $this->assertSame($firstId, $secondId);
+ }
+
+ public function testGetRemoteAddressWithoutTrustedRemote() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('trusted_proxies')
+ ->will($this->returnValue([]));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'REMOTE_ADDR' => '10.0.0.2',
+ 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
+ 'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('10.0.0.2', $request->getRemoteAddress());
+ }
+
+ public function testGetRemoteAddressWithNoTrustedHeader() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('trusted_proxies')
+ ->will($this->returnValue(['10.0.0.2']));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('forwarded_for_headers')
+ ->will($this->returnValue([]));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'REMOTE_ADDR' => '10.0.0.2',
+ 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
+ 'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('10.0.0.2', $request->getRemoteAddress());
+ }
+
+ public function testGetRemoteAddressWithSingleTrustedRemote() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('trusted_proxies')
+ ->will($this->returnValue(['10.0.0.2']));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('forwarded_for_headers')
+ ->will($this->returnValue(['HTTP_X_FORWARDED']));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'REMOTE_ADDR' => '10.0.0.2',
+ 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
+ 'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('10.4.0.5', $request->getRemoteAddress());
+ }
+
+ public function testGetRemoteAddressVerifyPriorityHeader() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('trusted_proxies')
+ ->will($this->returnValue(['10.0.0.2']));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('forwarded_for_headers')
+ ->will($this->returnValue([
+ 'HTTP_CLIENT_IP',
+ 'HTTP_X_FORWARDED_FOR',
+ 'HTTP_X_FORWARDED'
+ ]));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'REMOTE_ADDR' => '10.0.0.2',
+ 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
+ 'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('192.168.0.233', $request->getRemoteAddress());
+ }
+
+ /**
+ * @return array
+ */
+ public function httpProtocolProvider() {
+ return [
+ // Valid HTTP 1.0
+ ['HTTP/1.0', 'HTTP/1.0'],
+ ['http/1.0', 'HTTP/1.0'],
+ ['HTTp/1.0', 'HTTP/1.0'],
+
+ // Valid HTTP 1.1
+ ['HTTP/1.1', 'HTTP/1.1'],
+ ['http/1.1', 'HTTP/1.1'],
+ ['HTTp/1.1', 'HTTP/1.1'],
+
+ // Valid HTTP 2.0
+ ['HTTP/2', 'HTTP/2'],
+ ['http/2', 'HTTP/2'],
+ ['HTTp/2', 'HTTP/2'],
+
+ // Invalid
+ ['HTTp/394', 'HTTP/1.1'],
+ ['InvalidProvider/1.1', 'HTTP/1.1'],
+ [null, 'HTTP/1.1'],
+ ['', 'HTTP/1.1'],
+
+ ];
+ }
+
+ /**
+ * @dataProvider httpProtocolProvider
+ *
+ * @param mixed $input
+ * @param string $expected
+ */
+ public function testGetHttpProtocol($input, $expected) {
+ $request = new Request(
+ [
+ 'server' => [
+ 'SERVER_PROTOCOL' => $input,
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame($expected, $request->getHttpProtocol());
+ }
+
+ public function testGetServerProtocolWithOverride() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue('customProtocol'));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('overwritecondaddr')
+ ->will($this->returnValue(''));
+ $this->config
+ ->expects($this->at(2))
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue('customProtocol'));
+
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('customProtocol', $request->getServerProtocol());
+ }
+
+ public function testGetServerProtocolWithProtoValid() {
+ $this->config
+ ->expects($this->exactly(2))
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
+
+ $requestHttps = new Request(
+ [
+ 'server' => [
+ 'HTTP_X_FORWARDED_PROTO' => 'HtTpS'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+ $requestHttp = new Request(
+ [
+ 'server' => [
+ 'HTTP_X_FORWARDED_PROTO' => 'HTTp'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+
+ $this->assertSame('https', $requestHttps->getServerProtocol());
+ $this->assertSame('http', $requestHttp->getServerProtocol());
+ }
+
+ public function testGetServerProtocolWithHttpsServerValueOn() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTPS' => 'on'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+ $this->assertSame('https', $request->getServerProtocol());
+ }
+
+ public function testGetServerProtocolWithHttpsServerValueOff() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTPS' => 'off'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+ $this->assertSame('http', $request->getServerProtocol());
+ }
+
+ public function testGetServerProtocolWithHttpsServerValueEmpty() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTPS' => ''
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+ $this->assertSame('http', $request->getServerProtocol());
+ }
+
+ public function testGetServerProtocolDefault() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
+
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+ $this->assertSame('http', $request->getServerProtocol());
+ }
+
+ public function testGetServerProtocolBehindLoadBalancers() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTP_X_FORWARDED_PROTO' => 'https,http,http'
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('https', $request->getServerProtocol());
+ }
+
+ /**
+ * @dataProvider userAgentProvider
+ * @param string $testAgent
+ * @param array $userAgent
+ * @param bool $matches
+ */
+ public function testUserAgent($testAgent, $userAgent, $matches) {
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTP_USER_AGENT' => $testAgent,
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame($matches, $request->isUserAgent($userAgent));
+ }
+
+ /**
+ * @dataProvider userAgentProvider
+ * @param string $testAgent
+ * @param array $userAgent
+ * @param bool $matches
+ */
+ public function testUndefinedUserAgent($testAgent, $userAgent, $matches) {
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertFalse($request->isUserAgent($userAgent));
+ }
+
+ /**
+ * @return array
+ */
+ function userAgentProvider() {
+ return [
+ [
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
+ [
+ Request::USER_AGENT_IE
+ ],
+ true,
+ ],
+ [
+ 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0',
+ [
+ Request::USER_AGENT_IE
+ ],
+ false,
+ ],
+ [
+ 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36',
+ [
+ Request::USER_AGENT_ANDROID_MOBILE_CHROME
+ ],
+ true,
+ ],
+ [
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
+ [
+ Request::USER_AGENT_ANDROID_MOBILE_CHROME
+ ],
+ false,
+ ],
+ [
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
+ [
+ Request::USER_AGENT_IE,
+ Request::USER_AGENT_ANDROID_MOBILE_CHROME,
+ ],
+ true,
+ ],
+ [
+ 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36',
+ [
+ Request::USER_AGENT_IE,
+ Request::USER_AGENT_ANDROID_MOBILE_CHROME,
+ ],
+ true,
+ ],
+ [
+ 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0',
+ [
+ Request::USER_AGENT_FREEBOX
+ ],
+ false,
+ ],
+ [
+ 'Mozilla/5.0',
+ [
+ Request::USER_AGENT_FREEBOX
+ ],
+ true,
+ ],
+ [
+ 'Fake Mozilla/5.0',
+ [
+ Request::USER_AGENT_FREEBOX
+ ],
+ false,
+ ],
+ ];
+ }
+
+ public function testInsecureServerHostServerNameHeader() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'SERVER_NAME' => 'from.server.name:8080',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('from.server.name:8080', $request->getInsecureServerHost());
+ }
+
+ public function testInsecureServerHostHttpHostHeader() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'SERVER_NAME' => 'from.server.name:8080',
+ 'HTTP_HOST' => 'from.host.header:8080',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('from.host.header:8080', $request->getInsecureServerHost());
+ }
+
+ public function testInsecureServerHostHttpFromForwardedHeaderSingle() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'SERVER_NAME' => 'from.server.name:8080',
+ 'HTTP_HOST' => 'from.host.header:8080',
+ 'HTTP_X_FORWARDED_HOST' => 'from.forwarded.host:8080',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('from.forwarded.host:8080', $request->getInsecureServerHost());
+ }
+
+ public function testInsecureServerHostHttpFromForwardedHeaderStacked() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'SERVER_NAME' => 'from.server.name:8080',
+ 'HTTP_HOST' => 'from.host.header:8080',
+ 'HTTP_X_FORWARDED_HOST' => 'from.forwarded.host2:8080,another.one:9000',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('from.forwarded.host2:8080', $request->getInsecureServerHost());
+ }
+
+ public function testGetServerHostWithOverwriteHost() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('overwritehost')
+ ->will($this->returnValue('my.overwritten.host'));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('overwritecondaddr')
+ ->will($this->returnValue(''));
+ $this->config
+ ->expects($this->at(2))
+ ->method('getSystemValue')
+ ->with('overwritehost')
+ ->will($this->returnValue('my.overwritten.host'));
+
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('my.overwritten.host', $request->getServerHost());
+ }
+
+ public function testGetServerHostWithTrustedDomain() {
+ $this->config
+ ->expects($this->at(3))
+ ->method('getSystemValue')
+ ->with('trusted_domains')
+ ->will($this->returnValue(['my.trusted.host']));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTP_X_FORWARDED_HOST' => 'my.trusted.host',
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('my.trusted.host', $request->getServerHost());
+ }
+
+ public function testGetServerHostWithUntrustedDomain() {
+ $this->config
+ ->expects($this->at(3))
+ ->method('getSystemValue')
+ ->with('trusted_domains')
+ ->will($this->returnValue(['my.trusted.host']));
+ $this->config
+ ->expects($this->at(4))
+ ->method('getSystemValue')
+ ->with('trusted_domains')
+ ->will($this->returnValue(['my.trusted.host']));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTP_X_FORWARDED_HOST' => 'my.untrusted.host',
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('my.trusted.host', $request->getServerHost());
+ }
+
+ public function testGetServerHostWithNoTrustedDomain() {
+ $this->config
+ ->expects($this->at(3))
+ ->method('getSystemValue')
+ ->with('trusted_domains')
+ ->will($this->returnValue([]));
+ $this->config
+ ->expects($this->at(4))
+ ->method('getSystemValue')
+ ->with('trusted_domains')
+ ->will($this->returnValue([]));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'HTTP_X_FORWARDED_HOST' => 'my.untrusted.host',
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('', $request->getServerHost());
+ }
+
+ public function testGetOverwriteHostDefaultNull() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwritehost')
+ ->will($this->returnValue(''));
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertNull(self::invokePrivate($request, 'getOverwriteHost'));
+ }
+
+ public function testGetOverwriteHostWithOverwrite() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('overwritehost')
+ ->will($this->returnValue('www.owncloud.org'));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('overwritecondaddr')
+ ->will($this->returnValue(''));
+ $this->config
+ ->expects($this->at(2))
+ ->method('getSystemValue')
+ ->with('overwritehost')
+ ->will($this->returnValue('www.owncloud.org'));
+
+ $request = new Request(
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('www.owncloud.org', self::invokePrivate($request, 'getOverwriteHost'));
+ }
+
+ public function testGetPathInfoWithSetEnv() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'PATH_INFO' => 'apps/files/',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('apps/files/', $request->getPathInfo());
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage The requested uri(/foo.php) cannot be processed by the script '/var/www/index.php')
+ */
+ public function testGetPathInfoNotProcessible() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => '/foo.php',
+ 'SCRIPT_NAME' => '/var/www/index.php',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $request->getPathInfo();
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage The requested uri(/foo.php) cannot be processed by the script '/var/www/index.php')
+ */
+ public function testGetRawPathInfoNotProcessible() {
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => '/foo.php',
+ 'SCRIPT_NAME' => '/var/www/index.php',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $request->getRawPathInfo();
+ }
+
+ /**
+ * @dataProvider genericPathInfoProvider
+ * @param string $requestUri
+ * @param string $scriptName
+ * @param string $expected
+ */
+ public function testGetPathInfoWithoutSetEnvGeneric($requestUri, $scriptName, $expected) {
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => $requestUri,
+ 'SCRIPT_NAME' => $scriptName,
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame($expected, $request->getPathInfo());
+ }
+
+ /**
+ * @dataProvider genericPathInfoProvider
+ * @param string $requestUri
+ * @param string $scriptName
+ * @param string $expected
+ */
+ public function testGetRawPathInfoWithoutSetEnvGeneric($requestUri, $scriptName, $expected) {
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => $requestUri,
+ 'SCRIPT_NAME' => $scriptName,
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame($expected, $request->getRawPathInfo());
+ }
+
+ /**
+ * @dataProvider rawPathInfoProvider
+ * @param string $requestUri
+ * @param string $scriptName
+ * @param string $expected
+ */
+ public function testGetRawPathInfoWithoutSetEnv($requestUri, $scriptName, $expected) {
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => $requestUri,
+ 'SCRIPT_NAME' => $scriptName,
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame($expected, $request->getRawPathInfo());
+ }
+
+ /**
+ * @dataProvider pathInfoProvider
+ * @param string $requestUri
+ * @param string $scriptName
+ * @param string $expected
+ */
+ public function testGetPathInfoWithoutSetEnv($requestUri, $scriptName, $expected) {
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => $requestUri,
+ 'SCRIPT_NAME' => $scriptName,
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame($expected, $request->getPathInfo());
+ }
+
+ /**
+ * @return array
+ */
+ public function genericPathInfoProvider() {
+ return [
+ ['/core/index.php?XDEBUG_SESSION_START=14600', '/core/index.php', ''],
+ ['/index.php/apps/files/', 'index.php', '/apps/files/'],
+ ['/index.php/apps/files/../&amp;/&?someQueryParameter=QueryParam', 'index.php', '/apps/files/../&amp;/&'],
+ ['/remote.php/漢字編碼方法 / 汉字编码方法', 'remote.php', '/漢字編碼方法 / 汉字编码方法'],
+ ['///removeTrailin//gSlashes///', 'remote.php', '/removeTrailin/gSlashes/'],
+ ['/', '/', ''],
+ ['', '', ''],
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ public function rawPathInfoProvider() {
+ return [
+ ['/foo%2Fbar/subfolder', '', 'foo%2Fbar/subfolder'],
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ public function pathInfoProvider() {
+ return [
+ ['/foo%2Fbar/subfolder', '', 'foo/bar/subfolder'],
+ ];
+ }
+
+ public function testGetRequestUriWithoutOverwrite() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('overwritewebroot')
+ ->will($this->returnValue(''));
+
+ $request = new Request(
+ [
+ 'server' => [
+ 'REQUEST_URI' => '/test.php'
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ );
+
+ $this->assertSame('/test.php', $request->getRequestUri());
+ }
+
+ public function providesGetRequestUriWithOverwriteData() {
+ return [
+ ['/scriptname.php/some/PathInfo', '/owncloud/', ''],
+ ['/scriptname.php/some/PathInfo', '/owncloud/', '123'],
+ ];
+ }
+
+ /**
+ * @dataProvider providesGetRequestUriWithOverwriteData
+ */
+ public function testGetRequestUriWithOverwrite($expectedUri, $overwriteWebRoot, $overwriteCondAddr) {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('overwritewebroot')
+ ->will($this->returnValue($overwriteWebRoot));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('overwritecondaddr')
+ ->will($this->returnValue($overwriteCondAddr));
+
+ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
+ ->setMethods(['getScriptName'])
+ ->setConstructorArgs([
+ [
+ 'server' => [
+ 'REQUEST_URI' => '/test.php/some/PathInfo',
+ 'SCRIPT_NAME' => '/test.php',
+ ]
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ ])
+ ->getMock();
+ $request
+ ->expects($this->once())
+ ->method('getScriptName')
+ ->will($this->returnValue('/scriptname.php'));
+
+ $this->assertSame($expectedUri, $request->getRequestUri());
+ }
+
+ public function testPassesCSRFCheckWithGet() {
+ /** @var Request $request */
+ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
+ ->setMethods(['getScriptName'])
+ ->setConstructorArgs([
+ [
+ 'get' => [
+ 'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ ])
+ ->getMock();
+ $token = new CsrfToken('AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds');
+ $this->csrfTokenManager
+ ->expects($this->once())
+ ->method('isTokenValid')
+ ->with($token)
+ ->willReturn(true);
+
+ $this->assertTrue($request->passesCSRFCheck());
+ }
+
+ public function testPassesCSRFCheckWithPost() {
+ /** @var Request $request */
+ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
+ ->setMethods(['getScriptName'])
+ ->setConstructorArgs([
+ [
+ 'post' => [
+ 'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ ])
+ ->getMock();
+ $token = new CsrfToken('AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds');
+ $this->csrfTokenManager
+ ->expects($this->once())
+ ->method('isTokenValid')
+ ->with($token)
+ ->willReturn(true);
+
+ $this->assertTrue($request->passesCSRFCheck());
+ }
+
+ public function testPassesCSRFCheckWithHeader() {
+ /** @var Request $request */
+ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
+ ->setMethods(['getScriptName'])
+ ->setConstructorArgs([
+ [
+ 'server' => [
+ 'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ ])
+ ->getMock();
+ $token = new CsrfToken('AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds');
+ $this->csrfTokenManager
+ ->expects($this->once())
+ ->method('isTokenValid')
+ ->with($token)
+ ->willReturn(true);
+
+ $this->assertTrue($request->passesCSRFCheck());
+ }
+
+ /**
+ * @return array
+ */
+ public function invalidTokenDataProvider() {
+ return [
+ ['InvalidSentToken'],
+ ['InvalidSentToken:InvalidSecret'],
+ [null],
+ [''],
+ ];
+ }
+
+ /**
+ * @dataProvider invalidTokenDataProvider
+ * @param string $invalidToken
+ */
+ public function testPassesCSRFCheckWithInvalidToken($invalidToken) {
+ /** @var Request $request */
+ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
+ ->setMethods(['getScriptName'])
+ ->setConstructorArgs([
+ [
+ 'server' => [
+ 'HTTP_REQUESTTOKEN' => $invalidToken,
+ ],
+ ],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ ])
+ ->getMock();
+
+ $token = new CsrfToken($invalidToken);
+ $this->csrfTokenManager
+ ->expects($this->any())
+ ->method('isTokenValid')
+ ->with($token)
+ ->willReturn(false);
+
+ $this->assertFalse($request->passesCSRFCheck());
+ }
+
+ public function testPassesCSRFCheckWithoutTokenFail() {
+ /** @var Request $request */
+ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
+ ->setMethods(['getScriptName'])
+ ->setConstructorArgs([
+ [],
+ $this->secureRandom,
+ $this->config,
+ $this->csrfTokenManager,
+ $this->stream
+ ])
+ ->getMock();
+
+ $this->assertFalse($request->passesCSRFCheck());
+ }
+
+}