public async Task Processed(QuestionView QuestionView) { MainWindow.UpdateGui(() => { int i = QuestionView.QuestionListView.SelectedIndex; int c; QuestionView.Details.Children.Clear(); QuestionView.QuestionListView.Items.Remove(this); c = QuestionView.QuestionListView.Items.Count; if (c == 0) { MainWindow.currentInstance.CloseTab_Executed(this, null); } else if (i < c) { QuestionView.QuestionListView.SelectedIndex = i; } }); await Database.Delete(this); LinkedList <Question> ToRemove = null; foreach (Question Question in QuestionView.QuestionListView.Items) { if (Question.IsResolvedBy(this)) { if (ToRemove is null) { ToRemove = new LinkedList <Question>(); } ToRemove.AddLast(Question); } } if (ToRemove != null) { MainWindow.UpdateGui(() => { foreach (Question Question in ToRemove) { QuestionView.QuestionListView.Items.Remove(Question); } if (QuestionView.QuestionListView.Items.Count == 0) { MainWindow.currentInstance.CloseTab_Executed(this, null); } }); foreach (Question Question in ToRemove) { await Database.Delete(Question); } } }
private void UpdateTokenSource(string Token, string From) { LinkedList <KeyValuePair <DateTime, string> > ToRemove = null; Triplet <string, DateTime, X509Certificate2> Rec; DateTime TP = DateTime.Now; DateTime Timeout = TP.AddMinutes(-1); lock (this.synchObject) { if (this.sourceByToken.TryGetValue(Token, out Rec)) { this.sourceByToken.Remove(Token); this.tokenByLastAccess.Remove(Rec.Value2); } foreach (KeyValuePair <DateTime, string> P in tokenByLastAccess) { if (P.Key <= Timeout) { if (ToRemove == null) { ToRemove = new LinkedList <KeyValuePair <DateTime, string> > (); } ToRemove.AddLast(P); } else { break; } } if (ToRemove != null) { foreach (KeyValuePair <DateTime, string> P in ToRemove) { this.tokenByLastAccess.Remove(P.Key); this.sourceByToken.Remove(P.Value); } } while (this.tokenByLastAccess.ContainsKey(TP)) { TP = TP.AddTicks(gen.Next(1, 10)); } this.sourceByToken [Token] = new Triplet <string, DateTime, X509Certificate2> (From, TP, null); this.tokenByLastAccess [TP] = Token; } }
private void TimerCallback(object State) { LinkedList <SensorDataEventArgs> ToRemove = null; DateTime Now = DateTime.Now; lock (this.synchObj) { foreach (KeyValuePair <DateTime, SensorDataEventArgs> Pair in this.byTimeout) { if (Pair.Key > Now) { break; } if (ToRemove == null) { ToRemove = new LinkedList <SensorDataEventArgs> (); } ToRemove.AddLast(Pair.Value); } } if (ToRemove != null) { foreach (SensorDataEventArgs e in ToRemove) { lock (this.synchObj) { this.byTimeout.Remove(e.Timeout); this.receiving.Remove(e.SeqNr); if (this.byTimeout.Count == 0 && this.timer != null) { this.timer.Dispose(); this.timer = null; } } e.Receiving(); e.ReadoutState = ReadoutState.Timeout; e.Done = true; e.DoCallback(this); } } }
internal bool UnregisterSubscription(IPEndPoint RemoteEndpoint, ulong Token) { string Prefix = RemoteEndpoint.ToString() + " "; string Key = Prefix + Token.ToString(); lock (this.registrations) { this.registeredMessages = null; if (this.registrations.Remove(Key)) { return(true); } if (Token == 0) { LinkedList <string> ToRemove = null; foreach (string Key2 in this.registrations.Keys) { if (Key2.StartsWith(Prefix)) { if (ToRemove is null) { ToRemove = new LinkedList <string>(); } ToRemove.AddLast(Key2); } } if (ToRemove != null) { foreach (string Key2 in ToRemove) { this.registrations.Remove(Key2); } return(true); } } } return(false); }
private void RecalcTimerLocked() { if (this.timer != null) { this.timer.Dispose(); this.timer = null; } LinkedList <DateTime> ToRemove = null; DateTime Now = DateTime.Now; TimeSpan TimeLeft; foreach (KeyValuePair <DateTime, ScheduledEvent> Event in this.events) { TimeLeft = Event.Key - Now; if (TimeLeft <= TimeSpan.Zero) { if (ToRemove == null) { ToRemove = new LinkedList <DateTime>(); } ToRemove.AddLast(Event.Key); Task.Run((Action)Event.Value.Execute); } else { this.timer = new Timer(this.TimerElapsed, null, TimeLeft, OnlyOnce); break; } } if (ToRemove != null) { foreach (DateTime TP in ToRemove) { this.events.Remove(TP); } } }
/// <summary> /// Reports a set of newly measured field values. Conditions in existing event subscriptions will be analyzed and any corresponding events sent. /// </summary> /// <param name="FieldValues">Field values.</param> public void MomentaryValuesUpdated(params KeyValuePair <string, double>[] FieldValues) { Dictionary <Subscription, bool> ToUpdate = null; LinkedList <Subscription> ToRemove = null; List <Subscription> Subscriptions; DateTime Now = DateTime.Now; TimeSpan SinceLast; XmppContact Contact; bool MaxIntervalReached; bool Update; lock (this.synchObj) { foreach (KeyValuePair <string, double> Pair in FieldValues) { this.currentValues [Pair.Key] = Pair.Value; if (this.subscriptionsByField.TryGetValue(Pair.Key, out Subscriptions)) { foreach (Subscription Subscription in Subscriptions) { Contact = this.client.GetLocalContact(Subscription.From); if (Contact == null || (Contact.Subscription != RosterItemSubscription.Both && Contact.Subscription != RosterItemSubscription.To)) { if (ToRemove == null) { ToRemove = new LinkedList <Subscription> (); } ToRemove.AddLast(Subscription); continue; } if (Contact.LastPresence == null || Contact.LastPresence.Status == PresenceStatus.Offline) { continue; } SinceLast = Now - Subscription.LastUpdate; if (SinceLast < Subscription.MinInterval) { continue; } Update = MaxIntervalReached = SinceLast >= Subscription.MaxInterval; foreach (Condition Condition in Subscription.Conditions) { if (Condition.Trigger(Pair.Key, Pair.Value, MaxIntervalReached)) { Update = true; break; } } if (Update) { if (ToUpdate == null) { ToUpdate = new Dictionary <Subscription, bool> (); } ToUpdate [Subscription] = true; Subscription.LastUpdate = Now; } } } } } if (ToUpdate != null) { foreach (Subscription Subscription in ToUpdate.Keys) { this.SendFields(Subscription.SeqNr, Subscription.From, Subscription.Request); } } if (ToRemove != null) { foreach (Subscription Subscription in ToRemove) { this.RemoveSubscription(Subscription.Key, Subscription.SeqNr); } } }
private void OnMessage(XmppClient Client, XmppMessage Message) { if (Message.MessageType != MessageType.Chat) { return; } string s = Message.Body.Trim(); if (string.IsNullOrEmpty(s)) { return; } DateTime Now = DateTime.Now; DateTime Timeout = Now.AddMinutes(-15); LinkedList <Session> ToRemove = null; Session Session; string s2; int i; lock (this.sessionByJid) { foreach (KeyValuePair <DateTime, Session> P in this.sessionByLastAccess) { if (P.Key <= Timeout) { if (ToRemove == null) { ToRemove = new LinkedList <Session> (); } ToRemove.AddLast(P.Value); } else { break; } } if (ToRemove != null) { foreach (Session S in ToRemove) { this.sessionByJid.Remove(S.From); this.sessionByLastAccess.Remove(S.LastAccess); } } if (this.sessionByJid.TryGetValue(Message.From, out Session)) { this.sessionByLastAccess.Remove(Session.LastAccess); } else { Session = new Session(); Session.From = Message.From; this.sessionByJid [Session.From] = Session; } while (this.sessionByLastAccess.ContainsKey(Now)) { Now = Now.AddTicks(gen.Next(1, 10)); } Session.LastAccess = Now; this.sessionByLastAccess [Now] = Session; } switch (s) { case "#": this.SendMenu(Client, Message.From, true, string.Empty, Session); break; case "##": this.SendMenu(Client, Message.From, false, string.Empty, Session); break; case "?": if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.MomentaryValues, DateTime.MinValue, DateTime.MaxValue); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } break; case "??": if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.All, DateTime.MinValue, DateTime.MaxValue); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } break; case "html+": Session.Html = true; Client.SendMessage(Message.From, "HTML mode turned on.", MessageType.Chat); break; case "html-": Session.Html = false; Client.SendMessage(Message.From, "HTML mode turned off.", MessageType.Chat); break; case "=?": case "!?": if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so control through the chat interface is not allowed.", Session); } else if (this.control == null) { this.SendErrorMessage(Message.From, "No control interface provided.", Session); } else { this.provisioning.CanControl(Message.From, this.CanControlListParametersResponse, new object[] { Message.From, Session }, null, null, null, this.control.Parameters, null); } break; default: if (s.EndsWith("??")) { if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.All, DateTime.MinValue, DateTime.MaxValue, null, new string[] { s.Substring(0, s.Length - 2) }); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } } else if (s.EndsWith("?")) { if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.MomentaryValues, DateTime.MinValue, DateTime.MaxValue, null, new string[] { s.Substring(0, s.Length - 1) }); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } } else if ((i = s.IndexOfAny(controlDelimiters)) > 0) { IControlParameter Parameter; if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so control operations through the chat interface is not allowed.", Session); } else if (this.control == null) { this.SendErrorMessage(Message.From, "No control interface provided.", Session); } else if ((Parameter = this.control [s2 = s.Substring(0, i).Trim()]) == null) { this.SendErrorMessage(Message.From, "No control parameter named '" + s2 + "' found.", Session); } else { this.provisioning.CanControl(Message.From, this.CanControlParameterResponse, new object[] { Message.From, Session, Parameter, s2, s.Substring(i + 1).Trim() }, null, null, null, new string[] { s2 }, null); } } else { this.SendMenu(Client, Message.From, true, "Hello. Following is a list of commands you can use when chatting with me.\r\n\r\n", Session); } break; } }
private async void GetFormHandler(object Sender, IqEventArgs e) { try { LinkedList <IThingReference> Nodes = null; XmlElement E; string ServiceToken = XML.Attribute(e.Query, "st"); string DeviceToken = XML.Attribute(e.Query, "dt"); string UserToken = XML.Attribute(e.Query, "ut"); foreach (XmlNode N in e.Query.ChildNodes) { E = N as XmlElement; if (E is null) { continue; } if (E.LocalName == "nd") { if (Nodes is null) { Nodes = new LinkedList <IThingReference>(); } string NodeId = XML.Attribute(E, "id"); string SourceId = XML.Attribute(E, "src"); string Partition = XML.Attribute(E, "pt"); if (this.OnGetNode is null) { Nodes.AddLast(new ThingReference(NodeId, SourceId, Partition)); } else { IThingReference Ref = await this.OnGetNode(NodeId, SourceId, Partition); if (Ref is null) { throw new ItemNotFoundException("Node not found.", e.IQ); } Nodes.AddLast(Ref); } } } ControlParameter[] Parameters; if (Nodes is null) { Parameters = await this.GetControlParameters(null); if (Parameters is null) { NotFound(e); return; } } else { Dictionary <string, ControlParameter> Parameters1; Dictionary <string, ControlParameter> Parameters2; LinkedList <string> ToRemove = null; Parameters = null; Parameters1 = null; foreach (IThingReference Node in Nodes) { if (Parameters1 is null) { Parameters = await this.GetControlParameters(Node); if (Parameters is null) { NotFound(e); return; } Parameters1 = new Dictionary <string, ControlParameter>(); foreach (ControlParameter P in Parameters) { Parameters1[P.Name] = P; } } else { Parameters2 = await this.GetControlParametersByName(Node); if (Parameters2 is null) { NotFound(e); return; } foreach (KeyValuePair <string, ControlParameter> P in Parameters1) { if (!Parameters2.TryGetValue(P.Key, out ControlParameter P2) || !P.Value.Equals(P2)) { if (ToRemove is null) { ToRemove = new LinkedList <string>(); } ToRemove.AddLast(P.Key); } } if (ToRemove != null) { foreach (string Key in ToRemove) { Parameters1.Remove(Key); } ToRemove = null; } } } List <ControlParameter> Left = new List <ControlParameter>(); foreach (ControlParameter P in Parameters) { if (Parameters1.ContainsKey(P.Name)) { Left.Add(P); } } Parameters = Left.ToArray(); } if (this.provisioningClient != null) { int i, c = Parameters.Length; string[] ParameterNames = new string[c]; for (i = 0; i < c; i++) { ParameterNames[i] = Parameters[i].Name; } this.provisioningClient.CanControl(e.FromBareJid, Nodes, ParameterNames, ServiceToken.Split(space, StringSplitOptions.RemoveEmptyEntries), DeviceToken.Split(space, StringSplitOptions.RemoveEmptyEntries), UserToken.Split(space, StringSplitOptions.RemoveEmptyEntries), (sender2, e2) => { if (e2.Ok && e2.CanControl) { if (e2.ParameterNames != null) { List <ControlParameter> Parameters2 = new List <ControlParameter>(); foreach (ControlParameter P in Parameters) { if (Array.IndexOf <string>(e2.ParameterNames, P.Name) >= 0) { Parameters2.Add(P); } } Parameters = Parameters2.ToArray(); if (Parameters.Length == 0) { e.IqError("<error type='cancel'><forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" + "<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='en'>Access denied.</text></error>"); return; } } this.ReturnForm(e, Parameters, Nodes); } else { e.IqError("<error type='cancel'><forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" + "<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='en'>Access denied.</text></error>"); } }, null); } else { this.ReturnForm(e, Parameters, Nodes); } } catch (Exception ex) { e.IqError(ex); } }
private async void GetFormHandler(object Sender, IqEventArgs e) { try { LinkedList <ThingReference> Nodes = null; XmlElement E; foreach (XmlNode N in e.Query.ChildNodes) { E = N as XmlElement; if (E == null) { continue; } if (E.LocalName == "nd") { if (Nodes == null) { Nodes = new LinkedList <ThingReference>(); } Nodes.AddLast(new ThingReference( XML.Attribute(E, "id"), XML.Attribute(E, "src"), XML.Attribute(E, "pt"))); } } ControlParameter[] Parameters; if (Nodes == null) { Parameters = await this.GetControlParameters(null); if (Parameters == null) { NotFound(e); return; } } else { Dictionary <string, ControlParameter> Parameters1; Dictionary <string, ControlParameter> Parameters2; LinkedList <string> ToRemove = null; Parameters = null; Parameters1 = null; foreach (ThingReference Node in Nodes) { if (Parameters1 == null) { Parameters = await this.GetControlParameters(Node); if (Parameters == null) { NotFound(e); return; } Parameters1 = new Dictionary <string, ControlParameter>(); foreach (ControlParameter P in Parameters) { Parameters1[P.Name] = P; } } else { Parameters2 = await this.GetControlParametersByName(Node); if (Parameters2 == null) { NotFound(e); return; } foreach (KeyValuePair <string, ControlParameter> P in Parameters1) { if (!Parameters2.TryGetValue(P.Key, out ControlParameter P2) || !P.Value.Equals(P2)) { if (ToRemove == null) { ToRemove = new LinkedList <string>(); } ToRemove.AddLast(P.Key); } } if (ToRemove != null) { foreach (string Key in ToRemove) { Parameters1.Remove(Key); } ToRemove = null; } } } List <ControlParameter> Left = new List <ControlParameter>(); foreach (ControlParameter P in Parameters) { if (Parameters1.ContainsKey(P.Name)) { Left.Add(P); } } Parameters = Left.ToArray(); } StringBuilder Xml = new StringBuilder(); XmlWriter Output = XmlWriter.Create(Xml, XML.WriterSettings(false, true)); ThingReference FirstNode; Output.WriteStartElement("x", XmppClient.NamespaceData); Output.WriteAttributeString("xmlns", "xdv", null, XmppClient.NamespaceDataValidate); Output.WriteAttributeString("xmlns", "xdl", null, XmppClient.NamespaceDataLayout); Output.WriteAttributeString("xmlns", "xdd", null, XmppClient.NamespaceDynamicForms); if (Nodes == null) { FirstNode = null; Output.WriteElementString("title", this.client.BareJID); } else { FirstNode = Nodes.First.Value; if (Nodes.First.Next == null) { Output.WriteElementString("title", Nodes.First.Value.NodeId); } else { Output.WriteElementString("title", Nodes.Count.ToString() + " nodes"); } } LinkedList <string> PagesInOrder = new LinkedList <string>(); Dictionary <string, LinkedList <ControlParameter> > ParametersPerPage = new Dictionary <string, LinkedList <ControlParameter> >(); foreach (ControlParameter P in Parameters) { if (!ParametersPerPage.TryGetValue(P.Page, out LinkedList <ControlParameter> List)) { PagesInOrder.AddLast(P.Page); List = new LinkedList <ControlParameter>(); ParametersPerPage[P.Page] = List; } List.AddLast(P); } foreach (string Page in PagesInOrder) { Output.WriteStartElement("xdl", "page", null); Output.WriteAttributeString("label", Page); foreach (ControlParameter P in ParametersPerPage[Page]) { Output.WriteStartElement("xdl", "fieldref", null); Output.WriteAttributeString("var", P.Name); Output.WriteEndElement(); } Output.WriteEndElement(); } foreach (ControlParameter P in Parameters) { P.ExportToForm(Output, FirstNode); } Output.WriteEndElement(); Output.Flush(); e.IqResult(Xml.ToString()); } catch (Exception ex) { e.IqError(ex); } }
private void SubscribeHandler(object Sender, IqEventArgs e) { List <ThingReference> Nodes = null; Dictionary <string, FieldSubscriptionRule> Fields = null; XmlElement E = e.Query; FieldType FieldTypes = (FieldType)0; Duration MaxAge = null; Duration MinInterval = null; Duration MaxInterval = null; string ServiceToken = string.Empty; string DeviceToken = string.Empty; string UserToken = string.Empty; string NodeId; string SourceId; string Partition; string Id = string.Empty; bool Req = false; bool b; foreach (XmlAttribute Attr in E.Attributes) { switch (Attr.Name) { case "id": Id = Attr.Value; break; case "maxAge": if (!Duration.TryParse(Attr.Value, out MaxAge)) { MaxAge = null; } break; case "minInt": if (!Duration.TryParse(Attr.Value, out MinInterval)) { MinInterval = null; } break; case "maxInt": if (!Duration.TryParse(Attr.Value, out MaxInterval)) { MaxInterval = null; } break; case "st": ServiceToken = Attr.Value; break; case "dt": DeviceToken = Attr.Value; break; case "ut": UserToken = Attr.Value; break; case "all": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.All; } break; case "h": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.Historical; } break; case "m": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.Momentary; } break; case "p": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.Peak; } break; case "s": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.Status; } break; case "c": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.Computed; } break; case "i": if (CommonTypes.TryParse(Attr.Value, out b) && b) { FieldTypes |= FieldType.Identity; } break; case "req": if (!CommonTypes.TryParse(Attr.Value, out Req)) { Req = false; } break; } } foreach (XmlNode N in E.ChildNodes) { switch (N.LocalName) { case "nd": if (Nodes == null) { Nodes = new List <ThingReference>(); } E = (XmlElement)N; NodeId = XML.Attribute(E, "id"); SourceId = XML.Attribute(E, "src"); Partition = XML.Attribute(E, "pt"); ThingReference Ref = new ThingReference(NodeId, SourceId, Partition); Nodes.Add(Ref); break; case "f": if (Fields == null) { Fields = new Dictionary <string, FieldSubscriptionRule>(); } string FieldName = null; double?CurrentValue = null; double?ChangedBy = null; double?ChangedUp = null; double?ChangedDown = null; double d; foreach (XmlAttribute Attr in N.Attributes) { switch (Attr.Name) { case "n": FieldName = Attr.Value; break; case "v": if (CommonTypes.TryParse(Attr.Value, out d)) { CurrentValue = d; } break; case "by": if (CommonTypes.TryParse(Attr.Value, out d)) { ChangedBy = d; } break; case "up": if (CommonTypes.TryParse(Attr.Value, out d)) { ChangedUp = d; } break; case "dn": if (CommonTypes.TryParse(Attr.Value, out d)) { ChangedDown = d; } break; } } if (!string.IsNullOrEmpty(FieldName)) { Fields[FieldName] = new FieldSubscriptionRule(FieldName, CurrentValue, ChangedBy, ChangedUp, ChangedDown); } break; } } if (this.provisioningClient != null) { this.provisioningClient.CanRead(e.FromBareJid, FieldTypes, Nodes, Fields.Keys, ServiceToken.Split(space, StringSplitOptions.RemoveEmptyEntries), DeviceToken.Split(space, StringSplitOptions.RemoveEmptyEntries), UserToken.Split(space, StringSplitOptions.RemoveEmptyEntries), (sender2, e2) => { if (e2.Ok && e2.CanRead) { if (e2.FieldsNames != null) { Dictionary <string, bool> FieldNames = new Dictionary <string, bool>(); foreach (string FieldName in FieldNames.Keys) { FieldNames[FieldName] = true; } LinkedList <string> ToRemove = null; foreach (string FieldName in Fields.Keys) { if (!FieldNames.ContainsKey(FieldName)) { if (ToRemove == null) { ToRemove = new LinkedList <string>(); } ToRemove.AddLast(FieldName); } } if (ToRemove != null) { foreach (string FieldName in ToRemove) { Fields.Remove(FieldName); } } } this.PerformSubscription(Req, e, Id, Fields, e2.Nodes, e2.FieldTypes, ServiceToken, DeviceToken, UserToken, MaxAge, MinInterval, MaxInterval); } else { e.IqError("<error type='cancel'><forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" + "<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='en'>Access denied.</text></error>"); } }, null); } else { this.PerformSubscription(Req, e, Id, Fields, Nodes?.ToArray(), FieldTypes, ServiceToken, DeviceToken, UserToken, MaxAge, MinInterval, MaxInterval); } }
/// <summary> /// Checks if the request is authorized. /// </summary> /// <param name="Request">Request object.</param> /// <returns>User object, if authenticated, or null otherwise.</returns> public override async Task <IUser> IsAuthenticated(HttpRequest Request) { HttpFieldAuthorization Authorization = Request.Header.Authorization; if (Authorization != null && Authorization.Value.StartsWith("Digest ", StringComparison.CurrentCultureIgnoreCase)) { string UserName = null; string Opaque = null; string Realm = null; string Nonce = null; string Cnonce = null; string Nc = null; string Uri = null; string Qop = null; string[] QopItems; string Response = null; bool Auth = false; bool AuthInt = false; foreach (KeyValuePair <string, string> P in CommonTypes.ParseFieldValues(Authorization.Value.Substring(7))) { switch (P.Key.ToLower()) { case "username": UserName = P.Value; break; case "opaque": Opaque = P.Value; break; case "realm": Realm = P.Value; break; case "nonce": Nonce = P.Value; break; case "cnonce": Cnonce = P.Value; break; case "nc": Nc = P.Value; break; case "uri": Uri = P.Value; break; case "qop": Qop = P.Value; QopItems = Qop.Split(','); Auth = (Array.IndexOf(QopItems, "auth") >= 0); AuthInt = (Array.IndexOf(QopItems, "auth-int") >= 0); break; case "response": Response = P.Value; break; } } if (this.realm != Realm || Qop is null || Nonce is null || Cnonce is null || Nc is null || Uri is null || Response is null || UserName is null || (!Auth && !AuthInt)) { return(null); } if (this.opaque != Opaque) { // We need to ignore the opaque value if it's a POST from a web form, since it can be used from the original GET // (which might have ocurred when another instance of the application ran). if (Request.Header.Method != "POST" || Request.Header.ContentType.Value != "application/x-www-form-urlencoded") { return(null); } } DateTime TP = DateTime.Now; lock (this) { LinkedList <DateTime> ToRemove = null; foreach (KeyValuePair <DateTime, string> Pair in this.nonceByExpiration) { if (Pair.Key <= TP) { if (ToRemove is null) { ToRemove = new LinkedList <DateTime>(); } ToRemove.AddLast(Pair.Key); this.expirationByNonce.Remove(Pair.Value); } else { break; } } if (ToRemove != null) { foreach (DateTime ExpiryDate in ToRemove) { this.nonceByExpiration.Remove(ExpiryDate); } } if (!this.expirationByNonce.TryGetValue(Nonce, out TP)) { // We need to ignore the nonce value if it's a POST from a web form, since it can be used from the original GET // (which might have ocurred when another instance of the application ran). if (Request.Header.Method != "POST" || Request.Header.ContentType.Value != "application/x-www-form-urlencoded") { return(null); } } if (Request.Header.Method != "HEAD") { this.expirationByNonce.Remove(Nonce); this.nonceByExpiration.Remove(TP); } } string HA1; string HA2; string Digest; IUser User = await this.users.TryGetUser(UserName); if (User is null) { return(null); } switch (User.PasswordHashType) { case "": HA1 = ToHex(H(UserName + ":" + this.realm + ":" + User.PasswordHash)); break; case "DIGEST-MD5": HA1 = User.PasswordHash; break; default: return(null); } if (AuthInt) { HA2 = ToHex(H(Request.Header.Method + ":" + Uri + ":" + ToHex(H(string.Empty)))); } else { HA2 = ToHex(H(Request.Header.Method + ":" + Uri)); } Digest = HA1 + ":" + Nonce + ":" + Nc + ":" + Cnonce + ":" + Qop + ":" + HA2; Digest = ToHex(H(Digest)); if (Digest == Response) { LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP"); return(User); } else { LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP"); return(null); } } return(null); }