internal void FireStanzaReceived(XMPPStanza stanza) { if (OnStanzaReceived != null) { OnStanzaReceived(stanza, this); } }
public virtual int SendStanza(XMPPStanza stanza) { string strSend = stanza.XML; byte[] bStanza = System.Text.UTF8Encoding.UTF8.GetBytes(strSend); return(this.Send(bStanza)); }
/// <summary> /// A new XML fragment has been received /// </summary> /// <param name="node"></param> /// <returns>returns true if we handled this fragment, false if other wise</returns> public virtual bool NewXMLFragment(XMPPStanza stanza) { return false; }
protected virtual void XMPPConnection_OnStanzaReceived(XMPPStanza stanza, object objFrom) { bool bHandled = false; /// See if any of our handlers /// List <Logic> RemoveList = new List <Logic>(); lock (LogicLock) { foreach (Logic log in ActiveServices) { bHandled = log.NewXMLFragment(stanza); if (log.IsCompleted == true) { RemoveList.Add(log); } if (bHandled == true) { break; } } foreach (Logic log in RemoveList) { ActiveServices.Remove(log); } } if (bHandled == true) { return; } /// Now see if this stanza is a higher level IQ or message /// try { XElement elem = XElement.Parse(stanza.XML); XMPPMessageBase msg = null; if (elem.Name == "iq") { msg = XMPPMessageFactory.BuildIQ(elem, stanza.XML); } else if (elem.Name == "message") { msg = XMPPMessageFactory.BuildMessage(elem, stanza.XML); } else if (elem.Name == "presence") { msg = XMPPMessageFactory.BuildPresence(elem, stanza.XML); //msg = new PresenceMessage(stanza.XML); } /// TODO.. log IQ, MESSAGE or PRESENCE event, maybe have an event handler /// if (msg != null) { if (msg is IQ) { bHandled = OnIQ(msg as IQ); } else if (msg is Message) { bHandled = OnMessage(msg as Message); } else if (msg is PresenceMessage) { bHandled = OnPresence(msg as PresenceMessage); } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } if (bHandled == true) { return; } }
/// <summary> /// /// </summary> /// <param name="stanza"></param> /// <returns></returns> public override bool NewXMLFragment(XMPPStanza stanza) { /// Looks like the crippled windows phone 7 libraries can't use output from xsd.exe, have to do this the hard way /// //XDocument doc = XDocument.Load(new StringReader(stanza.XML)); //XmlReader reader = XmlReader.Create(new StringReader(stanza.XML)); stanza.XML = stanza.XML.Replace("stream:", ""); // no support for namespaces in windows phone 7, remove them XElement xmlElem = XElement.Parse(stanza.XML); if (XMPPClient.XMPPState >= XMPPState.Authenticated) { if (xmlElem.Name == "features") { return(true); /// If we hit this and parse the stream featurs a second time we re-authenticate. Just return for now } //if (xmlElem.Name == "stream") //{ // XMPPClient.XMPPState = XMPPState.CanBind; //} /// TODO.. see if this new stream supports bind } if (xmlElem.Name == "features") { //foreach (XElement node in xmlElem.Descendants()) //{ // System.Diagnostics.Debug.WriteLine(node.Name); //} var Mechanisms = from mech in xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-sasl}mechanism") select new Mechanism { Name = mech.Value, }; foreach (Mechanism mech in Mechanisms) { if (mech.Name == "DIGEST-MD5") { AuthMethodsSupported |= AuthMethod.MD5; } else if (mech.Name == "PLAIN") { AuthMethodsSupported |= AuthMethod.Plain; } // else if (mech.Name == "X-GOOGLE-TOKEN") // AuthMethodsSupported |= AuthMethod.googletoken; } if (AuthMethodsSupported == AuthMethod.NotSpecified) { throw new Exception("No acceptable authentication method was supplied"); } var tls = xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-tls}starttls"); if (tls.Count() > 0) { FeatureTLS = true; } if ((FeatureTLS == true) && (XMPPClient.UseTLS == true)) { /// Tell the man we want to negotiate TLS XMPPClient.SendRawXML(StartTLS); } else { StartAuthentication(); } return(true); } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-tls}proceed") { XMPPClient.XMPPConnection.StartTLS(); /// After starting TLS, start our normal digest authentication (or plain) /// StartAuthentication(); } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}challenge") { /// Build and send response /// string strChallenge = xmlElem.Value; byte[] bData = Convert.FromBase64String(strChallenge); string strUnbasedChallenge = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length); //realm="ninethumbs.com",nonce="oFun3YWfVm/6nHCkNI/9a4XpcWIdQ5RH9E0IDVKH",qop="auth",charset=utf-8,algorithm=md5-sess //string strExampleResponse = "dXNlcm5hbWU9InRlc3QiLHJlYWxtPSJuaW5ldGh1bWJzLmNvbSIsbm9uY2U9InJaNjgreS9BeGp2SjJ6cjBCVUNxVUhQcG9ocFE4ZFkzR29JclpJcFkiLGNub25jZT0iVkdFRDNqNHUrUHE1M3IxYzNab2NhcGFzaWp1eTh2NjhoYXFzRC9IWjVKTT0iLG5jPTAwMDAwMDAxLGRpZ2VzdC11cmk9InhtcHAvbmluZXRodW1icy5jb20iLHFvcD1hdXRoLHJlc3BvbnNlPTdiM2MzOTVjZjU2MDA2Njg5MDg5MzdlYTk2YjEzZjI2LGNoYXJzZXQ9dXRmLTg="; //bData = Convert.FromBase64String(strExampleResponse); //string strUnbasedResponse = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length); //"username=\"test\",realm=\"ninethumbs.com\",nonce=\"rZ68+y/AxjvJ2zr0BUCqUHPpohpQ8dY3GoIrZIpY\",cnonce=\"VGED3j4u+Pq53r1c3Zocapasijuy8v68haqsD/HZ5JM=\",nc=00000001,digest-uri=\"xmpp/ninethumbs.com\",qop=auth,response=7b3c395cf5600668908937ea96b13f26,charset=utf-8"; if (AuthMethodUsed == AuthMethod.MD5) { string strRealm = XMPPClient.Domain; Match matchrealm = Regex.Match(strUnbasedChallenge, @"realm=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); if (matchrealm.Success == true) { strRealm = matchrealm.Groups[1].Value; } string strNonce = ""; Match matchnonce = Regex.Match(strUnbasedChallenge, @"nonce=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline); if (matchnonce.Success == true) { strNonce = matchnonce.Groups[1].Value; } string strQop = "auth"; Match matchqop = Regex.Match(strUnbasedChallenge, @"qop=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); if (matchqop.Success == true) { strQop = matchqop.Groups[1].Value; } string strAlgo = "md5-sess"; Match matchalgo = Regex.Match(strUnbasedChallenge, @"algorithm=([^\s,]+)", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); if (matchalgo.Success == true) { strAlgo = matchalgo.Groups[1].Value; } Random rand = new Random(); string strCnonce = rand.Next().ToString("X8").ToLower(); // Compute our MD5 response, then base64 it string strResponse = GenerateMD5Response(strAlgo, XMPPClient.UserName, XMPPClient.Domain, XMPPClient.Password, strNonce, strCnonce); string ResponseMessage = MD5Response.Replace("##RESPONSE##", strResponse); XMPPClient.SendRawXML(ResponseMessage); } else if (AuthMethodUsed == AuthMethod.Plain) { /// Send plain text stuff /// } } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}success") /// Success { XMPPClient.XMPPState = XMPPState.Authenticated; if (XMPPClient.UseTLS == true) { /// Start a new stream for some strange reason, but don't close the old one. /// OpenStreamStanza open = new OpenStreamStanza(this.XMPPClient); XMPPClient.SendRawXML(open.XML); } else { XMPPClient.XMPPState = XMPPState.CanBind; } } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}failure") /// Failed to authorize { XMPPClient.XMPPState = XMPPState.AuthenticationFailed; } return(false); }
/// <summary> /// /// </summary> /// <param name="stanza"></param> /// <returns></returns> public override bool NewXMLFragment(XMPPStanza stanza) { /// Looks like the crippled windows phone 7 libraries can't use output from xsd.exe, have to do this the hard way /// //XDocument doc = XDocument.Load(new StringReader(stanza.XML)); //XmlReader reader = XmlReader.Create(new StringReader(stanza.XML)); stanza.XML = stanza.XML.Replace("stream:", ""); // no support for namespaces in windows phone 7, remove them XElement xmlElem = XElement.Parse(stanza.XML); if (XMPPClient.XMPPState >= XMPPState.Authenticated) { if (xmlElem.Name == "features") return true; /// If we hit this and parse the stream featurs a second time we re-authenticate. Just return for now //if (xmlElem.Name == "stream") //{ // XMPPClient.XMPPState = XMPPState.CanBind; //} /// TODO.. see if this new stream supports bind } if (xmlElem.Name== "features") { //foreach (XElement node in xmlElem.Descendants()) //{ // System.Diagnostics.Debug.WriteLine(node.Name); //} var Mechanisms = from mech in xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-sasl}mechanism") select new Mechanism { Name = mech.Value, }; foreach (Mechanism mech in Mechanisms) { if (mech.Name == "DIGEST-MD5") AuthMethodsSupported |= AuthMethod.MD5; else if (mech.Name == "PLAIN") AuthMethodsSupported |= AuthMethod.Plain; // else if (mech.Name == "X-GOOGLE-TOKEN") // AuthMethodsSupported |= AuthMethod.googletoken; } if (AuthMethodsSupported == AuthMethod.NotSpecified) throw new Exception("No acceptable authentication method was supplied"); var tls = xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-tls}starttls"); if (tls.Count() > 0) FeatureTLS = true; if ((FeatureTLS == true) && (XMPPClient.UseTLS == true)) { /// Tell the man we want to negotiate TLS XMPPClient.SendRawXML(StartTLS); } else { StartAuthentication(); } return true; } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-tls}proceed") { XMPPClient.XMPPConnection.StartTLS(); /// After starting TLS, start our normal digest authentication (or plain) /// StartAuthentication(); } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}challenge") { /// Build and send response /// string strChallenge = xmlElem.Value; byte[] bData = Convert.FromBase64String(strChallenge); string strUnbasedChallenge = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length); //realm="ninethumbs.com",nonce="oFun3YWfVm/6nHCkNI/9a4XpcWIdQ5RH9E0IDVKH",qop="auth",charset=utf-8,algorithm=md5-sess //string strExampleResponse = "dXNlcm5hbWU9InRlc3QiLHJlYWxtPSJuaW5ldGh1bWJzLmNvbSIsbm9uY2U9InJaNjgreS9BeGp2SjJ6cjBCVUNxVUhQcG9ocFE4ZFkzR29JclpJcFkiLGNub25jZT0iVkdFRDNqNHUrUHE1M3IxYzNab2NhcGFzaWp1eTh2NjhoYXFzRC9IWjVKTT0iLG5jPTAwMDAwMDAxLGRpZ2VzdC11cmk9InhtcHAvbmluZXRodW1icy5jb20iLHFvcD1hdXRoLHJlc3BvbnNlPTdiM2MzOTVjZjU2MDA2Njg5MDg5MzdlYTk2YjEzZjI2LGNoYXJzZXQ9dXRmLTg="; //bData = Convert.FromBase64String(strExampleResponse); //string strUnbasedResponse = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length); //"username=\"test\",realm=\"ninethumbs.com\",nonce=\"rZ68+y/AxjvJ2zr0BUCqUHPpohpQ8dY3GoIrZIpY\",cnonce=\"VGED3j4u+Pq53r1c3Zocapasijuy8v68haqsD/HZ5JM=\",nc=00000001,digest-uri=\"xmpp/ninethumbs.com\",qop=auth,response=7b3c395cf5600668908937ea96b13f26,charset=utf-8"; if (AuthMethodUsed == AuthMethod.MD5) { string strRealm = XMPPClient.Domain; Match matchrealm = Regex.Match(strUnbasedChallenge, @"realm=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); if (matchrealm.Success == true) strRealm = matchrealm.Groups[1].Value; string strNonce = ""; Match matchnonce = Regex.Match(strUnbasedChallenge, @"nonce=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline); if (matchnonce.Success == true) strNonce = matchnonce.Groups[1].Value; string strQop = "auth"; Match matchqop = Regex.Match(strUnbasedChallenge, @"qop=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); if (matchqop.Success == true) strQop = matchqop.Groups[1].Value; string strAlgo = "md5-sess"; Match matchalgo = Regex.Match(strUnbasedChallenge, @"algorithm=([^\s,]+)", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); if (matchalgo.Success == true) strAlgo = matchalgo.Groups[1].Value; Random rand = new Random(); string strCnonce = rand.Next().ToString("X8").ToLower(); // Compute our MD5 response, then base64 it string strResponse = GenerateMD5Response(strAlgo, XMPPClient.UserName, XMPPClient.Domain, XMPPClient.Password, strNonce, strCnonce); string ResponseMessage = MD5Response.Replace("##RESPONSE##", strResponse); XMPPClient.SendRawXML(ResponseMessage); } else if (AuthMethodUsed == AuthMethod.Plain) { /// Send plain text stuff /// } } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}success") /// Success { XMPPClient.XMPPState = XMPPState.Authenticated; if (XMPPClient.UseTLS == true) { /// Start a new stream for some strange reason, but don't close the old one. /// OpenStreamStanza open = new OpenStreamStanza(this.XMPPClient); XMPPClient.SendRawXML(open.XML); } else { XMPPClient.XMPPState = XMPPState.CanBind; } } else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}failure") /// Failed to authorize { XMPPClient.XMPPState = XMPPState.AuthenticationFailed; } return false; }
public void ParseStanzas(XMPPConnection connection, XMPPClient XMPPClient) { try { string CurrentNodeName = null; XMPPXMLNode objNode = null; while ( (objNode = ReadNextBlock(false)) != null) { //System.Diagnostics.Debug.WriteLine("**ReadNextBlock got: {0}", objNode.Name); if ((objNode.NodeType == XmlNodeType.XmlDeclaration) || (objNode.NodeType == XmlNodeType.Comment) || (objNode.NodeType == XmlNodeType.Whitespace)) continue; if ((objNode.NodeType == XmlNodeType.EndElement) && (objNode.Name == "stream:stream")) { Flush(); /// We've been closed, tell whoever /// connection.GracefulDisconnect(); } else if (objNode.Name == "stream:stream") { System.Diagnostics.Debug.WriteLine("Got stream beggining fragment"); FoundStreamBeginning = true; To = objNode.GetAttribute("to"); From = objNode.GetAttribute("from"); Id = objNode.GetAttribute("id"); Version = objNode.GetAttribute("version"); Language = objNode.GetAttribute("xml:lang"); CurrentNodeName = null; //System.Diagnostics.Debug.WriteLine("Setting CurrentNodeName to null"); Flush(); if (XMPPClient.XMPPState == XMPPState.Authenticated) XMPPClient.XMPPState = XMPPState.CanBind; } else if ( (objNode.NodeType == XmlNodeType.EndElement) && (CurrentNodeName == null) ) /// Must be a complete element { string strXML = FlushGet(); //System.Diagnostics.Debug.WriteLine("Got unpaired end fragment: {0}", strXML); XMPPStanza stanza = new XMPPStanza(strXML); connection.FireStanzaReceived(stanza); } else { if (CurrentNodeName == null) { CurrentNodeName = objNode.Name; //System.Diagnostics.Debug.WriteLine("Setting CurrentNodeName to : {0}", CurrentNodeName); } else { if (objNode.Name == CurrentNodeName) /// Found the end tag { //System.Diagnostics.Debug.WriteLine("Found End tag to CurrentNodeName: {0}, setting to null", CurrentNodeName); // Extract all the text up to this position CurrentNodeName = null; string strXML = FlushGet(); XMPPStanza stanza = new XMPPStanza(strXML); connection.FireStanzaReceived(stanza); } } } } } catch (Exception) { } finally { } }
public void ParseStanzas(XMPPConnection connection, XMPPClient XMPPClient) { try { string CurrentNodeName = null; XMPPXMLNode objNode = null; while ((objNode = ReadNextBlock(false)) != null) { //System.Diagnostics.Debug.WriteLine("**ReadNextBlock got: {0}", objNode.Name); if ((objNode.NodeType == XmlNodeType.XmlDeclaration) || (objNode.NodeType == XmlNodeType.Comment) || (objNode.NodeType == XmlNodeType.Whitespace)) { continue; } if ((objNode.NodeType == XmlNodeType.EndElement) && (objNode.Name == "stream:stream")) { Flush(); /// We've been closed, tell whoever /// connection.GracefulDisconnect(); } else if (objNode.Name == "stream:stream") { System.Diagnostics.Debug.WriteLine("Got stream beggining fragment"); FoundStreamBeginning = true; To = objNode.GetAttribute("to"); From = objNode.GetAttribute("from"); Id = objNode.GetAttribute("id"); Version = objNode.GetAttribute("version"); Language = objNode.GetAttribute("xml:lang"); CurrentNodeName = null; //System.Diagnostics.Debug.WriteLine("Setting CurrentNodeName to null"); Flush(); if (XMPPClient.XMPPState == XMPPState.Authenticated) { XMPPClient.XMPPState = XMPPState.CanBind; } } else if ((objNode.NodeType == XmlNodeType.EndElement) && (CurrentNodeName == null)) /// Must be a complete element { string strXML = FlushGet(); //System.Diagnostics.Debug.WriteLine("Got unpaired end fragment: {0}", strXML); XMPPStanza stanza = new XMPPStanza(strXML); connection.FireStanzaReceived(stanza); } else { if (CurrentNodeName == null) { CurrentNodeName = objNode.Name; //System.Diagnostics.Debug.WriteLine("Setting CurrentNodeName to : {0}", CurrentNodeName); } else { if (objNode.Name == CurrentNodeName) /// Found the end tag { //System.Diagnostics.Debug.WriteLine("Found End tag to CurrentNodeName: {0}, setting to null", CurrentNodeName); // Extract all the text up to this position CurrentNodeName = null; string strXML = FlushGet(); XMPPStanza stanza = new XMPPStanza(strXML); connection.FireStanzaReceived(stanza); } } } } } catch (Exception) { } finally { } }
/// <summary> /// A new XML fragment has been received /// </summary> /// <param name="node"></param> /// <returns>returns true if we handled this fragment, false if other wise</returns> public virtual bool NewXMLFragment(XMPPStanza stanza) { return(false); }