public void Call(DiscoNode node) { if (callback != null) { callback(manager, node, state); } }
private void GotItems(object sender, IQ iq, object onode) { DiscoNode dn = onode as DiscoNode; Debug.Assert(dn != null); if (iq.Type != IQType.result) { // protocol error dn.AddItems(this, null); return; } DiscoItems items = iq.Query as DiscoItems; if (items == null) { // protocol error dn.AddItems(this, null); return; } dn.AddItems(this, items.GetItems()); // automatically info everything we get an item for. foreach (DiscoNode n in dn.Children) { if (n.Features == null) { RequestInfo(n); } } }
/// <summary> /// Deletes the cache. /// </summary> public void Clear() { lock (m_items) { m_root = null; m_items.Clear(); } }
public void GotRootItems(DiscoManager manager, DiscoNode node, object state) { m_outstanding = node.Children.Count; foreach (DiscoNode n in node.Children) { manager.BeginGetFeatures(n, new DiscoNodeHandler(GotFeatures), state); } }
private void tvServices_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { jabber.connection.DiscoNode dn = (jabber.connection.DiscoNode)e.Node.Tag; if (dn.Children == null) { m_disco.BeginGetItems(dn.JID, dn.Node, new jabber.connection.DiscoNodeHandler(GotItems), null); } }
/// <summary> /// Create a CapsManager from an existing Disco Node. Pass in null /// to use a placeholder. /// </summary> /// <param name="node"></param> public CapsManager(DiscoNode node) { InitializeComponent(); this.OnStreamChanged += new bedrock.ObjectHandler(CapsManager_OnStreamChanged); if (node == null) m_disco = new DiscoNode(new JID(null, "placeholder", null), null); else m_disco = node; }
internal DiscoNode AddItem(DiscoManager manager, DiscoItem di) { DiscoNode dn = manager.GetNode(di.Jid, di.Node); if ((di.Named != null) && (di.Named != "")) { dn.Name = di.Named; } Children.Add(dn); return(dn); }
/// <summary> /// Retrieves the features associated with this node and /// then calls back on the handler. /// If the information is in the cache, handler gets called right now. /// </summary> /// <param name="node">Node to look for.</param> /// <param name="handler">Callback to use afterwards.</param> /// <param name="state">Context to pass back to caller when complete</param> public void BeginGetFeatures(DiscoNode node, DiscoNodeHandler handler, object state) { if (node == null) { node = Root; } if (node.AddFeatureCallback(this, handler, state)) { RequestInfo(node); } }
/// <summary> /// Retrieves the child items associated with this node, /// and then calls back on the handler. /// If the information is in the cache, handler gets /// called right now. /// </summary> /// <param name="node">Disco node to search.</param> /// <param name="handler">Callback that gets called with the items.</param> /// <param name="state">Context to pass back to caller when complete</param> public void BeginGetItems(DiscoNode node, DiscoNodeHandler handler, object state) { if (node == null) { node = Root; } if (node.AddItemsCallback(this, handler, state)) { RequestItems(node); } }
private void m_stream_OnAuthenticate(object sender) { // TODO: some of this will break in 2003. jabber.connection.DiscoNode dn = m_disco.GetNode(m_stream.Server, null); TreeNode tn = tvServices.Nodes.Add(dn.Key, dn.Name); tn.ToolTipText = dn.Key.Replace('\u0000', '\n'); tn.Tag = dn; tn.ImageIndex = 8; tn.SelectedImageIndex = 8; m_disco.BeginGetFeatures(dn, new jabber.connection.DiscoNodeHandler(GotInitialFeatures), null); }
/// <summary> /// Creates nodes and ensure that they are cached. /// </summary> /// <param name="jid">JID associated with DiscoNode.</param> /// <param name="node">Node associated with DiscoNode.</param> /// <returns> /// If DiscoNode exists, returns the found node. /// Otherwise it creates the node and return it. /// </returns> public DiscoNode GetNode(JID jid, string node) { lock (m_items) { string key = DiscoNode.GetKey(jid, node); DiscoNode n = (DiscoNode)m_items[key]; if (n == null) { n = new DiscoNode(jid, node); m_items.Add(key, n); } return(n); } }
private void GotCaps(DiscoManager m, DiscoNode node, object state) { // timeout if (node == null) return; string ver = (string)state; if (ver != CalculateVer(node)) { Debug.WriteLine("WARNING: invalid caps ver hash: " + ver); Debug.WriteLine(node.Info.OuterXml); return; } m_cache[ver] = node.Info; }
private void RequestItems(DiscoNode node) { lock (node) { if (!node.PendingItems) { IQ iq = node.ItemsIQ(m_stream.Document); jabber.server.JabberService js = m_stream as jabber.server.JabberService; if (js != null) { iq.From = js.ComponentID; } BeginIQ(iq, new jabber.connection.IqCB(GotItems), node); } } }
private void GotItems(DiscoManager sender, jabber.connection.DiscoNode node, object state) { // TODO: some of this will break in 2003. TreeNode[] nodes = tvServices.Nodes.Find(node.Key, true); foreach (TreeNode n in nodes) { n.ImageIndex = 7; n.SelectedImageIndex = 7; foreach (jabber.connection.DiscoNode dn in node.Children) { TreeNode tn = n.Nodes.Add(dn.Key, dn.Name); tn.ToolTipText = dn.Key.Replace('\u0000', '\n'); tn.Tag = dn; tn.ImageIndex = 8; tn.SelectedImageIndex = 8; } } pgServices.Refresh(); }
public void GotFeatures(DiscoManager manager, DiscoNode node, object state) { // yes, yes, this may call the handler more than once in multi-threaded world. Punt for now. if (m_handler != null) { if (node.HasFeature(m_URI)) { m_handler(manager, node, state); m_handler = null; } } if (Interlocked.Decrement(ref m_outstanding) == 0) { if (m_handler != null) { m_handler(manager, null, state); } } }
private void GotInfo(object sender, IQ iq, object onode) { DiscoNode dn = onode as DiscoNode; Debug.Assert(dn != null); if (iq.Type == IQType.error) { if (dn == m_root) { // root node. // Try agents. Error err = iq.Error; if (err != null) { string cond = err.Condition; if ((cond == Error.FEATURE_NOT_IMPLEMENTED) || (cond == Error.SERVICE_UNAVAILABLE)) { IQ aiq = new AgentsIQ(m_stream.Document); BeginIQ(aiq, new jabber.connection.IqCB(GotAgents), m_root); return; } } } } if (iq.Type != IQType.result) { // protocol error dn.AddInfo(null); return; } dn.AddInfo(iq.Query as DiscoInfo); if (dn == m_root) { RequestItems(m_root); } }
private void GotCaps(DiscoManager m, DiscoNode node, object state) { // timeout if (node == null) { return; } string ver = (string)state; string calc = CalculateVer(node); if (ver != calc) { Debug.WriteLine("WARNING: invalid caps ver hash: '" + ver + "' != '" + calc + "'"); if (node.Info != null) { Debug.WriteLine(node.Info.OuterXml); } return; } m_cache[ver] = node.Info; }
public void RequestUrl(Uri uri) { // FIXME: Actually we want to show this as a lightbox or something. LoadContent(uri, "Loading..."); if (m_Account.ConnectionState != AccountConnectionState.Connected) { LoadContent(uri, "You are not connected."); return; } var info = XmppUriQueryInfo.ParseQuery(uri.Query); string queryType = info.QueryType; // Default to disco. if (String.IsNullOrEmpty(queryType)) { queryType = "disco"; } switch (queryType) { case "disco": var jid = new JID(uri.AbsolutePath); string node = null; if (info.Parameters.ContainsKey("node")) { node = info.Parameters["node"]; } var discoNode = new jabber.connection.DiscoNode(jid, node); m_Account.DiscoManager.BeginGetFeatures(discoNode, new DiscoNodeHandler(ReceivedFeatures), null); break; default: throw new Exception("Unsupported query type: " + queryType); } }
private void discoManager_FindServiceWithFeature(DiscoManager sender, DiscoNode node, object state) { if (node == null) { return; } if (node.Name == "Rooms") { _discoManager.BeginGetItems(node, discoManager_SubscribeToRooms, new object()); } }
private string CalculateVer(DiscoNode n) { if (m_hash == null) { return(null); } // 1. Initialize an empty string S. StringBuilder S = new StringBuilder(); // 2. Sort the service discovery identities [16] by category and then by type // (if it exists) and then by xml:lang (if it exists), formatted as // CATEGORY '/' [TYPE] '/' [LANG] '/' [NAME]. Note that each slash is // included even if the TYPE, LANG, or NAME is not included. Ident[] ids = n.GetIdentities(); Array.Sort(ids); // 3. For each identity, append the 'category/type/lang/name' to S, followed by // the '<' character. foreach (Ident id in ids) { S.Append(id.Key); S.Append(SEP); } // 4. Sort the supported service discovery features. string[] features = n.FeatureNames; Array.Sort(features); // 5. For each feature, append the feature to S, followed by the '<' character. foreach (string feature in features) { S.Append(feature); S.Append(SEP); } // 6. If the service discovery information response includes XEP-0128 data forms, // sort the forms by the FORM_TYPE (i.e., by the XML character // data of the <value/> element). Data[] ext = n.Extensions; if (ext != null) { Array.Sort(ext, new FormTypeComparer()); foreach (Data x in ext) { // For each extended service discovery information form: // 1. Append the XML character data of the FORM_TYPE field's <value/> // element, followed by the '<' character. S.Append(x.FormType); S.Append(SEP); // 2. Sort the fields by the value of the "var" attribute. bedrock.collections.Tree fields = new bedrock.collections.Tree(); foreach (Field f in x.GetFields()) { fields[f.Var] = f; } // 3. For each field: foreach (System.Collections.DictionaryEntry entry in fields) { Field f = (Field)entry.Value; if (f.Var == "FORM_TYPE") { continue; } // 1. Append the value of the "var" attribute, followed by the '<' character. S.Append(f.Var); S.Append(SEP); // 2. Sort values by the XML character data of the <value/> element. string[] values = f.Vals; Array.Sort(values); foreach (string v in values) { // 3. For each <value/> element, append the XML character data, followed by the '<' character. S.Append(v); S.Append(SEP); } } } } // Ensure that S is encoded according to the UTF-8 encoding (RFC 3269 [16]). byte[] input = Encoding.UTF8.GetBytes(S.ToString()); // Compute the verification string by hashing S using the algorithm specified // in the 'hash' attribute (e.g., SHA-1 as defined in RFC 3174 [17]). The hashed // data MUST be generated with binary output and encoded using Base64 as specified // in Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT include // whitespace and MUST set padding bits to zero). [19] HashAlgorithm hasher = GetHasher(m_hash); byte[] hash = hasher.ComputeHash(input, 0, input.Length); return(Convert.ToBase64String(hash)); }
private void GotCaps(DiscoManager m, DiscoNode node, object state) { // timeout if (node == null) return; string ver = (string)state; string calc = CalculateVer(node); if (ver != calc) { Debug.WriteLine("WARNING: invalid caps ver hash: '" + ver + "' != '" + calc + "'"); if (node.Info != null) Debug.WriteLine(node.Info.OuterXml); return; } m_cache[ver] = node.Info; }
private string CalculateVer(DiscoNode n) { if (m_hash == null) return null; // 1. Initialize an empty string S. StringBuilder S = new StringBuilder(); // 2. Sort the service discovery identities [16] by category and then by type // (if it exists) and then by xml:lang (if it exists), formatted as // CATEGORY '/' [TYPE] '/' [LANG] '/' [NAME]. Note that each slash is // included even if the TYPE, LANG, or NAME is not included. Ident[] ids = n.GetIdentities(); Array.Sort(ids); // 3. For each identity, append the 'category/type/lang/name' to S, followed by // the '<' character. foreach (Ident id in ids) { S.Append(id.Key); S.Append(SEP); } // 4. Sort the supported service discovery features. string[] features = n.FeatureNames; Array.Sort(features); // 5. For each feature, append the feature to S, followed by the '<' character. foreach (string feature in features) { S.Append(feature); S.Append(SEP); } // 6. If the service discovery information response includes XEP-0128 data forms, // sort the forms by the FORM_TYPE (i.e., by the XML character // data of the <value/> element). Data[] ext = n.Extensions; if (ext != null) { Array.Sort(ext, new FormTypeComparer()); foreach (Data x in ext) { // For each extended service discovery information form: // 1. Append the XML character data of the FORM_TYPE field's <value/> // element, followed by the '<' character. S.Append(x.FormType); S.Append(SEP); // 2. Sort the fields by the value of the "var" attribute. bedrock.collections.Tree fields = new bedrock.collections.Tree(); foreach (Field f in x.GetFields()) fields[f.Var] = f; // 3. For each field: foreach (System.Collections.DictionaryEntry entry in fields) { Field f = (Field)entry.Value; if (f.Var == "FORM_TYPE") continue; // 1. Append the value of the "var" attribute, followed by the '<' character. S.Append(f.Var); S.Append(SEP); // 2. Sort values by the XML character data of the <value/> element. string[] values = f.Vals; Array.Sort(values); foreach (string v in values) { // 3. For each <value/> element, append the XML character data, followed by the '<' character. S.Append(v); S.Append(SEP); } } } } // Ensure that S is encoded according to the UTF-8 encoding (RFC 3269 [16]). byte[] input = Encoding.UTF8.GetBytes(S.ToString()); // Compute the verification string by hashing S using the algorithm specified // in the 'hash' attribute (e.g., SHA-1 as defined in RFC 3174 [17]). The hashed // data MUST be generated with binary output and encoded using Base64 as specified // in Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT include // whitespace and MUST set padding bits to zero). [19] HashAlgorithm hasher = GetHasher(m_hash); byte[] hash = hasher.ComputeHash(input, 0, input.Length); return Convert.ToBase64String(hash); }
private void GotAgents(object sender, IQ iq, object onode) { DiscoNode dn = onode as DiscoNode; Debug.Assert(dn != null); if (iq.Type != IQType.result) { dn.AddItems(this, null); return; } AgentsQuery aq = iq.Query as AgentsQuery; if (aq == null) { dn.AddItems(this, null); return; } if (dn.Children == null) { dn.Children = new Set(); } foreach (Agent agent in aq.GetAgents()) { DiscoItem di = new DiscoItem(m_stream.Document); di.Jid = agent.JID; di.Named = agent.AgentName; DiscoNode child = dn.AddItem(this, di); if (child.Features == null) { child.Features = new StringSet(); } if (child.Identity == null) { child.Identity = new Set(); } Ident id = new Ident(); id.Name = agent.Description; switch (agent.Service) { case "groupchat": id.Category = "conference"; id.Type = "text"; child.Identity.Add(id); break; case "jud": id.Category = "directory"; id.Type = "user"; child.Identity.Add(id); break; case null: case "": break; default: // guess this is a transport id.Category = "gateway"; id.Type = agent.Service; child.Identity.Add(id); break; } if (agent.Register) { child.Features.Add(URI.REGISTER); } if (agent.Search) { child.Features.Add(URI.SEARCH); } if (agent.Groupchat) { child.Features.Add(URI.MUC); } if (agent.Transport) { if (id.Category != "gateway") { Ident tid = new Ident(); tid.Name = id.Name; tid.Category = "gateway"; child.Identity.Add(tid); } } foreach (XmlElement ns in agent.GetElementsByTagName("ns")) { child.Features.Add(ns.InnerText); } child.AddItems(this, null); child.AddIdentities(null); child.AddFeatures((StringSet)null); } dn.AddItems(this, null); dn.AddIdentities(null); dn.AddFeatures((StringSet)null); }
public void Call(DiscoNode node) { if (callback != null) callback(manager, node, state); }
public void GotFeatures(DiscoManager manager, DiscoNode node, object state) { // yes, yes, this may call the handler more than once in multi-threaded world. Punt for now. if (m_handler != null) { if (node.HasFeature(m_URI)) { m_handler(manager, node, state); m_handler = null; } } if (Interlocked.Decrement(ref m_outstanding) == 0) { if (m_handler != null) m_handler(manager, null, state); } }
/// <summary> /// Retrieves the features associated with this node and /// then calls back on the handler. /// If the information is in the cache, handler gets called right now. /// </summary> /// <param name="node">Node to look for.</param> /// <param name="handler">Callback to use afterwards.</param> /// <param name="state">Context to pass back to caller when complete</param> public void BeginGetFeatures(DiscoNode node, DiscoNodeHandler handler, object state) { if (node == null) node = Root; if (node.AddFeatureCallback(this, handler, state)) RequestInfo(node); }
private void discoManager_SubscribeToRooms(DiscoManager sender, DiscoNode node, object state) { if (node == null) { return; } if (node.Children != null && SubscribedRooms == "@all") { foreach (DiscoNode dn in node.Children) { Logger.Info(string.Format("Subscribing to: {0}:{1}", dn.JID, dn.Name)); // hipchat no longer supports Groupchat 1.0 Protocol to enter rooms, // but jabber.net uses Groupchat to join rooms so we have to create // a Basic MUC Protocol message by hand instead. // // see http://help.hipchat.com/knowledgebase/articles/64377-xmpp-jabber-support-details // http://xmpp.org/extensions/xep-0045.html#enter-gc // http://xmpp.org/extensions/xep-0045.html#enter-muc var presenceMessage = new XmlDocument(); presenceMessage.LoadXml("<presence from='{0}' id='{1}' to='{2}'>" + " <x xmlns='http://jabber.org/protocol/muc'/>" + "</presence>"); // set the "from" value var presenceFrom = presenceMessage.SelectSingleNode("presence/@from"); if (presenceFrom == null) { throw new InvalidOperationException(); } presenceFrom.InnerText = new JID(this.UserName, dn.JID.Server, this.Resource); // set the "to" value var presenceTo = presenceMessage.SelectSingleNode("presence/@to"); if (presenceTo == null) { throw new InvalidOperationException(); } presenceTo.InnerText = new JID(dn.JID.User, dn.JID.Server, this.NickName); ; // write the message _jabberClient.Write(presenceMessage.DocumentElement); } } }
public void ComplexGenerationExample() { XmlDocument doc = new XmlDocument(); doc.LoadXml("<book xml:lang='en'/>"); XmlElement book = doc.DocumentElement; foreach (XmlAttribute attr in book.Attributes) { System.Console.WriteLine(attr.Name); } XmlElement root = doc.DocumentElement; DiscoInfo info = new DiscoInfo(doc); info.AddFeature("http://jabber.org/protocol/muc"); info.AddFeature("http://jabber.org/protocol/disco#info"); info.AddFeature("http://jabber.org/protocol/disco#items"); info.AddIdentity("client", "pc", "Psi 0.9.1", "en"); info.AddIdentity("client", "pc", "\u03a8 0.9.1", "el"); Data x = info.CreateExtension(); x.FormType = "urn:xmpp:dataforms:softwareinfo"; x.AddField("ip_version").Vals = new string[] { "ipv4", "ipv6" }; x.AddField("os").Val = "Mac"; x.AddField("os_version").Val = "10.5.1"; x.AddField("software").Val = "Psi"; x.AddField("software_version").Val = "0.11"; DiscoNode dn = new DiscoNode(new JID(null, "placeholder", null), null); dn.AddInfo(info); CapsManager cm = new CapsManager(dn); Assert.AreEqual("8lu+88MRxmKM7yO3MEzY7YmTsWs=", cm.Ver); }
private void tvServices_AfterSelect(object sender, TreeViewEventArgs e) { jabber.connection.DiscoNode dn = (jabber.connection.DiscoNode)e.Node.Tag; m_disco.BeginGetFeatures(dn, new jabber.connection.DiscoNodeHandler(GotInfo), null); }
/// <summary> /// Retrieves the child items associated with this node, /// and then calls back on the handler. /// /// If caching is specified, items already in the cache call the handler /// immediately. /// </summary> /// <param name="jid">JID of Service to query.</param> /// <param name="node">Node on the service to interact with.</param> /// <param name="handler">Callback that gets called with the items.</param> /// <param name="state">Context to pass back to caller when complete</param> /// <param name="cache">Should caching be performed on this request?</param> public void BeginGetItems(JID jid, string node, DiscoNodeHandler handler, object state, bool cache) { DiscoNode dn = cache ? GetNode(jid, node) : new DiscoNode(jid, node); BeginGetItems(dn, handler, state); }
private void GotInitialFeatures(DiscoManager sender, jabber.connection.DiscoNode node, object state) { m_disco.BeginGetItems(node, new jabber.connection.DiscoNodeHandler(GotItems), state); }
private void GotInfo(DiscoManager sender, jabber.connection.DiscoNode node, object state) { pgServices.SelectedObject = node; }
/// <summary> /// Retrieves the child items associated with this node, /// and then calls back on the handler. /// If the information is in the cache, handler gets /// called right now. /// </summary> /// <param name="node">Disco node to search.</param> /// <param name="handler">Callback that gets called with the items.</param> /// <param name="state">Context to pass back to caller when complete</param> public void BeginGetItems(DiscoNode node, DiscoNodeHandler handler, object state) { if (node == null) node = Root; if (node.AddItemsCallback(this, handler, state)) RequestItems(node); }
private void GotRoot(DiscoManager sender, DiscoNode node, object state) { if (node.Children != null) { foreach (DiscoNode component in node.Children) { if (component.HasFeature(jabber.protocol.URI.MUC)) cmbJID.Items.Add(component.JID); } if (cmbJID.Items.Count > 0) cmbJID.SelectedIndex = 0; } cmbJID.EndUpdate(); }
public void GotRootItems(DiscoManager manager, DiscoNode node, object state) { m_outstanding = node.Children.Count; foreach (DiscoNode n in node.Children) manager.BeginGetFeatures(n, new DiscoNodeHandler(GotFeatures), state); }
public void RequestUrl(Uri uri) { // FIXME: Actually we want to show this as a lightbox or something. LoadContent(uri, "Loading..."); if (m_Account.ConnectionState != AccountConnectionState.Connected) { LoadContent(uri, "You are not connected."); return; } var info = XmppUriQueryInfo.ParseQuery(uri.Query); string queryType = info.QueryType; // Default to disco. if (String.IsNullOrEmpty(queryType)) queryType = "disco"; switch (queryType) { case "disco": var jid = new JID(uri.AbsolutePath); string node = null; if (info.Parameters.ContainsKey("node")) node = info.Parameters["node"]; var discoNode = new jabber.connection.DiscoNode(jid, node); m_Account.DiscoManager.BeginGetFeatures(discoNode, new DiscoNodeHandler(ReceivedFeatures), null); break; default: throw new Exception("Unsupported query type: " + queryType); } }
/// <summary> /// Creates nodes and ensure that they are cached. /// </summary> /// <param name="jid">JID associated with DiscoNode.</param> /// <param name="node">Node associated with DiscoNode.</param> /// <returns> /// If DiscoNode exists, returns the found node. /// Otherwise it creates the node and return it. /// </returns> public DiscoNode GetNode(JID jid, string node) { lock (m_items) { string key = DiscoNode.GetKey(jid, node); DiscoNode n = (DiscoNode)m_items[key]; if (n == null) { n = new DiscoNode(jid, node); m_items.Add(key, n); } return n; } }
void ReceivedFeatures(DiscoManager manager, DiscoNode node, object state) { // Now query for items... m_Account.DiscoManager.BeginGetItems(node, new DiscoNodeHandler(ReceivedItems), null); }
private void RequestItems(DiscoNode node) { lock (node) { if (!node.PendingItems) { IQ iq = node.ItemsIQ(m_stream.Document); jabber.server.JabberService js = m_stream as jabber.server.JabberService; if (js != null) iq.From = js.ComponentID; BeginIQ(iq, new jabber.connection.IqCB(GotItems), node); } } }
void ReceivedItems(DiscoManager manager, DiscoNode node, object state) { string jid = node.JID.ToString(); string nodeName = String.Empty; if (node.Node != null) nodeName = node.Node; string templateContent = Util.ReadResource("ServiceDiscovery.html"); Template template = new Template(templateContent); template.SetField("NAME", jid); template.SetField("HREF", String.Format("xmpp:{0}?disco", jid)); template.SetField("NODE", nodeName); template.SelectSection("FEATURES"); foreach (var feature in node.FeatureNames) { template.SetField("FEATURE_NAME", feature); template.AppendSection(); } template.DeselectSection(); template.SelectSection("ITEMS"); foreach (DiscoNode item in node.Children) { template.SetField("ITEM_NAME", item.Name); template.SetField("ITEM_URL", String.Format("xmpp:{0}?disco;node={1}", item.JID.ToString(), item.Node)); template.AppendSection(); } template.DeselectSection(); template.SelectSection("IDENTITIES"); foreach (var identity in node.GetIdentities()) { template.SetField("IDENTITY_NAME", identity.Name); template.SetField("IDENTITY_CATEGORY", identity.Category); template.SetField("IDENTITY_TYPE", identity.Type); template.AppendSection(); } template.DeselectSection(); QApplication.Invoke(delegate { Uri uri = new Uri(String.Format("xmpp:{0}?disco;node={1}", node.JID.ToString(), node.Node)); LoadContent(uri, template.getContent()); }); }