/// <summary> /// Processes a message received from a chat room -- SNAC(0E,06) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(0E,06)</param> internal void ProcessIncomingMessage(DataPacket dp) { UserInfo sender = new UserInfo(); byte[] message; Encoding encoding = Encoding.ASCII; string language = ""; byte[] cookie = dp.Data.ReadByteArray(8); ushort channel = dp.Data.ReadUshort(); using (TlvBlock outerTlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { using (ByteStream userStream = new ByteStream(outerTlvs.ReadByteArray(0x0003))) { sender = userStream.ReadUserInfo(); } using (TlvBlock innerTlvs = new TlvBlock(outerTlvs.ReadByteArray(0x0005))) { message = innerTlvs.ReadByteArray(0x0001); encoding = Marshal.AolMimeToEncoding(innerTlvs.ReadString(0x0002, Encoding.ASCII)); language = innerTlvs.ReadString(0x0003, Encoding.ASCII); } } if (MessageReceived != null) { IM msg = new IM(sender); msg.Message = Encoding.Unicode.GetString(Encoding.Convert(encoding, Encoding.Unicode, message)); msg.Cookie = Cookie.GetReceivedCookie(cookie); MessageReceived(this, new MessageReceivedEventArgs(msg)); } }
/// <summary> /// Initializes a new offline instant message from a realtime instant message /// </summary> public OfflineIM(IM message) : base(message.ScreenName) { icbmCookie = message.Cookie; isAutoResponse = message.IsAutoResponse; this.message = message.Message; userInfo = message.SenderInfo; }
/// <summary> /// Creates a new MessageReceivedEventArgs /// </summary> public MessageReceivedEventArgs(IM message) { this.message = message; }
/// <summary> /// Raises the <see cref="MessageReceived"/> event /// </summary> /// <param name="message">The <see cref="IM"/> that was received</param> protected internal void OnMessageReceived(IM message) { // Check to see if there is a DirectIM connection that has been superceded by this message DirectIMConnection conn = parent.Connections.GetDirectIMByScreenname(message.ScreenName); if (conn != null && !conn.Connected) { parent.Connections.RemoveDirectConnection(conn.Cookie); parent.OnDirectIMSessionClosed(conn.Other, conn.Cookie); conn = null; } // Alert the user of the message if (MessageReceived != null) { MessageReceived(this, new MessageReceivedEventArgs(message)); } }
/// <summary> /// Processes an ICBM message sent by the server -- SNAC(04,07) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(04,07)</param> private void ProcessMessage(DataPacket dp) { // Pull apart the fixed part of the message byte[] message_cookie = dp.Data.ReadByteArray(8); ushort channel = dp.Data.ReadUshort(); UserInfo ui = dp.Data.ReadUserInfo(); IM message = new IM(ui); message.Cookie = Cookie.GetReceivedCookie(message_cookie); // End of the fixed part. Pull apart the channel-specific data switch (channel) { case 0x0001: ProcessChannelOneMessage(dp.Data, ui); break; case 0x0002: ProcessChannelTwoMessage(dp.Data, ui, dp); break; case 0x0004: //SMS From ISRAEL ProcessChannelFourMessage(dp.Data, ui); break; default: parent.OnWarning(ServerErrorCode.UnknownMessageChannel, dp); break; } }
/// <summary> /// Processes an incoming ICBM message on channel 1 -- SNAC(04,07) /// </summary> /// <param name="stream">A received <see cref="ByteStream"/></param> /// <param name="ui">The UserInfo block that came with this message</param> private void ProcessChannelOneMessage(ByteStream stream, UserInfo ui) { IM message = new IM(ui); using (TlvBlock tlvs = new TlvBlock(stream.ReadByteArrayToEnd())) { message.IsAutoResponse = tlvs.HasTlv(0x0004); // If this message was received offline, cast it to an OfflineIM if (tlvs.HasTlv(0x0006)) { message = new OfflineIM(message); if (tlvs.HasTlv(0x0016)) { ((OfflineIM)message).ReceivedOn = tlvs.ReadDateTime(0x0016); } } GetChannelOneMessage(new ByteStream(tlvs.ReadByteArray(0x0002)), ref message); } // Figure out what to do with it if (message is OfflineIM) { OfflineIM offlineMessage = message as OfflineIM; if (isRetrievingOfflineMessages) { // Queue it for delivery AcceptIcbmOIM(offlineMessage); } else { // A single offline message? Okay then if (OfflineMessagesReceived != null) { List<OfflineIM> tmpList = new List<OfflineIM>(1); tmpList.Add(offlineMessage); OfflineMessagesReceived(this, new OfflineMessagesReceivedEventArgs(parent.ScreenName, new Collection<OfflineIM>(tmpList))); } } // Offline messages don't get delivered via OnMessageReceived - if the offline messages event // isn't hooked up, tough stuff. return; } else { OnMessageReceived(message); } }
/// <summary> /// Retrieves the message text from SNAC(04,07) TLV 02 /// </summary> /// <param name="stream">A received <see cref="ByteStream"/></param> /// <param name="message">An <see cref="IM"/> object to be populated</param> private void GetChannelOneMessage(ByteStream stream, ref IM message) { while (stream.HasMoreData) { byte identifier = stream.ReadByte(); byte version = stream.ReadByte(); ushort length = stream.ReadUshort(); switch (identifier) { case 0x01: // Message text ushort charset = stream.ReadUshort(); ushort language = stream.ReadUshort(); Encoding incoming = IM.GetEncodingFromCharset(charset, language); message.Message = Encoding.Unicode.GetString( Encoding.Convert(incoming, Encoding.Unicode, stream.ReadByteArray(length - 4))); break; default: // Unhandled case stream.AdvanceOffset(length); break; } } }
/// <summary> /// Retrieves the message text from SNAC(04,07) TLV 05 /// </summary> /// <param name="stream">A received <see cref="ByteStream"/></param> /// <param name="message">An <see cref="IM"/> object to be populated</param> private void GetChannelfourMessage(ByteStream stream, ref IM message) { stream.ReadByteArray(46); //fixed unknon part ushort length = stream.ReadUshort(); ushort charset = stream.ReadUshort(); stream.ReadByte(); ushort charsubset = (ushort)0;//stream.ReadUshort(); Encoding incoming = IM.GetEncodingFromCharset(charset, charsubset); string xml = Encoding.Unicode.GetString( Encoding.Convert(incoming, Encoding.Unicode, stream.ReadByteArray(length))); // parse xml System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); doc.LoadXml(xml); System.Xml.XmlNode node = doc.SelectSingleNode("/sms_message/text"); if (node != null) { message.Message = node.InnerText; } node = doc.SelectSingleNode("/sms_message/sender"); if (node != null) { message.ScreenName = node.InnerText; } }