This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * @copyright Copyright (c) 2016 Lukas Reschke <[email protected]> |
||
4 | * |
||
5 | * @author Lukas Reschke <[email protected]> |
||
6 | * @author Roeland Jago Douma <[email protected]> |
||
7 | * |
||
8 | * @license GNU AGPL version 3 or any later version |
||
9 | * |
||
10 | * This program is free software: you can redistribute it and/or modify |
||
11 | * it under the terms of the GNU Affero General Public License as |
||
12 | * published by the Free Software Foundation, either version 3 of the |
||
13 | * License, or (at your option) any later version. |
||
14 | * |
||
15 | * This program is distributed in the hope that it will be useful, |
||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 | * GNU Affero General Public License for more details. |
||
19 | * |
||
20 | * You should have received a copy of the GNU Affero General Public License |
||
21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
22 | * |
||
23 | */ |
||
24 | |||
25 | namespace OCA\Richdocuments\AppInfo; |
||
26 | |||
27 | use OC\EventDispatcher\SymfonyAdapter; |
||
28 | use OC\Files\Type\Detection; |
||
29 | use OC\Security\CSP\ContentSecurityPolicy; |
||
30 | use OCA\Federation\TrustedServers; |
||
31 | use OCA\Richdocuments\AppConfig; |
||
32 | use OCA\Richdocuments\Capabilities; |
||
33 | use OCA\Richdocuments\PermissionManager; |
||
34 | use OCA\Richdocuments\Preview\MSExcel; |
||
35 | use OCA\Richdocuments\Preview\MSWord; |
||
36 | use OCA\Richdocuments\Preview\OOXML; |
||
37 | use OCA\Richdocuments\Preview\OpenDocument; |
||
38 | use OCA\Richdocuments\Preview\Pdf; |
||
39 | use OCA\Richdocuments\Service\CapabilitiesService; |
||
40 | use OCA\Richdocuments\Service\FederationService; |
||
41 | use OCA\Richdocuments\Template\CollaboraTemplateProvider; |
||
42 | use OCA\Richdocuments\WOPI\DiscoveryManager; |
||
43 | use OCA\Viewer\Event\LoadViewer; |
||
44 | use OCP\AppFramework\App; |
||
45 | use OCP\AppFramework\Bootstrap\IBootContext; |
||
46 | use OCP\AppFramework\Bootstrap\IBootstrap; |
||
47 | use OCP\AppFramework\Bootstrap\IRegistrationContext; |
||
48 | use OCP\EventDispatcher\IEventDispatcher; |
||
49 | use OCP\Files\Template\ITemplateManager; |
||
50 | use OCP\Files\Template\TemplateFileCreator; |
||
51 | use OCP\GlobalScale\IConfig; |
||
52 | use OCP\IPreview; |
||
53 | |||
54 | class Application extends App implements IBootstrap { |
||
55 | |||
56 | public const APPNAME = 'richdocuments'; |
||
57 | |||
58 | public function __construct(array $urlParams = array()) { |
||
59 | parent::__construct(self::APPNAME, $urlParams); |
||
60 | $this->getContainer()->registerCapability(Capabilities::class); |
||
61 | } |
||
62 | |||
63 | |||
64 | public function register(IRegistrationContext $context): void { |
||
65 | $context->registerTemplateProvider(CollaboraTemplateProvider::class); |
||
66 | $context->registerCapability(Capabilities::class); |
||
67 | } |
||
68 | |||
69 | public function boot(IBootContext $context): void { |
||
70 | $currentUser = \OC::$server->getUserSession()->getUser(); |
||
71 | if($currentUser !== null) { |
||
72 | /** @var PermissionManager $permissionManager */ |
||
73 | $permissionManager = \OC::$server->query(PermissionManager::class); |
||
74 | if(!$permissionManager->isEnabledForUser($currentUser)) { |
||
75 | return; |
||
76 | } |
||
77 | } |
||
78 | |||
79 | /** @var IEventDispatcher $eventDispatcher */ |
||
80 | $eventDispatcher = $this->getContainer()->getServer()->query(IEventDispatcher::class); |
||
81 | $eventDispatcher->addListener(LoadViewer::class, function () { |
||
82 | \OCP\Util::addScript('richdocuments', 'viewer'); |
||
83 | }); |
||
84 | |||
85 | $context->injectFn(function(ITemplateManager $templateManager) { |
||
86 | $templateManager->registerTemplateFileCreator(function () { |
||
87 | $odtType = new TemplateFileCreator('richdocuments', 'New document', '.odt'); |
||
88 | $odtType->addMimetype('application/vnd.oasis.opendocument.text'); |
||
89 | $odtType->addMimetype('application/vnd.oasis.opendocument.text-template'); |
||
90 | $odtType->setIconClass('icon-filetype-document'); |
||
91 | $odtType->setRatio(21/29.7); |
||
92 | return $odtType; |
||
93 | }); |
||
94 | $templateManager->registerTemplateFileCreator(function () { |
||
95 | $odsType = new TemplateFileCreator('richdocuments', 'New spreadsheet', '.ods'); |
||
96 | $odsType->addMimetype('application/vnd.oasis.opendocument.spreadsheet'); |
||
97 | $odsType->addMimetype('application/vnd.oasis.opendocument.spreadsheet-template'); |
||
98 | $odsType->setIconClass('icon-filetype-spreadsheet'); |
||
99 | $odsType->setRatio(16/9); |
||
100 | return $odsType; |
||
101 | }); |
||
102 | $templateManager->registerTemplateFileCreator(function () { |
||
103 | $odpType = new TemplateFileCreator('richdocuments', 'New presentation', '.odp'); |
||
104 | $odpType->addMimetype('application/vnd.oasis.opendocument.presentation'); |
||
105 | $odpType->addMimetype('application/vnd.oasis.opendocument.presentation-template'); |
||
106 | $odpType->setIconClass('icon-filetype-presentation'); |
||
107 | $odpType->setRatio(16/9); |
||
108 | return $odpType; |
||
109 | }); |
||
110 | }); |
||
111 | |||
112 | $context->injectFn(function (SymfonyAdapter $eventDispatcher) { |
||
113 | $eventDispatcher->addListener('OCA\Files::loadAdditionalScripts', |
||
114 | function() { |
||
115 | \OCP\Util::addScript('richdocuments', 'files'); |
||
116 | } |
||
117 | ); |
||
118 | $eventDispatcher->addListener('OCA\Files_Sharing::loadAdditionalScripts', |
||
119 | function() { |
||
120 | \OCP\Util::addScript('richdocuments', 'files'); |
||
121 | } |
||
122 | ); |
||
123 | |||
124 | if (class_exists('\OC\Files\Type\TemplateManager')) { |
||
125 | $manager = \OC_Helper::getFileTemplateManager(); |
||
126 | |||
127 | $manager->registerTemplate('application/vnd.openxmlformats-officedocument.wordprocessingml.document', dirname(__DIR__) . '/assets/docxtemplate.docx'); |
||
128 | $manager->registerTemplate('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', dirname(__DIR__) . '/assets/xlsxtemplate.xlsx'); |
||
129 | $manager->registerTemplate('application/vnd.openxmlformats-officedocument.presentationml.presentation', dirname(__DIR__) . '/assets/pptxtemplate.pptx'); |
||
130 | $manager->registerTemplate('application/vnd.oasis.opendocument.presentation', dirname(__DIR__) . '/assets/template.odp'); |
||
131 | $manager->registerTemplate('application/vnd.oasis.opendocument.text', dirname(__DIR__) . '/assets/template.odt'); |
||
132 | $manager->registerTemplate('application/vnd.oasis.opendocument.spreadsheet', dirname(__DIR__) . '/assets/template.ods'); |
||
133 | } |
||
134 | |||
135 | $this->registerProvider(); |
||
136 | $this->updateCSP(); |
||
137 | $this->checkAndEnableCODEServer(); |
||
138 | }); |
||
139 | } |
||
140 | |||
141 | public function registerProvider() { |
||
142 | $container = $this->getContainer(); |
||
143 | |||
144 | // Register mimetypes |
||
145 | /** @var Detection $detector */ |
||
146 | $detector = $container->query(\OCP\Files\IMimeTypeDetector::class); |
||
147 | $detector->getAllMappings(); |
||
148 | $detector->registerType('ott','application/vnd.oasis.opendocument.text-template'); |
||
149 | $detector->registerType('ots', 'application/vnd.oasis.opendocument.spreadsheet-template'); |
||
150 | $detector->registerType('otp', 'application/vnd.oasis.opendocument.presentation-template'); |
||
151 | |||
152 | /** @var IPreview $previewManager */ |
||
153 | $previewManager = $container->query(IPreview::class); |
||
154 | |||
155 | $previewManager->registerProvider('/application\/vnd.ms-excel/', function() use ($container) { |
||
156 | return $container->query(MSExcel::class); |
||
157 | }); |
||
158 | |||
159 | $previewManager->registerProvider('/application\/msword/', function() use ($container) { |
||
160 | return $container->query(MSWord::class); |
||
161 | }); |
||
162 | |||
163 | $previewManager->registerProvider('/application\/vnd.openxmlformats-officedocument.*/', function() use ($container) { |
||
164 | return $container->query(OOXML::class); |
||
165 | }); |
||
166 | |||
167 | // \OC::$server->getLogger()->debug('==== Richdocuments Application registerProvider: calling manager registerProvider:'); |
||
168 | $previewManager->registerProvider('/application\/vnd.oasis.opendocument.*/', function() use ($container) { |
||
169 | // \OC::$server->getLogger()->debug('==== Richdocuments Application registerProvider lambda. OpenDocument::class=' . OpenDocument::class); |
||
170 | return $container->query(OpenDocument::class); |
||
171 | }); |
||
172 | |||
173 | $previewManager->registerProvider('/application\/pdf/', function() use ($container) { |
||
174 | return $container->query(Pdf::class); |
||
175 | }); |
||
176 | } |
||
177 | |||
178 | public function updateCSP() { |
||
179 | $container = $this->getContainer(); |
||
180 | |||
181 | $publicWopiUrl = $container->getServer()->getConfig()->getAppValue('richdocuments', 'public_wopi_url', ''); |
||
182 | $publicWopiUrl = $publicWopiUrl === '' ? \OC::$server->getConfig()->getAppValue('richdocuments', 'wopi_url') : $publicWopiUrl; |
||
183 | $cspManager = $container->getServer()->getContentSecurityPolicyManager(); |
||
184 | $policy = new ContentSecurityPolicy(); |
||
185 | if ($publicWopiUrl !== '') { |
||
186 | $policy->addAllowedFrameDomain('\'self\''); |
||
187 | $policy->addAllowedFrameDomain($this->domainOnly($publicWopiUrl)); |
||
188 | if (method_exists($policy, 'addAllowedFormActionDomain')) { |
||
189 | $policy->addAllowedFormActionDomain($this->domainOnly($publicWopiUrl)); |
||
190 | } |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Dynamically add CSP for federated editing |
||
195 | */ |
||
196 | $path = ''; |
||
197 | try { |
||
198 | $path = $container->getServer()->getRequest()->getPathInfo(); |
||
199 | } catch (\Exception $e) {} |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
Loading history...
|
|||
200 | if (strpos($path, '/apps/files/') === 0 && $container->getServer()->getAppManager()->isEnabledForUser('federation')) { |
||
201 | /** @var FederationService $federationService */ |
||
202 | $federationService = \OC::$server->query(FederationService::class); |
||
203 | |||
204 | // Always add trusted servers on global scale |
||
205 | /** @var IConfig $globalScale */ |
||
206 | $globalScale = $container->query(IConfig::class); |
||
207 | if ($globalScale->isGlobalScaleEnabled()) { |
||
208 | $trustedList = \OC::$server->getConfig()->getSystemValue('gs.trustedHosts', []); |
||
209 | foreach ($trustedList as $server) { |
||
210 | $this->addTrustedRemote($policy, $server); |
||
211 | } |
||
212 | } |
||
213 | $remoteAccess = $container->getServer()->getRequest()->getParam('richdocuments_remote_access'); |
||
214 | |||
215 | if ($remoteAccess && $federationService->isTrustedRemote($remoteAccess)) { |
||
216 | $this->addTrustedRemote($policy, $remoteAccess); |
||
217 | } |
||
218 | } |
||
219 | |||
220 | $cspManager->addDefaultPolicy($policy); |
||
221 | } |
||
222 | |||
223 | private function addTrustedRemote($policy, $url) { |
||
224 | /** @var FederationService $federationService */ |
||
225 | $federationService = \OC::$server->query(FederationService::class); |
||
226 | try { |
||
227 | $remoteCollabora = $federationService->getRemoteCollaboraURL($url); |
||
228 | $policy->addAllowedFrameDomain($url); |
||
229 | $policy->addAllowedFrameDomain($remoteCollabora); |
||
230 | } catch (\Exception $e) { |
||
231 | // We can ignore this exception for adding predefined domains to the CSP as it it would then just |
||
232 | // reload the page to set a proper allowed frame domain if we don't have a fixed list of trusted |
||
233 | // remotes in a global scale scenario |
||
234 | } |
||
235 | } |
||
236 | |||
237 | public function checkAndEnableCODEServer() { |
||
238 | // Supported only on Linux OS, and x86_64 & ARM64 platforms |
||
239 | $supportedArchs = array('x86_64', 'aarch64'); |
||
240 | $osFamily = PHP_VERSION_ID >= 70200 ? PHP_OS_FAMILY : PHP_OS; |
||
241 | if ($osFamily !== 'Linux' || !in_array(php_uname('m'), $supportedArchs)) |
||
242 | return; |
||
243 | |||
244 | $CODEAppID = (php_uname('m') === 'x86_64') ? 'richdocumentscode' : 'richdocumentscode_arm64'; |
||
245 | |||
246 | if ($this->getContainer()->getServer()->getAppManager()->isEnabledForUser($CODEAppID)) { |
||
247 | $appConfig = $this->getContainer()->query(AppConfig::class); |
||
248 | $wopi_url = $appConfig->getAppValue('wopi_url'); |
||
249 | $isCODEEnabled = strpos($wopi_url, 'proxy.php?req=') !== false; |
||
250 | |||
251 | // Check if we have the wopi_url set to custom currently |
||
252 | if ($wopi_url !== null && $wopi_url !== '' && $isCODEEnabled === false) { |
||
253 | return; |
||
254 | } |
||
255 | |||
256 | $urlGenerator = \OC::$server->getURLGenerator(); |
||
257 | $relativeUrl = $urlGenerator->linkTo($CODEAppID, '') . 'proxy.php'; |
||
258 | $absoluteUrl = $urlGenerator->getAbsoluteURL($relativeUrl); |
||
259 | $new_wopi_url = $absoluteUrl . '?req='; |
||
260 | |||
261 | // Check if the wopi url needs to be updated |
||
262 | if ($isCODEEnabled && $wopi_url === $new_wopi_url) { |
||
263 | return; |
||
264 | } |
||
265 | |||
266 | $appConfig->setAppValue('wopi_url', $new_wopi_url); |
||
267 | $appConfig->setAppValue('disable_certificate_verification', 'yes'); |
||
268 | |||
269 | $discoveryManager = $this->getContainer()->query(DiscoveryManager::class); |
||
270 | $capabilitiesService = $this->getContainer()->query(CapabilitiesService::class); |
||
271 | |||
272 | $discoveryManager->refetch(); |
||
273 | $capabilitiesService->clear(); |
||
274 | $capabilitiesService->refetch(); |
||
275 | } |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Strips the path and query parameters from the URL. |
||
280 | * |
||
281 | * @param string $url |
||
282 | * @return string |
||
283 | */ |
||
284 | private function domainOnly($url) { |
||
285 | $parsed_url = parse_url($url); |
||
286 | $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; |
||
287 | $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; |
||
288 | $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; |
||
289 | return "$scheme$host$port"; |
||
290 | } |
||
291 | } |
||
292 |