diff --git a/appinfo/routes.php b/appinfo/routes.php
index 6fcd9c19..5985c429 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -12,17 +12,14 @@
['name' => 'MenuEntry#ExAppIcon', 'url' => '/embedded/{appId}/{name}/icon', 'verb' => 'GET' , 'root' => '/embedded'],
// Proxy
-// ['name' => 'MenuEntry#ExAppProxySubLinksGet',
-// 'url' => '/proxying/{appId}/{other}', 'verb' => 'GET' , 'root' => '/proxying',
-// 'requirements' => array('other' => '.+'), 'defaults' => array('other' => '')],
-// ['name' => 'MenuEntry#ExAppProxySubLinksPost',
-// 'url' => '/proxying/{appId}/{other}', 'verb' => 'POST' , 'root' => '/proxying',
-// 'requirements' => array('other' => '.+'), 'defaults' => array('other' => '')],
-// ['name' => 'MenuEntry#ExAppProxySubLinksPut',
-// 'url' => '/proxying/{appId}/{other}', 'verb' => 'PUT' , 'root' => '/proxying',
-// 'requirements' => array('other' => '.+'), 'defaults' => array('other' => '')],
- ['name' => 'MenuEntry#ExAppProxySubLinksGet',
- 'url' => '/proxy/css/{appId}/{other}', 'verb' => 'GET' , 'root' => '',
+ ['name' => 'MenuEntry#ExAppProxyGet',
+ 'url' => '/proxy/{appId}/{other}', 'verb' => 'GET' , 'root' => '/proxy',
+ 'requirements' => array('other' => '.+'), 'defaults' => array('other' => '')],
+ ['name' => 'MenuEntry#ExAppProxyPost',
+ 'url' => '/proxy/{appId}/{other}', 'verb' => 'POST' , 'root' => '/proxying',
+ 'requirements' => array('other' => '.+'), 'defaults' => array('other' => '')],
+ ['name' => 'MenuEntry#ExAppProxyPut',
+ 'url' => '/proxy/{appId}/{other}', 'verb' => 'PUT' , 'root' => '/proxying',
'requirements' => array('other' => '.+'), 'defaults' => array('other' => '')],
// ExApps actions
diff --git a/lib/Controller/MenuEntryController.php b/lib/Controller/MenuEntryController.php
index 1c47581d..c0cd1519 100644
--- a/lib/Controller/MenuEntryController.php
+++ b/lib/Controller/MenuEntryController.php
@@ -4,15 +4,13 @@
namespace OCA\AppAPI\Controller;
-use DOMDocument;
-use DOMException;
use OC\Security\CSP\ContentSecurityPolicyNonceManager;
use OCA\AppAPI\AppInfo\Application;
use OCA\AppAPI\Attribute\AppAPIAuth;
use OCA\AppAPI\ProxyResponse;
use OCA\AppAPI\Service\AppAPIService;
-use OCA\AppAPI\Service\ExAppMenuEntryService;
use OCA\AppAPI\Service\ExAppInitialStateService;
+use OCA\AppAPI\Service\ExAppMenuEntryService;
use OCA\AppAPI\Service\ExAppScriptsService;
use OCA\AppAPI\Service\ExAppStylesService;
use OCP\AppFramework\Controller;
@@ -31,10 +29,12 @@
use OCP\Http\Client\IResponse;
use OCP\IRequest;
use OCP\IURLGenerator;
-use OCP\Util;
class MenuEntryController extends Controller {
+ public bool $postprocess = false;
+ public array $jsProxyMap = [];
+
public function __construct(
IRequest $request,
private IInitialState $initialState,
@@ -74,64 +74,14 @@ public function viewExAppPage(string $appId, string $name): TemplateResponse {
foreach ($initialStates as $key => $value) {
$this->initialState->provideInitialState($key, $value);
}
- $this->scriptsService->applyExAppScripts($appId, 'top_menu');
+ $this->jsProxyMap = $this->scriptsService->applyExAppScripts($appId, 'top_menu');
$this->stylesService->applyExAppStyles($appId, 'top_menu');
+ $this->postprocess = true;
$response = new TemplateResponse(Application::APP_ID, 'main');
return $response;
}
- /**
- * @NoCSRFRequired
- * @NoAdminRequired
- * @throws DOMException
- */
- #[NoAdminRequired]
- #[NoCSRFRequired]
- public function ExAppIframeProxy(string $appId, string $name): Response {
- $exApp = $this->service->getExApp($appId);
- if ($exApp === null) {
- return new NotFoundResponse();
- }
- if (!$exApp->getEnabled()) {
- return new NotFoundResponse();
- }
- $menuEntry = $this->menuEntryService->getExAppMenuEntry($appId, $name);
- if ($menuEntry === null) {
- return new NotFoundResponse();
- }
- $response = $this->service->aeRequestToExApp(
- $exApp, $menuEntry->getRoute(), $this->userId, 'GET', request: $this->request
- );
- if (is_array($response)) {
- $error_response = new Response();
- return $error_response->setStatus(500);
- }
- $reHeaders = [];
- foreach ($response->getHeaders() as $k => $values) {
- $reHeaders[$k] = count($values) === 1 ? $values[0] : $values;
- }
- $reHeaders['content-security-policy'] = 'frame-ancestors *;';
-
- $dom = new DOMDocument();
- @$dom->loadHTML($response->getBody(), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
- $base = $dom->createElement('base');
- $base->setAttribute(
- 'href',
- $this->url->getAbsoluteURL('index.php/apps/app_api/proxying/'. $exApp->getAppid() . '/')
- );
- $base->setAttribute('target', '_parent');
- $head = $dom->getElementsByTagName('head')->item(0);
- if ($head) {
- if ($head->hasChildNodes()) {
- $head->insertBefore($base, $head->firstChild);
- } else {
- $head->appendChild($base);
- }
- }
- return new DataDisplayResponse($dom->saveHTML(), $response->getStatusCode(), $reHeaders);
- }
-
private function createProxyResponse(string $path, IResponse $response, $cache = true): ProxyResponse {
$content = $response->getBody();
$isHTML = pathinfo($path, PATHINFO_EXTENSION) === 'html';
@@ -181,28 +131,7 @@ private function createProxyResponse(string $path, IResponse $response, $cache =
#[NoAdminRequired]
#[NoCSRFRequired]
- public function ExAppProxyCss(string $appId, string $other): Response {
- $exApp = $this->service->getExApp($appId);
- if ($exApp === null) {
- return new NotFoundResponse();
- }
- if (!$exApp->getEnabled()) {
- return new NotFoundResponse();
- }
-
- $response = $this->service->aeRequestToExApp(
- $exApp, '/' . $other, $this->userId, 'GET', request: $this->request
- );
- if (is_array($response)) {
- $error_response = new Response();
- return $error_response->setStatus(500);
- }
- return $this->createProxyResponse($other, $response);
- }
-
- #[NoAdminRequired]
- #[NoCSRFRequired]
- public function ExAppProxySubLinksGet(string $appId, string $other): Response {
+ public function ExAppProxyGet(string $appId, string $other): Response {
$exApp = $this->service->getExApp($appId);
if ($exApp === null) {
return new NotFoundResponse();
@@ -223,7 +152,7 @@ public function ExAppProxySubLinksGet(string $appId, string $other): Response {
#[NoAdminRequired]
#[NoCSRFRequired]
- public function ExAppIframeProxySubLinksPost(string $appId, string $other): Response {
+ public function ExAppProxyPost(string $appId, string $other): Response {
$exApp = $this->service->getExApp($appId);
if ($exApp === null) {
return new NotFoundResponse();
@@ -246,7 +175,7 @@ public function ExAppIframeProxySubLinksPost(string $appId, string $other): Resp
#[NoAdminRequired]
#[NoCSRFRequired]
- public function ExAppIframeProxySubLinksPut(string $appId, string $other): Response {
+ public function ExAppProxyPut(string $appId, string $other): Response {
$exApp = $this->service->getExApp($appId);
if ($exApp === null) {
return new NotFoundResponse();
diff --git a/lib/Db/UI/InitialStateMapper.php b/lib/Db/UI/InitialStateMapper.php
index 9a90dcad..bf02d10f 100644
--- a/lib/Db/UI/InitialStateMapper.php
+++ b/lib/Db/UI/InitialStateMapper.php
@@ -31,7 +31,8 @@ public function findByAppIdType(string $appId, string $type): array {
->where(
$qb->expr()->eq('appid', $qb->createNamedParameter($appId, IQueryBuilder::PARAM_STR)),
$qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_STR))
- )->executeQuery();;
+ )->executeQuery();
+ ;
return $result->fetchAll();
}
}
diff --git a/lib/Db/UI/ScriptMapper.php b/lib/Db/UI/ScriptMapper.php
index aceb4270..7516a1f2 100644
--- a/lib/Db/UI/ScriptMapper.php
+++ b/lib/Db/UI/ScriptMapper.php
@@ -31,7 +31,8 @@ public function findByAppIdType(string $appId, string $type): array {
->where(
$qb->expr()->eq('appid', $qb->createNamedParameter($appId, IQueryBuilder::PARAM_STR)),
$qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_STR))
- )->executeQuery();;
+ )->executeQuery();
+ ;
return $result->fetchAll();
}
}
diff --git a/lib/Db/UI/StyleMapper.php b/lib/Db/UI/StyleMapper.php
index b8b0b0c8..dd296cd4 100644
--- a/lib/Db/UI/StyleMapper.php
+++ b/lib/Db/UI/StyleMapper.php
@@ -31,7 +31,8 @@ public function findByAppIdType(string $appId, string $type): array {
->where(
$qb->expr()->eq('appid', $qb->createNamedParameter($appId, IQueryBuilder::PARAM_STR)),
$qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_STR))
- )->executeQuery();;
+ )->executeQuery();
+ ;
return $result->fetchAll();
}
}
diff --git a/lib/Middleware/ExAppUiMiddleware.php b/lib/Middleware/ExAppUiMiddleware.php
index c323340b..3fbcd9fc 100644
--- a/lib/Middleware/ExAppUiMiddleware.php
+++ b/lib/Middleware/ExAppUiMiddleware.php
@@ -4,21 +4,14 @@
namespace OCA\AppAPI\Middleware;
-use Exception;
-use OCA\AppAPI\Attribute\AppAPIAuth;
use OCA\AppAPI\Controller\MenuEntryController;
-use OCA\AppAPI\Exceptions\AppAPIAuthNotValidException;
use OCA\AppAPI\Service\AppAPIService;
use OCP\AppFramework\Controller;
-use OCP\AppFramework\Http;
-use OCP\AppFramework\Http\JSONResponse;
-use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\IL10N;
use OCP\IRequest;
use Psr\Log\LoggerInterface;
-use ReflectionMethod;
class ExAppUiMiddleware extends Middleware {
@@ -31,12 +24,19 @@ public function __construct(
}
public function beforeOutput(Controller $controller, string $methodName, string $output) {
- if ($controller instanceof MenuEntryController) {
- $adjustedCss = preg_replace(
- '/(href=")(\/.*?)(\/app_api\/css\/)(proxy\/css\/.*css")/',
+ if (($controller instanceof MenuEntryController) && ($controller->postprocess)) {
+ $correctedOutput = preg_replace(
+ '/(href=")(\/.*?)(\/app_api\/css\/)(proxy\/.*css")/',
'$1/index.php/apps/app_api/$4',
$output);
- return $adjustedCss;
+ foreach ($controller->jsProxyMap as $key => $value) {
+ $correctedOutput = preg_replace(
+ '/(src=")(\/.*?)(\/app_api\/js\/)(proxy_js\/' . $key . '.js")/',
+ '$1/index.php/apps/app_api/proxy/' . $value . '.js"',
+ $correctedOutput,
+ limit: 1);
+ }
+ return $correctedOutput;
}
return $output;
}
diff --git a/lib/ProxyResponse.php b/lib/ProxyResponse.php
index da2fa958..41b6453c 100644
--- a/lib/ProxyResponse.php
+++ b/lib/ProxyResponse.php
@@ -14,8 +14,8 @@ class ProxyResponse extends Response implements ICallbackResponse {
private mixed $data;
public function __construct(int $status = HttpAlias::STATUS_OK,
- array $headers = [], mixed $data = null, int $length = 0,
- string $mimeType = '', int $lastModified = 0) {
+ array $headers = [], mixed $data = null, int $length = 0,
+ string $mimeType = '', int $lastModified = 0) {
parent::__construct();
$this->data = $data;
$this->setStatus($status);
diff --git a/lib/Service/ExAppScriptsService.php b/lib/Service/ExAppScriptsService.php
index fd56844a..b12b78bb 100644
--- a/lib/Service/ExAppScriptsService.php
+++ b/lib/Service/ExAppScriptsService.php
@@ -4,6 +4,7 @@
namespace OCA\AppAPI\Service;
+use LengthException;
use OCA\AppAPI\AppInfo\Application;
use OCA\AppAPI\Db\UI\ScriptMapper;
use OCP\DB\Exception;
@@ -12,6 +13,8 @@
class ExAppScriptsService {
+ public const MAX_JS_FILES = 20 + 1; //should be equal to number of files in "proxy_js" folder.
+
public function __construct(
private ScriptMapper $mapper,
private LoggerInterface $logger,
@@ -29,16 +32,29 @@ public function clearExAppScripts(string $appId, string $type) {
/**
* @throws Exception
*/
- public function applyExAppScripts(string $appId, string $type): void {
+ public function applyExAppScripts(string $appId, string $type): array {
// TODO: Add caching
+ $mapResult = [];
$scripts = $this->mapper->findByAppIdType($appId, $type);
+ if (count($scripts) > self::MAX_JS_FILES) {
+ throw new LengthException('More than' . self::MAX_JS_FILES . 'JS files on one page are not supported.');
+ }
+
+ $i = 0;
foreach ($scripts as $value) {
+ $fakeJsPath = 'proxy_js/' . $i;
if (is_null($value['after_app_id'])) {
- Util::addScript(Application::APP_ID, $value['path']);
+ Util::addScript(Application::APP_ID, $fakeJsPath);
+ } else {
+ Util::addScript(Application::APP_ID, $fakeJsPath, $value['after_app_id']);
}
- else {
- Util::addScript(Application::APP_ID, $value['path'], $value['after_app_id']);
+ if (str_starts_with($value['path'], '/')) {
+ $mapResult[$i] = $appId . $value['path'];
+ } else {
+ $mapResult[$i] = $appId . '/' . $value['path'];
}
+ $i++;
}
+ return $mapResult;
}
}
diff --git a/lib/Service/ExAppStylesService.php b/lib/Service/ExAppStylesService.php
index bac56dc2..519d988c 100644
--- a/lib/Service/ExAppStylesService.php
+++ b/lib/Service/ExAppStylesService.php
@@ -37,10 +37,9 @@ public function applyExAppStyles(string $appId, string $type): void {
foreach ($styles as $value) {
if (str_starts_with($value['path'], '/')) {
// in the future we should allow offload of styles to the NC instance if they start with '/'
- $path = 'proxy/css/'. $appId . $value['path'];
- }
- else {
- $path = 'proxy/css/'. $appId . '/' . $value['path'];
+ $path = 'proxy/'. $appId . $value['path'];
+ } else {
+ $path = 'proxy/'. $appId . '/' . $value['path'];
}
Util::addStyle(Application::APP_ID, $path);
}
diff --git a/psalm.xml b/psalm.xml
index 9ea6e4d5..b014fdd1 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -34,6 +34,7 @@
+