📄 icqworks.pas
字号:
S: String;
begin
count := 0;
S := '';
if Contacts.Count > 0 then
for i := 0 to Contacts.Count - 1 do
begin
if ExtractName(Contacts.Strings[i]) <> '' then
begin
S := S + ExtractName(Contacts.Strings[i]) + #$fe;
if ExtractValue(Contacts.Strings[i]) = '' then
S := S + ExtractName(Contacts.Strings[i]) + #$fe
else
S := S + ExtractValue(Contacts.Strings[i]) + #$fe;
Inc(count);
end;
end;
Result := IntToStr(count) + #$fe + S;
end;
{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=}
{The first packet sent by the client after connecting and receiving
the SRV_HELLO packet from the server. The packet basiclly identifies
what kind and version of client is connecting along with the user's
UIN and password.}
procedure CreateCLI_IDENT(Pkt: PRawPkt; UIN: LongWord; Password: String; var Seq: Word);
begin
PktInit(Pkt, 1, Seq); //Channel 1
PktInt(Pkt, 1, 4); //00 00 00 01
PktTLV(Pkt, 1, IntToStr(UIN)); //Adding user's UIN
ICQEncryptPassStr(Password); //Encrypt password
PktTLV(Pkt, 2, Password); //Adding encrypted password
// Pack client identification details. We identify ourselves as ICQ 2003b.
// eraser 13.05.2004
PktTLV(Pkt, 3, 'ICQ Inc. - Product of ICQ (TM).2003b.5.56.1.3916.85'); //Cookie
//Uknowns
PktInt(Pkt, $00160002, 4); PktInt(Pkt, $010a, 2);
PktInt(Pkt, $00170002, 4); PktInt(Pkt, $0005, 2);
PktInt(Pkt, $00180002, 4); PktInt(Pkt, $0025, 2);
PktInt(Pkt, $00190002, 4); PktInt(Pkt, $0001, 2);
PktInt(Pkt, $001a0002, 4); PktInt(Pkt, $0e90, 2);
PktInt(Pkt, $00140004, 4); PktInt(Pkt, $00000055, 4);
PktTLV(Pkt, $000f, 'en');
PktTLV(Pkt, $000e, 'us');
PktFinal(Pkt); //Finalize packet
end;
{Sent as the first packet after the client has logged in
to the second server and received the SRV_HELLO packet.}
procedure CreateCLI_COOKIE(Pkt: PRawPkt; const Cookie: String; var Seq: Word);
begin
PktInit(Pkt, 1, Seq); //Channel 1
PktInt(Pkt, 1, 4); //00 00 00 01
PktTLV(Pkt, 6, Cookie); //TLV(06) Cookie
PktFinal(Pkt); //Finalize packet
end;
{This packet is a response to SNAC(1,3), SRV_FAMILIES. This tells
the server which SNAC families and their corresponding versions
which the client understands. This also seems to identify the client
as an ICQ vice AIM client to the server.}
procedure CreateCLI_FAMILIES(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, 1, $17, 0, 0); //Snac: Type x01/x17, ID x0000, Flags 0
PktInt(Pkt, $00010003, 4); //Family x01 is Version x03
PktInt(Pkt, $00130002, 4); //Family x13 at Version x02
PktInt(Pkt, $00020001, 4); //Family x02 at Version x01
PktInt(Pkt, $00030001, 4); //Family x03 at Version x01
PktInt(Pkt, $00150001, 4); //Family x15 at Version x01
PktInt(Pkt, $00040001, 4); //Family x04 at Version x01
PktInt(Pkt, $00060001, 4); //Family x06 at Version x01
PktInt(Pkt, $00090001, 4); //Family x09 at Version x01
PktInt(Pkt, $000A0001, 4); //Family x0A at Version x01
PktInt(Pkt, $000B0001, 4); //Family x0B at Version x01
PktFinal(Pkt); //Finalize packet
end;
{This packet requests from the server several bits of information most
likely regarding how fast certain packets can be sent to the server and
possibly a maximum packet size as well.}
procedure CreateCLI_RATESREQUEST(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $06, 0, 0); //Snac: Type x01/x06, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{This packet is sent in response to the SRV_RATES SNAC(1,7). This
packet contains the same group numbers as was in the SRV_RATES
packet and is an acknowledgement of their receipt.}
procedure CreateCLI_ACKRATES(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $08, 0, 0); //Type x01/x08, ID x0000, Flags 0
PktInt(Pkt, $0001, 2); //Group1 - 0x0001
PktInt(Pkt, $0002, 2); //Group2 - 0x0002
PktInt(Pkt, $0003, 2); //Group3 - 0x0003
PktInt(Pkt, $0004, 2); //Group4 - 0x0004
PktInt(Pkt, $0005, 2); //Group5 - 0x0005
PktFinal(Pkt); //Finalize packet
end;
{This command requests from the server certain information
about the client that is stored on the server}
procedure CreateCLI_REQINFO(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $0E, 0, 0); //Snac: Type x01/x0E, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{Unknown}
procedure CreateCLI_REQUNKNOWN(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $13, $02, 0, 0); //Snac: Type x13/x02, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{This command, like CLI_CHECKROSTER, requests the server side contact list.
The difference between CLI_REQROSTER and CLI_CHECKROSTER is that CLI_REQROSTER
has no parameters, and always causes SRV_REPLYROSTER (rather than
SRV_REPLYROSTEROK). My guess is that CLI_REQROSTER is sent instead of
CLI_CHECKROSTER when the client does not have a cached copy of the contact
list; ie, the first time a user logs in with a particular client.}
procedure CreateCLI_REQROSTER(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $13, $04, $00010004, 0); //Snac: Type x13/x04, ID x00010004, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{Synchronizes the server side contact list with the client's.
If the passed values match those on the server, SNAC(13,F)
SRV_REPLYROSTEROK will be returned. If the values are older
than what is on the server then SNAC(13,6) SRV_REPLYROSTER will
be returned.}
procedure CreateCLI_CHECKROSTER(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $13, $05, $00010005, 0); //Snac: Type x13/x05, ID x00010005, Flags 0
PktInt(Pkt, $3C36D709, 4); //time(NULL), The last modification time of the server side contact list.
PktInt(Pkt, $0000, 2); //Size of server side contact list.
PktFinal(Pkt); //Finalize packet
end;
{Request rights information for location service. This is from
the OSCAR document.}
procedure CreateCLI_REQLOCATION(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $02, $02, 0, 0); //Snac: Type x02/x02, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{Request rights information for buddy service. This from the OSCAR document.}
procedure CreateCLI_REQBUDDY(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $03, $02, 0, 0); //Snac: Type x03/x02, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{Request rights information for ICBM (instant messages) operations. This
from the OSCAR document.}
procedure CreateCLI_REQICBM(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $04, $04, 0, 0); //Snac: Type x04/x04, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{Request BOS rights. This from the OSCAR document.}
procedure CreateCLI_REQBOS(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $09, $02, 0, 0); //Snac: Type x09/x02, ID x0000, Flags 0
PktFinal(Pkt); //Finalize packet
end;
{This packet sends the client's capabilities information to the server.}
procedure CreateCLI_SETUSERINFO(Pkt: PRawPkt; var Seq: Word);
const
caps: array[0..$40 - 1] of Byte = (
$09, $46, $13, $49, $4C, $7F, $11, $D1, $82, $22, $44, $45, $53, $54, $00, $00,
$97, $B1, $27, $51, $24, $3C, $43, $34, $AD, $22, $D6, $AB, $F7, $3F, $14, $92,
$2E, $7A, $64, $75, $FA, $DF, $4D, $C8, $88, $6F, $EA, $35, $95, $FD, $B6, $DF,
$09, $46, $13, $44, $4C, $7F, $11, $D1, $82, $22, $44, $45, $53, $54, $00, $00
);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $02, $04, 0, 0); //Snac: Type x02/x04, ID x0000, Flags 0
PktTLV(Pkt, 5, Length(caps), @caps); //Client's capabilities
PktFinal(Pkt); //Finalize packet
end;
{This packet seems to change some of the values passed from the server
in SRV_REPLYICBM SNAC(4,5).}
procedure CreateCLI_SETICBM(Pkt: PRawPkt; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $04, $02, 0, 0); //Snac: Type x04/x02, ID x0000, Flags 0
PktInt(Pkt, 0, 4); //0, Unknown; Numbers similar to x04/x05
PktInt(Pkt, $0003, 2); //3, Unknown
PktInt(Pkt, $1F40, 2); //8000, Unknown
PktInt(Pkt, $03E7, 2); //999, Unknown
PktInt(Pkt, $03E7, 2); //999, Unknown
PktInt(Pkt, 0, 4); //0, Unknown
PktFinal(Pkt); //Finalize packet
end;
{This sets the clients online status code and some other direct client
to client information as well. Used in login sequence.}
procedure CreateCLI_SETSTATUS(Pkt: PRawPkt; Status: LongWord; IP: LongInt; Port: Word; Cookie: LongWord; ProxyType: TProxyType; var Seq: Word);
var
lpkt: TRawPkt;
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $1E, 0, 0); //Snac: Type x01/x1E, ID x0000, Flags 0
PktTLV(Pkt, $06, 4, Status); //TLV(06) Status
PktTLV(Pkt, $08, 2, 0); //TLV(08) Error code
PktInitRaw(@lpkt);
//{$R-}
PktInt(@lpkt, Swap32(IP), 4); //The client computer's local IP address.(internal)
//{$R+}
PktInt(@lpkt, Port, 4); //This is the port to connect with when making client to client connections.
if ProxyType = P_NONE then
PktInt(@lpkt, $04, 1) //01 = Firewall (or HTTPS proxy); 02 = SOCKS4/5 proxy; 04 = 'normal' connection
else if (ProxyType = P_SOCKS4) or (ProxyType = P_SOCKS5) then
PktInt(@lpkt, $02, 1);
PktInt(@lpkt, ICQ_PROTOCOL_VER, 2); //The highest client to client protocol version this client uses.
PktInt(@lpkt, Cookie, 4); //Probably a direct client to client connection cookie.
PktInt(@lpkt, $0000, 2); //0, Unknown
PktInt(@lpkt, $0050, 2); //80, Unknown
PktInt(@lpkt, $0000, 2); //0, Unknown
PktInt(@lpkt, $0003, 2); //Count: 3
//Theese are used in miranda-icq // eraser
//PktInt(@lpkt, $FFFFFFFF, 4); //time(NULL): Miranda
//PktInt(@lpkt, $00010201, 4); //time(NULL): version 0.1.2.1
//PktInt(@lpkt, $3B7248ED, 4); //time(NULL): Thu Nov 08 22:49:54 2001
PktInt(@lpkt, $00000000, 4); //time(NULL)
PktInt(@lpkt, $00000000, 4); //time(NULL)
PktInt(@lpkt, $00000000, 4); //time(NULL)
PktInt(@lpkt, $0000, 2); //0, Unknown
PktTLV(Pkt, $0C, lpkt.len, @lpkt.Data); //TLV(0C)
PktFinal(Pkt); //Finalize packet
end;
{Set client's online status after login.}
procedure CreateCLI_SETSTATUS_SHORT(Pkt: PRawPkt; Status: LongWord; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $1E, 0, 0); //Snac: Type x01/x1E, ID x0000, Flags 0
PktTLV(Pkt, $06, 4, Status); //TLV(06) Status
PktFinal(Pkt); //Finalize packet
end;
{Set idle information. If idle_secs field is 0 then the user
isn't idle at all and the server informs all watching clients
to remove idletime-string in their tooltip of my uin-item.
If idle_secs field is greater then 0 then the user has already
been idle for idle_secs number of seconds. The server will
automatically keep incrementing this number, so do not repeatedly
call with new idle times.}
procedure CreateCLI_SETIDLETIME(Pkt: PRawPkt; const IsIdle: Boolean; var Seq: Word);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $11, 0, 0); //Snac: Type x01/x11, ID x0000, Flags 0
if IsIdle then
PktInt(Pkt, $0000003C, 4) //idle_secs field is 60 seconds - Show idle time = YES
else
PktInt(Pkt, $00000000, 4); //idle_secs field is 0 - Show idle time = NO
PktFinal(Pkt); //Finalize packet
end;
{This packet seems to pass the SNAC Families and their versions
along with some unknown other information back to the server.}
procedure CreateCLI_READY(Pkt: PRawPkt; var Seq: Word);
const
buf: array[0..79] of Byte = (
$00, $01, $00, $03, $01, $10, $04, $7B,
$00, $13, $00, $02, $01, $10, $04, $7B,
$00, $02, $00, $01, $01, $01, $04, $7B,
$00, $03, $00, $01, $01, $10, $04, $7B,
$00, $15, $00, $01, $01, $10, $04, $7B,
$00, $04, $00, $01, $01, $10, $04, $7B,
$00, $06, $00, $01, $01, $10, $04, $7B,
$00, $09, $00, $01, $01, $10, $04, $7B,
$00, $0A, $00, $01, $01, $10, $04, $7B,
$00, $0B, $00, $01, $01, $10, $04, $7B
);
begin
PktInit(Pkt, 2, Seq); //Channel 2
PktSnac(Pkt, $01, $02, 0, 0); //Snac: Type x01/x02, ID x0000, Flags 0
PktAddArrBuf(Pkt, @buf, SizeOf(buf)); //Number sequence matches SNAC(x01/x17)
PktFinal(Pkt); //Finalize packet
end;
{This packet seems to act as an interface between the AIM OSCAR-based server
and the old original ICQ server database.}
procedure CreateCLI_TOICQSRV(Pkt: PRawPkt; UIN: LongWord; Command: Word; Data: Pointer; DataLen: LongWord; var Seq, Seq2: Word);
var
lpkt: TRawPkt;
len: Word;
begin
PktInit(Pkt, 2, Seq); //Channel 2
if Seq2 = 2 then
PktSnac(Pkt, $15, $02, $00010002, 0) //Snac: Type x15/x02, ID x00010002, Flags 0
else
PktSnac(Pkt, $15, $02, $00000000, 0); //Snac: Type x15/x02, ID x00000000, Flags 0
PktInitRaw(@lpkt);
Inc(lpkt.Len, 2);
PktInt(@lpkt, Swap32(UIN), 4);
PktInt(@lpkt, Swap16(Command), 2);
PktInt(@lpkt, Swap16(Seq2), 2);
PktAddArrBuf(@lpkt, Data, DataLen);
//Store remaining size
len := lpkt.Len;
lpkt.Len := 0;
PktLInt(@lpkt, len - 2, 2);
lpkt.Len := len;
//--
PktTLV(Pkt, 1, lpkt.Len, @lpkt);
PktFinal(Pkt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -