mirror of
https://github.com/appwrite/appwrite
synced 2026-05-06 06:48:22 +00:00
Merge pull request #10255 from appwrite/chore-support-svg-favicon
chore: add support for svg favicons
This commit is contained in:
commit
d28e0152fd
4 changed files with 91 additions and 7 deletions
|
|
@ -10,6 +10,7 @@ use Appwrite\URL\URL as URLParse;
|
|||
use Appwrite\Utopia\Response;
|
||||
use chillerlan\QRCode\QRCode;
|
||||
use chillerlan\QRCode\QROptions;
|
||||
use enshrined\svgSanitize\Sanitizer as SvgSanitizer;
|
||||
use Utopia\App;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
|
|
@ -362,7 +363,8 @@ App::get('/v1/avatars/favicon')
|
|||
$client = new Client();
|
||||
try {
|
||||
$res = $client
|
||||
->setAllowRedirects(false)
|
||||
->setAllowRedirects(true)
|
||||
->setMaxRedirects(5)
|
||||
->setUserAgent(\sprintf(
|
||||
APP_USERAGENT,
|
||||
System::getEnv('_APP_VERSION', 'UNKNOWN'),
|
||||
|
|
@ -399,6 +401,12 @@ App::get('/v1/avatars/favicon')
|
|||
$ext = \pathinfo(\parse_url($absolute, PHP_URL_PATH), PATHINFO_EXTENSION);
|
||||
|
||||
switch ($ext) {
|
||||
case 'svg':
|
||||
// SVG icons are prioritized by assigning the maximum possible value.
|
||||
$space = PHP_INT_MAX;
|
||||
$outputHref = $absolute;
|
||||
$outputExt = $ext;
|
||||
break;
|
||||
case 'ico':
|
||||
case 'png':
|
||||
case 'jpg':
|
||||
|
|
@ -437,7 +445,8 @@ App::get('/v1/avatars/favicon')
|
|||
$client = new Client();
|
||||
try {
|
||||
$res = $client
|
||||
->setAllowRedirects(false)
|
||||
->setAllowRedirects(true)
|
||||
->setMaxRedirects(5)
|
||||
->fetch($outputHref);
|
||||
} catch (\Throwable) {
|
||||
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
|
||||
|
|
@ -449,14 +458,33 @@ App::get('/v1/avatars/favicon')
|
|||
|
||||
$data = $res->getBody();
|
||||
|
||||
if ('ico' == $outputExt) { // Skip crop, Imagick isn\'t supporting icon files
|
||||
if (empty($data) || (\mb_substr($data, 0, 5) === '<html') || \mb_substr($data, 0, 5) === '<!doc') {
|
||||
if ('ico' === $outputExt) { // Skip crop, Imagick isn\'t supporting icon files
|
||||
if (
|
||||
empty($data) ||
|
||||
stripos($data, '<html') === 0 ||
|
||||
stripos($data, '<!doc') === 0
|
||||
) {
|
||||
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found');
|
||||
}
|
||||
$response
|
||||
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
|
||||
->setContentType('image/x-icon')
|
||||
->file($data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('svg' === $outputExt) { // Skip crop, Imagick isn\'t supporting svg files
|
||||
$sanitizer = new SvgSanitizer();
|
||||
$sanitizer->minify(true);
|
||||
$cleanSvg = $sanitizer->sanitize($data);
|
||||
if ($cleanSvg === false) {
|
||||
throw new \Exception('SVG sanitization failed');
|
||||
}
|
||||
$response
|
||||
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
|
||||
->setContentType('image/svg+xml')
|
||||
->file($cleanSvg);
|
||||
return;
|
||||
}
|
||||
|
||||
$image = new Image($data);
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@
|
|||
"adhocore/jwt": "1.1.*",
|
||||
"spomky-labs/otphp": "^10.0",
|
||||
"webonyx/graphql-php": "14.11.*",
|
||||
"league/csv": "9.14.*"
|
||||
"league/csv": "9.14.*",
|
||||
"enshrined/svg-sanitize": "0.21.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-fileinfo": "*",
|
||||
|
|
|
|||
47
composer.lock
generated
47
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "edbe5912c45e1f467f398541a75a77de",
|
||||
"content-hash": "7b2ef6192403daf5c492219822ce0aa1",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -628,6 +628,51 @@
|
|||
],
|
||||
"time": "2023-08-10T19:36:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "enshrined/svg-sanitize",
|
||||
"version": "0.21.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/darylldoyle/svg-sanitizer.git",
|
||||
"reference": "5e477468fac5c5ce933dce53af3e8e4e58dcccc9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/5e477468fac5c5ce933dce53af3e8e4e58dcccc9",
|
||||
"reference": "5e477468fac5c5ce933dce53af3e8e4e58dcccc9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.5 || ^8.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"enshrined\\svgSanitize\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daryll Doyle",
|
||||
"email": "daryll@enshrined.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "An SVG sanitizer for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/darylldoyle/svg-sanitizer/issues",
|
||||
"source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.21.0"
|
||||
},
|
||||
"time": "2025-01-13T09:32:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "giggsey/libphonenumber-for-php-lite",
|
||||
"version": "8.13.36",
|
||||
|
|
|
|||
|
|
@ -284,7 +284,17 @@ trait AvatarsBase
|
|||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('image/x-icon', $response['headers']['content-type']);
|
||||
$this->assertEquals('image/svg+xml', $response['headers']['content-type']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/favicon', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'url' => 'https://appwrite.io/',
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('image/svg+xml', $response['headers']['content-type']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue