예제 #1
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);
            }
        }
예제 #2
0
        /// <summary>
        /// Writes the file from a byte array directly to the response. The output stream
        /// extension must be set prior to calling this method.
        /// If the response is provided and the path extension is not
        /// in the list of files to use IIS compatibility mode, this is much faster than 
        /// copying the file contents to the output stream and should be used whenever possible.
        /// If there is no response object, the method reverts to copying the file between streams.
        /// </summary>
        /// <param name="fileBytes">The file to render.</param>
        internal void WriteFileToResponse(byte[] fileBytes)
        {
            using (Disposer disposer = new Disposer())
            {
                // Open a stream on the file. For some odd reason fxcop does not acknowledge the ability of disposer
                // to actually dispose fileStream, so we give it its own using block.
                using (Stream fileStream = new MemoryStream(fileBytes))
                {
                    // If the response was provided (which it will be, in most non-test cases), then 
                    // do the TransmitFile or WriteFile. Otherwise, copy the streams to the response output stream.
                    if (Response != null)
                    {
                        // IisCompatibilityMode is not considered here, because in no case do we have a file 
                        // path that can be read by TransmitFile. 
                        WriteIisCompatibilityModeToResponse(fileStream); 
                    }
                    else
                    {
                        DetachableStream outputDS = new DetachableStream(OutputStream);
                        disposer.Push(outputDS);

                        Utilities.CopyStream(fileStream, ImpersonationBehavior.UseImpersonatedIdentity, outputDS, ImpersonationBehavior.UseImpersonatedIdentity);

                        outputDS.Detach();
                    }
                }
            }
        }
예제 #3
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();
            }
        }
예제 #4
0
        /// <summary>
        /// Writes the file from the package directly to the response and set the appropriate 
        /// content type in the response. If the response is provided and the path extension is not
        /// in the list of files to use IIS compatibility mode, this is much faster than 
        /// copying the file contents to the output stream and should be used whenever possible.
        /// If there is no response object, the method reverts to copying the file between streams.
        /// </summary>
        /// <param name="relativePath">The package-relative path to the file to render.</param>
        internal void WriteFileToResponse(string relativePath)
        {
            // Set the mime type on the response
            string pathExtension = Path.GetExtension(relativePath);
            SetOutputStreamExtension(pathExtension);

            using(Disposer disposer = new Disposer())
            {
                PackageReader pkgReader = m_session.GetPackageReader();
                disposer.Push(pkgReader);

                // If the response was provided (which it will be, in most non-test cases), then 
                // do the TransmitFile or WriteFile. Otherwise, copy the streams to the response output stream.
                if (Response != null) 
                {                
                    // If we are to use Compatibility mode, then write the file
                    if (UseCompatibilityMode(pathExtension))
                    {
                        Stream packageFile = pkgReader.GetFileStream(relativePath);
                        WriteIisCompatibilityModeToResponse(packageFile);
                    }
                    else
                    {
                        pkgReader.TransmitFile(relativePath, m_context.Response);
                    }
                }
                else
                {
                    DetachableStream outputDS = new DetachableStream(OutputStream);
                    disposer.Push(outputDS);

                    Stream packageFile = pkgReader.GetFileStream(relativePath);
                    disposer.Push(packageFile);

                    Utilities.CopyStream(packageFile, ImpersonationBehavior.UseImpersonatedIdentity, outputDS, ImpersonationBehavior.UseImpersonatedIdentity);

                    outputDS.Detach();
                }
            }
        }
        /// <summary>
        /// Get the schema information for this store from the cache or from the database.
        /// </summary>
        /// <param name="connectionString">Connection string used to access the store.</param>
        /// <param name="impersonationBehavior">Identifies which <c>WindowsIdentity</c> is used to
        ///     access the database when impersonation is involved.</param>
        /// <param name="debugLog">Location to which the debug log should be written, or
        ///     null if there isn't a debug log.</param>
        /// <returns>The schema information.</returns>
        private static LearningStoreSchema GetSchemaInformationFromCache(string connectionString,
                                                                         ImpersonationBehavior impersonationBehavior, TextWriter debugLog)
        {
            // Try to find the connection in the cache
            lock (s_allSchemasLock)
            {
                LearningStoreSchema schema;
                if (s_allSchemas.TryGetValue(connectionString, out schema))
                {
                    return(schema);
                }
            }

            // Not found in the cache -- so go get it from the database

            // This try/catch block is here for security reasons. Search MSDN for
            // "WrapVulnerableFinallyClausesInOuterTry" to see details.
            try
            {
                WindowsImpersonationContext impersonationContext = null;

                try
                {
                    // Impersonate if necessary
                    if (impersonationBehavior == ImpersonationBehavior.UseOriginalIdentity)
                    {
                        // Not adding it to the disposer, since that could fail (e.g., OutOfMemoryException),
                        // which could cause a security hole.  Instead, we'll clean it up manually later.
                        impersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero);
                    }

                    using (Microsoft.LearningComponents.Disposer disposer = new Microsoft.LearningComponents.Disposer())
                    {
                        // Create a connection
                        SqlConnection connection = new SqlConnection(connectionString);
                        disposer.Push(connection);
                        connection.Open();

                        // Create a command to retrieve information from the configuration table
                        LogableSqlCommand command = new LogableSqlCommand(connection, debugLog);
                        disposer.Push(command);

                        // Execute
                        command.Execute(
                            "SELECT EngineVersion,\r\n" +
                            "    SchemaDefinition\r\n" +
                            "FROM Configuration\r\n");

                        // Read return values from the database
                        if (!command.Read())
                        {
                            throw new LearningComponentsInternalException("LSTR1500");
                        }
                        if (command.GetFieldCount() != 2)
                        {
                            throw new LearningComponentsInternalException("LSTR1510");
                        }
                        int           engineVersion = command.GetInt32(0);
                        SqlXml        schemaXml     = command.GetSqlXml(1);
                        XPathDocument schemaDoc;
                        using (XmlReader reader = schemaXml.CreateReader())
                        {
                            schemaDoc = new XPathDocument(reader);
                        }
                        LearningStoreSchema newSchema = LearningStoreSchema.CreateSchema(schemaDoc);
                        if (command.Read())
                        {
                            throw new LearningComponentsInternalException("LSTR1520");
                        }
                        if (command.NextResult())
                        {
                            throw new LearningComponentsInternalException("LSTR1530");
                        }

                        // Fail if a different engine created this
                        if (engineVersion != LearningStore.EngineVersion)
                        {
                            throw new InvalidOperationException(LearningStoreStrings.IncompatibleEngineVersion);
                        }

                        // Save it in the cache
                        lock (s_allSchemasLock)
                        {
                            LearningStoreSchema schema;
                            if (s_allSchemas.TryGetValue(connectionString, out schema))
                            {
                                return(schema);
                            }
                            s_allSchemas.Add(connectionString, newSchema);
                        }

                        return(newSchema);
                    }
                }
                finally
                {
                    if (impersonationContext != null)
                    {
                        impersonationContext.Dispose();
                    }
                }
            }
            catch
            {
                throw;
            }
        }