Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions apps/appstore/lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class ApiController extends OCSController {

private const int OFFICIAL_APP_LEVEL = 200;

private const string USERCONTENT_PROXY_URL = 'https://usercontent.apps.nextcloud.com/';

/** @var array */
private $allApps = [];

Expand Down Expand Up @@ -305,13 +307,17 @@ public function enableBundle(string $bundleId): DataResponse {

/**
* Convert URL to proxied URL so CSP is no problem
*
* The app store already serves its screenshot URLs in this form; only an
* app's own info.xml still names the source.
*/
private function createProxyPreviewUrl(string $url): string {
if ($url === '') {
return '';
if ($url === '' || str_starts_with($url, self::USERCONTENT_PROXY_URL)) {
return $url;
}

return 'https://usercontent.apps.nextcloud.com/' . base64_encode($url);
// The proxy stores its files under the URL-safe alphabet
return self::USERCONTENT_PROXY_URL . strtr(base64_encode($url), '+/', '-_');
}

private function fetchApps(): void {
Expand Down Expand Up @@ -544,7 +550,7 @@ private function getAppsForCategory(string $requestedCategory = ''): array {
$phpDependencies
),
'level' => ($app['isFeatured'] === true) ? 200 : 100,
'screenshot' => isset($app['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/' . base64_encode($app['screenshots'][0]['url']) : '',
'screenshot' => $this->createProxyPreviewUrl($app['screenshots'][0]['url'] ?? ''),
'ratingOverall' => $app['ratingOverall'],
'ratingNumOverall' => $app['ratingNumOverall'],
'removable' => $existsLocally,
Expand Down
23 changes: 23 additions & 0 deletions apps/appstore/tests/Controller/ApiControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,27 @@ public function testListCategories(): void {
$jsonResponse = json_encode($response->getData());
$this->assertJsonStringEqualsJsonFile(__DIR__ . '/../fixtures/categories-api-response.json', $jsonResponse);
}

public static function dataCreateProxyPreviewUrl(): array {
return [
'empty' => ['', ''],
'already proxied by the app store' => [
'https://usercontent.apps.nextcloud.com/aHR0cHM6Ly9leGFtcGxlLm9yZy9hLnBuZw==',
'https://usercontent.apps.nextcloud.com/aHR0cHM6Ly9leGFtcGxlLm9yZy9hLnBuZw==',
],
'source URL' => [
'https://example.org/a.png',
'https://usercontent.apps.nextcloud.com/aHR0cHM6Ly9leGFtcGxlLm9yZy9hLnBuZw==',
],
'source URL encoding to + and /' => [
'https://example.org/?a=>>>',
'https://usercontent.apps.nextcloud.com/aHR0cHM6Ly9leGFtcGxlLm9yZy8_YT0-Pj4=',
],
];
}

#[\PHPUnit\Framework\Attributes\DataProvider('dataCreateProxyPreviewUrl')]
public function testCreateProxyPreviewUrl(string $url, string $expected): void {
$this->assertSame($expected, self::invokePrivate($this->apiController, 'createProxyPreviewUrl', [$url]));
}
}