Skip to content

Commit f6c7b4e

Browse files
authored
Merge pull request #1339 from nextcloud/master-limit-possible-image-mimetypes
Filter more mimetypes
2 parents f5aafdc + 6743995 commit f6c7b4e

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed

apps/dav/lib/CardDAV/ImageExportPlugin.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ function httpGet(RequestInterface $request, ResponseInterface $response) {
8787

8888
if ($result = $this->getPhoto($node)) {
8989
$response->setHeader('Content-Type', $result['Content-Type']);
90+
$response->setHeader('Content-Disposition', 'attachment');
9091
$response->setStatus(200);
9192

9293
$response->setBody($result['body']);
@@ -121,6 +122,17 @@ function getPhoto(Card $node) {
121122
}
122123
$val = file_get_contents($val);
123124
}
125+
126+
$allowedContentTypes = [
127+
'image/png',
128+
'image/jpeg',
129+
'image/gif',
130+
];
131+
132+
if(!in_array($type, $allowedContentTypes, true)) {
133+
$type = 'application/octet-stream';
134+
}
135+
124136
return [
125137
'Content-Type' => $type,
126138
'body' => $val

apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,20 @@ public function testCardWithOrWithoutPhoto($expected, $getPhotoResult) {
107107
$this->plugin->expects($this->once())->method('getPhoto')->willReturn($getPhotoResult);
108108

109109
if (!$expected) {
110-
$this->response->expects($this->once())->method('setHeader');
111-
$this->response->expects($this->once())->method('setStatus');
112-
$this->response->expects($this->once())->method('setBody');
110+
$this->response
111+
->expects($this->at(0))
112+
->method('setHeader')
113+
->with('Content-Type', $getPhotoResult['Content-Type']);
114+
$this->response
115+
->expects($this->at(1))
116+
->method('setHeader')
117+
->with('Content-Disposition', 'attachment');
118+
$this->response
119+
->expects($this->once())
120+
->method('setStatus');
121+
$this->response
122+
->expects($this->once())
123+
->method('setBody');
113124
}
114125

115126
$result = $this->plugin->httpGet($this->request, $this->response);
@@ -142,12 +153,43 @@ public function testGetPhoto($expected, $cardData) {
142153

143154
public function providesPhotoData() {
144155
return [
145-
'empty vcard' => [false, ''],
146-
'vcard without PHOTO' => [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n"],
147-
'vcard 3 with PHOTO' => [['Content-Type' => 'image/jpeg', 'body' => '12345'], "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU=\r\nEND:VCARD\r\n"],
148-
'vcard 3 with PHOTO URL' => [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;TYPE=JPEG;VALUE=URI:http://example.com/photo.jpg\r\nEND:VCARD\r\n"],
149-
'vcard 4 with PHOTO' => [['Content-Type' => 'image/jpeg', 'body' => '12345'], "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO:data:image/jpeg;base64,MTIzNDU=\r\nEND:VCARD\r\n"],
150-
'vcard 4 with PHOTO URL' => [false, "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;MEDIATYPE=image/jpeg:http://example.org/photo.jpg\r\nEND:VCARD\r\n"],
156+
'empty vcard' => [
157+
false,
158+
''
159+
],
160+
'vcard without PHOTO' => [
161+
false,
162+
"BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n"
163+
],
164+
'vcard 3 with PHOTO' => [
165+
[
166+
'Content-Type' => 'image/jpeg',
167+
'body' => '12345'
168+
],
169+
"BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU=\r\nEND:VCARD\r\n"
170+
],
171+
'vcard 3 with PHOTO URL' => [
172+
false,
173+
"BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;TYPE=JPEG;VALUE=URI:http://example.com/photo.jpg\r\nEND:VCARD\r\n"
174+
],
175+
'vcard 4 with PHOTO' => [
176+
[
177+
'Content-Type' => 'image/jpeg',
178+
'body' => '12345'
179+
],
180+
"BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO:data:image/jpeg;base64,MTIzNDU=\r\nEND:VCARD\r\n"
181+
],
182+
'vcard 4 with PHOTO URL' => [
183+
false,
184+
"BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;MEDIATYPE=image/jpeg:http://example.org/photo.jpg\r\nEND:VCARD\r\n"
185+
],
186+
'vcard 4 with PHOTO AND INVALID MIMEtYPE' => [
187+
[
188+
'Content-Type' => 'application/octet-stream',
189+
'body' => '12345'
190+
],
191+
"BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO:data:image/svg;base64,MTIzNDU=\r\nEND:VCARD\r\n"
192+
],
151193
];
152194
}
153195
}

0 commit comments

Comments
 (0)