diff options
Diffstat (limited to 'tests/lib/AppFramework/Http')
-rw-r--r-- | tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php | 429 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/DataResponseTest.php | 91 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/DispatcherTest.php | 466 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/DownloadResponseTest.php | 56 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php | 430 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/HttpTest.php | 99 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/JSONResponseTest.php | 123 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/OCSResponseTest.php | 72 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/RedirectResponseTest.php | 57 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/RequestStream.php | 110 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/RequestTest.php | 1453 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/ResponseTest.php | 267 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/StreamResponseTest.php | 100 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/TemplateResponseTest.php | 99 |
14 files changed, 3852 insertions, 0 deletions
diff --git a/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php b/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php new file mode 100644 index 00000000000..82f2b3873b7 --- /dev/null +++ b/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php @@ -0,0 +1,429 @@ +<?php +/** + * Copyright (c) 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 OCP\AppFramework\Http; +use OCP\AppFramework\Http\ContentSecurityPolicy; + +/** + * Class ContentSecurityPolicyTest + * + * @package OC\AppFramework\Http + */ +class ContentSecurityPolicyTest extends \Test\TestCase { + + /** @var ContentSecurityPolicy */ + private $contentSecurityPolicy; + + public function setUp() { + parent::setUp(); + $this->contentSecurityPolicy = new ContentSecurityPolicy(); + } + + public function testGetPolicyDefault() { + $defaultPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $this->assertSame($defaultPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com www.owncloud.org 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowScriptDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowScriptDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowScriptDomainMultipleStacked() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org')->disallowScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInline() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInlineWithDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->allowInlineScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDisallowInlineAndEval() { + $expectedPolicy = "default-src 'none';script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineScript(false); + $this->contentSecurityPolicy->allowEvalScript(false); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com www.owncloud.org 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowStyleDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowStyleDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowStyleDomainMultipleStacked() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org')->disallowStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleAllowInline() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineStyle(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleAllowInlineWithDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDisallowInline() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineStyle(false); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyImageDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyImageDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com www.owncloud.org;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowImageDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowImageDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowImageDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org')->disallowImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFontDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFontDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com www.owncloud.org;connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFontDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFontDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFontDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org')->disallowFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyConnectDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyConnectDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com www.owncloud.org;media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowConnectDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowConnectDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowConnectDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org')->disallowConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyMediaDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyMediaDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowMediaDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowMediaDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowMediaDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org')->disallowMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyObjectDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyObjectDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowObjectDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowObjectDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowObjectDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org')->disallowObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetAllowedFrameDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFrameDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFrameDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFrameDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFrameDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org')->disallowFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetAllowedChildSrcDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyChildSrcValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com child.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowChildSrcDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowChildSrcDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowChildSrcDomainMultipleStakes() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org')->disallowChildSrcDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } +} diff --git a/tests/lib/AppFramework/Http/DataResponseTest.php b/tests/lib/AppFramework/Http/DataResponseTest.php new file mode 100644 index 00000000000..cde553cdf5f --- /dev/null +++ b/tests/lib/AppFramework/Http/DataResponseTest.php @@ -0,0 +1,91 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2014 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + + +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http; + + +class DataResponseTest extends \Test\TestCase { + + /** + * @var DataResponse + */ + private $response; + + protected function setUp() { + parent::setUp(); + $this->response = new DataResponse(); + } + + + public function testSetData() { + $params = array('hi', 'yo'); + $this->response->setData($params); + + $this->assertEquals(array('hi', 'yo'), $this->response->getData()); + } + + + public function testConstructorAllowsToSetData() { + $data = array('hi'); + $code = 300; + $response = new DataResponse($data, $code); + + $this->assertEquals($data, $response->getData()); + $this->assertEquals($code, $response->getStatus()); + } + + + public function testConstructorAllowsToSetHeaders() { + $data = array('hi'); + $code = 300; + $headers = array('test' => 'something'); + $response = new DataResponse($data, $code, $headers); + + $expectedHeaders = [ + 'Cache-Control' => 'no-cache, must-revalidate', + 'Content-Security-Policy' => "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'", + ]; + $expectedHeaders = array_merge($expectedHeaders, $headers); + + $this->assertEquals($data, $response->getData()); + $this->assertEquals($code, $response->getStatus()); + $this->assertEquals($expectedHeaders, $response->getHeaders()); + } + + + public function testChainability() { + $params = array('hi', 'yo'); + $this->response->setData($params) + ->setStatus(Http::STATUS_NOT_FOUND); + + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->response->getStatus()); + $this->assertEquals(array('hi', 'yo'), $this->response->getData()); + } + + +} diff --git a/tests/lib/AppFramework/Http/DispatcherTest.php b/tests/lib/AppFramework/Http/DispatcherTest.php new file mode 100644 index 00000000000..6df6f7fa7fe --- /dev/null +++ b/tests/lib/AppFramework/Http/DispatcherTest.php @@ -0,0 +1,466 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + +use OC\AppFramework\Http\Dispatcher; +use OC\AppFramework\Http\Request; +use OC\AppFramework\Utility\ControllerMethodReflector; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Controller; + + +class TestController extends Controller { + /** + * @param string $appName + * @param \OCP\IRequest $request + */ + public function __construct($appName, $request) { + parent::__construct($appName, $request); + } + + /** + * @param int $int + * @param bool $bool + * @param int $test + * @param int $test2 + * @return array + */ + public function exec($int, $bool, $test=4, $test2=1) { + $this->registerResponder('text', function($in) { + return new JSONResponse(array('text' => $in)); + }); + return array($int, $bool, $test, $test2); + } + + + /** + * @param int $int + * @param bool $bool + * @param int $test + * @param int $test2 + * @return DataResponse + */ + public function execDataResponse($int, $bool, $test=4, $test2=1) { + return new DataResponse(array( + 'text' => array($int, $bool, $test, $test2) + )); + } + +} + + +class DispatcherTest extends \Test\TestCase { + private $middlewareDispatcher; + private $dispatcher; + private $controllerMethod; + private $response; + private $request; + private $lastModified; + private $etag; + private $http; + private $reflector; + + protected function setUp() { + parent::setUp(); + $this->controllerMethod = 'test'; + + $app = $this->getMockBuilder( + 'OC\AppFramework\DependencyInjection\DIContainer') + ->disableOriginalConstructor() + ->getMock(); + $request = $this->getMockBuilder( + '\OC\AppFramework\Http\Request') + ->disableOriginalConstructor() + ->getMock(); + $this->http = $this->getMockBuilder( + '\OC\AppFramework\Http') + ->disableOriginalConstructor() + ->getMock(); + + $this->middlewareDispatcher = $this->getMockBuilder( + '\OC\AppFramework\Middleware\MiddlewareDispatcher') + ->disableOriginalConstructor() + ->getMock(); + $this->controller = $this->getMock( + '\OCP\AppFramework\Controller', + array($this->controllerMethod), array($app, $request)); + + $this->request = $this->getMockBuilder( + '\OC\AppFramework\Http\Request') + ->disableOriginalConstructor() + ->getMock(); + + $this->reflector = new ControllerMethodReflector(); + + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + + $this->response = $this->getMockBuilder( + '\OCP\AppFramework\Http\Response') + ->disableOriginalConstructor() + ->getMock(); + + $this->lastModified = new \DateTime(null, new \DateTimeZone('GMT')); + $this->etag = 'hi'; + } + + + /** + * @param string $out + * @param string $httpHeaders + */ + private function setMiddlewareExpectations($out=null, + $httpHeaders=null, $responseHeaders=array(), + $ex=false, $catchEx=true) { + + if($ex) { + $exception = new \Exception(); + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeController') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod)) + ->will($this->throwException($exception)); + if($catchEx) { + $this->middlewareDispatcher->expects($this->once()) + ->method('afterException') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod), + $this->equalTo($exception)) + ->will($this->returnValue($this->response)); + } else { + $this->middlewareDispatcher->expects($this->once()) + ->method('afterException') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod), + $this->equalTo($exception)) + ->will($this->returnValue(null)); + return; + } + } else { + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeController') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod)); + $this->controller->expects($this->once()) + ->method($this->controllerMethod) + ->will($this->returnValue($this->response)); + } + + $this->response->expects($this->once()) + ->method('render') + ->will($this->returnValue($out)); + $this->response->expects($this->once()) + ->method('getStatus') + ->will($this->returnValue(Http::STATUS_OK)); + $this->response->expects($this->once()) + ->method('getLastModified') + ->will($this->returnValue($this->lastModified)); + $this->response->expects($this->once()) + ->method('getETag') + ->will($this->returnValue($this->etag)); + $this->response->expects($this->once()) + ->method('getHeaders') + ->will($this->returnValue($responseHeaders)); + $this->http->expects($this->once()) + ->method('getStatusHeader') + ->with($this->equalTo(Http::STATUS_OK), + $this->equalTo($this->lastModified), + $this->equalTo($this->etag)) + ->will($this->returnValue($httpHeaders)); + + $this->middlewareDispatcher->expects($this->once()) + ->method('afterController') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod), + $this->equalTo($this->response)) + ->will($this->returnValue($this->response)); + + $this->middlewareDispatcher->expects($this->once()) + ->method('afterController') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod), + $this->equalTo($this->response)) + ->will($this->returnValue($this->response)); + + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeOutput') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod), + $this->equalTo($out)) + ->will($this->returnValue($out)); + } + + + public function testDispatcherReturnsArrayWith2Entries() { + $this->setMiddlewareExpectations(); + + $response = $this->dispatcher->dispatch($this->controller, + $this->controllerMethod); + $this->assertNull($response[0]); + $this->assertEquals(array(), $response[1]); + $this->assertNull($response[2]); + } + + + public function testHeadersAndOutputAreReturned(){ + $out = 'yo'; + $httpHeaders = 'Http'; + $responseHeaders = array('hell' => 'yeah'); + $this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders); + + $response = $this->dispatcher->dispatch($this->controller, + $this->controllerMethod); + + $this->assertEquals($httpHeaders, $response[0]); + $this->assertEquals($responseHeaders, $response[1]); + $this->assertEquals($out, $response[3]); + } + + + public function testExceptionCallsAfterException() { + $out = 'yo'; + $httpHeaders = 'Http'; + $responseHeaders = array('hell' => 'yeah'); + $this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true); + + $response = $this->dispatcher->dispatch($this->controller, + $this->controllerMethod); + + $this->assertEquals($httpHeaders, $response[0]); + $this->assertEquals($responseHeaders, $response[1]); + $this->assertEquals($out, $response[3]); + } + + + public function testExceptionThrowsIfCanNotBeHandledByAfterException() { + $out = 'yo'; + $httpHeaders = 'Http'; + $responseHeaders = array('hell' => 'yeah'); + $this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true, false); + + $this->setExpectedException('\Exception'); + $response = $this->dispatcher->dispatch($this->controller, + $this->controllerMethod); + + } + + + private function dispatcherPassthrough() { + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeController'); + $this->middlewareDispatcher->expects($this->once()) + ->method('afterController') + ->will($this->returnCallback(function($a, $b, $in) { + return $in; + })); + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeOutput') + ->will($this->returnCallback(function($a, $b, $in) { + return $in; + })); + } + + + public function testControllerParametersInjected() { + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'method' => 'POST' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('[3,true,4,1]', $response[3]); + } + + + public function testControllerParametersInjectedDefaultOverwritten() { + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false', + 'test2' => 7 + ], + 'method' => 'POST', + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('[3,true,4,7]', $response[3]); + } + + + + public function testResponseTransformedByUrlFormat() { + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'urlParams' => [ + 'format' => 'text' + ], + 'method' => 'GET' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('{"text":[3,false,4,1]}', $response[3]); + } + + + public function testResponseTransformsDataResponse() { + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'urlParams' => [ + 'format' => 'json' + ], + 'method' => 'GET' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'execDataResponse'); + + $this->assertEquals('{"text":[3,false,4,1]}', $response[3]); + } + + + public function testResponseTransformedByAcceptHeader() { + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'server' => [ + 'HTTP_ACCEPT' => 'application/text, test', + 'HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded' + ], + 'method' => 'PUT' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('{"text":[3,false,4,1]}', $response[3]); + } + + + public function testResponsePrimarilyTransformedByParameterFormat() { + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'get' => [ + 'format' => 'text' + ], + 'server' => [ + 'HTTP_ACCEPT' => 'application/json, test' + ], + 'method' => 'POST' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('{"text":[3,true,4,1]}', $response[3]); + } + + + + +} diff --git a/tests/lib/AppFramework/Http/DownloadResponseTest.php b/tests/lib/AppFramework/Http/DownloadResponseTest.php new file mode 100644 index 00000000000..07c932b2725 --- /dev/null +++ b/tests/lib/AppFramework/Http/DownloadResponseTest.php @@ -0,0 +1,56 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + + +use OCP\AppFramework\Http\DownloadResponse; + +class ChildDownloadResponse extends DownloadResponse { + +}; + + +class DownloadResponseTest extends \Test\TestCase { + + /** + * @var ChildDownloadResponse + */ + protected $response; + + protected function setUp(){ + parent::setUp(); + $this->response = new ChildDownloadResponse('file', 'content'); + } + + + public function testHeaders() { + $headers = $this->response->getHeaders(); + + $this->assertContains('attachment; filename="file"', $headers['Content-Disposition']); + $this->assertContains('content', $headers['Content-Type']); + } + + +} diff --git a/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php b/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php new file mode 100644 index 00000000000..248c3d808d2 --- /dev/null +++ b/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php @@ -0,0 +1,430 @@ +<?php +/** + * Copyright (c) 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 OCP\AppFramework\Http; +use OCP\AppFramework\Http\EmptyContentSecurityPolicy; + +/** + * Class ContentSecurityPolicyTest + * + * @package OC\AppFramework\Http + */ +class EmptyContentSecurityPolicyTest extends \Test\TestCase { + + /** @var EmptyContentSecurityPolicy */ + private $contentSecurityPolicy; + + public function setUp() { + parent::setUp(); + $this->contentSecurityPolicy = new EmptyContentSecurityPolicy(); + } + + public function testGetPolicyDefault() { + $defaultPolicy = "default-src 'none'"; + $this->assertSame($defaultPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDomainValid() { + $expectedPolicy = "default-src 'none';script-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowScriptDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowScriptDomainMultiple() { + $expectedPolicy = "default-src 'none';script-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowScriptDomainMultipleStacked() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org')->disallowScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInline() { + $expectedPolicy = "default-src 'none';script-src 'unsafe-inline'"; + + $this->contentSecurityPolicy->allowInlineScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInlineWithDomain() { + $expectedPolicy = "default-src 'none';script-src www.owncloud.com 'unsafe-inline'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->allowInlineScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInlineAndEval() { + $expectedPolicy = "default-src 'none';script-src 'unsafe-inline' 'unsafe-eval'"; + + $this->contentSecurityPolicy->allowInlineScript(true); + $this->contentSecurityPolicy->allowEvalScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDomainValid() { + $expectedPolicy = "default-src 'none';style-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDomainValidMultiple() { + $expectedPolicy = "default-src 'none';style-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowStyleDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowStyleDomainMultiple() { + $expectedPolicy = "default-src 'none';style-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowStyleDomainMultipleStacked() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org')->disallowStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleAllowInline() { + $expectedPolicy = "default-src 'none';style-src 'unsafe-inline'"; + + $this->contentSecurityPolicy->allowInlineStyle(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleAllowInlineWithDomain() { + $expectedPolicy = "default-src 'none';style-src www.owncloud.com 'unsafe-inline'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->allowInlineStyle(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDisallowInline() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->allowInlineStyle(false); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyImageDomainValid() { + $expectedPolicy = "default-src 'none';img-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyImageDomainValidMultiple() { + $expectedPolicy = "default-src 'none';img-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowImageDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowImageDomainMultiple() { + $expectedPolicy = "default-src 'none';img-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowImageDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org')->disallowImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFontDomainValid() { + $expectedPolicy = "default-src 'none';font-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFontDomainValidMultiple() { + $expectedPolicy = "default-src 'none';font-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFontDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFontDomainMultiple() { + $expectedPolicy = "default-src 'none';font-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFontDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org')->disallowFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyConnectDomainValid() { + $expectedPolicy = "default-src 'none';connect-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyConnectDomainValidMultiple() { + $expectedPolicy = "default-src 'none';connect-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowConnectDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowConnectDomainMultiple() { + $expectedPolicy = "default-src 'none';connect-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowConnectDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org')->disallowConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyMediaDomainValid() { + $expectedPolicy = "default-src 'none';media-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyMediaDomainValidMultiple() { + $expectedPolicy = "default-src 'none';media-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowMediaDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowMediaDomainMultiple() { + $expectedPolicy = "default-src 'none';media-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowMediaDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org')->disallowMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyObjectDomainValid() { + $expectedPolicy = "default-src 'none';object-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyObjectDomainValidMultiple() { + $expectedPolicy = "default-src 'none';object-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowObjectDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowObjectDomainMultiple() { + $expectedPolicy = "default-src 'none';object-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowObjectDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org')->disallowObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetAllowedFrameDomain() { + $expectedPolicy = "default-src 'none';frame-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFrameDomainValidMultiple() { + $expectedPolicy = "default-src 'none';frame-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFrameDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFrameDomainMultiple() { + $expectedPolicy = "default-src 'none';frame-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowFrameDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org')->disallowFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetAllowedChildSrcDomain() { + $expectedPolicy = "default-src 'none';child-src child.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyChildSrcValidMultiple() { + $expectedPolicy = "default-src 'none';child-src child.owncloud.com child.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowChildSrcDomain() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowChildSrcDomainMultiple() { + $expectedPolicy = "default-src 'none';child-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyDisallowChildSrcDomainMultipleStakes() { + $expectedPolicy = "default-src 'none'"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); + $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org')->disallowChildSrcDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } +} diff --git a/tests/lib/AppFramework/Http/HttpTest.php b/tests/lib/AppFramework/Http/HttpTest.php new file mode 100644 index 00000000000..66256d1a86f --- /dev/null +++ b/tests/lib/AppFramework/Http/HttpTest.php @@ -0,0 +1,99 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + +use OC\AppFramework\Http; + + +class HttpTest extends \Test\TestCase { + + private $server; + + /** + * @var Http + */ + private $http; + + protected function setUp(){ + parent::setUp(); + + $this->server = array(); + $this->http = new Http($this->server); + } + + + public function testProtocol() { + $header = $this->http->getStatusHeader(Http::STATUS_TEMPORARY_REDIRECT); + $this->assertEquals('HTTP/1.1 307 Temporary Redirect', $header); + } + + + public function testProtocol10() { + $this->http = new Http($this->server, 'HTTP/1.0'); + $header = $this->http->getStatusHeader(Http::STATUS_OK); + $this->assertEquals('HTTP/1.0 200 OK', $header); + } + + + public function testEtagMatchReturnsNotModified() { + $http = new Http(array('HTTP_IF_NONE_MATCH' => 'hi')); + + $header = $http->getStatusHeader(Http::STATUS_OK, null, 'hi'); + $this->assertEquals('HTTP/1.1 304 Not Modified', $header); + } + + + public function testQuotedEtagMatchReturnsNotModified() { + $http = new Http(array('HTTP_IF_NONE_MATCH' => '"hi"')); + + $header = $http->getStatusHeader(Http::STATUS_OK, null, 'hi'); + $this->assertEquals('HTTP/1.1 304 Not Modified', $header); + } + + + public function testLastModifiedMatchReturnsNotModified() { + $dateTime = new \DateTime(null, new \DateTimeZone('GMT')); + $dateTime->setTimestamp('12'); + + $http = new Http( + array( + 'HTTP_IF_MODIFIED_SINCE' => 'Thu, 01 Jan 1970 00:00:12 +0000') + ); + + $header = $http->getStatusHeader(Http::STATUS_OK, $dateTime); + $this->assertEquals('HTTP/1.1 304 Not Modified', $header); + } + + + + public function testTempRedirectBecomesFoundInHttp10() { + $http = new Http(array(), 'HTTP/1.0'); + + $header = $http->getStatusHeader(Http::STATUS_TEMPORARY_REDIRECT); + $this->assertEquals('HTTP/1.0 302 Found', $header); + } + // TODO: write unittests for http codes + +} diff --git a/tests/lib/AppFramework/Http/JSONResponseTest.php b/tests/lib/AppFramework/Http/JSONResponseTest.php new file mode 100644 index 00000000000..23a55e7eee8 --- /dev/null +++ b/tests/lib/AppFramework/Http/JSONResponseTest.php @@ -0,0 +1,123 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @author Morris Jobke + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * @copyright 2013 Morris Jobke <morris.jobke@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + + +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http; + +class JSONResponseTest extends \Test\TestCase { + + /** + * @var JSONResponse + */ + private $json; + + protected function setUp() { + parent::setUp(); + $this->json = new JSONResponse(); + } + + + public function testHeader() { + $headers = $this->json->getHeaders(); + $this->assertEquals('application/json; charset=utf-8', $headers['Content-Type']); + } + + + public function testSetData() { + $params = array('hi', 'yo'); + $this->json->setData($params); + + $this->assertEquals(array('hi', 'yo'), $this->json->getData()); + } + + + public function testSetRender() { + $params = array('test' => 'hi'); + $this->json->setData($params); + + $expected = '{"test":"hi"}'; + + $this->assertEquals($expected, $this->json->render()); + } + + /** + * @return array + */ + public function renderDataProvider() { + return [ + [ + ['test' => 'hi'], '{"test":"hi"}', + ], + [ + ['<h1>test' => '<h1>hi'], '{"\u003Ch1\u003Etest":"\u003Ch1\u003Ehi"}', + ], + ]; + } + + /** + * @dataProvider renderDataProvider + * @param array $input + * @param string $expected + */ + public function testRender(array $input, $expected) { + $this->json->setData($input); + $this->assertEquals($expected, $this->json->render()); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Could not json_encode due to invalid non UTF-8 characters in the array: array ( + * @requires PHP 5.5 + */ + public function testRenderWithNonUtf8Encoding() { + $params = ['test' => hex2bin('e9')]; + $this->json->setData($params); + $this->json->render(); + } + + public function testConstructorAllowsToSetData() { + $data = array('hi'); + $code = 300; + $response = new JSONResponse($data, $code); + + $expected = '["hi"]'; + $this->assertEquals($expected, $response->render()); + $this->assertEquals($code, $response->getStatus()); + } + + public function testChainability() { + $params = array('hi', 'yo'); + $this->json->setData($params) + ->setStatus(Http::STATUS_NOT_FOUND); + + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->json->getStatus()); + $this->assertEquals(array('hi', 'yo'), $this->json->getData()); + } + +} diff --git a/tests/lib/AppFramework/Http/OCSResponseTest.php b/tests/lib/AppFramework/Http/OCSResponseTest.php new file mode 100644 index 00000000000..adac66a231c --- /dev/null +++ b/tests/lib/AppFramework/Http/OCSResponseTest.php @@ -0,0 +1,72 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + + +use OCP\AppFramework\Http\OCSResponse; + + +class OCSResponseTest extends \Test\TestCase { + + + public function testHeadersJSON() { + $response = new OCSResponse('json', 1, 2, 3); + $type = $response->getHeaders()['Content-Type']; + $this->assertEquals('application/json; charset=utf-8', $type); + } + + + public function testHeadersXML() { + $response = new OCSResponse('xml', 1, 2, 3); + $type = $response->getHeaders()['Content-Type']; + $this->assertEquals('application/xml; charset=utf-8', $type); + } + + + public function testRender() { + $response = new OCSResponse( + 'xml', 2, 'message', ['test' => 'hi'], 3, 4 + ); + $out = $response->render(); + $expected = "<?xml version=\"1.0\"?>\n" . + "<ocs>\n" . + " <meta>\n" . + " <status>failure</status>\n" . + " <statuscode>2</statuscode>\n" . + " <message>message</message>\n" . + " <totalitems>3</totalitems>\n" . + " <itemsperpage>4</itemsperpage>\n" . + " </meta>\n" . + " <data>\n" . + " <test>hi</test>\n" . + " </data>\n" . + "</ocs>\n"; + + $this->assertEquals($expected, $out); + + } + + +} diff --git a/tests/lib/AppFramework/Http/RedirectResponseTest.php b/tests/lib/AppFramework/Http/RedirectResponseTest.php new file mode 100644 index 00000000000..5ef82a1221d --- /dev/null +++ b/tests/lib/AppFramework/Http/RedirectResponseTest.php @@ -0,0 +1,57 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\RedirectResponse; + + +class RedirectResponseTest extends \Test\TestCase { + + /** + * @var RedirectResponse + */ + protected $response; + + protected function setUp(){ + parent::setUp(); + $this->response = new RedirectResponse('/url'); + } + + + public function testHeaders() { + $headers = $this->response->getHeaders(); + $this->assertEquals('/url', $headers['Location']); + $this->assertEquals(Http::STATUS_SEE_OTHER, + $this->response->getStatus()); + } + + + public function testGetRedirectUrl(){ + $this->assertEquals('/url', $this->response->getRedirectUrl()); + } + + +} diff --git a/tests/lib/AppFramework/Http/RequestStream.php b/tests/lib/AppFramework/Http/RequestStream.php new file mode 100644 index 00000000000..8f6dffd4e91 --- /dev/null +++ b/tests/lib/AppFramework/Http/RequestStream.php @@ -0,0 +1,110 @@ +<?php + +namespace Test\AppFramework\Http; + +/** + * Copy of http://dk1.php.net/manual/en/stream.streamwrapper.example-1.php + * Used to simulate php://input for Request tests + */ +class RequestStream { + protected $position; + protected $varname; + + function stream_open($path, $mode, $options, &$opened_path) { + $url = parse_url($path); + $this->varname = $url["host"]; + $this->position = 0; + + return true; + } + + function stream_read($count) { + $ret = substr($GLOBALS[$this->varname], $this->position, $count); + $this->position += strlen($ret); + return $ret; + } + + function stream_write($data) { + $left = substr($GLOBALS[$this->varname], 0, $this->position); + $right = substr($GLOBALS[$this->varname], $this->position + strlen($data)); + $GLOBALS[$this->varname] = $left . $data . $right; + $this->position += strlen($data); + return strlen($data); + } + + function stream_tell() { + return $this->position; + } + + function stream_eof() { + return $this->position >= strlen($GLOBALS[$this->varname]); + } + + function stream_seek($offset, $whence) { + switch ($whence) { + case SEEK_SET: + if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) { + $this->position = $offset; + return true; + } else { + return false; + } + break; + + case SEEK_CUR: + if ($offset >= 0) { + $this->position += $offset; + return true; + } else { + return false; + } + break; + + case SEEK_END: + if (strlen($GLOBALS[$this->varname]) + $offset >= 0) { + $this->position = strlen($GLOBALS[$this->varname]) + $offset; + return true; + } else { + return false; + } + break; + + default: + return false; + } + } + + public function stream_stat() { + $size = strlen($GLOBALS[$this->varname]); + $time = time(); + $data = array( + 'dev' => 0, + 'ino' => 0, + 'mode' => 0777, + 'nlink' => 1, + 'uid' => 0, + 'gid' => 0, + 'rdev' => '', + 'size' => $size, + 'atime' => $time, + 'mtime' => $time, + 'ctime' => $time, + 'blksize' => -1, + 'blocks' => -1, + ); + return array_values($data) + $data; + //return false; + } + + function stream_metadata($path, $option, $var) { + if($option == STREAM_META_TOUCH) { + $url = parse_url($path); + $varname = $url["host"]; + if(!isset($GLOBALS[$varname])) { + $GLOBALS[$varname] = ''; + } + return true; + } + return false; + } +} 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/../&/&?someQueryParameter=QueryParam', 'index.php', '/apps/files/../&/&'], + ['/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()); + } + +} diff --git a/tests/lib/AppFramework/Http/ResponseTest.php b/tests/lib/AppFramework/Http/ResponseTest.php new file mode 100644 index 00000000000..0c582f8f6ea --- /dev/null +++ b/tests/lib/AppFramework/Http/ResponseTest.php @@ -0,0 +1,267 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + + +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http; + + +class ResponseTest extends \Test\TestCase { + + /** + * @var \OCP\AppFramework\Http\Response + */ + private $childResponse; + + protected function setUp(){ + parent::setUp(); + $this->childResponse = new Response(); + } + + + public function testAddHeader(){ + $this->childResponse->addHeader(' hello ', 'world'); + $headers = $this->childResponse->getHeaders(); + $this->assertEquals('world', $headers['hello']); + } + + + public function testSetHeaders() { + $expected = array( + 'Last-Modified' => 1, + 'ETag' => 3, + 'Something-Else' => 'hi' + ); + + $this->childResponse->setHeaders($expected); + $headers = $this->childResponse->getHeaders(); + $expected['Content-Security-Policy'] = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->assertEquals($expected, $headers); + } + + public function testOverwriteCsp() { + $expected = [ + 'Content-Security-Policy' => "default-src 'none';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'", + ]; + $policy = new Http\ContentSecurityPolicy(); + $policy->allowInlineScript(true); + + $this->childResponse->setContentSecurityPolicy($policy); + $headers = $this->childResponse->getHeaders(); + + $this->assertEquals(array_merge($expected, $headers), $headers); + } + + public function testGetCsp() { + $policy = new Http\ContentSecurityPolicy(); + $policy->allowInlineScript(true); + + $this->childResponse->setContentSecurityPolicy($policy); + $this->assertEquals($policy, $this->childResponse->getContentSecurityPolicy()); + } + + public function testGetCspEmpty() { + $this->assertNull($this->childResponse->getContentSecurityPolicy()); + } + + public function testAddHeaderValueNullDeletesIt(){ + $this->childResponse->addHeader('hello', 'world'); + $this->childResponse->addHeader('hello', null); + $this->assertEquals(2, count($this->childResponse->getHeaders())); + } + + + public function testCacheHeadersAreDisabledByDefault(){ + $headers = $this->childResponse->getHeaders(); + $this->assertEquals('no-cache, must-revalidate', $headers['Cache-Control']); + } + + + public function testAddCookie() { + $this->childResponse->addCookie('foo', 'bar'); + $this->childResponse->addCookie('bar', 'foo', new \DateTime('1970-01-01')); + + $expectedResponse = array( + 'foo' => array( + 'value' => 'bar', + 'expireDate' => null, + ), + 'bar' => array( + 'value' => 'foo', + 'expireDate' => new \DateTime('1970-01-01') + ) + ); + $this->assertEquals($expectedResponse, $this->childResponse->getCookies()); + } + + + function testSetCookies() { + $expected = array( + 'foo' => array( + 'value' => 'bar', + 'expireDate' => null, + ), + 'bar' => array( + 'value' => 'foo', + 'expireDate' => new \DateTime('1970-01-01') + ) + ); + + $this->childResponse->setCookies($expected); + $cookies = $this->childResponse->getCookies(); + + $this->assertEquals($expected, $cookies); + } + + + function testInvalidateCookie() { + $this->childResponse->addCookie('foo', 'bar'); + $this->childResponse->invalidateCookie('foo'); + $expected = array( + 'foo' => array( + 'value' => 'expired', + 'expireDate' => new \DateTime('1971-01-01') + ) + ); + + $cookies = $this->childResponse->getCookies(); + + $this->assertEquals($expected, $cookies); + } + + + function testInvalidateCookies() { + $this->childResponse->addCookie('foo', 'bar'); + $this->childResponse->addCookie('bar', 'foo'); + $expected = array( + 'foo' => array( + 'value' => 'bar', + 'expireDate' => null + ), + 'bar' => array( + 'value' => 'foo', + 'expireDate' => null + ) + ); + $cookies = $this->childResponse->getCookies(); + $this->assertEquals($expected, $cookies); + + $this->childResponse->invalidateCookies(array('foo', 'bar')); + $expected = array( + 'foo' => array( + 'value' => 'expired', + 'expireDate' => new \DateTime('1971-01-01') + ), + 'bar' => array( + 'value' => 'expired', + 'expireDate' => new \DateTime('1971-01-01') + ) + ); + + $cookies = $this->childResponse->getCookies(); + $this->assertEquals($expected, $cookies); + } + + + public function testRenderReturnNullByDefault(){ + $this->assertEquals(null, $this->childResponse->render()); + } + + + public function testGetStatus() { + $default = $this->childResponse->getStatus(); + + $this->childResponse->setStatus(Http::STATUS_NOT_FOUND); + + $this->assertEquals(Http::STATUS_OK, $default); + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->childResponse->getStatus()); + } + + + public function testGetEtag() { + $this->childResponse->setEtag('hi'); + $this->assertSame('hi', $this->childResponse->getEtag()); + } + + + public function testGetLastModified() { + $lastModified = new \DateTime(null, new \DateTimeZone('GMT')); + $lastModified->setTimestamp(1); + $this->childResponse->setLastModified($lastModified); + $this->assertEquals($lastModified, $this->childResponse->getLastModified()); + } + + + + public function testCacheSecondsZero() { + $this->childResponse->cacheFor(0); + + $headers = $this->childResponse->getHeaders(); + $this->assertEquals('no-cache, no-store, must-revalidate', $headers['Cache-Control']); + } + + + public function testCacheSeconds() { + $this->childResponse->cacheFor(33); + + $headers = $this->childResponse->getHeaders(); + $this->assertEquals('max-age=33, must-revalidate', + $headers['Cache-Control']); + } + + + + public function testEtagLastModifiedHeaders() { + $lastModified = new \DateTime(null, new \DateTimeZone('GMT')); + $lastModified->setTimestamp(1); + $this->childResponse->setLastModified($lastModified); + $headers = $this->childResponse->getHeaders(); + $this->assertEquals('Thu, 01 Jan 1970 00:00:01 +0000', $headers['Last-Modified']); + } + + public function testChainability() { + $lastModified = new \DateTime(null, new \DateTimeZone('GMT')); + $lastModified->setTimestamp(1); + + $this->childResponse->setEtag('hi') + ->setStatus(Http::STATUS_NOT_FOUND) + ->setLastModified($lastModified) + ->cacheFor(33) + ->addHeader('hello', 'world'); + + $headers = $this->childResponse->getHeaders(); + + $this->assertEquals('world', $headers['hello']); + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->childResponse->getStatus()); + $this->assertEquals('hi', $this->childResponse->getEtag()); + $this->assertEquals('Thu, 01 Jan 1970 00:00:01 +0000', $headers['Last-Modified']); + $this->assertEquals('max-age=33, must-revalidate', + $headers['Cache-Control']); + + } + +} diff --git a/tests/lib/AppFramework/Http/StreamResponseTest.php b/tests/lib/AppFramework/Http/StreamResponseTest.php new file mode 100644 index 00000000000..1f761d6b89c --- /dev/null +++ b/tests/lib/AppFramework/Http/StreamResponseTest.php @@ -0,0 +1,100 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + + +use OCP\AppFramework\Http\StreamResponse; +use OCP\AppFramework\Http\IOutput; +use OCP\AppFramework\Http; + + +class StreamResponseTest extends \Test\TestCase { + + /** @var IOutput */ + private $output; + + protected function setUp() { + parent::setUp(); + $this->output = $this->getMock('OCP\\AppFramework\\Http\\IOutput'); + } + + public function testOutputNotModified(){ + $path = __FILE__; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_NOT_MODIFIED)); + $this->output->expects($this->never()) + ->method('setReadfile'); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + + public function testOutputOk(){ + $path = __FILE__; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_OK)); + $this->output->expects($this->once()) + ->method('setReadfile') + ->with($this->equalTo($path)) + ->will($this->returnValue(true)); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + + public function testOutputNotFound(){ + $path = __FILE__ . 'test'; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_OK)); + $this->output->expects($this->never()) + ->method('setReadfile'); + $this->output->expects($this->once()) + ->method('setHttpResponseCode') + ->with($this->equalTo(Http::STATUS_NOT_FOUND)); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + + public function testOutputReadFileError(){ + $path = __FILE__; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_OK)); + $this->output->expects($this->once()) + ->method('setReadfile') + ->will($this->returnValue(false)); + $this->output->expects($this->once()) + ->method('setHttpResponseCode') + ->with($this->equalTo(Http::STATUS_BAD_REQUEST)); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + +} diff --git a/tests/lib/AppFramework/Http/TemplateResponseTest.php b/tests/lib/AppFramework/Http/TemplateResponseTest.php new file mode 100644 index 00000000000..87fb6864f78 --- /dev/null +++ b/tests/lib/AppFramework/Http/TemplateResponseTest.php @@ -0,0 +1,99 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace Test\AppFramework\Http; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Http; + + +class TemplateResponseTest extends \Test\TestCase { + + /** + * @var \OCP\AppFramework\Http\TemplateResponse + */ + private $tpl; + + /** + * @var \OCP\AppFramework\IApi + */ + private $api; + + protected function setUp() { + parent::setUp(); + + $this->api = $this->getMock('OC\AppFramework\Core\API', + array('getAppName'), array('test')); + $this->api->expects($this->any()) + ->method('getAppName') + ->will($this->returnValue('app')); + + $this->tpl = new TemplateResponse($this->api, 'home'); + } + + + public function testSetParamsConstructor(){ + $params = array('hi' => 'yo'); + $this->tpl = new TemplateResponse($this->api, 'home', $params); + + $this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams()); + } + + + public function testSetRenderAsConstructor(){ + $renderAs = 'myrender'; + $this->tpl = new TemplateResponse($this->api, 'home', array(), $renderAs); + + $this->assertEquals($renderAs, $this->tpl->getRenderAs()); + } + + + public function testSetParams(){ + $params = array('hi' => 'yo'); + $this->tpl->setParams($params); + + $this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams()); + } + + + public function testGetTemplateName(){ + $this->assertEquals('home', $this->tpl->getTemplateName()); + } + + public function testGetRenderAs(){ + $render = 'myrender'; + $this->tpl->renderAs($render); + $this->assertEquals($render, $this->tpl->getRenderAs()); + } + + public function testChainability() { + $params = array('hi' => 'yo'); + $this->tpl->setParams($params) + ->setStatus(Http::STATUS_NOT_FOUND); + + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->tpl->getStatus()); + $this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams()); + } + +} |