private void handleTag(string tagName, ICQDataStream streamContent)
        {
            switch(tagName)
            {
                case "AnswerFlags":
                    byte[] baAnswerFlags = streamContent.readFixedBinary(5);
                    break;
                case "SendFlags":
                case "Status":
                case "Read":
                    byte[] baSendFlags = streamContent.readFixedBinary(5); // TODO: this is a special Uint format: First 0x69 then four bytes of uint
                    break;
                case "Body":
                    byte[] baBodyHeader = new byte[0x13];
                    streamContent.Read(baBodyHeader, 0, 0x3);

                    if (baBodyHeader[1] == 0xEB)    // as opposed to 0xEA
                    {
                        streamContent.Read(baBodyHeader, 3, 0x10);
                        //if (isOutgoing != ((baBodyHeader[4] & 0x01) == 0x01))
                        //    throw new InvalidDataException("Outgoing flag is different in packet head and body head");
                    }

                    byte[] bodyContent = streamContent.readBinary();
                    if (null != bodyContent)
                    {
                        // bodyContent contains 0x58 as start tag for only ANSI text (ICQ Pro 2003a) or RTF and ANSI (ICQ Pro 2003b)
                        ICQDataStream strmBody = new ICQDataStream(bodyContent);
                        if (0x58 == bodyContent[0])     // maybe bodyContent[0] and bodyContent[1] together are a package type number?
                        {
                            strmBody.Seek(2, SeekOrigin.Begin);
                            UInt32 iICQ2003bIndicator = strmBody.readUInt32();
                            if (0 != iICQ2003bIndicator)    // this means the RTF starts immediately. ICQ Pro 2003b style.
                            {
                                strmBody.Seek(-4, SeekOrigin.Current);
                                parseICQ2003bBody(strmBody);
                            }
                        }
                        else if (0x23 == bodyContent[0])    // this means:  ANSI + RTF + UTF-8
                            strmBody.Seek(2, SeekOrigin.Begin);
                        else if (0x03 == bodyContent[0])    // observed cases are only "The user has added you to his/her Contact list"
                                                            // + "You added him/her to your Contact List"
                        {
                            MessageType = "Added2ContactList";
                            return;
                        }
                        else if (0x01 == bodyContent[0])
                        {
                            MessageType = "AuthorizationRequestAccepted";
                            return;
                        }
                        else if (0x00 == bodyContent[0])
                        {
                            MessageType = "Contacts";
                            return;
                        }
                        else if (0x11 == bodyContent[0])
                        {
                            MessageType = "BirthdayReminder";
                            return;
                        }
                        else
                            throw new NotImplementedException("Message start tag " + bodyContent[0].ToString() + " not implemented");

                        parseICQ2003aBody(strmBody);
                    }

                    break;
                case "CLSID":
                    byte clsidStartTag = Convert.ToByte(streamContent.ReadByte());
                    byte[] clsidData = streamContent.readBinary();
                    break;
                case "ExtId":
                    byte[] extidContent = streamContent.readFixedBinary(3);
                    break;
                case "ExtName":
                    byte extName = Convert.ToByte(streamContent.ReadByte());
                    MessageType = streamContent.readString();
                    break;
                case "ExtVers":
                    byte[] extVers = streamContent.readFixedBinary( 5);
                    break;
                case "Folder":
                    byte[] folder = streamContent.readFixedBinary(3);
                    break;
                case "MsgUserName":
                    byte startTag = (byte)streamContent.ReadByte();
                    OtherPartyName = streamContent.readString();
                    break;
                case "Time":
                    byte timeStartTag = (byte)streamContent.ReadByte();
                    if (timeStartTag != 0x69)
                        throw new ArgumentException("Time tag expected to be 0x69, but it was " + timeStartTag.ToString());
                    TimeOfMessage = streamContent.readUnixTime();
                    break;
                default:
                    throw new NotImplementedException("Unknown tag \"" + tagName + "\"");
            }
        }
示例#2
0
        private void parseMessagePacket(ICQDataStream streamContent)
        {
            Text = streamContent.readString();

            byte[] messageFlags = streamContent.readFixedBinary(0x0a);    // Mostly 0x00, but last two bytes are 0xC8 0x01(?), 0x23 0x02, or 0x19 0x02, or 0x03 0x02
            // the first four bytes seem to be ff ff ff ff in case of an SMS
            isOutgoing = ((messageFlags[4] & 0x01) == 0x01);

            TimeOfMessage = streamContent.readUnixTime();

            byte[] zeroes = streamContent.readFixedBinary(0x13);
            if (streamContent.Position > streamContent.Length - 8)
                return; // not enough to read anymore
            if (zeroes.Any(zeroByte => zeroByte != 0x00))
                return;     // The RTF messages are always zero in these bytes
            UInt16 possibleRTFLength = streamContent.readUInt16();
            byte[] baPossibleStrangeHeader = streamContent.readFixedBinary(6);      // in later versions of ICQ, these prepend the RTF
            AfterTextFooterType footerType = parseFooterTypeFromStrangeHeader(possibleRTFLength, baPossibleStrangeHeader);

            if (footerType == AfterTextFooterType.NoFooterBeforeRTF || footerType == AfterTextFooterType.SMSText)
                streamContent.Seek(-8, SeekOrigin.Current); // seek back the 8 bytes for the header
            //else if ()
            //    streamContent.Seek(-6, SeekOrigin.Current); // Only an UTF-8 text will be provided
            else if (footerType == AfterTextFooterType.NoFooterAtAll)
                return;
            //else
            //{
            //    UInt32 nextStrangeNumber = streamContent.readUInt32();
            //    if (0x00c0c0c0 != (0xFFc0c0c0 & nextStrangeNumber))
            //        return;
            //    // if the two strange numbers are there... just go on and parse the RTF :-)
            //}

            try
            {
                string textUTF8Temp;
                string textRTFTemp;
                streamContent.parsePossiblyRemainingRTFandUTF8(out textRTFTemp, out textUTF8Temp);
                TextRTF = textRTFTemp;  // TextRTF will be null before that operation anyway
                if (null != textUTF8Temp)
                    Text = textUTF8Temp;
            }
            catch (Exception ex)
            {
                throw new InvalidDataException("Parsed message text \"" + Text + "\" after which a footer of type "
                    + footerType.ToString() + " was detected, but there was a problem parsing the RTF/UTF-8 footer.", ex);
            }

            //            byte[] tail = streamContent.readFixedBinary(0x08);  // zeroes for incoming messages, E4 04 00 00 00 80 80 00 for outgoing
        }