/// <summary> /// Internal method to create the actual transform stack of streams which /// will handle the encoding and decoding /// </summary> /// <param name="containerReference">Package reference for the data space stream</param> /// <param name="rawStream">Stream with raw bytes on disk</param> /// <returns>Stream with clear text</returns> internal Stream CreateDataSpaceStream( CompoundFileStreamReference containerReference , Stream rawStream ) { Stream outputStream = rawStream; // RightsManagementEncryptionTransform and CompressionTransform do not use transformContext IDictionary transformContext = new Hashtable(); // Transform context object // See which data space we're creating this stream in string dataSpaceLabel = _dataSpaceMap[containerReference] as string; Debug.Assert( null != dataSpaceLabel, "Internal caller has asked to create a data space stream but the reference is not associated with a data space" ); // Retrieve the transform object stack ArrayList transformStack = GetDataSpaceDefinition(dataSpaceLabel).TransformStack; Debug.Assert( null != transformStack, "Internal inconsistency - data space name does not have a transform stack definition" ); // Iterate the initialization process for each transform on the stack foreach( string transformLabel in transformStack ) { // Get information on this layer of the transform stack TransformInstance transformLayer = GetTransformInstanceOf( transformLabel ); Debug.Assert( null != transformLayer, "Data space definition included an undefined transform" ); // If we haven't gotten around to creating the transform object, go do it. if( null == transformLayer.transformReference ) { transformLayer.transformEnvironment = new TransformEnvironment( this, transformLabel ); transformLayer.transformReference = InstantiateDataTransformObject( transformLayer.ClassType, transformLayer.typeName, transformLayer.transformEnvironment ); } Debug.Assert( null != transformLayer.transformReference, "Failed to have a transform instance going in" ); IDataTransform transformObject = transformLayer.transformReference; // If transform is not ready, call initializers to make it ready. if( ! transformObject.IsReady ) { CallTransformInitializers( new TransformInitializationEventArgs( transformObject, dataSpaceLabel, containerReference.FullName, transformLabel) ); if( ! transformObject.IsReady ) // If STILL not ready, nobody could make it "ready". throw new InvalidOperationException( SR.Get(SRID.TransformObjectInitFailed)); } // Everything is setup, get a transformed stream outputStream = transformObject.GetTransformedStream( outputStream, transformContext ); } outputStream = new BufferedStream( outputStream ); // Add buffering layer outputStream = new StreamWithDictionary( outputStream, transformContext ); _transformedStreams.Add( outputStream ); // Remember this for later use return outputStream; }
/// <summary> /// Deserialize from the given stream /// </summary> /// <param name="reader">the BinaryReader to deserialize from with the seek pointer at the beginning of the container reference</param> /// <param name="bytesRead">bytes consumed from the stream</param> /// <remarks> /// Side effect of change the stream pointer /// </remarks> /// <exception cref="FileFormatException">Throws a FileFormatException if any formatting errors are encountered</exception> internal static CompoundFileReference Load(BinaryReader reader, out int bytesRead) { ContainerUtilities.CheckAgainstNull( reader, "reader" ); bytesRead = 0; // running count of how much we've read - sanity check // create the TypeMap // reconstitute ourselves from the given BinaryReader // in this version, the next Int32 is the number of entries Int32 entryCount = reader.ReadInt32(); bytesRead += ContainerUtilities.Int32Size; // EntryCount of zero indicates the root storage. if (entryCount < 0) throw new FileFormatException( SR.Get(SRID.CFRCorrupt)); // need a temp collection because we don't know what we're dealing with until a non-storage component // type is encountered StringCollection storageList = null; String streamName = null; // loop through the entries - accumulating strings until we know what kind of object // we ultimately need int byteLength; // reusable while (entryCount > 0) { // first Int32 tells us what kind of component this entry represents RefComponentType refType = (RefComponentType)reader.ReadInt32(); bytesRead += ContainerUtilities.Int32Size; switch (refType) { case RefComponentType.Storage: { if (streamName != null) throw new FileFormatException( SR.Get(SRID.CFRCorruptStgFollowStm)); if (storageList == null) storageList = new StringCollection(); String str = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out byteLength); bytesRead += byteLength; storageList.Add(str); } break; case RefComponentType.Stream: { if (streamName != null) throw new FileFormatException( SR.Get(SRID.CFRCorruptMultiStream)); streamName = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out byteLength); bytesRead += byteLength; } break; // we don't handle these types yet default: throw new FileFormatException( SR.Get(SRID.UnknownReferenceComponentType)); } --entryCount; } CompoundFileReference newRef = null; // stream or storage? if (streamName == null) { newRef = new CompoundFileStorageReference( ContainerUtilities.ConvertStringArrayPathToBackSlashPath(storageList)); } else newRef = new CompoundFileStreamReference( ContainerUtilities.ConvertStringArrayPathToBackSlashPath(storageList, streamName)); return newRef; }
/// <summary> /// Creates a new instance relative to the given parent /// </summary> /// <param name="parent">The parent storage</param> /// <param name="streamName">Path to stream under parent storage</param> /// <param name="compressionOption">CompressionOption</param> /// <param name="encryptionOption">EncryptionOption</param> internal StreamInfo( StorageInfo parent, string streamName, CompressionOption compressionOption, EncryptionOption encryptionOption ) { // Parameter validation CU.CheckAgainstNull( parent, "parent" ); CU.CheckStringAgainstNullAndEmpty( streamName, "streamName" ); // Parse path relative to given parent. BuildStreamInfoRelativeToStorage( parent, streamName); _compressionOption = compressionOption; _encryptionOption = encryptionOption; _streamReference = new CompoundFileStreamReference(this.parentStorage.FullNameInternal, this.core.streamName); }