コード例 #1
0
        /// <summary>
        /// Creates a new <see cref="ChatRoom"/> from a received <see cref="ByteStream"/>
        /// </summary>
        public ChatRoom(ByteStream stream)
        {
            exchangeNumber = stream.ReadUshort();
            fullName       = stream.ReadString(stream.ReadByte(), Encoding.ASCII);
            instance       = stream.ReadUshort();

            // A small chat room info block will only contain the bare essentials:
            // exchange number, chat room name, and instance number.
            // The chat room class really wants a display name, so parse one here.
            if (stream.HasMoreData)
            {
                detailLevel = stream.ReadByte();
                unknownCode = stream.ReadUshort(); // No idea what this is

                using (TlvBlock block = new TlvBlock(stream.ReadByteArrayToEnd()))
                {
                    flags = block.ReadUshort(CHATROOM_FLAGS);
                    if (block.HasTlv(CHATROOM_CREATION_TIME))
                    {
                        creationTime = block.ReadDateTime(CHATROOM_CREATION_TIME);
                    }
                    maxMessageLength    = block.ReadUshort(CHATROOM_MESSAGE_LENGTH);
                    maxOccupants        = block.ReadUshort(CHATROOM_MAX_OCCUPANTS);
                    displayName         = block.ReadString(CHATROOM_DISPLAYNAME, Encoding.ASCII);
                    creationPermissions = block.ReadByte(CHATROOM_PERMISSIONS);

                    string charset = block.ReadString(CHATROOM_CHARSET1, Encoding.ASCII);
                    if (!String.IsNullOrEmpty(charset))
                    {
                        charSet1 = Encoding.GetEncoding(charset);
                    }
                    language1 = block.ReadString(CHATROOM_LANGUAGE1, Encoding.ASCII);

                    charset = block.ReadString(CHATROOM_CHARSET2, Encoding.ASCII);
                    if (!String.IsNullOrEmpty(charset))
                    {
                        charSet2 = Encoding.GetEncoding(charset);
                    }
                    language2 = block.ReadString(CHATROOM_LANGUAGE2, Encoding.ASCII);

                    contentType = block.ReadString(CHATROOM_CONTENTTYPE, Encoding.ASCII);
                }
            }

            // Make sure there's a display name to show
            if (String.IsNullOrEmpty(displayName))
            {
                Match match = AolUriParser.Match(fullName);
                if (match.Success)
                {
                    //displayName = UtilityMethods.DeHexUri(match.Groups["roomname"].Value);
                    int lastDashBeforeName = fullName.IndexOf('-', 16);
                    displayName = fullName.Substring(lastDashBeforeName + 1);
                }
                else
                {
                    displayName = fullName;
                }
            }
        }
コード例 #2
0
        /// <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));
            }
        }
コード例 #3
0
ファイル: IcqManager.cs プロジェクト: saroj82/OscarLib
        private void ProcessMetaInformationResponse(DataPacket dp)
        {
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                if (tlvs.HasTlv(0x0001))
                {
                    ByteStream stream    = new ByteStream(tlvs.ReadByteArray(0x0001));
                    ushort     cmdLength = stream.ReadUshortLE();
                    String     uin       = stream.ReadUintLE().ToString();
                    ushort     command   = stream.ReadUshortLE();
                    ushort     requestId = stream.ReadUshortLE();

                    MetaResponseType responseType = (MetaResponseType)command;
                    switch (responseType)
                    {
                    case MetaResponseType.OfflineMessage:
                        parent.Messages.ReadIcqOfflineMessage(uin, stream);
                        break;

                    case MetaResponseType.EndOfflineMessage:
                        parent.Messages.EndOfflineMessageSequence(uin, true);
                        break;

                    case MetaResponseType.MetaDataReply:
                        this.ProcessMetaDataReply(uin, dp, stream);
                        break;
                    }
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Processes requested chat room information -- SNAC(0D,09)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(0D,09)</param>
        public void ProcessChatRoomInformation(DataPacket dp)
        {
            ushort maxRooms = 0xFFFF;
            ReadOnlyCollection <Tlv> exchangeTlvs = null;
            ChatRoom newRoom = null;

            // Parse the response
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                maxRooms = tlvs.ReadByte(0x0002);
                if (tlvs.HasTlv(0x0003))
                {
                    exchangeTlvs = tlvs.ReadAllTlvs(0x0003);
                }
                if (tlvs.HasTlv(0x0004))
                {
                    newRoom = new ChatRoom(new ByteStream(tlvs.ReadByteArray(0x0004)));
                }
            }

            // If this packet was received in response to a chat room creation request,
            // request a new chat room connection from the BOS connection
            if (newRoom != null)
            {
                RequestChatRoomConnection(newRoom);
            }
        }
コード例 #5
0
        /// <summary>
        /// Sends a request for a new chat room connection -- SNAC(01,04)
        /// </summary>
        /// <param name="chatRoom">A <see cref="ChatRoom"/> object</param>
        internal void RequestChatRoomConnection(ChatRoom chatRoom)
        {
            SNACHeader sh = new SNACHeader();

            sh.FamilyServiceID = 0x0001;
            sh.FamilySubtypeID = 0x0004;



            ByteStream chatStream = new ByteStream();

            chatStream.WriteUshort(chatRoom.Exchange);
            chatStream.WriteByte((byte)Encoding.ASCII.GetByteCount(chatRoom.FullName));
            chatStream.WriteString(chatRoom.FullName, Encoding.ASCII);
            chatStream.WriteUshort(chatRoom.Instance);

            TlvBlock tlv = new TlvBlock();

            tlv.WriteByteArray(0x0001, chatStream.GetBytes());

            ByteStream mainStream = new ByteStream();

            mainStream.WriteUshort(0x000E);
            mainStream.WriteTlvBlock(tlv);

            parent.StoreRequestID(sh.RequestID, chatRoom);

            DataPacket dp = Marshal.BuildDataPacket(parent, sh, mainStream);

            // This one is always sent on BOS
            dp.ParentConnection = parent.Connections.BOSConnection;
            SNACFunctions.BuildFLAP(dp);
        }
コード例 #6
0
ファイル: StatusManager.cs プロジェクト: saroj82/OscarLib
        /// <summary>
        /// Sets the away message and/or profile of the client
        /// </summary>
        /// <param name="awayMessage">The away message to set</param>
        /// <param name="profile">The profile to set</param>
        private void SetAwayMessageProfileInternal(string awayMessage, string profile)
        {
            // Build the SNAC header
            SNACHeader sh = new SNACHeader();

            sh.FamilyServiceID = SNAC_LOCATION_FAMILY;
            sh.FamilySubtypeID = LOCATION_PARAMETER_USERINFO;

            ByteStream stream = new ByteStream();

            using (TlvBlock tlvs = new TlvBlock())
            {
                if (profile != null)
                {
                    Encoding profileEncoding = UtilityMethods.FindBestOscarEncoding(profile);
                    tlvs.WriteString(LOCATION_PROFILE_ENCODING, Marshal.EncodingToAolMime(profileEncoding), Encoding.ASCII);
                    tlvs.WriteString(LOCATION_PROFILE, profile, profileEncoding);
                }
                if (awayMessage != null)
                {
                    Encoding awayMessageEncoding = UtilityMethods.FindBestOscarEncoding(awayMessage);
                    tlvs.WriteString(LOCATION_AWAYMESSAGE_ENCODING, Marshal.EncodingToAolMime(awayMessageEncoding),
                                     Encoding.ASCII);
                    tlvs.WriteString(LOCATION_AWAYMESSAGE, awayMessage, awayMessageEncoding);
                }
                stream.WriteByteArray(tlvs.GetBytes());
            }

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
        }
コード例 #7
0
        /// <summary>
        /// Processes the parameter information sent by the server -- SNAC(09,03)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(09,03)</param>
        public static void ProcessParametersList(DataPacket dp)
        {
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                ushort max_visiblelist_size   = tlvs.ReadUshort(0x0001);
                ushort max_invisiblelist_size = tlvs.ReadUshort(0x0002);

                dp.ParentSession.ParameterSetArrived();
            }
        }
コード例 #8
0
ファイル: SNAC09.cs プロジェクト: pkt30/OscarLib
        /// <summary>
        /// Processes the parameter information sent by the server -- SNAC(09,03)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(09,03)</param>
        public static void ProcessParametersList(DataPacket dp)
        {
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                ushort max_visiblelist_size = tlvs.ReadUshort(0x0001);
                ushort max_invisiblelist_size = tlvs.ReadUshort(0x0002);

                dp.ParentSession.ParameterSetArrived();
            }
        }
コード例 #9
0
ファイル: StatusManager.cs プロジェクト: saroj82/OscarLib
        /// <summary>
        /// Processes the parameter information sent by the server -- SNAC(03,03)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(03,03)</param>
        private void ProcessBuddyParameterList(DataPacket dp)
        {
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                maxBuddyListEntries   = tlvs.ReadUshort(PARAMETER_MAXBUDDIES);
                maxWatcherListEntries = tlvs.ReadUshort(PARAMETER_MAXWATCHERS);
                maxNotifications      = tlvs.ReadUshort(PARAMETER_MAXNOTIFICATIONS);
            }

            parent.ParameterSetArrived();
        }
コード例 #10
0
ファイル: StatusManager.cs プロジェクト: saroj82/OscarLib
        /// <summary>
        /// Processes the parameter information sent by the server -- SNAC(02,03)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(02,03)</param>
        private void ProcessLocationParameterList(DataPacket dp)
        {
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                maxCapabilities  = tlvs.ReadUshort(PARAMETER_MAXCAPABILITIES);
                maxProfileLength = tlvs.ReadUshort(PARAMETER_PROFILELENGTH);
            }

            ReportClientCapabilities();
            parent.ParameterSetArrived();
        }
コード例 #11
0
        /// <summary>
        /// Writes the ChatRoomInfo's parameters to a byte stream for transmission
        /// </summary>
        internal void WriteToByteStream(ByteStream stream)
        {
            // Write the basic info header
            stream.WriteUshort(exchangeNumber);
            stream.WriteByte((byte)"create".Length);
            stream.WriteString("create", Encoding.ASCII);
            stream.WriteUshort(instance);

            // Write details
            stream.WriteByte(0x01);     // Detail level
            stream.WriteUshort(0x0003); // An unknown code, AIM 5.9 sets this to 0x0003
            using (TlvBlock tlvs = new TlvBlock())
            {
                tlvs.WriteString(CHATROOM_CHARSET1, UtilityMethods.OscarEncodingToString(charSet1), Encoding.ASCII);
                tlvs.WriteString(CHATROOM_DISPLAYNAME, displayName, Encoding.ASCII);
                tlvs.WriteString(CHATROOM_LANGUAGE1, language1, Encoding.ASCII);

                // Everything else is optional
                if (contentType != "text/x-aolrtf")
                {
                    tlvs.WriteString(CHATROOM_CONTENTTYPE, contentType, Encoding.ASCII);
                }

                if (Flags != 0xFFFF)
                {
                    tlvs.WriteUshort(CHATROOM_FLAGS, Flags);
                }
                if (MaxMessageLength != 0xFFFF)
                {
                    tlvs.WriteUshort(CHATROOM_MESSAGE_LENGTH, MaxMessageLength);
                }
                if (MaxOccupants != 0xFFFF)
                {
                    tlvs.WriteUshort(CHATROOM_MAX_OCCUPANTS, MaxOccupants);
                }
                if (CreationPermissions != 0xFF)
                {
                    tlvs.WriteByte(CHATROOM_PERMISSIONS, CreationPermissions);
                }
                if (charSet2 != null)
                {
                    tlvs.WriteString(CHATROOM_CHARSET2, charSet2.WebName, Encoding.ASCII);
                }
                if (!String.IsNullOrEmpty(language2))
                {
                    tlvs.WriteString(CHATROOM_LANGUAGE2, language2, Encoding.ASCII);
                }

                //stream.WriteUshort((ushort) tlvs.GetByteCount());
                stream.WriteTlvBlock(tlvs);
            }
        }
コード例 #12
0
ファイル: ServiceManager.cs プロジェクト: saroj82/OscarLib
        /// <summary>
        /// Processes the server response to a new family request -- SNAC(01,05)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(01,05)</param>
        private void ProcessNewServiceResponse(DataPacket dp)
        {
            int startIndex = 0;

            byte[] SNACData = dp.Data.ReadByteArrayToEnd();
            if (SNACData[0] == 0x00 && SNACData[1] == 0x06)
            {
                startIndex += 2; // What the heck is this...0x0006, some families, some of the time?
            }

            using (TlvBlock tlvs = new TlvBlock(SNACData, startIndex))
            {
                ushort family     = tlvs.ReadUshort(NEW_SERVICE_FAMILY);
                string BOSaddress = tlvs.ReadString(NEW_SERVICE_ADDRESS, Encoding.ASCII);
                byte[] cookie     = tlvs.ReadByteArray(NEW_SERVICE_COOKIE);

                Connection newconn = null;
                object     store   = dp.ParentSession.RetrieveRequestID(dp.SNAC.RequestID);

                if (family != 0x000E)
                {
                    newconn = dp.ParentSession.Connections.CreateNewConnection(family);
                }
                else
                {
                    ChatRoom roominfo = (ChatRoom)store;
                    newconn = dp.ParentSession.Connections.CreateNewChatConnection(roominfo);
                }

                string[] bosinfo = BOSaddress.Split(':');
                int      port    = 0;
                if (bosinfo.Length == 2)
                {
                    port = Int32.Parse(bosinfo[1]);
                }
                else
                {
                    port = dp.ParentSession.ServerSettings.LoginPort;
                }

                newconn.ServerConnectionCompleted += delegate { newconn.ReadHeader(); };
                newconn.Server = bosinfo[0];
                newconn.Port   = port;
                newconn.Cookie = new Cookie(cookie);
                newconn.ConnectToServer();
            }

            // The connection process continues when the server sends SNAC(01,03)
        }
コード例 #13
0
ファイル: ChatNavTests.cs プロジェクト: saroj82/OscarLib
        public void TestChatRoomCreation()
        {
            ByteStream dataStream = new ByteStream(Data.SNAC_0D_09);

            using (TlvBlock tlvs = new TlvBlock(dataStream.ReadByteArrayToEnd()))
            {
                Assert.IsTrue(tlvs.HasTlv(0x0004), "TLV 0x0004 missing from data stream");
                ChatRoom chatRoom = new ChatRoom(new ByteStream(tlvs.ReadByteArray(0x0004)));

                Assert.AreEqual(0x0004, chatRoom.Exchange);
                Assert.AreEqual("!aol://2719:10-4-chat9614646934270543373", chatRoom.FullName);
                Assert.AreEqual(0x0000, chatRoom.Instance);
                Assert.AreEqual("Chat 9614646934270543373", chatRoom.DisplayName);
                Assert.AreEqual(new DateTime(2007, 8, 5, 20, 9, 21, DateTimeKind.Utc), chatRoom.CreationTime);
            }
        }
コード例 #14
0
ファイル: StatusManager.cs プロジェクト: saroj82/OscarLib
        /// <summary>
        /// Processes user information sent by the server -- SNAC(02,06)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(02,06)</param>
        private void ProcessUserInfo(DataPacket dp)
        {
            if (dp.SNAC.Flags != 0)
            {
                Logging.DumpFLAP(dp.Data.GetBytes(), "You've got to be s******g me");
            }

            // Apparently, the userinfo block will always be first,
            // and then possibly TLVs 0x0001 - 0x0005, depending on the request
            byte[]   awaymessage         = null;
            Encoding awaymessageencoding = Encoding.ASCII;

            byte[]       profile         = null;
            Encoding     profileencoding = Encoding.ASCII;
            Capabilities caps            = Capabilities.None;

            UserInfo ui = dp.Data.ReadUserInfo();

            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                profileencoding     = Marshal.AolMimeToEncoding(tlvs.ReadString(LOCATION_PROFILE_ENCODING, Encoding.ASCII));
                profile             = tlvs.ReadByteArray(LOCATION_PROFILE);
                awaymessageencoding = Marshal.AolMimeToEncoding(tlvs.ReadString(LOCATION_AWAYMESSAGE_ENCODING, Encoding.ASCII));
                awaymessage         = tlvs.ReadByteArray(LOCATION_AWAYMESSAGE);
                caps = CapabilityProcessor.ProcessCLSIDList(tlvs.ReadByteArray(LOCATION_CAPABILITIES));
            }

            UserInfoResponse uir = new UserInfoResponse();

            uir.Info = ui;
            if (profile != null)
            {
                uir.Profile         = profileencoding.GetString(profile, 0, profile.Length);
                uir.ProfileEncoding = profileencoding;
            }
            if (awaymessage != null)
            {
                uir.AwayMessage         = awaymessageencoding.GetString(awaymessage, 0, awaymessage.Length);
                uir.AwayMessageEncoding = awaymessageencoding;
            }
            uir.ClientCapabilities = caps;

            if (UserInfoReceived != null)
            {
                UserInfoReceived(this, uir);
            }
        }
コード例 #15
0
        /// <summary>
        /// Send a message to this chatroom using a specific character set and language
        /// </summary>
        /// <param name="message">The message to send</param>
        /// <param name="charset">The character set in which to encode the message</param>
        /// <param name="language">The two-letter code of the language of the message</param>
        private void SendMessage(string message, Encoding charset, string language)
        {
            if (!Connection.Connected)
            {
                // TODO:  The semantics here aren't right
                throw new NotLoggedInException();
            }

            SNACHeader sh = new SNACHeader();

            sh.FamilyServiceID = 0x000E;
            sh.FamilySubtypeID = (ushort)ChatService.MessageFromClient;

            byte[] cookie = new byte[8];
            Random r      = new Random();

            r.NextBytes(cookie);

            ByteStream stream = new ByteStream();

            stream.WriteByteArray(cookie);
            stream.WriteUshort(0x0003);

            TlvBlock tlvs = new TlvBlock();

            using (TlvBlock messageBlock = new TlvBlock())
            {
                Encoding messageEncoding = UtilityMethods.FindBestOscarEncoding(message);

                messageBlock.WriteString(CHATMESSAGE_MESSAGE, message, messageEncoding);
                messageBlock.WriteString(CHATMESSAGE_CHARSET,
                                         UtilityMethods.OscarEncodingToString(messageEncoding), Encoding.ASCII);
                messageBlock.WriteString(CHATMESSAGE_LANGUAGE, language, Encoding.ASCII);
                messageBlock.WriteString(CHATMESSAGE_CONTENTTYPE, "text/x-aolrtf", Encoding.ASCII);
                messageBlock.WriteString(CHATMESSAGE_ENCODING, "binary", Encoding.ASCII);

                tlvs.WriteByteArray(0x0005, messageBlock.GetBytes());
            }
            tlvs.WriteEmpty(0x0001);

            stream.WriteTlvBlock(tlvs);

            DataPacket dp = Marshal.BuildDataPacket(Connection.ParentSession, sh, stream);

            dp.ParentConnection = Connection;
            SNACFunctions.BuildFLAP(dp);
        }
コード例 #16
0
        /// <summary>
        /// Processes a login response -- SNAC(17,03)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,03)</param>
        internal void ProcessLoginResponse(DataPacket dp)
        {
            // Pull apart SNAC(17,03)
            Cookie cookie;
            string BOSaddress;

            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                if (tlvs.HasTlv(0x0008))
                {
                    ushort errorcode = tlvs.ReadUshort(0x0008);
                    parent.OnLoginFailed((LoginErrorCode)errorcode);
                    return;
                }

                BOSaddress = tlvs.ReadString(0x0005, Encoding.ASCII);
                cookie     = Cookie.GetReceivedCookie(tlvs.ReadByteArray(0x0006));
            }

            // Shut down the authorization connection
            // Socket shutdown is initiated by the server
            parent.OnLoginStatusUpdate("Authorized", 0.33);
            dp.ParentConnection.DisconnectFromServer(false);

            // Create a new connection to the BOS server
            Connection newconn = parent.Connections.CreateNewConnection(0x0001);

            string[] bosinfo = BOSaddress.Split(':');

            newconn.ServerConnectionCompleted += delegate(Connection conn) { conn.ReadyForData = true; conn.ReadHeader(); };
            newconn.Server = bosinfo[0];
            if (bosinfo.Length == 2)
            {
                newconn.Port = Int32.Parse(bosinfo[1]);
            }
            else
            {
                newconn.Port = dp.ParentConnection.Port;
            }

            Logging.WriteString("Connect to Server after auth. Address from dp: {0} - Address to connect: {1}:{2}", BOSaddress, newconn.Server, newconn.Port);

            newconn.Cookie = cookie;
            newconn.ConnectToServer();

            // The login process continues when the server sends SNAC(01,03) on the new connection
        }
コード例 #17
0
        private ChatExchangeInfo ParseChatExchangeInfo(ByteStream stream, int tlvLength)
        {
            ChatExchangeInfo retval = new ChatExchangeInfo();

            retval.Exchange = stream.ReadUshort();
            using (TlvBlock tlvs = new TlvBlock(stream.ReadByteArray(tlvLength)))
            {
                retval.ClassPermissions    = tlvs.ReadUshort(0x0002);
                retval.Flags               = tlvs.ReadUshort(0x00C9);
                retval.Name                = tlvs.ReadString(0x00D3, Encoding.ASCII);
                retval.CreationPermissions = tlvs.ReadByte(0x00D5);
                retval.CharSet1            = tlvs.ReadString(0x00D6, Encoding.ASCII);
                retval.Language1           = tlvs.ReadString(0x00D7, Encoding.ASCII);
                retval.CharSet2            = tlvs.ReadString(0x00D8, Encoding.ASCII);
                retval.Language2           = tlvs.ReadString(0x00D9, Encoding.ASCII);
            }

            return(retval);
        }
コード例 #18
0
        /// <summary>
        /// Sends authorization request -- SNAC(17,02)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,07)</param>
        void SendAuthorizationRequest(DataPacket dp)
        {
            // Pull apart SNAC(17,07)
            byte[] key = dp.Data.ReadByteArray(dp.Data.ReadUshort());

            // Construct SNAC(17,02)
            SNACHeader header = new SNACHeader();

            header.FamilyServiceID = SNAC_AUTH_FAMILY;
            header.FamilySubtypeID = AUTH_LOGIN_REQUEST;

            OSCARIdentification id = parent.ClientIdentification;

            ByteStream stream = new ByteStream();

            using (TlvBlock tlvs = new TlvBlock())
            {
                tlvs.WriteString(0x0001, parent.ScreenName, Encoding.ASCII);
                tlvs.WriteString(0x0003, id.ClientName, Encoding.ASCII);
                tlvs.WriteString(0x000F, "en", Encoding.ASCII);
                tlvs.WriteString(0x000E, "us", Encoding.ASCII);
                tlvs.WriteUint(0x0014, id.ClientDistribution);
                tlvs.WriteUshort(0x0016, id.ClientId);
                tlvs.WriteUshort(0x0017, id.ClientMajor);
                tlvs.WriteUshort(0x0018, id.ClientMinor);
                tlvs.WriteUshort(0x0019, id.ClientLesser);
                tlvs.WriteUshort(0x001A, id.ClientBuild);
                tlvs.WriteByteArray(0x0025, parent.HashPassword(key));
                tlvs.WriteByte(0x004A, 0x01);
                tlvs.WriteEmpty(0x004C);
                stream.WriteTlvBlock(tlvs);
            }

            DataPacket newPacket = Marshal.BuildDataPacket(parent, header, stream);

            newPacket.ParentConnection = dp.ParentConnection;
            SNACFunctions.BuildFLAP(newPacket);
        }
コード例 #19
0
        /// <summary>
        /// Processes an update to the chat room information -- SNAC(0E,02)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(0E,02)</param>
        internal void ProcessRoomUpdate(DataPacket dp)
        {
            exchangeNumber = dp.Data.ReadUshort();
            fullName       = dp.Data.ReadString(dp.Data.ReadByte(), Encoding.ASCII);
            instance       = dp.Data.ReadUshort();
            detailLevel    = dp.Data.ReadByte();


            ushort tlvcount = dp.Data.ReadUshort();

            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                displayName      = tlvs.ReadString(CHATROOM_DISPLAYNAME, Encoding.ASCII);
                flags            = tlvs.ReadUshort(CHATROOM_FLAGS);
                creationTime     = tlvs.ReadDateTime(CHATROOM_CREATION_TIME);
                maxMessageLength = tlvs.ReadUshort(CHATROOM_MESSAGE_LENGTH);

                string charset = tlvs.ReadString(CHATROOM_CHARSET1, Encoding.ASCII);
                if (!String.IsNullOrEmpty(charset))
                {
                    charSet1 = Encoding.GetEncoding(charset);
                }
                language1 = tlvs.ReadString(CHATROOM_LANGUAGE1, Encoding.ASCII);

                charset = tlvs.ReadString(CHATROOM_CHARSET2, Encoding.ASCII);
                if (!String.IsNullOrEmpty(charset))
                {
                    charSet2 = Encoding.GetEncoding(charset);
                }
                language2 = tlvs.ReadString(CHATROOM_LANGUAGE2, Encoding.ASCII);

                contentType = tlvs.ReadString(CHATROOM_CONTENTTYPE, Encoding.ASCII);

                ushort maxvisiblemessagelength = tlvs.ReadUshort(0x00DA);
                string description             = tlvs.ReadString(0x00D3, Encoding.ASCII);
            }
        }
コード例 #20
0
        /// <summary>
        /// Kicks off the authorization hash request when the initial connection is complete
        /// </summary>
        void loginConnection_ServerConnectionCompleted(Connection conn)
        {
            conn.ReadyForData = true;

            /*** Send SNAC(17,06) to get the auth key ***/
            SNACHeader sh = new SNACHeader();

            sh.FamilyServiceID = SNAC_AUTH_FAMILY;
            sh.FamilySubtypeID = AUTH_KEY_REQUEST;

            ByteStream stream = new ByteStream();

            using (TlvBlock tlvs = new TlvBlock())
            {
                tlvs.WriteString(0x0001, parent.ScreenName, Encoding.ASCII);
                tlvs.WriteEmpty(0x004B);
                tlvs.WriteEmpty(0x005A);
                stream.WriteTlvBlock(tlvs);
            }

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));

            conn.ReadHeader();
        }
コード例 #21
0
ファイル: ChatRoomInfo.cs プロジェクト: pkt30/OscarLib
        /// <summary>
        /// Send a message to this chatroom using a specific character set and language
        /// </summary>
        /// <param name="message">The message to send</param>
        /// <param name="charset">The character set in which to encode the message</param>
        /// <param name="language">The two-letter code of the language of the message</param>
        private void SendMessage(string message, Encoding charset, string language)
        {
            if (!Connection.Connected)
            {
                // TODO:  The semantics here aren't right
                throw new NotLoggedInException();
            }

            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = 0x000E;
            sh.FamilySubtypeID = (ushort) ChatService.MessageFromClient;

            byte[] cookie = new byte[8];
            Random r = new Random();
            r.NextBytes(cookie);

            ByteStream stream = new ByteStream();
            stream.WriteByteArray(cookie);
            stream.WriteUshort(0x0003);

            TlvBlock tlvs = new TlvBlock();
            using (TlvBlock messageBlock = new TlvBlock())
            {
                Encoding messageEncoding = UtilityMethods.FindBestOscarEncoding(message);

                messageBlock.WriteString(CHATMESSAGE_MESSAGE, message, messageEncoding);
                messageBlock.WriteString(CHATMESSAGE_CHARSET,
                    UtilityMethods.OscarEncodingToString(messageEncoding), Encoding.ASCII);
                messageBlock.WriteString(CHATMESSAGE_LANGUAGE, language, Encoding.ASCII);
                messageBlock.WriteString(CHATMESSAGE_CONTENTTYPE, "text/x-aolrtf", Encoding.ASCII);
                messageBlock.WriteString(CHATMESSAGE_ENCODING, "binary", Encoding.ASCII);

                tlvs.WriteByteArray(0x0005, messageBlock.GetBytes());
            }
            tlvs.WriteEmpty(0x0001);

            stream.WriteTlvBlock(tlvs);

            DataPacket dp = Marshal.BuildDataPacket(Connection.ParentSession, sh, stream);
            dp.ParentConnection = Connection;
            SNACFunctions.BuildFLAP(dp);
        }
コード例 #22
0
ファイル: ChatRoomInfo.cs プロジェクト: pkt30/OscarLib
        /// <summary>
        /// Writes the ChatRoomInfo's parameters to a byte stream for transmission
        /// </summary>
        internal void WriteToByteStream(ByteStream stream)
        {
            // Write the basic info header
            stream.WriteUshort(exchangeNumber);
            stream.WriteByte((byte) "create".Length);
            stream.WriteString("create", Encoding.ASCII);
            stream.WriteUshort(instance);

            // Write details
            stream.WriteByte(0x01); // Detail level
            stream.WriteUshort(0x0003); // An unknown code, AIM 5.9 sets this to 0x0003
            using (TlvBlock tlvs = new TlvBlock())
            {
                tlvs.WriteString(CHATROOM_CHARSET1, UtilityMethods.OscarEncodingToString(charSet1), Encoding.ASCII);
                tlvs.WriteString(CHATROOM_DISPLAYNAME, displayName, Encoding.ASCII);
                tlvs.WriteString(CHATROOM_LANGUAGE1, language1, Encoding.ASCII);

                // Everything else is optional
                if (contentType != "text/x-aolrtf")
                {
                    tlvs.WriteString(CHATROOM_CONTENTTYPE, contentType, Encoding.ASCII);
                }

                if (Flags != 0xFFFF)
                {
                    tlvs.WriteUshort(CHATROOM_FLAGS, Flags);
                }
                if (MaxMessageLength != 0xFFFF)
                {
                    tlvs.WriteUshort(CHATROOM_MESSAGE_LENGTH, MaxMessageLength);
                }
                if (MaxOccupants != 0xFFFF)
                {
                    tlvs.WriteUshort(CHATROOM_MAX_OCCUPANTS, MaxOccupants);
                }
                if (CreationPermissions != 0xFF)
                {
                    tlvs.WriteByte(CHATROOM_PERMISSIONS, CreationPermissions);
                }
                if (charSet2 != null)
                {
                    tlvs.WriteString(CHATROOM_CHARSET2, charSet2.WebName, Encoding.ASCII);
                }
                if (!String.IsNullOrEmpty(language2))
                {
                    tlvs.WriteString(CHATROOM_LANGUAGE2, language2, Encoding.ASCII);
                }

                //stream.WriteUshort((ushort) tlvs.GetByteCount());
                stream.WriteTlvBlock(tlvs);
            }
        }
コード例 #23
0
ファイル: ChatRoomInfo.cs プロジェクト: pkt30/OscarLib
        /// <summary>
        /// Processes an update to the chat room information -- SNAC(0E,02)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(0E,02)</param>
        internal void ProcessRoomUpdate(DataPacket dp)
        {
            exchangeNumber = dp.Data.ReadUshort();
            fullName = dp.Data.ReadString(dp.Data.ReadByte(), Encoding.ASCII);
            instance = dp.Data.ReadUshort();
            detailLevel = dp.Data.ReadByte();

            ushort tlvcount = dp.Data.ReadUshort();
            using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()))
            {
                displayName = tlvs.ReadString(CHATROOM_DISPLAYNAME, Encoding.ASCII);
                flags = tlvs.ReadUshort(CHATROOM_FLAGS);
                creationTime = tlvs.ReadDateTime(CHATROOM_CREATION_TIME);
                maxMessageLength = tlvs.ReadUshort(CHATROOM_MESSAGE_LENGTH);

                string charset = tlvs.ReadString(CHATROOM_CHARSET1, Encoding.ASCII);
                if (!String.IsNullOrEmpty(charset))
                {
                    charSet1 = Encoding.GetEncoding(charset);
                }
                language1 = tlvs.ReadString(CHATROOM_LANGUAGE1, Encoding.ASCII);

                charset = tlvs.ReadString(CHATROOM_CHARSET2, Encoding.ASCII);
                if (!String.IsNullOrEmpty(charset))
                {
                    charSet2 = Encoding.GetEncoding(charset);
                }
                language2 = tlvs.ReadString(CHATROOM_LANGUAGE2, Encoding.ASCII);

                contentType = tlvs.ReadString(CHATROOM_CONTENTTYPE, Encoding.ASCII);

                ushort maxvisiblemessagelength = tlvs.ReadUshort(0x00DA);
                string description = tlvs.ReadString(0x00D3, Encoding.ASCII);
            }
        }
コード例 #24
0
ファイル: ChatRoomInfo.cs プロジェクト: pkt30/OscarLib
        /// <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));
            }
        }
コード例 #25
0
ファイル: ChatRoomInfo.cs プロジェクト: pkt30/OscarLib
        /// <summary>
        /// Creates a new <see cref="ChatRoom"/> from a received <see cref="ByteStream"/>
        /// </summary>
        public ChatRoom(ByteStream stream)
        {
            exchangeNumber = stream.ReadUshort();
            fullName = stream.ReadString(stream.ReadByte(), Encoding.ASCII);
            instance = stream.ReadUshort();

            // A small chat room info block will only contain the bare essentials:
            // exchange number, chat room name, and instance number.
            // The chat room class really wants a display name, so parse one here.
            if (stream.HasMoreData)
            {
                detailLevel = stream.ReadByte();
                unknownCode = stream.ReadUshort(); // No idea what this is

                using (TlvBlock block = new TlvBlock(stream.ReadByteArrayToEnd()))
                {
                    flags = block.ReadUshort(CHATROOM_FLAGS);
                    if (block.HasTlv(CHATROOM_CREATION_TIME))
                    {
                        creationTime = block.ReadDateTime(CHATROOM_CREATION_TIME);
                    }
                    maxMessageLength = block.ReadUshort(CHATROOM_MESSAGE_LENGTH);
                    maxOccupants = block.ReadUshort(CHATROOM_MAX_OCCUPANTS);
                    displayName = block.ReadString(CHATROOM_DISPLAYNAME, Encoding.ASCII);
                    creationPermissions = block.ReadByte(CHATROOM_PERMISSIONS);

                    string charset = block.ReadString(CHATROOM_CHARSET1, Encoding.ASCII);
                    if (!String.IsNullOrEmpty(charset))
                    {
                        charSet1 = Encoding.GetEncoding(charset);
                    }
                    language1 = block.ReadString(CHATROOM_LANGUAGE1, Encoding.ASCII);

                    charset = block.ReadString(CHATROOM_CHARSET2, Encoding.ASCII);
                    if (!String.IsNullOrEmpty(charset))
                    {
                        charSet2 = Encoding.GetEncoding(charset);
                    }
                    language2 = block.ReadString(CHATROOM_LANGUAGE2, Encoding.ASCII);

                    contentType = block.ReadString(CHATROOM_CONTENTTYPE, Encoding.ASCII);
                }
            }

            // Make sure there's a display name to show
            if (String.IsNullOrEmpty(displayName))
            {
                Match match = AolUriParser.Match(fullName);
                if (match.Success)
                {
                    //displayName = UtilityMethods.DeHexUri(match.Groups["roomname"].Value);
                    int lastDashBeforeName = fullName.IndexOf('-', 16);
                    displayName = fullName.Substring(lastDashBeforeName + 1);
                }
                else
                {
                    displayName = fullName;
                }
            }
        }
コード例 #26
0
ファイル: IcqManager.cs プロジェクト: saroj82/OscarLib
        private void ProcessDirectoryQueryResponseUserDetails(TlvBlock tlvs)
        {
            FullUserInfo ui = new FullUserInfo();

            // Email
            ui.Email = tlvs.ReadString(0x50, Encoding.ASCII);       // Verified e-mail
            if (string.IsNullOrEmpty(ui.Email))
            {
                ui.Email = tlvs.ReadString(0x55, Encoding.ASCII);   // Pending e-mail
            }
            // Names
            ui.Screenname = tlvs.ReadString(0x32, Encoding.ASCII);
            ui.Firstname  = tlvs.ReadString(0x64, Encoding.UTF8);
            ui.Lastname   = tlvs.ReadString(0x6e, Encoding.UTF8);
            ui.Nickname   = tlvs.ReadString(0x78, Encoding.UTF8);

            // Home Address
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0x96), ref ui);
            // Origin Address
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0xa0), ref ui);
            // Phone Numbers
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0xc8), ref ui);
            // Emails
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0x8c), ref ui);
            // Work
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0x118), ref ui);
            // Education
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0x10e), ref ui);
            // Interests
            ProcessDirectoryQueryResponseUserDetails(tlvs.ReadTlv(0x122), ref ui);

            ui.Timezone = tlvs.ReadSshort(0x17c, 0);

            switch (tlvs.ReadByte(0x82))
            {
            case 1: ui.Gender = 'F'; break;

            case 2: ui.Gender = 'M'; break;

            default: ui.Gender = '\0'; break;
            }

            ui.Website = tlvs.ReadString(0xfa, Encoding.ASCII);

            double birthday = tlvs.ReadDouble(0x1A4, 0);

            if (birthday != 0)
            {
                ui.Birthday = DateTime.FromOADate(birthday + 2);
                ui.Age      = (byte)(DateTime.Now.Year - ui.Birthday.Year);
                if (ui.Birthday.DayOfYear > DateTime.Now.DayOfYear)
                {
                    ui.Age--;
                }
            }

            ui.Language1 = (LanguageList)tlvs.ReadUshort(0xaa, 0);
            ui.Language2 = (LanguageList)tlvs.ReadUshort(0xb4, 0);
            ui.Language3 = (LanguageList)tlvs.ReadUshort(0xbe, 0);

            ui.MaritalStatus = (MartialList)tlvs.ReadUshort(0x12c, 0);
            ui.About         = tlvs.ReadString(0x186, Encoding.UTF8);

            ui.StatusNote   = tlvs.ReadString(0x226, Encoding.UTF8);
            ui.PrivacyLevel = tlvs.ReadUshort(0x1f9, 0);
            ui.Auth         = tlvs.ReadUshort(0x19a, 0);
            ui.WebAware     = tlvs.ReadByte(0x212, 0);
            ui.AllowSpam    = tlvs.ReadByte(0x1ea, 0);
            ui.CodePage     = tlvs.ReadUshort(0x1c2, 0);

            if (FullUserInfoReceived != null)
            {
                FullUserInfoReceived(this, ui);
            }
        }
コード例 #27
0
ファイル: IcqManager.cs プロジェクト: saroj82/OscarLib
        /// <summary>
        /// Set my icq contact informations.
        /// </summary>
        /// <param name="ui">My Details</param>
        /// <remarks>
        /// <para>The following properties can't be set:</para>
        /// <para><seealso cref="FullUserInfo.Screenname"/>, <seealso cref="FullUserInfo.Email"/> (use <seealso cref="SendUserEmail"/> instead), <seealso cref="FullUserInfo.Age"/>, <seealso cref="FullUserInfo.CodePage"/>,
        /// <seealso cref="FullUserInfo.Timezone"/></para>
        /// </remarks>
        public void SendUserInfo(FullUserInfo ui)
        {
            TlvBlock tlvs = new TlvBlock();

            // Names
            tlvs.WriteString(0x64, ui.Firstname, Encoding.UTF8);
            tlvs.WriteString(0x6e, ui.Lastname, Encoding.UTF8);
            tlvs.WriteString(0x78, ui.Nickname, Encoding.UTF8);

            // Home Address
            tlvs.WriteByteArray(0x96, ProcessDirectoryUpdateRequestUserDetails(0x96, ui));
            // Origin Address
            tlvs.WriteByteArray(0xa0, ProcessDirectoryUpdateRequestUserDetails(0xa0, ui));
            // Phone Numbers
            tlvs.WriteByteArray(0xc8, ProcessDirectoryUpdateRequestUserDetails(0xc8, ui));
            // Emails
            tlvs.WriteByteArray(0x8c, ProcessDirectoryUpdateRequestUserDetails(0x8c, ui));
            // Work
            tlvs.WriteByteArray(0x118, ProcessDirectoryUpdateRequestUserDetails(0x118, ui));
            // Education
            tlvs.WriteByteArray(0x10e, ProcessDirectoryUpdateRequestUserDetails(0x10e, ui));
            // Interests
            tlvs.WriteByteArray(0x122, ProcessDirectoryUpdateRequestUserDetails(0x122, ui));

            // Timezone
            TimeSpan ts = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);

            if (TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now))
            {
                ts -= TimeZone.CurrentTimeZone.GetDaylightChanges(DateTime.Now.Year).Delta;
            }
            tlvs.WriteSshort(0x17c, (short)(ts.TotalMinutes / -30));

            switch (ui.Gender.ToString().ToUpper())
            {
            case "F": tlvs.WriteByte(0x82, 1); break;

            case "M": tlvs.WriteByte(0x82, 2); break;

            default: tlvs.WriteByte(0x82, 0); break;
            }

            tlvs.WriteString(0xfa, ui.Website, Encoding.ASCII);

            if (ui.Birthday == DateTime.MinValue)
            {
                tlvs.WriteDouble(0x1a4, 0);
            }
            else
            {
                tlvs.WriteDouble(0x1a4, ui.Birthday.ToOADate() - 2);
            }

            tlvs.WriteUshort(0xaa, (ushort)ui.Language1);
            tlvs.WriteUshort(0xb4, (ushort)ui.Language2);
            tlvs.WriteUshort(0xbe, (ushort)ui.Language3);

            tlvs.WriteUshort(0x12c, (ushort)ui.MaritalStatus);
            tlvs.WriteString(0x186, ui.About, Encoding.UTF8);

            tlvs.WriteString(0x226, ui.StatusNote, Encoding.UTF8);
            tlvs.WriteUshort(0x1f9, ui.PrivacyLevel);
            tlvs.WriteUshort(0x19a, ui.Auth);
            tlvs.WriteByte(0x212, ui.WebAware);
            tlvs.WriteByte(0x1ea, ui.AllowSpam);
            tlvs.WriteUshort(0x1c2, (ushort)Encoding.Default.CodePage);     //ui.CodePage

            ByteStream stream = new ByteStream();

            stream.WriteUshort(0x0003);
            stream.WriteUshort((ushort)tlvs.GetByteCount());
            stream.WriteByteArray(tlvs.GetBytes());

            /* * * * * Header * * * * */
            SNACHeader sh = CreateIcqMetaHeader();

            stream = CreateDirectoryHeader(DirectoryRequestType.SetInfoRequest, stream);
            stream = CreateMetaInfoHeader(parent, sh, MetaInfoRequestType.DirectoryUpdateRequest, stream);

            //parent.StoreRequestID(sh.RequestID, DirecotyQueryType.InfoUser);
            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
        }
コード例 #28
0
ファイル: IcqManager.cs プロジェクト: saroj82/OscarLib
        void ProcessDirectoryQueryResponse(DataPacket dp, ByteStream data)
        {
            DirecotyQueryType responseType = (DirecotyQueryType)parent.RetrieveRequestID(dp.SNAC.RequestID);

            Byte success = data.ReadByte();     // 0x0a

            ushort responseLength = data.ReadUshortLE();

            Debug.Assert(responseLength == data.RemainingBytes);

            // Read Sub Snac Header
            SNACHeader shsub = data.ReadSnacHeader();

            // Reads Snac Extra Bytes
            ushort snacExtraBytesLength = data.ReadUshort();

            if (snacExtraBytesLength > 0)
            {
                // Version or Anything
                if (snacExtraBytesLength == 6)
                {
                    ushort snacExtraBytesTyp   = data.ReadUshort();
                    ushort snacExtraBytesLen   = data.ReadUshort();
                    ushort snacExtraBytesValue = data.ReadUshort(); // VersionsNr
                }
                else
                {
                    data.ReadByteArray(snacExtraBytesLength);
                }
            }

            Byte result = data.ReadByte();      // 0x01

            ushort errorLength = data.ReadUshort();

            if (errorLength > 0)
            {
                data.ReadByteArray(errorLength);
                Logging.WriteString("Warning: Data in error message present!");
            }

            if (data.RemainingBytes <= 0x16)
            {
                parent.OnError(ServerErrorCode.InvalidSNACFormat, dp);
                return;
            }

            // Unknown Stuff
            data.ReadByteArray(0x10);

            // TODO: check itemcount, pagecount against the cookie data ???
            uint   itemcount = data.ReadUint();
            ushort pagecount = data.ReadUshort();

            if (responseType == DirecotyQueryType.Search)
            {
                Logging.WriteString("Directory Search: %d contacts found (%u pages)", itemcount, pagecount);
            }

            if (data.RemainingBytes <= 2)
            {
                parent.OnError(ServerErrorCode.InvalidSNACFormat, dp);
                return;
            }

            // Maybe the bock count of the following data
            ushort dataAvailable = data.ReadUshort();

            if (dataAvailable == 0)
            {
                parent.OnError(ServerErrorCode.InvalidSNACFormat, dp);
                return;
            }

            ushort dataLength = data.ReadUshort();

            Debug.Assert(dataLength == data.RemainingBytes);

            if (dataAvailable != 1 || dataLength != data.RemainingBytes)
            {
                parent.OnError(ServerErrorCode.InvalidSNACFormat, dp);
                return;
            }

            using (TlvBlock tlvs = new TlvBlock(data.ReadByteArrayToEnd()))
            {
                switch (responseType)
                {
                case DirecotyQueryType.InfoOwner:
                case DirecotyQueryType.InfoUser:
                case DirecotyQueryType.InfoMulti:
                    ProcessDirectoryQueryResponseUserDetails(tlvs);
                    break;

                case DirecotyQueryType.Search:
                    break;
                }
            }
        }