private void AddRecipientToRecipientDisplayNameCache(LoadedItemPart itemPart)
 {
     foreach (KeyValuePair <string, Participant> keyValuePair in itemPart.DisplayNameToParticipant)
     {
         this.displayNameToParticipant[keyValuePair.Key] = keyValuePair.Value;
     }
 }
        public bool ConversationNodeContainedInChildren(IConversationTree conversationTree, IConversationTreeNode node)
        {
            if (node.HasChildren)
            {
                this.LoadItemParts(conversationTree, (from n in node.ChildNodes
                                                      select n.MainStoreObjectId).ToList <StoreObjectId>());
            }
            ItemPart itemPart = this.GetItemPart(conversationTree, node.MainStoreObjectId);

            if (itemPart != null && itemPart.Attachments != null && itemPart.Attachments.Count > 0)
            {
                return(false);
            }
            foreach (IConversationTreeNode conversationTreeNode in node.ChildNodes)
            {
                if (this.HasLoadedItemPart(conversationTreeNode.MainStoreObjectId))
                {
                    LoadedItemPart loadedItemPart = this.GetItemPart(conversationTree, node.MainStoreObjectId) as LoadedItemPart;
                    ExtractionData extractionData = null;
                    if (loadedItemPart.BodyFragmentInfo != null && this.IsBodyPartPresent(loadedItemPart.BodyFragmentInfo, node.StorePropertyBags[0], true, out extractionData))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        public ItemPart GetItemPart(IConversationTree conversationTree, StoreObjectId itemId)
        {
            IStorePropertyBag     propertyBag          = null;
            ItemPart              itemPart             = null;
            IConversationTreeNode conversationTreeNode = null;

            if (!conversationTree.TryGetConversationTreeNode(itemId, out conversationTreeNode) || !conversationTreeNode.TryGetPropertyBag(itemId, out propertyBag))
            {
                throw new ArgumentException("No ConversationTreeNode/PropertyBag can be found for the passed StoreObjectId");
            }
            if (!this.itemParts.TryGetValue(itemId, out itemPart))
            {
                this.LoadItemPart(conversationTree, propertyBag);
                itemPart = this.loadedItemParts[itemId];
            }
            if (itemPart is LoadedItemPart && !itemPart.DidLoadSucceed)
            {
                return(itemPart);
            }
            if (itemPart.UniqueFragmentInfo == null)
            {
                LoadedItemPart loadedItemPart = (LoadedItemPart)itemPart;
                ExtractionData extractionData;
                if (!this.CanSkipDiffing(conversationTree, loadedItemPart, out extractionData))
                {
                    BodyFragmentInfo parentBodyFragment = null;
                    if (conversationTreeNode.ParentNode.HasData)
                    {
                        StoreObjectId mainStoreObjectId = conversationTreeNode.ParentNode.MainStoreObjectId;
                        if (this.treeNodeBodyFragment.ContainsKey(mainStoreObjectId))
                        {
                            parentBodyFragment = this.treeNodeBodyFragment[mainStoreObjectId].Key;
                        }
                        else
                        {
                            LoadedItemPart loadedItemPart2 = null;
                            if (!this.loadedItemParts.TryGetValue(mainStoreObjectId, out loadedItemPart2))
                            {
                                IStorePropertyBag propertyBag2;
                                if (!conversationTreeNode.ParentNode.TryGetPropertyBag(mainStoreObjectId, out propertyBag2))
                                {
                                    throw new ArgumentException("No Property bag can be found for the passed StoreObjectId on the ParentNode");
                                }
                                this.LoadItemPart(conversationTree, propertyBag2);
                                loadedItemPart2 = this.loadedItemParts[mainStoreObjectId];
                            }
                            parentBodyFragment = loadedItemPart2.BodyFragmentInfo;
                        }
                    }
                    ConversationDataExtractor.DiffItemParts(parentBodyFragment, loadedItemPart);
                }
                else
                {
                    itemPart.UniqueFragmentInfo     = extractionData.ChildUniqueBody;
                    itemPart.DisclaimerFragmentInfo = extractionData.ChildDisclaimer;
                }
            }
            return(itemPart);
        }
        public bool IsBodyPartPresent(BodyFragmentInfo childBodyFragment, IStorePropertyBag parentPropertyBag, bool ignoreCache, out ExtractionData extractionData)
        {
            StoreObjectId objectId = ((VersionedId)parentPropertyBag.TryGetProperty(ItemSchema.Id)).ObjectId;
            KeyValuePair <ConversationBodyScanner, StoreObjectId> key = new KeyValuePair <ConversationBodyScanner, StoreObjectId>(childBodyFragment.BodyScanner, objectId);

            if (this.loadStatus.TryGetValue(key, out extractionData))
            {
                bool flag = extractionData != null && extractionData.BodyFragment != null;
                if (flag || !ignoreCache)
                {
                    return(flag);
                }
            }
            if (!ignoreCache && this.loadedItemParts.ContainsKey(objectId))
            {
                extractionData = new ExtractionData();
            }
            else
            {
                byte[] array = parentPropertyBag.TryGetProperty(ItemSchema.BodyTag) as byte[];
                if (array == null && ignoreCache)
                {
                    LoadedItemPart loadedItemPart = null;
                    if (this.loadedItemParts.TryGetValue(objectId, out loadedItemPart) && loadedItemPart.BodyFragmentInfo != null && loadedItemPart.BodyFragmentInfo.BodyTag != null)
                    {
                        array = loadedItemPart.BodyFragmentInfo.BodyTag.ToByteArray();
                    }
                }
                this.optimizationInfo.IncrementBodyTagMatchingAttempts();
                if (array != null)
                {
                    extractionData = new ExtractionData(childBodyFragment, BodyTagInfo.FromByteArray(array));
                    if (extractionData.BodyFragment != null)
                    {
                        this.loadStatus[key] = extractionData;
                        if (!extractionData.IsFormatReliable)
                        {
                            this.optimizationInfo.UpdateItemBodyFormatMismatched(objectId);
                            this.optimizationInfo.IncrementBodyTagMatchingIssues();
                        }
                    }
                    else
                    {
                        this.optimizationInfo.UpdateItemBodyTagMismatched(objectId);
                        this.optimizationInfo.IncrementBodyTagMatchingIssues();
                    }
                }
                else
                {
                    extractionData = new ExtractionData();
                    this.optimizationInfo.UpdateItemBodyTagNotPresent(objectId);
                    this.optimizationInfo.IncrementBodyTagMatchingIssues();
                }
            }
            this.loadStatus[key] = extractionData;
            return(extractionData.BodyFragment != null);
        }
        private bool CanSkipDiffing(IConversationTree conversationTree, LoadedItemPart loadedItemPart, out ExtractionData extractionData)
        {
            extractionData = null;
            IConversationTreeNode conversationTreeNode;

            if (conversationTree.TryGetConversationTreeNode(loadedItemPart.ObjectId, out conversationTreeNode))
            {
                IConversationTreeNode parentNode = conversationTreeNode.ParentNode;
                return(parentNode != null && parentNode.HasData && this.IsBodyPartPresent(loadedItemPart.BodyFragmentInfo, parentNode.StorePropertyBags[0], out extractionData));
            }
            return(false);
        }
 private static void DiffItemParts(BodyFragmentInfo parentBodyFragment, LoadedItemPart childItemPart)
 {
     if (childItemPart.UniqueFragmentInfo != null)
     {
         return;
     }
     if (parentBodyFragment != null)
     {
         BodyDiffer bodyDiffer = new BodyDiffer(childItemPart.BodyFragmentInfo, parentBodyFragment);
         childItemPart.UniqueFragmentInfo     = bodyDiffer.UniqueBodyPart;
         childItemPart.DisclaimerFragmentInfo = bodyDiffer.DisclaimerPart;
         return;
     }
     childItemPart.UniqueFragmentInfo     = childItemPart.BodyFragmentInfo.Trim();
     childItemPart.DisclaimerFragmentInfo = FragmentInfo.Empty;
 }
        private void RecursiveLoadBodyFragments(IConversationTree conversationTree, IConversationTreeNode treeNode, ICollection <StoreObjectId> itemPartsToLoad, out bool forceParentLoadBodyFragment)
        {
            IStorePropertyBag storePropertyBag = null;
            StoreObjectId     storeObjectId    = null;

            forceParentLoadBodyFragment = false;
            if (treeNode.HasData)
            {
                foreach (IStorePropertyBag storePropertyBag2 in treeNode.StorePropertyBags)
                {
                    StoreObjectId objectId = ((VersionedId)storePropertyBag2.TryGetProperty(ItemSchema.Id)).ObjectId;
                    storePropertyBag = storePropertyBag2;
                    storeObjectId    = objectId;
                    if (itemPartsToLoad == null || itemPartsToLoad.Contains(objectId))
                    {
                        forceParentLoadBodyFragment = true;
                        break;
                    }
                }
            }
            BodyFragmentInfo bodyFragmentInfo = null;
            bool             flag             = false;
            bool             flag2            = false;

            foreach (IConversationTreeNode conversationTreeNode in treeNode.ChildNodes)
            {
                ConversationTreeNode conversationTreeNode2 = (ConversationTreeNode)conversationTreeNode;
                bool flag3;
                this.RecursiveLoadBodyFragments(conversationTree, conversationTreeNode2, itemPartsToLoad, out flag3);
                flag2 = (flag2 || flag3);
                if (storePropertyBag != null)
                {
                    if (this.itemParts.ContainsKey(storeObjectId))
                    {
                        flag             = true;
                        bodyFragmentInfo = (this.treeNodeBodyFragment.ContainsKey(treeNode.MainStoreObjectId) ? this.treeNodeBodyFragment[treeNode.MainStoreObjectId].Key : null);
                    }
                    else if (this.treeNodeBodyFragment.ContainsKey(conversationTreeNode2.MainStoreObjectId))
                    {
                        ExtractionData extractionData;
                        this.IsBodyPartPresent(this.treeNodeBodyFragment[conversationTreeNode2.MainStoreObjectId].Key, storePropertyBag, out extractionData);
                        if (extractionData != null && extractionData.BodyFragment != null)
                        {
                            if (!flag && extractionData.IsFormatReliable)
                            {
                                bodyFragmentInfo = extractionData.BodyFragment;
                                flag             = true;
                            }
                            else if (bodyFragmentInfo == null)
                            {
                                bodyFragmentInfo = extractionData.BodyFragment;
                            }
                        }
                    }
                }
            }
            if (!treeNode.HasData)
            {
                return;
            }
            bool flag4 = false;

            if (itemPartsToLoad != null && itemPartsToLoad.Contains(storeObjectId) && !flag)
            {
                flag4 = true;
            }
            else if (bodyFragmentInfo == null && (forceParentLoadBodyFragment || flag2))
            {
                flag4 = true;
            }
            if (flag4 && !this.loadedItemParts.ContainsKey(storeObjectId))
            {
                this.LoadItemPart(conversationTree, storePropertyBag);
            }
            if (this.loadedItemParts.ContainsKey(storeObjectId))
            {
                LoadedItemPart loadedItemPart = this.loadedItemParts[storeObjectId];
                if (this.InternalHasIrmFailed(storeObjectId))
                {
                    bodyFragmentInfo = null;
                }
                else
                {
                    bodyFragmentInfo = loadedItemPart.BodyFragmentInfo;
                    flag             = true;
                }
            }
            if (bodyFragmentInfo != null)
            {
                this.treeNodeBodyFragment[treeNode.MainStoreObjectId] = new KeyValuePair <BodyFragmentInfo, bool>(bodyFragmentInfo, flag);
            }
        }
        private void LoadItemPart(IConversationTree conversationTree, IStorePropertyBag propertyBag)
        {
            StoreObjectId objectId = ((VersionedId)propertyBag.TryGetProperty(ItemSchema.Id)).ObjectId;

            if (this.loadedItemParts.ContainsKey(objectId))
            {
                return;
            }
            IConversationTreeNode treeNode = null;

            if (!conversationTree.TryGetConversationTreeNode(objectId, out treeNode))
            {
                throw new ArgumentException("No ConversationTreeNode can be found for the passed StorePropertyBag");
            }
            LoadItemEventArgs loadItemEventArgs = new LoadItemEventArgs(treeNode, propertyBag);

            PropertyDefinition[] array = null;
            if (this.OnBeforeItemLoad != null)
            {
                this.OnBeforeItemLoad(this, loadItemEventArgs);
                if (loadItemEventArgs.OpportunisticLoadPropertyDefinitions != null && loadItemEventArgs.MessagePropertyDefinitions != null)
                {
                    array = new PropertyDefinition[loadItemEventArgs.OpportunisticLoadPropertyDefinitions.Length + loadItemEventArgs.MessagePropertyDefinitions.Length];
                    loadItemEventArgs.MessagePropertyDefinitions.CopyTo(array, 0);
                    loadItemEventArgs.OpportunisticLoadPropertyDefinitions.CopyTo(array, loadItemEventArgs.MessagePropertyDefinitions.Length);
                }
                else if (loadItemEventArgs.OpportunisticLoadPropertyDefinitions != null)
                {
                    array = loadItemEventArgs.OpportunisticLoadPropertyDefinitions;
                }
                else
                {
                    array = loadItemEventArgs.MessagePropertyDefinitions;
                }
            }
            LoadedItemPart loadedItemPart = this.itemPartLoader.Load(propertyBag[ItemSchema.Id] as StoreId, propertyBag, loadItemEventArgs.HtmlStreamOptionCallback, array, this.bytesLoadedForConversation, this.isSmimeSupported, this.domainName);

            if (loadedItemPart.DidLoadSucceed)
            {
                this.bytesLoadedForConversation += loadedItemPart.BytesLoaded;
            }
            this.loadedItemParts.Add(objectId, loadedItemPart);
            this.AddRecipientToRecipientDisplayNameCache(this.loadedItemParts[objectId]);
            this.optimizationInfo.UpdateItemOpened(objectId);
            if (propertyBag.TryGetProperty(InternalSchema.MapiHasAttachment).Equals(true))
            {
                this.optimizationInfo.UpdateItemMapiAttachmentPresent(objectId);
                if (propertyBag.TryGetProperty(ItemSchema.HasAttachment).Equals(true))
                {
                    this.optimizationInfo.UpdateItemAttachmentPresent(objectId);
                }
            }
            if (!this.itemParts.ContainsKey(objectId))
            {
                this.itemParts.Add(objectId, this.loadedItemParts[objectId]);
                return;
            }
            this.loadedItemParts[objectId].UniqueFragmentInfo     = this.itemParts[objectId].UniqueFragmentInfo;
            this.loadedItemParts[objectId].DisclaimerFragmentInfo = this.itemParts[objectId].DisclaimerFragmentInfo;
            this.itemParts[objectId] = this.loadedItemParts[objectId];
        }