public PropertyContext(ulong nid, PSTFile pst) { var bytes = BlockBO.GetNodeData(nid, pst); var HN = new HN(bytes); this.BTH = new BTH(HN); this.Properties = this.BTH.GetExchangeProperties(); }
public PSTBTree(BREF bref, PSTFile pst) { using (var viewer = pst.PSTMMF.CreateViewAccessor((long)bref.IB, 512)) { var data = new byte[512]; viewer.ReadArray(0, data, 0, 512); this.Root = new BTPage(data, bref, pst); } }
//this is only here for testing purposes, this needs to be moved public bool BlankPassword(PSTFile pst) { var toMatch = new byte[] { 0xFF, 0x67 }; foreach (var entry in this.DataEntries) { if (entry.Key[0] == toMatch[0] && entry.Key[1] == toMatch[1]) { pst.CloseMMF(); //DatatEncoder.CryptPermute(ref this._data.Parent.Data, this._data.Parent.Data.Length, true); using (var stream = new FileStream(pst.Path, FileMode.Open)) { var dataBlockOffset = entry.DataOffset; //this._data.Parent.Data[dataBlockOffset] = 0x00; //this._data.Parent.Data[dataBlockOffset + 1] = 0x00; this._data.Parent.Data[dataBlockOffset + 2] = 0x00; this._data.Parent.Data[dataBlockOffset + 3] = 0x00; this._data.Parent.Data[dataBlockOffset + 4] = 0x00; this._data.Parent.Data[dataBlockOffset + 5] = 0x00; DataEncoder.CryptPermute(this._data.Parent.Data, this._data.Parent.Data.Length, true, pst); var testCRC = (new CRC32()).ComputeCRC(0, this._data.Parent.Data, (uint)this._data.Parent.Data.Length); stream.Seek((long)(this._data.Parent.PstOffset + entry.DataOffset), SeekOrigin.Begin); stream.Write( new [] { //this._data.Parent.Data[dataBlockOffset], //this._data.Parent.Data[dataBlockOffset + 1], this._data.Parent.Data[dataBlockOffset + 2], this._data.Parent.Data[dataBlockOffset + 3], this._data.Parent.Data[dataBlockOffset + 4], this._data.Parent.Data[dataBlockOffset + 5] }, 0, 4); var newCRC = (new CRC32()).ComputeCRC(0, this._data.Parent.Data, (uint)this._data.Parent.Data.Length); DataEncoder.CryptPermute(this._data.Parent.Data, this._data.Parent.Data.Length, false, pst); var crcoffset = (int)(this._data.Parent.PstOffset + this._data.Parent.CRCOffset); stream.Seek(crcoffset, SeekOrigin.Begin); var temp = BitConverter.GetBytes(newCRC); stream.Write(new [] { temp[0], temp[1], temp[2], temp[3] }, 0, 4); } pst.OpenMMF(); return(true); } } return(false); }
private void GetMessageClass(PSTFile pst) { if (!PC.Properties.ContainsKey(MessageProperty.MessageClass)) { return; } MessageClass = pst.Header.isUnicode ? Encoding.Unicode.GetString(PC.Properties[MessageProperty.MessageClass].Data) : Encoding.ASCII.GetString(PC.Properties[MessageProperty.MessageClass].Data); }
//this is only here for testing purposes, this needs to be moved public bool BlankPassword(PSTFile pst) { var toMatch = new byte[] {0xFF, 0x67}; foreach (var entry in this.DataEntries) if (entry.Key[0] == toMatch[0] && entry.Key[1] == toMatch[1]) { pst.CloseMMF(); //DatatEncoder.CryptPermute(ref this._data.Parent.Data, this._data.Parent.Data.Length, true); using (var stream = new FileStream(pst.Path, FileMode.Open)) { var dataBlockOffset = entry.DataOffset; //this._data.Parent.Data[dataBlockOffset] = 0x00; //this._data.Parent.Data[dataBlockOffset + 1] = 0x00; this._data.Parent.Data[dataBlockOffset + 2] = 0x00; this._data.Parent.Data[dataBlockOffset + 3] = 0x00; this._data.Parent.Data[dataBlockOffset + 4] = 0x00; this._data.Parent.Data[dataBlockOffset + 5] = 0x00; DatatEncoder.CryptPermute(this._data.Parent.Data, this._data.Parent.Data.Length, true, pst); var testCRC = (new CRC32()).ComputeCRC(0, this._data.Parent.Data, (uint)this._data.Parent.Data.Length); stream.Seek((long)(this._data.Parent.PstOffset + entry.DataOffset), SeekOrigin.Begin); stream.Write( new [] { //this._data.Parent.Data[dataBlockOffset], //this._data.Parent.Data[dataBlockOffset + 1], this._data.Parent.Data[dataBlockOffset + 2], this._data.Parent.Data[dataBlockOffset + 3], this._data.Parent.Data[dataBlockOffset + 4], this._data.Parent.Data[dataBlockOffset + 5] }, 0, 4); var newCRC = (new CRC32()).ComputeCRC(0, this._data.Parent.Data, (uint) this._data.Parent.Data.Length); DatatEncoder.CryptPermute(this._data.Parent.Data, this._data.Parent.Data.Length, false, pst); var crcoffset = (int) (this._data.Parent.PstOffset + this._data.Parent.CRCOffset); stream.Seek(crcoffset, SeekOrigin.Begin); var temp = BitConverter.GetBytes(newCRC); stream.Write(new [] { temp[0],temp[1],temp[2],temp[3] }, 0, 4); } pst.OpenMMF(); return true; } return false; }
private bool processSingleOutlookPstFile(string path) { bool result = true; PSTFile pst = PSTFile.Open(File.OpenRead(path)); Folder rootFolder = pst.GetRootMailboxFolder(); walkPstDir(rootFolder); return(result); }
public void ShouldCorrectlyReadFolderDisplayName() { //Arrange var sut = PSTFile.Open(new MemoryStream(Resources.user1_test_lab)); //Act var result = sut.GetRootMailboxFolder().GetProperty(MAPIProperties.PidTagDisplayName); //Assert Assert.AreEqual("Top of Outlook data file", result.Value.Value.ToUnicode()); }
public void ShouldCorrectlyReadMessageStoreDisplayName() { //Arrange var sut = PSTFile.Open(new MemoryStream(Resources.user1_test_lab)); //Act var result = sut.MessageStore.GetProperty(MAPIProperties.PidTagDisplayName); //Assert Assert.AreEqual("*****@*****.**", Encoding.Unicode.GetString(result.Value.Value)); }
private static List <BlockDataDTO> GetXBlockData(XBLOCK xblock, PSTFile pst) { var ret = new List <BlockDataDTO>(); foreach (var bid in xblock.BIDEntries) { var bbtEntry = pst.GetBlockBBTEntry(bid); ret.AddRange(BlockBO.GetBBTEntryData(bbtEntry, pst)); } return(ret); }
private Message GetMessageSut(string messageSubject) { var sut = PSTFile.Open(new MemoryStream(Resources.user1_test_lab)); return (sut .GetRootMailboxFolder() .GetSubFolders() .First(f => f.GetDisplayNameUnicode() == "FolderWithMessagesWithAttachments") .GetMessages() .First(m => m.GetSubjectUnicode() == messageSubject)); }
public bool BlankPassword(PSTFile pst) { if (this.Data != null) return this.Data.BlankPassword(pst); foreach (var child in Children) child.BlankPassword(pst); /*if (child.BlankPassword(Data) != null) return child.BlankPassword(Data);*/ return false; }
public MailFolder(ulong NID, List <string> path, PSTFile pst) { _pst = pst; Path = path; var nid = NID; var pcNID = ((nid >> 5) << 5) | 0x02; PC = new PropertyContext(pcNID, pst); DisplayName = pst.Header.isUnicode ? Encoding.Unicode.GetString(PC.Properties[MessageProperty.DisplayName].Data) : Encoding.ASCII.GetString(PC.Properties[MessageProperty.DisplayName].Data); Path = new List <string>(path); Path.Add(DisplayName); var heirachyNID = ((nid >> 5) << 5) | 0x0D; var contentsNID = ((nid >> 5) << 5) | 0x0E; var faiNID = ((nid >> 5) << 5) | 0x0F; HierarchyTC = new TableContext(heirachyNID, pst); SubFolders = new List <MailFolder>(); foreach (var row in HierarchyTC.ReverseRowIndex) { SubFolders.Add(new MailFolder(row.Value, Path, pst)); //var temp = row.Key; //var temp2 = row.Value; //SubFolderEntryIDs.Add(row.); } ContentsTC = new TableContext(contentsNID, pst); FaiTC = new TableContext(faiNID, pst); Messages = new List <Message>(); OtherItems = new List <IPMItem>(); foreach (var row in ContentsTC.ReverseRowIndex) { var item = new IPMItem(_pst, row.Value); //if (item.MessageClass.StartsWith("IPM.Note")) //{ Messages.Add(new Message(row.Value, _pst)); //} //else //{ // OtherItems.Add(item); //} } }
public NamedToPropertyLookup(PSTFile pst) { PC = new PropertyContext(NodeId, pst); GUIDs = PC.Properties[(MessageProperty)0x0002].Data; Entries = PC.Properties[(MessageProperty)0x0003].Data; String = PC.Properties[(MessageProperty)0x0004].Data; Lookup = new Dictionary <ushort, NAMEID>(); for (int i = 0; i < Entries.Length; i += 8) { var cur = new NAMEID(Entries, i, this); Lookup.Add(cur.PropIndex, cur); } }
public NamedToPropertyLookup(PSTFile pst) { PC = new PropertyContext(NODE_ID, pst); _GUIDs = PC.Properties[MessageProperty.GuidList].Data; _entries = PC.Properties[MessageProperty.EntryList].Data; _string = PC.Properties[MessageProperty.StringList].Data; Lookup = new Dictionary <ushort, NAMEID>(); for (int i = 0; i < _entries.Length; i += 8) { var cur = new NAMEID(_entries, i, this); Lookup.Add(cur.PropIndex, cur); } }
public BTPage(bool unicode, byte[] pageData, BREF _ref, PSTFile pst) { InternalChildren = new List <BTPage>(); this._ref = _ref; if (unicode) { _trailer = new PageTrailer(unicode, pageData.RangeSubset(496, 16)); _numEntries = pageData[488]; _maxEntries = pageData[489]; _cbEnt = pageData[490]; _cLevel = pageData[491]; } else { _trailer = new PageTrailer(unicode, pageData.RangeSubset(500, 12)); _numEntries = pageData[496]; _maxEntries = pageData[497]; _cbEnt = pageData[498]; _cLevel = pageData[499]; } Entries = new List <BTPAGEENTRY>(); for (var i = 0; i < _numEntries; i++) { var curEntryBytes = pageData.RangeSubset(i * _cbEnt, _cbEnt); if (_cLevel == 0) { if (_trailer.PageType == PageType.NBT) { Entries.Add(new NBTENTRY(unicode, curEntryBytes)); } else { Entries.Add(new BBTENTRY(unicode, curEntryBytes)); } } else { //btentries var entry = new BTENTRY(unicode, curEntryBytes); Entries.Add(entry); using (var view = pst.PSTMMF.CreateViewAccessor((long)entry.BREF.IB, 512)) { var bytes = new byte[512]; view.ReadArray(0, bytes, 0, 512); InternalChildren.Add(new BTPage(unicode, bytes, entry.BREF, pst)); } } } }
public NamedToPropertyLookup(PSTFile pst) { this.PC = new PropertyContext(NamedToPropertyLookup.NODE_ID, pst); this._GUIDs = this.PC.Properties[0x0002].Data; this._entries = this.PC.Properties[0x0003].Data; this._string = this.PC.Properties[0x0004].Data; this.Lookup = new Dictionary<ushort, NAMEID>(); for (int i = 0; i < this._entries.Length; i += 8) { var cur = new NAMEID(this._entries, i, this); this.Lookup.Add(cur.PropIndex, cur); } }
public static NodeDataDTO GetNodeData(Tuple <ulong, ulong> nodeBIDs, PSTFile pst) { var mainData = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(nodeBIDs.Item1), pst); var subNodeData = new Dictionary <ulong, NodeDataDTO>(); if (nodeBIDs.Item2 != 0) { subNodeData = BlockBO.GetSubNodeData(pst.GetBlockBBTEntry(nodeBIDs.Item2), pst); } return(new NodeDataDTO { NodeData = mainData, SubNodeData = subNodeData }); }
public NamedToPropertyLookup(PSTFile pst) { this.PC = new PropertyContext(NamedToPropertyLookup.NODE_ID, pst); this._GUIDs = this.PC.Properties[0x0002].Data; this._entries = this.PC.Properties[0x0003].Data; this._string = this.PC.Properties[0x0004].Data; this.Lookup = new Dictionary <ushort, NAMEID>(); for (int i = 0; i < this._entries.Length; i += 8) { var cur = new NAMEID(this._entries, i, this); this.Lookup.Add(cur.PropIndex, cur); } }
public static NodeDataDTO GetNodeData(SLENTRY entry, PSTFile pst) { var mainData = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(entry.SubNodeBID), pst); if (entry.SubSubNodeBID != 0) { var subNodeData = BlockBO.GetSubNodeData(pst.GetBlockBBTEntry(entry.SubSubNodeBID), pst); return(new NodeDataDTO { NodeData = mainData, SubNodeData = subNodeData }); } return(new NodeDataDTO { NodeData = mainData, SubNodeData = null }); }
public void ShouldCorrectlyReadMessageStorePassword() { //Arrange var sut = PSTFile.Open(new MemoryStream(Resources.user1_test_lab)); //Act var result = sut.MessageStore.GetProperty(MAPIProperties.PidTagPstPassword); //Assert //Although the PST is a Unicode PST. However, the password is encoded as ASCII. //TODO: Get some documentation on this. var encodedPassword = Encoding.ASCII.GetBytes("user1"); Assert.AreEqual(Crc32.ComputeCrc32(encodedPassword), result.Value.Value.ToInt32()); }
public static NodeDataDTO GetNodeData(ulong nid, PSTFile pst) { var nodeBIDs = pst.GetNodeBIDs(nid); var blockBBT_Entry = pst.GetBlockBBTEntry(nodeBIDs.Item1); var mainData = GetBBTEntryData(blockBBT_Entry, pst); var subNodeData = new Dictionary <ulong, NodeDataDTO>(); if (nodeBIDs.Item2 != 0) { subNodeData = GetSubNodeData(pst.GetBlockBBTEntry(nodeBIDs.Item2), pst); } return(new NodeDataDTO { NodeData = mainData, SubNodeData = subNodeData }); }
private static List <BlockDataDTO> GetXXBlockData(XXBLOCK xxblock, PSTFile pst) { var ret = new List <BlockDataDTO>(); foreach (var bid in xxblock.XBlockBIDs) { var bbtEntry = pst.GetBlockBBTEntry(bid); var curXblockData = BlockBO.GetBBTEntryData(bbtEntry, pst); //var curXblockData = BlockBO.GetXBlockData(curXblock); foreach (var block in curXblockData) { ret.Add(block); } } return(ret); }
public static NodeDataDTO GetNodeData(NBTENTRY entry, PSTFile pst) { var mainData = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(entry.BID_Data), pst); if (entry.BID_SUB != 0) { var subnodeData = BlockBO.GetSubNodeData(pst.GetBlockBBTEntry(entry.BID_SUB), pst); return(new NodeDataDTO { NodeData = mainData, SubNodeData = subnodeData }); } return(new NodeDataDTO { NodeData = mainData, SubNodeData = null }); }
public static Dictionary <ulong, NodeDataDTO> GetSubNodeData(ulong nid, PSTFile pst, int take = int.MaxValue) { var nodeBIDs = pst.GetNodeBIDs(nid); Dictionary <ulong, NodeDataDTO> subNodeData; if (nodeBIDs.Item2 == 0) { subNodeData = new Dictionary <ulong, NodeDataDTO>(); } else { subNodeData = GetSubNodeData(pst.GetBlockBBTEntry(nodeBIDs.Item2), pst, take); } return(subNodeData); }
public void ShouldCorrectlyDetectNewlyAddedFolder() { //Arrange var memoryStream = new MemoryStream(Resources.user1_test_lab); var sut = PSTFile.Open(memoryStream); //Act sut.GetRootMailboxFolder().NewFolder("NewFolder"); sut.Save(); sut = PSTFile.Open(memoryStream); //Assert Assert.IsTrue(sut.GetRootMailboxFolder().GetSubFolders().Any(f => f.GetDisplayNameUnicode() == "NewFolder")); }
public bool BlankPassword(PSTFile pst) { if (this.Data != null) { return(this.Data.BlankPassword(pst)); } foreach (var child in Children) { child.BlankPassword(pst); } /*if (child.BlankPassword(Data) != null) * return child.BlankPassword(Data);*/ return(false); }
public static void CryptPermute(byte[] pv, int cb, bool fEncrypt, PSTFile pst) { if (pst.Header.EncodingAlgotihm == PSTHeader.BlockEncoding.NONE) { return; } if (pst.Header.EncodingAlgotihm == PSTHeader.BlockEncoding.PERMUTE) { int idx = (fEncrypt ? 0 : 512); int temp = 0; for (int pvIndex = 0; pvIndex < cb; pvIndex++) { temp = pv[pvIndex]; temp = temp & 0xFF; pv[pvIndex] = mpbbCrypt[temp + idx]; } } }
public TableContext(ulong nid, PSTFile pst) { this.NodeData = BlockBO.GetNodeData(nid, pst); this.HeapNode = new HN(this.NodeData); var tcinfoHID = this.HeapNode.HeapNodes[0].Header.UserRoot; var tcinfoHIDbytes = this.HeapNode.GetHIDBytes(tcinfoHID); this.TCHeader = new TCINFOHEADER(tcinfoHIDbytes.Data); this.RowIndexBTH = new BTH(this.HeapNode,this.TCHeader.RowIndexLocation); this.ReverseRowIndex = new Dictionary<uint, uint>(); foreach(var prop in this.RowIndexBTH.Properties) { var temp = BitConverter.ToUInt32(prop.Value.Data, 0); this.ReverseRowIndex.Add(temp,BitConverter.ToUInt32(prop.Key, 0)); } this.RowMatrix = new TCRowMatrix(this, this.RowIndexBTH); }
public TableContext(ulong nid, PSTFile pst) { NodeData = BlockBO.GetNodeData(nid, pst); HeapNode = new HN(NodeData); var tcinfoHID = HeapNode.HeapNodes[0].Header.UserRoot; var tcinfoHIDbytes = HeapNode.GetHIDBytes(tcinfoHID); TCHeader = new TCINFOHEADER(tcinfoHIDbytes.Data); RowIndexBTH = new BTH(HeapNode, TCHeader.RowIndexLocation); ReverseRowIndex = new Dictionary <uint, uint>(); foreach (var prop in RowIndexBTH.Properties) { var temp = BitConverter.ToUInt32(prop.Value.Data, 0); ReverseRowIndex.Add(temp, BitConverter.ToUInt32(prop.Key, 0)); } RowMatrix = new TCRowMatrix(this, RowIndexBTH); }
public BTPage(byte[] pageData, BREF _ref, PSTFile pst) { this._ref = _ref; this.InternalChildren = new List <BTPage>(); this._trailer = new PageTrailer(pageData.RangeSubset(496, 16)); this._numEntries = pageData[488]; this._maxEntries = pageData[489]; this._cbEnt = pageData[490]; this._cLevel = pageData[491]; this.Entries = new List <BTPAGEENTRY>(); for (var i = 0; i < this._numEntries; i++) { var curEntryBytes = pageData.RangeSubset(i * this._cbEnt, this._cbEnt); if (this._cLevel == 0) { if (this._trailer.PageType == PageType.NBT) { this.Entries.Add(new NBTENTRY(curEntryBytes)); } else { var curEntry = new BBTENTRY(curEntryBytes); this.Entries.Add(curEntry); } } else { //btentries var entry = new BTENTRY(curEntryBytes); this.Entries.Add(entry); using (var view = pst.PSTMMF.CreateViewAccessor((long)entry.BREF.IB, 512)) { var bytes = new byte[512]; view.ReadArray(0, bytes, 0, 512); this.InternalChildren.Add(new BTPage(bytes, entry.BREF, pst)); } } } }
public BTPage(byte[] pageData, BREF _ref, PSTFile pst) { this._ref = _ref; this.InternalChildren = new List<BTPage>(); this._trailer = new PageTrailer(pageData.RangeSubset(496,16)); this._numEntries = pageData[488]; this._maxEntries = pageData[489]; this._cbEnt = pageData[490]; this._cLevel = pageData[491]; this.Entries = new List<BTPAGEENTRY>(); for (var i = 0; i < this._numEntries; i++) { var curEntryBytes = pageData.RangeSubset(i*this._cbEnt, this._cbEnt); if (this._cLevel == 0) { if (this._trailer.PageType == PageType.NBT) this.Entries.Add(new NBTENTRY(curEntryBytes)); else { var curEntry = new BBTENTRY(curEntryBytes); this.Entries.Add(curEntry); } } else { //btentries var entry = new BTENTRY(curEntryBytes); this.Entries.Add(entry); using (var view = pst.PSTMMF.CreateViewAccessor((long)entry.BREF.IB,512)) { var bytes = new byte[512]; view.ReadArray(0, bytes, 0, 512); this.InternalChildren.Add(new BTPage(bytes, entry.BREF, pst)); } } } }
private void OpenPST(string fileName) { if (currentFile != null) { try { currentFile.Dispose(); } catch { } } try { Cursor = Cursors.WaitCursor; currentFile = new PSTFile(fileName); treeViewFolders.Nodes.Clear(); LayoutFolders(null, currentFile.TopOfPST); } catch (Exception ex) { MessageBox.Show(this, ex.Message + ":\n\n" + ex.StackTrace.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } finally { Cursor = Cursors.Default; } }
public Message(uint NID, PSTFile pst) : base(pst, NID) { unicode = pst.Header.isUnicode; Data = BlockBO.GetNodeData(NID, pst); this.NID = NID; ContentEx = new List <string>(); //MessagePC = new PropertyContext(Data); int attachmentPcIndex = 0; foreach (var subNode in Data.SubNodeData) { var temp = new NID(subNode.Key); switch (temp.Type) { case NDB.NID.NodeType.ATTACHMENT_TABLE: AttachmentTable = new TableContext(subNode.Value); foreach (var row in AttachmentTable.RowMatrix.Rows) { Attachments.Add(new Attachment(pst.Header.isUnicode, row)); } break; case NDB.NID.NodeType.ATTACHMENT_PC: var AttachmentPC = new PropertyContext(subNode.Value); if (Attachments.Count > attachmentPcIndex) { Attachments[attachmentPcIndex].AddProperties(unicode, AttachmentPC); } attachmentPcIndex++; break; case NDB.NID.NodeType.RECIPIENT_TABLE: RecipientTable = new TableContext(subNode.Value); foreach (var row in RecipientTable.RowMatrix.Rows) { var recipient = new Recipient(pst.Header.isUnicode, row); switch (recipient.Type) { case Recipient.RecipientType.TO: To.Add(recipient); break; case Recipient.RecipientType.FROM: From.Add(recipient); break; case Recipient.RecipientType.CC: CC.Add(recipient); break; case Recipient.RecipientType.BCC: BCC.Add(recipient); break; } } break; case NDB.NID.NodeType.CONTENT_EX: // TODO: investigate what this is. /* * foreach (var nodeData in subNode.Value.NodeData) * { * ContentEx.Add(pst.Header.isUnicode * ? Encoding.Unicode.GetString(subNode.Value.NodeData[0].Data) * : Encoding.ASCII.GetString(subNode.Value.NodeData[0].Data)); * } */ break; default: // TODO: investigate what this is. /* * foreach (var nodeData in subNode.Value.NodeData) * { * string foo = pst.Header.isUnicode * ? Encoding.Unicode.GetString(subNode.Value.NodeData[0].Data) * : Encoding.ASCII.GetString(subNode.Value.NodeData[0].Data); * Console.WriteLine(foo); * } */ break; } } foreach (var prop in PC.Properties) { if (prop.Value.Data == null || prop.Value.Data.Length == 0) { continue; } switch (prop.Key) { case MessageProperty.Importance: Imporance = (Importance)BitConverter.ToInt16(prop.Value.Data, 0); break; case MessageProperty.Sensitivity: Sensitivity = (Sensitivity)BitConverter.ToInt16(prop.Value.Data, 0); break; case MessageProperty.Subject: Subject = pst.Header.isUnicode ? Encoding.Unicode.GetString(prop.Value.Data) : Encoding.ASCII.GetString(prop.Value.Data); if (Subject.Length > 0) { var chars = Subject.ToCharArray(); if (chars[0] == 0x1) { /* * // for skipping past "Re:", "Fwd:", etc. * var length = (int)chars[1]; * int i = 0; * if (length > 1) * i++; * SubjectPrefix = Subject.Substring(2, length-1); * Subject = Subject.Substring(2 + length-1); */ Subject = Subject.Substring(2); } } break; case MessageProperty.ClientSubmitTime: ClientSubmitTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case MessageProperty.SentRepresentingName: SentRepresentingName = pst.Header.isUnicode ? Encoding.Unicode.GetString(prop.Value.Data) : Encoding.ASCII.GetString(prop.Value.Data); break; case MessageProperty.ConversationTopic: ConversationTopic = pst.Header.isUnicode ? Encoding.Unicode.GetString(prop.Value.Data) : Encoding.ASCII.GetString(prop.Value.Data); break; case MessageProperty.MessageClass: MessageClass = pst.Header.isUnicode ? Encoding.Unicode.GetString(prop.Value.Data) : Encoding.ASCII.GetString(prop.Value.Data); break; case MessageProperty.SenderName: SenderName = pst.Header.isUnicode ? Encoding.Unicode.GetString(prop.Value.Data) : Encoding.ASCII.GetString(prop.Value.Data); break; case MessageProperty.MessageDeliveryTime: MessageDeliveryTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case MessageProperty.MessageFlags: MessageFlags = BitConverter.ToUInt32(prop.Value.Data, 0); Read = (MessageFlags & 0x1) != 0; Unsent = (MessageFlags & 0x8) != 0; Unmodified = (MessageFlags & 0x2) != 0; HasAttachments = (MessageFlags & 0x10) != 0; FromMe = (MessageFlags & 0x20) != 0; IsFAI = (MessageFlags & 0x40) != 0; NotifyReadRequested = (MessageFlags & 0x100) != 0; NotifyUnreadRequested = (MessageFlags & 0x200) != 0; EverRead = (MessageFlags & 0x400) != 0; break; case MessageProperty.MessageSize: MessageSize = BitConverter.ToUInt32(prop.Value.Data, 0); break; case MessageProperty.InternetArticleNumber: InternetArticleNumber = BitConverter.ToUInt32(prop.Value.Data, 0); break; case MessageProperty.AttributeHidden: AttributeHidden = prop.Value.Data[0] == 0x01; break; case MessageProperty.ReadOnly: ReadOnly = prop.Value.Data[0] == 0x01; break; case MessageProperty.CreationTime: CreationTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case MessageProperty.LastModificationTime: LastModificationTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case MessageProperty.CodePage: CodePage = BitConverter.ToUInt32(prop.Value.Data, 0); break; case MessageProperty.NonUnicodeCodePage: NonUnicodeCodePage = BitConverter.ToUInt32(prop.Value.Data, 0); break; default: break; } } }
public MapiItem(PSTFile pst, PropertyContext propertyContext) : base(pst, propertyContext) { }
public Message(uint NID, IPMItem item, PSTFile pst) { this._IPMItem = item; this.Data = BlockBO.GetNodeData(NID, pst); this.NID = NID; //this.MessagePC = new PropertyContext(this.Data); foreach(var subNode in this.Data.SubNodeData) { var temp = new NID(subNode.Key); switch(temp.Type) { case NDB.NID.NodeType.ATTACHMENT_TABLE: this.AttachmentTable = new TableContext(subNode.Value); break; case NDB.NID.NodeType.ATTACHMENT_PC: this.AttachmentPC = new PropertyContext(subNode.Value); this.Attachments = new List<Attachment>(); foreach(var row in this.AttachmentTable.RowMatrix.Rows) { this.Attachments.Add(new Attachment(row)); } break; case NDB.NID.NodeType.RECIPIENT_TABLE: this.RecipientTable = new TableContext(subNode.Value); foreach(var row in this.RecipientTable.RowMatrix.Rows) { var recipient = new Recipient(row); switch(recipient.Type) { case Recipient.RecipientType.TO: this.To.Add(recipient); break; case Recipient.RecipientType.FROM: this.From.Add(recipient); break; case Recipient.RecipientType.CC: this.CC.Add(recipient); break; case Recipient.RecipientType.BCC: this.BCC.Add(recipient); break; } } break; } } foreach(var prop in this._IPMItem.PC.Properties) { if (prop.Value.Data == null) continue; switch(prop.Key) { case 0x17: this.Imporance = (Importance) BitConverter.ToInt16(prop.Value.Data, 0); break; case 0x36: this.Sensitivity = (Sensitivity) BitConverter.ToInt16(prop.Value.Data, 0); break; case 0x37: this.Subject = Encoding.Unicode.GetString(prop.Value.Data); if (this.Subject.Length > 0) { var chars = this.Subject.ToCharArray(); if (chars[0] == 0x001) { var length = (int)chars[1]; int i = 0; if (length > 1) i++; this.SubjectPrefix = this.Subject.Substring(2, length-1); this.Subject = this.Subject.Substring(2 + length-1); } } break; case 0x39: this.ClientSubmitTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case 0x42: this.SentRepresentingName = Encoding.Unicode.GetString(prop.Value.Data); break; case 0x70: this.ConversationTopic = Encoding.Unicode.GetString(prop.Value.Data); break; case 0x1a: this.MessageClass = Encoding.Unicode.GetString(prop.Value.Data); break; case 0xc1a: this.SenderName = Encoding.Unicode.GetString(prop.Value.Data); break; case 0xe06: this.MessageDeliveryTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case 0xe07: this.MessageFlags = BitConverter.ToUInt32(prop.Value.Data, 0); this.Read = (this.MessageFlags & 0x1) != 0; this.Unsent = (this.MessageFlags & 0x8) != 0; this.Unmodified = (this.MessageFlags & 0x2) != 0; this.HasAttachments = (this.MessageFlags & 0x10) != 0; this.FromMe = (this.MessageFlags & 0x20) != 0; this.IsFAI = (this.MessageFlags & 0x40) != 0; this.NotifyReadRequested = (this.MessageFlags & 0x100) != 0; this.NotifyUnreadRequested = (this.MessageFlags & 0x200) != 0; this.EverRead = (this.MessageFlags & 0x400) != 0; break; case 0xe08: this.MessageSize = BitConverter.ToUInt32(prop.Value.Data, 0); break; case 0xe23: this.InternetArticalNumber = BitConverter.ToUInt32(prop.Value.Data, 0); break; case 0xe27: //unknown break; case 0xe29: //nextSentAccount, ignore this, string break; case 0xe62: //unknown break; case 0xe79: //trusted sender break; case 0x1000: this.BodyPlainText = Encoding.Unicode.GetString(prop.Value.Data); break; case 0x1009: this.BodyCompressedRTF = prop.Value.Data.RangeSubset(4, prop.Value.Data.Length - 4); break; case 0x1035: this.InternetMessageID = Encoding.Unicode.GetString(prop.Value.Data); break; case 0x10F3: this.UrlCompositeName = Encoding.Unicode.GetString(prop.Value.Data); break; case 0x10F4: this.AttributeHidden = prop.Value.Data[0] == 0x01; break; case 0x10F5: //unknown break; case 0x10F6: this.ReadOnly = prop.Value.Data[0] == 0x01; break; case 0x3007: this.CreationTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case 0x3008: this.LastModificationTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(prop.Value.Data, 0)); break; case 0x300B: //seach key break; case 0x3fDE: this.CodePage = BitConverter.ToUInt32(prop.Value.Data, 0); break; case 0x3ff1: //localeID break; case 0x3ff8: this.CreatorName = Encoding.Unicode.GetString(prop.Value.Data); break; case 0x3ff9: //creator entryid break; case 0x3ffa: //last modifier name break; case 0x3ffb: //last modifier entryid break; case 0x3ffd: this.NonUnicodeCodePage = BitConverter.ToUInt32(prop.Value.Data, 0); break; case 0x4019: //unknown break; case 0x401a: //sentrepresentingflags break; case 0x619: //userentryid break; default: break; } } }
public static NodeDataDTO GetNodeData(ulong nid, PSTFile pst) { var nodeBIDs = pst.GetNodeBIDs(nid); var mainData = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(nodeBIDs.Item1), pst); var subNodeData = new Dictionary<ulong,NodeDataDTO>(); if (nodeBIDs.Item2 != 0) subNodeData = BlockBO.GetSubNodeData(pst.GetBlockBBTEntry(nodeBIDs.Item2), pst); return new NodeDataDTO {NodeData = mainData, SubNodeData = subNodeData}; }
private static List<BlockDataDTO> GetXBlockData(XBLOCK xblock, PSTFile pst) { var ret = new List<BlockDataDTO>(); foreach(var bid in xblock.BIDEntries) { var bbtEntry = pst.GetBlockBBTEntry(bid); ret.AddRange(BlockBO.GetBBTEntryData(bbtEntry,pst)); } return ret; }
public static HN GetHeapNode(ulong NID, PSTFile pst) { return(new HN(BlockBO.GetNodeData(NID, pst))); }
public static void CryptPermute(byte[] pv, int cb, bool fEncrypt, PSTFile pst) { if (pst.Header.EncodingAlgotihm == PSTHeader.BlockEncoding.NONE) return; if (pst.Header.EncodingAlgotihm == PSTHeader.BlockEncoding.PERMUTE) { int idx = (fEncrypt ? 0 : 512); int temp = 0; for (int pvIndex = 0; pvIndex < cb; pvIndex++) { temp = pv[pvIndex]; temp = temp & 0xFF; pv[pvIndex] = mpbbCrypt[temp + idx]; } } }
//for a given bbt entry, retrieve the raw bytes associated with the BID //this includes retrieving data trees via xblocks public static List<BlockDataDTO> GetBBTEntryData(BBTENTRY entry, PSTFile pst) { var dataSize = entry.BlockByteCount; var blockSize = entry.BlockByteCount + 16; if (blockSize % 64 != 0) blockSize += 64 - (blockSize%64); List<BlockDataDTO> dataBlocks; /*if (isSubNode) { using (var viewer = PSTFile.PSTMMF.CreateViewAccessor((long)entry.BREF.IB, blockSize)) { var blockBytes = new byte[dataSize]; viewer.ReadArray(0, blockBytes, 0, dataSize); dataBlocks = new List<BlockDataDTO> {new BlockDataDTO {Data = blockBytes, PstOffset = entry.BREF.IB, BBTEntry = entry}}; return dataBlocks; } } else */ if (entry.Internal) { using(var viewer = pst.PSTMMF.CreateViewAccessor((long)entry.BREF.IB,blockSize)) { var blockBytes = new byte[dataSize]; viewer.ReadArray(0, blockBytes, 0, dataSize); var trailerBytes = new byte[16]; viewer.ReadArray(blockSize-16, trailerBytes, 0, 16); var trailer = new BlockTrailer(trailerBytes, 0); var dataBlockDTO = new BlockDataDTO { Data = blockBytes, PstOffset = entry.BREF.IB, CRCOffset = (uint)((long)entry.BREF.IB + (blockSize - 12)), BBTEntry = entry }; var type = blockBytes[0]; var level = blockBytes[1]; if (type == 2) //si or sl entry { return new List<BlockDataDTO> {dataBlockDTO}; } else if (type == 1) { if (blockBytes[1] == 0x01) //XBLOCK { var xblock = new XBLOCK(dataBlockDTO); return BlockBO.GetXBlockData(xblock, pst); } else //XXBLOCK { var xxblock = new XXBLOCK(dataBlockDTO); return BlockBO.GetXXBlockData(xxblock, pst); } } else { throw new NotImplementedException(); } } } else { using(var viewer = pst.PSTMMF.CreateViewAccessor((long)entry.BREF.IB,blockSize)) { var dataBytes = new byte[dataSize]; viewer.ReadArray(0, dataBytes, 0, dataSize); var trailerBytes = new byte[16]; viewer.ReadArray(blockSize-16, trailerBytes, 0, 16); var trailer = new BlockTrailer(trailerBytes, 0); dataBlocks = new List<BlockDataDTO> { new BlockDataDTO { Data = dataBytes, PstOffset = entry.BREF.IB, CRC32 = trailer.CRC, CRCOffset = (uint) (blockSize -12), BBTEntry = entry } }; } } for (int i = 0; i < dataBlocks.Count; i++) { var temp = dataBlocks[i].Data; DatatEncoder.CryptPermute(temp, temp.Length, false, pst); } return dataBlocks; }
public static NodeDataDTO GetNodeData(NBTENTRY entry, PSTFile pst) { var mainData = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(entry.BID_Data), pst); if (entry.BID_SUB != 0) { var subnodeData = BlockBO.GetSubNodeData(pst.GetBlockBBTEntry(entry.BID_SUB), pst); return new NodeDataDTO {NodeData = mainData, SubNodeData = subnodeData}; } return new NodeDataDTO {NodeData = mainData, SubNodeData = null}; }
private static Dictionary<ulong, NodeDataDTO> GetSIBlockData(SIBLOCK siblock, PSTFile pst) { var ret = new Dictionary<ulong, NodeDataDTO>(); foreach(var entry in siblock.Entries) { var curSLBlockBBT = pst.GetBlockBBTEntry(entry.SLBlockBID); var slblock = new SLBLOCK(BlockBO.GetBBTEntryData(curSLBlockBBT, pst)[0]); var data = BlockBO.GetSLBlockData(slblock, pst); foreach(var item in data) ret.Add(item.Key, item.Value); } return ret; }
//gets all the data for an SL block. an SL block points directly to all the immediate subnodes private static Dictionary<ulong, NodeDataDTO> GetSLBlockData(SLBLOCK slblock, PSTFile pst) { var ret = new Dictionary<ulong, NodeDataDTO>(); foreach(var entry in slblock.Entries) { //this data should represent the main data part of the subnode var data = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(entry.SubNodeBID), pst); var cur = new NodeDataDTO {NodeData = data}; ret.Add(entry.SubNodeNID, cur); //see if there are sub nodes of this current sub node if (entry.SubSubNodeBID != 0) //if there are subnodes, treat them like any other subnode cur.SubNodeData = GetSubNodeData(pst.GetBlockBBTEntry(entry.SubSubNodeBID), pst); } return ret; }
private static Dictionary<ulong, NodeDataDTO> GetSubNodeData(BBTENTRY entry, PSTFile pst) { var allData = BlockBO.GetBBTEntryData(entry, pst); var dataBlock = allData[0]; if (entry.Internal) { var type = dataBlock.Data[0]; var cLevel = dataBlock.Data[1]; if (cLevel == 0) //SLBlock, no intermediate { return BlockBO.GetSLBlockData(new SLBLOCK(dataBlock), pst); } else //SIBlock { return BlockBO.GetSIBlockData(new SIBLOCK(dataBlock), pst); } } else { throw new Exception("Whoops"); } }
static void Main(string[] args) { var sw = new Stopwatch(); sw.Start(); var pstPath = @"C:\test\[email protected]"; var logPath = @"C:\test\nidlog.txt"; var pstSize = new FileInfo(pstPath).Length *1.0 / 1024 / 1024; using (var file = new PSTFile(pstPath)) { Console.WriteLine("Magic value: " + file.Header.DWMagic); Console.WriteLine("Is Ansi? " + file.Header.IsANSI); var stack = new Stack <MailFolder>(); stack.Push(file.TopOfPST); var totalCount = 0; if (File.Exists(logPath)) { File.Delete(logPath); } using (var writer = new StreamWriter(logPath)) { while (stack.Count > 0) { var curFolder = stack.Pop(); foreach (var child in curFolder.SubFolders) { stack.Push(child); } var count = curFolder.ContentsTC.RowIndexBTH.Properties.Count; totalCount += count; Console.WriteLine(String.Join(" -> ", curFolder.Path) + " ({0} messages)", count); foreach (var ipmItem in curFolder) { if (ipmItem is Message) { var message = ipmItem as Message; Console.WriteLine(message.Subject); Console.WriteLine(message.Imporance); Console.WriteLine("Sender Name: " + message.SenderName); if (message.From.Count > 0) { Console.WriteLine("From: {0}", String.Join("; ", message.From.Select(r => r.EmailAddress))); } if (message.To.Count > 0) { Console.WriteLine("To: {0}", String.Join("; ", message.To.Select(r => r.EmailAddress))); } if (message.CC.Count > 0) { Console.WriteLine("CC: {0}", String.Join("; ", message.CC.Select(r => r.EmailAddress))); } if (message.BCC.Count > 0) { Console.WriteLine("BCC: {0}", String.Join("; ", message.BCC.Select(r => r.EmailAddress))); } writer.WriteLine(ByteArrayToString(BitConverter.GetBytes(message.NID))); } } } } sw.Stop(); Console.WriteLine("{0} messages total", totalCount); Console.WriteLine("Parsed {0} ({2:0.00} MB) in {1} milliseconds", Path.GetFileName(pstPath), sw.ElapsedMilliseconds, pstSize); //file.Header.NodeBT.Root.GetOffset(1); Console.Read(); } }
public IPMItem(PSTFile pst, uint nid) { this._nid = nid; this.PC = new PropertyContext(nid, pst); this.MessageClass = Encoding.Unicode.GetString(this.PC.Properties[0x1a].Data); }
public static HN GetHeapNode(ulong NID, PSTFile pst) { return new HN(BlockBO.GetNodeData(NID, pst)); }
public static NodeDataDTO GetNodeData(SLENTRY entry, PSTFile pst) { var mainData = BlockBO.GetBBTEntryData(pst.GetBlockBBTEntry(entry.SubNodeBID), pst); if (entry.SubSubNodeBID != 0) { var subNodeData = BlockBO.GetSubNodeData(pst.GetBlockBBTEntry(entry.SubSubNodeBID),pst); return new NodeDataDTO {NodeData = mainData, SubNodeData = subNodeData}; } return new NodeDataDTO {NodeData = mainData, SubNodeData = null}; }
private static List<BlockDataDTO> GetXXBlockData(XXBLOCK xxblock, PSTFile pst) { var ret = new List<BlockDataDTO>(); foreach(var bid in xxblock.XBlockBIDs) { var bbtEntry = pst.GetBlockBBTEntry(bid); var curXblockData = BlockBO.GetBBTEntryData(bbtEntry, pst); //var curXblockData = BlockBO.GetXBlockData(curXblock); foreach(var block in curXblockData) ret.Add(block); } return ret; }