@@ -64,9 +64,11 @@ public function __construct(
6464 private readonly IFactory $ l10nFactory ,
6565 private readonly LoggerInterface $ logger ,
6666 private readonly IFilenameValidator $ filenameValidator ,
67+ private readonly string $ serverRoot ,
6768 ) {
6869 $ this ->l10n = $ l10nFactory ->get ('lib ' );
6970 $ this ->userId = $ userSession ->getUser ()?->getUID();
71+
7072 }
7173
7274 #[Override]
@@ -320,8 +322,8 @@ public function initializeTemplateDirectory(?string $path = null, ?string $userI
320322 $ this ->userId = $ userId ;
321323 }
322324
323- $ defaultSkeletonDirectory = \ OC :: $ SERVERROOT . '/core/skeleton ' ;
324- $ defaultTemplateDirectory = \ OC :: $ SERVERROOT . '/core/skeleton/Templates ' ;
325+ $ defaultSkeletonDirectory = $ this -> serverRoot . '/core/skeleton ' ;
326+ $ defaultTemplateDirectory = $ this -> serverRoot . '/core/skeleton/Templates ' ;
325327 $ skeletonPath = $ this ->config ->getSystemValueString ('skeletondirectory ' , $ defaultSkeletonDirectory );
326328 $ skeletonTemplatePath = $ this ->config ->getSystemValueString ('templatedirectory ' , $ defaultTemplateDirectory );
327329 $ isDefaultSkeleton = $ skeletonPath === $ defaultSkeletonDirectory ;
@@ -371,7 +373,7 @@ public function initializeTemplateDirectory(?string $path = null, ?string $userI
371373 if (!$ isDefaultTemplates && $ folderIsEmpty ) {
372374 $ localizedSkeletonTemplatePath = $ this ->getLocalizedTemplatePath ($ skeletonTemplatePath , $ userLang );
373375 if (!empty ($ localizedSkeletonTemplatePath ) && file_exists ($ localizedSkeletonTemplatePath )) {
374- \OC_Util:: copyr ($ localizedSkeletonTemplatePath , $ folder );
376+ $ this -> copyr ($ localizedSkeletonTemplatePath , $ folder );
375377 $ userFolder ->getStorage ()->getScanner ()->scan ($ folder ->getInternalPath (), Scanner::SCAN_RECURSIVE );
376378 $ this ->setTemplatePath ($ userTemplatePath );
377379 return $ userTemplatePath ;
@@ -381,7 +383,7 @@ public function initializeTemplateDirectory(?string $path = null, ?string $userI
381383 if ($ path !== null && $ isDefaultSkeleton && $ isDefaultTemplates && $ folderIsEmpty ) {
382384 $ localizedSkeletonPath = $ this ->getLocalizedTemplatePath ($ skeletonPath . '/Templates ' , $ userLang );
383385 if (!empty ($ localizedSkeletonPath ) && file_exists ($ localizedSkeletonPath )) {
384- \OC_Util:: copyr ($ localizedSkeletonPath , $ folder );
386+ $ this -> copyr ($ localizedSkeletonPath , $ folder );
385387 $ userFolder ->getStorage ()->getScanner ()->scan ($ folder ->getInternalPath (), Scanner::SCAN_RECURSIVE );
386388 $ this ->setTemplatePath ($ userTemplatePath );
387389 return $ userTemplatePath ;
@@ -412,4 +414,80 @@ private function getLocalizedTemplatePath(string $skeletonTemplatePath, string $
412414
413415 return $ localizedSkeletonTemplatePath ;
414416 }
417+
418+ /**
419+ * Copies a local directory recursively by using streams
420+ */
421+ private function copyr (string $ source , Folder $ target ): void {
422+ // Verify if folder exists
423+ $ dir = opendir ($ source );
424+ if ($ dir === false ) {
425+ $ this ->logger ->error (sprintf ('Could not opendir "%s" ' , $ source ), ['app ' => 'core ' ]);
426+ return ;
427+ }
428+
429+ // Copy the files
430+ while (false !== ($ file = readdir ($ dir ))) {
431+ if (!Filesystem::isIgnoredDir ($ file )) {
432+ if (is_dir ($ source . '/ ' . $ file )) {
433+ $ child = $ target ->newFolder ($ file );
434+ $ this ->copyr ($ source . '/ ' . $ file , $ child );
435+ } else {
436+ $ sourceStream = fopen ($ source . '/ ' . $ file , 'r ' );
437+ if ($ sourceStream === false ) {
438+ $ this ->logger ->error (sprintf ('Could not fopen "%s" ' , $ source . '/ ' . $ file ), ['app ' => 'core ' ]);
439+ closedir ($ dir );
440+ return ;
441+ }
442+ $ target ->newFile ($ file , $ sourceStream );
443+ }
444+ }
445+ }
446+ closedir ($ dir );
447+ }
448+
449+ public function copySkeleton (string $ userId ): void {
450+ $ user = $ this ->userManager ->get ($ userId );
451+ if ($ user === null ) {
452+ throw new \LogicException ('Trying to initialize home dir for a non-existent user ' );
453+ }
454+
455+ $ userDirectory = $ this ->rootFolder ->getUserFolder ($ userId );
456+
457+ $ plainSkeletonDirectory = $ this ->config ->getSystemValueString ('skeletondirectory ' , $ this ->serverRoot . '/core/skeleton ' );
458+ $ userLang = $ this ->l10nFactory ->findLanguage ();
459+ $ skeletonDirectory = str_replace ('{lang} ' , $ userLang , $ plainSkeletonDirectory );
460+
461+ if (!file_exists ($ skeletonDirectory )) {
462+ $ dialectStart = strpos ($ userLang , '_ ' );
463+ if ($ dialectStart !== false ) {
464+ $ skeletonDirectory = str_replace ('{lang} ' , substr ($ userLang , 0 , $ dialectStart ), $ plainSkeletonDirectory );
465+ }
466+ if ($ dialectStart === false || !file_exists ($ skeletonDirectory )) {
467+ $ skeletonDirectory = str_replace ('{lang} ' , 'default ' , $ plainSkeletonDirectory );
468+ }
469+ if (!file_exists ($ skeletonDirectory )) {
470+ $ skeletonDirectory = '' ;
471+ }
472+ }
473+
474+ $ instanceId = $ this ->config ->getSystemValue ('instanceid ' , '' );
475+
476+ if ($ instanceId === null ) {
477+ throw new \RuntimeException ('no instance id! ' );
478+ }
479+ $ appdata = 'appdata_ ' . $ instanceId ;
480+ if ($ userId === $ appdata ) {
481+ throw new \RuntimeException ('username is reserved name: ' . $ appdata );
482+ }
483+
484+ if (!empty ($ skeletonDirectory )) {
485+ $ this ->logger ->debug ('copying skeleton for ' . $ userId . ' from ' . $ skeletonDirectory . ' to ' . $ userDirectory ->getFullPath ('/ ' ), ['app ' => 'files_skeleton ' ]);
486+ $ this ->copyr ($ skeletonDirectory , $ userDirectory );
487+ // update the file cache
488+ $ userDirectory ->getStorage ()->getScanner ()->scan ('' , Scanner::SCAN_RECURSIVE );
489+
490+ $ this ->initializeTemplateDirectory (null , $ userId );
491+ }
492+ }
415493}
0 commit comments