/// <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); }