/// <summary> /// This method saves all the Excel embedded binary objects from the <paramref name="inputFile"/> to the /// <see cref="outputFolder"/> /// </summary> /// <param name="inputFile">The binary Excel file</param> /// <param name="outputFolder">The output folder</param> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when the <paramref name="inputFile"/> is password protected</exception> /// <exception cref="OEFileIsCorrupt">Raised when the file is corrupt</exception> public static List<string> SaveToFolder(string inputFile, string outputFolder) { using (var compoundFile = new CompoundFile(inputFile)) { try { if (IsPasswordProtected(compoundFile)) throw new OEFileIsPasswordProtected("The file '" + Path.GetFileName(inputFile) + "' is password protected"); } catch (CFCorruptedFileException) { throw new OEFileIsCorrupt("The file '" + Path.GetFileName(inputFile) + "' is corrupt"); } var result = new List<string>(); foreach (var child in compoundFile.RootStorage.Children) { var childStorage = child as CFStorage; if (childStorage == null) continue; // Linked files start with "LNK" if (!childStorage.Name.StartsWith("MBD")) continue; var extractedFileName = Extraction.SaveFromStorageNode(childStorage, outputFolder); if (extractedFileName != null) result.Add(extractedFileName); } return result; } }
/// <summary> /// Returns true when the Word file is password protected /// </summary> /// <param name="compoundFile"></param> /// <returns></returns> /// <exception cref="OEFileIsCorrupt">Raised when the file is corrupt</exception> public static bool IsPasswordProtected(CompoundFile compoundFile) { if (!compoundFile.RootStorage.ExistsStream("WordDocument")) throw new OEFileIsCorrupt("Could not find the WordDocument stream in the file '" + compoundFile.FileName + "'"); var stream = compoundFile.RootStorage.GetStream("WordDocument") as CFStream; if (stream == null) return false; var bytes = stream.GetData(); using (var memoryStream = new MemoryStream(bytes)) using (var binaryReader = new BinaryReader(memoryStream)) { //http://msdn.microsoft.com/en-us/library/dd944620%28v=office.12%29.aspx // The bit that shows if the file is encrypted is in the 11th and 12th byte so we // need to skip the first 10 bytes binaryReader.ReadBytes(10); // Now we read the 2 bytes that we need var pnNext = binaryReader.ReadUInt16(); //(value & mask) == mask) // The bit that tells us if the file is encrypted return (pnNext & 0x0100) == 0x0100; } }
internal CFStream(CompoundFile sectorManager, IDirectoryEntry dirEntry) : base(sectorManager) { if (dirEntry == null || dirEntry.SID < 0) throw new CFException("Attempting to add a CFStream using an unitialized directory"); DirEntry = dirEntry; }
/// <summary> /// This method saves all the Word embedded binary objects from the <paramref name="inputFile"/> to the /// <see cref="outputFolder"/> /// </summary> /// <param name="inputFile">The binary Word file</param> /// <param name="outputFolder">The output folder</param> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when the <see cref="inputFile"/> is password protected</exception> public static List<string> SaveToFolder(string inputFile, string outputFolder) { using (var compoundFile = new CompoundFile(inputFile)) { if (IsPasswordProtected(compoundFile)) throw new OEFileIsPasswordProtected("The file '" + Path.GetFileName(inputFile) + "' is password protected"); var result = new List<string>(); if (!compoundFile.RootStorage.ExistsStorage("ObjectPool")) return result; var objectPoolStorage = compoundFile.RootStorage.GetStorage("ObjectPool") as CFStorage; if (objectPoolStorage == null) return result; // Multiple objects are stored as children of the storage object foreach (var child in objectPoolStorage.Children) { var childStorage = child as CFStorage; if (childStorage == null) continue; // Get the objInfo stream to check if this is a linked file... if so then ignore it var objInfo = childStorage.GetStream("\x0003ObjInfo"); var objInfoStream = new ObjInfoStream(objInfo); // We don't want to export linked objects and objects that are not shown as an icon... // because these objects are already visible on the Word document if (objInfoStream.Link || !objInfoStream.Icon) continue; var extractedFileName = Extraction.SaveFromStorageNode(childStorage, outputFolder); if (!string.IsNullOrEmpty(extractedFileName)) result.Add(extractedFileName); } return result; } }
protected CFItem(CompoundFile compoundFile) { _compoundFile = compoundFile; }
/// <summary> /// Saves the <paramref name="data"/> byte array to the <paramref name="outputFile"/> /// </summary> /// <param name="data">The stream as byte array</param> /// <param name="outputFile">The output filename with path</param> /// <returns></returns> /// <exception cref="OEFileIsCorrupt">Raised when the file is corrupt</exception> internal static string SaveByteArrayToFile(byte[] data, string outputFile) { // Because the data is stored in a stream we have no name for it so we // have to check the magic bytes to see with what kind of file we are dealing var extension = Path.GetExtension(outputFile); if (string.IsNullOrEmpty(extension)) { var fileType = FileTypeSelector.GetFileTypeFileInfo(data); if (fileType != null && !string.IsNullOrEmpty(fileType.Extension)) outputFile += "." + fileType.Extension; if (fileType != null) extension = "." + fileType.Extension; } // Check if the output file already exists and if so make a new one outputFile = FileManager.FileExistsMakeNew(outputFile); if (extension != null) { switch (extension.ToUpperInvariant()) { case ".XLS": case ".XLT": case ".XLW": using (var memoryStream = new MemoryStream(data)) using (var compoundFile = new CompoundFile(memoryStream)) { Excel.SetWorkbookVisibility(compoundFile.RootStorage); compoundFile.Save(outputFile); } break; case ".XLSB": case ".XLSM": case ".XLSX": case ".XLTM": case ".XLTX": using (var memoryStream = new MemoryStream(data)) { var file = Excel.SetWorkbookVisibility(memoryStream); File.WriteAllBytes(outputFile, file.ToArray()); } break; default: File.WriteAllBytes(outputFile, data); break; } } else File.WriteAllBytes(outputFile, data); return outputFile; }
/// <summary> /// This will save the complete tree from the given <paramref name="storage"/> to a new <see cref="CompoundFile"/> /// </summary> /// <param name="storage"></param> /// <param name="fileName">The filename with path for the new compound file</param> internal static string SaveStorageTreeToCompoundFile(CFStorage storage, string fileName) { fileName = FileManager.FileExistsMakeNew(fileName); using (var compoundFile = new CompoundFile()) { GetStorageChain(compoundFile.RootStorage, storage); compoundFile.Save(fileName); } return fileName; }
/// <summary> /// This method will extract and save the data from the given <see cref="CompoundFile"/> node to the <see cref="outputFolder"/> /// </summary> /// <param name="bytes">The <see cref="CompoundFile"/> as a byte array</param> /// <param name="outputFolder">The outputFolder</param> /// <param name="fileName">The fileName to use, null when the fileName is unknown</param> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when a WordDocument, WorkBook or PowerPoint Document stream is password protected</exception> internal static string SaveFromStorageNode(byte[] bytes, string outputFolder, string fileName) { using (var memoryStream = new MemoryStream(bytes)) using (var compoundFile = new CompoundFile(memoryStream)) return SaveFromStorageNode(compoundFile.RootStorage, outputFolder, fileName); }
internal CFStream(CompoundFile sectorManager) : base(sectorManager) { DirEntry = new DirectoryEntry(StgType.StgStream); sectorManager.InsertNewDirectoryEntry(DirEntry); }
/// <summary> /// This method saves all the PowerPoint embedded binary objects from the <paramref name="inputFile"/> to the /// <paramref name="outputFolder"/> /// </summary> /// <param name="inputFile">The binary PowerPoint file</param> /// <param name="outputFolder">The output folder</param> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when the <see cref="inputFile"/> is password protected</exception> public static List<string> SaveToFolder(string inputFile, string outputFolder) { using (var compoundFile = new CompoundFile(inputFile)) { if (IsPasswordProtected(compoundFile)) throw new OEFileIsPasswordProtected("The file '" + Path.GetFileName(inputFile) + "' is password protected"); var result = new List<string>(); if (!compoundFile.RootStorage.ExistsStream("PowerPoint Document")) return result; var stream = compoundFile.RootStorage.GetStream("PowerPoint Document") as CFStream; if (stream == null) return result; using (var memoryStream = new MemoryStream(stream.GetData())) using (var binaryReader = new BinaryReader(memoryStream)) { while (binaryReader.BaseStream.Position != memoryStream.Length) { var verAndInstance = binaryReader.ReadUInt16(); // ReSharper disable once UnusedVariable var version = verAndInstance & 0x000FU; // First 4 bit of field verAndInstance var instance = (verAndInstance & 0xFFF0U) >> 4; // Last 12 bit of field verAndInstance var typeCode = binaryReader.ReadUInt16(); var size = binaryReader.ReadUInt32(); // Embedded OLE objects start with code 4113 if (typeCode == 4113) { if (instance == 0) { // Uncompressed var bytes = binaryReader.ReadBytes((int)size); // Check if the ole object is another compound storage node with a package stream if (Extraction.IsCompoundFile(bytes)) result.Add(Extraction.SaveFromStorageNode(bytes, outputFolder)); else Extraction.SaveByteArrayToFile(bytes, outputFolder + Extraction.DefaultEmbeddedObjectName); } else { var decompressedSize = binaryReader.ReadUInt32(); var data = binaryReader.ReadBytes((int)size - 4); var compressedMemoryStream = new MemoryStream(data); // skip the first 2 bytes compressedMemoryStream.ReadByte(); compressedMemoryStream.ReadByte(); // Decompress the bytes var decompressedBytes = new byte[decompressedSize]; var deflateStream = new DeflateStream(compressedMemoryStream, CompressionMode.Decompress, true); deflateStream.Read(decompressedBytes, 0, decompressedBytes.Length); string extractedFileName; // Check if the ole object is another compound storage node with a package stream if (Extraction.IsCompoundFile(decompressedBytes)) extractedFileName = Extraction.SaveFromStorageNode(decompressedBytes, outputFolder); else extractedFileName = Extraction.SaveByteArrayToFile(decompressedBytes, outputFolder + Extraction.DefaultEmbeddedObjectName); if (!string.IsNullOrEmpty(extractedFileName)) result.Add(extractedFileName); } } else binaryReader.BaseStream.Position += size; } } return result; } }
/// <summary> /// Extracts a Outlook File Attachment object from the given <paramref name="stream"/> /// </summary> /// <param name="stream"></param> /// <param name="outputFolder">The output folder</param> internal static string ExtractOutlookAttachmentObject(Stream stream, string outputFolder) { // Outlook attachments embedded in RTF are firstly embedded in an OLE v1.0 object var ole10 = new Ole10(stream); // After that it is wrapped in a compound document using (var internalStream = new MemoryStream(ole10.NativeData)) using (var compoundFile = new CompoundFile(internalStream)) { string fileName = null; if (compoundFile.RootStorage.ExistsStream("AttachDesc")) { var attachDescStream = compoundFile.RootStorage.GetStream("AttachDesc") as CFStream; fileName = GetFileNameFromAttachDescStream(attachDescStream); } if (string.IsNullOrEmpty(fileName)) fileName = Extraction.DefaultEmbeddedObjectName; fileName = FileManager.RemoveInvalidFileNameChars(fileName); fileName = Path.Combine(outputFolder, fileName); fileName = FileManager.FileExistsMakeNew(fileName); if (compoundFile.RootStorage.ExistsStream("AttachContents")) { var data = compoundFile.RootStorage.GetStream("AttachContents").GetData(); return Extraction.SaveByteArrayToFile(data, fileName); } if (compoundFile.RootStorage.ExistsStorage("MAPIMessage")) { fileName = Path.Combine(outputFolder, fileName); var storage = compoundFile.RootStorage.GetStorage("MAPIMessage") as CFStorage; return Extraction.SaveStorageTreeToCompoundFile(storage, fileName); } return null; } }
/// <summary> /// Extracts all the embedded object from the OpenDocument <paramref name="inputFile"/> to the /// <see cref="outputFolder"/> and returns the files with full path as a list of strings /// </summary> /// <param name="inputFile">The OpenDocument format file</param> /// <param name="outputFolder">The output folder</param> /// <returns>List with files or en empty list when there are nog embedded files</returns> /// <exception cref="OEFileIsPasswordProtected">Raised when the OpenDocument format file is password protected</exception> internal List<string> ExtractFromOpenDocumentFormat(string inputFile, string outputFolder) { var result = new List<string>(); var zipFile = new ZipFile(inputFile); // Check if the file is password protected var manifestEntry = zipFile.FindEntry("META-INF/manifest.xml", true); if (manifestEntry != -1) { using (var manifestEntryStream = zipFile.GetInputStream(manifestEntry)) using (var manifestEntryMemoryStream = new MemoryStream()) { manifestEntryStream.CopyTo(manifestEntryMemoryStream); manifestEntryMemoryStream.Position = 0; using (var streamReader = new StreamReader(manifestEntryMemoryStream)) { var manifest = streamReader.ReadToEnd(); if (manifest.ToUpperInvariant().Contains("ENCRYPTION-DATA")) throw new OEFileIsPasswordProtected("The file '" + Path.GetFileName(inputFile) + "' is password protected"); } } } foreach (ZipEntry zipEntry in zipFile) { if (!zipEntry.IsFile) continue; if (zipEntry.IsCrypted) throw new OEFileIsPasswordProtected("The file '" + Path.GetFileName(inputFile) + "' is password protected"); var name = zipEntry.Name.ToUpperInvariant(); if (!name.StartsWith("OBJECT") || name.Contains("/")) continue; string fileName = null; var objectReplacementFileIndex = zipFile.FindEntry("ObjectReplacements/" + name, true); if (objectReplacementFileIndex != -1) fileName = Extraction.GetFileNameFromObjectReplacementFile(zipFile, objectReplacementFileIndex); using (var zipEntryStream = zipFile.GetInputStream(zipEntry)) using (var zipEntryMemoryStream = new MemoryStream()) { zipEntryStream.CopyTo(zipEntryMemoryStream); using (var compoundFile = new CompoundFile(zipEntryMemoryStream)) result.Add(Extraction.SaveFromStorageNode(compoundFile.RootStorage, outputFolder, fileName)); } } return result; }
/// <summary> /// Extracts all the embedded object from the Office Open XML <paramref name="inputFile"/> to the /// <see cref="outputFolder"/> and returns the files with full path as a list of strings /// </summary> /// <param name="inputFile">The Office Open XML format file</param> /// <param name="embeddingPartString">The folder in the Office Open XML format (zip) file</param> /// <param name="outputFolder">The output folder</param> /// <returns>List with files or en empty list when there are nog embedded files</returns> /// <exception cref="OEFileIsPasswordProtected">Raised when the Microsoft Office file is password protected</exception> internal List<string> ExtractFromOfficeOpenXmlFormat(string inputFile, string embeddingPartString, string outputFolder) { var result = new List<string>(); using (var inputFileMemoryStream = new MemoryStream(File.ReadAllBytes(inputFile))) { try { var package = Package.Open(inputFileMemoryStream); // Get the embedded files names. foreach (var packagePart in package.GetParts()) { if (packagePart.Uri.ToString().StartsWith(embeddingPartString)) { using (var packagePartStream = packagePart.GetStream()) using (var packagePartMemoryStream = new MemoryStream()) { packagePartStream.CopyTo(packagePartMemoryStream); var fileName = outputFolder + packagePart.Uri.ToString().Remove(0, embeddingPartString.Length); if (fileName.ToUpperInvariant().Contains("OLEOBJECT")) { using (var compoundFile = new CompoundFile(packagePartStream)) { result.Add(Extraction.SaveFromStorageNode(compoundFile.RootStorage, outputFolder)); //result.Add(ExtractFileFromOle10Native(packagePartMemoryStream.ToArray(), outputFolder)); } } else { fileName = FileManager.FileExistsMakeNew(fileName); File.WriteAllBytes(fileName, packagePartMemoryStream.ToArray()); result.Add(fileName); } } } } package.Close(); return result; } catch (FileFormatException fileFormatException) { if ( !fileFormatException.Message.Equals("File contains corrupted data.", StringComparison.InvariantCultureIgnoreCase)) return null; try { // When we receive this exception we can have 2 things: // - The file is corrupt // - The file is password protected, in this case the file is saved as a compound file //EncryptedPackage using (var compoundFile = new CompoundFile(inputFileMemoryStream)) { if (compoundFile.RootStorage.ExistsStream("EncryptedPackage")) throw new OEFileIsPasswordProtected("The file '" + Path.GetFileName(inputFile) + "' is password protected"); } } catch (Exception) { return null; } } } return null; }
/// <summary> /// Returns true when the Word file is password protected /// </summary> /// <param name="inputFile">The Word file to check</param> /// <returns></returns> /// <exception cref="OCFileIsCorrupt">Raised when the file is corrupt</exception> internal static bool FileIsPasswordProtected(string inputFile) { try { using (var compoundFile = new CompoundFile(inputFile)) { if (compoundFile.RootStorage.ExistsStream("EncryptedPackage")) return true; if (!compoundFile.RootStorage.ExistsStream("WordDocument")) throw new OCFileIsCorrupt("Could not find the WordDocument stream in the file '" + compoundFile.FileName + "'"); var stream = compoundFile.RootStorage.GetStream("WordDocument") as CFStream; if (stream == null) return false; var bytes = stream.GetData(); using (var memoryStream = new MemoryStream(bytes)) using (var binaryReader = new BinaryReader(memoryStream)) { //http://msdn.microsoft.com/en-us/library/dd944620%28v=office.12%29.aspx // The bit that shows if the file is encrypted is in the 11th and 12th byte so we // need to skip the first 10 bytes binaryReader.ReadBytes(10); // Now we read the 2 bytes that we need var pnNext = binaryReader.ReadUInt16(); //(value & mask) == mask) // The bit that tells us if the file is encrypted return (pnNext & 0x0100) == 0x0100; } } } catch (CFCorruptedFileException) { throw new OCFileIsCorrupt("The file '" + Path.GetFileName(inputFile) + "' is corrupt"); } catch (CFFileFormatException) { // It seems the file is just a normal Microsoft Office 2007 and up Open XML file return false; } }
/// <summary> /// Returns true when the Excel file is password protected /// </summary> /// <param name="inputFile">The Excel file to check</param> /// <returns></returns> /// <exception cref="OCFileIsCorrupt">Raised when the file is corrupt</exception> internal static bool FileIsPasswordProtected(string inputFile) { try { using (var compoundFile = new CompoundFile(inputFile)) { if (compoundFile.RootStorage.ExistsStream("EncryptedPackage")) return true; if (!compoundFile.RootStorage.ExistsStream("WorkBook")) throw new OCFileIsCorrupt("Could not find the WorkBook stream in the file '" + compoundFile.FileName + "'"); var stream = compoundFile.RootStorage.GetStream("WorkBook") as CFStream; if (stream == null) return false; var bytes = stream.GetData(); using (var memoryStream = new MemoryStream(bytes)) using (var binaryReader = new BinaryReader(memoryStream)) { // Get the record type, at the beginning of the stream this should always be the BOF var recordType = binaryReader.ReadUInt16(); // Something seems to be wrong, we would expect a BOF but for some reason it isn't so stop it if (recordType != 0x809) throw new OCFileIsCorrupt("The file '" + Path.GetFileName(compoundFile.FileName) + "' is corrupt"); var recordLength = binaryReader.ReadUInt16(); binaryReader.BaseStream.Position += recordLength; // Search after the BOF for the FilePass record, this starts with 2F hex recordType = binaryReader.ReadUInt16(); if (recordType != 0x2F) return false; binaryReader.ReadUInt16(); var filePassRecord = new FilePassRecord(memoryStream); var key = Biff8EncryptionKey.Create(filePassRecord.DocId); return !key.Validate(filePassRecord.SaltData, filePassRecord.SaltHash); } } } catch (OCConfiguration) { // If we get an OCExcelConfiguration exception it means we have an unknown encryption // type so we return a false so that Excel itself can figure out if the file is password // protected return false; } catch (CFCorruptedFileException) { throw new OCFileIsCorrupt("The file '" + Path.GetFileName(inputFile) + "' is corrupt"); } catch (CFFileFormatException) { // It seems the file is just a normal Microsoft Office 2007 and up Open XML file return false; } }
/* // Because the properties to be set are known in advance, // most of the structures involved can be statically declared // to minimize expensive MAPIAllocateBuffer calls. SPropValue spvProps[NUM_PROPS] = {0}; spvProps[p_PR_MESSAGE_CLASS_W].ulPropTag = PR_MESSAGE_CLASS_W; spvProps[p_PR_ICON_INDEX].ulPropTag = PR_ICON_INDEX; spvProps[p_PR_SUBJECT_W].ulPropTag = PR_SUBJECT_W; spvProps[p_PR_CONVERSATION_TOPIC_W].ulPropTag = PR_CONVERSATION_TOPIC_W; spvProps[p_PR_BODY_W].ulPropTag = PR_BODY_W; spvProps[p_PR_IMPORTANCE].ulPropTag = PR_IMPORTANCE; spvProps[p_PR_READ_RECEIPT_REQUESTED].ulPropTag = PR_READ_RECEIPT_REQUESTED; spvProps[p_PR_MESSAGE_FLAGS].ulPropTag = PR_MESSAGE_FLAGS; spvProps[p_PR_MSG_EDITOR_FORMAT].ulPropTag = PR_MSG_EDITOR_FORMAT; spvProps[p_PR_MESSAGE_LOCALE_ID].ulPropTag = PR_MESSAGE_LOCALE_ID; spvProps[p_PR_INETMAIL_OVERRIDE_FORMAT].ulPropTag = PR_INETMAIL_OVERRIDE_FORMAT; spvProps[p_PR_DELETE_AFTER_SUBMIT].ulPropTag = PR_DELETE_AFTER_SUBMIT; spvProps[p_PR_INTERNET_CPID].ulPropTag = PR_INTERNET_CPID; spvProps[p_PR_CONVERSATION_INDEX].ulPropTag = PR_CONVERSATION_INDEX; spvProps[p_PR_MESSAGE_CLASS_W].Value.lpszW = L"IPM.Note"; spvProps[p_PR_ICON_INDEX].Value.l = 0x103; // Unsent Mail spvProps[p_PR_SUBJECT_W].Value.lpszW = szSubject; spvProps[p_PR_CONVERSATION_TOPIC_W].Value.lpszW = szSubject; spvProps[p_PR_BODY_W].Value.lpszW = szBody; spvProps[p_PR_IMPORTANCE].Value.l = bHighImportance?IMPORTANCE_HIGH:IMPORTANCE_NORMAL; spvProps[p_PR_READ_RECEIPT_REQUESTED].Value.b = bReadReceipt?true:false; spvProps[p_PR_MESSAGE_FLAGS].Value.l = MSGFLAG_UNSENT; spvProps[p_PR_MSG_EDITOR_FORMAT].Value.l = EDITOR_FORMAT_PLAINTEXT; spvProps[p_PR_MESSAGE_LOCALE_ID].Value.l = 1033; // (en-us) spvProps[p_PR_INETMAIL_OVERRIDE_FORMAT].Value.l = NULL; // Mail system chooses default encoding scheme spvProps[p_PR_DELETE_AFTER_SUBMIT].Value.b = bDeleteAfterSubmit?true:false; spvProps[p_PR_INTERNET_CPID].Value.l = cpidASCII; hRes = BuildConversationIndex( &spvProps[p_PR_CONVERSATION_INDEX].Value.bin.cb, &spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb); */ public void Test() { using (var stream = File.OpenRead("d:\\message.msg")) using (var cf = new CompoundFile(stream)) { var st = cf.RootStorage.GetStream("__properties_version1.0"); var p = new TopLevelPropertiesStream(st); foreach (var child in cf.RootStorage.Children) { if (child.IsStream) { var cfStream = child as CFStream; if (cfStream == null) continue; if (cfStream.Name.StartsWith("__substg1.0_")) p.AddProperty(cfStream); } } var pr = p.Find(m => m.IdAsString == "0E1D"); } }
/// <summary> /// Returns true when the binary PowerPoint file is password protected /// </summary> /// <param name="inputFile">The PowerPoint file to check</param> /// <returns></returns> internal static bool FileIsPasswordProtected(string inputFile) { try { using (var compoundFile = new CompoundFile(inputFile)) { if (compoundFile.RootStorage.ExistsStream("EncryptedPackage")) return true; if (!compoundFile.RootStorage.ExistsStream("Current User")) return false; var stream = compoundFile.RootStorage.GetStream("Current User") as CFStream; if (stream == null) return false; using (var memoryStream = new MemoryStream(stream.GetData())) using (var binaryReader = new BinaryReader(memoryStream)) { var verAndInstance = binaryReader.ReadUInt16(); // ReSharper disable UnusedVariable // We need to read these fields to get to the correct location in the Current User stream var version = verAndInstance & 0x000FU; // first 4 bit of field verAndInstance var instance = (verAndInstance & 0xFFF0U) >> 4; // last 12 bit of field verAndInstance var typeCode = binaryReader.ReadUInt16(); var size = binaryReader.ReadUInt32(); var size1 = binaryReader.ReadUInt32(); // ReSharper restore UnusedVariable var headerToken = binaryReader.ReadUInt32(); switch (headerToken) { // Not encrypted case 0xE391C05F: return false; // Encrypted case 0xF3D1C4DF: return true; default: return false; } } } } catch (CFCorruptedFileException) { throw new OCFileIsCorrupt("The file '" + Path.GetFileName(inputFile) + "' is corrupt"); } catch (CFFileFormatException) { // It seems the file is just a normal Microsoft Office 2007 and up Open XML file return false; } }
/// <summary> /// Returns true when the binary PowerPoint file is password protected /// </summary> /// <param name="compoundFile"></param> /// <returns></returns> private static bool IsPasswordProtected(CompoundFile compoundFile) { if (!compoundFile.RootStorage.ExistsStream("Current User")) return false; var stream = compoundFile.RootStorage.GetStream("Current User") as CFStream; if (stream == null) return false; using (var memoryStream = new MemoryStream(stream.GetData())) using (var binaryReader = new BinaryReader(memoryStream)) { var verAndInstance = binaryReader.ReadUInt16(); // ReSharper disable UnusedVariable // We need to read these fields to get to the correct location in the Current User stream var version = verAndInstance & 0x000FU; // first 4 bit of field verAndInstance var instance = (verAndInstance & 0xFFF0U) >> 4; // last 12 bit of field verAndInstance var typeCode = binaryReader.ReadUInt16(); var size = binaryReader.ReadUInt32(); var size1 = binaryReader.ReadUInt32(); // ReSharper restore UnusedVariable var headerToken = binaryReader.ReadUInt32(); switch (headerToken) { // Not encrypted case 0xE391C05F: return false; // Encrypted case 0xF3D1C4DF: return true; default: return false; } } }