Beispiel #1
0
        public FileItem ResolveFileResourcePath2(string submittedFilePath, FileSystemTask context)
        {
            if (String.IsNullOrEmpty(submittedFilePath))
            {
                throw new InvalidResourcePathException("An empty or null string is not a valid file path");
            }

            //make sure we operate on absolute paths
            var absolutePath = PathUtil.GetAbsolutePath(submittedFilePath, RootDirectory);

            if (IsRootPath(absolutePath))
            {
                throw new InvalidResourcePathException("Invalid path submitted: " + submittedFilePath);
            }

            var             localFile   = new FileInfo(absolutePath);
            VirtualFileInfo virtualFile = localFile.CreateFileResourceInfo();

            var item = new FileItem(localFile, virtualFile);

            //convert to relative paths if required (also prevents qualified paths in validation exceptions)
            if (UseRelativePaths)
            {
                item.MakePathsRelativeTo(RootDirectory);
            }

            ValidateFileRequestAccess(item, submittedFilePath, context);
            return(item);
        }
Beispiel #2
0
        /// <summary>
        /// Checks whether a given path (whether null, relative, or absolute)
        /// will be resolved as the root path.
        /// </summary>
        /// <param name="path">The path to be inspected.</param>
        /// <returns>True if the folder path resolves to the system root.</returns>
        private bool IsRootPath(string path)
        {
            if (RootDirectory == null)
            {
                return(String.IsNullOrEmpty(path));
            }

            path = PathUtil.GetAbsolutePath(path, RootDirectory);
            return(String.Equals(path, RootDirectory.FullName, StringComparison.InvariantCultureIgnoreCase));
        }
Beispiel #3
0
        /// <summary>
        /// Creates or updates a given file resource in the file system.
        /// </summary>
        /// <param name="filePath">The qualified path of the file to be created.</param>
        /// <param name="input">A stream that provides the file's contents.</param>
        /// <param name="overwrite">Whether an existing file should be overwritten
        /// or not. If this parameter is false and the file already exists, a
        /// <see cref="ResourceOverwriteException"/> is thrown.</param>
        /// <exception cref="ResourceAccessException">In case of invalid or prohibited
        /// resource access.</exception>
        /// <exception cref="ResourceOverwriteException">If a file already exists at the
        /// specified location, and the <paramref name="overwrite"/> flag was not set.</exception>
        /// <exception cref="ArgumentNullException">If any of the parameters is a null reference.</exception>
        public override VirtualFileInfo WriteFile(string filePath, Stream input, bool overwrite)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException("filePath");
            }
            string   absolutePath = PathUtil.GetAbsolutePath(filePath, RootDirectory);
            FileInfo fi           = new FileInfo(absolutePath);

            return(WriteFile(fi.DirectoryName, fi.Name, input, overwrite));
        }
        protected VirtualFileInfo GetFileInfoInternal(string virtualFilePath, bool mustExist, out string absolutePath)
        {
            try
            {
                if (String.IsNullOrEmpty(virtualFilePath))
                {
                    VfsLog.Debug("File request without file path received.");
                    throw new ResourceAccessException("An empty or null string is not a valid file path");
                }

                //make sure we operate on absolute paths
                absolutePath = PathUtil.GetAbsolutePath(virtualFilePath, RootDirectory);

                if (IsRootPath(absolutePath))
                {
                    VfsLog.Debug("Blocked file request with path '{0}' (resolves to root directory).", virtualFilePath);
                    throw new ResourceAccessException("Invalid path submitted: " + virtualFilePath);
                }

                var             fi       = new FileInfo(absolutePath);
                VirtualFileInfo fileInfo = fi.CreateFileResourceInfo();

                //convert to relative paths if required (also prevents qualified paths in validation exceptions)
                if (UseRelativePaths)
                {
                    fileInfo.MakePathsRelativeTo(RootDirectory);
                }

                //make sure the user is allowed to access the resource
                ValidateResourceAccess(fileInfo);

                //verify file exists on FS
                if (mustExist)
                {
                    fileInfo.VerifyFileExists(RootDirectory);
                }

                return(fileInfo);
            }
            catch (VfsException)
            {
                //just bubble internal exceptions
                throw;
            }
            catch (Exception e)
            {
                VfsLog.Debug(e, "Could not create file based on path '{0}' with root '{1}'", virtualFilePath,
                             RootDirectory);
                throw new ResourceAccessException("Invalid path submitted: " + virtualFilePath);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Checks whether the <see cref="VirtualResourceInfo.FullName"/>
        /// matches an existing directory on the local file system. If that's
        /// not the case, a <see cref="VirtualResourceNotFoundException"/> is
        /// thrown.
        /// </summary>
        /// <param name="folder">The folder to check.</param>
        /// <param name="rootDirectory">The used root directory, if any, which is used
        /// to resolve relative paths.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="folder"/>
        /// is a null reference.</exception>
        /// <exception cref="VirtualResourceNotFoundException">If the submitted
        /// folder's <see cref="VirtualResourceInfo.FullName"/> does not link to
        /// an existing directory.</exception>
        internal static void VerifyDirectoryExists(this VirtualFolderInfo folder, DirectoryInfo rootDirectory)
        {
            if (folder == null)
            {
                throw new ArgumentNullException("folder");
            }

            string path = PathUtil.GetAbsolutePath(folder.FullName, rootDirectory);

            if (String.IsNullOrEmpty(path) || !Directory.Exists(path))
            {
                string msg = String.Format("Directory '{0}' not found on local file system.", folder.FullName);
                throw new VirtualResourceNotFoundException(msg)
                      {
                          Resource = folder
                      };
            }
        }
Beispiel #6
0
        /// <summary>
        /// Checks whether the <see cref="VirtualResourceInfo.FullName"/>
        /// matches an existing file on the local file system. If that's
        /// not the case, a <see cref="VirtualResourceNotFoundException"/> is
        /// thrown.
        /// </summary>
        /// <param name="file">The file to check.</param>
        /// <param name="rootDirectory">The used root directory, if any, which is used
        /// to resolve relative paths.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="file"/>
        /// is a null reference.</exception>
        /// <exception cref="VirtualResourceNotFoundException">If the submitted
        /// file's <see cref="VirtualResourceInfo.FullName"/> does not link to
        /// an existing file.</exception>
        internal static void VerifyFileExists(this VirtualFileInfo file, DirectoryInfo rootDirectory)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            string path = PathUtil.GetAbsolutePath(file.FullName, rootDirectory);

            if (String.IsNullOrEmpty(path) || !File.Exists(path))
            {
                string msg = String.Format("File not found on local file system at '{0}'", file.FullName);
                throw new VirtualResourceNotFoundException(msg)
                      {
                          Resource = file
                      };
            }
        }
        protected VirtualFolderInfo GetFolderInfoInternal(string virtualFolderPath, bool mustExist, out string absolutePath)
        {
            try
            {
                //make sure we operate on absolute paths
                absolutePath = PathUtil.GetAbsolutePath(virtualFolderPath ?? "", RootDirectory);

                if (IsRootPath(absolutePath))
                {
                    return(GetFileSystemRoot());
                }

                var di = new DirectoryInfo(absolutePath);
                VirtualFolderInfo folderInfo = di.CreateFolderResourceInfo();

                //convert to relative paths if required (also prevents qualified paths in validation exceptions)
                if (UseRelativePaths)
                {
                    folderInfo.MakePathsRelativeTo(RootDirectory);
                }

                //make sure the user is allowed to access the resource
                ValidateResourceAccess(folderInfo);

                //verify folder exists on FS
                if (mustExist)
                {
                    folderInfo.VerifyDirectoryExists(RootDirectory);
                }

                return(folderInfo);
            }
            catch (VfsException)
            {
                //just bubble internal exceptions
                throw;
            }
            catch (Exception e)
            {
                VfsLog.Debug(e, "Could not create directory based on path '{0}' with root '{1}'", virtualFolderPath,
                             RootDirectory);
                throw new ResourceAccessException("Invalid path submitted: " + virtualFolderPath);
            }
        }
        /// <summary>
        /// Resolves the parent folder for a virtual resource.
        /// </summary>
        /// <param name="child">The child file or folder.</param>
        /// <returns>The parent folder info.</returns>
        private VirtualFolderInfo GetParentInternal(VirtualResourceInfo child)
        {
            if (child == null)
            {
                throw new ArgumentNullException("child");
            }

            string path = PathUtil.GetAbsolutePath(child.FullName, RootDirectory);

            if (IsRootPath(path))
            {
                //only log the request for the root's parent - do not include that
                //info in an exception in case we're hiding path information
                string msg = "Error while requesting parent of resource {0} - the folder itself already is the root.";
                VfsLog.Error(msg, child.FullName);

                //create exception with a relative path, if required
                string exceptionPath = UseRelativePaths ? PathUtil.RelativeRootPrefix : child.FullName;
                msg = String.Format(msg, exceptionPath);
                throw new ResourceAccessException(msg);
            }

            //make sure the processed directory exists
            VirtualFolderInfo folder = child as VirtualFolderInfo;

            if (folder != null)
            {
                folder.VerifyDirectoryExists(RootDirectory);
            }
            else
            {
                VirtualFileInfo file = (VirtualFileInfo)child;
                file.VerifyFileExists(RootDirectory);
            }

            //get the path of the parent (returned value may be null!)
            string parentPath = Path.GetDirectoryName(path);

            //get folder info
            return(GetFolderInfo(parentPath));
        }
Beispiel #9
0
        public FolderItem ResolveFolderResourcePath2(string submittedFolderPath, FileSystemTask context)
        {
            //make sure we operate on absolute paths
            string absolutePath = PathUtil.GetAbsolutePath(submittedFolderPath ?? "", RootDirectory);

            if (IsRootPath(absolutePath))
            {
                return(GetFileSystemRootImplementation() as FolderItem);
            }

            var di = new DirectoryInfo(absolutePath);
            VirtualFolderInfo folderInfo = di.CreateFolderResourceInfo();

            var item = new FolderItem(di, folderInfo);

            //convert to relative paths if required (also prevents qualified paths in validation exceptions)
            if (UseRelativePaths)
            {
                item.MakePathsRelativeTo(RootDirectory);
            }

            ValidateFolderRequestAccess(item, submittedFolderPath, context);
            return(item);
        }
Beispiel #10
0
        /// <summary>
        /// Checks whether a given folder exists on the file system. This method is
        /// being invoked by <see cref="FileSystemProviderBase2{TFile,TFolder}.IsFolderAvailable"/>.
        /// </summary>
        /// <param name="virtualFolderPath">The received folder path to be processed.</param>
        /// <returns>True if the folder exists, otherwise false.</returns>
        protected override bool IsFolderAvailableInternal(string virtualFolderPath)
        {
            string path = PathUtil.GetAbsolutePath(virtualFolderPath ?? "", RootDirectory);

            return(Directory.Exists(path));
        }
Beispiel #11
0
        /// <summary>
        /// Creates a new folder in the file system.
        /// </summary>
        /// <param name="parentFolderPath">The qualified name of the designated parent folder, which
        /// needs to exists, and provide write access.</param>
        /// <param name="folderName">The name of the folder to be created.</param>
        /// <returns>A <see cref="VirtualFileInfo"/> instance which represents
        /// the created folder.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="parentFolderPath"/>
        /// is a null reference.</exception>
        /// <exception cref="ArgumentNullException">If <paramref name="folderName"/>
        /// is a null reference.</exception>
        /// <exception cref="ResourceAccessException">In case of invalid or prohibited
        /// resource access.</exception>
        /// <exception cref="VirtualResourceNotFoundException">If no folder exists that
        /// matches the submitted <paramref name="parentFolderPath"/>.</exception>
        /// <exception cref="ResourceOverwriteException">If the folder already exists on the file
        /// system.</exception>
        public override VirtualFolderInfo CreateFolder(string parentFolderPath, string folderName)
        {
            if (parentFolderPath == null)
            {
                throw new ArgumentNullException("parentFolderPath");
            }
            if (folderName == null)
            {
                throw new ArgumentNullException("folderName");
            }

            string absoluteParentPath;
            var    parent = GetFolderInfoInternal(parentFolderPath, true, out absoluteParentPath);

            if (RootDirectory == null && parent.IsRootFolder)
            {
                VfsLog.Debug("Blocked attempt to create a folder '{0}' at system root.", folderName);
                throw new ResourceAccessException("Folders cannot be created at the system root.");
            }

            //create path of the child
            string childPath = PathUtil.GetAbsolutePath(folderName, new DirectoryInfo(absoluteParentPath));

            //make sure the folder name is not a relative path that points outside the scope
            if (RootDirectory != null && !RootDirectory.IsParentOf(childPath))
            {
                string msg = "Blocked attempt to create folder outside of root through with parent '{0}' and folder name '{1}'";
                VfsLog.Warn(msg, absoluteParentPath, folderName);

                throw new ResourceAccessException("Invalid file path: " + folderName);
            }

            var directory = new DirectoryInfo(childPath);

            if (directory.Exists)
            {
                //log and create exception if the directory already exists
                VfsLog.Debug("Blocked attempt to recreate directory '{0}'", directory.FullName);
                string relativePath = PathUtil.GetRelativePath(childPath, RootDirectory);
                string msg          = String.Format("The folder '{0}' already exists.", relativePath);
                throw new ResourceOverwriteException(msg);
            }

            try
            {
                //create directory
                directory.Create();
            }
            catch (Exception e)
            {
                const string msg = "Exception occurred when trying to create new folder '{0}' for parent '{1}'";
                VfsLog.Debug(e, msg, folderName, parent.FullName);

                throw new ResourceAccessException("Could not create folder", e);
            }

            var folder = directory.CreateFolderResourceInfo();

            //adjust and return
            if (UseRelativePaths)
            {
                folder.MakePathsRelativeTo(RootDirectory);
            }
            return(folder);
        }
Beispiel #12
0
        /// <summary>
        /// Creates or updates a given file resource in the file system.
        /// </summary>
        /// <param name="parentFolderPath">The qualified path of the parent folder that will
        /// contain the file.</param>
        /// <param name="fileName">The name of the file to be created.</param>
        /// <param name="input">A stream that provides the file's contents.</param>
        /// <param name="overwrite">Whether an existing file should be overwritten
        /// or not. If this parameter is false and the file already exists, a
        /// <see cref="ResourceOverwriteException"/> is thrown.</param>
        /// <exception cref="VirtualResourceNotFoundException">If the parent folder
        /// does not exist.</exception>
        /// <exception cref="ResourceAccessException">In case of invalid or prohibited
        /// resource access.</exception>
        /// <exception cref="ResourceOverwriteException">If a file already exists at the
        /// specified location, and the <paramref name="overwrite"/> flag was not set.</exception>
        /// <exception cref="ArgumentNullException">If any of the parameters is a null reference.</exception>
        public override VirtualFileInfo WriteFile(string parentFolderPath, string fileName, Stream input, bool overwrite)
        {
            if (parentFolderPath == null)
            {
                throw new ArgumentNullException("parentFolderPath");
            }
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }


            //get the parent and make sure it exists
            string absoluteParentPath;
            var    parent = GetFolderInfoInternal(parentFolderPath, true, out absoluteParentPath);

            if (RootDirectory == null && parent.IsRootFolder)
            {
                VfsLog.Debug("Blocked attempt to create a file '{0}' at system root (which is the machine itself - no root directory was set).", fileName);
                throw new ResourceAccessException("Files cannot be created at the system root.");
            }

            //combine to file path and get virtual file (also makes sure we don't get out of scope)
            string absoluteFilePath = PathUtil.GetAbsolutePath(fileName, new DirectoryInfo(absoluteParentPath));

            FileInfo fi = new FileInfo(absoluteFilePath);

            if (fi.Exists && !overwrite)
            {
                VfsLog.Debug("Blocked attempt to overwrite file '{0}'", fi.FullName);
                string msg = String.Format("The file [{0}] already exists.", fileName);
                throw new ResourceOverwriteException(msg);
            }

            try
            {
                using (Stream writeStream = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    input.WriteTo(writeStream);
                }
            }
            catch (Exception e)
            {
                //log exception with full path
                string msg = "Could not write write submitted content to file '{0}'.";
                VfsLog.Error(e, msg, fi.FullName);
                //generate exception with relative path
                msg = String.Format(msg, PathUtil.GetRelativePath(fi.FullName, RootDirectory));
                throw new ResourceAccessException(msg, e);
            }

            //return update file info
            var file = fi.CreateFileResourceInfo();

            //adjust and return
            if (UseRelativePaths)
            {
                file.MakePathsRelativeTo(RootDirectory);
            }
            return(file);
        }
        /// <summary>
        /// Validates whether a  <see cref="LocalFileSystemProvider"/> was configured
        /// with access restricted to a given <see cref="LocalFileSystemProvider.RootDirectory"/>,
        /// and makes sure that the requested <paramref name="resource"/> is indeed contained
        /// within that folder.
        /// </summary>
        /// <param name="resource">The requested resource.</param>
        /// <exception cref="ResourceAccessException">If the requested resource is not
        /// a descendant of a configured <see cref="LocalFileSystemProvider.RootDirectory"/>.</exception>
        /// <exception cref="ArgumentNullException">If <paramref name="resource"/>
        /// is a null reference.</exception>
        private void ValidateResourceAccess(VirtualResourceInfo resource)
        {
            if (resource == null)
            {
                throw new ArgumentNullException("resource");
            }

            //if there isn't a restricted custom root, every file resource can be accessed
            //(if the path is invalid, this will fail later, depending on the action)
            if (RootDirectory == null)
            {
                return;
            }

            try
            {
                string path = PathUtil.GetAbsolutePath(resource.FullName, RootDirectory);

                //if the root path was submitted, we're within the scope, too
                if (IsRootPath(path))
                {
                    return;
                }

                //if we have a custom root, make sure the resource is indeed a descendant of the root
                if (RootDirectory.IsParentOf(path))
                {
                    return;
                }
            }
            catch (ResourceAccessException e)
            {
                //just bubble a resource access exception
                if (e.Resource == null)
                {
                    e.Resource = resource;
                }
                throw;
            }
            catch (Exception e)
            {
                //exceptions can happen in case of invalid file paths

                //log detailed info
                string error = "Resource request for '{0}' caused exception when validating against root directory '{1}'.";
                error = String.Format(error, resource.FullName, RootDirectory.FullName);
                VfsLog.Debug(e, error);

                //do not expose too much path information (e.g. absolute paths if disabled)
                error = String.Format("Invalid resource path: '{0}'.", resource.FullName);
                throw new ResourceAccessException(error)
                      {
                          Resource = resource
                      };
            }

            //if none of the above is true, the request is invalid

            //log detailed info
            string msg = "Resource request for '{0}' was blocked. The resource is outside the root directory '{1}'.";

            msg = String.Format(msg, resource.FullName, RootDirectory.FullName);
            VfsLog.Debug(msg);

            //do not expose too much path information (e.g. absolute paths if disabled)
            msg = String.Format("Invalid resource path: '{0}'.", resource.FullName);
            throw new ResourceAccessException(msg)
                  {
                      Resource = resource
                  };
        }