Beispiel #1
0
        /// <summary>
        /// Create a cookie collection from a cookie header.
        /// </summary>
        /// <param name="header">Http cookie header.</param>
        /// <returns>Cookie collection.</returns>
        public static List <DreamCookie> ParseCookieHeader(string header)
        {
            List <DreamCookie> result = new List <DreamCookie>();

            if (string.IsNullOrEmpty(header))
            {
                return(result);
            }
            int    index = 0;
            string name;
            string value;

            if (!ParseNameValue(out name, out value, header, ref index, false))
            {
                return(result);
            }

            // check if we read the cookie version information
            if (string.Compare(name, "$Version", true) != 0)
            {
                // we read something else; let's forget that we read it
                index = 0;
            }
            while (index < header.Length - 1)
            {
                DreamCookie cookie = ParseCookie(header, ref index);
                if (cookie != null)
                {
                    result.Add(cookie);
                }
            }
            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Update the jar with a cookie.
        /// </summary>
        /// <param name="cookie">Cookie to store.</param>
        /// <param name="uri">Uri this cookie applies to.</param>
        public void Update(DreamCookie cookie, XUri uri)
        {
            List <DreamCookie> list = new List <DreamCookie>();

            list.Add(cookie);
            Update(list, uri);
        }
Beispiel #3
0
        private void Insert(DreamCookie updatedCookie, string[] segments, int depth)
        {
            // find leaf node
            if (depth < segments.Length)
            {
                if (_jars == null)
                {
                    _jars = new Dictionary <string, DreamCookieJar>(StringComparer.OrdinalIgnoreCase);
                }
                DreamCookieJar subjar;
                if (!_jars.TryGetValue(segments[depth], out subjar))
                {
                    subjar = new DreamCookieJar();
                    _jars.Add(segments[depth], subjar);
                }
                subjar.Insert(updatedCookie, segments, depth + 1);
            }
            else
            {
                if (_cookies == null)
                {
                    _cookies = new List <DreamCookie>();
                }
                List <DreamCookie> expired = new List <DreamCookie>();
                for (int i = 0; i < _cookies.Count; ++i)
                {
                    DreamCookie cookie = _cookies[i];

                    // check if cookie is expired; if so, remove it
                    if (cookie.Expired)
                    {
                        expired.Add(cookie);
                        continue;
                    }

                    // TODO (steveb): we need to add support for '.' prefixes on the domain name

                    // check if cookie matches the expired cookie
                    if (StringUtil.EqualsInvariantIgnoreCase(cookie.Domain, updatedCookie.Domain) && StringUtil.EqualsInvariantIgnoreCase(cookie.Name, updatedCookie.Name) && (cookie.Secure == updatedCookie.Secure))
                    {
                        _cookies[i] = updatedCookie;
                        return;
                    }
                }
                foreach (DreamCookie cookie in expired)
                {
                    _cookies.Remove(cookie);
                }
                _cookies.Add(updatedCookie);
            }
        }
Beispiel #4
0
        private void Delete(DreamCookie expiredCookie, string[] segments, int depth)
        {
            // find leaf node
            if (depth < segments.Length)
            {
                if (_jars != null)
                {
                    DreamCookieJar subjar;
                    if (_jars.TryGetValue(segments[depth], out subjar))
                    {
                        subjar.Delete(expiredCookie, segments, depth + 1);
                        if (subjar.IsEmpty)
                        {
                            _jars.Remove(segments[depth]);
                        }
                    }
                }
            }
            else if (_cookies != null)
            {
                List <DreamCookie> expired = new List <DreamCookie>();
                foreach (DreamCookie cookie in _cookies)
                {
                    // check if cookie is expired; if so, remove it
                    if (cookie.Expired)
                    {
                        expired.Add(cookie);
                        continue;
                    }

                    // TODO (steveb): we need to add support for '.' prefixes on the domain name

                    // check if cookie matches the expired cookie
                    if (StringUtil.EqualsInvariantIgnoreCase(cookie.Domain, expiredCookie.Domain) && StringUtil.EqualsInvariantIgnoreCase(cookie.Name, expiredCookie.Name) && (cookie.Secure == expiredCookie.Secure))
                    {
                        expired.Add(cookie);
                        continue;
                    }
                }
                foreach (DreamCookie cookie in expired)
                {
                    _cookies.Remove(cookie);
                }
            }
        }
Beispiel #5
0
        //--- Class Methods ---

        /// <summary>
        /// Gets the matching cookie with the longest path from a collection of cookies.
        /// </summary>
        /// <param name="cookies">Collection of cookies.</param>
        /// <param name="name">Cookie name.</param>
        /// <returns>Matching cookie with longest path, or null if no cookies matched.</returns>
        public static DreamCookie GetCookie(List <DreamCookie> cookies, string name)
        {
            // TODO (steveb): consider making this an extension method

            // TODO (arnec): Should also match on domain/path as sanity check
            DreamCookie result        = null;
            int         maxPathLength = -1;

            foreach (DreamCookie cookie in cookies)
            {
                int length = cookie.Path == null ? 0 : cookie.Path.Length;
                if ((cookie.Name != name) || (length <= maxPathLength))
                {
                    continue;
                }
                maxPathLength = length;
                result        = cookie;
            }
            return(result);
        }
Beispiel #6
0
 //--- Methods ---
 /// <summary>
 /// Compare <see cref="DreamCookie"/> instances for identical content.
 /// </summary>
 /// <param name="cookie">Cookie to compare.</param>
 /// <returns><see langword="True"/> if the cookies are the same.</returns>
 public bool Equals(DreamCookie cookie)
 {
     return ToString().Equals(cookie.ToString());
 }
Beispiel #7
0
 public void With_and_without_cookiejar()
 {
     DreamCookie global = new DreamCookie("test", "global", new XUri("http://baz.com/foo"));
     List<DreamCookie> globalCollection = new List<DreamCookie>();
     globalCollection.Add(global);
     Plug.GlobalCookies.Update(globalCollection, null);
     DreamCookie local = new DreamCookie("test", "local", new XUri("http://baz.com/foo"));
     List<DreamCookie> localCollection = new List<DreamCookie>();
     localCollection.Add(local);
     DreamCookieJar localJar = new DreamCookieJar();
     localJar.Update(localCollection, null);
     Plug globalPlug = Plug.New("http://baz.com/foo/bar");
     Plug localPlug = globalPlug.WithCookieJar(localJar);
     Plug globalPlug2 = localPlug.WithoutCookieJar();
     Assert.AreEqual("global", globalPlug.CookieJar.Fetch(globalPlug.Uri)[0].Value);
     Assert.AreEqual("local", localPlug.CookieJar.Fetch(localPlug.Uri)[0].Value);
     Assert.AreEqual("global", globalPlug2.CookieJar.Fetch(globalPlug2.Uri)[0].Value);
 }
Beispiel #8
0
 public void TestCookie2()
 {
     Plug test = _host.At("test");
     DreamMessage request = DreamMessage.Ok();
     DreamCookie cookie = new DreamCookie("test-cookie", "test-value", null);
     request.Cookies.Add(cookie);
     DreamMessage response = test.Post(request);
     Assert.AreEqual(DreamStatus.Ok, response.Status);
     Assert.IsFalse(response.ToDocument()["body"].IsEmpty);
     Assert.AreEqual(cookie.ToString(), DreamCookie.ParseCookie(response.ToDocument()["headers/cookie"]).ToString());
 }
Beispiel #9
0
 //--- Constructors ---
 /// <summary>
 /// Create a new dispatcher.
 /// </summary>
 /// <param name="config">Configuration instance injected from pub sub service.</param>
 public Dispatcher(DispatcherConfig config)
 {
     _owner = config.ServiceUri.AsServerUri();
     _serviceKeySetCookie = config.ServiceAccessCookie;
     _combinedSet = new PubSubSubscriptionSet(_owner, 0, _serviceKeySetCookie);
     _dispatchQueue = new ProcessingQueue<DispatcherEvent>(DispatchFromQueue, 10);
 }
Beispiel #10
0
 //--- Methods ---
 /// <summary>
 /// Compare <see cref="DreamCookie"/> instances for identical content.
 /// </summary>
 /// <param name="cookie">Cookie to compare.</param>
 /// <returns><see langword="True"/> if the cookies are the same.</returns>
 public bool Equals(DreamCookie cookie)
 {
     return(ToString().Equals(cookie.ToString()));
 }
Beispiel #11
0
        /// <summary>
        /// Update the jar with a collection cookies.
        /// </summary>
        /// <param name="collection">List of cookies to store.</param>
        /// <param name="uri">Uri cookies apply to.</param>
        public void Update(List <DreamCookie> collection, XUri uri)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }

            // process all cookies
            foreach (DreamCookie c in collection)
            {
                DreamCookie cookie = c;
                if (!string.IsNullOrEmpty(cookie.Name))
                {
                    string[] segments = null;
                    if (uri != null)
                    {
                        // set default domain if needed
                        if (string.IsNullOrEmpty(cookie.Domain))
                        {
                            cookie = cookie.WithHostPort(uri.HostPort);
                        }
                        else if (!StringUtil.EqualsInvariantIgnoreCase(cookie.Domain, uri.HostPort))
                        {
                            // domain doesn't match, ignore cookie
                            continue;
                        }

                        // set default path if needed
                        if (string.IsNullOrEmpty(cookie.Path))
                        {
                            cookie   = cookie.WithPath(uri.Path);
                            segments = uri.Segments;
                        }
                        else
                        {
                            segments = cookie.Uri == null ? new string[0] : cookie.Uri.Segments;
                            if (!uri.PathStartsWith(segments))
                            {
                                // path doesn't match ignore cookie
                                continue;
                            }
                        }
                    }
                    if (!string.IsNullOrEmpty(cookie.Path) && !string.IsNullOrEmpty(cookie.Domain))
                    {
                        if (segments == null)
                        {
                            segments = cookie.Uri == null ? new string[0] : cookie.Uri.Segments;
                        }
                        if (cookie.Expired)
                        {
                            Delete(cookie, segments, 0);
                        }
                        else
                        {
                            Insert(cookie, segments, 0);
                        }
                    }
                }
            }
        }
Beispiel #12
0
        //--- Constructors ---
        /// <summary>
        /// Create a new subscription set.
        /// </summary>
        /// <param name="owner">Owner uri.</param>
        /// <param name="version">Version serial number.</param>
        /// <param name="cookie">Pub sub location access cookie.</param>
        /// <param name="childSubscriptions">Subscriptions.</param>
        public PubSubSubscriptionSet(XUri owner, long version, DreamCookie cookie, params PubSubSubscription[] childSubscriptions)
        {
            Owner = owner;
            Version = version;
            Dictionary<string, PubSubSubscription> subs = new Dictionary<string, PubSubSubscription>();
            foreach(var sub in childSubscriptions) {
                foreach(var channel in sub.Channels) {
                    if(channel.Scheme == "pubsub") {

                        // pubsub scheme is for PubSubService internal use only, so it should never be aggregated
                        continue;
                    }
                    XUri[] resources = (sub.Resources == null || sub.Resources.Length == 0) ? new XUri[] { null } : sub.Resources;
                    foreach(XUri resource in resources) {
                        PubSubSubscription combo;
                        string key = channel + ":" + resource;
                        subs.TryGetValue(key, out combo);
                        subs[key] = PubSubSubscription.MergeForChannelAndResource(channel, resource, this, cookie, sub, combo);
                    }
                }
            }
            Subscriptions = new PubSubSubscription[subs.Count];
            subs.Values.CopyTo(Subscriptions, 0);
            MaxFailures = MAX_FAILURES;
        }
Beispiel #13
0
 /// <summary>
 /// Update the jar with a cookie.
 /// </summary>
 /// <param name="cookie">Cookie to store.</param>
 /// <param name="uri">Uri this cookie applies to.</param>
 public void Update(DreamCookie cookie, XUri uri)
 {
     List<DreamCookie> list = new List<DreamCookie>();
     list.Add(cookie);
     Update(list, uri);
 }
Beispiel #14
0
        private void Delete(DreamCookie expiredCookie, string[] segments, int depth)
        {
            // find leaf node
            if(depth < segments.Length) {
                if(_jars != null) {
                    DreamCookieJar subjar;
                    if(_jars.TryGetValue(segments[depth], out subjar)) {
                        subjar.Delete(expiredCookie, segments, depth + 1);
                        if(subjar.IsEmpty) {
                            _jars.Remove(segments[depth]);
                        }
                    }
                }
            } else if(_cookies != null) {
                List<DreamCookie> expired = new List<DreamCookie>();
                foreach(DreamCookie cookie in _cookies) {

                    // check if cookie is expired; if so, remove it
                    if(cookie.Expired) {
                        expired.Add(cookie);
                        continue;
                    }

                    // TODO (steveb): we need to add support for '.' prefixes on the domain name

                    // check if cookie matches the expired cookie
                    if(StringUtil.EqualsInvariantIgnoreCase(cookie.Domain, expiredCookie.Domain) && StringUtil.EqualsInvariantIgnoreCase(cookie.Name, expiredCookie.Name) && (cookie.Secure == expiredCookie.Secure)) {
                        expired.Add(cookie);
                        continue;
                    }
                }
                foreach(DreamCookie cookie in expired) {
                    _cookies.Remove(cookie);
                }
            }
        }
Beispiel #15
0
        private void Insert(DreamCookie updatedCookie, string[] segments, int depth)
        {
            // find leaf node
            if(depth < segments.Length) {
                if(_jars == null) {
                    _jars = new Dictionary<string, DreamCookieJar>(StringComparer.OrdinalIgnoreCase);
                }
                DreamCookieJar subjar;
                if(!_jars.TryGetValue(segments[depth], out subjar)) {
                    subjar = new DreamCookieJar();
                    _jars.Add(segments[depth], subjar);
                }
                subjar.Insert(updatedCookie, segments, depth + 1);
            } else {
                if(_cookies == null) {
                    _cookies = new List<DreamCookie>();
                }
                List<DreamCookie> expired = new List<DreamCookie>();
                for(int i = 0; i < _cookies.Count; ++i) {
                    DreamCookie cookie = _cookies[i];

                    // check if cookie is expired; if so, remove it
                    if(cookie.Expired) {
                        expired.Add(cookie);
                        continue;
                    }

                    // TODO (steveb): we need to add support for '.' prefixes on the domain name

                    // check if cookie matches the expired cookie
                    if(StringUtil.EqualsInvariantIgnoreCase(cookie.Domain, updatedCookie.Domain) && StringUtil.EqualsInvariantIgnoreCase(cookie.Name, updatedCookie.Name) && (cookie.Secure == updatedCookie.Secure)) {
                        _cookies[i] = updatedCookie;
                        return;
                    }
                }
                foreach(DreamCookie cookie in expired) {
                    _cookies.Remove(cookie);
                }
                _cookies.Add(updatedCookie);
            }
        }
Beispiel #16
0
        /// <summary>
        /// Create a subscription from a subscription document.
        /// </summary>
        /// <param name="sub">Subscription document.</param>
        /// <param name="owner">Owning set.</param>
        public PubSubSubscription(XDoc sub, PubSubSubscriptionSet owner)
        {
            Owner = owner;
            // sanity check the input
            XDoc channels = sub["channel"];
            if(channels.IsEmpty) {
                throw new ArgumentException("<subscription> must have at least one <channel>");
            }
            XDoc filter = sub["filter"];
            if(filter.ListLength > 1) {
                throw new ArgumentException("<subscription> must have zero or one <filter>");
            }
            XDoc proxy = sub["uri.proxy"];
            if(proxy.ListLength > 1) {
                throw new ArgumentException("<subscription> must have zero or one <uri.proxy>");
            }
            XDoc recipients = sub["recipient"];
            if(recipients.IsEmpty) {
                throw new ArgumentException("<subscription> must have at least one valid <recipient>");
            }
            if(recipients.ListLength > 1 && proxy.ListLength == 0) {
                throw new ArgumentException("<subscription> must include <uri.proxy> if there is more than one <recipient>");
            }

            // create our internal representation
            try {
                Id = sub["@id"].Contents;
                if(string.IsNullOrEmpty(Id)) {
                    Id = Guid.NewGuid().ToString();
                }
                XDoc cookie = sub["set-cookie"];
                if(!cookie.IsEmpty) {
                    Cookie = DreamCookie.ParseSetCookie(cookie);
                }
                List<XUri> channelList = new List<XUri>();
                foreach(XDoc c in channels) {
                    channelList.Add(c.AsUri);
                }
                Channels = channelList.ToArray();
                List<XUri> resourceList = new List<XUri>();
                foreach(XDoc r in sub["uri.resource"]) {
                    resourceList.Add(r.AsUri);
                }
                Resources = resourceList.ToArray();
                if(proxy.IsEmpty) {
                    Destination = new DispatcherRecipient(recipients).Uri;
                } else {
                    Destination = proxy.AsUri;
                    _isProxy = true;
                }
                List<DispatcherRecipient> recipientList = new List<DispatcherRecipient>();
                foreach(XDoc recipient in recipients) {
                    recipientList.Add(new DispatcherRecipient(recipient));
                }
                Recipients = recipientList.ToArray();
            } catch(Exception e) {
                throw new ArgumentException("Unable to parse subscription: " + e.Message, e);
            }
        }
Beispiel #17
0
 //--- Class Methods ---
 /// <summary>
 /// Merge two subscriptions on matchine channel and resource.
 /// </summary>
 /// <param name="channel">Common channel.</param>
 /// <param name="resource">Common resource.</param>
 /// <param name="owner">Common owner.</param>
 /// <param name="cookie">Subscription set cookie.</param>
 /// <param name="first">First subscription to merge.</param>
 /// <param name="second">Second subscription to merge.</param>
 /// <returns></returns>
 public static PubSubSubscription MergeForChannelAndResource(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second)
 {
     return new PubSubSubscription(channel, resource, owner, cookie, first, second);
 }
Beispiel #18
0
 //--- Constructors ---
 private PubSubSubscription(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second)
 {
     if(channel == null) {
         throw new ArgumentNullException("channel");
     }
     Channels = new[] { channel };
     Resources = resource == null ? new XUri[0] : new[] { resource };
     Id = Guid.NewGuid().ToString();
     Owner = owner;
     Destination = Owner.Owner.At("publish");
     Cookie = cookie;
     Recipients = ArrayUtil.Union(first.Recipients, (second == null) ? new DispatcherRecipient[0] : second.Recipients);
     _isProxy = true;
 }
Beispiel #19
0
 public DreamMessage SyncDreamCookiesNoAttr(
     DreamCookie x
     )
 {
     return Response(new XDoc("r").Elem("x", x.Value));
 }
Beispiel #20
0
        //--- Constructors ---
        /// <summary>
        /// Create a new dispatcher.
        /// </summary>
        /// <param name="config">Configuration instance injected from pub sub service.</param>
        /// <param name="queueRepository">Factory for dispatch queues used by persisted (i.e. expiring) subscriptions</param>
        public Dispatcher(DispatcherConfig config, IPubSubDispatchQueueRepository queueRepository)
        {
            _queueRepository = queueRepository;
            _owner = config.ServiceUri.AsServerUri();
            _serviceKeySetCookie = config.ServiceAccessCookie;
            _combinedSet = new PubSubSubscriptionSet(_owner, 0, _serviceKeySetCookie);
            _dispatchQueue = new ProcessingQueue<DispatcherEvent>(DispatchFromQueue, 10);
            _defaultQueue = new ImmediatePubSubDispatchQueue(TryDispatchItem);
            var pubSubSubscriptionSets = queueRepository.GetUninitializedSets();

            // Note (arnec): only invoking lock here, so that RegisterSet and Update don't do it over and over
            lock(_subscriptionsByOwner) {
                foreach(var set in pubSubSubscriptionSets) {
                    RegisterSet(set, true);
                }
                Update();
            }
            queueRepository.InitializeRepository(TryDispatchItem);
        }