using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace Rssdp { /// /// Represents a custom HTTP header sent on device search response or notification messages. /// public sealed class CustomHttpHeader { #region Fields private string _Name; private string _Value; #endregion #region Constructors /// /// Full constructor. /// /// The field name of the header. /// The value of the header /// /// As per RFC 822 and 2616, the name must contain only printable ASCII characters (33-126) excluding colon (:). The value may contain any ASCII characters except carriage return or line feed. /// /// Thrown if the name is null. /// Thrown if the name is an empty value, or contains an invalid character. Also thrown if the value contains a \r or \n character. public CustomHttpHeader(string name, string value) { Name = name; Value = value; } #endregion #region Public Properties /// /// Return the name of this header. /// public string Name { get { return _Name; } private set { EnsureValidName(value); _Name = value; } } /// /// Returns the value of this header. /// public string Value { get { return _Value; } private set { EnsureValidValue(value); _Value = value; } } #endregion #region Overrides /// /// Returns the header formatted for use in an HTTP message. /// /// A string representing this header in the format of 'name: value'. public override string ToString() { return this.Name + ": " + this.Value; } #endregion #region Private Methods private static void EnsureValidName(string name) { if (name == null) throw new ArgumentNullException(nameof(name), "Name cannot be null."); if (name.Length == 0) throw new ArgumentException("Name cannot be blank.", nameof(name)); foreach (var c in name) { var b = (byte)c; if (c == ':' || b < 33 || b > 126) throw new ArgumentException("Name contains illegal characters.", nameof(name)); } } private static void EnsureValidValue(string value) { if (String.IsNullOrEmpty(value)) return; if (value.Contains("\r") || value.Contains("\n")) throw new ArgumentException("Invalid value.", nameof(value)); } #endregion } /// /// Represents a collection of custom HTTP headers, keyed by name. /// public class CustomHttpHeadersCollection : IEnumerable { #region Fields private IDictionary _Headers; #endregion #region Constructors /// /// Default constructor. /// public CustomHttpHeadersCollection() { _Headers = new Dictionary(); } /// /// Full constructor. /// /// Specifies the initial capacity of the collection. public CustomHttpHeadersCollection(int capacity) { _Headers = new Dictionary(capacity); } #endregion #region Public Methpds /// /// Adds a instance to the collection. /// /// The instance to add to the collection. /// /// /// /// Thrown if is null. public void Add(CustomHttpHeader header) { if (header == null) throw new ArgumentNullException(nameof(header)); lock (_Headers) { _Headers.Add(header.Name, header); } } #region Remove Overloads /// /// Removes the specified header instance from the collection. /// /// The instance to remove from the collection. /// /// Only removes the specified header if that instance was in the collection, if another header with the same name exists in the collection it is not removed. /// /// True if an item was removed from the collection, otherwise false (because it did not exist or was not the same instance). /// /// Thrown if the is null. public bool Remove(CustomHttpHeader header) { if (header == null) throw new ArgumentNullException(nameof(header)); lock (_Headers) { if (_Headers.ContainsKey(header.Name) && _Headers[header.Name] == header) return _Headers.Remove(header.Name); } return false; } /// /// Removes the property with the specified key ( from the collection. /// /// The name of the instance to remove from the collection. /// True if an item was removed from the collection, otherwise false (because no item exists in the collection with that key). /// Thrown if the argument is null or empty string. public bool Remove(string headerName) { if (String.IsNullOrEmpty(headerName)) throw new ArgumentException("headerName cannot be null or empty.", nameof(headerName)); lock (_Headers) { return _Headers.Remove(headerName); } } #endregion /// /// Returns a boolean indicating whether or not the specified instance is in the collection. /// /// An instance to check the collection for. /// True if the specified instance exists in the collection, otherwise false. public bool Contains(CustomHttpHeader header) { if (header == null) throw new ArgumentNullException(nameof(header)); lock (_Headers) { if (_Headers.ContainsKey(header.Name)) return _Headers[header.Name] == header; } return false; } /// /// Returns a boolean indicating whether or not a instance with the specified full name value exists in the collection. /// /// A string containing the full name of the instance to check for. /// True if an item with the specified full name exists in the collection, otherwise false. public bool Contains(string headerName) { if (String.IsNullOrEmpty(headerName)) throw new ArgumentException("headerName cannot be null or empty.", nameof(headerName)); lock (_Headers) { return _Headers.ContainsKey(headerName); } } #endregion #region Public Properties /// /// Returns the number of items in the collection. /// public int Count { get { return _Headers.Count; } } /// /// Returns the instance from the collection that has the specified value. /// /// The full name of the property to return. /// A instance from the collection. /// Thrown if no item exists in the collection with the specified value. public CustomHttpHeader this[string name] { get { return _Headers[name]; } } #endregion #region IEnumerable Members /// /// Returns an enumerator of instances in this collection. /// /// An enumerator of instances in this collection. public IEnumerator GetEnumerator() { lock (_Headers) { return _Headers.Values.GetEnumerator(); } } /// /// Returns an enumerator of instances in this collection. /// /// An enumerator of instances in this collection. IEnumerator IEnumerable.GetEnumerator() { lock (_Headers) { return _Headers.Values.GetEnumerator(); } } #endregion } }