13
13
use OCP \Files \File ;
14
14
use OCP \Files \FileInfo ;
15
15
use OCP \Files \Folder ;
16
+ use OCP \Files \IFilenameValidator ;
17
+ use OCP \Files \NotFoundException ;
16
18
use OCP \Files \NotPermittedException ;
17
19
18
20
class NotesService {
19
21
private MetaService $ metaService ;
20
22
private SettingsService $ settings ;
21
23
private NoteUtil $ noteUtil ;
24
+ private IFilenameValidator $ filenameValidator ;
22
25
23
26
public function __construct (
24
27
MetaService $ metaService ,
25
28
SettingsService $ settings ,
26
29
NoteUtil $ noteUtil ,
30
+ IFilenameValidator $ filenameValidator ,
27
31
) {
28
32
$ this ->metaService = $ metaService ;
29
33
$ this ->settings = $ settings ;
30
34
$ this ->noteUtil = $ noteUtil ;
35
+ $ this ->filenameValidator = $ filenameValidator ;
31
36
}
32
37
33
38
public function getAll (string $ userId , bool $ autoCreateNotesFolder = false ) : array {
@@ -223,8 +228,8 @@ private static function getFileById(string $customExtension, Folder $folder, int
223
228
* @NoCSRFRequired
224
229
* @return \OCP\Files\File
225
230
*/
226
- public function getAttachment (string $ userId , int $ noteid , string $ path ) : File {
227
- $ note = $ this ->get ($ userId , $ noteid );
231
+ public function getAttachment (string $ userId , int $ noteId , string $ path ) : File {
232
+ $ note = $ this ->get ($ userId , $ noteId );
228
233
$ notesFolder = $ this ->getNotesFolder ($ userId );
229
234
$ path = str_replace ('\\' , '/ ' , $ path ); // change windows style path
230
235
$ p = explode ('/ ' , $ note ->getCategory ());
@@ -243,24 +248,24 @@ public function getAttachment(string $userId, int $noteid, string $path) : File
243
248
244
249
/**
245
250
* @param $userId
246
- * @param $noteid
251
+ * @param $noteId
247
252
* @param $fileDataArray
253
+ *
254
+ * @return array
248
255
* @throws NotPermittedException
249
256
* @throws ImageNotWritableException
250
- * https://github.com/nextcloud/deck/blob/master/lib/Service/AttachmentService.php
257
+ * @throws NotFoundException
258
+ * @throws InvalidPathException
259
+ * https://github.com/nextcloud/text/blob/main/lib/Service/AttachmentService.php
251
260
*/
252
- public function createImage (string $ userId , int $ noteid , $ fileDataArray ) {
253
- $ note = $ this ->get ($ userId , $ noteid );
261
+ public function createImage (string $ userId , int $ noteId , $ fileDataArray ) : array {
262
+ $ note = $ this ->get ($ userId , $ noteId );
254
263
$ notesFolder = $ this ->getNotesFolder ($ userId );
255
- $ parent = $ this ->noteUtil ->getCategoryFolder ($ notesFolder , $ note ->getCategory ());
264
+ $ parentFolder = $ this ->noteUtil ->getCategoryFolder ($ notesFolder , $ note ->getCategory ());
256
265
257
- // try to generate long id, if not available on system fall back to a shorter one
258
- try {
259
- $ filename = bin2hex (random_bytes (16 ));
260
- } catch (\Exception $ e ) {
261
- $ filename = uniqid ();
262
- }
263
- $ filename = $ filename . '. ' . explode ('. ' , $ fileDataArray ['name ' ])[1 ];
266
+ $ saveDir = $ this ->getAttachmentDirectoryForNote ($ note , $ userId );
267
+ $ fileName = self ::getUniqueFileName ($ saveDir , $ fileDataArray ['name ' ]);
268
+ $ this ->filenameValidator ->validateFilename ($ fileName );
264
269
265
270
if ($ fileDataArray ['tmp_name ' ] === '' ) {
266
271
throw new ImageNotWritableException ();
@@ -272,8 +277,61 @@ public function createImage(string $userId, int $noteid, $fileDataArray) {
272
277
fclose ($ fp );
273
278
274
279
$ result = [];
275
- $ result ['filename ' ] = $ filename ;
276
- $ this -> noteUtil -> getRoot ()-> newFile ($ parent -> getPath () . ' / ' . $ filename , $ content );
280
+ $ result ['filename ' ] = ' .attachments. ' . $ note -> getId () . ' / ' . $ fileName ;
281
+ $ saveDir -> newFile ($ fileName , $ content );
277
282
return $ result ;
278
283
}
284
+
285
+ /**
286
+ * Get unique file name in a directory. Add '(n)' suffix.
287
+ *
288
+ * @param Folder $dir
289
+ * @param string $fileName
290
+ *
291
+ * @return string
292
+ */
293
+ public static function getUniqueFileName (Folder $ dir , string $ fileName ) : string {
294
+ $ extension = pathinfo ($ fileName , PATHINFO_EXTENSION );
295
+ $ counter = 1 ;
296
+ $ uniqueFileName = $ fileName ;
297
+ if ($ extension !== '' ) {
298
+ while ($ dir ->nodeExists ($ uniqueFileName )) {
299
+ $ counter ++;
300
+ $ uniqueFileName = (string )preg_replace ('/\. ' . $ extension . '$/ ' , ' ( ' . $ counter . '). ' . $ extension , $ fileName );
301
+ }
302
+ } else {
303
+ while ($ dir ->nodeExists ($ uniqueFileName )) {
304
+ $ counter ++;
305
+ $ uniqueFileName = (string )preg_replace ('/$/ ' , ' ( ' . $ counter . ') ' , $ fileName );
306
+ }
307
+ }
308
+ return $ uniqueFileName ;
309
+ }
310
+
311
+ /**
312
+ * Get or create file--specific attachment folder
313
+ *
314
+ * @param Note $note
315
+ * @param string $userid
316
+ *
317
+ * @return Folder
318
+ * @throws NotFoundException
319
+ * @throws NotPermittedException
320
+ * @throws InvalidPathException
321
+ */
322
+ private function getAttachmentDirectoryForNote (Note $ note , string $ userId ) : Folder {
323
+ $ notesFolder = $ this ->getNotesFolder ($ userId );
324
+ $ parentFolder = $ this ->noteUtil ->getCategoryFolder ($ notesFolder , $ note ->getCategory ());
325
+
326
+ $ attachmentFolderName = '.attachments. ' . $ note ->getId ();
327
+ if ($ parentFolder ->nodeExists ($ attachmentFolderName )) {
328
+ $ attachmentFolder = $ parentFolder ->get ($ attachmentFolderName );
329
+ if ($ attachmentFolder instanceof Folder) {
330
+ return $ attachmentFolder ;
331
+ }
332
+ } else {
333
+ return $ parentFolder ->newFolder ($ attachmentFolderName );
334
+ }
335
+ throw new NotFoundException ('Attachment dir for note ' . $ note ->getId () . ' was not found or could not be created. ' );
336
+ }
279
337
}
0 commit comments