/// <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> /// 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> /// 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 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 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); }
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)); }
/// <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> /// 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> /// 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> /// 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> /// 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 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> /// 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 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> /// 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> /// 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)); }
/// <summary> /// Accept a direct connection attempt /// </summary> public void SendDirectConnectionAccept(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.Accept)); tlv05.WriteByteArray(conn.Cookie.ToByteArray()); tlv05.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); tlv05.WriteUint(0x00030000); stream.WriteUshort(0x0005); stream.WriteUshort((ushort)tlv05.GetByteCount()); stream.WriteByteArray(tlv05.GetBytes()); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
/// <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> /// This method is invoked when the connection is complete /// </summary> protected virtual void OnConnectionFinished() { Connecting = true; // Read in the first ten bytes (6 byte FLAP channel 0x01 + 0x00000001) // of the connection handshake byte[] serverhandshake = new byte[10]; try { int bytesreceived = 0; int receiveindex = 0; lock (socket) { while (bytesreceived < 10) { bytesreceived = socket.Read(serverhandshake, receiveindex, 10 - receiveindex); receiveindex += bytesreceived; } } } catch (Exception ex) { Logging.WriteString("Can't read handshake from server: {0}, connection {1}", ex.Message, ID); DisconnectFromServer(true); return; } finally { serverhandshake = null; } // Construct our reply to the connection handshake using (ByteStream clientHandshake = new ByteStream()) { FLAPHeader fh; fh.Channel = 0x01; fh.DatagramSequenceNumber = FLAPSequence; fh.DataSize = (ushort)(4 + ((cookie == null) ? 0 : 4 + cookie.GetByteCount())); clientHandshake.PrependOscarHeaders(fh, null); clientHandshake.WriteUint(Constants.PROTOCOL_VERSION); if (cookie != null) { clientHandshake.WriteUshort(0x0006); clientHandshake.WriteUshort((ushort)cookie.GetByteCount()); clientHandshake.WriteByteArray(cookie.ToByteArray()); } try { lock (socket) { socket.Write(clientHandshake.GetBytes()); } } catch (Exception ex) { Logging.WriteString("Couldn't send handshake to server: {0}, connection {1}", ex.Message, ID); DisconnectFromServer(true); return; } } StopTimeoutPeriod(); Connecting = true; // And the handshaking is done. Auth connection will send // SNAC(17,06) and any other connection will receive SNAC(01,03) OnServerConnectionCompleted(); }
/// <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> /// 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 client's idle time. /// </summary> /// <param name="seconds">The client's idle time, in seconds</param> /// <remarks> /// <para> /// To remove idle status, set <paramref name="seconds"/> to zero. /// </para> /// <para> /// This method should be used only once to set the client as idle, /// or to remove idle status. The server updates the client's idle time /// automatically. So, for example, if the client application wants the /// user to appear idle after ten minutes, the application should call /// this method after 10 minutes of being idle: /// <code>Session s; /// ... /// s.SetIdleTime(600);</code> /// The next time this method is called, it should be to remove idle status: /// <code>s.SetIdleTime(0);</code> /// </para> /// </remarks> /// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception> public void SetIdleTime(uint seconds) { if (!parent.LoggedIn) { throw new NotLoggedInException(); } SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = 0x0001; sh.FamilySubtypeID = 0x0011; ByteStream stream = new ByteStream(); stream.WriteUint(seconds); // Always gets sent on BOS DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = parent.Connections.BOSConnection; SNACFunctions.BuildFLAP(dp); }
/// <summary> /// Requests all user information from the server /// </summary> /// <param name="screenname">The screenname to get information about</param> /// <remarks>Results are returned by the <see cref="UserInfoReceived"/> event</remarks> public void RequestAllUserInfo(string screenname) { //KSD-SYSTEMS - commented at 24.02.2010 -> I want AllUserInfo, no Redirect // If the requested information is an ICQ name, redirect this //if (ScreennameVerifier.IsValidICQ(screenname)) //{ // RequestBasicUserInfo(screenname, BasicUserInfoRequest.AwayMessage); // return; //} // Build SNAC(02,15) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_LOCATION_FAMILY; sh.FamilySubtypeID = LOCATION_REQUEST_ALL_INFO; ByteStream stream = new ByteStream(); stream.WriteUint((uint)(UserInfoRequest.AwayMessage | UserInfoRequest.Capabilities | UserInfoRequest.UserProfile)); stream.WriteByte((byte)Encoding.ASCII.GetByteCount(screenname)); stream.WriteString(screenname, Encoding.ASCII); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
/// <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> /// 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> /// 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 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> /// Sets ICBM parameters to more reasonable values than the defaults -- SNAC(04,02) /// </summary> private void UpdateParameters() { // Construct the SNAC header SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_SET_PARAMETERS; // Put the ICBM parameters into a byte array ByteStream stream = new ByteStream(); // Channel to setup -- should always be 0 stream.WriteUshort(0x0000); // Message flags stream.WriteUint((uint)ICBMParameters.All); // Maximum message size parent.Limits.MaxMessageSize = 8000; // Maximum sender evil level parent.Limits.MaxSenderWarningLevel = 999; // Maximum receiver evil level parent.Limits.MaxReceiverWarningLevel = 999; // Send the limits to the server stream.WriteUshort(parent.Limits.MaxMessageSize); stream.WriteUshort(parent.Limits.MaxSenderWarningLevel); stream.WriteUshort(parent.Limits.MaxReceiverWarningLevel); // Minimum message interval, in seconds stream.WriteUint(0x00000000); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, 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)); }