/// <summary> /// Processes a notification of e-mail information change -- SNAC(18,07) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(18,07)</param> public static void ProcessEmailInformation(DataPacket dp) { // There are 24 bytes of cookies prior to the TLV list, an 8-byte cookie // and a 16-byte cookie. The 16 byte cookie is identifying information // that may be useful byte[] cookie = dp.Data.ReadByteArray(8); byte[] idcookie = dp.Data.ReadByteArray(16); TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()); string alertTitle = tlvs.ReadString(0x0005, Encoding.ASCII); string url = tlvs.ReadString(0x0007, Encoding.ASCII); string alertUrl = tlvs.ReadString(0x000D, Encoding.ASCII); ushort numMessages = tlvs.ReadUshort(0x0080); byte unread = tlvs.ReadByte(0x0081); if (unread == 0) { numMessages = 0; } string domain = tlvs.ReadString(0x0082, Encoding.ASCII); ushort flags = tlvs.ReadUshort(0x0084); if (numMessages == 0xFFFF) { // If this message was received, at least one email message is available // even if TLV 0x0080 wasn't in the message numMessages = 1; } }
/// <summary> /// Sets the user's directory information -- SNAC(02,09) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="allow"><c>true</c> if other users may search this information, <c>false</c> if not</param> /// <param name="firstname">A first name</param> /// <param name="middlename">A middle name</param> /// <param name="lastname">A last name</param> /// <param name="maidenname">A maiden name</param> /// <param name="nickname">A nickname</param> /// <param name="city">A city</param> /// <param name="state">A state</param> /// <param name="country">A country (two-letter code)</param> /// <param name="zip">A ZIP code</param> /// <param name="address">An address</param> public static void SetDirectoryInformation( Session sess, bool allow, string firstname, string middlename, string lastname, string maidenname, string nickname, string city, string state, string country, string zip, string address) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.LocationService; sh.FamilySubtypeID = (ushort)LocationServices.UpdateDirectoryInfoRequest; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteUshort(0x001A, (ushort)((allow) ? 0x0001 : 0x0000)); tlvs.WriteString(DIRECTORY_FIRSTNAME, firstname, Encoding.ASCII); tlvs.WriteString(DIRECTORY_MIDDLENAME, middlename, Encoding.ASCII); tlvs.WriteString(DIRECTORY_LASTNAME, lastname, Encoding.ASCII); tlvs.WriteString(DIRECTORY_MAIDENNAME, maidenname, Encoding.ASCII); tlvs.WriteString(DIRECTORY_COUNTRY, country, Encoding.ASCII); tlvs.WriteString(DIRECTORY_STATE, state, Encoding.ASCII); tlvs.WriteString(DIRECTORY_CITY, city, Encoding.ASCII); tlvs.WriteString(DIRECTORY_NICKNAME, nickname, Encoding.ASCII); tlvs.WriteString(DIRECTORY_ZIPCODE, zip, Encoding.ASCII); tlvs.WriteString(DIRECTORY_ADDRESS, address, Encoding.ASCII); stream.WriteByteArray(tlvs.GetBytes()); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Writes a <see cref="TlvBlock"/> into the stream /// </summary> public void WriteTlvBlock(TlvBlock value) { lock (this) { dataSegments.Add(new TlvBlockSegment(value)); byteCount += value.GetByteCount(); } }
/// <summary> /// Processes a popup message sent by the server -- SNAC(08,02) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(08,02)</param> public static void ProcessPopupMessage(DataPacket dp) { TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()); string message = tlvs.ReadString(0x0001, Encoding.ASCII); string url = tlvs.ReadString(0x0002, Encoding.ASCII); ushort width = tlvs.ReadUshort(0x0003); ushort height = tlvs.ReadUshort(0x0004); ushort delay = tlvs.ReadUshort(0x0005); dp.ParentSession.OnPopupMessage(width, height, delay, url, message); }
/// <summary> /// Processes a popup message sent by the server -- SNAC(08,02) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(08,02)</param> public static void ProcessPopupMessage(DataPacket dp) { TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()); string message = tlvs.ReadString(0x0001, Encoding.ASCII); string url = tlvs.ReadString(0x0002, Encoding.ASCII); ushort width = tlvs.ReadUshort(0x0003); ushort height = tlvs.ReadUshort(0x0004); ushort delay = tlvs.ReadUshort(0x0005); dp.ParentSession.OnPopupMessage(width, height, delay, url, message); }
/// <summary> /// Reads a tlv block /// </summary> /// <param name="tlvBlockLength">the total byte length of the block</param> /// <returns>the tlv block</returns> public TlvBlock ReadTlvBlockByLength(int tlvBlockLength) { if (dataIndex + tlvBlockLength > dataBuffer.Length) { throw new ByteStreamReadException(dataBuffer.Length, dataIndex, tlvBlockLength); } TlvBlock retval = new TlvBlock(dataBuffer, dataIndex, tlvBlockLength); dataIndex += tlvBlockLength; return(retval); }
/// <summary> /// Processes the Message Of The Day -- SNAC(01,13) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(01,13)</param> public static void ProcessMOTD(DataPacket dp) { ushort motdtype = dp.Data.ReadUshort(); using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { string messagestring = tlvs.ReadString(MOTD_MESSAGE, Encoding.ASCII); // Signal the client that the MOTD has come through dp.ParentSession.OnMessageOfTheDayReceived(motdtype, messagestring); } }
/// <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> public static 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(SERVICE_RESPONSE_FAMILY); string BOSaddress = tlvs.ReadString(SERVICE_RESPONSE_ADDRESS, Encoding.ASCII); byte[] cookie = tlvs.ReadByteArray(SERVICE_RESPONSE_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; dp.ParentSession.Connections.CreateNewChatConnection(roominfo); newconn = roominfo.Connection; } string[] bosinfo = BOSaddress.Split(':'); int port = 0; if (bosinfo.Length == 2) { port = Int32.Parse(bosinfo[1]); } else { port = dp.ParentSession.LoginPort; } newconn.ServerConnectionCompleted += new ServerConnectionCompletedHandler(newconn_ServerConnnectionCompleted); 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) }
/// <summary> /// Reads the error code and subcode from a SNAC(XX,01) packet /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(XX,01)</param> /// <param name="errorCode">The main error code contained in the SNAC</param> /// <param name="subCode">The subcode contained in the SNAC, or 0 if there is no subcode present</param> public static void GetSNACErrorCodes(DataPacket dp, out ushort errorCode, out ushort subCode) { errorCode = dp.Data.ReadUshort(); subCode = 0; if (dp.Data.HasMoreData) { using (TlvBlock tlvs = dp.Data.ReadTlvBlockByLength(dp.Data.GetRemainingByteCount())) { if (tlvs.HasTlv(0x0008)) { subCode = tlvs.ReadUshort(0x0008); } } } }
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> /// Sends an AIM invitation to a receipient -- SNAC(06,02) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="email">The email address of the person to invite</param> /// <param name="text">The text of the invitation</param> public static void SendInvitiationRequest(ISession sess, string email, string text) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.PrivacyManagementService; sh.FamilySubtypeID = (ushort) PrivacyManagementService.ServiceParametersRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x0011, email, Encoding.ASCII); tlvs.WriteString(0x0015, text, Encoding.ASCII); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Performs a directory search by interest -- SNAC(0F,02) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="interest">The interest to search for</param> public static void SearchByInterest(Session sess, string interest) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.DirectoryUserSearch; sh.FamilySubtypeID = (ushort)DirectorySearch.SearchUserRequest; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x001C, "us-ascii", Encoding.ASCII); tlvs.WriteUshort(0x000A, 0x0001); tlvs.WriteString(0x0001, interest, Encoding.ASCII); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Sends an AIM invitation to a receipient -- SNAC(06,02) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="email">The email address of the person to invite</param> /// <param name="text">The text of the invitation</param> public static void SendInvitiationRequest(ISession sess, string email, string text) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.PrivacyManagementService; sh.FamilySubtypeID = (ushort)PrivacyManagementService.ServiceParametersRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x0011, email, Encoding.ASCII); tlvs.WriteString(0x0015, text, Encoding.ASCII); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Sends authorization request -- SNAC(17,02) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,07)</param> public static 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 = (ushort)SNACFamily.AuthorizationRegistrationService; header.FamilySubtypeID = (ushort)AuthorizationRegistrationService.LoginRequest; header.Flags = 0; header.RequestID = Session.GetNextRequestID(); OSCARIdentification id = dp.ParentSession.ClientIdentification; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x0001, dp.ParentSession.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, dp.ParentSession.HashPassword(key)); tlvs.WriteByte(0x004A, 0x01); tlvs.WriteEmpty(0x004C); stream.WriteTlvBlock(tlvs); } DataPacket newPacket = Marshal.BuildDataPacket(dp.ParentSession, header, stream); newPacket.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(newPacket); }
/// <summary> /// Send MD5 key request -- SNAC(17,06) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> public static void SendMD5Request(ISession sess) { /*** Send SNAC(17,06) to get the auth key ***/ SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.AuthorizationRegistrationService; sh.FamilySubtypeID = (ushort)AuthorizationRegistrationService.MD5AuthkeyRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x0001, sess.ScreenName, Encoding.ASCII); tlvs.WriteEmpty(0x004B); tlvs.WriteEmpty(0x005A); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Processes a login response -- SNAC(17,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,03)</param> public static 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); dp.ParentSession.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 dp.ParentSession.OnLoginStatusUpdate("Authorized", 0.33); dp.ParentConnection.DisconnectFromServer(false); // Create a new connection to the BOS server Connection newconn = dp.ParentSession.Connections.CreateNewConnection(0x0001); string[] bosinfo = BOSaddress.Split(':'); newconn.ServerConnectionCompleted += new ServerConnectionCompletedHandler(newconn_ServerConnnectionCompleted); newconn.Server = bosinfo[0]; newconn.Port = Int32.Parse(bosinfo[1]); newconn.Cookie = cookie; newconn.ConnectToServer(); // The connection process continues when the server sends SNAC(01,03) }
/// <summary> /// Processes a login response -- SNAC(17,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,03)</param> public static 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); dp.ParentSession.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 dp.ParentSession.OnLoginStatusUpdate("Authorized", 0.33); dp.ParentConnection.DisconnectFromServer(false); // Create a new connection to the BOS server Connection newconn = dp.ParentSession.Connections.CreateNewConnection(0x0001); string[] bosinfo = BOSaddress.Split(':'); newconn.ServerConnectionCompleted += new ServerConnectionCompletedHandler(newconn_ServerConnnectionCompleted); newconn.Server = bosinfo[0]; newconn.Port = Int32.Parse(bosinfo[1]); newconn.Cookie = cookie; newconn.ConnectToServer(); // The connection process continues when the server sends SNAC(01,03) }
/// <summary> /// Read a specified number of TLVs from the stream into a <see cref="TlvBlock"/> /// </summary> public TlvBlock ReadTlvBlock(int numberOfTlvs) { int tlvBlockLength = 0; int currentIndex = dataIndex; for (int i = 0; i < numberOfTlvs; i++) { // Skip the Type tlvBlockLength += 2; currentIndex += 2; // Calculate the size of the Value ushort currentTlvLength = (ushort)((dataBuffer[currentIndex] << 8) | (dataBuffer[currentIndex + 1])); // Skip the Length and the size of the Value currentIndex += currentTlvLength + 2; tlvBlockLength += currentTlvLength + 2; } TlvBlock retval = new TlvBlock(dataBuffer, dataIndex, tlvBlockLength); dataIndex += tlvBlockLength; return(retval); }
/// <summary> /// Sets the user's interests list -- SNAC(02,0F) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="allow"><c>true</c> if other users may search this information, <c>false</c> if not</param> /// <param name="interests">An array of interest names</param> /// <remarks> /// OSCAR allows a user to set up to five interests. If <paramref name="interests"/> contains /// more than five items, only the first five are used. /// </remarks> public static void SetInterestsInformation(Session sess, bool allow, string[] interests) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.LocationService; sh.FamilySubtypeID = (ushort)LocationServices.UpdateInterestsRequest; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteUshort(INTERESTS_ALLOWSEARCH, (ushort)((allow) ? 0x0001 : 0x0000)); for (int i = 0; i < interests.Length && i < 5; i++) { tlvs.WriteString(INTERESTS_INTEREST, interests[i], Encoding.ASCII); } stream.WriteByteArray(tlvs.GetBytes()); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Processes the parameter information sent by the server -- SNAC(13,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(13,03)</param> public static void ProcessParametersList(DataPacket dp) { List <ushort> maximums = new List <ushort>(); using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { using (ByteStream stream = new ByteStream(tlvs.ReadByteArray(0x0004))) { while (stream.HasMoreData) { maximums.Add(stream.ReadUshort()); } } } // Do something with these capabilities dp.ParentSession.Limits.MaxBuddies = maximums[0]; dp.ParentSession.Limits.MaxGroups = maximums[1]; dp.ParentSession.Limits.MaxPermits = maximums[2]; dp.ParentSession.Limits.MaxDenys = maximums[3]; dp.ParentSession.ParameterSetArrived(); }
/// <summary> /// Sends authorization request -- SNAC(17,02) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,07)</param> public static 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 = (ushort) SNACFamily.AuthorizationRegistrationService; header.FamilySubtypeID = (ushort) AuthorizationRegistrationService.LoginRequest; header.Flags = 0; header.RequestID = Session.GetNextRequestID(); OSCARIdentification id = dp.ParentSession.ClientIdentification; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x0001, dp.ParentSession.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, dp.ParentSession.HashPassword(key)); tlvs.WriteByte(0x004A, 0x01); tlvs.WriteEmpty(0x004C); stream.WriteTlvBlock(tlvs); } DataPacket newPacket = Marshal.BuildDataPacket(dp.ParentSession, header, stream); newPacket.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(newPacket); }
/// <summary> /// Reads a <see cref="UserInfo"/> from the stream /// </summary> public UserInfo ReadUserInfo() { UserInfo retval = new UserInfo(); byte screenNameLength = ReadByte(); if (screenNameLength == 0) { return(null); } retval.ScreenName = ReadString(screenNameLength, Encoding.ASCII); retval.WarningLevel = ReadUshort(); using (TlvBlock tlvBlock = ReadTlvBlock(ReadUshort())) { retval.Class = (UserClass)tlvBlock.ReadUshort(0x0001); retval.CreateTime = tlvBlock.ReadDateTime(0x0002); retval.SignonTime = tlvBlock.ReadDateTime(0x0003); retval.IdleTime = tlvBlock.ReadUshort(0x0004); if (retval.IdleTime == 0xFFFF) { retval.IdleTime = 0; } retval.RegisterTime = tlvBlock.ReadDateTime(0x0005); retval.ICQUserStatus = tlvBlock.ReadUint(0x0006); retval.ExternalIPAddress = tlvBlock.ReadUint(0x000A); // Read the DC info from 0x000C retval.ClientCapabilities = CapabilityProcessor.ProcessCLSIDList(tlvBlock.ReadByteArray(0x000D)); retval.OnlineTime = tlvBlock.ReadUint(0x000F); if (tlvBlock.HasTlv(0x001D)) { ReadIconInfo(tlvBlock.ReadByteArray(0x001D), retval); } } return(retval); }
/// <summary> /// Sends a direct connection request /// </summary> /// <param name="conn">A <see cref="DirectConnection"/> object that will handle the request</param> public void RequestDirectConnectionInvite(DirectConnection conn) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, conn.Cookie, 0x0002, conn.Other.ScreenName); using (ByteStream tlv05 = new ByteStream()) { tlv05.WriteUshort(RendezvousData.UshortFromType(RendezvousType.Invite)); tlv05.WriteByteArray(conn.Cookie.ToByteArray()); tlv05.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteUshort(DC_SEQUENCE_NUMBER, RendezvousData.UshortFromSequence(conn.Sequence)); if (conn.Sequence == RendezvousSequence.DirectOrStage1) { tlvs.WriteEmpty(0x000F); } if (!String.IsNullOrEmpty(conn.Message)) { tlvs.WriteString(DC_MESSAGE, conn.Message, Encoding.ASCII); } uint ipaddress = 0; if (conn.Method == DirectConnectionMethod.Proxied) { ipaddress = ConvertIPAddress(conn.AOLProxyIP); } else { ipaddress = ConvertIPAddress(conn.ClientIP); } tlvs.WriteUint(DC_PROXY_IP_ADDRESS, ipaddress); tlvs.WriteUint(DC_PROXY_IP_ADDRESS_COMPLIMENT, ~ipaddress); if (conn.Sequence == RendezvousSequence.DirectOrStage1) { tlvs.WriteUint(DC_CLIENT_IP_ADDRESS, ConvertIPAddress(conn.ClientIP)); } if (conn.Sequence != RendezvousSequence.Stage3) { tlvs.WriteUshort(DC_PORT, (ushort)conn.Port); tlvs.WriteUshort(DC_PORT_COMPLIMENT, (ushort)(~conn.Port)); } if (conn.Method == DirectConnectionMethod.Proxied) { tlvs.WriteEmpty(DC_USE_PROXY_FLAG); } if (conn is FileTransferConnection && conn.Sequence == RendezvousSequence.DirectOrStage1) { FileTransferConnection ftc = conn as FileTransferConnection; using (ByteStream tlv2711 = new ByteStream()) { tlv2711.WriteUshort((ushort)((ftc.TotalFiles > 1) ? 0x0002 : 0x0001)); tlv2711.WriteUshort((ushort)ftc.TotalFiles); tlv2711.WriteUint(ftc.TotalFileSize); tlv2711.WriteString(ftc.FileHeader.Name, Encoding.ASCII); tlv2711.WriteByte(0x00); tlvs.WriteByteArray(0x2711, tlv2711.GetBytes()); } tlvs.WriteString(0x2712, ftc.LocalFileNameEncoding.WebName, Encoding.ASCII); } tlv05.WriteByteArray(tlvs.GetBytes()); } stream.WriteUshort(0x0005); stream.WriteUshort((ushort)tlv05.GetByteCount()); stream.WriteByteArray(tlv05.GetBytes()); } // Acknowledgement request stream.WriteUint(0x00030000); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
public TlvBlockSegment(TlvBlock value) { this.value = value; }
/// <summary> /// Invites an AIM user to an AOL chatroom /// </summary> /// <param name="chatroom">The <see cref="ChatRoom"/> describing the chatroom</param> /// <param name="screenName">The screenname of the user to invite</param> /// <param name="message">A message to send along with the invitation</param> public Cookie InviteToChatRoom(ChatRoom chatroom, string screenName, string message) { if (!parent.LoggedIn) { throw new NotLoggedInException(); } SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; Cookie cookie = Cookie.CreateCookieForSending(); Encoding enc = Encoding.ASCII; byte destlength = (byte) enc.GetByteCount(screenName); ushort messagelength = (ushort) enc.GetByteCount(message); byte roomnamelength = (byte) enc.GetByteCount(chatroom.FullName); ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, cookie, 0x0002, screenName); ByteStream header = new ByteStream(); header.WriteUshort(0x0000); header.WriteByteArray(cookie.ToByteArray()); header.WriteUint(0x748F2420); header.WriteUint(0x628711D1); header.WriteUint(0x82224445); header.WriteUint(0x53540000); using (TlvBlock tlv05 = new TlvBlock()) { tlv05.WriteUshort(0x000A, 0x0001); tlv05.WriteEmpty(0x000F); tlv05.WriteString(0x000C, message, enc); ByteStream tlv2711 = new ByteStream(); tlv2711.WriteUshort(chatroom.Exchange); tlv2711.WriteByte(roomnamelength); tlv2711.WriteString(chatroom.FullName, enc); tlv2711.WriteUshort(chatroom.Instance); tlv05.WriteByteArray(0x2711, tlv2711.GetBytes()); header.WriteByteArray(tlv05.GetBytes()); } stream.WriteUshort(0x0005); stream.WriteUshort((ushort) header.GetByteCount()); stream.WriteByteArray(header.GetBytes()); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); return cookie; }
/// <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 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) }
/// <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> /// Sends a status report to the OSCAR server -- SNAC(0B,03) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <remarks>libfaim does not send this report</remarks> public static void SendStatusReport(ISession sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.UsageStatsService; sh.FamilySubtypeID = (ushort)UsageStatsService.UsageReport; sh.Flags = 0; sh.RequestID = Session.GetNextRequestID(); // Get the necessary strings together string sn = sess.ScreenName; // Here we start lying until I can figure out how to get *all* the values in .NET string osversion = Environment.OSVersion.ToString(); string osname = "Windows 98"; //osversion.Substring(0, osversion.LastIndexOf(" ") - 1); string osver = "4.10.67766446"; //osversion.Substring(osversion.LastIndexOf(" ") + 1); string procname = "Intel Pentium"; string winsockname = "Microsoft Corporation BSD Socket API for Windows"; string winsockver = "4.1.1998"; Encoding enc = Encoding.ASCII; byte snlength = (byte)enc.GetByteCount(sn); ushort osversionlength = (ushort)enc.GetByteCount(osversion); ushort osnamelength = (ushort)enc.GetByteCount(osname); ushort osverlength = (ushort)enc.GetByteCount(osver); ushort procnamelength = (ushort)enc.GetByteCount(procname); ushort winsocknamelength = (ushort)enc.GetByteCount(winsockname); ushort winsockverlength = (ushort)enc.GetByteCount(winsockver); ByteStream mainStream = new ByteStream(); using (ByteStream stream = new ByteStream()) { TimeSpan t = (DateTime.Now - new DateTime(1970, 1, 1)); stream.WriteUint((uint)t.Seconds); t = (DateTime.UtcNow - new DateTime(1970, 1, 1).ToUniversalTime()); stream.WriteUint((uint)t.Seconds); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteByte(snlength); stream.WriteString(sn, Encoding.ASCII); stream.WriteUshort(osnamelength); stream.WriteString(osname, Encoding.ASCII); stream.WriteUshort(osverlength); stream.WriteString(osver, Encoding.ASCII); stream.WriteUshort(procnamelength); stream.WriteString(procname, Encoding.ASCII); stream.WriteUshort(winsocknamelength); stream.WriteString(winsockname, Encoding.ASCII); stream.WriteUshort(winsockverlength); stream.WriteString(winsockver, Encoding.ASCII); stream.WriteUint(0x00000002); stream.WriteUint(0x00010001); stream.WriteUint(0x00020002); using (TlvBlock tlv = new TlvBlock()) { tlv.WriteByteArray(0x0009, stream.GetBytes()); mainStream.WriteTlvBlock(tlv); } } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, mainStream)); }
/// <summary> /// Reads a tlv block /// </summary> /// <param name="tlvBlockLength">the total byte length of the block</param> /// <returns>the tlv block</returns> public TlvBlock ReadTlvBlockByLength(int tlvBlockLength) { if (dataIndex + tlvBlockLength > dataBuffer.Length) { throw new ByteStreamReadException(dataBuffer.Length, dataIndex, tlvBlockLength); } TlvBlock retval = new TlvBlock(dataBuffer, dataIndex, tlvBlockLength); dataIndex += tlvBlockLength; return retval; }
/// <summary> /// Send MD5 key request -- SNAC(17,06) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> public static void SendMD5Request(ISession sess) { /*** Send SNAC(17,06) to get the auth key ***/ SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.AuthorizationRegistrationService; sh.FamilySubtypeID = (ushort) AuthorizationRegistrationService.MD5AuthkeyRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x0001, sess.ScreenName, Encoding.ASCII); tlvs.WriteEmpty(0x004B); tlvs.WriteEmpty(0x005A); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Processes an incoming ICBM message on channel 1 -- SNAC(04,07) /// </summary> /// <param name="stream">A received <see cref="ByteStream"/></param> /// <param name="ui">The UserInfo block that came with this message</param> private void ProcessChannelOneMessage(ByteStream stream, UserInfo ui) { IM message = new IM(ui); using (TlvBlock tlvs = new TlvBlock(stream.ReadByteArrayToEnd())) { message.IsAutoResponse = tlvs.HasTlv(0x0004); // If this message was received offline, cast it to an OfflineIM if (tlvs.HasTlv(0x0006)) { message = new OfflineIM(message); if (tlvs.HasTlv(0x0016)) { ((OfflineIM)message).ReceivedOn = tlvs.ReadDateTime(0x0016); } } GetChannelOneMessage(new ByteStream(tlvs.ReadByteArray(0x0002)), ref message); } // Figure out what to do with it if (message is OfflineIM) { OfflineIM offlineMessage = message as OfflineIM; if (isRetrievingOfflineMessages) { // Queue it for delivery AcceptIcbmOIM(offlineMessage); } else { // A single offline message? Okay then if (OfflineMessagesReceived != null) { List<OfflineIM> tmpList = new List<OfflineIM>(1); tmpList.Add(offlineMessage); OfflineMessagesReceived(this, new OfflineMessagesReceivedEventArgs(parent.ScreenName, new Collection<OfflineIM>(tmpList))); } } // Offline messages don't get delivered via OnMessageReceived - if the offline messages event // isn't hooked up, tough stuff. return; } else { OnMessageReceived(message); } }
/// <summary> /// Performs a directory search by interest -- SNAC(0F,02) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="interest">The interest to search for</param> public static void SearchByInterest(Session sess, string interest) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.DirectoryUserSearch; sh.FamilySubtypeID = (ushort) DirectorySearch.SearchUserRequest; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x001C, "us-ascii", Encoding.ASCII); tlvs.WriteUshort(0x000A, 0x0001); tlvs.WriteString(0x0001, interest, Encoding.ASCII); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Process a ICBM that was sent over channel two - rich text messages, chat/filetransfer invites, buddy icons /// </summary> private void ProcessChannelTwoMessage(ByteStream stream, UserInfo ui, DataPacket dp) { TlvBlock tlvs = new TlvBlock(stream.ReadByteArrayToEnd()); //KSD-SYSTEMS - commented at 02.12.2009 -> Hangs up at errorCode reading //ushort errorCode = tlvs.ReadUshort(0x000B); DirectConnection conn = ProcessChannel2Tlv05(new ByteStream(tlvs.ReadByteArray(0x0005)), ui, dp); }
/// <summary> /// Sends an ICBM on channel 1 -- SNAC(04,06) /// </summary> /// <param name="destination">The screenname to receive the IM</param> /// <param name="message">The message to send</param> /// <param name="flags">A <see cref="OutgoingMessageFlags"/> enumeration specifying what /// additional information should be sent with the message</param> private Cookie SendMessageThroughServer(string destination, string message, OutgoingMessageFlags flags) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; byte[] default_features = new byte[] { 0x01, 0x01, 0x01, 0x02 }; Cookie cookie = Cookie.CreateCookieForSending(); Encoding encoding = UtilityMethods.FindBestOscarEncoding(message); ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, cookie, 0x0001, destination); using (TlvBlock tlvs = new TlvBlock()) { // Write in TLV 0x0002: a text message using (TlvBlock tlv02 = new TlvBlock()) { tlv02.WriteByteArray(0x0501, default_features); ByteStream feature0101 = new ByteStream(); feature0101.WriteUshort(Marshal.EncodingToCharset(encoding)); feature0101.WriteUshort(0x0000); feature0101.WriteString(message, encoding); tlv02.WriteByteArray(0x0101, feature0101.GetBytes()); tlvs.WriteByteArray(0x0002, tlv02.GetBytes()); } // Pack in optional TLVs if ((flags & OutgoingMessageFlags.AutoResponse) != 0) { tlvs.WriteEmpty(0x0004); } else { // Request a notification of delivery - note that this can't happen // with an AutoResponse flag set, otherwise the message is bounced tlvs.WriteEmpty(0x0003); } if ((flags & OutgoingMessageFlags.DeliverOffline) != 0 && (flags & OutgoingMessageFlags.AutoResponse) == 0) { // Try to store if the user is offline tlvs.WriteEmpty(0x0006); } // Add the TLVs to the byte stream stream.WriteByteArray(tlvs.GetBytes()); } // Cache the message for delivery updates messageStatuses.Add(sh.RequestID, new MessageStatusEventArgs(cookie, destination)); // Send that sucker off SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); return cookie; }
/// <summary> /// Processes the inner TLV list in TLV 0x0005 and returns a new DirectConnection /// </summary> private DirectConnection ProcessChannel2Tlv05(ByteStream stream, UserInfo ui, DataPacket dp) { byte[] invitemessage; Encoding encoding = Encoding.ASCII; string language = "en"; DirectConnection directconn = null; // Pull the type, cookie, and capability array RendezvousType rtype = RendezvousData.TypeFromUshort(stream.ReadUshort()); Cookie cookie = Cookie.GetReceivedCookie(stream.ReadByteArray(8)); byte[] capabilitiesArray = stream.ReadByteArray(16); Capabilities capabilities = CapabilityProcessor.ProcessCLSIDList(capabilitiesArray); // Create the correct type of connection based on the capability if (capabilities == Capabilities.SendFiles) { if ((directconn = parent.Connections.GetDirectConnectionByCookie(cookie)) == null) { directconn = parent.Connections.CreateNewFileTransferConnection( DirectConnectionMethod.Direct, DirectConnectRole.Receiver); } } else if (capabilities == Capabilities.DirectIM) { if ((directconn = parent.Connections.GetDirectConnectionByCookie(cookie)) == null) { directconn = parent.Connections.CreateNewDirectIMConnection( DirectConnectionMethod.Direct, DirectConnectRole.Receiver); } } else if (capabilities == Capabilities.Chat) { directconn = parent.Connections.CreateNewChatInvitationConnection(DirectConnectRole.Receiver); } else { // Currently unsupported parent.OnWarning(ServerErrorCode.UnknownRendezvousChannel, dp); return null; } directconn.Other = ui; directconn.Cookie = cookie; directconn.Type = rtype; ByteStream serviceData = null; Encoding serviceDataEncoding = Encoding.ASCII; // Process the inner TLV list using (TlvBlock tlvs = new TlvBlock(stream.ReadByteArrayToEnd())) { directconn.AOLProxyIP = tlvs.ReadIPAddress(DC_PROXY_IP_ADDRESS); // proxy ip directconn.ClientIP = tlvs.ReadIPAddress(DC_CLIENT_IP_ADDRESS); // internal ip directconn.VerifiedIP = tlvs.ReadIPAddress(0x0004); // external ip directconn.Port = tlvs.ReadUshort(DC_PORT); directconn.Sequence = RendezvousData.SequenceFromUshort(tlvs.ReadUshort(DC_SEQUENCE_NUMBER)); invitemessage = tlvs.ReadByteArray(DC_MESSAGE); if (tlvs.HasTlv(0x000D)) { encoding = Encoding.GetEncoding(tlvs.ReadString(0x000D, Encoding.ASCII)); } language = tlvs.ReadString(0x000E, Encoding.ASCII); directconn.Method = (tlvs.HasTlv(DC_USE_PROXY_FLAG)) ? DirectConnectionMethod.Proxied : DirectConnectionMethod.Direct; serviceData = new ByteStream(tlvs.ReadByteArray(0x2711)); if (tlvs.HasTlv(0x2712)) { serviceDataEncoding = Encoding.GetEncoding(tlvs.ReadString(0x2712, Encoding.ASCII)); } } if (invitemessage != null) { directconn.Message = encoding.GetString(invitemessage, 0, invitemessage.Length); } // Process the extra data, if necessary if (directconn is FileTransferConnection || directconn is DirectIMConnection) { ProcessDirectConnectionRequest(directconn, serviceData); } else if (directconn is ChatInvitationConnection) { ChatInvitationConnection cic = directconn as ChatInvitationConnection; cic.ChatInvite = new ChatInvitation(); cic.ChatInvite.Message = directconn.Message; cic.ChatInvite.Encoding = encoding; cic.ChatInvite.Language = language; ProcessChatInvitationRequest(cic, serviceData); } return directconn; }
/// <summary> /// Cancel a direct connection attempt /// </summary> public void SendDirectConnectionCancellation(DirectConnection conn, string reason) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, conn.Cookie, 0x0002, conn.Other.ScreenName); using (ByteStream tlv05 = new ByteStream()) { tlv05.WriteUshort(RendezvousData.UshortFromType(RendezvousType.Cancel)); tlv05.WriteByteArray(conn.Cookie.ToByteArray()); tlv05.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteUshort(0x000B, 0x0001); tlvs.WriteString(0x000C, reason, Encoding.ASCII); tlvs.WriteEmpty(0x0003); //KSD-SYSTEMS - commented at 02.12.2009 -> Canceling = Send Message only with Cookie //tlv05.WriteByteArray(tlvs.GetBytes()); } stream.WriteUshort(0x0005); stream.WriteUshort((ushort)tlv05.GetByteCount()); stream.WriteByteArray(tlv05.GetBytes()); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
public TlvBlockSegment(TlvBlock value) { this.value = value; }
/// <summary> /// Processes the Message Of The Day -- SNAC(01,13) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(01,13)</param> public static void ProcessMOTD(DataPacket dp) { ushort motdtype = dp.Data.ReadUshort(); using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { string messagestring = tlvs.ReadString(MOTD_MESSAGE, Encoding.ASCII); // Signal the client that the MOTD has come through dp.ParentSession.OnMessageOfTheDayReceived(motdtype, messagestring); } }
/// <summary> /// Read a specified number of TLVs from the stream into a <see cref="TlvBlock"/> /// </summary> public TlvBlock ReadTlvBlock(int numberOfTlvs) { int tlvBlockLength = 0; int currentIndex = dataIndex; for (int i = 0; i < numberOfTlvs; i++) { // Skip the Type tlvBlockLength += 2; currentIndex += 2; // Calculate the size of the Value ushort currentTlvLength = (ushort)((dataBuffer[currentIndex] << 8) | (dataBuffer[currentIndex + 1])); // Skip the Length and the size of the Value currentIndex += currentTlvLength + 2; tlvBlockLength += currentTlvLength + 2; } TlvBlock retval = new TlvBlock(dataBuffer, dataIndex, tlvBlockLength); dataIndex += tlvBlockLength; return retval; }
/// <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> /// Writes a <see cref="TlvBlock"/> into the stream /// </summary> public void WriteTlvBlock(TlvBlock value) { lock (this) { dataSegments.Add(new TlvBlockSegment(value)); byteCount += value.GetByteCount(); } }
/// <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> /// 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 }
/// <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> /// 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 the parameter information sent by the server -- SNAC(13,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(13,03)</param> public static void ProcessParametersList(DataPacket dp) { List<ushort> maximums = new List<ushort>(); using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { using (ByteStream stream = new ByteStream(tlvs.ReadByteArray(0x0004))) { while (stream.HasMoreData) { maximums.Add(stream.ReadUshort()); } } } // Do something with these capabilities dp.ParentSession.Limits.MaxBuddies = maximums[0]; dp.ParentSession.Limits.MaxGroups = maximums[1]; dp.ParentSession.Limits.MaxPermits = maximums[2]; dp.ParentSession.Limits.MaxDenys = maximums[3]; dp.ParentSession.ParameterSetArrived(); }
/// <summary> /// Performs a directory search by personal information -- SNAC(0F,02) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="items">The number of non-null search terms</param> /// <param name="firstname">A first name</param> /// <param name="middlename">A middle name</param> /// <param name="lastname">A last name</param> /// <param name="maidenname">A maiden name</param> /// <param name="nickname">A nickname</param> /// <param name="city">A city</param> /// <param name="state">A state</param> /// <param name="country">A country (two letter code)</param> /// <param name="zip">A ZIP code</param> /// <param name="address">An address</param> /// <remarks> /// <para>If a search term is to be ignored, it must be set to <c>null</c>.</para> /// <para>There must be at least one non-null search term.</para></remarks> public static void SearchByInfo( Session sess, int items, string firstname, string middlename, string lastname, string maidenname, string nickname, string city, string state, string country, string zip, string address) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.DirectoryUserSearch; sh.FamilySubtypeID = (ushort)DirectorySearch.SearchUserRequest; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x001C, "us-ascii", Encoding.ASCII); tlvs.WriteUshort(0x000A, 0x0000); if (firstname != null) { tlvs.WriteString(0x0001, firstname, Encoding.ASCII); } if (middlename != null) { tlvs.WriteString(0x0002, middlename, Encoding.ASCII); } if (lastname != null) { tlvs.WriteString(0x0003, lastname, Encoding.ASCII); } if (maidenname != null) { tlvs.WriteString(0x0004, maidenname, Encoding.ASCII); } if (country != null) { tlvs.WriteString(0x0006, country, Encoding.ASCII); } if (state != null) { tlvs.WriteString(0x0007, state, Encoding.ASCII); } if (city != null) { tlvs.WriteString(0x0008, city, Encoding.ASCII); } if (nickname != null) { tlvs.WriteString(0x000C, nickname, Encoding.ASCII); } if (zip != null) { tlvs.WriteString(0x000D, zip, Encoding.ASCII); } if (address != null) { tlvs.WriteString(0x0021, address, Encoding.ASCII); } stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Performs a directory search by personal information -- SNAC(0F,02) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="items">The number of non-null search terms</param> /// <param name="firstname">A first name</param> /// <param name="middlename">A middle name</param> /// <param name="lastname">A last name</param> /// <param name="maidenname">A maiden name</param> /// <param name="nickname">A nickname</param> /// <param name="city">A city</param> /// <param name="state">A state</param> /// <param name="country">A country (two letter code)</param> /// <param name="zip">A ZIP code</param> /// <param name="address">An address</param> /// <remarks> /// <para>If a search term is to be ignored, it must be set to <c>null</c>.</para> /// <para>There must be at least one non-null search term.</para></remarks> public static void SearchByInfo( Session sess, int items, string firstname, string middlename, string lastname, string maidenname, string nickname, string city, string state, string country, string zip, string address) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.DirectoryUserSearch; sh.FamilySubtypeID = (ushort) DirectorySearch.SearchUserRequest; ByteStream stream = new ByteStream(); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteString(0x001C, "us-ascii", Encoding.ASCII); tlvs.WriteUshort(0x000A, 0x0000); if (firstname != null) tlvs.WriteString(0x0001, firstname, Encoding.ASCII); if (middlename != null) tlvs.WriteString(0x0002, middlename, Encoding.ASCII); if (lastname != null) tlvs.WriteString(0x0003, lastname, Encoding.ASCII); if (maidenname != null) tlvs.WriteString(0x0004, maidenname, Encoding.ASCII); if (country != null) tlvs.WriteString(0x0006, country, Encoding.ASCII); if (state != null) tlvs.WriteString(0x0007, state, Encoding.ASCII); if (city != null) tlvs.WriteString(0x0008, city, Encoding.ASCII); if (nickname != null) tlvs.WriteString(0x000C, nickname, Encoding.ASCII); if (zip != null) tlvs.WriteString(0x000D, zip, Encoding.ASCII); if (address != null) tlvs.WriteString(0x0021, address, Encoding.ASCII); stream.WriteTlvBlock(tlvs); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }