/// <summary> /// Sets the client's extended status -- SNAC(01,1E) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="availablemessage">The available message to set</param> /// <param name="flags">The ICQ flags to set</param> /// <param name="status">The ICQ status to set</param> /// <remarks>Either the available message or the flags/status can be set in one call to SetExtendedStatus</remarks> private static void SetExtendedStatus(Session sess, string availablemessage, ICQFlags flags, ICQStatus status) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.SetExtendedStatus; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); if (availablemessage != null) { 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); } else { uint stat = (uint)((ushort)flags << 16); stat |= (ushort)status; stream.WriteUint(0x00060004); stream.WriteUint(stat); } DataPacket dp = Marshal.BuildDataPacket(sess, sh, stream); dp.ParentConnection = sess.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Adds a frame to the delay queue /// </summary> /// <param name="sh">The SNAC header of the frame to add</param> /// <param name="data">A byte array consisting of the delayed frame</param> /// <returns><c>true</c> if a queue already existed for this family, or <c>false</c> if <see cref="ServiceManager.RequestNewService"/> should be called /// </returns> public bool AddFrameToDelayQueue(SNACHeader sh, byte[] data) { Queue q = null; bool retval = true; ushort key = sh.FamilyServiceID; DelayedFrame df = new DelayedFrame(); df.SNAC = sh; df.Data = data; if (_delayqueues.ContainsKey(key)) { q = (Queue)_delayqueues[key]; q.Enqueue(df); retval = true; } else { q = new Queue(); q.Enqueue(df); _delayqueues[key] = q; retval = false; } return(retval); }
/// <summary> /// Adds a frame to the delay queue /// </summary> /// <param name="sh">The SNAC header of the frame to add</param> /// <param name="data">A byte array consisting of the delayed frame</param> /// <returns><c>true</c> if a queue already existed for this family, or <c>false</c> if <see cref="ServiceManager.RequestNewService"/> should be called /// </returns> public bool AddFrameToDelayQueue(SNACHeader sh, byte[] data) { Queue q = null; bool retval = true; ushort key = sh.FamilyServiceID; DelayedFrame df = new DelayedFrame(); df.SNAC = sh; df.Data = data; if (_delayqueues.ContainsKey(key)) { q = (Queue) _delayqueues[key]; q.Enqueue(df); retval = true; } else { q = new Queue(); q.Enqueue(df); _delayqueues[key] = q; retval = false; } return retval; }
/// <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> /// Requests a full set of information about 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 GetAllICQInfo(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(0x04B2); stream.WriteUint(uint.Parse(screenname)); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <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> /// Sends service versions request -- SNAC(01,17) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object</param> public static void RequestServiceVersions(DataPacket dp) { Session sess = dp.ParentSession; // Construct SNAC (01,17) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.ServerServicesVersionRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); // Pack the family IDs and version numbers into a stream ushort[] families = sess.Connections.GetFamilies(dp.ParentConnection); Array.Sort(families); Array.Reverse(families); ByteStream stream = new ByteStream(); foreach (ushort id in families) { ushort version = sess.Families.GetFamilyVersion(id); stream.WriteUshort(id); stream.WriteUshort(version); } DataPacket dp2 = Marshal.BuildDataPacket(sess, sh, stream); dp2.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(dp2); }
public static DataPacket BuildDataPacket(Session sess, SNACHeader header, ByteStream data) { DataPacket dp = new DataPacket(data); dp.ParentSession = sess; dp.SNAC = header; return(dp); }
/// <summary> /// Requests that the server activate the client's SSI information -- SNAC(13,07) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <remarks> /// Sending this SNAC will cause the server to begin broadcasting online notifications /// to the contacts on the client's buddy list. /// </remarks> public static void ActivateSSI(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort) SNACFamily.SSIService; sh.FamilySubtypeID = (ushort) SSIService.LoadContactList; SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, new ByteStream())); }
/// <summary> /// Finishes an SSI modification transaction -- SNAC(13,12) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> public static void SendEditComplete(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.SSIService; sh.FamilySubtypeID = (ushort)SSIService.ContactsEditEnd; SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, new ByteStream())); }
/// <summary> /// Sends a request for the original SSI contact list -- SNAC(13,04) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> public static void RequestInitialContactList(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.SSIService; sh.FamilySubtypeID = (ushort)SSIService.ContactListInitialRequest; SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, new ByteStream())); }
/// <summary> /// Requests a list of known interests -- SNAC(0F,04) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> public static void RequestInterestList(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.DirectoryUserSearch; sh.FamilySubtypeID = (ushort)DirectorySearch.InterestsListRequest; SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, new ByteStream())); }
/// <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)); }
/// <summary> /// Reads an <see cref="SNACHeader"/> from the stream /// </summary> /// <returns>A populated <see cref="SNACHeader"/></returns> public SNACHeader ReadSnacHeader() { if (dataIndex + 10 > dataBuffer.Length) { throw new ByteStreamReadException(dataBuffer.Length, dataIndex, 10); } SNACHeader sh = new SNACHeader(ReadUshort(), ReadUshort(), ReadUshort(), ReadUint()); return(sh); }
/// <summary> /// Writes a <see cref="SNACHeader"/> into the stream /// </summary> public void WriteSnacHeader(SNACHeader value) { lock (this) { dataSegments.Add(new UshortSegment(value.FamilyServiceID)); dataSegments.Add(new UshortSegment(value.FamilySubtypeID)); dataSegments.Add(new UshortSegment(value.Flags)); dataSegments.Add(new UintSegment(value.RequestID)); byteCount += 10; } }
/// <summary> /// (Obsolete) Sends a keepalive no-op -- SNAC(01,16) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <remarks> /// This SNAC is not used anymore. Channel 5 FLAPs should be used /// for keepalive, and are sent automatically by the <see cref="Connection"/> /// objects. /// </remarks> public static void SendNoOp(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.NoOp; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, new ByteStream())); }
/// <summary> /// Prepends a <see cref="FLAPHeader"/> and a <see cref="SNACHeader"/> into the byte stream /// </summary> public void PrependOscarHeaders(FLAPHeader flap, SNACHeader snac) { lock (this) { dataSegments.Insert(0, new FlapSegment(flap)); byteCount += 6; if (snac != null) { dataSegments.Insert(1, new SnacSegment(snac)); byteCount += 10; } } }
/// <summary> /// Removes a series of SSI items from the server-side list -- SNAC(13,0A) /// </summary> /// <param name="sess"></param> /// <param name="items">An array of <see cref="SSIItem"/> objects</param> public static void RemoveSSIItems(Session sess, SSIItem[] items) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.SSIService; sh.FamilySubtypeID = (ushort)SSIService.SSIEditRemoveItem; ByteStream stream = new ByteStream(); stream.WriteSSIItems(items); sess.SSI.OutstandingRequests++; SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Delete yourself from another client server-side contact list. /// </summary> /// <param name="sess"></param> /// <param name="screenname">The contacts icq-number.</param> public static void RemoveMySSIItem(Session sess, string screenname) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.SSIService; sh.FamilySubtypeID = (ushort)SSIService.RemoveSelfFromContact; ByteStream stream = new ByteStream(); stream.WriteByte((byte)screenname.Length); stream.WriteString(screenname, Encoding.ASCII); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <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> /// 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 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 a request for rate information -- SNAC(01,06) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object</param> public static void RequestRateInformation(DataPacket dp) { Session sess = dp.ParentSession; // Construct SNAC (01,06) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (byte)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (byte)GenericServiceControls.RateLimitRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); DataPacket dp2 = Marshal.BuildDataPacket(sess, sh, new ByteStream()); dp2.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(dp2); }
/// <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> /// Requests the client's own online information -- SNAC(01,0E) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> public static void RequestOwnInformation(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.OwnInformationRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); // This SNAC expects a response in SNAC(01,0F) sess.StoreRequestID(sh.RequestID, null); DataPacket dp = Marshal.BuildDataPacket(sess, sh, new ByteStream()); // Always gets sent on BOS dp.ParentConnection = sess.Connections.BOSConnection; SNACFunctions.BuildFLAP(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> /// Requests for the server side contact list. /// </summary> /// <param name="sess">the session object</param> /// <param name="modificationDate">the last client side modification date</param> /// <param name="isLocalTime">Determines if the given modification time is in the local or universal time format</param> /// <param name="itemCount">the total item count at the client side</param> public static void SendContactListCheckout(Session sess, DateTime modificationDate, bool isLocalTime, ushort itemCount) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.SSIService; sh.FamilySubtypeID = (ushort)SSIService.ContactListCheckout; ByteStream stream = new ByteStream(); uint modDateValue = ByteStream.ConvertDateTimeToUint(modificationDate, isLocalTime); stream.WriteUint(modDateValue); stream.WriteUshort(itemCount); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream)); }
/// <summary> /// Registers the user's screenname with the Location service -- SNAC(02,0B) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <remarks> /// The function of this SNAC is unknown, but the official AIM client (5.9.3861) sends it sometime /// after SNAC(01,02) is sent. /// </remarks> public static void SetSelfLocation(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.LocationService; sh.FamilySubtypeID = (ushort)0x000B; ByteStream stream = new ByteStream(); stream.WriteByte((byte)Encoding.ASCII.GetByteCount(sess.ScreenName)); stream.WriteString(sess.ScreenName, Encoding.ASCII); // This SNAC expects a response in SNAC(02,0C) sess.StoreRequestID(sh.RequestID, null); 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> /// Creates a <see cref="DataPacket"/> from the beginning of the stream /// </summary> /// <returns>A new <see cref="DataPacket"/></returns> public DataPacket CreateDataPacket() { if (dataIndex != 0) { throw new Exception("A DataPacket can only be created from an unused ByteStream"); } SNACHeader header = new SNACHeader(this); if ((header.Flags & 0x8000) != 0) { dataIndex += 2 + ReadUshort(); // Read past family version information } DataPacket retval = new DataPacket(this); retval.SNAC = header; return(retval); }
/// <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> /// Sets the client's privacy settings -- SNAC(01,14) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="settings">The privacy flags to send to the server</param> public static void SetPrivacySettings(Session sess, uint settings) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.SetPrivacyFlags; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUint(settings); DataPacket dp = Marshal.BuildDataPacket(sess, sh, stream); // Always gets sent on BOS dp.ParentConnection = sess.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Allows the authorization to another client in the future /// </summary> /// <param name="sess">the session object</param> /// <param name="screenname">the destination screenname</param> /// <param name="reason">the reason for the future authorization</param> public static void SendFutureAuthorizationGrant(Session sess, string screenname, string reason) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.SSIService; sh.FamilySubtypeID = (ushort)SSIService.SendFutureAuthorizationGrant; ByteStream stream = new ByteStream(); stream.WriteByte((byte)Encoding.ASCII.GetByteCount(screenname)); stream.WriteString(screenname, Encoding.ASCII); stream.WriteUshort((ushort)sess.Encoding.GetByteCount(reason)); stream.WriteString(reason, sess.Encoding); stream.WriteUshort(0x0000); 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 a response to a client verification request -- SNAC(01,20) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <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. This SNAC pair not been /// reported as being used in years. /// </remarks> public static void SendVerificationResponse(Session sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.ClientVertificationResponse; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUint(0x44a95d26); stream.WriteUint(0xd2490423); stream.WriteUint(0x93b8821f); stream.WriteUint(0x51c54b01); DataPacket dp = Marshal.BuildDataPacket(sess, sh, stream); dp.ParentConnection = sess.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <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> /// 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 a request for a new service family -- SNAC(01,04) /// </summary> /// <param name="sess">A <see cref="Session"/> object</param> /// <param name="newfamily">The new family to request</param> public static void RequestNewService(Session sess, ushort newfamily) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.BasicOscarService; sh.FamilySubtypeID = (ushort)GenericServiceControls.NewServiceRequest; sh.Flags = 0x0000; sh.RequestID = Session.GetNextRequestID(); ByteStream stream = new ByteStream(); stream.WriteUshort(newfamily); // This SNAC expects a response in SNAC(01,05) sess.StoreRequestID(sh.RequestID, null); DataPacket dp = Marshal.BuildDataPacket(sess, sh, stream); // This one is always sent on BOS dp.ParentConnection = sess.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <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> /// 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> /// Processes a pause request from the server -- SNAC(01,0B) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(01,0B)</param> private void ProcessPauseRequest(DataPacket dp) { // TODO: Actually tell the connection to stop sending in preparation for the migration SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_PAUSE_CONNECTION_RESPONSE; DataPacket dp2 = Marshal.BuildDataPacket(parent, sh, new ByteStream()); dp2.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(dp2); }
/// <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> /// Creates a <see cref="DataPacket"/> from the beginning of the stream /// </summary> /// <returns>A new <see cref="DataPacket"/></returns> public DataPacket CreateDataPacket() { if (dataIndex != 0) { throw new Exception("A DataPacket can only be created from an unused ByteStream"); } SNACHeader header = new SNACHeader(this); if ((header.Flags & 0x8000) != 0) { dataIndex += 2 + ReadUshort(); // Read past family version information } DataPacket retval = new DataPacket(this); retval.SNAC = header; return retval; }
/// <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> /// Requests the client's own online information /// </summary> public void RequestOnlineInformation() { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_REQUEST_OWN_INFORMATION; DataPacket dp = Marshal.BuildDataPacket(parent, sh, new ByteStream()); // Always gets sent on BOS dp.ParentConnection = parent.Connections.BOSConnection; 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> /// Writes a <see cref="SNACHeader"/> into the stream /// </summary> public void WriteSnacHeader(SNACHeader value) { lock (this) { dataSegments.Add(new UshortSegment(value.FamilyServiceID)); dataSegments.Add(new UshortSegment(value.FamilySubtypeID)); dataSegments.Add(new UshortSegment(value.Flags)); dataSegments.Add(new UintSegment(value.RequestID)); byteCount += 10; } }
/// <summary> /// Reads an <see cref="SNACHeader"/> from the stream /// </summary> /// <returns>A populated <see cref="SNACHeader"/></returns> public SNACHeader ReadSnacHeader() { if (dataIndex + 10 > dataBuffer.Length) { throw new ByteStreamReadException(dataBuffer.Length, dataIndex, 10); } SNACHeader sh = new SNACHeader(ReadUshort(), ReadUshort(), ReadUshort(), ReadUint()); return sh; }
/// <summary> /// Sends SNAC(01,06) in response to SNAC(01,18) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(01,18)</param> /// <remarks>OscarLib doesn't store the version list, so this method just sends SNAC(01,06) for rate limit info</remarks> private void ProcessVersionsListAndGetRateLimits(DataPacket dp) { // Construct SNAC (01,06) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_RATE_LIMIT_REQUST; DataPacket dp2 = Marshal.BuildDataPacket(parent, sh, new ByteStream()); dp2.ParentConnection = dp.ParentConnection; SNACFunctions.BuildFLAP(dp2); }
/// <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 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> /// 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)); }
/// <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 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> /// 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> /// 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); }
public SnacSegment(SNACHeader value) { header = value; }
/// <summary> /// Prepends a <see cref="FLAPHeader"/> and a <see cref="SNACHeader"/> into the byte stream /// </summary> public void PrependOscarHeaders(FLAPHeader flap, SNACHeader snac) { lock (this) { dataSegments.Insert(0, new FlapSegment(flap)); byteCount += 6; if (snac != null) { dataSegments.Insert(1, new SnacSegment(snac)); byteCount += 10; } } }
/// <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); } } }