7777use OCP \Share \Exceptions \ShareNotFound ;
7878use OCP \Share \IManager as ShareManager ;
7979use OCP \Share \IShare ;
80+ use OCP \Share \IPublicShareTemplateFactory ;
8081use OCP \Template ;
8182
8283/**
@@ -99,24 +100,28 @@ class ShareController extends AuthPublicShareController {
99100 protected ShareManager $ shareManager ;
100101 protected ISecureRandom $ secureRandom ;
101102 protected ?Share \IShare $ share = null ;
102-
103- public function __construct (string $ appName ,
104- IRequest $ request ,
105- IConfig $ config ,
106- IURLGenerator $ urlGenerator ,
107- IUserManager $ userManager ,
108- ILogger $ logger ,
109- \OCP \Activity \IManager $ activityManager ,
110- ShareManager $ shareManager ,
111- ISession $ session ,
112- IPreview $ previewManager ,
113- IRootFolder $ rootFolder ,
114- FederatedShareProvider $ federatedShareProvider ,
115- IAccountManager $ accountManager ,
116- IEventDispatcher $ eventDispatcher ,
117- IL10N $ l10n ,
118- ISecureRandom $ secureRandom ,
119- Defaults $ defaults ) {
103+ private IPublicShareTemplateFactory $ publicShareTemplateFactory ;
104+
105+ public function __construct (
106+ string $ appName ,
107+ IRequest $ request ,
108+ IConfig $ config ,
109+ IURLGenerator $ urlGenerator ,
110+ IUserManager $ userManager ,
111+ ILogger $ logger ,
112+ \OCP \Activity \IManager $ activityManager ,
113+ ShareManager $ shareManager ,
114+ ISession $ session ,
115+ IPreview $ previewManager ,
116+ IRootFolder $ rootFolder ,
117+ FederatedShareProvider $ federatedShareProvider ,
118+ IAccountManager $ accountManager ,
119+ IEventDispatcher $ eventDispatcher ,
120+ IL10N $ l10n ,
121+ ISecureRandom $ secureRandom ,
122+ Defaults $ defaults ,
123+ IPublicShareTemplateFactory $ publicShareTemplateFactory
124+ ) {
120125 parent ::__construct ($ appName , $ request , $ session , $ urlGenerator );
121126
122127 $ this ->config = $ config ;
@@ -132,6 +137,7 @@ public function __construct(string $appName,
132137 $ this ->secureRandom = $ secureRandom ;
133138 $ this ->defaults = $ defaults ;
134139 $ this ->shareManager = $ shareManager ;
140+ $ this ->publicShareTemplateFactory = $ publicShareTemplateFactory ;
135141 }
136142
137143 public const SHARE_ACCESS = 'access ' ;
@@ -367,6 +373,15 @@ public function showShare($path = ''): TemplateResponse {
367373
368374 $ shareNode = $ share ->getNode ();
369375
376+ try {
377+ $ templateProvider = $ this ->publicShareTemplateFactory ->getProvider ($ share );
378+ $ response = $ templateProvider ->renderPage ($ share , $ this ->getToken (), $ path );
379+ } catch (NotFoundException $ e ) {
380+ $ this ->emitAccessShareHook ($ share , 404 , 'Share not found ' );
381+ $ this ->emitShareAccessEvent ($ share , ShareController::SHARE_ACCESS , 404 , 'Share not found ' );
382+ throw new NotFoundException ();
383+ }
384+
370385 // We can't get the path of a file share
371386 try {
372387 if ($ shareNode instanceof \OCP \Files \File && $ path !== '' ) {
@@ -380,205 +395,6 @@ public function showShare($path = ''): TemplateResponse {
380395 throw $ e ;
381396 }
382397
383- $ shareTmpl = [];
384- $ shareTmpl ['owner ' ] = '' ;
385- $ shareTmpl ['shareOwner ' ] = '' ;
386-
387- $ owner = $ this ->userManager ->get ($ share ->getShareOwner ());
388- if ($ owner instanceof IUser) {
389- $ ownerAccount = $ this ->accountManager ->getAccount ($ owner );
390-
391- $ ownerName = $ ownerAccount ->getProperty (IAccountManager::PROPERTY_DISPLAYNAME );
392- if ($ ownerName ->getScope () === IAccountManager::SCOPE_PUBLISHED ) {
393- $ shareTmpl ['owner ' ] = $ owner ->getUID ();
394- $ shareTmpl ['shareOwner ' ] = $ owner ->getDisplayName ();
395- }
396- }
397-
398- $ shareTmpl ['filename ' ] = $ shareNode ->getName ();
399- $ shareTmpl ['directory_path ' ] = $ share ->getTarget ();
400- $ shareTmpl ['note ' ] = $ share ->getNote ();
401- $ shareTmpl ['mimetype ' ] = $ shareNode ->getMimetype ();
402- $ shareTmpl ['previewSupported ' ] = $ this ->previewManager ->isMimeSupported ($ shareNode ->getMimetype ());
403- $ shareTmpl ['dirToken ' ] = $ this ->getToken ();
404- $ shareTmpl ['sharingToken ' ] = $ this ->getToken ();
405- $ shareTmpl ['server2serversharing ' ] = $ this ->federatedShareProvider ->isOutgoingServer2serverShareEnabled ();
406- $ shareTmpl ['protected ' ] = $ share ->getPassword () !== null ? 'true ' : 'false ' ;
407- $ shareTmpl ['dir ' ] = '' ;
408- $ shareTmpl ['nonHumanFileSize ' ] = $ shareNode ->getSize ();
409- $ shareTmpl ['fileSize ' ] = \OCP \Util::humanFileSize ($ shareNode ->getSize ());
410- $ shareTmpl ['hideDownload ' ] = $ share ->getHideDownload ();
411-
412- $ hideFileList = false ;
413-
414- if ($ shareNode instanceof \OCP \Files \Folder) {
415- $ shareIsFolder = true ;
416-
417- try {
418- $ folderNode = $ shareNode ->get ($ path );
419- } catch (\OCP \Files \NotFoundException $ e ) {
420- $ this ->emitAccessShareHook ($ share , 404 , 'Share not found ' );
421- $ this ->emitShareAccessEvent ($ share , self ::SHARE_ACCESS , 404 , 'Share not found ' );
422- throw new NotFoundException ();
423- }
424-
425- $ shareTmpl ['dir ' ] = $ shareNode ->getRelativePath ($ folderNode ->getPath ());
426-
427- /*
428- * The OC_Util methods require a view. This just uses the node API
429- */
430- $ freeSpace = $ share ->getNode ()->getStorage ()->free_space ($ share ->getNode ()->getInternalPath ());
431- if ($ freeSpace < \OCP \Files \FileInfo::SPACE_UNLIMITED ) {
432- $ freeSpace = (int )max ($ freeSpace , 0 );
433- } else {
434- $ freeSpace = (INF > 0 ) ? INF : PHP_INT_MAX ; // work around https://bugs.php.net/bug.php?id=69188
435- }
436-
437- $ hideFileList = !($ share ->getPermissions () & \OCP \Constants::PERMISSION_READ );
438- $ maxUploadFilesize = $ freeSpace ;
439-
440- $ folder = new Template ('files ' , 'list ' , '' );
441-
442- $ folder ->assign ('dir ' , $ shareNode ->getRelativePath ($ folderNode ->getPath ()));
443- $ folder ->assign ('dirToken ' , $ this ->getToken ());
444- $ folder ->assign ('permissions ' , \OCP \Constants::PERMISSION_READ );
445- $ folder ->assign ('isPublic ' , true );
446- $ folder ->assign ('hideFileList ' , $ hideFileList );
447- $ folder ->assign ('publicUploadEnabled ' , 'no ' );
448- // default to list view
449- $ folder ->assign ('showgridview ' , false );
450- $ folder ->assign ('uploadMaxFilesize ' , $ maxUploadFilesize );
451- $ folder ->assign ('uploadMaxHumanFilesize ' , \OCP \Util::humanFileSize ($ maxUploadFilesize ));
452- $ folder ->assign ('freeSpace ' , $ freeSpace );
453- $ folder ->assign ('usedSpacePercent ' , 0 );
454- $ folder ->assign ('trash ' , false );
455- $ shareTmpl ['folder ' ] = $ folder ->fetchPage ();
456- } else {
457- $ shareIsFolder = false ;
458- }
459-
460- // default to list view
461- $ shareTmpl ['showgridview ' ] = false ;
462-
463- $ shareTmpl ['hideFileList ' ] = $ hideFileList ;
464- $ shareTmpl ['downloadURL ' ] = $ this ->urlGenerator ->linkToRouteAbsolute ('files_sharing.sharecontroller.downloadShare ' , [
465- 'token ' => $ this ->getToken (),
466- 'filename ' => $ shareIsFolder ? null : $ shareNode ->getName ()
467- ]);
468- $ shareTmpl ['shareUrl ' ] = $ this ->urlGenerator ->linkToRouteAbsolute ('files_sharing.sharecontroller.showShare ' , ['token ' => $ this ->getToken ()]);
469- $ shareTmpl ['maxSizeAnimateGif ' ] = $ this ->config ->getSystemValue ('max_filesize_animated_gifs_public_sharing ' , 10 );
470- $ shareTmpl ['previewEnabled ' ] = $ this ->config ->getSystemValue ('enable_previews ' , true );
471- $ shareTmpl ['previewMaxX ' ] = $ this ->config ->getSystemValue ('preview_max_x ' , 1024 );
472- $ shareTmpl ['previewMaxY ' ] = $ this ->config ->getSystemValue ('preview_max_y ' , 1024 );
473- $ shareTmpl ['disclaimer ' ] = $ this ->config ->getAppValue ('core ' , 'shareapi_public_link_disclaimertext ' , null );
474- $ shareTmpl ['previewURL ' ] = $ shareTmpl ['downloadURL ' ];
475-
476- if ($ shareTmpl ['previewSupported ' ]) {
477- $ shareTmpl ['previewImage ' ] = $ this ->urlGenerator ->linkToRouteAbsolute ('files_sharing.PublicPreview.getPreview ' ,
478- ['x ' => 200 , 'y ' => 200 , 'file ' => $ shareTmpl ['directory_path ' ], 'token ' => $ shareTmpl ['dirToken ' ]]);
479- $ ogPreview = $ shareTmpl ['previewImage ' ];
480-
481- // We just have direct previews for image files
482- if ($ shareNode ->getMimePart () === 'image ' ) {
483- $ shareTmpl ['previewURL ' ] = $ this ->urlGenerator ->linkToRouteAbsolute ('files_sharing.publicpreview.directLink ' , ['token ' => $ this ->getToken ()]);
484-
485- $ ogPreview = $ shareTmpl ['previewURL ' ];
486-
487- //Whatapp is kind of picky about their size requirements
488- if ($ this ->request ->isUserAgent (['/^WhatsApp/ ' ])) {
489- $ ogPreview = $ this ->urlGenerator ->linkToRouteAbsolute ('files_sharing.PublicPreview.getPreview ' , [
490- 'token ' => $ this ->getToken (),
491- 'x ' => 256 ,
492- 'y ' => 256 ,
493- 'a ' => true ,
494- ]);
495- }
496- }
497- } else {
498- $ shareTmpl ['previewImage ' ] = $ this ->urlGenerator ->getAbsoluteURL ($ this ->urlGenerator ->imagePath ('core ' , 'favicon-fb.png ' ));
499- $ ogPreview = $ shareTmpl ['previewImage ' ];
500- }
501-
502- // Load files we need
503- \OCP \Util::addScript ('files ' , 'semaphore ' );
504- \OCP \Util::addScript ('files ' , 'file-upload ' );
505- \OCP \Util::addStyle ('files_sharing ' , 'publicView ' );
506- \OCP \Util::addScript ('files_sharing ' , 'public ' );
507- \OCP \Util::addScript ('files_sharing ' , 'templates ' );
508- \OCP \Util::addScript ('files ' , 'fileactions ' );
509- \OCP \Util::addScript ('files ' , 'fileactionsmenu ' );
510- \OCP \Util::addScript ('files ' , 'jquery.fileupload ' );
511- \OCP \Util::addScript ('files_sharing ' , 'files_drop ' );
512-
513- if (isset ($ shareTmpl ['folder ' ])) {
514- // JS required for folders
515- \OCP \Util::addStyle ('files ' , 'merged ' );
516- \OCP \Util::addScript ('files ' , 'filesummary ' );
517- \OCP \Util::addScript ('files ' , 'templates ' );
518- \OCP \Util::addScript ('files ' , 'breadcrumb ' );
519- \OCP \Util::addScript ('files ' , 'fileinfomodel ' );
520- \OCP \Util::addScript ('files ' , 'newfilemenu ' );
521- \OCP \Util::addScript ('files ' , 'files ' );
522- \OCP \Util::addScript ('files ' , 'filemultiselectmenu ' );
523- \OCP \Util::addScript ('files ' , 'filelist ' );
524- \OCP \Util::addScript ('files ' , 'keyboardshortcuts ' );
525- \OCP \Util::addScript ('files ' , 'operationprogressbar ' );
526- }
527-
528- // Load Viewer scripts
529- if (class_exists (LoadViewer::class)) {
530- $ this ->eventDispatcher ->dispatchTyped (new LoadViewer ());
531- }
532- // OpenGraph Support: http://ogp.me/
533- \OCP \Util::addHeader ('meta ' , ['property ' => "og:title " , 'content ' => $ shareTmpl ['filename ' ]]);
534- \OCP \Util::addHeader ('meta ' , ['property ' => "og:description " , 'content ' => $ this ->defaults ->getName () . ($ this ->defaults ->getSlogan () !== '' ? ' - ' . $ this ->defaults ->getSlogan () : '' )]);
535- \OCP \Util::addHeader ('meta ' , ['property ' => "og:site_name " , 'content ' => $ this ->defaults ->getName ()]);
536- \OCP \Util::addHeader ('meta ' , ['property ' => "og:url " , 'content ' => $ shareTmpl ['shareUrl ' ]]);
537- \OCP \Util::addHeader ('meta ' , ['property ' => "og:type " , 'content ' => "object " ]);
538- \OCP \Util::addHeader ('meta ' , ['property ' => "og:image " , 'content ' => $ ogPreview ]);
539-
540- $ this ->eventDispatcher ->dispatchTyped (new BeforeTemplateRenderedEvent ($ share ));
541-
542- $ csp = new \OCP \AppFramework \Http \ContentSecurityPolicy ();
543- $ csp ->addAllowedFrameDomain ('\'self \'' );
544-
545- $ response = new PublicTemplateResponse ($ this ->appName , 'public ' , $ shareTmpl );
546- $ response ->setHeaderTitle ($ shareTmpl ['filename ' ]);
547- if ($ shareTmpl ['shareOwner ' ] !== '' ) {
548- $ response ->setHeaderDetails ($ this ->l10n ->t ('shared by %s ' , [$ shareTmpl ['shareOwner ' ]]));
549- }
550-
551- $ isNoneFileDropFolder = $ shareIsFolder === false || $ share ->getPermissions () !== \OCP \Constants::PERMISSION_CREATE ;
552-
553- if ($ isNoneFileDropFolder && !$ share ->getHideDownload ()) {
554- \OCP \Util::addScript ('files_sharing ' , 'public_note ' );
555-
556- $ downloadWhite = new SimpleMenuAction ('download ' , $ this ->l10n ->t ('Download ' ), 'icon-download-white ' , $ shareTmpl ['downloadURL ' ], 0 );
557- $ downloadAllWhite = new SimpleMenuAction ('download ' , $ this ->l10n ->t ('Download all files ' ), 'icon-download-white ' , $ shareTmpl ['downloadURL ' ], 0 );
558- $ download = new SimpleMenuAction ('download ' , $ this ->l10n ->t ('Download ' ), 'icon-download ' , $ shareTmpl ['downloadURL ' ], 10 , $ shareTmpl ['fileSize ' ]);
559- $ downloadAll = new SimpleMenuAction ('download ' , $ this ->l10n ->t ('Download all files ' ), 'icon-download ' , $ shareTmpl ['downloadURL ' ], 10 , $ shareTmpl ['fileSize ' ]);
560- $ directLink = new LinkMenuAction ($ this ->l10n ->t ('Direct link ' ), 'icon-public ' , $ shareTmpl ['previewURL ' ]);
561- // TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
562- $ externalShare = new ExternalShareMenuAction ($ this ->l10n ->t ('Add to your %s ' , [$ this ->defaults ->getProductName ()]), 'icon-external ' , $ shareTmpl ['owner ' ], $ shareTmpl ['shareOwner ' ], $ shareTmpl ['filename ' ]);
563-
564- $ responseComposer = [];
565-
566- if ($ shareIsFolder ) {
567- $ responseComposer [] = $ downloadAllWhite ;
568- $ responseComposer [] = $ downloadAll ;
569- } else {
570- $ responseComposer [] = $ downloadWhite ;
571- $ responseComposer [] = $ download ;
572- }
573- $ responseComposer [] = $ directLink ;
574- if ($ this ->federatedShareProvider ->isOutgoingServer2serverShareEnabled ()) {
575- $ responseComposer [] = $ externalShare ;
576- }
577-
578- $ response ->setHeaderActions ($ responseComposer );
579- }
580-
581- $ response ->setContentSecurityPolicy ($ csp );
582398
583399 $ this ->emitAccessShareHook ($ share );
584400 $ this ->emitShareAccessEvent ($ share , self ::SHARE_ACCESS );
0 commit comments