private async void SetHandler(object Sender, IqEventArgs e) { try { string ServiceToken = XML.Attribute(e.Query, "st"); string DeviceToken = XML.Attribute(e.Query, "dt"); string UserToken = XML.Attribute(e.Query, "ut"); LinkedList <IThingReference> Nodes = null; SortedDictionary <string, bool> ParameterNames = this.provisioningClient is null ? null : new SortedDictionary <string, bool>(); LinkedList <ControlOperation> Operations = new LinkedList <ControlOperation>(); ControlParameter Parameter; DataForm Form = null; XmlElement E; string Name; foreach (XmlNode N in e.Query.ChildNodes) { E = N as XmlElement; if (E is null) { continue; } switch (E.LocalName) { case "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); } break; case "b": case "cl": case "d": case "dt": case "db": case "dr": case "e": case "i": case "l": case "s": case "t": if (ParameterNames != null) { ParameterNames[XML.Attribute(E, "n")] = true; } break; case "x": Form = new DataForm(this.client, E, null, null, e.From, e.To); if (Form.Type != FormType.Submit) { ParameterBadRequest(e); return; } if (ParameterNames != null) { foreach (Field Field in Form.Fields) { ParameterNames[Field.Var] = true; } } break; default: ParameterBadRequest(e); return; } } foreach (XmlNode N in e.Query.ChildNodes) { E = N as XmlElement; if (E is null) { continue; } switch (E.LocalName) { case "b": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } BooleanControlParameter BooleanControlParameter = Parameter as BooleanControlParameter; if (BooleanControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new BooleanControlOperation(Node, BooleanControlParameter, XML.Attribute(E, "v", false), e)); } break; case "cl": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } ColorControlParameter ColorControlParameter = Parameter as ColorControlParameter; if (ColorControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new ColorControlOperation(Node, ColorControlParameter, XML.Attribute(E, "v"), e)); } break; case "d": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } DateControlParameter DateControlParameter = Parameter as DateControlParameter; if (DateControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new DateControlOperation(Node, DateControlParameter, XML.Attribute(E, "v", DateTime.MinValue), e)); } break; case "dt": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } DateTimeControlParameter DateTimeControlParameter = Parameter as DateTimeControlParameter; if (DateTimeControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new DateTimeControlOperation(Node, DateTimeControlParameter, XML.Attribute(E, "v", DateTime.MinValue), e)); } break; case "db": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } DoubleControlParameter DoubleControlParameter = Parameter as DoubleControlParameter; if (DoubleControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new DoubleControlOperation(Node, DoubleControlParameter, XML.Attribute(E, "v", 0.0), e)); } break; case "dr": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } DurationControlParameter DurationControlParameter = Parameter as DurationControlParameter; if (DurationControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new DurationControlOperation(Node, DurationControlParameter, XML.Attribute(E, "v", Duration.Zero), e)); } break; case "e": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } string StringValue = XML.Attribute(E, "v"); if (Parameter is EnumControlParameter EnumControlParameter) { Type T = Types.GetType(XML.Attribute(E, "t")); if (T is null) { e.IqError("<error type='modify'><bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><paramError xmlns=\"" + ControlClient.NamespaceControl + "\" n=\"" + Name + "\">Type not found.</paramError></error>"); return; } if (!T.GetTypeInfo().IsEnum) { e.IqError("<error type='modify'><bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><paramError xmlns=\"" + ControlClient.NamespaceControl + "\" n=\"" + Name + "\">Type is not an enumeration.</paramError></error>"); return; } Enum Value; try { Value = (Enum)Enum.Parse(T, StringValue); } catch (Exception) { e.IqError("<error type='modify'><bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><paramError xmlns=\"" + ControlClient.NamespaceControl + "\" n=\"" + Name + "\">Value not valid element of enumeration.</paramError></error>"); return; } Operations.AddLast(new EnumControlOperation(Node, EnumControlParameter, Value, e)); } else if (Parameter is StringControlParameter StringControlParameter) { Operations.AddLast(new StringControlOperation(Node, StringControlParameter, StringValue, e)); } else if (Parameter is MultiLineTextControlParameter MultiLineTextControlParameter) { Operations.AddLast(new MultiLineTextControlOperation(Node, MultiLineTextControlParameter, StringValue, e)); } else { ParameterWrongType(Name, e); return; } } break; case "i": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } Int32ControlParameter Int32ControlParameter = Parameter as Int32ControlParameter; if (Int32ControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new Int32ControlOperation(Node, Int32ControlParameter, XML.Attribute(E, "v", 0), e)); } break; case "l": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } Int64ControlParameter Int64ControlParameter = Parameter as Int64ControlParameter; if (Int64ControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new Int64ControlOperation(Node, Int64ControlParameter, XML.Attribute(E, "v", 0L), e)); } break; case "s": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } if (Parameter is StringControlParameter StringControlParameter) { Operations.AddLast(new StringControlOperation(Node, StringControlParameter, XML.Attribute(E, "v"), e)); } else if (Parameter is MultiLineTextControlParameter MultiLineTextControlParameter) { Operations.AddLast(new MultiLineTextControlOperation(Node, MultiLineTextControlParameter, XML.Attribute(E, "v"), e)); } else { ParameterWrongType(Name, e); return; } } break; case "t": Name = XML.Attribute(E, "n"); foreach (IThingReference Node in Nodes ?? NoNodes) { Parameter = await this.GetParameter(Node, Name, e); if (Parameter is null) { return; } TimeControlParameter TimeControlParameter = Parameter as TimeControlParameter; if (TimeControlParameter is null) { ParameterWrongType(Name, e); return; } Operations.AddLast(new TimeControlOperation(Node, TimeControlParameter, XML.Attribute(E, "v", TimeSpan.Zero), e)); } break; case "x": Dictionary <string, ControlParameter> Parameters; foreach (IThingReference Node in Nodes ?? NoNodes) { Parameters = await this.GetControlParametersByName(Node); if (Parameters is null) { NotFound(e); return; } foreach (Field Field in Form.Fields) { if (!Parameters.TryGetValue(Field.Var, out Parameter)) { ParameterNotFound(Field.Var, e); return; } Operations.AddLast(new FormControlOperation(Node, Parameter, Field.ValueString, e)); } } break; } } if (this.provisioningClient != null) { string[] ParameterNames2 = new string[ParameterNames.Count]; ParameterNames.Keys.CopyTo(ParameterNames2, 0); this.provisioningClient.CanControl(e.FromBareJid, Nodes, ParameterNames2, ServiceToken.Split(space, StringSplitOptions.RemoveEmptyEntries), DeviceToken.Split(space, StringSplitOptions.RemoveEmptyEntries), UserToken.Split(space, StringSplitOptions.RemoveEmptyEntries), (sender2, e2) => { if (e2.Ok && e2.CanControl) { LinkedList <ControlOperation> Operations2 = null; bool Restricted; if (e2.Nodes != null || e2.ParameterNames != null) { Dictionary <IThingReference, bool> AllowedNodes = null; Dictionary <string, bool> AllowedParameterNames = null; Operations2 = new LinkedList <ControlOperation>(); Restricted = false; if (e2.Nodes != null) { AllowedNodes = new Dictionary <IThingReference, bool>(); foreach (IThingReference Node in e2.Nodes) { AllowedNodes[Node] = true; } } if (e2.ParameterNames != null) { AllowedParameterNames = new Dictionary <string, bool>(); foreach (string ParameterName in e2.ParameterNames) { AllowedParameterNames[ParameterName] = true; } } foreach (ControlOperation Operation in Operations) { if (AllowedNodes != null && !AllowedNodes.ContainsKey(Operation.Node ?? ThingReference.Empty)) { Restricted = true; continue; } if (AllowedParameterNames != null && !AllowedParameterNames.ContainsKey(Operation.ParameterName)) { Restricted = true; continue; } Operations2.AddLast(Operation); } } else { Restricted = false; } if (Restricted) { this.PerformOperations(Operations2, e, e2.Nodes, e2.ParameterNames); } else { this.PerformOperations(Operations, e, null, null); } } 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.PerformOperations(Operations, e, null, null); } } catch (Exception ex) { e.IqError(ex); } }
/// <summary> /// Double control operation. /// </summary> /// <param name="Node">Node on which operation is to be performed.</param> /// <param name="Parameter">Control parameter.</param> /// <param name="Value">Value to set.</param> /// <param name="request">Original request.</param> public DoubleControlOperation(IThingReference Node, DoubleControlParameter Parameter, double Value, IqEventArgs request) : base(Node, request, Parameter) { this.parameter = Parameter; this.value = Value; }