/// <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); } #if DOTNET40 else if (FileIsHtml(pathExtension)) { SendHtmlChangingCssHref(pkgReader.GetFileStream(relativePath)); } else if (FileIsJavascript(pathExtension)) { SendJavascriptChangingCssHref(pkgReader.GetFileStream(relativePath)); } #endif 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> /// Return a file located at the specified package-relative path. /// </summary> /// <param name="relativePath">The package-relative path to the file in the package.</param> /// <returns></returns> /// <remarks> /// <para>This method reads files from the file system. It combines the path /// information with the cachePath value to determine the file location. /// </para> /// </remarks> /// <exception cref="DirectoryNotFoundException">Thrown if <paramref name="relativePath"/> /// contains a reference to a directory that does not exist.</exception> /// <exception cref="FileNotFoundException">Thrown if <paramref name="relativePath"/> /// contains a reference to a file that does not exist.</exception> public override Stream GetFileStream(string relativePath) { if (m_isDisposed) { throw new ObjectDisposedException(GetType().Name); } // If it's the manifest, ask to get it from the store. Otherwise have the SharePointPackageReader // get it. if (IsManifest(relativePath)) { return(m_store.GetManifestFile(m_packageId)); } return(m_spPackageReader.GetFileStream(relativePath)); }
/// <summary> /// Read the files from a package and import the package information into LearningStore. Only packages /// which may be executed can be imported into LearningStore. /// See the class overview information for details. /// </summary> /// <param name="packageReader">A reader to read the files in the package to be imported.</param> /// <param name="packageId">The identifier of the package whose files are being imported.</param> /// <returns>Returns the location of the package that was added.</returns> /// <remarks> /// <p/>This method copies all package files that are referenced in the manifest into a unique /// subdirectory in the basePath directory. /// /// <p/>This method will validate that the package does not have any errors when it is /// processed by the <c>PackageValidator</c> class. Warnings that occur during validaton /// will have no effect on adding the package. /// /// <p/>Only packages which can be excuted may be imported into LearningStore. A package may be /// executed if there is at least one <Organization> nodes within it. /// /// <p/>This method creates a transaction, regardless of whether or not it is called within /// a transaction. /// /// <p/>The identity passed to the constructor will be used to write the files to the file system. This /// account must have appropriate permissions to write to the basePath directory for the package store. /// /// <p/>The exceptions thrown by Directory.CreateDirectory() may also be thrown by this method. /// </remarks> /// <exception cref="PackageImportException">Thrown if the package to be added is not a /// <c>PackageType.ContentAggregation</c> or does not contain /// at least one <item> node.</exception> /// <exception cref="UnauthorizedAccessException">Thrown if the identity used to create this object /// does not have sufficient permissions in the file system directory.</exception> private string ImportFiles(PackageItemIdentifier packageId, PackageReader packageReader) { string relativePackageLocation; // package location unique to this pacakge // The outer try/catch block is there for security reasons. Search MSDN for // "WrapVulnerableFinallyClausesInOuterTry" to see details. try { string absPackageLocation = null; // Create directories using the identity account that was passed to the store. using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { // Create the directory, relative to m_basePath relativePackageLocation = CreatePackageDirectory(packageId.GetKey(), 100); // Get the absolution package location of the new package directory absPackageLocation = PackageReader.SafePathCombine(m_basePath, relativePackageLocation); } if (packageReader.GetType().Equals(typeof(ZipPackageReader))) { // Let the zip reader do its own copy, as it's more efficient. Do not impersonate, as the package reader // needs to use its own identity (not the the store's identity) to access the files // ZipPackageReader doesn't want the directory to exist. (We had to create it above to verify it was // possible). using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { Directory.Delete(absPackageLocation); } ZipPackageReader zipReader = packageReader as ZipPackageReader; zipReader.CopyTo(absPackageLocation); } else { foreach (string filePath in packageReader.GetFilePaths()) { using (Disposer disposer = new Disposer()) { string absFilePath; // absolute location of the file to write string absDirPath; // absolute location of the drectory to write to FileStream outputStream; // stream to write to // Get stream for file from package Stream pkgStream = packageReader.GetFileStream(filePath); disposer.Push(pkgStream); // Create subdirectory, if it's required using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { absFilePath = PackageReader.SafePathCombine(absPackageLocation, filePath); absDirPath = Path.GetDirectoryName(absFilePath); if (!File.Exists(absDirPath) && !Directory.Exists(absDirPath)) { // Create it Directory.CreateDirectory(absDirPath); } // Create file location to write outputStream = new FileStream(absFilePath, FileMode.Create); disposer.Push(outputStream); } // Copy from the pkgStream to the outputStream, using the correct identities Utilities.CopyStream(pkgStream, ImpersonationBehavior.UseImpersonatedIdentity, outputStream, m_impersonationBehavior); } } } using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { // Remove imsmanifest.xml from the target directory. It'll be stored in LearningStore and providing two // copies may cause confusion or sync issues. string manifestFilePath = PackageReader.SafePathCombine(absPackageLocation, "imsmanifest.xml"); File.Delete(manifestFilePath); } } catch { throw; } // Return the new package return(relativePackageLocation); }