Passed
Push — master ( 21b7e5...813bdc )
by Christoph
12:53 queued 10s
created
lib/public/AppFramework/ApiController.php 2 patches
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -39,60 +39,60 @@
 block discarded – undo
39 39
  */
40 40
 abstract class ApiController extends Controller {
41 41
 
42
-	private $corsMethods;
43
-	private $corsAllowedHeaders;
44
-	private $corsMaxAge;
42
+    private $corsMethods;
43
+    private $corsAllowedHeaders;
44
+    private $corsMaxAge;
45 45
 
46
-	/**
47
-	 * constructor of the controller
48
-	 * @param string $appName the name of the app
49
-	 * @param IRequest $request an instance of the request
50
-	 * @param string $corsMethods comma separated string of HTTP verbs which
51
-	 * should be allowed for websites or webapps when calling your API, defaults to
52
-	 * 'PUT, POST, GET, DELETE, PATCH'
53
-	 * @param string $corsAllowedHeaders comma separated string of HTTP headers
54
-	 * which should be allowed for websites or webapps when calling your API,
55
-	 * defaults to 'Authorization, Content-Type, Accept'
56
-	 * @param int $corsMaxAge number in seconds how long a preflighted OPTIONS
57
-	 * request should be cached, defaults to 1728000 seconds
58
-	 * @since 7.0.0
59
-	 */
60
-	public function __construct($appName,
61
-								IRequest $request,
62
-								$corsMethods='PUT, POST, GET, DELETE, PATCH',
63
-								$corsAllowedHeaders='Authorization, Content-Type, Accept',
64
-								$corsMaxAge=1728000){
65
-		parent::__construct($appName, $request);
66
-		$this->corsMethods = $corsMethods;
67
-		$this->corsAllowedHeaders = $corsAllowedHeaders;
68
-		$this->corsMaxAge = $corsMaxAge;
69
-	}
46
+    /**
47
+     * constructor of the controller
48
+     * @param string $appName the name of the app
49
+     * @param IRequest $request an instance of the request
50
+     * @param string $corsMethods comma separated string of HTTP verbs which
51
+     * should be allowed for websites or webapps when calling your API, defaults to
52
+     * 'PUT, POST, GET, DELETE, PATCH'
53
+     * @param string $corsAllowedHeaders comma separated string of HTTP headers
54
+     * which should be allowed for websites or webapps when calling your API,
55
+     * defaults to 'Authorization, Content-Type, Accept'
56
+     * @param int $corsMaxAge number in seconds how long a preflighted OPTIONS
57
+     * request should be cached, defaults to 1728000 seconds
58
+     * @since 7.0.0
59
+     */
60
+    public function __construct($appName,
61
+                                IRequest $request,
62
+                                $corsMethods='PUT, POST, GET, DELETE, PATCH',
63
+                                $corsAllowedHeaders='Authorization, Content-Type, Accept',
64
+                                $corsMaxAge=1728000){
65
+        parent::__construct($appName, $request);
66
+        $this->corsMethods = $corsMethods;
67
+        $this->corsAllowedHeaders = $corsAllowedHeaders;
68
+        $this->corsMaxAge = $corsMaxAge;
69
+    }
70 70
 
71 71
 
72
-	/**
73
-	 * This method implements a preflighted cors response for you that you can
74
-	 * link to for the options request
75
-	 *
76
-	 * @NoAdminRequired
77
-	 * @NoCSRFRequired
78
-	 * @PublicPage
79
-	 * @since 7.0.0
80
-	 */
81
-	public function preflightedCors() {
82
-		if(isset($this->request->server['HTTP_ORIGIN'])) {
83
-			$origin = $this->request->server['HTTP_ORIGIN'];
84
-		} else {
85
-			$origin = '*';
86
-		}
72
+    /**
73
+     * This method implements a preflighted cors response for you that you can
74
+     * link to for the options request
75
+     *
76
+     * @NoAdminRequired
77
+     * @NoCSRFRequired
78
+     * @PublicPage
79
+     * @since 7.0.0
80
+     */
81
+    public function preflightedCors() {
82
+        if(isset($this->request->server['HTTP_ORIGIN'])) {
83
+            $origin = $this->request->server['HTTP_ORIGIN'];
84
+        } else {
85
+            $origin = '*';
86
+        }
87 87
 
88
-		$response = new Response();
89
-		$response->addHeader('Access-Control-Allow-Origin', $origin);
90
-		$response->addHeader('Access-Control-Allow-Methods', $this->corsMethods);
91
-		$response->addHeader('Access-Control-Max-Age', (string)$this->corsMaxAge);
92
-		$response->addHeader('Access-Control-Allow-Headers', $this->corsAllowedHeaders);
93
-		$response->addHeader('Access-Control-Allow-Credentials', 'false');
94
-		return $response;
95
-	}
88
+        $response = new Response();
89
+        $response->addHeader('Access-Control-Allow-Origin', $origin);
90
+        $response->addHeader('Access-Control-Allow-Methods', $this->corsMethods);
91
+        $response->addHeader('Access-Control-Max-Age', (string)$this->corsMaxAge);
92
+        $response->addHeader('Access-Control-Allow-Headers', $this->corsAllowedHeaders);
93
+        $response->addHeader('Access-Control-Allow-Credentials', 'false');
94
+        return $response;
95
+    }
96 96
 
97 97
 
98 98
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -59,9 +59,9 @@  discard block
 block discarded – undo
59 59
 	 */
60 60
 	public function __construct($appName,
61 61
 								IRequest $request,
62
-								$corsMethods='PUT, POST, GET, DELETE, PATCH',
63
-								$corsAllowedHeaders='Authorization, Content-Type, Accept',
64
-								$corsMaxAge=1728000){
62
+								$corsMethods = 'PUT, POST, GET, DELETE, PATCH',
63
+								$corsAllowedHeaders = 'Authorization, Content-Type, Accept',
64
+								$corsMaxAge = 1728000) {
65 65
 		parent::__construct($appName, $request);
66 66
 		$this->corsMethods = $corsMethods;
67 67
 		$this->corsAllowedHeaders = $corsAllowedHeaders;
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
 	 * @since 7.0.0
80 80
 	 */
81 81
 	public function preflightedCors() {
82
-		if(isset($this->request->server['HTTP_ORIGIN'])) {
82
+		if (isset($this->request->server['HTTP_ORIGIN'])) {
83 83
 			$origin = $this->request->server['HTTP_ORIGIN'];
84 84
 		} else {
85 85
 			$origin = '*';
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
 		$response = new Response();
89 89
 		$response->addHeader('Access-Control-Allow-Origin', $origin);
90 90
 		$response->addHeader('Access-Control-Allow-Methods', $this->corsMethods);
91
-		$response->addHeader('Access-Control-Max-Age', (string)$this->corsMaxAge);
91
+		$response->addHeader('Access-Control-Max-Age', (string) $this->corsMaxAge);
92 92
 		$response->addHeader('Access-Control-Allow-Headers', $this->corsAllowedHeaders);
93 93
 		$response->addHeader('Access-Control-Allow-Credentials', 'false');
94 94
 		return $response;
Please login to merge, or discard this patch.
lib/public/AppFramework/Http/DataDisplayResponse.php 2 patches
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -34,59 +34,59 @@
 block discarded – undo
34 34
  */
35 35
 class DataDisplayResponse extends Response {
36 36
 
37
-	/**
38
-	 * response data
39
-	 * @var string
40
-	 */
41
-	protected $data;
37
+    /**
38
+     * response data
39
+     * @var string
40
+     */
41
+    protected $data;
42 42
 
43 43
 
44
-	/**
45
-	 * @param string $data the data to display
46
-	 * @param int $statusCode the Http status code, defaults to 200
47
-	 * @param array $headers additional key value based headers
48
-	 * @since 8.1.0
49
-	 */
50
-	public function __construct($data='', $statusCode=Http::STATUS_OK,
51
-								$headers=[]) {
52
-		parent::__construct();
44
+    /**
45
+     * @param string $data the data to display
46
+     * @param int $statusCode the Http status code, defaults to 200
47
+     * @param array $headers additional key value based headers
48
+     * @since 8.1.0
49
+     */
50
+    public function __construct($data='', $statusCode=Http::STATUS_OK,
51
+                                $headers=[]) {
52
+        parent::__construct();
53 53
 
54
-		$this->data = $data;
55
-		$this->setStatus($statusCode);
56
-		$this->setHeaders(array_merge($this->getHeaders(), $headers));
57
-		$this->addHeader('Content-Disposition', 'inline; filename=""');
58
-	}
54
+        $this->data = $data;
55
+        $this->setStatus($statusCode);
56
+        $this->setHeaders(array_merge($this->getHeaders(), $headers));
57
+        $this->addHeader('Content-Disposition', 'inline; filename=""');
58
+    }
59 59
 
60
-	/**
61
-	 * Outputs data. No processing is done.
62
-	 * @return string
63
-	 * @since 8.1.0
64
-	 */
65
-	public function render() {
66
-		return $this->data;
67
-	}
60
+    /**
61
+     * Outputs data. No processing is done.
62
+     * @return string
63
+     * @since 8.1.0
64
+     */
65
+    public function render() {
66
+        return $this->data;
67
+    }
68 68
 
69 69
 
70
-	/**
71
-	 * Sets values in the data
72
-	 * @param string $data the data to display
73
-	 * @return DataDisplayResponse Reference to this object
74
-	 * @since 8.1.0
75
-	 */
76
-	public function setData($data){
77
-		$this->data = $data;
70
+    /**
71
+     * Sets values in the data
72
+     * @param string $data the data to display
73
+     * @return DataDisplayResponse Reference to this object
74
+     * @since 8.1.0
75
+     */
76
+    public function setData($data){
77
+        $this->data = $data;
78 78
 
79
-		return $this;
80
-	}
79
+        return $this;
80
+    }
81 81
 
82 82
 
83
-	/**
84
-	 * Used to get the set parameters
85
-	 * @return string the data
86
-	 * @since 8.1.0
87
-	 */
88
-	public function getData(){
89
-		return $this->data;
90
-	}
83
+    /**
84
+     * Used to get the set parameters
85
+     * @return string the data
86
+     * @since 8.1.0
87
+     */
88
+    public function getData(){
89
+        return $this->data;
90
+    }
91 91
 
92 92
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -47,8 +47,8 @@  discard block
 block discarded – undo
47 47
 	 * @param array $headers additional key value based headers
48 48
 	 * @since 8.1.0
49 49
 	 */
50
-	public function __construct($data='', $statusCode=Http::STATUS_OK,
51
-								$headers=[]) {
50
+	public function __construct($data = '', $statusCode = Http::STATUS_OK,
51
+								$headers = []) {
52 52
 		parent::__construct();
53 53
 
54 54
 		$this->data = $data;
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
 	 * @return DataDisplayResponse Reference to this object
74 74
 	 * @since 8.1.0
75 75
 	 */
76
-	public function setData($data){
76
+	public function setData($data) {
77 77
 		$this->data = $data;
78 78
 
79 79
 		return $this;
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
 	 * @return string the data
86 86
 	 * @since 8.1.0
87 87
 	 */
88
-	public function getData(){
88
+	public function getData() {
89 89
 		return $this->data;
90 90
 	}
91 91
 
Please login to merge, or discard this patch.
lib/public/AppFramework/Http/TemplateResponse.php 2 patches
Indentation   +127 added lines, -127 removed lines patch added patch discarded remove patch
@@ -40,132 +40,132 @@
 block discarded – undo
40 40
  */
41 41
 class TemplateResponse extends Response {
42 42
 
43
-	const EVENT_LOAD_ADDITIONAL_SCRIPTS = self::class . '::loadAdditionalScripts';
44
-	const EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN = self::class . '::loadAdditionalScriptsLoggedIn';
45
-
46
-	/**
47
-	 * name of the template
48
-	 * @var string
49
-	 */
50
-	protected $templateName;
51
-
52
-	/**
53
-	 * parameters
54
-	 * @var array
55
-	 */
56
-	protected $params;
57
-
58
-	/**
59
-	 * rendering type (admin, user, blank)
60
-	 * @var string
61
-	 */
62
-	protected $renderAs;
63
-
64
-	/**
65
-	 * app name
66
-	 * @var string
67
-	 */
68
-	protected $appName;
69
-
70
-	/**
71
-	 * constructor of TemplateResponse
72
-	 * @param string $appName the name of the app to load the template from
73
-	 * @param string $templateName the name of the template
74
-	 * @param array $params an array of parameters which should be passed to the
75
-	 * template
76
-	 * @param string $renderAs how the page should be rendered, defaults to user
77
-	 * @since 6.0.0 - parameters $params and $renderAs were added in 7.0.0
78
-	 */
79
-	public function __construct($appName, $templateName, array $params=[],
80
-								$renderAs='user') {
81
-		parent::__construct();
82
-
83
-		$this->templateName = $templateName;
84
-		$this->appName = $appName;
85
-		$this->params = $params;
86
-		$this->renderAs = $renderAs;
87
-
88
-		$this->setContentSecurityPolicy(new ContentSecurityPolicy());
89
-		$this->setFeaturePolicy(new FeaturePolicy());
90
-	}
91
-
92
-
93
-	/**
94
-	 * Sets template parameters
95
-	 * @param array $params an array with key => value structure which sets template
96
-	 *                      variables
97
-	 * @return TemplateResponse Reference to this object
98
-	 * @since 6.0.0 - return value was added in 7.0.0
99
-	 */
100
-	public function setParams(array $params){
101
-		$this->params = $params;
102
-
103
-		return $this;
104
-	}
105
-
106
-
107
-	/**
108
-	 * Used for accessing the set parameters
109
-	 * @return array the params
110
-	 * @since 6.0.0
111
-	 */
112
-	public function getParams(){
113
-		return $this->params;
114
-	}
115
-
116
-
117
-	/**
118
-	 * Used for accessing the name of the set template
119
-	 * @return string the name of the used template
120
-	 * @since 6.0.0
121
-	 */
122
-	public function getTemplateName(){
123
-		return $this->templateName;
124
-	}
125
-
126
-
127
-	/**
128
-	 * Sets the template page
129
-	 * @param string $renderAs admin, user or blank. Admin also prints the admin
130
-	 *                         settings header and footer, user renders the normal
131
-	 *                         normal page including footer and header and blank
132
-	 *                         just renders the plain template
133
-	 * @return TemplateResponse Reference to this object
134
-	 * @since 6.0.0 - return value was added in 7.0.0
135
-	 */
136
-	public function renderAs($renderAs){
137
-		$this->renderAs = $renderAs;
138
-
139
-		return $this;
140
-	}
141
-
142
-
143
-	/**
144
-	 * Returns the set renderAs
145
-	 * @return string the renderAs value
146
-	 * @since 6.0.0
147
-	 */
148
-	public function getRenderAs(){
149
-		return $this->renderAs;
150
-	}
151
-
152
-
153
-	/**
154
-	 * Returns the rendered html
155
-	 * @return string the rendered html
156
-	 * @since 6.0.0
157
-	 */
158
-	public function render(){
159
-		// \OCP\Template needs an empty string instead of 'blank' for an unwrapped response
160
-		$renderAs = $this->renderAs === 'blank' ? '' : $this->renderAs;
161
-
162
-		$template = new \OCP\Template($this->appName, $this->templateName, $renderAs);
163
-
164
-		foreach($this->params as $key => $value){
165
-			$template->assign($key, $value);
166
-		}
167
-
168
-		return $template->fetchPage($this->params);
169
-	}
43
+    const EVENT_LOAD_ADDITIONAL_SCRIPTS = self::class . '::loadAdditionalScripts';
44
+    const EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN = self::class . '::loadAdditionalScriptsLoggedIn';
45
+
46
+    /**
47
+     * name of the template
48
+     * @var string
49
+     */
50
+    protected $templateName;
51
+
52
+    /**
53
+     * parameters
54
+     * @var array
55
+     */
56
+    protected $params;
57
+
58
+    /**
59
+     * rendering type (admin, user, blank)
60
+     * @var string
61
+     */
62
+    protected $renderAs;
63
+
64
+    /**
65
+     * app name
66
+     * @var string
67
+     */
68
+    protected $appName;
69
+
70
+    /**
71
+     * constructor of TemplateResponse
72
+     * @param string $appName the name of the app to load the template from
73
+     * @param string $templateName the name of the template
74
+     * @param array $params an array of parameters which should be passed to the
75
+     * template
76
+     * @param string $renderAs how the page should be rendered, defaults to user
77
+     * @since 6.0.0 - parameters $params and $renderAs were added in 7.0.0
78
+     */
79
+    public function __construct($appName, $templateName, array $params=[],
80
+                                $renderAs='user') {
81
+        parent::__construct();
82
+
83
+        $this->templateName = $templateName;
84
+        $this->appName = $appName;
85
+        $this->params = $params;
86
+        $this->renderAs = $renderAs;
87
+
88
+        $this->setContentSecurityPolicy(new ContentSecurityPolicy());
89
+        $this->setFeaturePolicy(new FeaturePolicy());
90
+    }
91
+
92
+
93
+    /**
94
+     * Sets template parameters
95
+     * @param array $params an array with key => value structure which sets template
96
+     *                      variables
97
+     * @return TemplateResponse Reference to this object
98
+     * @since 6.0.0 - return value was added in 7.0.0
99
+     */
100
+    public function setParams(array $params){
101
+        $this->params = $params;
102
+
103
+        return $this;
104
+    }
105
+
106
+
107
+    /**
108
+     * Used for accessing the set parameters
109
+     * @return array the params
110
+     * @since 6.0.0
111
+     */
112
+    public function getParams(){
113
+        return $this->params;
114
+    }
115
+
116
+
117
+    /**
118
+     * Used for accessing the name of the set template
119
+     * @return string the name of the used template
120
+     * @since 6.0.0
121
+     */
122
+    public function getTemplateName(){
123
+        return $this->templateName;
124
+    }
125
+
126
+
127
+    /**
128
+     * Sets the template page
129
+     * @param string $renderAs admin, user or blank. Admin also prints the admin
130
+     *                         settings header and footer, user renders the normal
131
+     *                         normal page including footer and header and blank
132
+     *                         just renders the plain template
133
+     * @return TemplateResponse Reference to this object
134
+     * @since 6.0.0 - return value was added in 7.0.0
135
+     */
136
+    public function renderAs($renderAs){
137
+        $this->renderAs = $renderAs;
138
+
139
+        return $this;
140
+    }
141
+
142
+
143
+    /**
144
+     * Returns the set renderAs
145
+     * @return string the renderAs value
146
+     * @since 6.0.0
147
+     */
148
+    public function getRenderAs(){
149
+        return $this->renderAs;
150
+    }
151
+
152
+
153
+    /**
154
+     * Returns the rendered html
155
+     * @return string the rendered html
156
+     * @since 6.0.0
157
+     */
158
+    public function render(){
159
+        // \OCP\Template needs an empty string instead of 'blank' for an unwrapped response
160
+        $renderAs = $this->renderAs === 'blank' ? '' : $this->renderAs;
161
+
162
+        $template = new \OCP\Template($this->appName, $this->templateName, $renderAs);
163
+
164
+        foreach($this->params as $key => $value){
165
+            $template->assign($key, $value);
166
+        }
167
+
168
+        return $template->fetchPage($this->params);
169
+    }
170 170
 
171 171
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -40,8 +40,8 @@  discard block
 block discarded – undo
40 40
  */
41 41
 class TemplateResponse extends Response {
42 42
 
43
-	const EVENT_LOAD_ADDITIONAL_SCRIPTS = self::class . '::loadAdditionalScripts';
44
-	const EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN = self::class . '::loadAdditionalScriptsLoggedIn';
43
+	const EVENT_LOAD_ADDITIONAL_SCRIPTS = self::class.'::loadAdditionalScripts';
44
+	const EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN = self::class.'::loadAdditionalScriptsLoggedIn';
45 45
 
46 46
 	/**
47 47
 	 * name of the template
@@ -76,8 +76,8 @@  discard block
 block discarded – undo
76 76
 	 * @param string $renderAs how the page should be rendered, defaults to user
77 77
 	 * @since 6.0.0 - parameters $params and $renderAs were added in 7.0.0
78 78
 	 */
79
-	public function __construct($appName, $templateName, array $params=[],
80
-								$renderAs='user') {
79
+	public function __construct($appName, $templateName, array $params = [],
80
+								$renderAs = 'user') {
81 81
 		parent::__construct();
82 82
 
83 83
 		$this->templateName = $templateName;
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
 	 * @return TemplateResponse Reference to this object
98 98
 	 * @since 6.0.0 - return value was added in 7.0.0
99 99
 	 */
100
-	public function setParams(array $params){
100
+	public function setParams(array $params) {
101 101
 		$this->params = $params;
102 102
 
103 103
 		return $this;
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
 	 * @return array the params
110 110
 	 * @since 6.0.0
111 111
 	 */
112
-	public function getParams(){
112
+	public function getParams() {
113 113
 		return $this->params;
114 114
 	}
115 115
 
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
 	 * @return string the name of the used template
120 120
 	 * @since 6.0.0
121 121
 	 */
122
-	public function getTemplateName(){
122
+	public function getTemplateName() {
123 123
 		return $this->templateName;
124 124
 	}
125 125
 
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
 	 * @return TemplateResponse Reference to this object
134 134
 	 * @since 6.0.0 - return value was added in 7.0.0
135 135
 	 */
136
-	public function renderAs($renderAs){
136
+	public function renderAs($renderAs) {
137 137
 		$this->renderAs = $renderAs;
138 138
 
139 139
 		return $this;
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
 	 * @return string the renderAs value
146 146
 	 * @since 6.0.0
147 147
 	 */
148
-	public function getRenderAs(){
148
+	public function getRenderAs() {
149 149
 		return $this->renderAs;
150 150
 	}
151 151
 
@@ -155,13 +155,13 @@  discard block
 block discarded – undo
155 155
 	 * @return string the rendered html
156 156
 	 * @since 6.0.0
157 157
 	 */
158
-	public function render(){
158
+	public function render() {
159 159
 		// \OCP\Template needs an empty string instead of 'blank' for an unwrapped response
160 160
 		$renderAs = $this->renderAs === 'blank' ? '' : $this->renderAs;
161 161
 
162 162
 		$template = new \OCP\Template($this->appName, $this->templateName, $renderAs);
163 163
 
164
-		foreach($this->params as $key => $value){
164
+		foreach ($this->params as $key => $value) {
165 165
 			$template->assign($key, $value);
166 166
 		}
167 167
 
Please login to merge, or discard this patch.
lib/public/AppFramework/Http/Response.php 2 patches
Indentation   +355 added lines, -355 removed lines patch added patch discarded remove patch
@@ -45,359 +45,359 @@
 block discarded – undo
45 45
  */
46 46
 class Response {
47 47
 
48
-	/**
49
-	 * Headers - defaults to ['Cache-Control' => 'no-cache, no-store, must-revalidate']
50
-	 * @var array
51
-	 */
52
-	private $headers = [
53
-		'Cache-Control' => 'no-cache, no-store, must-revalidate'
54
-	];
55
-
56
-
57
-	/**
58
-	 * Cookies that will be need to be constructed as header
59
-	 * @var array
60
-	 */
61
-	private $cookies = [];
62
-
63
-
64
-	/**
65
-	 * HTTP status code - defaults to STATUS OK
66
-	 * @var int
67
-	 */
68
-	private $status = Http::STATUS_OK;
69
-
70
-
71
-	/**
72
-	 * Last modified date
73
-	 * @var \DateTime
74
-	 */
75
-	private $lastModified;
76
-
77
-
78
-	/**
79
-	 * ETag
80
-	 * @var string
81
-	 */
82
-	private $ETag;
83
-
84
-	/** @var ContentSecurityPolicy|null Used Content-Security-Policy */
85
-	private $contentSecurityPolicy = null;
86
-
87
-	/** @var FeaturePolicy */
88
-	private $featurePolicy;
89
-
90
-	/** @var bool */
91
-	private $throttled = false;
92
-	/** @var array */
93
-	private $throttleMetadata = [];
94
-
95
-	/**
96
-	 * @since 17.0.0
97
-	 */
98
-	public function __construct() {
99
-	}
100
-
101
-	/**
102
-	 * Caches the response
103
-	 * @param int $cacheSeconds the amount of seconds that should be cached
104
-	 * if 0 then caching will be disabled
105
-	 * @return $this
106
-	 * @since 6.0.0 - return value was added in 7.0.0
107
-	 */
108
-	public function cacheFor(int $cacheSeconds) {
109
-		if($cacheSeconds > 0) {
110
-			$this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . ', must-revalidate');
111
-
112
-			// Old scool prama caching
113
-			$this->addHeader('Pragma', 'public');
114
-
115
-			// Set expires header
116
-			$expires = new \DateTime();
117
-			/** @var ITimeFactory $time */
118
-			$time = \OC::$server->query(ITimeFactory::class);
119
-			$expires->setTimestamp($time->getTime());
120
-			$expires->add(new \DateInterval('PT'.$cacheSeconds.'S'));
121
-			$this->addHeader('Expires', $expires->format(\DateTime::RFC2822));
122
-		} else {
123
-			$this->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
124
-			unset($this->headers['Expires'], $this->headers['Pragma']);
125
-		}
126
-
127
-		return $this;
128
-	}
129
-
130
-	/**
131
-	 * Adds a new cookie to the response
132
-	 * @param string $name The name of the cookie
133
-	 * @param string $value The value of the cookie
134
-	 * @param \DateTime|null $expireDate Date on that the cookie should expire, if set
135
-	 * 									to null cookie will be considered as session
136
-	 * 									cookie.
137
-	 * @return $this
138
-	 * @since 8.0.0
139
-	 */
140
-	public function addCookie($name, $value, \DateTime $expireDate = null) {
141
-		$this->cookies[$name] = ['value' => $value, 'expireDate' => $expireDate];
142
-		return $this;
143
-	}
144
-
145
-
146
-	/**
147
-	 * Set the specified cookies
148
-	 * @param array $cookies array('foo' => array('value' => 'bar', 'expire' => null))
149
-	 * @return $this
150
-	 * @since 8.0.0
151
-	 */
152
-	public function setCookies(array $cookies) {
153
-		$this->cookies = $cookies;
154
-		return $this;
155
-	}
156
-
157
-
158
-	/**
159
-	 * Invalidates the specified cookie
160
-	 * @param string $name
161
-	 * @return $this
162
-	 * @since 8.0.0
163
-	 */
164
-	public function invalidateCookie($name) {
165
-		$this->addCookie($name, 'expired', new \DateTime('1971-01-01 00:00'));
166
-		return $this;
167
-	}
168
-
169
-	/**
170
-	 * Invalidates the specified cookies
171
-	 * @param array $cookieNames array('foo', 'bar')
172
-	 * @return $this
173
-	 * @since 8.0.0
174
-	 */
175
-	public function invalidateCookies(array $cookieNames) {
176
-		foreach($cookieNames as $cookieName) {
177
-			$this->invalidateCookie($cookieName);
178
-		}
179
-		return $this;
180
-	}
181
-
182
-	/**
183
-	 * Returns the cookies
184
-	 * @return array
185
-	 * @since 8.0.0
186
-	 */
187
-	public function getCookies() {
188
-		return $this->cookies;
189
-	}
190
-
191
-	/**
192
-	 * Adds a new header to the response that will be called before the render
193
-	 * function
194
-	 * @param string $name The name of the HTTP header
195
-	 * @param string $value The value, null will delete it
196
-	 * @return $this
197
-	 * @since 6.0.0 - return value was added in 7.0.0
198
-	 */
199
-	public function addHeader($name, $value) {
200
-		$name = trim($name);  // always remove leading and trailing whitespace
201
-							  // to be able to reliably check for security
202
-							  // headers
203
-
204
-		if(is_null($value)) {
205
-			unset($this->headers[$name]);
206
-		} else {
207
-			$this->headers[$name] = $value;
208
-		}
209
-
210
-		return $this;
211
-	}
212
-
213
-
214
-	/**
215
-	 * Set the headers
216
-	 * @param array $headers value header pairs
217
-	 * @return $this
218
-	 * @since 8.0.0
219
-	 */
220
-	public function setHeaders(array $headers) {
221
-		$this->headers = $headers;
222
-
223
-		return $this;
224
-	}
225
-
226
-
227
-	/**
228
-	 * Returns the set headers
229
-	 * @return array the headers
230
-	 * @since 6.0.0
231
-	 */
232
-	public function getHeaders() {
233
-		$mergeWith = [];
234
-
235
-		if($this->lastModified) {
236
-			$mergeWith['Last-Modified'] =
237
-				$this->lastModified->format(\DateTime::RFC2822);
238
-		}
239
-
240
-		$this->headers['Content-Security-Policy'] = $this->getContentSecurityPolicy()->buildPolicy();
241
-		$this->headers['Feature-Policy'] = $this->getFeaturePolicy()->buildPolicy();
242
-
243
-		if($this->ETag) {
244
-			$mergeWith['ETag'] = '"' . $this->ETag . '"';
245
-		}
246
-
247
-		return array_merge($mergeWith, $this->headers);
248
-	}
249
-
250
-
251
-	/**
252
-	 * By default renders no output
253
-	 * @return string
254
-	 * @since 6.0.0
255
-	 */
256
-	public function render() {
257
-		return '';
258
-	}
259
-
260
-
261
-	/**
262
-	 * Set response status
263
-	 * @param int $status a HTTP status code, see also the STATUS constants
264
-	 * @return Response Reference to this object
265
-	 * @since 6.0.0 - return value was added in 7.0.0
266
-	 */
267
-	public function setStatus($status) {
268
-		$this->status = $status;
269
-
270
-		return $this;
271
-	}
272
-
273
-	/**
274
-	 * Set a Content-Security-Policy
275
-	 * @param EmptyContentSecurityPolicy $csp Policy to set for the response object
276
-	 * @return $this
277
-	 * @since 8.1.0
278
-	 */
279
-	public function setContentSecurityPolicy(EmptyContentSecurityPolicy $csp) {
280
-		$this->contentSecurityPolicy = $csp;
281
-		return $this;
282
-	}
283
-
284
-	/**
285
-	 * Get the currently used Content-Security-Policy
286
-	 * @return EmptyContentSecurityPolicy|null Used Content-Security-Policy or null if
287
-	 *                                    none specified.
288
-	 * @since 8.1.0
289
-	 */
290
-	public function getContentSecurityPolicy() {
291
-		if ($this->contentSecurityPolicy === null) {
292
-			$this->setContentSecurityPolicy(new EmptyContentSecurityPolicy());
293
-		}
294
-		return $this->contentSecurityPolicy;
295
-	}
296
-
297
-
298
-	/**
299
-	 * @since 17.0.0
300
-	 */
301
-	public function getFeaturePolicy(): EmptyFeaturePolicy {
302
-		if ($this->featurePolicy === null) {
303
-			$this->setFeaturePolicy(new EmptyFeaturePolicy());
304
-		}
305
-		return $this->featurePolicy;
306
-	}
307
-
308
-	/**
309
-	 * @since 17.0.0
310
-	 */
311
-	public function setFeaturePolicy(EmptyFeaturePolicy $featurePolicy): self {
312
-		$this->featurePolicy = $featurePolicy;
313
-
314
-		return $this;
315
-	}
316
-
317
-
318
-
319
-	/**
320
-	 * Get response status
321
-	 * @since 6.0.0
322
-	 */
323
-	public function getStatus() {
324
-		return $this->status;
325
-	}
326
-
327
-
328
-	/**
329
-	 * Get the ETag
330
-	 * @return string the etag
331
-	 * @since 6.0.0
332
-	 */
333
-	public function getETag() {
334
-		return $this->ETag;
335
-	}
336
-
337
-
338
-	/**
339
-	 * Get "last modified" date
340
-	 * @return \DateTime RFC2822 formatted last modified date
341
-	 * @since 6.0.0
342
-	 */
343
-	public function getLastModified() {
344
-		return $this->lastModified;
345
-	}
346
-
347
-
348
-	/**
349
-	 * Set the ETag
350
-	 * @param string $ETag
351
-	 * @return Response Reference to this object
352
-	 * @since 6.0.0 - return value was added in 7.0.0
353
-	 */
354
-	public function setETag($ETag) {
355
-		$this->ETag = $ETag;
356
-
357
-		return $this;
358
-	}
359
-
360
-
361
-	/**
362
-	 * Set "last modified" date
363
-	 * @param \DateTime $lastModified
364
-	 * @return Response Reference to this object
365
-	 * @since 6.0.0 - return value was added in 7.0.0
366
-	 */
367
-	public function setLastModified($lastModified) {
368
-		$this->lastModified = $lastModified;
369
-
370
-		return $this;
371
-	}
372
-
373
-	/**
374
-	 * Marks the response as to throttle. Will be throttled when the
375
-	 * @BruteForceProtection annotation is added.
376
-	 *
377
-	 * @param array $metadata
378
-	 * @since 12.0.0
379
-	 */
380
-	public function throttle(array $metadata = []) {
381
-		$this->throttled = true;
382
-		$this->throttleMetadata = $metadata;
383
-	}
384
-
385
-	/**
386
-	 * Returns the throttle metadata, defaults to empty array
387
-	 *
388
-	 * @return array
389
-	 * @since 13.0.0
390
-	 */
391
-	public function getThrottleMetadata() {
392
-		return $this->throttleMetadata;
393
-	}
394
-
395
-	/**
396
-	 * Whether the current response is throttled.
397
-	 *
398
-	 * @since 12.0.0
399
-	 */
400
-	public function isThrottled() {
401
-		return $this->throttled;
402
-	}
48
+    /**
49
+     * Headers - defaults to ['Cache-Control' => 'no-cache, no-store, must-revalidate']
50
+     * @var array
51
+     */
52
+    private $headers = [
53
+        'Cache-Control' => 'no-cache, no-store, must-revalidate'
54
+    ];
55
+
56
+
57
+    /**
58
+     * Cookies that will be need to be constructed as header
59
+     * @var array
60
+     */
61
+    private $cookies = [];
62
+
63
+
64
+    /**
65
+     * HTTP status code - defaults to STATUS OK
66
+     * @var int
67
+     */
68
+    private $status = Http::STATUS_OK;
69
+
70
+
71
+    /**
72
+     * Last modified date
73
+     * @var \DateTime
74
+     */
75
+    private $lastModified;
76
+
77
+
78
+    /**
79
+     * ETag
80
+     * @var string
81
+     */
82
+    private $ETag;
83
+
84
+    /** @var ContentSecurityPolicy|null Used Content-Security-Policy */
85
+    private $contentSecurityPolicy = null;
86
+
87
+    /** @var FeaturePolicy */
88
+    private $featurePolicy;
89
+
90
+    /** @var bool */
91
+    private $throttled = false;
92
+    /** @var array */
93
+    private $throttleMetadata = [];
94
+
95
+    /**
96
+     * @since 17.0.0
97
+     */
98
+    public function __construct() {
99
+    }
100
+
101
+    /**
102
+     * Caches the response
103
+     * @param int $cacheSeconds the amount of seconds that should be cached
104
+     * if 0 then caching will be disabled
105
+     * @return $this
106
+     * @since 6.0.0 - return value was added in 7.0.0
107
+     */
108
+    public function cacheFor(int $cacheSeconds) {
109
+        if($cacheSeconds > 0) {
110
+            $this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . ', must-revalidate');
111
+
112
+            // Old scool prama caching
113
+            $this->addHeader('Pragma', 'public');
114
+
115
+            // Set expires header
116
+            $expires = new \DateTime();
117
+            /** @var ITimeFactory $time */
118
+            $time = \OC::$server->query(ITimeFactory::class);
119
+            $expires->setTimestamp($time->getTime());
120
+            $expires->add(new \DateInterval('PT'.$cacheSeconds.'S'));
121
+            $this->addHeader('Expires', $expires->format(\DateTime::RFC2822));
122
+        } else {
123
+            $this->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
124
+            unset($this->headers['Expires'], $this->headers['Pragma']);
125
+        }
126
+
127
+        return $this;
128
+    }
129
+
130
+    /**
131
+     * Adds a new cookie to the response
132
+     * @param string $name The name of the cookie
133
+     * @param string $value The value of the cookie
134
+     * @param \DateTime|null $expireDate Date on that the cookie should expire, if set
135
+     * 									to null cookie will be considered as session
136
+     * 									cookie.
137
+     * @return $this
138
+     * @since 8.0.0
139
+     */
140
+    public function addCookie($name, $value, \DateTime $expireDate = null) {
141
+        $this->cookies[$name] = ['value' => $value, 'expireDate' => $expireDate];
142
+        return $this;
143
+    }
144
+
145
+
146
+    /**
147
+     * Set the specified cookies
148
+     * @param array $cookies array('foo' => array('value' => 'bar', 'expire' => null))
149
+     * @return $this
150
+     * @since 8.0.0
151
+     */
152
+    public function setCookies(array $cookies) {
153
+        $this->cookies = $cookies;
154
+        return $this;
155
+    }
156
+
157
+
158
+    /**
159
+     * Invalidates the specified cookie
160
+     * @param string $name
161
+     * @return $this
162
+     * @since 8.0.0
163
+     */
164
+    public function invalidateCookie($name) {
165
+        $this->addCookie($name, 'expired', new \DateTime('1971-01-01 00:00'));
166
+        return $this;
167
+    }
168
+
169
+    /**
170
+     * Invalidates the specified cookies
171
+     * @param array $cookieNames array('foo', 'bar')
172
+     * @return $this
173
+     * @since 8.0.0
174
+     */
175
+    public function invalidateCookies(array $cookieNames) {
176
+        foreach($cookieNames as $cookieName) {
177
+            $this->invalidateCookie($cookieName);
178
+        }
179
+        return $this;
180
+    }
181
+
182
+    /**
183
+     * Returns the cookies
184
+     * @return array
185
+     * @since 8.0.0
186
+     */
187
+    public function getCookies() {
188
+        return $this->cookies;
189
+    }
190
+
191
+    /**
192
+     * Adds a new header to the response that will be called before the render
193
+     * function
194
+     * @param string $name The name of the HTTP header
195
+     * @param string $value The value, null will delete it
196
+     * @return $this
197
+     * @since 6.0.0 - return value was added in 7.0.0
198
+     */
199
+    public function addHeader($name, $value) {
200
+        $name = trim($name);  // always remove leading and trailing whitespace
201
+                                // to be able to reliably check for security
202
+                                // headers
203
+
204
+        if(is_null($value)) {
205
+            unset($this->headers[$name]);
206
+        } else {
207
+            $this->headers[$name] = $value;
208
+        }
209
+
210
+        return $this;
211
+    }
212
+
213
+
214
+    /**
215
+     * Set the headers
216
+     * @param array $headers value header pairs
217
+     * @return $this
218
+     * @since 8.0.0
219
+     */
220
+    public function setHeaders(array $headers) {
221
+        $this->headers = $headers;
222
+
223
+        return $this;
224
+    }
225
+
226
+
227
+    /**
228
+     * Returns the set headers
229
+     * @return array the headers
230
+     * @since 6.0.0
231
+     */
232
+    public function getHeaders() {
233
+        $mergeWith = [];
234
+
235
+        if($this->lastModified) {
236
+            $mergeWith['Last-Modified'] =
237
+                $this->lastModified->format(\DateTime::RFC2822);
238
+        }
239
+
240
+        $this->headers['Content-Security-Policy'] = $this->getContentSecurityPolicy()->buildPolicy();
241
+        $this->headers['Feature-Policy'] = $this->getFeaturePolicy()->buildPolicy();
242
+
243
+        if($this->ETag) {
244
+            $mergeWith['ETag'] = '"' . $this->ETag . '"';
245
+        }
246
+
247
+        return array_merge($mergeWith, $this->headers);
248
+    }
249
+
250
+
251
+    /**
252
+     * By default renders no output
253
+     * @return string
254
+     * @since 6.0.0
255
+     */
256
+    public function render() {
257
+        return '';
258
+    }
259
+
260
+
261
+    /**
262
+     * Set response status
263
+     * @param int $status a HTTP status code, see also the STATUS constants
264
+     * @return Response Reference to this object
265
+     * @since 6.0.0 - return value was added in 7.0.0
266
+     */
267
+    public function setStatus($status) {
268
+        $this->status = $status;
269
+
270
+        return $this;
271
+    }
272
+
273
+    /**
274
+     * Set a Content-Security-Policy
275
+     * @param EmptyContentSecurityPolicy $csp Policy to set for the response object
276
+     * @return $this
277
+     * @since 8.1.0
278
+     */
279
+    public function setContentSecurityPolicy(EmptyContentSecurityPolicy $csp) {
280
+        $this->contentSecurityPolicy = $csp;
281
+        return $this;
282
+    }
283
+
284
+    /**
285
+     * Get the currently used Content-Security-Policy
286
+     * @return EmptyContentSecurityPolicy|null Used Content-Security-Policy or null if
287
+     *                                    none specified.
288
+     * @since 8.1.0
289
+     */
290
+    public function getContentSecurityPolicy() {
291
+        if ($this->contentSecurityPolicy === null) {
292
+            $this->setContentSecurityPolicy(new EmptyContentSecurityPolicy());
293
+        }
294
+        return $this->contentSecurityPolicy;
295
+    }
296
+
297
+
298
+    /**
299
+     * @since 17.0.0
300
+     */
301
+    public function getFeaturePolicy(): EmptyFeaturePolicy {
302
+        if ($this->featurePolicy === null) {
303
+            $this->setFeaturePolicy(new EmptyFeaturePolicy());
304
+        }
305
+        return $this->featurePolicy;
306
+    }
307
+
308
+    /**
309
+     * @since 17.0.0
310
+     */
311
+    public function setFeaturePolicy(EmptyFeaturePolicy $featurePolicy): self {
312
+        $this->featurePolicy = $featurePolicy;
313
+
314
+        return $this;
315
+    }
316
+
317
+
318
+
319
+    /**
320
+     * Get response status
321
+     * @since 6.0.0
322
+     */
323
+    public function getStatus() {
324
+        return $this->status;
325
+    }
326
+
327
+
328
+    /**
329
+     * Get the ETag
330
+     * @return string the etag
331
+     * @since 6.0.0
332
+     */
333
+    public function getETag() {
334
+        return $this->ETag;
335
+    }
336
+
337
+
338
+    /**
339
+     * Get "last modified" date
340
+     * @return \DateTime RFC2822 formatted last modified date
341
+     * @since 6.0.0
342
+     */
343
+    public function getLastModified() {
344
+        return $this->lastModified;
345
+    }
346
+
347
+
348
+    /**
349
+     * Set the ETag
350
+     * @param string $ETag
351
+     * @return Response Reference to this object
352
+     * @since 6.0.0 - return value was added in 7.0.0
353
+     */
354
+    public function setETag($ETag) {
355
+        $this->ETag = $ETag;
356
+
357
+        return $this;
358
+    }
359
+
360
+
361
+    /**
362
+     * Set "last modified" date
363
+     * @param \DateTime $lastModified
364
+     * @return Response Reference to this object
365
+     * @since 6.0.0 - return value was added in 7.0.0
366
+     */
367
+    public function setLastModified($lastModified) {
368
+        $this->lastModified = $lastModified;
369
+
370
+        return $this;
371
+    }
372
+
373
+    /**
374
+     * Marks the response as to throttle. Will be throttled when the
375
+     * @BruteForceProtection annotation is added.
376
+     *
377
+     * @param array $metadata
378
+     * @since 12.0.0
379
+     */
380
+    public function throttle(array $metadata = []) {
381
+        $this->throttled = true;
382
+        $this->throttleMetadata = $metadata;
383
+    }
384
+
385
+    /**
386
+     * Returns the throttle metadata, defaults to empty array
387
+     *
388
+     * @return array
389
+     * @since 13.0.0
390
+     */
391
+    public function getThrottleMetadata() {
392
+        return $this->throttleMetadata;
393
+    }
394
+
395
+    /**
396
+     * Whether the current response is throttled.
397
+     *
398
+     * @since 12.0.0
399
+     */
400
+    public function isThrottled() {
401
+        return $this->throttled;
402
+    }
403 403
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -106,8 +106,8 @@  discard block
 block discarded – undo
106 106
 	 * @since 6.0.0 - return value was added in 7.0.0
107 107
 	 */
108 108
 	public function cacheFor(int $cacheSeconds) {
109
-		if($cacheSeconds > 0) {
110
-			$this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . ', must-revalidate');
109
+		if ($cacheSeconds > 0) {
110
+			$this->addHeader('Cache-Control', 'max-age='.$cacheSeconds.', must-revalidate');
111 111
 
112 112
 			// Old scool prama caching
113 113
 			$this->addHeader('Pragma', 'public');
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 	 * @since 8.0.0
174 174
 	 */
175 175
 	public function invalidateCookies(array $cookieNames) {
176
-		foreach($cookieNames as $cookieName) {
176
+		foreach ($cookieNames as $cookieName) {
177 177
 			$this->invalidateCookie($cookieName);
178 178
 		}
179 179
 		return $this;
@@ -197,11 +197,11 @@  discard block
 block discarded – undo
197 197
 	 * @since 6.0.0 - return value was added in 7.0.0
198 198
 	 */
199 199
 	public function addHeader($name, $value) {
200
-		$name = trim($name);  // always remove leading and trailing whitespace
200
+		$name = trim($name); // always remove leading and trailing whitespace
201 201
 							  // to be able to reliably check for security
202 202
 							  // headers
203 203
 
204
-		if(is_null($value)) {
204
+		if (is_null($value)) {
205 205
 			unset($this->headers[$name]);
206 206
 		} else {
207 207
 			$this->headers[$name] = $value;
@@ -232,7 +232,7 @@  discard block
 block discarded – undo
232 232
 	public function getHeaders() {
233 233
 		$mergeWith = [];
234 234
 
235
-		if($this->lastModified) {
235
+		if ($this->lastModified) {
236 236
 			$mergeWith['Last-Modified'] =
237 237
 				$this->lastModified->format(\DateTime::RFC2822);
238 238
 		}
@@ -240,8 +240,8 @@  discard block
 block discarded – undo
240 240
 		$this->headers['Content-Security-Policy'] = $this->getContentSecurityPolicy()->buildPolicy();
241 241
 		$this->headers['Feature-Policy'] = $this->getFeaturePolicy()->buildPolicy();
242 242
 
243
-		if($this->ETag) {
244
-			$mergeWith['ETag'] = '"' . $this->ETag . '"';
243
+		if ($this->ETag) {
244
+			$mergeWith['ETag'] = '"'.$this->ETag.'"';
245 245
 		}
246 246
 
247 247
 		return array_merge($mergeWith, $this->headers);
Please login to merge, or discard this patch.
lib/public/AppFramework/Http/DataResponse.php 2 patches
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -39,50 +39,50 @@
 block discarded – undo
39 39
  */
40 40
 class DataResponse extends Response {
41 41
 
42
-	/**
43
-	 * response data
44
-	 * @var array|object
45
-	 */
46
-	protected $data;
42
+    /**
43
+     * response data
44
+     * @var array|object
45
+     */
46
+    protected $data;
47 47
 
48 48
 
49
-	/**
50
-	 * @param array|object $data the object or array that should be transformed
51
-	 * @param int $statusCode the Http status code, defaults to 200
52
-	 * @param array $headers additional key value based headers
53
-	 * @since 8.0.0
54
-	 */
55
-	public function __construct($data=[], $statusCode=Http::STATUS_OK,
56
-								array $headers=[]) {
57
-		parent::__construct();
49
+    /**
50
+     * @param array|object $data the object or array that should be transformed
51
+     * @param int $statusCode the Http status code, defaults to 200
52
+     * @param array $headers additional key value based headers
53
+     * @since 8.0.0
54
+     */
55
+    public function __construct($data=[], $statusCode=Http::STATUS_OK,
56
+                                array $headers=[]) {
57
+        parent::__construct();
58 58
 
59
-		$this->data = $data;
60
-		$this->setStatus($statusCode);
61
-		$this->setHeaders(array_merge($this->getHeaders(), $headers));
62
-	}
59
+        $this->data = $data;
60
+        $this->setStatus($statusCode);
61
+        $this->setHeaders(array_merge($this->getHeaders(), $headers));
62
+    }
63 63
 
64 64
 
65
-	/**
66
-	 * Sets values in the data json array
67
-	 * @param array|object $data an array or object which will be transformed
68
-	 * @return DataResponse Reference to this object
69
-	 * @since 8.0.0
70
-	 */
71
-	public function setData($data){
72
-		$this->data = $data;
65
+    /**
66
+     * Sets values in the data json array
67
+     * @param array|object $data an array or object which will be transformed
68
+     * @return DataResponse Reference to this object
69
+     * @since 8.0.0
70
+     */
71
+    public function setData($data){
72
+        $this->data = $data;
73 73
 
74
-		return $this;
75
-	}
74
+        return $this;
75
+    }
76 76
 
77 77
 
78
-	/**
79
-	 * Used to get the set parameters
80
-	 * @return array the data
81
-	 * @since 8.0.0
82
-	 */
83
-	public function getData(){
84
-		return $this->data;
85
-	}
78
+    /**
79
+     * Used to get the set parameters
80
+     * @return array the data
81
+     * @since 8.0.0
82
+     */
83
+    public function getData(){
84
+        return $this->data;
85
+    }
86 86
 
87 87
 
88 88
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -52,8 +52,8 @@  discard block
 block discarded – undo
52 52
 	 * @param array $headers additional key value based headers
53 53
 	 * @since 8.0.0
54 54
 	 */
55
-	public function __construct($data=[], $statusCode=Http::STATUS_OK,
56
-								array $headers=[]) {
55
+	public function __construct($data = [], $statusCode = Http::STATUS_OK,
56
+								array $headers = []) {
57 57
 		parent::__construct();
58 58
 
59 59
 		$this->data = $data;
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
 	 * @return DataResponse Reference to this object
69 69
 	 * @since 8.0.0
70 70
 	 */
71
-	public function setData($data){
71
+	public function setData($data) {
72 72
 		$this->data = $data;
73 73
 
74 74
 		return $this;
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
 	 * @return array the data
81 81
 	 * @since 8.0.0
82 82
 	 */
83
-	public function getData(){
83
+	public function getData() {
84 84
 		return $this->data;
85 85
 	}
86 86
 
Please login to merge, or discard this patch.
lib/public/AppFramework/Controller.php 1 patch
Indentation   +112 added lines, -112 removed lines patch added patch discarded remove patch
@@ -46,116 +46,116 @@
 block discarded – undo
46 46
  */
47 47
 abstract class Controller {
48 48
 
49
-	/**
50
-	 * app name
51
-	 * @var string
52
-	 * @since 7.0.0
53
-	 */
54
-	protected $appName;
55
-
56
-	/**
57
-	 * current request
58
-	 * @var \OCP\IRequest
59
-	 * @since 6.0.0
60
-	 */
61
-	protected $request;
62
-
63
-	/**
64
-	 * @var array
65
-	 * @since 7.0.0
66
-	 */
67
-	private $responders;
68
-
69
-	/**
70
-	 * constructor of the controller
71
-	 * @param string $appName the name of the app
72
-	 * @param IRequest $request an instance of the request
73
-	 * @since 6.0.0 - parameter $appName was added in 7.0.0 - parameter $app was removed in 7.0.0
74
-	 */
75
-	public function __construct($appName,
76
-								IRequest $request) {
77
-		$this->appName = $appName;
78
-		$this->request = $request;
79
-
80
-		// default responders
81
-		$this->responders = [
82
-			'json' => function ($data) {
83
-				if ($data instanceof DataResponse) {
84
-					$response = new JSONResponse(
85
-						$data->getData(),
86
-						$data->getStatus()
87
-					);
88
-					$dataHeaders = $data->getHeaders();
89
-					$headers = $response->getHeaders();
90
-					// do not overwrite Content-Type if it already exists
91
-					if (isset($dataHeaders['Content-Type'])) {
92
-						unset($headers['Content-Type']);
93
-					}
94
-					$response->setHeaders(array_merge($dataHeaders, $headers));
95
-					return $response;
96
-				}
97
-				return new JSONResponse($data);
98
-			}
99
-		];
100
-	}
101
-
102
-
103
-	/**
104
-	 * Parses an HTTP accept header and returns the supported responder type
105
-	 * @param string $acceptHeader
106
-	 * @param string $default
107
-	 * @return string the responder type
108
-	 * @since 7.0.0
109
-	 * @since 9.1.0 Added default parameter
110
-	 */
111
-	public function getResponderByHTTPHeader($acceptHeader, $default='json') {
112
-		$headers = explode(',', $acceptHeader);
113
-
114
-		// return the first matching responder
115
-		foreach ($headers as $header) {
116
-			$header = strtolower(trim($header));
117
-
118
-			$responder = str_replace('application/', '', $header);
119
-
120
-			if (array_key_exists($responder, $this->responders)) {
121
-				return $responder;
122
-			}
123
-		}
124
-
125
-		// no matching header return default
126
-		return $default;
127
-	}
128
-
129
-
130
-	/**
131
-	 * Registers a formatter for a type
132
-	 * @param string $format
133
-	 * @param \Closure $responder
134
-	 * @since 7.0.0
135
-	 */
136
-	protected function registerResponder($format, \Closure $responder) {
137
-		$this->responders[$format] = $responder;
138
-	}
139
-
140
-
141
-	/**
142
-	 * Serializes and formats a response
143
-	 * @param mixed $response the value that was returned from a controller and
144
-	 * is not a Response instance
145
-	 * @param string $format the format for which a formatter has been registered
146
-	 * @throws \DomainException if format does not match a registered formatter
147
-	 * @return Response
148
-	 * @since 7.0.0
149
-	 */
150
-	public function buildResponse($response, $format='json') {
151
-		if(array_key_exists($format, $this->responders)) {
152
-
153
-			$responder = $this->responders[$format];
154
-
155
-			return $responder($response);
156
-
157
-		}
158
-		throw new \DomainException('No responder registered for format '.
159
-			$format . '!');
160
-	}
49
+    /**
50
+     * app name
51
+     * @var string
52
+     * @since 7.0.0
53
+     */
54
+    protected $appName;
55
+
56
+    /**
57
+     * current request
58
+     * @var \OCP\IRequest
59
+     * @since 6.0.0
60
+     */
61
+    protected $request;
62
+
63
+    /**
64
+     * @var array
65
+     * @since 7.0.0
66
+     */
67
+    private $responders;
68
+
69
+    /**
70
+     * constructor of the controller
71
+     * @param string $appName the name of the app
72
+     * @param IRequest $request an instance of the request
73
+     * @since 6.0.0 - parameter $appName was added in 7.0.0 - parameter $app was removed in 7.0.0
74
+     */
75
+    public function __construct($appName,
76
+                                IRequest $request) {
77
+        $this->appName = $appName;
78
+        $this->request = $request;
79
+
80
+        // default responders
81
+        $this->responders = [
82
+            'json' => function ($data) {
83
+                if ($data instanceof DataResponse) {
84
+                    $response = new JSONResponse(
85
+                        $data->getData(),
86
+                        $data->getStatus()
87
+                    );
88
+                    $dataHeaders = $data->getHeaders();
89
+                    $headers = $response->getHeaders();
90
+                    // do not overwrite Content-Type if it already exists
91
+                    if (isset($dataHeaders['Content-Type'])) {
92
+                        unset($headers['Content-Type']);
93
+                    }
94
+                    $response->setHeaders(array_merge($dataHeaders, $headers));
95
+                    return $response;
96
+                }
97
+                return new JSONResponse($data);
98
+            }
99
+        ];
100
+    }
101
+
102
+
103
+    /**
104
+     * Parses an HTTP accept header and returns the supported responder type
105
+     * @param string $acceptHeader
106
+     * @param string $default
107
+     * @return string the responder type
108
+     * @since 7.0.0
109
+     * @since 9.1.0 Added default parameter
110
+     */
111
+    public function getResponderByHTTPHeader($acceptHeader, $default='json') {
112
+        $headers = explode(',', $acceptHeader);
113
+
114
+        // return the first matching responder
115
+        foreach ($headers as $header) {
116
+            $header = strtolower(trim($header));
117
+
118
+            $responder = str_replace('application/', '', $header);
119
+
120
+            if (array_key_exists($responder, $this->responders)) {
121
+                return $responder;
122
+            }
123
+        }
124
+
125
+        // no matching header return default
126
+        return $default;
127
+    }
128
+
129
+
130
+    /**
131
+     * Registers a formatter for a type
132
+     * @param string $format
133
+     * @param \Closure $responder
134
+     * @since 7.0.0
135
+     */
136
+    protected function registerResponder($format, \Closure $responder) {
137
+        $this->responders[$format] = $responder;
138
+    }
139
+
140
+
141
+    /**
142
+     * Serializes and formats a response
143
+     * @param mixed $response the value that was returned from a controller and
144
+     * is not a Response instance
145
+     * @param string $format the format for which a formatter has been registered
146
+     * @throws \DomainException if format does not match a registered formatter
147
+     * @return Response
148
+     * @since 7.0.0
149
+     */
150
+    public function buildResponse($response, $format='json') {
151
+        if(array_key_exists($format, $this->responders)) {
152
+
153
+            $responder = $this->responders[$format];
154
+
155
+            return $responder($response);
156
+
157
+        }
158
+        throw new \DomainException('No responder registered for format '.
159
+            $format . '!');
160
+    }
161 161
 }
Please login to merge, or discard this patch.
lib/public/Share.php 1 patch
Indentation   +82 added lines, -82 removed lines patch added patch discarded remove patch
@@ -49,94 +49,94 @@
 block discarded – undo
49 49
  */
50 50
 class Share extends \OC\Share\Constants {
51 51
 
52
-	/**
53
-	 * Get the item of item type shared with a given user by source
54
-	 * @param string $itemType
55
-	 * @param string $itemSource
56
-	 * @param string $user User to whom the item was shared
57
-	 * @param string $owner Owner of the share
58
-	 * @return array Return list of items with file_target, permissions and expiration
59
-	 * @since 6.0.0 - parameter $owner was added in 8.0.0
60
-	 * @deprecated 17.0.0
61
-	 */
62
-	public static function getItemSharedWithUser($itemType, $itemSource, $user, $owner = null) {
63
-		return \OC\Share\Share::getItemSharedWithUser($itemType, $itemSource, $user, $owner);
64
-	}
52
+    /**
53
+     * Get the item of item type shared with a given user by source
54
+     * @param string $itemType
55
+     * @param string $itemSource
56
+     * @param string $user User to whom the item was shared
57
+     * @param string $owner Owner of the share
58
+     * @return array Return list of items with file_target, permissions and expiration
59
+     * @since 6.0.0 - parameter $owner was added in 8.0.0
60
+     * @deprecated 17.0.0
61
+     */
62
+    public static function getItemSharedWithUser($itemType, $itemSource, $user, $owner = null) {
63
+        return \OC\Share\Share::getItemSharedWithUser($itemType, $itemSource, $user, $owner);
64
+    }
65 65
 
66
-	/**
67
-	 * Get the item of item type shared with the current user by source
68
-	 * @param string $itemType
69
-	 * @param string $itemSource
70
-	 * @param int $format (optional) Format type must be defined by the backend
71
-	 * @param mixed $parameters
72
-	 * @param bool $includeCollections
73
-	 * @return array
74
-	 * @since 5.0.0
75
-	 * @deprecated 17.0.0
76
-	 */
77
-	public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
78
-		$parameters = null, $includeCollections = false) {
79
-		// not used by any app - only here to not break apps syntax
80
-	}
66
+    /**
67
+     * Get the item of item type shared with the current user by source
68
+     * @param string $itemType
69
+     * @param string $itemSource
70
+     * @param int $format (optional) Format type must be defined by the backend
71
+     * @param mixed $parameters
72
+     * @param bool $includeCollections
73
+     * @return array
74
+     * @since 5.0.0
75
+     * @deprecated 17.0.0
76
+     */
77
+    public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
78
+        $parameters = null, $includeCollections = false) {
79
+        // not used by any app - only here to not break apps syntax
80
+    }
81 81
 
82
-	/**
83
-	 * Based on the given token the share information will be returned - password protected shares will be verified
84
-	 * @param string $token
85
-	 * @param bool $checkPasswordProtection
86
-	 * @return array|bool false will be returned in case the token is unknown or unauthorized
87
-	 * @since 5.0.0 - parameter $checkPasswordProtection was added in 7.0.0
88
-	 * @deprecated 17.0.0
89
-	 */
90
-	public static function getShareByToken($token, $checkPasswordProtection = true) {
91
-		// not used by any app - only here to not break apps syntax
92
-	}
82
+    /**
83
+     * Based on the given token the share information will be returned - password protected shares will be verified
84
+     * @param string $token
85
+     * @param bool $checkPasswordProtection
86
+     * @return array|bool false will be returned in case the token is unknown or unauthorized
87
+     * @since 5.0.0 - parameter $checkPasswordProtection was added in 7.0.0
88
+     * @deprecated 17.0.0
89
+     */
90
+    public static function getShareByToken($token, $checkPasswordProtection = true) {
91
+        // not used by any app - only here to not break apps syntax
92
+    }
93 93
 
94 94
 
95
-	/**
96
-	 * Get the shared items of item type owned by the current user
97
-	 * @param string $itemType
98
-	 * @param int $format (optional) Format type must be defined by the backend
99
-	 * @param mixed $parameters
100
-	 * @param int $limit Number of items to return (optional) Returns all by default
101
-	 * @param bool $includeCollections
102
-	 * @return mixed Return depends on format
103
-	 * @since 5.0.0
104
-	 * @deprecated 17.0.0
105
-	 */
106
-	public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null,
107
-		$limit = -1, $includeCollections = false) {
95
+    /**
96
+     * Get the shared items of item type owned by the current user
97
+     * @param string $itemType
98
+     * @param int $format (optional) Format type must be defined by the backend
99
+     * @param mixed $parameters
100
+     * @param int $limit Number of items to return (optional) Returns all by default
101
+     * @param bool $includeCollections
102
+     * @return mixed Return depends on format
103
+     * @since 5.0.0
104
+     * @deprecated 17.0.0
105
+     */
106
+    public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null,
107
+        $limit = -1, $includeCollections = false) {
108 108
 
109
-		// only used by AppVNCSafe app (https://github.com/vnc-biz/nextcloud-appvncsafe/issues/2) - only here to not break apps syntax
110
-	}
109
+        // only used by AppVNCSafe app (https://github.com/vnc-biz/nextcloud-appvncsafe/issues/2) - only here to not break apps syntax
110
+    }
111 111
 
112
-	/**
113
-	 * Get the shared item of item type owned by the current user
114
-	 * @param string $itemType
115
-	 * @param string $itemSource
116
-	 * @param int $format (optional) Format type must be defined by the backend
117
-	 * @param mixed $parameters
118
-	 * @param bool $includeCollections
119
-	 * @return mixed Return depends on format
120
-	 * @since 5.0.0
121
-	 * @deprecated 17.0.0
122
-	 */
123
-	public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
124
-										 $parameters = null, $includeCollections = false) {
112
+    /**
113
+     * Get the shared item of item type owned by the current user
114
+     * @param string $itemType
115
+     * @param string $itemSource
116
+     * @param int $format (optional) Format type must be defined by the backend
117
+     * @param mixed $parameters
118
+     * @param bool $includeCollections
119
+     * @return mixed Return depends on format
120
+     * @since 5.0.0
121
+     * @deprecated 17.0.0
122
+     */
123
+    public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
124
+                                            $parameters = null, $includeCollections = false) {
125 125
 
126
-		return \OC\Share\Share::getItemShared($itemType, $itemSource, $format, $parameters, $includeCollections);
127
-	}
126
+        return \OC\Share\Share::getItemShared($itemType, $itemSource, $format, $parameters, $includeCollections);
127
+    }
128 128
 
129
-	/**
130
-	 * sent status if users got informed by mail about share
131
-	 * @param string $itemType
132
-	 * @param string $itemSource
133
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
134
-	 * @param string $recipient with whom was the item shared
135
-	 * @param bool $status
136
-	 * @since 6.0.0 - parameter $originIsSource was added in 8.0.0
137
-	 * @deprecated 17.0.0
138
-	 */
139
-	public static function setSendMailStatus($itemType, $itemSource, $shareType, $recipient, $status) {
140
-		// not used by any app - only here to not break apps syntax
141
-	}
129
+    /**
130
+     * sent status if users got informed by mail about share
131
+     * @param string $itemType
132
+     * @param string $itemSource
133
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
134
+     * @param string $recipient with whom was the item shared
135
+     * @param bool $status
136
+     * @since 6.0.0 - parameter $originIsSource was added in 8.0.0
137
+     * @deprecated 17.0.0
138
+     */
139
+    public static function setSendMailStatus($itemType, $itemSource, $shareType, $recipient, $status) {
140
+        // not used by any app - only here to not break apps syntax
141
+    }
142 142
 }
Please login to merge, or discard this patch.
lib/private/IntegrityCheck/Checker.php 1 patch
Indentation   +536 added lines, -536 removed lines patch added patch discarded remove patch
@@ -58,540 +58,540 @@
 block discarded – undo
58 58
  * @package OC\IntegrityCheck
59 59
  */
60 60
 class Checker {
61
-	const CACHE_KEY = 'oc.integritycheck.checker';
62
-	/** @var EnvironmentHelper */
63
-	private $environmentHelper;
64
-	/** @var AppLocator */
65
-	private $appLocator;
66
-	/** @var FileAccessHelper */
67
-	private $fileAccessHelper;
68
-	/** @var IConfig */
69
-	private $config;
70
-	/** @var ICache */
71
-	private $cache;
72
-	/** @var IAppManager */
73
-	private $appManager;
74
-	/** @var ITempManager */
75
-	private $tempManager;
76
-	/** @var IMimeTypeDetector */
77
-	private $mimeTypeDetector;
78
-
79
-	/**
80
-	 * @param EnvironmentHelper $environmentHelper
81
-	 * @param FileAccessHelper $fileAccessHelper
82
-	 * @param AppLocator $appLocator
83
-	 * @param IConfig $config
84
-	 * @param ICacheFactory $cacheFactory
85
-	 * @param IAppManager $appManager
86
-	 * @param ITempManager $tempManager
87
-	 * @param IMimeTypeDetector $mimeTypeDetector
88
-	 */
89
-	public function __construct(EnvironmentHelper $environmentHelper,
90
-								FileAccessHelper $fileAccessHelper,
91
-								AppLocator $appLocator,
92
-								IConfig $config = null,
93
-								ICacheFactory $cacheFactory,
94
-								IAppManager $appManager = null,
95
-								ITempManager $tempManager,
96
-								IMimeTypeDetector $mimeTypeDetector) {
97
-		$this->environmentHelper = $environmentHelper;
98
-		$this->fileAccessHelper = $fileAccessHelper;
99
-		$this->appLocator = $appLocator;
100
-		$this->config = $config;
101
-		$this->cache = $cacheFactory->createDistributed(self::CACHE_KEY);
102
-		$this->appManager = $appManager;
103
-		$this->tempManager = $tempManager;
104
-		$this->mimeTypeDetector = $mimeTypeDetector;
105
-	}
106
-
107
-	/**
108
-	 * Whether code signing is enforced or not.
109
-	 *
110
-	 * @return bool
111
-	 */
112
-	public function isCodeCheckEnforced(): bool {
113
-		$notSignedChannels = [ '', 'git'];
114
-		if (\in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
115
-			return false;
116
-		}
117
-
118
-		/**
119
-		 * This config option is undocumented and supposed to be so, it's only
120
-		 * applicable for very specific scenarios and we should not advertise it
121
-		 * too prominent. So please do not add it to config.sample.php.
122
-		 */
123
-		$isIntegrityCheckDisabled = false;
124
-		if ($this->config !== null) {
125
-			$isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
126
-		}
127
-		if ($isIntegrityCheckDisabled === true) {
128
-			return false;
129
-		}
130
-
131
-		return true;
132
-	}
133
-
134
-	/**
135
-	 * Enumerates all files belonging to the folder. Sensible defaults are excluded.
136
-	 *
137
-	 * @param string $folderToIterate
138
-	 * @param string $root
139
-	 * @return \RecursiveIteratorIterator
140
-	 * @throws \Exception
141
-	 */
142
-	private function getFolderIterator(string $folderToIterate, string $root = ''): \RecursiveIteratorIterator {
143
-		$dirItr = new \RecursiveDirectoryIterator(
144
-			$folderToIterate,
145
-			\RecursiveDirectoryIterator::SKIP_DOTS
146
-		);
147
-		if($root === '') {
148
-			$root = \OC::$SERVERROOT;
149
-		}
150
-		$root = rtrim($root, '/');
151
-
152
-		$excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
153
-		$excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator, $root);
154
-
155
-		return new \RecursiveIteratorIterator(
156
-			$excludeFoldersIterator,
157
-			\RecursiveIteratorIterator::SELF_FIRST
158
-		);
159
-	}
160
-
161
-	/**
162
-	 * Returns an array of ['filename' => 'SHA512-hash-of-file'] for all files found
163
-	 * in the iterator.
164
-	 *
165
-	 * @param \RecursiveIteratorIterator $iterator
166
-	 * @param string $path
167
-	 * @return array Array of hashes.
168
-	 */
169
-	private function generateHashes(\RecursiveIteratorIterator $iterator,
170
-									string $path): array {
171
-		$hashes = [];
172
-
173
-		$baseDirectoryLength = \strlen($path);
174
-		foreach($iterator as $filename => $data) {
175
-			/** @var \DirectoryIterator $data */
176
-			if($data->isDir()) {
177
-				continue;
178
-			}
179
-
180
-			$relativeFileName = substr($filename, $baseDirectoryLength);
181
-			$relativeFileName = ltrim($relativeFileName, '/');
182
-
183
-			// Exclude signature.json files in the appinfo and root folder
184
-			if($relativeFileName === 'appinfo/signature.json') {
185
-				continue;
186
-			}
187
-			// Exclude signature.json files in the appinfo and core folder
188
-			if($relativeFileName === 'core/signature.json') {
189
-				continue;
190
-			}
191
-
192
-			// The .htaccess file in the root folder of ownCloud can contain
193
-			// custom content after the installation due to the fact that dynamic
194
-			// content is written into it at installation time as well. This
195
-			// includes for example the 404 and 403 instructions.
196
-			// Thus we ignore everything below the first occurrence of
197
-			// "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####" and have the
198
-			// hash generated based on this.
199
-			if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') {
200
-				$fileContent = file_get_contents($filename);
201
-				$explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent);
202
-				if(\count($explodedArray) === 2) {
203
-					$hashes[$relativeFileName] = hash('sha512', $explodedArray[0]);
204
-					continue;
205
-				}
206
-			}
207
-			if ($filename === $this->environmentHelper->getServerRoot() . '/core/js/mimetypelist.js') {
208
-				$oldMimetypeList = new GenerateMimetypeFileBuilder();
209
-				$newFile = $oldMimetypeList->generateFile($this->mimeTypeDetector->getAllAliases());
210
-				if($newFile === file_get_contents($filename)) {
211
-					$hashes[$relativeFileName] = hash('sha512', $oldMimetypeList->generateFile($this->mimeTypeDetector->getOnlyDefaultAliases()));
212
-					continue;
213
-				}
214
-			}
215
-
216
-			$hashes[$relativeFileName] = hash_file('sha512', $filename);
217
-		}
218
-
219
-		return $hashes;
220
-	}
221
-
222
-	/**
223
-	 * Creates the signature data
224
-	 *
225
-	 * @param array $hashes
226
-	 * @param X509 $certificate
227
-	 * @param RSA $privateKey
228
-	 * @return array
229
-	 */
230
-	private function createSignatureData(array $hashes,
231
-										 X509 $certificate,
232
-										 RSA $privateKey): array {
233
-		ksort($hashes);
234
-
235
-		$privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
236
-		$privateKey->setMGFHash('sha512');
237
-		// See https://tools.ietf.org/html/rfc3447#page-38
238
-		$privateKey->setSaltLength(0);
239
-		$signature = $privateKey->sign(json_encode($hashes));
240
-
241
-		return [
242
-			'hashes' => $hashes,
243
-			'signature' => base64_encode($signature),
244
-			'certificate' => $certificate->saveX509($certificate->currentCert),
245
-		];
246
-	}
247
-
248
-	/**
249
-	 * Write the signature of the app in the specified folder
250
-	 *
251
-	 * @param string $path
252
-	 * @param X509 $certificate
253
-	 * @param RSA $privateKey
254
-	 * @throws \Exception
255
-	 */
256
-	public function writeAppSignature($path,
257
-									  X509 $certificate,
258
-									  RSA $privateKey) {
259
-		$appInfoDir = $path . '/appinfo';
260
-		try {
261
-			$this->fileAccessHelper->assertDirectoryExists($appInfoDir);
262
-
263
-			$iterator = $this->getFolderIterator($path);
264
-			$hashes = $this->generateHashes($iterator, $path);
265
-			$signature = $this->createSignatureData($hashes, $certificate, $privateKey);
266
-				$this->fileAccessHelper->file_put_contents(
267
-					$appInfoDir . '/signature.json',
268
-				json_encode($signature, JSON_PRETTY_PRINT)
269
-			);
270
-		} catch (\Exception $e){
271
-			if (!$this->fileAccessHelper->is_writable($appInfoDir)) {
272
-				throw new \Exception($appInfoDir . ' is not writable');
273
-			}
274
-			throw $e;
275
-		}
276
-	}
277
-
278
-	/**
279
-	 * Write the signature of core
280
-	 *
281
-	 * @param X509 $certificate
282
-	 * @param RSA $rsa
283
-	 * @param string $path
284
-	 * @throws \Exception
285
-	 */
286
-	public function writeCoreSignature(X509 $certificate,
287
-									   RSA $rsa,
288
-									   $path) {
289
-		$coreDir = $path . '/core';
290
-		try {
291
-
292
-			$this->fileAccessHelper->assertDirectoryExists($coreDir);
293
-			$iterator = $this->getFolderIterator($path, $path);
294
-			$hashes = $this->generateHashes($iterator, $path);
295
-			$signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
296
-			$this->fileAccessHelper->file_put_contents(
297
-				$coreDir . '/signature.json',
298
-				json_encode($signatureData, JSON_PRETTY_PRINT)
299
-			);
300
-		} catch (\Exception $e){
301
-			if (!$this->fileAccessHelper->is_writable($coreDir)) {
302
-				throw new \Exception($coreDir . ' is not writable');
303
-			}
304
-			throw $e;
305
-		}
306
-	}
307
-
308
-	/**
309
-	 * Verifies the signature for the specified path.
310
-	 *
311
-	 * @param string $signaturePath
312
-	 * @param string $basePath
313
-	 * @param string $certificateCN
314
-	 * @return array
315
-	 * @throws InvalidSignatureException
316
-	 * @throws \Exception
317
-	 */
318
-	private function verify(string $signaturePath, string $basePath, string $certificateCN): array {
319
-		if(!$this->isCodeCheckEnforced()) {
320
-			return [];
321
-		}
322
-
323
-		$content = $this->fileAccessHelper->file_get_contents($signaturePath);
324
-		$signatureData = null;
325
-
326
-		if (\is_string($content)) {
327
-			$signatureData = json_decode($content, true);
328
-		}
329
-		if(!\is_array($signatureData)) {
330
-			throw new InvalidSignatureException('Signature data not found.');
331
-		}
332
-
333
-		$expectedHashes = $signatureData['hashes'];
334
-		ksort($expectedHashes);
335
-		$signature = base64_decode($signatureData['signature']);
336
-		$certificate = $signatureData['certificate'];
337
-
338
-		// Check if certificate is signed by Nextcloud Root Authority
339
-		$x509 = new \phpseclib\File\X509();
340
-		$rootCertificatePublicKey = $this->fileAccessHelper->file_get_contents($this->environmentHelper->getServerRoot().'/resources/codesigning/root.crt');
341
-		$x509->loadCA($rootCertificatePublicKey);
342
-		$x509->loadX509($certificate);
343
-		if(!$x509->validateSignature()) {
344
-			throw new InvalidSignatureException('Certificate is not valid.');
345
-		}
346
-		// Verify if certificate has proper CN. "core" CN is always trusted.
347
-		if($x509->getDN(X509::DN_OPENSSL)['CN'] !== $certificateCN && $x509->getDN(X509::DN_OPENSSL)['CN'] !== 'core') {
348
-			throw new InvalidSignatureException(
349
-					sprintf('Certificate is not valid for required scope. (Requested: %s, current: CN=%s)', $certificateCN, $x509->getDN(true)['CN'])
350
-			);
351
-		}
352
-
353
-		// Check if the signature of the files is valid
354
-		$rsa = new \phpseclib\Crypt\RSA();
355
-		$rsa->loadKey($x509->currentCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']);
356
-		$rsa->setSignatureMode(RSA::SIGNATURE_PSS);
357
-		$rsa->setMGFHash('sha512');
358
-		// See https://tools.ietf.org/html/rfc3447#page-38
359
-		$rsa->setSaltLength(0);
360
-		if(!$rsa->verify(json_encode($expectedHashes), $signature)) {
361
-			throw new InvalidSignatureException('Signature could not get verified.');
362
-		}
363
-
364
-		// Fixes for the updater as shipped with ownCloud 9.0.x: The updater is
365
-		// replaced after the code integrity check is performed.
366
-		//
367
-		// Due to this reason we exclude the whole updater/ folder from the code
368
-		// integrity check.
369
-		if($basePath === $this->environmentHelper->getServerRoot()) {
370
-			foreach($expectedHashes as $fileName => $hash) {
371
-				if(strpos($fileName, 'updater/') === 0) {
372
-					unset($expectedHashes[$fileName]);
373
-				}
374
-			}
375
-		}
376
-
377
-		// Compare the list of files which are not identical
378
-		$currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath);
379
-		$differencesA = array_diff($expectedHashes, $currentInstanceHashes);
380
-		$differencesB = array_diff($currentInstanceHashes, $expectedHashes);
381
-		$differences = array_unique(array_merge($differencesA, $differencesB));
382
-		$differenceArray = [];
383
-		foreach($differences as $filename => $hash) {
384
-			// Check if file should not exist in the new signature table
385
-			if(!array_key_exists($filename, $expectedHashes)) {
386
-				$differenceArray['EXTRA_FILE'][$filename]['expected'] = '';
387
-				$differenceArray['EXTRA_FILE'][$filename]['current'] = $hash;
388
-				continue;
389
-			}
390
-
391
-			// Check if file is missing
392
-			if(!array_key_exists($filename, $currentInstanceHashes)) {
393
-				$differenceArray['FILE_MISSING'][$filename]['expected'] = $expectedHashes[$filename];
394
-				$differenceArray['FILE_MISSING'][$filename]['current'] = '';
395
-				continue;
396
-			}
397
-
398
-			// Check if hash does mismatch
399
-			if($expectedHashes[$filename] !== $currentInstanceHashes[$filename]) {
400
-				$differenceArray['INVALID_HASH'][$filename]['expected'] = $expectedHashes[$filename];
401
-				$differenceArray['INVALID_HASH'][$filename]['current'] = $currentInstanceHashes[$filename];
402
-				continue;
403
-			}
404
-
405
-			// Should never happen.
406
-			throw new \Exception('Invalid behaviour in file hash comparison experienced. Please report this error to the developers.');
407
-		}
408
-
409
-		return $differenceArray;
410
-	}
411
-
412
-	/**
413
-	 * Whether the code integrity check has passed successful or not
414
-	 *
415
-	 * @return bool
416
-	 */
417
-	public function hasPassedCheck(): bool {
418
-		$results = $this->getResults();
419
-		if(empty($results)) {
420
-			return true;
421
-		}
422
-
423
-		return false;
424
-	}
425
-
426
-	/**
427
-	 * @return array
428
-	 */
429
-	public function getResults(): array {
430
-		$cachedResults = $this->cache->get(self::CACHE_KEY);
431
-		if(!\is_null($cachedResults)) {
432
-			return json_decode($cachedResults, true);
433
-		}
434
-
435
-		if ($this->config !== null) {
436
-			return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
437
-		}
438
-		return [];
439
-	}
440
-
441
-	/**
442
-	 * Stores the results in the app config as well as cache
443
-	 *
444
-	 * @param string $scope
445
-	 * @param array $result
446
-	 */
447
-	private function storeResults(string $scope, array $result) {
448
-		$resultArray = $this->getResults();
449
-		unset($resultArray[$scope]);
450
-		if(!empty($result)) {
451
-			$resultArray[$scope] = $result;
452
-		}
453
-		if ($this->config !== null) {
454
-			$this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
455
-		}
456
-		$this->cache->set(self::CACHE_KEY, json_encode($resultArray));
457
-	}
458
-
459
-	/**
460
-	 *
461
-	 * Clean previous results for a proper rescanning. Otherwise
462
-	 */
463
-	private function cleanResults() {
464
-		$this->config->deleteAppValue('core', self::CACHE_KEY);
465
-		$this->cache->remove(self::CACHE_KEY);
466
-	}
467
-
468
-	/**
469
-	 * Verify the signature of $appId. Returns an array with the following content:
470
-	 * [
471
-	 * 	'FILE_MISSING' =>
472
-	 * 	[
473
-	 * 		'filename' => [
474
-	 * 			'expected' => 'expectedSHA512',
475
-	 * 			'current' => 'currentSHA512',
476
-	 * 		],
477
-	 * 	],
478
-	 * 	'EXTRA_FILE' =>
479
-	 * 	[
480
-	 * 		'filename' => [
481
-	 * 			'expected' => 'expectedSHA512',
482
-	 * 			'current' => 'currentSHA512',
483
-	 * 		],
484
-	 * 	],
485
-	 * 	'INVALID_HASH' =>
486
-	 * 	[
487
-	 * 		'filename' => [
488
-	 * 			'expected' => 'expectedSHA512',
489
-	 * 			'current' => 'currentSHA512',
490
-	 * 		],
491
-	 * 	],
492
-	 * ]
493
-	 *
494
-	 * Array may be empty in case no problems have been found.
495
-	 *
496
-	 * @param string $appId
497
-	 * @param string $path Optional path. If none is given it will be guessed.
498
-	 * @return array
499
-	 */
500
-	public function verifyAppSignature(string $appId, string $path = ''): array {
501
-		try {
502
-			if($path === '') {
503
-				$path = $this->appLocator->getAppPath($appId);
504
-			}
505
-			$result = $this->verify(
506
-					$path . '/appinfo/signature.json',
507
-					$path,
508
-					$appId
509
-			);
510
-		} catch (\Exception $e) {
511
-			$result = [
512
-				'EXCEPTION' => [
513
-					'class' => \get_class($e),
514
-					'message' => $e->getMessage(),
515
-				],
516
-			];
517
-		}
518
-		$this->storeResults($appId, $result);
519
-
520
-		return $result;
521
-	}
522
-
523
-	/**
524
-	 * Verify the signature of core. Returns an array with the following content:
525
-	 * [
526
-	 * 	'FILE_MISSING' =>
527
-	 * 	[
528
-	 * 		'filename' => [
529
-	 * 			'expected' => 'expectedSHA512',
530
-	 * 			'current' => 'currentSHA512',
531
-	 * 		],
532
-	 * 	],
533
-	 * 	'EXTRA_FILE' =>
534
-	 * 	[
535
-	 * 		'filename' => [
536
-	 * 			'expected' => 'expectedSHA512',
537
-	 * 			'current' => 'currentSHA512',
538
-	 * 		],
539
-	 * 	],
540
-	 * 	'INVALID_HASH' =>
541
-	 * 	[
542
-	 * 		'filename' => [
543
-	 * 			'expected' => 'expectedSHA512',
544
-	 * 			'current' => 'currentSHA512',
545
-	 * 		],
546
-	 * 	],
547
-	 * ]
548
-	 *
549
-	 * Array may be empty in case no problems have been found.
550
-	 *
551
-	 * @return array
552
-	 */
553
-	public function verifyCoreSignature(): array {
554
-		try {
555
-			$result = $this->verify(
556
-					$this->environmentHelper->getServerRoot() . '/core/signature.json',
557
-					$this->environmentHelper->getServerRoot(),
558
-					'core'
559
-			);
560
-		} catch (\Exception $e) {
561
-			$result = [
562
-				'EXCEPTION' => [
563
-					'class' => \get_class($e),
564
-					'message' => $e->getMessage(),
565
-				],
566
-			];
567
-		}
568
-		$this->storeResults('core', $result);
569
-
570
-		return $result;
571
-	}
572
-
573
-	/**
574
-	 * Verify the core code of the instance as well as all applicable applications
575
-	 * and store the results.
576
-	 */
577
-	public function runInstanceVerification() {
578
-		$this->cleanResults();
579
-		$this->verifyCoreSignature();
580
-		$appIds = $this->appLocator->getAllApps();
581
-		foreach($appIds as $appId) {
582
-			// If an application is shipped a valid signature is required
583
-			$isShipped = $this->appManager->isShipped($appId);
584
-			$appNeedsToBeChecked = false;
585
-			if ($isShipped) {
586
-				$appNeedsToBeChecked = true;
587
-			} elseif ($this->fileAccessHelper->file_exists($this->appLocator->getAppPath($appId) . '/appinfo/signature.json')) {
588
-				// Otherwise only if the application explicitly ships a signature.json file
589
-				$appNeedsToBeChecked = true;
590
-			}
591
-
592
-			if($appNeedsToBeChecked) {
593
-				$this->verifyAppSignature($appId);
594
-			}
595
-		}
596
-	}
61
+    const CACHE_KEY = 'oc.integritycheck.checker';
62
+    /** @var EnvironmentHelper */
63
+    private $environmentHelper;
64
+    /** @var AppLocator */
65
+    private $appLocator;
66
+    /** @var FileAccessHelper */
67
+    private $fileAccessHelper;
68
+    /** @var IConfig */
69
+    private $config;
70
+    /** @var ICache */
71
+    private $cache;
72
+    /** @var IAppManager */
73
+    private $appManager;
74
+    /** @var ITempManager */
75
+    private $tempManager;
76
+    /** @var IMimeTypeDetector */
77
+    private $mimeTypeDetector;
78
+
79
+    /**
80
+     * @param EnvironmentHelper $environmentHelper
81
+     * @param FileAccessHelper $fileAccessHelper
82
+     * @param AppLocator $appLocator
83
+     * @param IConfig $config
84
+     * @param ICacheFactory $cacheFactory
85
+     * @param IAppManager $appManager
86
+     * @param ITempManager $tempManager
87
+     * @param IMimeTypeDetector $mimeTypeDetector
88
+     */
89
+    public function __construct(EnvironmentHelper $environmentHelper,
90
+                                FileAccessHelper $fileAccessHelper,
91
+                                AppLocator $appLocator,
92
+                                IConfig $config = null,
93
+                                ICacheFactory $cacheFactory,
94
+                                IAppManager $appManager = null,
95
+                                ITempManager $tempManager,
96
+                                IMimeTypeDetector $mimeTypeDetector) {
97
+        $this->environmentHelper = $environmentHelper;
98
+        $this->fileAccessHelper = $fileAccessHelper;
99
+        $this->appLocator = $appLocator;
100
+        $this->config = $config;
101
+        $this->cache = $cacheFactory->createDistributed(self::CACHE_KEY);
102
+        $this->appManager = $appManager;
103
+        $this->tempManager = $tempManager;
104
+        $this->mimeTypeDetector = $mimeTypeDetector;
105
+    }
106
+
107
+    /**
108
+     * Whether code signing is enforced or not.
109
+     *
110
+     * @return bool
111
+     */
112
+    public function isCodeCheckEnforced(): bool {
113
+        $notSignedChannels = [ '', 'git'];
114
+        if (\in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
115
+            return false;
116
+        }
117
+
118
+        /**
119
+         * This config option is undocumented and supposed to be so, it's only
120
+         * applicable for very specific scenarios and we should not advertise it
121
+         * too prominent. So please do not add it to config.sample.php.
122
+         */
123
+        $isIntegrityCheckDisabled = false;
124
+        if ($this->config !== null) {
125
+            $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
126
+        }
127
+        if ($isIntegrityCheckDisabled === true) {
128
+            return false;
129
+        }
130
+
131
+        return true;
132
+    }
133
+
134
+    /**
135
+     * Enumerates all files belonging to the folder. Sensible defaults are excluded.
136
+     *
137
+     * @param string $folderToIterate
138
+     * @param string $root
139
+     * @return \RecursiveIteratorIterator
140
+     * @throws \Exception
141
+     */
142
+    private function getFolderIterator(string $folderToIterate, string $root = ''): \RecursiveIteratorIterator {
143
+        $dirItr = new \RecursiveDirectoryIterator(
144
+            $folderToIterate,
145
+            \RecursiveDirectoryIterator::SKIP_DOTS
146
+        );
147
+        if($root === '') {
148
+            $root = \OC::$SERVERROOT;
149
+        }
150
+        $root = rtrim($root, '/');
151
+
152
+        $excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
153
+        $excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator, $root);
154
+
155
+        return new \RecursiveIteratorIterator(
156
+            $excludeFoldersIterator,
157
+            \RecursiveIteratorIterator::SELF_FIRST
158
+        );
159
+    }
160
+
161
+    /**
162
+     * Returns an array of ['filename' => 'SHA512-hash-of-file'] for all files found
163
+     * in the iterator.
164
+     *
165
+     * @param \RecursiveIteratorIterator $iterator
166
+     * @param string $path
167
+     * @return array Array of hashes.
168
+     */
169
+    private function generateHashes(\RecursiveIteratorIterator $iterator,
170
+                                    string $path): array {
171
+        $hashes = [];
172
+
173
+        $baseDirectoryLength = \strlen($path);
174
+        foreach($iterator as $filename => $data) {
175
+            /** @var \DirectoryIterator $data */
176
+            if($data->isDir()) {
177
+                continue;
178
+            }
179
+
180
+            $relativeFileName = substr($filename, $baseDirectoryLength);
181
+            $relativeFileName = ltrim($relativeFileName, '/');
182
+
183
+            // Exclude signature.json files in the appinfo and root folder
184
+            if($relativeFileName === 'appinfo/signature.json') {
185
+                continue;
186
+            }
187
+            // Exclude signature.json files in the appinfo and core folder
188
+            if($relativeFileName === 'core/signature.json') {
189
+                continue;
190
+            }
191
+
192
+            // The .htaccess file in the root folder of ownCloud can contain
193
+            // custom content after the installation due to the fact that dynamic
194
+            // content is written into it at installation time as well. This
195
+            // includes for example the 404 and 403 instructions.
196
+            // Thus we ignore everything below the first occurrence of
197
+            // "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####" and have the
198
+            // hash generated based on this.
199
+            if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') {
200
+                $fileContent = file_get_contents($filename);
201
+                $explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent);
202
+                if(\count($explodedArray) === 2) {
203
+                    $hashes[$relativeFileName] = hash('sha512', $explodedArray[0]);
204
+                    continue;
205
+                }
206
+            }
207
+            if ($filename === $this->environmentHelper->getServerRoot() . '/core/js/mimetypelist.js') {
208
+                $oldMimetypeList = new GenerateMimetypeFileBuilder();
209
+                $newFile = $oldMimetypeList->generateFile($this->mimeTypeDetector->getAllAliases());
210
+                if($newFile === file_get_contents($filename)) {
211
+                    $hashes[$relativeFileName] = hash('sha512', $oldMimetypeList->generateFile($this->mimeTypeDetector->getOnlyDefaultAliases()));
212
+                    continue;
213
+                }
214
+            }
215
+
216
+            $hashes[$relativeFileName] = hash_file('sha512', $filename);
217
+        }
218
+
219
+        return $hashes;
220
+    }
221
+
222
+    /**
223
+     * Creates the signature data
224
+     *
225
+     * @param array $hashes
226
+     * @param X509 $certificate
227
+     * @param RSA $privateKey
228
+     * @return array
229
+     */
230
+    private function createSignatureData(array $hashes,
231
+                                            X509 $certificate,
232
+                                            RSA $privateKey): array {
233
+        ksort($hashes);
234
+
235
+        $privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
236
+        $privateKey->setMGFHash('sha512');
237
+        // See https://tools.ietf.org/html/rfc3447#page-38
238
+        $privateKey->setSaltLength(0);
239
+        $signature = $privateKey->sign(json_encode($hashes));
240
+
241
+        return [
242
+            'hashes' => $hashes,
243
+            'signature' => base64_encode($signature),
244
+            'certificate' => $certificate->saveX509($certificate->currentCert),
245
+        ];
246
+    }
247
+
248
+    /**
249
+     * Write the signature of the app in the specified folder
250
+     *
251
+     * @param string $path
252
+     * @param X509 $certificate
253
+     * @param RSA $privateKey
254
+     * @throws \Exception
255
+     */
256
+    public function writeAppSignature($path,
257
+                                        X509 $certificate,
258
+                                        RSA $privateKey) {
259
+        $appInfoDir = $path . '/appinfo';
260
+        try {
261
+            $this->fileAccessHelper->assertDirectoryExists($appInfoDir);
262
+
263
+            $iterator = $this->getFolderIterator($path);
264
+            $hashes = $this->generateHashes($iterator, $path);
265
+            $signature = $this->createSignatureData($hashes, $certificate, $privateKey);
266
+                $this->fileAccessHelper->file_put_contents(
267
+                    $appInfoDir . '/signature.json',
268
+                json_encode($signature, JSON_PRETTY_PRINT)
269
+            );
270
+        } catch (\Exception $e){
271
+            if (!$this->fileAccessHelper->is_writable($appInfoDir)) {
272
+                throw new \Exception($appInfoDir . ' is not writable');
273
+            }
274
+            throw $e;
275
+        }
276
+    }
277
+
278
+    /**
279
+     * Write the signature of core
280
+     *
281
+     * @param X509 $certificate
282
+     * @param RSA $rsa
283
+     * @param string $path
284
+     * @throws \Exception
285
+     */
286
+    public function writeCoreSignature(X509 $certificate,
287
+                                        RSA $rsa,
288
+                                        $path) {
289
+        $coreDir = $path . '/core';
290
+        try {
291
+
292
+            $this->fileAccessHelper->assertDirectoryExists($coreDir);
293
+            $iterator = $this->getFolderIterator($path, $path);
294
+            $hashes = $this->generateHashes($iterator, $path);
295
+            $signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
296
+            $this->fileAccessHelper->file_put_contents(
297
+                $coreDir . '/signature.json',
298
+                json_encode($signatureData, JSON_PRETTY_PRINT)
299
+            );
300
+        } catch (\Exception $e){
301
+            if (!$this->fileAccessHelper->is_writable($coreDir)) {
302
+                throw new \Exception($coreDir . ' is not writable');
303
+            }
304
+            throw $e;
305
+        }
306
+    }
307
+
308
+    /**
309
+     * Verifies the signature for the specified path.
310
+     *
311
+     * @param string $signaturePath
312
+     * @param string $basePath
313
+     * @param string $certificateCN
314
+     * @return array
315
+     * @throws InvalidSignatureException
316
+     * @throws \Exception
317
+     */
318
+    private function verify(string $signaturePath, string $basePath, string $certificateCN): array {
319
+        if(!$this->isCodeCheckEnforced()) {
320
+            return [];
321
+        }
322
+
323
+        $content = $this->fileAccessHelper->file_get_contents($signaturePath);
324
+        $signatureData = null;
325
+
326
+        if (\is_string($content)) {
327
+            $signatureData = json_decode($content, true);
328
+        }
329
+        if(!\is_array($signatureData)) {
330
+            throw new InvalidSignatureException('Signature data not found.');
331
+        }
332
+
333
+        $expectedHashes = $signatureData['hashes'];
334
+        ksort($expectedHashes);
335
+        $signature = base64_decode($signatureData['signature']);
336
+        $certificate = $signatureData['certificate'];
337
+
338
+        // Check if certificate is signed by Nextcloud Root Authority
339
+        $x509 = new \phpseclib\File\X509();
340
+        $rootCertificatePublicKey = $this->fileAccessHelper->file_get_contents($this->environmentHelper->getServerRoot().'/resources/codesigning/root.crt');
341
+        $x509->loadCA($rootCertificatePublicKey);
342
+        $x509->loadX509($certificate);
343
+        if(!$x509->validateSignature()) {
344
+            throw new InvalidSignatureException('Certificate is not valid.');
345
+        }
346
+        // Verify if certificate has proper CN. "core" CN is always trusted.
347
+        if($x509->getDN(X509::DN_OPENSSL)['CN'] !== $certificateCN && $x509->getDN(X509::DN_OPENSSL)['CN'] !== 'core') {
348
+            throw new InvalidSignatureException(
349
+                    sprintf('Certificate is not valid for required scope. (Requested: %s, current: CN=%s)', $certificateCN, $x509->getDN(true)['CN'])
350
+            );
351
+        }
352
+
353
+        // Check if the signature of the files is valid
354
+        $rsa = new \phpseclib\Crypt\RSA();
355
+        $rsa->loadKey($x509->currentCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']);
356
+        $rsa->setSignatureMode(RSA::SIGNATURE_PSS);
357
+        $rsa->setMGFHash('sha512');
358
+        // See https://tools.ietf.org/html/rfc3447#page-38
359
+        $rsa->setSaltLength(0);
360
+        if(!$rsa->verify(json_encode($expectedHashes), $signature)) {
361
+            throw new InvalidSignatureException('Signature could not get verified.');
362
+        }
363
+
364
+        // Fixes for the updater as shipped with ownCloud 9.0.x: The updater is
365
+        // replaced after the code integrity check is performed.
366
+        //
367
+        // Due to this reason we exclude the whole updater/ folder from the code
368
+        // integrity check.
369
+        if($basePath === $this->environmentHelper->getServerRoot()) {
370
+            foreach($expectedHashes as $fileName => $hash) {
371
+                if(strpos($fileName, 'updater/') === 0) {
372
+                    unset($expectedHashes[$fileName]);
373
+                }
374
+            }
375
+        }
376
+
377
+        // Compare the list of files which are not identical
378
+        $currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath);
379
+        $differencesA = array_diff($expectedHashes, $currentInstanceHashes);
380
+        $differencesB = array_diff($currentInstanceHashes, $expectedHashes);
381
+        $differences = array_unique(array_merge($differencesA, $differencesB));
382
+        $differenceArray = [];
383
+        foreach($differences as $filename => $hash) {
384
+            // Check if file should not exist in the new signature table
385
+            if(!array_key_exists($filename, $expectedHashes)) {
386
+                $differenceArray['EXTRA_FILE'][$filename]['expected'] = '';
387
+                $differenceArray['EXTRA_FILE'][$filename]['current'] = $hash;
388
+                continue;
389
+            }
390
+
391
+            // Check if file is missing
392
+            if(!array_key_exists($filename, $currentInstanceHashes)) {
393
+                $differenceArray['FILE_MISSING'][$filename]['expected'] = $expectedHashes[$filename];
394
+                $differenceArray['FILE_MISSING'][$filename]['current'] = '';
395
+                continue;
396
+            }
397
+
398
+            // Check if hash does mismatch
399
+            if($expectedHashes[$filename] !== $currentInstanceHashes[$filename]) {
400
+                $differenceArray['INVALID_HASH'][$filename]['expected'] = $expectedHashes[$filename];
401
+                $differenceArray['INVALID_HASH'][$filename]['current'] = $currentInstanceHashes[$filename];
402
+                continue;
403
+            }
404
+
405
+            // Should never happen.
406
+            throw new \Exception('Invalid behaviour in file hash comparison experienced. Please report this error to the developers.');
407
+        }
408
+
409
+        return $differenceArray;
410
+    }
411
+
412
+    /**
413
+     * Whether the code integrity check has passed successful or not
414
+     *
415
+     * @return bool
416
+     */
417
+    public function hasPassedCheck(): bool {
418
+        $results = $this->getResults();
419
+        if(empty($results)) {
420
+            return true;
421
+        }
422
+
423
+        return false;
424
+    }
425
+
426
+    /**
427
+     * @return array
428
+     */
429
+    public function getResults(): array {
430
+        $cachedResults = $this->cache->get(self::CACHE_KEY);
431
+        if(!\is_null($cachedResults)) {
432
+            return json_decode($cachedResults, true);
433
+        }
434
+
435
+        if ($this->config !== null) {
436
+            return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
437
+        }
438
+        return [];
439
+    }
440
+
441
+    /**
442
+     * Stores the results in the app config as well as cache
443
+     *
444
+     * @param string $scope
445
+     * @param array $result
446
+     */
447
+    private function storeResults(string $scope, array $result) {
448
+        $resultArray = $this->getResults();
449
+        unset($resultArray[$scope]);
450
+        if(!empty($result)) {
451
+            $resultArray[$scope] = $result;
452
+        }
453
+        if ($this->config !== null) {
454
+            $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
455
+        }
456
+        $this->cache->set(self::CACHE_KEY, json_encode($resultArray));
457
+    }
458
+
459
+    /**
460
+     *
461
+     * Clean previous results for a proper rescanning. Otherwise
462
+     */
463
+    private function cleanResults() {
464
+        $this->config->deleteAppValue('core', self::CACHE_KEY);
465
+        $this->cache->remove(self::CACHE_KEY);
466
+    }
467
+
468
+    /**
469
+     * Verify the signature of $appId. Returns an array with the following content:
470
+     * [
471
+     * 	'FILE_MISSING' =>
472
+     * 	[
473
+     * 		'filename' => [
474
+     * 			'expected' => 'expectedSHA512',
475
+     * 			'current' => 'currentSHA512',
476
+     * 		],
477
+     * 	],
478
+     * 	'EXTRA_FILE' =>
479
+     * 	[
480
+     * 		'filename' => [
481
+     * 			'expected' => 'expectedSHA512',
482
+     * 			'current' => 'currentSHA512',
483
+     * 		],
484
+     * 	],
485
+     * 	'INVALID_HASH' =>
486
+     * 	[
487
+     * 		'filename' => [
488
+     * 			'expected' => 'expectedSHA512',
489
+     * 			'current' => 'currentSHA512',
490
+     * 		],
491
+     * 	],
492
+     * ]
493
+     *
494
+     * Array may be empty in case no problems have been found.
495
+     *
496
+     * @param string $appId
497
+     * @param string $path Optional path. If none is given it will be guessed.
498
+     * @return array
499
+     */
500
+    public function verifyAppSignature(string $appId, string $path = ''): array {
501
+        try {
502
+            if($path === '') {
503
+                $path = $this->appLocator->getAppPath($appId);
504
+            }
505
+            $result = $this->verify(
506
+                    $path . '/appinfo/signature.json',
507
+                    $path,
508
+                    $appId
509
+            );
510
+        } catch (\Exception $e) {
511
+            $result = [
512
+                'EXCEPTION' => [
513
+                    'class' => \get_class($e),
514
+                    'message' => $e->getMessage(),
515
+                ],
516
+            ];
517
+        }
518
+        $this->storeResults($appId, $result);
519
+
520
+        return $result;
521
+    }
522
+
523
+    /**
524
+     * Verify the signature of core. Returns an array with the following content:
525
+     * [
526
+     * 	'FILE_MISSING' =>
527
+     * 	[
528
+     * 		'filename' => [
529
+     * 			'expected' => 'expectedSHA512',
530
+     * 			'current' => 'currentSHA512',
531
+     * 		],
532
+     * 	],
533
+     * 	'EXTRA_FILE' =>
534
+     * 	[
535
+     * 		'filename' => [
536
+     * 			'expected' => 'expectedSHA512',
537
+     * 			'current' => 'currentSHA512',
538
+     * 		],
539
+     * 	],
540
+     * 	'INVALID_HASH' =>
541
+     * 	[
542
+     * 		'filename' => [
543
+     * 			'expected' => 'expectedSHA512',
544
+     * 			'current' => 'currentSHA512',
545
+     * 		],
546
+     * 	],
547
+     * ]
548
+     *
549
+     * Array may be empty in case no problems have been found.
550
+     *
551
+     * @return array
552
+     */
553
+    public function verifyCoreSignature(): array {
554
+        try {
555
+            $result = $this->verify(
556
+                    $this->environmentHelper->getServerRoot() . '/core/signature.json',
557
+                    $this->environmentHelper->getServerRoot(),
558
+                    'core'
559
+            );
560
+        } catch (\Exception $e) {
561
+            $result = [
562
+                'EXCEPTION' => [
563
+                    'class' => \get_class($e),
564
+                    'message' => $e->getMessage(),
565
+                ],
566
+            ];
567
+        }
568
+        $this->storeResults('core', $result);
569
+
570
+        return $result;
571
+    }
572
+
573
+    /**
574
+     * Verify the core code of the instance as well as all applicable applications
575
+     * and store the results.
576
+     */
577
+    public function runInstanceVerification() {
578
+        $this->cleanResults();
579
+        $this->verifyCoreSignature();
580
+        $appIds = $this->appLocator->getAllApps();
581
+        foreach($appIds as $appId) {
582
+            // If an application is shipped a valid signature is required
583
+            $isShipped = $this->appManager->isShipped($appId);
584
+            $appNeedsToBeChecked = false;
585
+            if ($isShipped) {
586
+                $appNeedsToBeChecked = true;
587
+            } elseif ($this->fileAccessHelper->file_exists($this->appLocator->getAppPath($appId) . '/appinfo/signature.json')) {
588
+                // Otherwise only if the application explicitly ships a signature.json file
589
+                $appNeedsToBeChecked = true;
590
+            }
591
+
592
+            if($appNeedsToBeChecked) {
593
+                $this->verifyAppSignature($appId);
594
+            }
595
+        }
596
+    }
597 597
 }
Please login to merge, or discard this patch.
lib/private/Preview/Generator.php 1 patch
Indentation   +395 added lines, -395 removed lines patch added patch discarded remove patch
@@ -42,413 +42,413 @@
 block discarded – undo
42 42
 
43 43
 class Generator {
44 44
 
45
-	/** @var IPreview */
46
-	private $previewManager;
47
-	/** @var IConfig */
48
-	private $config;
49
-	/** @var IAppData */
50
-	private $appData;
51
-	/** @var GeneratorHelper */
52
-	private $helper;
53
-	/** @var EventDispatcherInterface */
54
-	private $eventDispatcher;
55
-
56
-	/**
57
-	 * @param IConfig $config
58
-	 * @param IPreview $previewManager
59
-	 * @param IAppData $appData
60
-	 * @param GeneratorHelper $helper
61
-	 * @param EventDispatcherInterface $eventDispatcher
62
-	 */
63
-	public function __construct(
64
-		IConfig $config,
65
-		IPreview $previewManager,
66
-		IAppData $appData,
67
-		GeneratorHelper $helper,
68
-		EventDispatcherInterface $eventDispatcher
69
-	) {
70
-		$this->config = $config;
71
-		$this->previewManager = $previewManager;
72
-		$this->appData = $appData;
73
-		$this->helper = $helper;
74
-		$this->eventDispatcher = $eventDispatcher;
75
-	}
76
-
77
-	/**
78
-	 * Returns a preview of a file
79
-	 *
80
-	 * The cache is searched first and if nothing usable was found then a preview is
81
-	 * generated by one of the providers
82
-	 *
83
-	 * @param File $file
84
-	 * @param int $width
85
-	 * @param int $height
86
-	 * @param bool $crop
87
-	 * @param string $mode
88
-	 * @param string $mimeType
89
-	 * @return ISimpleFile
90
-	 * @throws NotFoundException
91
-	 * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
92
-	 */
93
-	public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
94
-		//Make sure that we can read the file
95
-		if (!$file->isReadable()) {
96
-			throw new NotFoundException('Cannot read file');
97
-		}
98
-
99
-
100
-		$this->eventDispatcher->dispatch(
101
-			IPreview::EVENT,
102
-			new GenericEvent($file, [
103
-				'width' => $width,
104
-				'height' => $height,
105
-				'crop' => $crop,
106
-				'mode' => $mode
107
-			])
108
-		);
109
-
110
-		if ($mimeType === null) {
111
-			$mimeType = $file->getMimeType();
112
-		}
113
-		if (!$this->previewManager->isMimeSupported($mimeType)) {
114
-			throw new NotFoundException();
115
-		}
116
-
117
-		$previewFolder = $this->getPreviewFolder($file);
118
-
119
-		$previewVersion = '';
120
-		if ($file instanceof IVersionedPreviewFile) {
121
-			$previewVersion = $file->getPreviewVersion() . '-';
122
-		}
123
-
124
-		// Get the max preview and infer the max preview sizes from that
125
-		$maxPreview = $this->getMaxPreview($previewFolder, $file, $mimeType, $previewVersion);
126
-		if ($maxPreview->getSize() === 0) {
127
-			$maxPreview->delete();
128
-			throw new NotFoundException('Max preview size 0, invalid!');
129
-		}
130
-
131
-		list($maxWidth, $maxHeight) = $this->getPreviewSize($maxPreview, $previewVersion);
132
-
133
-		// If both width and heigth are -1 we just want the max preview
134
-		if ($width === -1 && $height === -1) {
135
-			$width = $maxWidth;
136
-			$height = $maxHeight;
137
-		}
138
-
139
-		// Calculate the preview size
140
-		list($width, $height) = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight);
141
-
142
-		// No need to generate a preview that is just the max preview
143
-		if ($width === $maxWidth && $height === $maxHeight) {
144
-			return $maxPreview;
145
-		}
146
-
147
-		// Try to get a cached preview. Else generate (and store) one
148
-		try {
149
-			try {
150
-				$preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion);
151
-			} catch (NotFoundException $e) {
152
-				$preview = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion);
153
-			}
154
-		} catch (\InvalidArgumentException $e) {
155
-			throw new NotFoundException();
156
-		}
157
-
158
-		if ($preview->getSize() === 0) {
159
-			$preview->delete();
160
-			throw new NotFoundException('Cached preview size 0, invalid!');
161
-		}
162
-
163
-		return $preview;
164
-	}
165
-
166
-	/**
167
-	 * @param ISimpleFolder $previewFolder
168
-	 * @param File $file
169
-	 * @param string $mimeType
170
-	 * @param string $prefix
171
-	 * @return ISimpleFile
172
-	 * @throws NotFoundException
173
-	 */
174
-	private function getMaxPreview(ISimpleFolder $previewFolder, File $file, $mimeType, $prefix) {
175
-		$nodes = $previewFolder->getDirectoryListing();
176
-
177
-		foreach ($nodes as $node) {
178
-			$name = $node->getName();
179
-			if (($prefix === '' || strpos($name, $prefix) === 0) && strpos($name, 'max')) {
180
-				return $node;
181
-			}
182
-		}
183
-
184
-		$previewProviders = $this->previewManager->getProviders();
185
-		foreach ($previewProviders as $supportedMimeType => $providers) {
186
-			if (!preg_match($supportedMimeType, $mimeType)) {
187
-				continue;
188
-			}
189
-
190
-			foreach ($providers as $providerClosure) {
191
-				$provider = $this->helper->getProvider($providerClosure);
192
-				if (!($provider instanceof IProviderV2)) {
193
-					continue;
194
-				}
195
-
196
-				if (!$provider->isAvailable($file)) {
197
-					continue;
198
-				}
199
-
200
-				$maxWidth = (int)$this->config->getSystemValue('preview_max_x', 4096);
201
-				$maxHeight = (int)$this->config->getSystemValue('preview_max_y', 4096);
202
-
203
-				$preview = $this->helper->getThumbnail($provider, $file, $maxWidth, $maxHeight);
204
-
205
-				if (!($preview instanceof IImage)) {
206
-					continue;
207
-				}
208
-
209
-				// Try to get the extention.
210
-				try {
211
-					$ext = $this->getExtention($preview->dataMimeType());
212
-				} catch (\InvalidArgumentException $e) {
213
-					// Just continue to the next iteration if this preview doesn't have a valid mimetype
214
-					continue;
215
-				}
216
-
217
-				$path = $prefix . (string)$preview->width() . '-' . (string)$preview->height() . '-max.' . $ext;
218
-				try {
219
-					$file = $previewFolder->newFile($path);
220
-					$file->putContent($preview->data());
221
-				} catch (NotPermittedException $e) {
222
-					throw new NotFoundException();
223
-				}
224
-
225
-				return $file;
226
-			}
227
-		}
228
-
229
-		throw new NotFoundException();
230
-	}
231
-
232
-	/**
233
-	 * @param ISimpleFile $file
234
-	 * @param string $prefix
235
-	 * @return int[]
236
-	 */
237
-	private function getPreviewSize(ISimpleFile $file, string $prefix = '') {
238
-		$size = explode('-', substr($file->getName(), strlen($prefix)));
239
-		return [(int)$size[0], (int)$size[1]];
240
-	}
241
-
242
-	/**
243
-	 * @param int $width
244
-	 * @param int $height
245
-	 * @param bool $crop
246
-	 * @param string $mimeType
247
-	 * @param string $prefix
248
-	 * @return string
249
-	 */
250
-	private function generatePath($width, $height, $crop, $mimeType, $prefix) {
251
-		$path = $prefix . (string)$width . '-' . (string)$height;
252
-		if ($crop) {
253
-			$path .= '-crop';
254
-		}
255
-
256
-		$ext = $this->getExtention($mimeType);
257
-		$path .= '.' . $ext;
258
-		return $path;
259
-	}
260
-
261
-
262
-	/**
263
-	 * @param int $width
264
-	 * @param int $height
265
-	 * @param bool $crop
266
-	 * @param string $mode
267
-	 * @param int $maxWidth
268
-	 * @param int $maxHeight
269
-	 * @return int[]
270
-	 */
271
-	private function calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight) {
272
-
273
-		/*
45
+    /** @var IPreview */
46
+    private $previewManager;
47
+    /** @var IConfig */
48
+    private $config;
49
+    /** @var IAppData */
50
+    private $appData;
51
+    /** @var GeneratorHelper */
52
+    private $helper;
53
+    /** @var EventDispatcherInterface */
54
+    private $eventDispatcher;
55
+
56
+    /**
57
+     * @param IConfig $config
58
+     * @param IPreview $previewManager
59
+     * @param IAppData $appData
60
+     * @param GeneratorHelper $helper
61
+     * @param EventDispatcherInterface $eventDispatcher
62
+     */
63
+    public function __construct(
64
+        IConfig $config,
65
+        IPreview $previewManager,
66
+        IAppData $appData,
67
+        GeneratorHelper $helper,
68
+        EventDispatcherInterface $eventDispatcher
69
+    ) {
70
+        $this->config = $config;
71
+        $this->previewManager = $previewManager;
72
+        $this->appData = $appData;
73
+        $this->helper = $helper;
74
+        $this->eventDispatcher = $eventDispatcher;
75
+    }
76
+
77
+    /**
78
+     * Returns a preview of a file
79
+     *
80
+     * The cache is searched first and if nothing usable was found then a preview is
81
+     * generated by one of the providers
82
+     *
83
+     * @param File $file
84
+     * @param int $width
85
+     * @param int $height
86
+     * @param bool $crop
87
+     * @param string $mode
88
+     * @param string $mimeType
89
+     * @return ISimpleFile
90
+     * @throws NotFoundException
91
+     * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
92
+     */
93
+    public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
94
+        //Make sure that we can read the file
95
+        if (!$file->isReadable()) {
96
+            throw new NotFoundException('Cannot read file');
97
+        }
98
+
99
+
100
+        $this->eventDispatcher->dispatch(
101
+            IPreview::EVENT,
102
+            new GenericEvent($file, [
103
+                'width' => $width,
104
+                'height' => $height,
105
+                'crop' => $crop,
106
+                'mode' => $mode
107
+            ])
108
+        );
109
+
110
+        if ($mimeType === null) {
111
+            $mimeType = $file->getMimeType();
112
+        }
113
+        if (!$this->previewManager->isMimeSupported($mimeType)) {
114
+            throw new NotFoundException();
115
+        }
116
+
117
+        $previewFolder = $this->getPreviewFolder($file);
118
+
119
+        $previewVersion = '';
120
+        if ($file instanceof IVersionedPreviewFile) {
121
+            $previewVersion = $file->getPreviewVersion() . '-';
122
+        }
123
+
124
+        // Get the max preview and infer the max preview sizes from that
125
+        $maxPreview = $this->getMaxPreview($previewFolder, $file, $mimeType, $previewVersion);
126
+        if ($maxPreview->getSize() === 0) {
127
+            $maxPreview->delete();
128
+            throw new NotFoundException('Max preview size 0, invalid!');
129
+        }
130
+
131
+        list($maxWidth, $maxHeight) = $this->getPreviewSize($maxPreview, $previewVersion);
132
+
133
+        // If both width and heigth are -1 we just want the max preview
134
+        if ($width === -1 && $height === -1) {
135
+            $width = $maxWidth;
136
+            $height = $maxHeight;
137
+        }
138
+
139
+        // Calculate the preview size
140
+        list($width, $height) = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight);
141
+
142
+        // No need to generate a preview that is just the max preview
143
+        if ($width === $maxWidth && $height === $maxHeight) {
144
+            return $maxPreview;
145
+        }
146
+
147
+        // Try to get a cached preview. Else generate (and store) one
148
+        try {
149
+            try {
150
+                $preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion);
151
+            } catch (NotFoundException $e) {
152
+                $preview = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion);
153
+            }
154
+        } catch (\InvalidArgumentException $e) {
155
+            throw new NotFoundException();
156
+        }
157
+
158
+        if ($preview->getSize() === 0) {
159
+            $preview->delete();
160
+            throw new NotFoundException('Cached preview size 0, invalid!');
161
+        }
162
+
163
+        return $preview;
164
+    }
165
+
166
+    /**
167
+     * @param ISimpleFolder $previewFolder
168
+     * @param File $file
169
+     * @param string $mimeType
170
+     * @param string $prefix
171
+     * @return ISimpleFile
172
+     * @throws NotFoundException
173
+     */
174
+    private function getMaxPreview(ISimpleFolder $previewFolder, File $file, $mimeType, $prefix) {
175
+        $nodes = $previewFolder->getDirectoryListing();
176
+
177
+        foreach ($nodes as $node) {
178
+            $name = $node->getName();
179
+            if (($prefix === '' || strpos($name, $prefix) === 0) && strpos($name, 'max')) {
180
+                return $node;
181
+            }
182
+        }
183
+
184
+        $previewProviders = $this->previewManager->getProviders();
185
+        foreach ($previewProviders as $supportedMimeType => $providers) {
186
+            if (!preg_match($supportedMimeType, $mimeType)) {
187
+                continue;
188
+            }
189
+
190
+            foreach ($providers as $providerClosure) {
191
+                $provider = $this->helper->getProvider($providerClosure);
192
+                if (!($provider instanceof IProviderV2)) {
193
+                    continue;
194
+                }
195
+
196
+                if (!$provider->isAvailable($file)) {
197
+                    continue;
198
+                }
199
+
200
+                $maxWidth = (int)$this->config->getSystemValue('preview_max_x', 4096);
201
+                $maxHeight = (int)$this->config->getSystemValue('preview_max_y', 4096);
202
+
203
+                $preview = $this->helper->getThumbnail($provider, $file, $maxWidth, $maxHeight);
204
+
205
+                if (!($preview instanceof IImage)) {
206
+                    continue;
207
+                }
208
+
209
+                // Try to get the extention.
210
+                try {
211
+                    $ext = $this->getExtention($preview->dataMimeType());
212
+                } catch (\InvalidArgumentException $e) {
213
+                    // Just continue to the next iteration if this preview doesn't have a valid mimetype
214
+                    continue;
215
+                }
216
+
217
+                $path = $prefix . (string)$preview->width() . '-' . (string)$preview->height() . '-max.' . $ext;
218
+                try {
219
+                    $file = $previewFolder->newFile($path);
220
+                    $file->putContent($preview->data());
221
+                } catch (NotPermittedException $e) {
222
+                    throw new NotFoundException();
223
+                }
224
+
225
+                return $file;
226
+            }
227
+        }
228
+
229
+        throw new NotFoundException();
230
+    }
231
+
232
+    /**
233
+     * @param ISimpleFile $file
234
+     * @param string $prefix
235
+     * @return int[]
236
+     */
237
+    private function getPreviewSize(ISimpleFile $file, string $prefix = '') {
238
+        $size = explode('-', substr($file->getName(), strlen($prefix)));
239
+        return [(int)$size[0], (int)$size[1]];
240
+    }
241
+
242
+    /**
243
+     * @param int $width
244
+     * @param int $height
245
+     * @param bool $crop
246
+     * @param string $mimeType
247
+     * @param string $prefix
248
+     * @return string
249
+     */
250
+    private function generatePath($width, $height, $crop, $mimeType, $prefix) {
251
+        $path = $prefix . (string)$width . '-' . (string)$height;
252
+        if ($crop) {
253
+            $path .= '-crop';
254
+        }
255
+
256
+        $ext = $this->getExtention($mimeType);
257
+        $path .= '.' . $ext;
258
+        return $path;
259
+    }
260
+
261
+
262
+    /**
263
+     * @param int $width
264
+     * @param int $height
265
+     * @param bool $crop
266
+     * @param string $mode
267
+     * @param int $maxWidth
268
+     * @param int $maxHeight
269
+     * @return int[]
270
+     */
271
+    private function calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight) {
272
+
273
+        /*
274 274
 		 * If we are not cropping we have to make sure the requested image
275 275
 		 * respects the aspect ratio of the original.
276 276
 		 */
277
-		if (!$crop) {
278
-			$ratio = $maxHeight / $maxWidth;
277
+        if (!$crop) {
278
+            $ratio = $maxHeight / $maxWidth;
279 279
 
280
-			if ($width === -1) {
281
-				$width = $height / $ratio;
282
-			}
283
-			if ($height === -1) {
284
-				$height = $width * $ratio;
285
-			}
280
+            if ($width === -1) {
281
+                $width = $height / $ratio;
282
+            }
283
+            if ($height === -1) {
284
+                $height = $width * $ratio;
285
+            }
286 286
 
287
-			$ratioH = $height / $maxHeight;
288
-			$ratioW = $width / $maxWidth;
287
+            $ratioH = $height / $maxHeight;
288
+            $ratioW = $width / $maxWidth;
289 289
 
290
-			/*
290
+            /*
291 291
 			 * Fill means that the $height and $width are the max
292 292
 			 * Cover means min.
293 293
 			 */
294
-			if ($mode === IPreview::MODE_FILL) {
295
-				if ($ratioH > $ratioW) {
296
-					$height = $width * $ratio;
297
-				} else {
298
-					$width = $height / $ratio;
299
-				}
300
-			} else if ($mode === IPreview::MODE_COVER) {
301
-				if ($ratioH > $ratioW) {
302
-					$width = $height / $ratio;
303
-				} else {
304
-					$height = $width * $ratio;
305
-				}
306
-			}
307
-		}
308
-
309
-		if ($height !== $maxHeight && $width !== $maxWidth) {
310
-			/*
294
+            if ($mode === IPreview::MODE_FILL) {
295
+                if ($ratioH > $ratioW) {
296
+                    $height = $width * $ratio;
297
+                } else {
298
+                    $width = $height / $ratio;
299
+                }
300
+            } else if ($mode === IPreview::MODE_COVER) {
301
+                if ($ratioH > $ratioW) {
302
+                    $width = $height / $ratio;
303
+                } else {
304
+                    $height = $width * $ratio;
305
+                }
306
+            }
307
+        }
308
+
309
+        if ($height !== $maxHeight && $width !== $maxWidth) {
310
+            /*
311 311
 			 * Scale to the nearest power of four
312 312
 			 */
313
-			$pow4height = 4 ** ceil(log($height) / log(4));
314
-			$pow4width = 4 ** ceil(log($width) / log(4));
315
-
316
-			// Minimum size is 64
317
-			$pow4height = max($pow4height, 64);
318
-			$pow4width = max($pow4width, 64);
319
-
320
-			$ratioH = $height / $pow4height;
321
-			$ratioW = $width / $pow4width;
322
-
323
-			if ($ratioH < $ratioW) {
324
-				$width = $pow4width;
325
-				$height /= $ratioW;
326
-			} else {
327
-				$height = $pow4height;
328
-				$width /= $ratioH;
329
-			}
330
-		}
331
-
332
-		/*
313
+            $pow4height = 4 ** ceil(log($height) / log(4));
314
+            $pow4width = 4 ** ceil(log($width) / log(4));
315
+
316
+            // Minimum size is 64
317
+            $pow4height = max($pow4height, 64);
318
+            $pow4width = max($pow4width, 64);
319
+
320
+            $ratioH = $height / $pow4height;
321
+            $ratioW = $width / $pow4width;
322
+
323
+            if ($ratioH < $ratioW) {
324
+                $width = $pow4width;
325
+                $height /= $ratioW;
326
+            } else {
327
+                $height = $pow4height;
328
+                $width /= $ratioH;
329
+            }
330
+        }
331
+
332
+        /*
333 333
 		 * Make sure the requested height and width fall within the max
334 334
 		 * of the preview.
335 335
 		 */
336
-		if ($height > $maxHeight) {
337
-			$ratio = $height / $maxHeight;
338
-			$height = $maxHeight;
339
-			$width /= $ratio;
340
-		}
341
-		if ($width > $maxWidth) {
342
-			$ratio = $width / $maxWidth;
343
-			$width = $maxWidth;
344
-			$height /= $ratio;
345
-		}
346
-
347
-		return [(int)round($width), (int)round($height)];
348
-	}
349
-
350
-	/**
351
-	 * @param ISimpleFolder $previewFolder
352
-	 * @param ISimpleFile $maxPreview
353
-	 * @param int $width
354
-	 * @param int $height
355
-	 * @param bool $crop
356
-	 * @param int $maxWidth
357
-	 * @param int $maxHeight
358
-	 * @param string $prefix
359
-	 * @return ISimpleFile
360
-	 * @throws NotFoundException
361
-	 * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
362
-	 */
363
-	private function generatePreview(ISimpleFolder $previewFolder, ISimpleFile $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) {
364
-		$preview = $this->helper->getImage($maxPreview);
365
-
366
-		if (!$preview->valid()) {
367
-			throw new \InvalidArgumentException('Failed to generate preview, failed to load image');
368
-		}
369
-
370
-		if ($crop) {
371
-			if ($height !== $preview->height() && $width !== $preview->width()) {
372
-				//Resize
373
-				$widthR = $preview->width() / $width;
374
-				$heightR = $preview->height() / $height;
375
-
376
-				if ($widthR > $heightR) {
377
-					$scaleH = $height;
378
-					$scaleW = $maxWidth / $heightR;
379
-				} else {
380
-					$scaleH = $maxHeight / $widthR;
381
-					$scaleW = $width;
382
-				}
383
-				$preview->preciseResize((int)round($scaleW), (int)round($scaleH));
384
-			}
385
-			$cropX = (int)floor(abs($width - $preview->width()) * 0.5);
386
-			$cropY = (int)floor(abs($height - $preview->height()) * 0.5);
387
-			$preview->crop($cropX, $cropY, $width, $height);
388
-		} else {
389
-			$preview->resize(max($width, $height));
390
-		}
391
-
392
-
393
-		$path = $this->generatePath($width, $height, $crop, $preview->dataMimeType(), $prefix);
394
-		try {
395
-			$file = $previewFolder->newFile($path);
396
-			$file->putContent($preview->data());
397
-		} catch (NotPermittedException $e) {
398
-			throw new NotFoundException();
399
-		}
400
-
401
-		return $file;
402
-	}
403
-
404
-	/**
405
-	 * @param ISimpleFolder $previewFolder
406
-	 * @param int $width
407
-	 * @param int $height
408
-	 * @param bool $crop
409
-	 * @param string $mimeType
410
-	 * @param string $prefix
411
-	 * @return ISimpleFile
412
-	 *
413
-	 * @throws NotFoundException
414
-	 */
415
-	private function getCachedPreview(ISimpleFolder $previewFolder, $width, $height, $crop, $mimeType, $prefix) {
416
-		$path = $this->generatePath($width, $height, $crop, $mimeType, $prefix);
417
-
418
-		return $previewFolder->getFile($path);
419
-	}
420
-
421
-	/**
422
-	 * Get the specific preview folder for this file
423
-	 *
424
-	 * @param File $file
425
-	 * @return ISimpleFolder
426
-	 */
427
-	private function getPreviewFolder(File $file) {
428
-		try {
429
-			$folder = $this->appData->getFolder($file->getId());
430
-		} catch (NotFoundException $e) {
431
-			$folder = $this->appData->newFolder($file->getId());
432
-		}
433
-
434
-		return $folder;
435
-	}
436
-
437
-	/**
438
-	 * @param string $mimeType
439
-	 * @return null|string
440
-	 * @throws \InvalidArgumentException
441
-	 */
442
-	private function getExtention($mimeType) {
443
-		switch ($mimeType) {
444
-			case 'image/png':
445
-				return 'png';
446
-			case 'image/jpeg':
447
-				return 'jpg';
448
-			case 'image/gif':
449
-				return 'gif';
450
-			default:
451
-				throw new \InvalidArgumentException('Not a valid mimetype');
452
-		}
453
-	}
336
+        if ($height > $maxHeight) {
337
+            $ratio = $height / $maxHeight;
338
+            $height = $maxHeight;
339
+            $width /= $ratio;
340
+        }
341
+        if ($width > $maxWidth) {
342
+            $ratio = $width / $maxWidth;
343
+            $width = $maxWidth;
344
+            $height /= $ratio;
345
+        }
346
+
347
+        return [(int)round($width), (int)round($height)];
348
+    }
349
+
350
+    /**
351
+     * @param ISimpleFolder $previewFolder
352
+     * @param ISimpleFile $maxPreview
353
+     * @param int $width
354
+     * @param int $height
355
+     * @param bool $crop
356
+     * @param int $maxWidth
357
+     * @param int $maxHeight
358
+     * @param string $prefix
359
+     * @return ISimpleFile
360
+     * @throws NotFoundException
361
+     * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
362
+     */
363
+    private function generatePreview(ISimpleFolder $previewFolder, ISimpleFile $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) {
364
+        $preview = $this->helper->getImage($maxPreview);
365
+
366
+        if (!$preview->valid()) {
367
+            throw new \InvalidArgumentException('Failed to generate preview, failed to load image');
368
+        }
369
+
370
+        if ($crop) {
371
+            if ($height !== $preview->height() && $width !== $preview->width()) {
372
+                //Resize
373
+                $widthR = $preview->width() / $width;
374
+                $heightR = $preview->height() / $height;
375
+
376
+                if ($widthR > $heightR) {
377
+                    $scaleH = $height;
378
+                    $scaleW = $maxWidth / $heightR;
379
+                } else {
380
+                    $scaleH = $maxHeight / $widthR;
381
+                    $scaleW = $width;
382
+                }
383
+                $preview->preciseResize((int)round($scaleW), (int)round($scaleH));
384
+            }
385
+            $cropX = (int)floor(abs($width - $preview->width()) * 0.5);
386
+            $cropY = (int)floor(abs($height - $preview->height()) * 0.5);
387
+            $preview->crop($cropX, $cropY, $width, $height);
388
+        } else {
389
+            $preview->resize(max($width, $height));
390
+        }
391
+
392
+
393
+        $path = $this->generatePath($width, $height, $crop, $preview->dataMimeType(), $prefix);
394
+        try {
395
+            $file = $previewFolder->newFile($path);
396
+            $file->putContent($preview->data());
397
+        } catch (NotPermittedException $e) {
398
+            throw new NotFoundException();
399
+        }
400
+
401
+        return $file;
402
+    }
403
+
404
+    /**
405
+     * @param ISimpleFolder $previewFolder
406
+     * @param int $width
407
+     * @param int $height
408
+     * @param bool $crop
409
+     * @param string $mimeType
410
+     * @param string $prefix
411
+     * @return ISimpleFile
412
+     *
413
+     * @throws NotFoundException
414
+     */
415
+    private function getCachedPreview(ISimpleFolder $previewFolder, $width, $height, $crop, $mimeType, $prefix) {
416
+        $path = $this->generatePath($width, $height, $crop, $mimeType, $prefix);
417
+
418
+        return $previewFolder->getFile($path);
419
+    }
420
+
421
+    /**
422
+     * Get the specific preview folder for this file
423
+     *
424
+     * @param File $file
425
+     * @return ISimpleFolder
426
+     */
427
+    private function getPreviewFolder(File $file) {
428
+        try {
429
+            $folder = $this->appData->getFolder($file->getId());
430
+        } catch (NotFoundException $e) {
431
+            $folder = $this->appData->newFolder($file->getId());
432
+        }
433
+
434
+        return $folder;
435
+    }
436
+
437
+    /**
438
+     * @param string $mimeType
439
+     * @return null|string
440
+     * @throws \InvalidArgumentException
441
+     */
442
+    private function getExtention($mimeType) {
443
+        switch ($mimeType) {
444
+            case 'image/png':
445
+                return 'png';
446
+            case 'image/jpeg':
447
+                return 'jpg';
448
+            case 'image/gif':
449
+                return 'gif';
450
+            default:
451
+                throw new \InvalidArgumentException('Not a valid mimetype');
452
+        }
453
+    }
454 454
 }
Please login to merge, or discard this patch.