// // BodyPartCollection.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2020 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Linq; using System.Collections; using System.Collections.Generic; using MimeKit.Utils; namespace MailKit { /// /// A collection. /// /// /// A collection. /// public class BodyPartCollection : ICollection { readonly List collection = new List (); /// /// Initializes a new instance of the class. /// /// /// Creates a new . /// public BodyPartCollection () { } /// /// Get the number of body parts in the collection. /// /// /// Gets the number of body parts in the collection. /// /// The count. public int Count { get { return collection.Count; } } /// /// Get whether or not this body part collection is read only. /// /// /// Gets whether or not this body part collection is read only. /// /// true if this collection is read only; otherwise, false. public bool IsReadOnly { get { return false; } } /// /// Add the specified body part to the collection. /// /// /// Adds the specified body part to the collection. /// /// The body part. /// /// is null. /// public void Add (BodyPart part) { if (part == null) throw new ArgumentNullException (nameof (part)); collection.Add (part); } /// /// Clears the body part collection. /// /// /// Removes all of the body parts from the collection. /// public void Clear () { collection.Clear (); } /// /// Checks if the collection contains the specified body part. /// /// /// Determines whether or not the collection contains the specified body part. /// /// true if the specified body part exists; otherwise false. /// The body part. /// /// is null. /// public bool Contains (BodyPart part) { if (part == null) throw new ArgumentNullException (nameof (part)); return collection.Contains (part); } /// /// Copies all of the body parts in the collection to the specified array. /// /// /// Copies all of the body parts within the collection into the array, /// starting at the specified array index. /// /// The array. /// The array index. /// /// is null. /// /// /// is out of range. /// public void CopyTo (BodyPart[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException (nameof (array)); if (arrayIndex < 0 || arrayIndex + Count > array.Length) throw new ArgumentOutOfRangeException (nameof (arrayIndex)); collection.CopyTo (array, arrayIndex); } /// /// Removes the specified body part. /// /// /// Removes the specified body part. /// /// true if the body part was removed; otherwise false. /// The body part. /// /// is null. /// public bool Remove (BodyPart part) { if (part == null) throw new ArgumentNullException (nameof (part)); return collection.Remove (part); } /// /// Get the body part at the specified index. /// /// /// Gets the body part at the specified index. /// /// The body part at the specified index. /// The index. /// /// is out of range. /// public BodyPart this [int index] { get { if (index < 0 || index >= collection.Count) throw new ArgumentOutOfRangeException (nameof (index)); return collection[index]; } } /// /// Gets the index of the body part matching the specified URI. /// /// /// Finds the index of the body part matching the specified URI, if it exists. /// If the URI scheme is "cid", then matching is performed based on the Content-Id header /// values, otherwise the Content-Location headers are used. If the provided URI is absolute and a child /// part's Content-Location is relative, then then the child part's Content-Location URI will be combined /// with the value of its Content-Base header, if available, otherwise it will be combined with the /// multipart/related part's Content-Base header in order to produce an absolute URI that can be /// compared with the provided absolute URI. /// /// The index of the part matching the specified URI if found; otherwise -1. /// The URI of the body part. /// /// is null. /// public int IndexOf (Uri uri) { if (uri == null) throw new ArgumentNullException (nameof (uri)); bool cid = uri.IsAbsoluteUri && uri.Scheme.ToLowerInvariant () == "cid"; for (int index = 0; index < Count; index++) { var bodyPart = this[index] as BodyPartBasic; if (bodyPart == null) continue; if (uri.IsAbsoluteUri) { if (cid) { if (!string.IsNullOrEmpty (bodyPart.ContentId)) { // Note: we might have a Content-Id in the form "", so attempt to decode it var id = MimeUtils.EnumerateReferences (bodyPart.ContentId).FirstOrDefault () ?? bodyPart.ContentId; if (id == uri.AbsolutePath) return index; } } else if (bodyPart.ContentLocation != null) { if (!bodyPart.ContentLocation.IsAbsoluteUri) continue; if (bodyPart.ContentLocation == uri) return index; } } else if (bodyPart.ContentLocation == uri) { return index; } } return -1; } #region IEnumerable implementation /// /// Get the body part enumerator. /// /// /// Gets the body part enumerator. /// /// The enumerator. public IEnumerator GetEnumerator () { return collection.GetEnumerator (); } #endregion #region IEnumerable implementation /// /// Get the body part enumerator. /// /// /// Gets the body part enumerator. /// /// The enumerator. IEnumerator IEnumerable.GetEnumerator () { return GetEnumerator (); } #endregion } }