[BUGFIX] Exception if directories are not readable 05/26905/6
authorSteffen Ritter <info@rs-websystems.de>
Tue, 21 Jan 2014 09:49:23 +0000 (10:49 +0100)
committerSteffen Ritter <info@rs-websystems.de>
Thu, 30 Jan 2014 18:36:30 +0000 (19:36 +0100)
If a user has listing rights on a folder which contains
folders he does not have access to the user currently
will end up with Exceptions in folder trees, file lists
as well as element browsers.

Before FAL these folders just have been shown "locked".

This change introduces an "InaccessibleFolder" object
which will be created by the storage if a Folder is
requested which exists but there is no read access while
the user is allowed to list the contents of the parent
folder.

In addition the components have been adapted to use this
new information for a graceful behaviour.

WIP: Did not adapt the tests yet, since I need to do some
urgent customer work. Feel free to go on with that.

Resolves: #51512, #53854
Releases: 6.2
Change-Id: If5c234fe66d1930e4cc0cb16279d2f77874d82db
Reviewed-on: https://review.typo3.org/26905
Tested-by: Ingo Schmitt
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Ingo Schmitt
Reviewed-by: Steffen Ritter
Tested-by: Steffen Ritter
typo3/sysext/backend/Classes/Tree/View/FolderTreeView.php
typo3/sysext/core/Classes/Resource/InaccessibleFolder.php [new file with mode: 0644]
typo3/sysext/core/Classes/Resource/ResourceStorage.php
typo3/sysext/filelist/Classes/FileList.php
typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php

index f600e08..7c0c3f2 100644 (file)
@@ -148,7 +148,7 @@ class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
                // Wrap icon in click-menu link.
                if (!$this->ext_IconMode) {
                        // Check storage access to wrap with click menu
-                       if ($folderObject->getStorage()->hasFolder('/')) {
+                       if (!$folderObject instanceof \TYPO3\CMS\Core\Resource\InaccessibleFolder) {
                                $theFolderIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($theFolderIcon, $folderObject->getCombinedIdentifier(), '', 0);
                        }
                } elseif ($this->ext_IconMode === 'titlelink') {
@@ -169,7 +169,7 @@ class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
         */
        public function wrapTitle($title, \TYPO3\CMS\Core\Resource\Folder $folderObject, $bank = 0) {
                // Check storage access to wrap with click menu
-               if (!$folderObject->getStorage()->hasFolder('/')) {
+               if ($folderObject instanceof \TYPO3\CMS\Core\Resource\InaccessibleFolder) {
                        return $title;
                }
                $aOnClick = 'return jumpTo(\'' . $this->getJumpToParam($folderObject) . '\', this, \'' . $this->domIdPrefix . $this->getId($folderObject) . '\', ' . $bank . ');';
@@ -348,9 +348,13 @@ class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
 
                // This generates the directory tree
                /* array of \TYPO3\CMS\Core\Resource\Folder */
-               $subFolders = $folderObject->getSubfolders();
-               $subFolders = \TYPO3\CMS\Core\Resource\Utility\ListUtility::resolveSpecialFolderNames($subFolders);
-               uksort($subFolders, 'strnatcasecmp');
+               if ($folderObject instanceof \TYPO3\CMS\Core\Resource\InaccessibleFolder) {
+                       $subFolders = array();
+               } else {
+                       $subFolders = $folderObject->getSubfolders();
+                       $subFolders = \TYPO3\CMS\Core\Resource\Utility\ListUtility::resolveSpecialFolderNames($subFolders);
+                       uksort($subFolders, 'strnatcasecmp');
+               }
 
                $totalSubFolders = count($subFolders);
                $HTML = '';
@@ -361,6 +365,7 @@ class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
                        $this->tree[] = array();
                        // Get the key for this space
                        end($this->tree);
+                       $isLocked = $subFolder instanceof \TYPO3\CMS\Core\Resource\InaccessibleFolder;
                        $treeKey = key($this->tree);
                        $specUID = GeneralUtility::md5int($subFolder->getCombinedIdentifier());
                        $this->specUIDmap[$specUID] = $subFolder->getCombinedIdentifier();
@@ -371,22 +376,22 @@ class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
                                'folder' => $subFolder
                        );
                        // Make a recursive call to the next level
-                       if ($depth > 1 && $this->expandNext($specUID)) {
+                       if (!$isLocked && $depth > 1 && $this->expandNext($specUID)) {
                                $nextCount = $this->getFolderTree($subFolder, $depth - 1, $type);
                                // Set "did expand" flag
                                $isOpen = 1;
                        } else {
-                               $nextCount = $this->getNumberOfSubfolders($subFolder);
+                               $nextCount = $isLocked ? 0 : $this->getNumberOfSubfolders($subFolder);
                                // Clear "did expand" flag
                                $isOpen = 0;
                        }
                        // Set HTML-icons, if any:
                        if ($this->makeHTML) {
                                $HTML = $this->PMicon($subFolder, $subFolderCounter, $totalSubFolders, $nextCount, $isOpen);
-                               if ($subFolder->checkActionPermission('write')) {
-                                       $type = '';
-                                       $overlays = array();
-                               } else {
+                               $type = '';
+                               $overlays = array();
+
+                               if ($isLocked) {
                                        $type = 'readonly';
                                        $overlays = array('status-overlay-locked' => array());
                                }
diff --git a/typo3/sysext/core/Classes/Resource/InaccessibleFolder.php b/typo3/sysext/core/Classes/Resource/InaccessibleFolder.php
new file mode 100644 (file)
index 0000000..093f07e
--- /dev/null
@@ -0,0 +1,271 @@
+<?php
+namespace TYPO3\CMS\Core\Resource;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Steffen Ritter <steffen.ritter@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the text file GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\PathUtility;
+
+/**
+ * A representation for an inaccessible folder.
+ *
+ * If a folder has execution rights you can list it's contents
+ * despite the access rights on the subfolders. If a subfolder
+ * has no rights it has to be shown anyhow, but marked as
+ * inaccessible.
+ */
+class InaccessibleFolder extends Folder {
+
+       /**
+        * Throws an Exception,
+        * used to prevent duplicate code in al the methods
+        *
+        * @throws Exception\InsufficientFolderReadPermissionsException
+        * @return void
+        */
+       protected function throwInaccessibleException() {
+               throw new \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderReadPermissionsException(
+                       'You are trying to use a method on an Inaccssible Folder',
+                       1390290029
+               );
+       }
+
+       /**
+        * Sets a new name of the folder
+        * currently this does not trigger the "renaming process"
+        * as the name is more seen as a label
+        *
+        * @param string $name The new name
+        * @return void
+        */
+       public function setName($name) {
+               $this->throwInaccessibleException();
+       }
+
+
+       /**
+        * Returns a publicly accessible URL for this folder
+        *
+        * WARNING: Access to the folder may be restricted by further means, e.g. some
+        * web-based authentication. You have to take care of this yourself.
+        *
+        * @param boolean $relativeToCurrentScript Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
+        * @return string
+        */
+       public function getPublicUrl($relativeToCurrentScript = FALSE) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Returns a list of files in this folder, optionally filtered. There are several filter modes available, see the
+        * FILTER_MODE_* constants for more information.
+        *
+        * For performance reasons the returned items can also be limited to a given range
+        *
+        * @param integer $start The item to start at
+        * @param integer $numberOfItems The number of items to return
+        * @param integer $filterMode The filter mode to use for the file list.
+        * @param boolean $recursive
+        * @return \TYPO3\CMS\Core\Resource\File[]
+        */
+       public function getFiles($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive = FALSE) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Returns amount of all files within this folder, optionally filtered by
+        * the given pattern
+        *
+        * @param array $filterMethods
+        * @param boolean $recursive
+        *
+        * @return integer
+        */
+       public function getFileCount(array $filterMethods = array(), $recursive = FALSE) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Returns the object for a subfolder of the current folder, if it exists.
+        *
+        * @param string $name Name of the subfolder
+        *
+        * @throws \InvalidArgumentException
+        * @return Folder
+        */
+       public function getSubfolder($name) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Returns a list of subfolders
+        *
+        * @param integer $start The item to start at
+        * @param integer $numberOfItems The number of items to return
+        * @param integer $filterMode The filter mode to use for the file list.
+        * @return Folder[]
+        */
+       public function getSubfolders($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Adds a file from the local server disk. If the file already exists and
+        * overwriting is disabled,
+        *
+        * @param string $localFilePath
+        * @param string $fileName
+        * @param string $conflictMode possible value are 'cancel', 'replace'
+        * @return File The file object
+        */
+       public function addFile($localFilePath, $fileName = NULL, $conflictMode = 'cancel') {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Adds an uploaded file into the Storage.
+        *
+        * @param array $uploadedFileData contains information about the uploaded file given by $_FILES['file1']
+        * @param string $conflictMode possible value are 'cancel', 'replace'
+        * @return File The file object
+        */
+       public function addUploadedFile(array $uploadedFileData, $conflictMode = 'cancel') {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Renames this folder.
+        *
+        * @param string $newName
+        * @return Folder
+        */
+       public function rename($newName) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Deletes this folder from its storage. This also means that this object becomes useless.
+        *
+        * @param boolean $deleteRecursively
+        * @return boolean TRUE if deletion succeeded
+        */
+       public function delete($deleteRecursively = TRUE) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Creates a new blank file
+        *
+        * @param string $fileName
+        * @return File The new file object
+        */
+       public function createFile($fileName) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Creates a new folder
+        *
+        * @param string $folderName
+        * @return Folder The new folder object
+        */
+       public function createFolder($folderName) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Copies folder to a target folder
+        *
+        * @param Folder $targetFolder Target folder to copy to.
+        * @param string $targetFolderName an optional destination fileName
+        * @param string $conflictMode "overrideExistingFile", "renameNewFile" or "cancel
+        * @return Folder New (copied) folder object.
+        */
+       public function copyTo(Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Moves folder to a target folder
+        *
+        * @param Folder $targetFolder Target folder to move to.
+        * @param string $targetFolderName an optional destination fileName
+        * @param string $conflictMode "overrideExistingFile", "renameNewFile" or "cancel
+        * @return Folder New (copied) folder object.
+        */
+       public function moveTo(Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Checks if a file exists in this folder
+        *
+        * @param string $name
+        * @return boolean
+        */
+       public function hasFile($name) {
+               $this->throwInaccessibleException();
+       }
+
+       /**
+        * Checks if a folder exists in this folder.
+        *
+        * @param string $name
+        * @return boolean
+        */
+       public function hasFolder($name) {
+               $this->throwInaccessibleException();
+       }
+
+
+       /**
+        * Updates the properties of this folder, e.g. after re-indexing or moving it.
+        *
+        * NOTE: This method should not be called from outside the File Abstraction Layer (FAL)!
+        *
+        * @param array $properties
+        * @return void
+        * @internal
+        */
+       public function updateProperties(array $properties) {
+               $this->throwInaccessibleException();
+       }
+
+
+       /**
+        * Sets the filters to use when listing files. These are only used if the filter mode is one of
+        * FILTER_MODE_USE_OWN_FILTERS and FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS
+        *
+        * @param array $filters
+        */
+       public function setFileAndFolderNameFilters(array $filters) {
+               $this->throwInaccessibleException();
+       }
+
+
+
+
+}
index fafa005..7eafa12 100644 (file)
@@ -1921,7 +1921,7 @@ class ResourceStorage {
                }
                $folders = array();
                foreach ($folderIdentifiers as $folderIdentifier) {
-                       $folders[$folderIdentifier] = $this->getFolder($folderIdentifier);
+                       $folders[$folderIdentifier] = $this->getFolder($folderIdentifier, TRUE);
                }
                return $folders;
        }
@@ -2019,14 +2019,32 @@ class ResourceStorage {
 
        /**
         * @param string $identifier
+        * @param boolean $returnInaccessibleFolderObject
         *
         * @return Folder
         */
-       public function getFolder($identifier) {
+       public function getFolder($identifier, $returnInaccessibleFolderObject = FALSE) {
                $data = $this->driver->getFolderInfoByIdentifier($identifier);
                $folder = ResourceFactory::getInstance()->createFolderObject($this, $data['identifier'], $data['name']);
-               $this->assureFolderReadPermission($folder);
 
+               try {
+                       $this->assureFolderReadPermission($folder);
+               } catch (Exception\InsufficientFolderAccessPermissionsException $e) {
+                       $folder = NULL;
+                       if ($returnInaccessibleFolderObject) {
+                               // if parent folder is readable return innaccessible folder object
+                               $parentPermissions = $this->driver->getPermissions($this->driver->getParentFolderIdentifierOfIdentifier($identifier));
+                               if ($parentPermissions['r']) {
+                                       $folder = GeneralUtility::makeInstance(
+                                               'TYPO3\\CMS\\Core\\Resource\\InaccessibleFolder', $this, $data['identifier'], $data['name']
+                                       );
+                               }
+                       }
+
+                       if ($folder === NULL) {
+                               throw $e;
+                       }
+               }
                return $folder;
        }
 
index 0ef2a27..47285f3 100644 (file)
@@ -338,7 +338,7 @@ class FileList extends \TYPO3\CMS\Backend\RecordList\AbstractRecordList {
                        $this->fieldArray = explode(',', $rowlist);
                        $folderObjects = array();
                        foreach ($folders as $folder) {
-                               $folderObjects[] = $storage->getFolder($folder);
+                               $folderObjects[] = $storage->getFolder($folder, TRUE);
                        }
 
                        $folderObjects = \TYPO3\CMS\Core\Resource\Utility\ListUtility::resolveSpecialFolderNames($folderObjects);
@@ -463,48 +463,63 @@ class FileList extends \TYPO3\CMS\Backend\RecordList\AbstractRecordList {
                        list($flag, $code) = $this->fwd_rwd_nav();
                        $out .= $code;
                        if ($flag) {
+                               $isLocked = $folderObject instanceof \TYPO3\CMS\Core\Resource\InaccessibleFolder;
+                               $isWritable = $folderObject->checkActionPermission('write');
+
                                // Initialization
                                $this->counter++;
                                list($_, $icon, $path) = $this->dirData($folderObject);
                                // The icon with link
-                               $theIcon = IconUtility::getSpriteIcon($icon, array('title' => $folderName));
-                               if ($this->clickMenus) {
-                                       $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($theIcon, $folderObject->getCombinedIdentifier());
+
+                               if (!$isLocked) {
+                                       $theIcon = IconUtility::getSpriteIcon($icon, array('title' => $folderName));
+                                       if (!$this->clickMenus) {
+                                               $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($theIcon, $folderObject->getCombinedIdentifier());
+                                       }
+                               } else {
+                                       $theIcon = IconUtility::getSpriteIcon($icon, array('title' => $folderName), array('status-overlay-locked' => array()));
                                }
                                // Preparing and getting the data-array
                                $theData = array();
-                               foreach ($this->fieldArray as $field) {
-                                       switch ($field) {
-                                               case 'size':
-                                                       $numFiles = $folderObject->getFileCount();
-                                                       $theData[$field] = $numFiles . ' ' . $GLOBALS['LANG']->getLL(($numFiles === 1 ? 'file' : 'files'), TRUE);
-                                                       break;
-                                               case 'rw':
-                                                       $theData[$field] = (!$folderObject->checkActionPermission('read') ? ' ' : '<span class="typo3-red"><strong>' . $GLOBALS['LANG']->getLL('read', TRUE) . '</strong></span>') . (!$folderObject->checkActionPermission('write') ? '' : '<span class="typo3-red"><strong>' . $GLOBALS['LANG']->getLL('write', TRUE) . '</strong></span>');
-                                                       break;
-                                               case 'fileext':
-                                                       $theData[$field] = $GLOBALS['LANG']->getLL('folder', TRUE);
-                                                       break;
-                                               case 'tstamp':
-                                                       // @todo: FAL: how to get the mtime info -- $theData[$field] = \TYPO3\CMS\Backend\Utility\BackendUtility::date($theFile['tstamp']);
-                                                       $theData[$field] = '-';
-                                                       break;
-                                               case 'file':
-                                                       $theData[$field] = $this->linkWrapDir($displayName, $folderObject);
-                                                       break;
-                                               case '_CLIPBOARD_':
-                                                       $temp = '';
-                                                       if ($this->bigControlPanel) {
-                                                               $temp .= $this->makeEdit($folderObject);
-                                                       }
-                                                       $temp .= $this->makeClip($folderObject);
-                                                       $theData[$field] = $temp;
-                                                       break;
-                                               case '_REF_':
-                                                       $theData[$field] = $this->makeRef($folderObject);
-                                                       break;
-                                               default:
-                                                       $theData[$field] = GeneralUtility::fixed_lgd_cs($theFile[$field], $this->fixedL);
+                               if ($isLocked) {
+                                       foreach ($this->fieldArray as $field) {
+                                               $theData[$field] = '';
+                                       }
+                                       $theData['file'] = $displayName;
+                               } else {
+                                       foreach ($this->fieldArray as $field) {
+                                               switch ($field) {
+                                                       case 'size':
+                                                               $numFiles = $folderObject->getFileCount();
+                                                               $theData[$field] = $numFiles . ' ' . $GLOBALS['LANG']->getLL(($numFiles === 1 ? 'file' : 'files'), TRUE);
+                                                               break;
+                                                       case 'rw':
+                                                               $theData[$field] = '<span class="typo3-red"><strong>' . $GLOBALS['LANG']->getLL('read', TRUE) . '</strong></span>' . (!$isWritable ? '' : '<span class="typo3-red"><strong>' . $GLOBALS['LANG']->getLL('write', TRUE) . '</strong></span>');
+                                                               break;
+                                                       case 'fileext':
+                                                               $theData[$field] = $GLOBALS['LANG']->getLL('folder', TRUE);
+                                                               break;
+                                                       case 'tstamp':
+                                                               // @todo: FAL: how to get the mtime info -- $theData[$field] = \TYPO3\CMS\Backend\Utility\BackendUtility::date($theFile['tstamp']);
+                                                               $theData[$field] = '-';
+                                                               break;
+                                                       case 'file':
+                                                               $theData[$field] = $this->linkWrapDir($displayName, $folderObject);
+                                                               break;
+                                                       case '_CLIPBOARD_':
+                                                               $temp = '';
+                                                               if ($this->bigControlPanel) {
+                                                                       $temp .= $this->makeEdit($folderObject);
+                                                               }
+                                                               $temp .= $this->makeClip($folderObject);
+                                                               $theData[$field] = $temp;
+                                                               break;
+                                                       case '_REF_':
+                                                               $theData[$field] = $this->makeRef($folderObject);
+                                                               break;
+                                                       default:
+                                                               $theData[$field] = GeneralUtility::fixed_lgd_cs($theFile[$field], $this->fixedL);
+                                               }
                                        }
                                }
                                $out .= $this->addelement(1, $theIcon, $theData, ' class="file_list_normal"');
@@ -584,10 +599,6 @@ class FileList extends \TYPO3\CMS\Backend\RecordList\AbstractRecordList {
                        $icon = 'apps-filetree-folder-recycler';
                        $title = '<strong>' . $GLOBALS['LANG']->getLL('recycler', TRUE) . '</strong>';
                }
-               // Mark the icon as read-only icon if the folder is not writable
-               if ($folderObject->checkActionPermission('write') === FALSE) {
-                       $icon = 'apps-filetree-folder-locked';
-               }
                return array($title, $icon, $folderObject->getIdentifier());
        }
 
index 07229d0..b6f0cad 100644 (file)
@@ -1693,7 +1693,14 @@ class ElementBrowser {
                                $c++;
                                if ($renderFolders) {
                                        $fileIdentifier = $fileOrFolderObject->getCombinedIdentifier();
-                                       $icon = IconUtility::getSpriteIconForFile('folder');
+                                       $overlays = array();
+                                       if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\InaccessibleFolder) {
+                                               $overlays = array('status-overlay-locked' => array());
+                                       }
+                                       $icon = IconUtility::getSpriteIcon(
+                                               IconUtility::mapFileExtensionToSpriteIconName('folder'),
+                                               array('title' => $fileOrFolderObject->getName()),
+                                               $overlays);
                                        $itemUid = 'file:' . $fileIdentifier;
                                } else {
                                        $fileIdentifier = $fileOrFolderObject->getUid();
@@ -1714,12 +1721,17 @@ class ElementBrowser {
                                        $arrCol = '';
                                }
                                // Put it all together for the file element:
-                               $out .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'],
-                                               ('gfx/ol/join' . ($c == $totalItems ? 'bottom' : '') . '.gif'),
-                                               'width="18" height="16"'
-                                       ) . ' alt="" />' . $arrCol . '<a href="#" onclick="return link_folder(\'' . $itemUid . '\');">'
-                                       . $icon . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen))
-                                       . '</a><br />';
+                               $out .=
+                                       '<img' .
+                                               IconUtility::skinImg(
+                                                       $GLOBALS['BACK_PATH'],
+                                                       ('gfx/ol/join' . ($c == $totalItems ? 'bottom' : '') . '.gif'),
+                                                       'width="18" height="16"'
+                                               ) . ' alt="" />' . $arrCol .
+                                       '<a href="#" onclick="return link_folder(\'' . $itemUid . '\');">' .
+                                               $icon .
+                                               htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) .
+                                       '</a><br />';
                        }
                }
                return $out;