Passed
Push — master ( c613c8...97e427 )
by John
37:17 queued 19:48
created
apps/dav/lib/CardDAV/PhotoCache.php 1 patch
Indentation   +267 added lines, -267 removed lines patch added patch discarded remove patch
@@ -43,271 +43,271 @@
 block discarded – undo
43 43
 
44 44
 class PhotoCache {
45 45
 
46
-	/** @var array  */
47
-	public const ALLOWED_CONTENT_TYPES = [
48
-		'image/png' => 'png',
49
-		'image/jpeg' => 'jpg',
50
-		'image/gif' => 'gif',
51
-		'image/vnd.microsoft.icon' => 'ico',
52
-	];
53
-
54
-	/** @var IAppData */
55
-	protected $appData;
56
-
57
-	/** @var ILogger */
58
-	protected $logger;
59
-
60
-	/**
61
-	 * PhotoCache constructor.
62
-	 *
63
-	 * @param IAppData $appData
64
-	 * @param ILogger $logger
65
-	 */
66
-	public function __construct(IAppData $appData, ILogger $logger) {
67
-		$this->appData = $appData;
68
-		$this->logger = $logger;
69
-	}
70
-
71
-	/**
72
-	 * @param int $addressBookId
73
-	 * @param string $cardUri
74
-	 * @param int $size
75
-	 * @param Card $card
76
-	 *
77
-	 * @return ISimpleFile
78
-	 * @throws NotFoundException
79
-	 */
80
-	public function get($addressBookId, $cardUri, $size, Card $card) {
81
-		$folder = $this->getFolder($addressBookId, $cardUri);
82
-
83
-		if ($this->isEmpty($folder)) {
84
-			$this->init($folder, $card);
85
-		}
86
-
87
-		if (!$this->hasPhoto($folder)) {
88
-			throw new NotFoundException();
89
-		}
90
-
91
-		if ($size !== -1) {
92
-			$size = 2 ** ceil(log($size) / log(2));
93
-		}
94
-
95
-		return $this->getFile($folder, $size);
96
-	}
97
-
98
-	/**
99
-	 * @param ISimpleFolder $folder
100
-	 * @return bool
101
-	 */
102
-	private function isEmpty(ISimpleFolder $folder) {
103
-		return $folder->getDirectoryListing() === [];
104
-	}
105
-
106
-	/**
107
-	 * @param ISimpleFolder $folder
108
-	 * @param Card $card
109
-	 * @throws NotPermittedException
110
-	 */
111
-	private function init(ISimpleFolder $folder, Card $card): void {
112
-		$data = $this->getPhoto($card);
113
-
114
-		if ($data === false || !isset($data['Content-Type'])) {
115
-			$folder->newFile('nophoto', '');
116
-			return;
117
-		}
118
-
119
-		$contentType = $data['Content-Type'];
120
-		$extension = self::ALLOWED_CONTENT_TYPES[$contentType] ?? null;
121
-
122
-		if ($extension === null) {
123
-			$folder->newFile('nophoto', '');
124
-			return;
125
-		}
126
-
127
-		$file = $folder->newFile('photo.' . $extension);
128
-		$file->putContent($data['body']);
129
-	}
130
-
131
-	private function hasPhoto(ISimpleFolder $folder) {
132
-		return !$folder->fileExists('nophoto');
133
-	}
134
-
135
-	private function getFile(ISimpleFolder $folder, $size) {
136
-		$ext = $this->getExtension($folder);
137
-
138
-		if ($size === -1) {
139
-			$path = 'photo.' . $ext;
140
-		} else {
141
-			$path = 'photo.' . $size . '.' . $ext;
142
-		}
143
-
144
-		try {
145
-			$file = $folder->getFile($path);
146
-		} catch (NotFoundException $e) {
147
-			if ($size <= 0) {
148
-				throw new NotFoundException;
149
-			}
150
-
151
-			$photo = new \OC_Image();
152
-			/** @var ISimpleFile $file */
153
-			$file = $folder->getFile('photo.' . $ext);
154
-			$photo->loadFromData($file->getContent());
155
-
156
-			$ratio = $photo->width() / $photo->height();
157
-			if ($ratio < 1) {
158
-				$ratio = 1 / $ratio;
159
-			}
160
-
161
-			$size = (int) ($size * $ratio);
162
-			if ($size !== -1) {
163
-				$photo->resize($size);
164
-			}
165
-
166
-			try {
167
-				$file = $folder->newFile($path);
168
-				$file->putContent($photo->data());
169
-			} catch (NotPermittedException $e) {
170
-			}
171
-		}
172
-
173
-		return $file;
174
-	}
175
-
176
-	/**
177
-	 * @throws NotFoundException
178
-	 * @throws NotPermittedException
179
-	 */
180
-	private function getFolder(int $addressBookId, string $cardUri, bool $createIfNotExists = true): ISimpleFolder {
181
-		$hash = md5($addressBookId . ' ' . $cardUri);
182
-		try {
183
-			return $this->appData->getFolder($hash);
184
-		} catch (NotFoundException $e) {
185
-			if ($createIfNotExists) {
186
-				return $this->appData->newFolder($hash);
187
-			} else {
188
-				throw $e;
189
-			}
190
-		}
191
-	}
192
-
193
-	/**
194
-	 * Get the extension of the avatar. If there is no avatar throw Exception
195
-	 *
196
-	 * @param ISimpleFolder $folder
197
-	 * @return string
198
-	 * @throws NotFoundException
199
-	 */
200
-	private function getExtension(ISimpleFolder $folder): string {
201
-		foreach (self::ALLOWED_CONTENT_TYPES as $extension) {
202
-			if ($folder->fileExists('photo.' . $extension)) {
203
-				return $extension;
204
-			}
205
-		}
206
-
207
-		throw new NotFoundException('Avatar not found');
208
-	}
209
-
210
-	/**
211
-	 * @param Card $node
212
-	 * @return bool|array{body: string, Content-Type: string}
213
-	 */
214
-	private function getPhoto(Card $node) {
215
-		try {
216
-			$vObject = $this->readCard($node->get());
217
-			return $this->getPhotoFromVObject($vObject);
218
-		} catch (\Exception $e) {
219
-			$this->logger->logException($e, [
220
-				'message' => 'Exception during vcard photo parsing'
221
-			]);
222
-		}
223
-		return false;
224
-	}
225
-
226
-	/**
227
-	 * @param Document $vObject
228
-	 * @return bool|array{body: string, Content-Type: string}
229
-	 */
230
-	public function getPhotoFromVObject(Document $vObject) {
231
-		try {
232
-			if (!$vObject->PHOTO) {
233
-				return false;
234
-			}
235
-
236
-			$photo = $vObject->PHOTO;
237
-			$val = $photo->getValue();
238
-
239
-			// handle data URI. e.g PHOTO;VALUE=URI:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE
240
-			if ($photo->getValueType() === 'URI') {
241
-				$parsed = \Sabre\URI\parse($val);
242
-
243
-				// only allow data://
244
-				if ($parsed['scheme'] !== 'data') {
245
-					return false;
246
-				}
247
-				if (substr_count($parsed['path'], ';') === 1) {
248
-					[$type] = explode(';', $parsed['path']);
249
-				}
250
-				$val = file_get_contents($val);
251
-			} else {
252
-				// get type if binary data
253
-				$type = $this->getBinaryType($photo);
254
-			}
255
-
256
-			if (empty($type) || !isset(self::ALLOWED_CONTENT_TYPES[$type])) {
257
-				$type = 'application/octet-stream';
258
-			}
259
-
260
-			return [
261
-				'Content-Type' => $type,
262
-				'body' => $val
263
-			];
264
-		} catch (\Exception $e) {
265
-			$this->logger->logException($e, [
266
-				'message' => 'Exception during vcard photo parsing'
267
-			]);
268
-		}
269
-		return false;
270
-	}
271
-
272
-	/**
273
-	 * @param string $cardData
274
-	 * @return \Sabre\VObject\Document
275
-	 */
276
-	private function readCard($cardData) {
277
-		return Reader::read($cardData);
278
-	}
279
-
280
-	/**
281
-	 * @param Binary $photo
282
-	 * @return string
283
-	 */
284
-	private function getBinaryType(Binary $photo) {
285
-		$params = $photo->parameters();
286
-		if (isset($params['TYPE']) || isset($params['MEDIATYPE'])) {
287
-			/** @var Parameter $typeParam */
288
-			$typeParam = isset($params['TYPE']) ? $params['TYPE'] : $params['MEDIATYPE'];
289
-			$type = $typeParam->getValue();
290
-
291
-			if (strpos($type, 'image/') === 0) {
292
-				return $type;
293
-			} else {
294
-				return 'image/' . strtolower($type);
295
-			}
296
-		}
297
-		return '';
298
-	}
299
-
300
-	/**
301
-	 * @param int $addressBookId
302
-	 * @param string $cardUri
303
-	 * @throws NotPermittedException
304
-	 */
305
-	public function delete($addressBookId, $cardUri) {
306
-		try {
307
-			$folder = $this->getFolder($addressBookId, $cardUri, false);
308
-			$folder->delete();
309
-		} catch (NotFoundException $e) {
310
-			// that's OK, nothing to do
311
-		}
312
-	}
46
+    /** @var array  */
47
+    public const ALLOWED_CONTENT_TYPES = [
48
+        'image/png' => 'png',
49
+        'image/jpeg' => 'jpg',
50
+        'image/gif' => 'gif',
51
+        'image/vnd.microsoft.icon' => 'ico',
52
+    ];
53
+
54
+    /** @var IAppData */
55
+    protected $appData;
56
+
57
+    /** @var ILogger */
58
+    protected $logger;
59
+
60
+    /**
61
+     * PhotoCache constructor.
62
+     *
63
+     * @param IAppData $appData
64
+     * @param ILogger $logger
65
+     */
66
+    public function __construct(IAppData $appData, ILogger $logger) {
67
+        $this->appData = $appData;
68
+        $this->logger = $logger;
69
+    }
70
+
71
+    /**
72
+     * @param int $addressBookId
73
+     * @param string $cardUri
74
+     * @param int $size
75
+     * @param Card $card
76
+     *
77
+     * @return ISimpleFile
78
+     * @throws NotFoundException
79
+     */
80
+    public function get($addressBookId, $cardUri, $size, Card $card) {
81
+        $folder = $this->getFolder($addressBookId, $cardUri);
82
+
83
+        if ($this->isEmpty($folder)) {
84
+            $this->init($folder, $card);
85
+        }
86
+
87
+        if (!$this->hasPhoto($folder)) {
88
+            throw new NotFoundException();
89
+        }
90
+
91
+        if ($size !== -1) {
92
+            $size = 2 ** ceil(log($size) / log(2));
93
+        }
94
+
95
+        return $this->getFile($folder, $size);
96
+    }
97
+
98
+    /**
99
+     * @param ISimpleFolder $folder
100
+     * @return bool
101
+     */
102
+    private function isEmpty(ISimpleFolder $folder) {
103
+        return $folder->getDirectoryListing() === [];
104
+    }
105
+
106
+    /**
107
+     * @param ISimpleFolder $folder
108
+     * @param Card $card
109
+     * @throws NotPermittedException
110
+     */
111
+    private function init(ISimpleFolder $folder, Card $card): void {
112
+        $data = $this->getPhoto($card);
113
+
114
+        if ($data === false || !isset($data['Content-Type'])) {
115
+            $folder->newFile('nophoto', '');
116
+            return;
117
+        }
118
+
119
+        $contentType = $data['Content-Type'];
120
+        $extension = self::ALLOWED_CONTENT_TYPES[$contentType] ?? null;
121
+
122
+        if ($extension === null) {
123
+            $folder->newFile('nophoto', '');
124
+            return;
125
+        }
126
+
127
+        $file = $folder->newFile('photo.' . $extension);
128
+        $file->putContent($data['body']);
129
+    }
130
+
131
+    private function hasPhoto(ISimpleFolder $folder) {
132
+        return !$folder->fileExists('nophoto');
133
+    }
134
+
135
+    private function getFile(ISimpleFolder $folder, $size) {
136
+        $ext = $this->getExtension($folder);
137
+
138
+        if ($size === -1) {
139
+            $path = 'photo.' . $ext;
140
+        } else {
141
+            $path = 'photo.' . $size . '.' . $ext;
142
+        }
143
+
144
+        try {
145
+            $file = $folder->getFile($path);
146
+        } catch (NotFoundException $e) {
147
+            if ($size <= 0) {
148
+                throw new NotFoundException;
149
+            }
150
+
151
+            $photo = new \OC_Image();
152
+            /** @var ISimpleFile $file */
153
+            $file = $folder->getFile('photo.' . $ext);
154
+            $photo->loadFromData($file->getContent());
155
+
156
+            $ratio = $photo->width() / $photo->height();
157
+            if ($ratio < 1) {
158
+                $ratio = 1 / $ratio;
159
+            }
160
+
161
+            $size = (int) ($size * $ratio);
162
+            if ($size !== -1) {
163
+                $photo->resize($size);
164
+            }
165
+
166
+            try {
167
+                $file = $folder->newFile($path);
168
+                $file->putContent($photo->data());
169
+            } catch (NotPermittedException $e) {
170
+            }
171
+        }
172
+
173
+        return $file;
174
+    }
175
+
176
+    /**
177
+     * @throws NotFoundException
178
+     * @throws NotPermittedException
179
+     */
180
+    private function getFolder(int $addressBookId, string $cardUri, bool $createIfNotExists = true): ISimpleFolder {
181
+        $hash = md5($addressBookId . ' ' . $cardUri);
182
+        try {
183
+            return $this->appData->getFolder($hash);
184
+        } catch (NotFoundException $e) {
185
+            if ($createIfNotExists) {
186
+                return $this->appData->newFolder($hash);
187
+            } else {
188
+                throw $e;
189
+            }
190
+        }
191
+    }
192
+
193
+    /**
194
+     * Get the extension of the avatar. If there is no avatar throw Exception
195
+     *
196
+     * @param ISimpleFolder $folder
197
+     * @return string
198
+     * @throws NotFoundException
199
+     */
200
+    private function getExtension(ISimpleFolder $folder): string {
201
+        foreach (self::ALLOWED_CONTENT_TYPES as $extension) {
202
+            if ($folder->fileExists('photo.' . $extension)) {
203
+                return $extension;
204
+            }
205
+        }
206
+
207
+        throw new NotFoundException('Avatar not found');
208
+    }
209
+
210
+    /**
211
+     * @param Card $node
212
+     * @return bool|array{body: string, Content-Type: string}
213
+     */
214
+    private function getPhoto(Card $node) {
215
+        try {
216
+            $vObject = $this->readCard($node->get());
217
+            return $this->getPhotoFromVObject($vObject);
218
+        } catch (\Exception $e) {
219
+            $this->logger->logException($e, [
220
+                'message' => 'Exception during vcard photo parsing'
221
+            ]);
222
+        }
223
+        return false;
224
+    }
225
+
226
+    /**
227
+     * @param Document $vObject
228
+     * @return bool|array{body: string, Content-Type: string}
229
+     */
230
+    public function getPhotoFromVObject(Document $vObject) {
231
+        try {
232
+            if (!$vObject->PHOTO) {
233
+                return false;
234
+            }
235
+
236
+            $photo = $vObject->PHOTO;
237
+            $val = $photo->getValue();
238
+
239
+            // handle data URI. e.g PHOTO;VALUE=URI:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE
240
+            if ($photo->getValueType() === 'URI') {
241
+                $parsed = \Sabre\URI\parse($val);
242
+
243
+                // only allow data://
244
+                if ($parsed['scheme'] !== 'data') {
245
+                    return false;
246
+                }
247
+                if (substr_count($parsed['path'], ';') === 1) {
248
+                    [$type] = explode(';', $parsed['path']);
249
+                }
250
+                $val = file_get_contents($val);
251
+            } else {
252
+                // get type if binary data
253
+                $type = $this->getBinaryType($photo);
254
+            }
255
+
256
+            if (empty($type) || !isset(self::ALLOWED_CONTENT_TYPES[$type])) {
257
+                $type = 'application/octet-stream';
258
+            }
259
+
260
+            return [
261
+                'Content-Type' => $type,
262
+                'body' => $val
263
+            ];
264
+        } catch (\Exception $e) {
265
+            $this->logger->logException($e, [
266
+                'message' => 'Exception during vcard photo parsing'
267
+            ]);
268
+        }
269
+        return false;
270
+    }
271
+
272
+    /**
273
+     * @param string $cardData
274
+     * @return \Sabre\VObject\Document
275
+     */
276
+    private function readCard($cardData) {
277
+        return Reader::read($cardData);
278
+    }
279
+
280
+    /**
281
+     * @param Binary $photo
282
+     * @return string
283
+     */
284
+    private function getBinaryType(Binary $photo) {
285
+        $params = $photo->parameters();
286
+        if (isset($params['TYPE']) || isset($params['MEDIATYPE'])) {
287
+            /** @var Parameter $typeParam */
288
+            $typeParam = isset($params['TYPE']) ? $params['TYPE'] : $params['MEDIATYPE'];
289
+            $type = $typeParam->getValue();
290
+
291
+            if (strpos($type, 'image/') === 0) {
292
+                return $type;
293
+            } else {
294
+                return 'image/' . strtolower($type);
295
+            }
296
+        }
297
+        return '';
298
+    }
299
+
300
+    /**
301
+     * @param int $addressBookId
302
+     * @param string $cardUri
303
+     * @throws NotPermittedException
304
+     */
305
+    public function delete($addressBookId, $cardUri) {
306
+        try {
307
+            $folder = $this->getFolder($addressBookId, $cardUri, false);
308
+            $folder->delete();
309
+        } catch (NotFoundException $e) {
310
+            // that's OK, nothing to do
311
+        }
312
+    }
313 313
 }
Please login to merge, or discard this patch.