Skip to content

Commit a50c4b3

Browse files
Merge pull request #61302 from nextcloud/backport/61253/stable34
[stable34] fix(theming): preserve uploaded favicon and touch icon
2 parents 452a9c2 + 9f4e0e0 commit a50c4b3

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

apps/theming/lib/Controller/IconController.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ public function getFavicon(string $app = 'core'): Response {
9999
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
100100
} catch (NotFoundException $e) {
101101
}
102-
// retrieve or generate app specific favicon
103-
if (($this->imageManager->canConvert('PNG') || $this->imageManager->canConvert('SVG')) && $this->imageManager->canConvert('ICO')) {
102+
// retrieve or generate app specific favicon, but only if no custom favicon was uploaded
103+
if ($iconFile === null && ($this->imageManager->canConvert('PNG') || $this->imageManager->canConvert('SVG')) && $this->imageManager->canConvert('ICO')) {
104104
$color = $this->themingDefaults->getColorPrimary();
105105
try {
106106
$iconFile = $this->imageManager->getCachedImage('favIcon-' . $app . $color);
@@ -141,14 +141,15 @@ public function getTouchIcon(string $app = 'core'): Response {
141141
}
142142

143143
$response = null;
144+
$iconFile = null;
144145
// retrieve instance favicon
145146
try {
146147
$iconFile = $this->imageManager->getImage('favicon');
147148
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => $iconFile->getMimeType()]);
148149
} catch (NotFoundException $e) {
149150
}
150-
// retrieve or generate app specific touch icon
151-
if ($this->imageManager->canConvert('PNG')) {
151+
// retrieve or generate app specific touch icon, but only if no custom favicon was uploaded
152+
if ($iconFile === null && $this->imageManager->canConvert('PNG')) {
152153
$color = $this->themingDefaults->getColorPrimary();
153154
try {
154155
$iconFile = $this->imageManager->getCachedImage('touchIcon-' . $app . $color);

apps/theming/tests/Controller/IconControllerTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,24 @@ public function testGetFaviconThemed(): void {
124124
$this->assertEquals($expected, $this->iconController->getFavicon());
125125
}
126126

127+
public function testGetFaviconUploaded(): void {
128+
// a custom favicon was uploaded, so it must be served as-is and the
129+
// app-specific generation path must not overwrite it
130+
$file = $this->iconFileMock('favicon.ico', 'filecontent');
131+
$this->imageManager->expects($this->once())
132+
->method('getImage')
133+
->with('favicon', false)
134+
->willReturn($file);
135+
$this->imageManager->expects($this->never())
136+
->method('getCachedImage');
137+
$this->iconBuilder->expects($this->never())
138+
->method('getFavicon');
139+
140+
$expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
141+
$expected->cacheFor(86400);
142+
$this->assertEquals($expected, $this->iconController->getFavicon());
143+
}
144+
127145
public function testGetFaviconDefault(): void {
128146
$this->imageManager->expects($this->once())
129147
->method('getImage')
@@ -179,6 +197,24 @@ public function testGetTouchIconDefault(): void {
179197
$this->assertEquals($expected, $this->iconController->getTouchIcon());
180198
}
181199

200+
public function testGetTouchIconUploaded(): void {
201+
// a custom favicon was uploaded, so it must be served as-is and the
202+
// app-specific generation path must not overwrite it
203+
$file = $this->iconFileMock('favicon.png', 'filecontent');
204+
$this->imageManager->expects($this->once())
205+
->method('getImage')
206+
->with('favicon')
207+
->willReturn($file);
208+
$this->imageManager->expects($this->never())
209+
->method('getCachedImage');
210+
$this->iconBuilder->expects($this->never())
211+
->method('getTouchIcon');
212+
213+
$expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image type']);
214+
$expected->cacheFor(86400);
215+
$this->assertEquals($expected, $this->iconController->getTouchIcon());
216+
}
217+
182218
public function testGetTouchIconFail(): void {
183219
$this->imageManager->expects($this->once())
184220
->method('getImage')

0 commit comments

Comments
 (0)