3333use OCP \IL10N ;
3434use OCP \IPreview ;
3535use OCP \IUserManager ;
36- use OCP \IUserSession ;
3736use OCP \L10N \IFactory ;
3837use Override ;
3938use Psr \Container \ContainerInterface ;
@@ -50,23 +49,22 @@ class TemplateManager implements ITemplateManager {
5049 /** @var array<class-string<ICustomTemplateProvider>, ICustomTemplateProvider>|null */
5150 private ?array $ providers = null ;
5251 private IL10n $ l10n ;
53- private ?string $ userId ;
5452
5553 public function __construct (
5654 private readonly ContainerInterface $ serverContainer ,
5755 private readonly IEventDispatcher $ eventDispatcher ,
5856 private readonly Coordinator $ bootstrapCoordinator ,
5957 private readonly IRootFolder $ rootFolder ,
60- IUserSession $ userSession ,
6158 private readonly IUserManager $ userManager ,
6259 private readonly IPreview $ previewManager ,
6360 private readonly IConfig $ config ,
6461 private readonly IFactory $ l10nFactory ,
6562 private readonly LoggerInterface $ logger ,
6663 private readonly IFilenameValidator $ filenameValidator ,
64+ private readonly string $ serverRoot ,
65+ private ?string $ userId ,
6766 ) {
6867 $ this ->l10n = $ l10nFactory ->get ('lib ' );
69- $ this ->userId = $ userSession ->getUser ()?->getUID();
7068 }
7169
7270 #[Override]
@@ -320,8 +318,8 @@ public function initializeTemplateDirectory(?string $path = null, ?string $userI
320318 $ this ->userId = $ userId ;
321319 }
322320
323- $ defaultSkeletonDirectory = \ OC :: $ SERVERROOT . '/core/skeleton ' ;
324- $ defaultTemplateDirectory = \ OC :: $ SERVERROOT . '/core/skeleton/Templates ' ;
321+ $ defaultSkeletonDirectory = $ this -> serverRoot . '/core/skeleton ' ;
322+ $ defaultTemplateDirectory = $ this -> serverRoot . '/core/skeleton/Templates ' ;
325323 $ skeletonPath = $ this ->config ->getSystemValueString ('skeletondirectory ' , $ defaultSkeletonDirectory );
326324 $ skeletonTemplatePath = $ this ->config ->getSystemValueString ('templatedirectory ' , $ defaultTemplateDirectory );
327325 $ isDefaultSkeleton = $ skeletonPath === $ defaultSkeletonDirectory ;
@@ -371,7 +369,7 @@ public function initializeTemplateDirectory(?string $path = null, ?string $userI
371369 if (!$ isDefaultTemplates && $ folderIsEmpty ) {
372370 $ localizedSkeletonTemplatePath = $ this ->getLocalizedTemplatePath ($ skeletonTemplatePath , $ userLang );
373371 if (!empty ($ localizedSkeletonTemplatePath ) && file_exists ($ localizedSkeletonTemplatePath )) {
374- \OC_Util:: copyr ($ localizedSkeletonTemplatePath , $ folder );
372+ $ this -> copyr ($ localizedSkeletonTemplatePath , $ folder );
375373 $ userFolder ->getStorage ()->getScanner ()->scan ($ folder ->getInternalPath (), Scanner::SCAN_RECURSIVE );
376374 $ this ->setTemplatePath ($ userTemplatePath );
377375 return $ userTemplatePath ;
@@ -381,7 +379,7 @@ public function initializeTemplateDirectory(?string $path = null, ?string $userI
381379 if ($ path !== null && $ isDefaultSkeleton && $ isDefaultTemplates && $ folderIsEmpty ) {
382380 $ localizedSkeletonPath = $ this ->getLocalizedTemplatePath ($ skeletonPath . '/Templates ' , $ userLang );
383381 if (!empty ($ localizedSkeletonPath ) && file_exists ($ localizedSkeletonPath )) {
384- \OC_Util:: copyr ($ localizedSkeletonPath , $ folder );
382+ $ this -> copyr ($ localizedSkeletonPath , $ folder );
385383 $ userFolder ->getStorage ()->getScanner ()->scan ($ folder ->getInternalPath (), Scanner::SCAN_RECURSIVE );
386384 $ this ->setTemplatePath ($ userTemplatePath );
387385 return $ userTemplatePath ;
@@ -412,4 +410,80 @@ private function getLocalizedTemplatePath(string $skeletonTemplatePath, string $
412410
413411 return $ localizedSkeletonTemplatePath ;
414412 }
413+
414+ /**
415+ * Copies a local directory recursively by using streams
416+ */
417+ private function copyr (string $ source , Folder $ target ): void {
418+ // Verify if folder exists
419+ $ dir = opendir ($ source );
420+ if ($ dir === false ) {
421+ $ this ->logger ->error (sprintf ('Could not opendir "%s" ' , $ source ), ['app ' => 'core ' ]);
422+ return ;
423+ }
424+
425+ // Copy the files
426+ while (false !== ($ file = readdir ($ dir ))) {
427+ if (!Filesystem::isIgnoredDir ($ file )) {
428+ if (is_dir ($ source . '/ ' . $ file )) {
429+ $ child = $ target ->newFolder ($ file );
430+ $ this ->copyr ($ source . '/ ' . $ file , $ child );
431+ } else {
432+ $ sourceStream = fopen ($ source . '/ ' . $ file , 'r ' );
433+ if ($ sourceStream === false ) {
434+ $ this ->logger ->error (sprintf ('Could not fopen "%s" ' , $ source . '/ ' . $ file ), ['app ' => 'core ' ]);
435+ closedir ($ dir );
436+ return ;
437+ }
438+ $ target ->newFile ($ file , $ sourceStream );
439+ }
440+ }
441+ }
442+ closedir ($ dir );
443+ }
444+
445+ public function copySkeleton (string $ userId ): void {
446+ $ user = $ this ->userManager ->get ($ userId );
447+ if ($ user === null ) {
448+ throw new \LogicException ('Trying to initialize home dir for a non-existent user ' );
449+ }
450+
451+ $ userDirectory = $ this ->rootFolder ->getUserFolder ($ userId );
452+
453+ $ plainSkeletonDirectory = $ this ->config ->getSystemValueString ('skeletondirectory ' , $ this ->serverRoot . '/core/skeleton ' );
454+ $ userLang = $ this ->l10nFactory ->findLanguage ();
455+ $ skeletonDirectory = str_replace ('{lang} ' , $ userLang , $ plainSkeletonDirectory );
456+
457+ if (!file_exists ($ skeletonDirectory )) {
458+ $ dialectStart = strpos ($ userLang , '_ ' );
459+ if ($ dialectStart !== false ) {
460+ $ skeletonDirectory = str_replace ('{lang} ' , substr ($ userLang , 0 , $ dialectStart ), $ plainSkeletonDirectory );
461+ }
462+ if ($ dialectStart === false || !file_exists ($ skeletonDirectory )) {
463+ $ skeletonDirectory = str_replace ('{lang} ' , 'default ' , $ plainSkeletonDirectory );
464+ }
465+ if (!file_exists ($ skeletonDirectory )) {
466+ $ skeletonDirectory = '' ;
467+ }
468+ }
469+
470+ $ instanceId = $ this ->config ->getSystemValue ('instanceid ' , '' );
471+
472+ if ($ instanceId === null ) {
473+ throw new \RuntimeException ('no instance id! ' );
474+ }
475+ $ appdata = 'appdata_ ' . $ instanceId ;
476+ if ($ userId === $ appdata ) {
477+ throw new \RuntimeException ('username is reserved name: ' . $ appdata );
478+ }
479+
480+ if (!empty ($ skeletonDirectory )) {
481+ $ this ->logger ->debug ('copying skeleton for ' . $ userId . ' from ' . $ skeletonDirectory . ' to ' . $ userDirectory ->getFullPath ('/ ' ), ['app ' => 'files_skeleton ' ]);
482+ $ this ->copyr ($ skeletonDirectory , $ userDirectory );
483+ // update the file cache
484+ $ userDirectory ->getStorage ()->getScanner ()->scan ('' , Scanner::SCAN_RECURSIVE );
485+
486+ $ this ->initializeTemplateDirectory (null , $ userId );
487+ }
488+ }
415489}
0 commit comments