/// <summary> /// Processes a newly received offline message for the specified UIN /// </summary> /// <remarks>This is called from the ICQ manager, which receives the incoming /// offline message packet and sends it here for processing</remarks> internal void ReadIcqOfflineMessage(String uin, ByteStream stream) { String sender = stream.ReadUintLE().ToString(); // Read in the date information (GMT) ushort year = stream.ReadUshortLE(); byte month = stream.ReadByte(); byte day = stream.ReadByte(); byte hourGmt = stream.ReadByte(); byte minute = stream.ReadByte(); DateTime received = new DateTime(year, month, day, hourGmt, minute, 0, DateTimeKind.Utc); // Read in message type information byte messageType = stream.ReadByte(); byte messageFlags = stream.ReadByte(); Encoding messageEncoding = GetOfflineMessageEncoding(messageType); OfflineIM im = new OfflineIM(sender); im.ReceivedOn = received; im.Message = Encoding.Unicode.GetString( Encoding.Convert(messageEncoding, Encoding.Unicode, stream.ReadByteArray(stream.ReadUshortLE() - 1))); im.IsAutoResponse = (messageFlags == 0x03) || (messageType == 0xE8); // Store it for delivery to the client AcceptIcbmOIM(im); }
/// <summary> /// Caches an offline message until the entire collection has been retrieved /// </summary> private void AcceptIcbmOIM(OfflineIM message) { try { lock (offlineMessages) { offlineMessagesTimer.Change(750, 750); if (!offlineMessages.ContainsKey(parent.ScreenName)) { offlineMessages.Add(parent.ScreenName, new Collection<OfflineIM>()); } offlineMessages[parent.ScreenName].Add(message); } } catch (Exception ex) { Logging.WriteString("Couldn't add offline Message to Queue: {0}", ex.Message); Logging.WriteString(ex.StackTrace); } }
/// <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); } }