Example #1
0
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]    // the writer is disposed for all code paths
        internal static void CopyStream(Stream fromStream, ImpersonationBehavior readImpersonationBehavior, Stream toStream, ImpersonationBehavior writeImpersonationBehavior)
        {
            // An addition revert during write operations is required if the setting for reading and writing
            // is not the same
            bool requiresWriteRevert = (readImpersonationBehavior != writeImpersonationBehavior);

            using (ImpersonateIdentity readId = new ImpersonateIdentity(readImpersonationBehavior))
            {
                byte[] bytesIn = new byte[65536];
                int    bytesRead;
                while ((bytesRead = fromStream.Read(bytesIn, 0, bytesIn.Length)) != 0)
                {
                    // If we have to impersonate to write, then do it. Otherwise skip it.
                    if (requiresWriteRevert)
                    {
                        using (ImpersonateIdentity id = new ImpersonateIdentity(writeImpersonationBehavior))
                        {
                            toStream.Write(bytesIn, 0, bytesRead);
                        }
                    }
                    else
                    {
                        toStream.Write(bytesIn, 0, bytesRead);
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Writes the requested file from the package directly to the response.
        /// This method clears the response before sending the file and provides an option to skip 
        /// package validation.
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="response"></param>
        /// <param name="skipValidation"></param>
        internal void TransmitFile(string filePath, HttpResponse response, bool skipValidation)
        {
            Utilities.ValidateParameterNonNull("filePath", filePath);
            Utilities.ValidateParameterNotEmpty("filePath", filePath);
            Utilities.ValidateParameterNonNull("response", response);

            if (!skipValidation)
            {
                using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
                {
                    // If user does not have access, a UnauthorizedAccess Exception is thrown
                    Directory.GetFiles(m_packageBasePath);
                    // Check if package has valid e-learning content
                    if (!ManifestExists())
                        throw new InvalidPackageException(Resources.ImsManifestXmlMissing);
                }
            }

            string absoluteFilePath = SafePathCombine(m_packageBasePath, filePath);
            response.Clear();
            response.Buffer = false;
            response.BufferOutput = false;
            using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
            {
                response.TransmitFile(absoluteFilePath);
            }
        }
Example #3
0
 /// <summary>
 /// Gets the collection of file paths in the package, with the option to skip package validation.
 /// </summary>
 internal ReadOnlyCollection<string> GetFilePaths(bool skipValidation)
 {
     ReadOnlyCollection<string> filePaths = null;
     using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
     {
         // If the user does not have access, the UnauthorizedAccess Exception is thrown
         Directory.GetFiles(m_packageBasePath);
         // If validation is requested, check if package has valid e-learning content
         if ((!skipValidation) && (!ManifestExists()))
             throw new InvalidPackageException(Resources.ImsManifestXmlMissing);
         filePaths = GetFilePaths(new DirectoryInfo(m_packageBasePath));
     }
     return filePaths;
 }
Example #4
0
        /// <summary>
        /// Gets a value indicating whether the file exists in the package, providing the option to 
        /// validate the package.
        /// </summary>
        internal bool FileExists(string filePath, bool skipValidation)
        {
            bool fileExists = false;
            try
            {
                if (!skipValidation)
                {
                    // If the current user has access problems with the package, the package is not Validated
                    using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
                    {
                        // Check if user has access to the files
                        Directory.GetFiles(m_packageBasePath);
                        // Check if package has valid e-learning content
                        if (!ManifestExists())
                            throw new InvalidPackageException(Resources.ImsManifestXmlMissing);
                    }
                }

                // SafePathCombine throws the ArgumentException and ArgumentNullException noted above.
                // File.Exists will throw UnauthorizedAccessException if user does not have FileIOPermission.
                string path;
                using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
                {
                    path = SafePathCombine(m_packageBasePath, filePath);
                    fileExists = File.Exists(path);
                    // imsmanifest.xml is special, since it is created from index.xml.
                    if (!fileExists && IsImsManifest(filePath))
                    {
                        // one more chance for imsmanifest.xml - if it doesn't exist as "imsmanifest.xml" it
                        // can still exist as a conversion from index.xml, so return true if index.xml exists.
                        fileExists = ManifestExists();
                    }
                }
            }
            // catch exceptions that should be converted into a "false" file exists.
            catch (DirectoryNotFoundException)
            {
            }
            catch (ArgumentException)
            {
            }
            catch (NotSupportedException)
            {
            }
            catch (SecurityException)
            {
            }
            catch (IOException)
            {
            }
            catch (UnauthorizedAccessException)
            {
            }
            return fileExists;
        }
Example #5
0
 /// <summary>
 /// Shared helper function to read a file from the package location and wrap the resulting exceptions
 /// to be consistent within MLC.
 /// </summary>
 /// <param name="packagePath">The path to the root folder of the package.</param>
 /// <param name="filePath">The package-relative path of the file within the package.</param>
 /// <param name="impersonationBehavior">Indicates which identity to use when reading the file.</param>
 /// <returns>A stream containing the file.</returns>
 internal static Stream ReadFile(string packagePath, string filePath, ImpersonationBehavior impersonationBehavior)
 {
     Stream stream = null;
     try
     {
         using (ImpersonateIdentity id = new ImpersonateIdentity(impersonationBehavior))
         {
             stream = File.OpenRead(SafePathCombine(packagePath, filePath));
         }
     }
     catch (UnauthorizedAccessException)
     {
         // don't wrap the inner exception to obfuscate any system file info that might exist
         throw new UnauthorizedAccessException(String.Format(CultureInfo.InvariantCulture, Resources.UnauthorizedAccess, filePath));
     }
     catch (FileNotFoundException)
     {
         // don't wrap the inner exception to obfuscate any system file info that might exist
         throw new FileNotFoundException(Resources.PackageFileNotFound, filePath);
     }
     catch (DirectoryNotFoundException)
     {
         // don't wrap the inner exception to obfuscate any system file info that might exist
         throw new DirectoryNotFoundException(String.Format(CultureInfo.InvariantCulture, Resources.DirectoryNotFound, filePath));
     }
     return stream;
 }
Example #6
0
        /// <summary>
        /// Returns a <Typ>/System.IO.Stream</Typ> that can read the specified file, providing the option to 
        /// validate the package.
        /// </summary>
        internal Stream GetFileStream(string filePath, bool skipValidation)
        {
            // SafePathCombine throws the ArgumentException and ArgumentNullException noted above.
            // File.OpenRead throws UnauthorizedAccessException, PathTooLongException,
            // DirectoryNotFoundException, FileNotFoundException, and NotSupportedException.

            if (!skipValidation)
            {
                // If the current user has access problems with the package, the package is not Validated
                using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
                {
                    // Check if user has access to the files
                    Directory.GetFiles(m_packageBasePath);
                    // Check if package has valid e-learning content
                    if (!ManifestExists())
                        throw new InvalidPackageException(Resources.ImsManifestXmlMissing);
                }
            }

            // if filePath is imsmanifest.xml and there is an index.xml, assume this is IMS+ content
            // and return the imsmanifest.xml converted from index.xml instead of the actual imsmanifest.xml.
            if (IsImsManifest(filePath) && FileExists("index.xml"))
            {
                try
                {
                    return ConvertFromIndexXml();
                }
                catch (InvalidPackageException)
                {
                    // don't wrap the inner exception to obfuscate any system file info that might exist
                    throw new FileNotFoundException(Resources.PackageFileNotFound, filePath);
                }
            }
            else
            {
                return ReadFile(m_packageBasePath, filePath, m_impersonationBehavior);
            }
        }
Example #7
0
        /// <summary>
        /// Recursively copy from one folder to another by reading the files into memory. 
        /// </summary>
        /// <param name="fromDir">The folder to copy from.</param>
        /// <param name="fromImpersonationBehavior">The identity that has rights to read the <paramref name="fromDir"/>.</param>
        /// <param name="toDir">The folder to write to. Writing is not done in an impersonation block.</param>
        private static void RecursiveCopyStreams(DirectoryInfo fromDir, ImpersonationBehavior fromImpersonationBehavior, DirectoryInfo toDir)
        {
            FileInfo[] files;

            using (ImpersonateIdentity id = new ImpersonateIdentity(fromImpersonationBehavior))
            {
                files = fromDir.GetFiles();
            }
            foreach (FileInfo file in files)
            {
                using(Disposer disposer = new Disposer())
                {
                    FileStream fromStream;
                    using (ImpersonateIdentity id = new ImpersonateIdentity(fromImpersonationBehavior))
                    {
                         fromStream = file.OpenRead();
                         disposer.Push(fromStream);
                    }
                    string toPath = PackageReader.SafePathCombine(toDir.FullName, file.Name);
                    FileInfo toFileInfo = new FileInfo(toPath);
                    FileStream toStream = toFileInfo.OpenWrite();
                    disposer.Push(toStream);

                    Utilities.CopyStream(fromStream, fromImpersonationBehavior, toStream, ImpersonationBehavior.UseImpersonatedIdentity);
                }
            }
            foreach (DirectoryInfo sub in fromDir.GetDirectories())
            {
                DirectoryInfo newSub = Directory.CreateDirectory(Path.Combine(toDir.FullName, sub.Name));
                RecursiveCopy(sub, newSub);
            }
        }
Example #8
0
        /// <summary>
        /// Recursively copy all package files from one directory to another.
        /// </summary>
        /// <param name="from">Directory to copy from.</param>
        /// <param name="to">Directory to copy to.</param>
        /// <param name="impersonationBehavior">The identity that can read the files in the <paramref name="from"/> folder.
        /// If this identity can also write to the <paramref name="to"/> folder, the method performs faster
        /// than if it does not have write permissions.</param>
        internal static void RecursiveCopy(DirectoryInfo from, DirectoryInfo to, ImpersonationBehavior impersonationBehavior)
        {
            bool copySucceeded = false;
            try
            {
                using (ImpersonateIdentity id = new ImpersonateIdentity(impersonationBehavior))
                {
                    try
                    {
                        to.Create();
                    }
                    catch (IOException ex)
                    {
                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
                            Resources.PackageDirectoryAlreadyExists, to.FullName), ex);
                    }

                    RecursiveCopy(from, to);
                    copySucceeded = true;
                }
            }
            catch (UnauthorizedAccessException)
            {
                // This means the identity probably did not have write privileges to the 'to' folder.
                // So, try continue and try loading files into memory before writing them to the output folder.
            }

            if (!copySucceeded)
            {
                // Load files into memory before writing them to the output
                RecursiveCopyStreams(from, impersonationBehavior, to);
            }
        }
Example #9
0
        /// <summary>
        /// Explodes the m_zip file into a newly created (randomly named, in the temporary directory)
		/// destination directory if this hasn't been done already.
        /// </summary>
        /// <remarks>
        /// <c>m_state</c> affects what this method does, and can be changed by this method.
        /// <c>m_unzipPath</c> can be changed by this method.
        /// </remarks>
        /// <exception cref="ObjectDisposedException">State of the reader is "Closed".</exception>
        /// <exception cref="InvalidPackageException">There is a problem with the zip package.</exception>
        /// <returns>Package root path.</returns>
        private string ExplodeZipIfNeeded()
        {
            if (m_state == ZipPackageReaderState.Disposed)
            {
                throw new ObjectDisposedException("ZipPackageReader");
            }
            if (m_state != ZipPackageReaderState.Exploded)
            {
                // If there is an m_stream but no m_zip, we still need to stream the stream into a temp file.
                if (m_stream != null && m_zip == null)
                {
                    using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
                    {
                        m_zip = new FileInfo(Path.GetTempFileName());
                        using (FileStream fileStream = m_zip.Create())
                        {
                            // Read from the stream and write to the exploded location using the specified identity.
                            Utilities.CopyStream(m_stream, m_impersonationBehavior, fileStream, m_impersonationBehavior);
                        }
                    }
                    m_mustDeleteFile = true;
                }

                using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior))
                {
                    // Note that Path.Combine is safe here since Path.GetTempPath() and Path.GetRandomFileName()
                    // are known to be safe.
                    // Just in case Path.GetRandomFileName() returns a filename that already exists, keep trying
                    // until success.
                    bool done = false;
                    while (!done)
                    {
                        m_unzipPath = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));
                        if (m_unzipPath.Exists) continue;
                        m_unzipPath.Create();
                        done = true;
                    }
                    // explode the zip file
                    try
                    {
												throw new Exception("Compression class is not found!");
                        //Compression.Unzip(m_zip, m_unzipPath);
                        m_state = ZipPackageReaderState.Exploded;
                    }
                    catch (Exception e)
                    {
                        // on Exception, convert into InvalidPackageException.

                        // wrap this message into a descriptive message
                        string message = "";
                        message = String.Format(CultureInfo.InvariantCulture, ValidatorResources.PackageCouldNotBeOpened, message);
                        throw new InvalidPackageException(message, e);
                    }
                }
            }
            return m_unzipPath.ToString();
        }
Example #10
0
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]    // the writer is disposed for all code paths
        internal static void CopyStream(Stream fromStream, ImpersonationBehavior readImpersonationBehavior, Stream toStream, ImpersonationBehavior writeImpersonationBehavior)
        {
            using (Disposer disposer = new Disposer())
            {
                DetachableStream dsToStream = new DetachableStream(toStream);
                disposer.Push(dsToStream);

                BinaryWriter writer = new BinaryWriter(dsToStream);
                disposer.Push(writer);

                // An addition revert during write operations is required if the setting for reading and writing
                // is not the same
                bool requiresWriteRevert = (readImpersonationBehavior != writeImpersonationBehavior);

                using (ImpersonateIdentity readId = new ImpersonateIdentity(readImpersonationBehavior))
                {
                    byte[] bytesIn = new byte[65536];
                    int bytesRead;
                    while ((bytesRead = fromStream.Read(bytesIn, 0, bytesIn.Length)) != 0)
                    {
                        // If we have to impersonate to write, then do it. Otherwise skip it.
                        if (requiresWriteRevert)
                        {
                            using (ImpersonateIdentity id = new ImpersonateIdentity(writeImpersonationBehavior))
                            {
                                writer.Write(bytesIn, 0, bytesRead);
                            }
                        }
                        else
                        {
                            writer.Write(bytesIn, 0, bytesRead);
                        }
                    }
                }
                dsToStream.Detach();
            }
        }