public void TestByteStreamReading() { // Test bytes using (ByteStream stream = new ByteStream(testData)) { for (int i = 0; i < testData.Length; i++) { Assert.AreEqual(testData[i], stream.ReadByte(), "ReadByte returned incorrect value"); } } // Test ushorts using (ByteStream stream = new ByteStream(testData)) { Assert.AreEqual(0x0841, stream.ReadUshort()); Assert.AreEqual(0x6472, stream.ReadUshort()); Assert.AreEqual(0x6965, stream.ReadUshort()); Assert.AreEqual(0x6e6e, stream.ReadUshort()); } // Test uints using (ByteStream stream = new ByteStream(testData)) { Assert.AreEqual(0x08416472, stream.ReadUint()); Assert.AreEqual(0x69656e6e, stream.ReadUint()); } // Test string using (ByteStream stream = new ByteStream(testData)) { Assert.AreEqual("Adrienne", stream.ReadString(stream.ReadByte(), Encoding.ASCII)); } }
/// <summary> /// Requests the alias assigned to an ICQ account /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="screenname">The account for which to retrieve information</param> public static void GetAlias(ISession sess, string screenname) { if (!ScreennameVerifier.IsValidICQ(screenname)) { throw new ArgumentException(screenname + " is not a valid ICQ screenname", "screenname"); } SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.ICQExtensionsService; sh.FamilySubtypeID = (ushort) ICQExtensionsService.MetaInformationRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUshort(0x0001); stream.WriteUshort(0x000A); stream.WriteUshort(0x0008); stream.WriteUint(uint.Parse(sess.ScreenName)); stream.WriteUshortLE(0x07D0); stream.WriteUshortLE((ushort) sh.RequestID); stream.WriteUshort(0x04BA); stream.WriteUint(uint.Parse(screenname)); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Modifies a series of SSI items on the server-side list -- SNAC(13,09) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="items">An array of <see cref="SSIItem"/> objects</param> public static void ModifySSIItems(Session sess, SSIItem[] items) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.SSIService; sh.FamilySubtypeID = (ushort) SSIService.SSIEditUpdateGroupHeader; ByteStream stream = new ByteStream(); stream.WriteSSIItems(items); sess.SSI.OutstandingRequests++; SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
public void TestByteStreamNumberWriting() { ByteStream stream = new ByteStream(); stream.WriteByte(0x08); stream.WriteUshort(0x4164); stream.WriteUint(0x7269656e); stream.WriteByteArray(new byte[] {0x6e, 0x65}); Assert.AreEqual(testData.Length, stream.GetByteCount()); ByteStream testStream = new ByteStream(stream.GetBytes()); Assert.AreEqual("Adrienne", testStream.ReadString(testStream.ReadByte(), Encoding.ASCII)); }
public void TestByteStreamStringWriting() { ByteStream stream = new ByteStream(); stream.WriteByte((byte) Encoding.ASCII.GetByteCount("Adrienne")); stream.WriteString("Adrienne", Encoding.ASCII); Assert.AreEqual(testData.Length, stream.GetByteCount()); byte[] data = stream.GetBytes(); for (int i = 0; i < testData.Length; i++) { Assert.AreEqual(testData[i], data[i]); } }
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 a request to find accounts by their associated email address -- SNAC(0A,02) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="email">The email address to query</param> public static void FindUsersByEmail(ISession sess, string email) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.UserLookupService; sh.FamilySubtypeID = (ushort) UserLookupService.FindUserByEmailRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteString(email, Encoding.ASCII); sess.StoreRequestID(sh.RequestID, email); DataPacket dp = Marshal.BuildDataPacket(sess, sh, stream); SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Sends an acknowledgement of the server's rate limitations -- SNAC(01,08) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object</param> /// <param name="classes">The known rate classes to acknowledge</param> public static void AcknowledgeRateLimitations(DataPacket dp, ushort[] classes) { Session sess = dp.ParentSession; SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.AcknowledgeRateLimits; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); for (int i = 0; i < classes.Length; i++) { stream.WriteUshort(classes[i]); } DataPacket dp2 = Marshal.BuildDataPacket(sess, sh, stream); dp2.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(dp2); sess.OnLoginStatusUpdate("Protocol negotiation complete", 0.66); /* * If this is the initial services connection, we call the remaining SNACs * in the login sequence. * Otherwise, this is the last step in setting up a new service connection, * and we send SNAC(01,02) here. */ if (!sess.LoggedIn) { // Start stage 3, services setup RequestOwnInformation(sess); SNAC13.RequestParametersList(sess); SNAC13.RequestInitialContactList(sess); sess.Statuses.RequestParameters(); sess.Messages.RequestParametersList(); SNAC09.RequestParametersList(sess); sess.Statuses.ReportClientCapabilities(); sess.Statuses.SetProfile(sess.Statuses.Profile); } else { SendReadyNotification(dp); } }
/// <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> /// Changes the password on an ICQ account /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="newpassword">The new password</param> /// <remarks>If the new password is longer than 8 characters, it is automatically /// truncated to 8 characters by the server.</remarks> public static void ChangeICQPassword(ISession sess, string newpassword) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.ICQExtensionsService; sh.FamilySubtypeID = (ushort) ICQExtensionsService.MetaInformationRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUshort(0x0001); stream.WriteUshort(0x000A); stream.WriteUshort(0x0008); stream.WriteUint(uint.Parse(sess.ScreenName)); stream.WriteUshortLE(0x07D0); stream.WriteUshortLE((ushort) sh.RequestID); stream.WriteUshort(0x042E); stream.WriteUshort((ushort) (newpassword.Length + 1)); stream.WriteString(newpassword, Encoding.ASCII); stream.WriteByte(0x00); 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> /// 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> /// Processes the list of rate limitations -- SNAC(01,07) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(01,07)</param> /// <remarks>This is the last step in setting up a secondary service connection, /// and the trigger to initialize basic services for the primary connection.</remarks> private void ProcessRateLimitations(DataPacket dp) { ushort num_classes = dp.Data.ReadUshort(); ushort[] classes = new ushort[num_classes]; RateClassManager rcm = parent.RateClasses; // Get the rate class attributes out of the SNAC for (int i = 0; i < num_classes; i++) { ushort id = dp.Data.ReadUshort(); RateClass rc = rcm.GetByID(id); rc.WindowSize = dp.Data.ReadUint(); rc.ClearLevel = dp.Data.ReadUint(); rc.AlertLevel = dp.Data.ReadUint(); rc.LimitLevel = dp.Data.ReadUint(); rc.DisconnectLevel = dp.Data.ReadUint(); rc.CurrentLevel = dp.Data.ReadUint(); rc.MaxLevel = dp.Data.ReadUint(); if (parent.Families.GetFamilyVersion(0x0001) >= 3) { rc.LastTime = dp.Data.ReadUint(); rc.IsDroppingSNACs = dp.Data.ReadByte() != 0; } rcm.SetByID(id, rc); rc.StartLimitedTransmission(); classes[i] = id; } // Register rates with the session's ConnectionList for (int i = 0; i < num_classes; i++) { ushort id = dp.Data.ReadUshort(); ushort num_pairs = dp.Data.ReadUshort(); for (int j = 0; j < num_pairs; j++) { ushort family = dp.Data.ReadUshort(); ushort subtype = dp.Data.ReadUshort(); if (family == 0x04) { if (id == 1) { Console.WriteLine("** SNAC 4 handled by RC " + id); } else { Console.WriteLine("SNAC 4-{0} handled by RC " + id, subtype); } } else if (family == 0x02 && subtype == 0x05) { Console.WriteLine("** 02,05 handled by RC " + id); } rcm.SetRateClassKey(family, subtype, id); } } // Construct SNAC(01,08) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_ACKNOWLEDGE_RATE_LIMITS; ByteStream stream = new ByteStream(); for (int i = 0; i < classes.Length; i++) { stream.WriteUshort(classes[i]); } DataPacket dp2 = Marshal.BuildDataPacket(parent, sh, stream); dp2.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(dp2); parent.OnLoginStatusUpdate("Protocol negotiation complete", 0.66); /* * If this is the initial services connection, we call the remaining SNACs * in the login sequence. * Otherwise, this is the last step in setting up a new service connection, * and we send SNAC(01,02) here. */ if (!parent.LoggedIn) { // Start stage 3, services setup RequestOnlineInformation(); SNAC13.RequestParametersList(parent); SNAC13.RequestInitialContactList(parent); parent.Statuses.RequestParameters(); parent.Messages.RequestParametersList(); SNAC09.RequestParametersList(parent); parent.Statuses.ReportClientCapabilities(); parent.Statuses.SetProfile(parent.Statuses.Profile); } else { SendReadyNotification(dp.ParentConnection); } }
/// <summary> /// Sets the client's ICQ status -- SNAC(01,1E) /// </summary> /// <param name="flags">The ICQ flags to set</param> /// <param name="status">The ICQ status flags to set</param> internal void SetExtendedICQStatus(ICQFlags flags, ICQStatus status) { SNACHeader sh = new SNACHeader(SNAC_BOS_FAMILY, BOS_SET_EXTENDED_STATUS); ByteStream stream = new ByteStream(); uint stat = (uint)((ushort)flags << 16); stat |= (ushort)status; stream.WriteUint(0x00060004); stream.WriteUint(stat); DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = parent.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Sets the client's DC info -- SNAC(01,1E) /// </summary> /// <remarks>see <see cref="UserDCInfo"/> for contact info</remarks> internal void SetDCInfo() { SNACHeader sh = new SNACHeader(SNAC_BOS_FAMILY, BOS_SET_EXTENDED_STATUS); ByteStream stream = new ByteStream(); // Header stream.WriteUshort(0x000c); stream.WriteUshort(0x0025); // Values from Icq 6.5 & 7 dumping // Miranda use other Values (see CIcqProto::handleServUINSettings) stream.WriteUint(0); // IP stream.WriteUint(0); // Port stream.WriteByte((byte)DCType.Disabled); // DC type stream.WriteUshort((ushort)DCProtocol.IcqLite); // DC protocol version stream.WriteInt(AuthCookie); // DC auth cookie stream.WriteUint(0); // Web front port stream.WriteUint(0); // Client futures stream.WriteUint(0); // last info update time stream.WriteUint(0); // last ext info update time (i.e. icqphone status) stream.WriteUint(0); // last ext status update time (i.e. phonebook) stream.WriteUshort(0); // unknown DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = parent.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Sets the client's available message -- SNAC(01,1E) /// </summary> /// <param name="availablemessage">The available message to set</param> internal void SetAvailableMessage(string availablemessage) { SNACHeader sh = new SNACHeader(SNAC_BOS_FAMILY, BOS_SET_EXTENDED_STATUS); ByteStream stream = new ByteStream(); if (String.IsNullOrEmpty(availablemessage)) { availablemessage = String.Empty; } stream.WriteUshort(0x001D); stream.WriteUshort((ushort)(availablemessage.Length + 8)); stream.WriteUshort(0x0002); stream.WriteByte(0x04); stream.WriteByte((byte)(Encoding.ASCII.GetByteCount(availablemessage) + 4)); stream.WriteUshort((ushort)Encoding.ASCII.GetByteCount(availablemessage)); stream.WriteString(availablemessage, Encoding.ASCII); stream.WriteUshort(0x0000); DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = parent.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Sends a response to a client verification request -- SNAC(01,20) /// </summary> /// <remarks> /// SNAC(01,1F) and SNAC(01,20) are used to verify that the client connecting /// to the network was the official AOL Instant Messenger. The server sends /// two integers, an offset and a length, in SNAC(01,1F). These parameters are then used to /// get 16 bytes of data in the offical client's static memory region. However, after /// AOL begain using this authentication method, the servers never changed the requested /// offset and length. The expected response was the same 16 bytes every time, which made /// it a fairly ineffective deterrent to "unauthorized" clients. /// </remarks> public void SendVerificationResponse() { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_CLIENT_VERIFICATION_RESPONSE; ByteStream stream = new ByteStream(); stream.WriteUint(0x44a95d26); stream.WriteUint(0xd2490423); stream.WriteUint(0x93b8821f); stream.WriteUint(0x51c54b01); DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = parent.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Notifies the OSCAR server that the new connection is ready to receive service-specific data /// </summary> /// <remarks> /// This SNAC must be sent within 30ish seconds of connection, or the connection will drop. /// This should not ever be a problem, barring a lost connection well below the level of this library. /// </remarks> public void SendReadyNotification(Connection conn) { // Build SNAC(01,02) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_CONNECTION_READY; ushort[] families = parent.Connections.GetFamilies(conn); FamilyManager fm = parent.Families; Array.Sort(families); Array.Reverse(families); bool isChatRoomConnection = false; bool isChatNavService = false; ByteStream stream = new ByteStream(); DataPacket[][] delayedframes = new DataPacket[families.Length][]; for (int i = 0; i < families.Length; i++) { ushort family = families[i]; delayedframes[i] = parent.Connections.GetDelayedPackets(family); stream.WriteUshort(family); stream.WriteUshort(fm.GetFamilyVersion(family)); stream.WriteUshort(fm.GetFamilyToolID(family)); stream.WriteUshort(fm.GetFamilyToolVersion(family)); if (family == 0x000D) { isChatNavService = true; } else if (family == 0x000E) { isChatRoomConnection = true; } } /* * The initial service connection has to send SNAC(01,1E) before it actually * sends SNAC(01,02), thus the check for the initial connection here * and after it gets sent. */ if (!parent.LoggedIn) { SetAvailableMessage(parent.Statuses.AvailableMessage); SetDCInfo(); SetExtendedICQStatus(parent.Statuses.ICQFlags, parent.Statuses.ICQStatus); } // The connection is done, so start sending keepalives conn.Connecting = false; conn.ReadyForData = true; DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = conn; SNACFunctions.BuildFLAP(dp); /* * If this is a new service connection, there is probably at least one * delayed packet. Process those packets. Additionally, if the new connection is * a chatroom connection, query the Rendezvous manager to see if it is the result * of an explict room creation (or implict, as in accepting a chat invitation). * If it was explict, notify the user that it's done */ if (parent.LoggedIn) { foreach (DataPacket[] list in delayedframes) { if (list == null) continue; foreach (DataPacket dp_delay in list) { dp_delay.ParentConnection = conn; SNACFunctions.DispatchToRateClass(dp_delay); } } if (isChatNavService) { parent.ChatRooms.OnChatNavServiceAvailable(); } else if (isChatRoomConnection) { ChatRoom chatRoom = parent.Connections.GetChatByConnection((ChatConnection)conn); parent.ChatRooms.OnChatRoomConnectionAvailable(chatRoom); } } }
/// <summary> /// Requests the version of SNAC services provided to this connection /// </summary> /// <param name="connection">The <see cref="Connection"/> for which to retrieve service information</param> public void RequestServiceVersions(Connection connection) { // Pack the family IDs and version numbers into a stream ushort[] families = parent.Connections.GetFamilies(connection); Array.Sort(families); Array.Reverse(families); ByteStream stream = new ByteStream(); foreach (ushort id in families) { ushort version = parent.Families.GetFamilyVersion(id); stream.WriteUshort(id); stream.WriteUshort(version); } // Construct SNAC (01,17) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_FAMILY_VERSION_REQUEST; DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = connection; // Always send this on the same connection it was received SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Sends a request for a new service family /// </summary> /// <param name="newfamily">The new family to request</param> public void RequestNewService(ushort newfamily) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_REQUEST_NEW_SERVICE; ByteStream stream = new ByteStream(); stream.WriteUshort(newfamily); // This SNAC expects a response in SNAC(01,05) parent.StoreRequestID(sh.RequestID, null); DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); // This one is always sent on BOS dp.ParentConnection = parent.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <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> /// Sends an XML string /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="xml">The contents of an XML document</param> /// <remarks>I have no idea how to use this.</remarks> public static void SendXmlRequest(ISession sess, string xml) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.ICQExtensionsService; sh.FamilySubtypeID = (ushort) ICQExtensionsService.MetaInformationRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUshort(0x0001); stream.WriteUshort(0x000A); stream.WriteUshort(0x0008); stream.WriteUint(uint.Parse(sess.ScreenName)); stream.WriteUshortLE(0x07D0); stream.WriteUshortLE((ushort) sh.RequestID); stream.WriteUshort(0x0998); stream.WriteUshort((ushort) Encoding.ASCII.GetByteCount(xml)); stream.WriteString(xml, Encoding.ASCII); stream.WriteByte(0x00); 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> 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> /// Completes the initial connection to the AOL proxy server /// </summary> /// <remarks>This method is used to complete the proxy server transaction for both /// Stage 1 sending and Stage 2 receiver-redirect proxy scenarios</remarks> private void InitAolProxyConnectFinished() { try { ProxyInitializeSend(); RendezvousProxyPacket rpp = ReadProxyPacket(); if (rpp.Command == RendezvousProxyCommand.Acknowledge) { using (ByteStream bstream = new ByteStream(rpp.Data)) { Port = bstream.ReadUshort(); aolProxyIP = (new IPAddress(bstream.ReadByteArray(4))).ToString(); } // Send the "send file" request on SNAC(04,06):02 parent.Messages.RequestDirectConnectionInvite(this); // Wait for the proxy to send its 12 byte READY sequence lock (socket) { socket.BeginRead(new byte[12], 0, 12, new AsyncCallback(ProxyReceivedReady), null); //socket.BeginReceive(new byte[12], 0, 12, SocketFlags.None, new AsyncCallback(ProxyReceivedReady), null); } } else { ushort error = (ushort)((rpp.Data[0] << 8) | rpp.Data[1]); if (error == 0x0004) { throw new Exception("Recipient not logged in"); } else if (error == 0x000D) { throw new Exception("Client sent bad request"); } throw new Exception("AOL proxy sent unknown error"); } } catch (Exception ex) { if (DirectConnectionFailed != null) { DirectConnectionFailed(ex.Message); } } }
/// <summary> /// Synchronously reads a packet from a Rendezvous proxy connection /// </summary> private RendezvousProxyPacket ReadProxyPacket() { int bytesreceived = 0; byte[] header = new byte[12]; while (bytesreceived < header.Length) { bytesreceived += socket.Read(header, bytesreceived, header.Length - bytesreceived); } Logging.DumpFLAP(header, "Rendezvous proxy read packet header"); RendezvousProxyPacket retval = new RendezvousProxyPacket(); using (ByteStream bstream = new ByteStream(header)) { retval.Data = new byte[bstream.ReadUshort() - 10]; bstream.AdvanceToPosition(4); retval.Command = (RendezvousProxyCommand)bstream.ReadUshort(); } bytesreceived = 0; while (bytesreceived < retval.Data.Length) { bytesreceived += socket.Read(retval.Data, bytesreceived, retval.Data.Length - bytesreceived); } Logging.DumpFLAP(retval.Data, "Rendezvous proxy read packet data"); return retval; }
/// <summary> /// Hides the client's IP address from view /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> public static void HidePublicIP(ISession sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.ICQExtensionsService; sh.FamilySubtypeID = (ushort) ICQExtensionsService.MetaInformationRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUshort(0x0001); stream.WriteUshort(0x000A); stream.WriteUshort(0x0008); stream.WriteUint(uint.Parse(sess.ScreenName)); stream.WriteUshortLE(0x07D0); stream.WriteUshortLE((ushort) sh.RequestID); stream.WriteUshort(0x0424); stream.WriteUshort(0x0001); stream.WriteUshort(0x0001); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
public byte[] GetBytes() { ByteStream buffer = new ByteStream(); buffer.WriteUshort((ushort)Encoding.UTF8.GetByteCount(item.Name)); buffer.WriteString(item.Name, Encoding.UTF8); buffer.WriteUshort(item.GroupID); buffer.WriteUshort(item.ItemID); buffer.WriteUshort(item.ItemType); if (item.Tlvs == null) buffer.WriteUshort(0x000); else { buffer.WriteUshort((ushort)item.Tlvs.GetByteCount()); buffer.WriteTlvBlock(item.Tlvs); } return buffer.GetBytes(); }
/// <summary> /// Sends an out-of-the-country text message /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <param name="number">The number to which to send the message</param> /// <param name="message">The message to send</param> /// <param name="alias">The sender's alias</param> /// <remarks><paramref name="message"/> must be in codepage 1252. A delivery receipt /// is automatically requested by this method.</remarks> public static void SendSMSMessage(ISession sess, string number, string message, string alias) { string xmlformat = "<icq_sms_message>\n" + "\t<destination>{0}</destination>\n" + "\t<text>{1}</text>\n" + "\t<codepage>1252</codepage>\n" + "\t<senders_UIN>{2}</senders_UIN>\n" + "\t<senders_name>{3}</senders_name>\n" + "\t<delivery_receipt>Yes</delivery_receipt>\n" + "\t<time>{4}</time>\n" + "</icq_sms_message>\n"; string xml = String.Format(xmlformat, number, message, sess.ScreenName, alias, DateTime.Now.ToString("r")); SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.ICQExtensionsService; sh.FamilySubtypeID = (ushort) ICQExtensionsService.MetaInformationRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUshort(0x0001); stream.WriteUshort(0x000A); stream.WriteUshort(0x0008); stream.WriteUint(uint.Parse(sess.ScreenName)); stream.WriteUshortLE(0x07D0); stream.WriteUshortLE((ushort) sh.RequestID); stream.WriteUshort(0x8214); stream.WriteUshort(0x0001); stream.WriteUshort(0x0016); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUshort(0x0000); stream.WriteUshort((ushort) Encoding.ASCII.GetByteCount(xml)); stream.WriteString(xml, Encoding.ASCII); stream.WriteByte(0x00); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Parses a byte buffer into an <see cref="BartID"/> object /// </summary> private void ReadIconInfo(byte[] buffer, UserInfo userinfo) { using (ByteStream iconStream = new ByteStream(buffer)) { int iconStreamSize = iconStream.GetByteCount(); while (iconStream.CurrentPosition + 4 <= iconStreamSize) { BartID item = new BartID(iconStream); // Find the end of the current data item in the stream int endDataPosition = iconStream.CurrentPosition + item.Data.Length; switch (item.Type) { case BartTypeId.BuddyIcon: if (!GraphicsManager.IsBlankIcon(item.Data)) { userinfo.Icon = item; } break; case BartTypeId.StatusString: // Available message using (ByteStream messageStream = new ByteStream(item.Data)) { Encoding encoding = Encoding.UTF8; byte[] amessage = new byte[0]; if (messageStream.HasMoreData) { // Pull the message to a byte array, assume at first that the encoding // is UTF-8. If existing encoding information exists, use that instead amessage = messageStream.ReadByteArray(messageStream.ReadByte()); // Check if there's encoding information available if (messageStream.HasMoreData) { // Check to see if the encoding's been specified if (messageStream.ReadUshort() == 0x0001) { messageStream.AdvanceOffset(2); string encodingStr = messageStream.ReadString(messageStream.ReadUshort(), Encoding.ASCII); // Try to use the encoding from the byte stream try { encoding = Encoding.GetEncoding(encodingStr); } catch (ArgumentException) { Logging.WriteString( "ReadIconInfo: Got unknown encoding for available message (" + encodingStr + "), falling back to UTF-8"); encoding = Encoding.UTF8; } } } } userinfo.AvailableMessage = Encoding.Unicode.GetString( Encoding.Convert(encoding, Encoding.Unicode, amessage)); } break; default: break; } } } }
byte[] ISegment.GetBytes() { using (ByteStream buffer = new ByteStream()) { buffer.WriteUshort((ushort)item.Type); buffer.WriteByte((byte)item.Flags); buffer.WriteByte((byte)item.Data.Length); buffer.WriteByteArray(item.Data); return buffer.GetBytes(); } }