/// <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; } } }
/// <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)); } }
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; } } } }
/// <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); } }
/// <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); }
/// <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)); }
/// <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(); } }
/// <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(); }
/// <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(); }
/// <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); } }
/// <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) }
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); } }
/// <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); } }
/// <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); }
/// <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 }
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); }
/// <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); }
/// <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); } }
/// <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(); }
/// <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); }
/// <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); } }
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); } }
/// <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)); }
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; } } }