Share

TICQLib

Tracker: Bugs

9 TICQclient can't receive messages - ID: 1646364
Last Update: Comment added ( nobody )

Hi folks!

Looks like ICQ Inc. changes protocol once again. My program can't receive
messages. Event 'PktParse' is emitted, but that's all - after few seconds
my beloved ICQ client shows me that message can't be delivered. :(


Alek Silverstone ( alek_si ) - 2007-01-28 10:39

9

Open

Fixed

Nobody/Anonymous

ICQClient.pas bug

None

Public


Comments ( 4 )




Date: 2008-02-23 17:14
Sender: nobody

Logged In: NO

open ICQClient.pas

and replace whole procedure: procedure TICQClient.HSnac0407(Flap:
TFlapHdr; Snac: TSnacHdr; Pkt: PRawPkt);

with:
procedure TICQClient.HSnac0407(Flap: TFlapHdr; Snac: TSnacHdr; Pkt:
PRawPkt);
var
ITime, IRandomID: LongWord;
ULen: Word;
c, i: Word;
TlvType:Word;
ft_pkt, ack_pkt: TRawPkt;
chunks: array[0..49] of Byte;
CharsetNumber, CharsetSubset: Word;
Msg, UIN: String;
Status: LongWord;
MsgType: Word;
MsgFlag: Byte;
Answer: LongWord;
aPort: Word;
aIP: DWord;
extIP: DWORD;
wAck: Word;
Request: Boolean;
// dwOnlineSince: DWORD;
Desc, URL: String;
v: Byte;
atype: String;
XML: String;
XMLTime, XMLSource, XMLSender, XMLText: String;
FName, FDesc: String;
FSize: LongWord;
FFSeq, FFSeq2: Word;
Rec: TFTRequestRec;
TCMD: String;
List: TStringList;
PSender, PEmail, PSenderIP: string;
chan: integer;
begin
Request := False;
ITime := GetInt(Pkt, 4); //Time(system up since):
time(NULL) - ITime div 1000
//'System up since: ' +
DateTimeToStr(DateTimeToUnix(Now) - ITime div 1000);
//Seen by ICQ2003x

IRandomID := GetInt(Pkt, 2); //RandomID
Inc(Pkt^.Len, 2); //Unknown: empty
Msg := '';
{Subtypes}
chan:=GetInt(Pkt, 2);
UIN := GetStr(Pkt, GetInt(Pkt, 1));
Inc(Pkt^.Len, 2);
c := GetInt(Pkt, 2); //A count of the number of
following TLVs.
for i := 0 to c - 1 do //Skip all TLVs
begin
Inc(Pkt^.Len, 2);
if (Pkt^.Len>=Flap.DataLen) then exit;
Inc(Pkt^.Len, GetInt(Pkt, 2));
end;
case chan of
1: //Simply(old-type)
message
begin
if GetInt(Pkt, 2) = 2 then //TLV with message remain
begin
Inc(Pkt^.Len, 4); //TLV length + Unknown
const
Inc(Pkt^.Len, GetInt(Pkt, 2)); //Counts of following
bytes + following bytes
Inc(Pkt^.Len, 2); //x0101, Unknown,
constant
ULen := GetInt(Pkt, 2) - 4; //Length of the message +
4

// Support for other charsets by Yegor
CharsetNumber:=GetInt (Pkt, 2); //The encoding used for
the message.
//0x0000: US-ASCII
//0x0002: UCS-2BE (or
UTF-16?)
//0x0003: local 8bit
encoding, eg iso-8859-1, cp-1257, cp-1251.
//Beware that UCS-2BE will
contain zero-bytes for characters in the US-ASCII range.
CharsetSubset:=GetInt (Pkt, 2); //Unknown; seen: 0x0000 =
0, 0xffff = -1.

// Inc(Pkt^.Len, 4); //Unknown seems to be
constant

Msg := GetStr(Pkt, ULen); //The actual message text.
There will be no ending NULL.
if not ((CharsetNumber=0) or (CharsetNumber=3))
then Msg:=UTF8ToStrSmart (Msg);
if FDoPlain
then Msg:=RTF2Plain (Msg);
if (Length(Msg) > 0) and Assigned(OnMessageRecv) then
FOnMsg(Self, Msg, UIN);
end;
end;
2: //Advanced(new-type)
begin
while(Pkt^.Len<Flap.DataLen)do
begin
if GetInt(Pkt, 2) = 5 then

begin
Inc(Pkt^.Len, 2);
if GetInt(Pkt, 2) <> 0 then //ACKTYPE: 0x0000 - This
is a normal message
Exit;
Inc(Pkt^.Len, 16); //File signature
Inc(Pkt^.Len, 8); //TIME + RANDOM
for i := 0 to 5 do
begin
TlvType := GetInt(Pkt, 2);

if TlvType = $2711 then //Searching for TLV(2711) (with
sources)
begin
// * eraser 21.04.2004
// todo: AdvancedOnlineInfo event: aIP, aPort, ITime, Online
Since
Inc(Pkt^.Len, 2); //TLV Length
Move(Ptr(LongWord(Pkt) + Pkt^.Len)^, chunks, 47);
if GetInt(Pkt, 1) <> $1B then //If this value is not
present, this is not a message packet. Also, ICQ2001b does not send an ACK,
SNAC(4,B), if this is not 0x1B.
Exit;
Inc(Pkt^.Len, 26);
FFSeq := GetInt(Pkt, 2);
Inc(Pkt^.Len, 16);
// * eraser 21.04.2004
MsgType := GetInt(Pkt, 1); //message type (e.g. ea =
AWAY)
MsgFlag := GetInt(Pkt, 1); //message flags (e.g. 03 =
MFLAG_AUTO)
Answer := GetInt(Pkt, 4); //Read away-msg: seen 00
00 00 00
//Send away-msg: seen zero
and non zero

//Away-Msgs respond from ICQ Lite
if ((MsgType and $E0) = $E0) and (MsgFlag = MFLAG_AUTO)
then
begin
if Request = False then begin
Msg := GetLNTS(Pkt); //message string
(null-terminated)
if Assigned(OnAutoMsgResponse) then
FOnAutoMsgResponse(Self, UIN, IRandomID, MsgType,
Msg);
// Exit;
end;
(*
else (todo) who is reading my away-msg event
*)
end else
//
if MsgType = M_FILE then //File request
begin
FDesc := GetLNTS(Pkt); //File description
Inc(Pkt^.Len, 4); //Unknown: 00 00 00 00
FName := GetLNTS(Pkt); //File name
FSize := GetLInt(Pkt, 4); //File size

{Set the records' items}
Rec.ITime := ITime;
Rec.IRandomID := IRandomID;
Rec.UIN := StrToInt64(UIN);
Rec.FileSize := FSize;
Rec.Description := FDesc;
Rec.FileName := FName;
Rec.Seq := FFSeq;
Rec.ReqType := $01;
if Assigned(OnFTRequest) then
FOnFTRequest(Self, Rec);
Exit;
end else
if MsgType = M_ADVANCED then //Advanced message
container
begin
GetLNTS(Pkt); //Empty message (contains
only a null terminator)
Inc(Pkt^.Len, 2); //Following length
Inc(Pkt^.Len, 16); //Signature
Inc(Pkt^.Len, 2); //Unknown: empty
TCMD := GetDWStr(Pkt); //Text command
If (Pos('File', TCmd) > 0) or (Pos(#$D4#$E0#$E9#$EB, TCmd)
> 0) Then {Fix for russian users from Yegor} //Someone is sending
us a file
begin
Inc(Pkt^.Len, 19);
fDesc := GetDWStr(Pkt);
aPort := GetInt(Pkt, 2);
FFSeq2:= GetInt(Pkt, 2);
fName := GetWStr(Pkt);
fSize := GetInt(Pkt, 4);
Rec.Port := aPort;
Rec.ITime := ITime;
Rec.IRandomID := IRandomID;
Rec.UIN := StrToInt64(UIN);
Rec.FileSize := FSize;
Rec.Description := FDesc;
Rec.FileName := FName;
Rec.Seq := FFSeq;
// Send Ack through Server.
Rec.ReqType := $01; //
//NOTE From NighTrader: This is not working correctly,
//I was doing this wrong, if you have any knowladge of
//how this works please ICQ me @ 30391169.
if Assigned(OnFTRequest) then
FOnFTRequest(Self, Rec);
Exit;
end else
if (Pos('Request For Contacts', TCMD) > 0) or
(Pos(#$C7#$E0#$EF#$F0#$EE#$F1#$20#$CA#$EE#$ED#$F2#$E0#$EA#$F2#$EE#$E2,
TCmd) > 0) then
begin
Inc(Pkt^.Len, 15); //15 unknown bytes
Inc(Pkt^.Len, 4); //Following length
Msg := GetDWStr(Pkt); //Message containing a
reason
if Assigned(OnContactListRequest) then
FOnContactListReq(Self, UIN, Msg);
end else
if (Pos('Contacts',TCMD) > 0 ) or
(Pos(#$CA#$EE#$ED#$F2#$E0#$EA#$F2#$FB, TCMD) > 0) then
begin
Inc(Pkt^.Len, 4); //Following length
Msg := GetDWStr(Pkt); //Message containing a
list with contacts
List := TStringList.Create; //Create temporary list
ParseContacts(Msg, List); //Parse message with
contacts
if Assigned(OnContactListRecv) then
FOnContactListRecv(Self, UIN, List);
end else
if (Pos('Web Page Address (URL)',TCMD) > 0) or
(Pos(#$CF#$EE#$F1#$EB#$E0#$F2#$FC#$20#$D1#$F1#$FB#$EB#$EA#$F3#$20#$ED#$E0#$20#$E2#$E5#$E1#$2D#$F1#$F2#$F0#$E0#$ED#$E8#$F6#$F3,TCmd)
> 0) then
begin
// Handle URL Msg
Inc(Pkt^.Len, 19);
Msg := GetDWStr(Pkt);
if Pos(#$FE, Msg) <> -1 then begin // Break apart
strings
Desc := Copy(Msg, 1, Pos(#$FE, Msg) - 1);
URL := Copy(Msg, Length(Desc) + 2, 255);
if Assigned(OnURLRecv) then
FOnURL(Self, Desc, URL, UIN);
end;
end;
end
else
Msg := GetLNTS(Pkt); //The actual message text.
There will be ending NULL.

{Sending ACK of the message}
PktInit(@ack_pkt, 2, FSeq); //Channel 2
PktSnac(@ack_pkt, $04, $0B, 0, 0); //SNAC(x04/x0B)
Move(Ptr(LongWord(Pkt) + TSNACSZ)^, Ptr(LongWord(@ack_pkt) +
ack_pkt.Len)^, 10); //First 10 bytes of TLV(2711)
Inc(ack_pkt.Len, 10); //Skip first 10
bytes copied from TLV(2711) which were added before
PktLStr(@ack_pkt, UIN); //User's UIN
PktInt(@ack_pkt, $0003, 2); //00 03
PktAddArrBuf(@ack_pkt, @chunks, 47); //First 47 bytes
of source packet (with message)
PktInt(@ack_pkt, $00000000, 4); //00 00 00 00
//If it's an auto-away message request
if (MsgType and $E0 = $E0) and Request then
PktLNTS(@ack_pkt, FAutoAwayMsg) //Auto-away
message
else begin
PktInt(@ack_pkt, 1, 1); //01
PktInt(@ack_pkt, 0, 4); //00 00 00 00
PktInt(@ack_pkt, 0, 2); //00 00
PktInt(@ack_pkt, $FFFFFF00, 4); //FF FF FF 00
end;
PktFinal(@ack_pkt);
FSock.SendData(ack_pkt, ack_pkt.Len);

if (Length(Msg) > 0) then
begin
if MsgType = M_PLAIN then
begin
if FDoPlain then Msg := Rtf2Plain(Msg); //Convert
message from RTF to plaintext when needed
if Assigned(OnMessageRecv) then
FOnMsg(Self, Msg, UIN);
end else
if MsgType = M_URL then
begin
Desc := Copy(Msg, 0, Pos(#$fe, Msg) - 1);
URL := Copy(Msg, Pos(#$fe, Msg) + 1, Length(Msg) -
Pos(#$fe, Msg));
if Assigned(OnURLRecv) then
FOnURL(Self, Desc, URL, UIN);
end;
end;
Exit;
end else
if TlvType = 5 then // TVL(5) Get a Port
begin
Inc(pkt^.Len, 2); // Skip Length
aPort := GetInt(Pkt, 2); // Get Port Number
end else
// *eraser 21.04.2004
{
if TlvType = 6 then // TLV(6) Status
begin
Inc(pkt^.Len, 4);
Status := GetInt(Pkt, 4);
end else
}
if TlvType = $0004 then // TLV(4) Get an ExtIP
begin
Inc(pkt^.Len, 4); // skip length
extIP := GetInt(Pkt, 4); // Get IP Number
end else
if TlvType = $000F then // TLV(F)
begin
Inc(pkt^.Len, 2); // skip length
Request := True; // possibly it is a request
end else
if TlvType = $000A then // TLV(A)
begin
Inc(pkt^.Len, 2); // 0x0002 skip length
wAck := GetInt(Pkt, 2); // seen 0001 - req (unk 0x000F
0x0000)
// seen 0002 - reply (IP, Port)
end else
//
if TlvType = 3 then // TLV(3) Get an IntIP
begin
Inc(pkt^.Len,2); // Skip Length
aIP := GetInt(Pkt,4); // Get IP Number
end else
Inc(Pkt^.Len, GetInt(Pkt, 2));
end;
end else
Inc(Pkt^.Len, GetInt(Pkt, 2));
end;
// todo special user online event
end;
4: //Another message
type
begin
UIN := GetLStr(Pkt);
for i := 0 to 4 do
begin
v := GetInt(Pkt, 1);
if (v = 5) or ((GetInt(Pkt, 1) = 5) and (v = 0)) then //TLV(5)
was found
begin
if v = 5 then //Some
modifications for MAC clients
Inc(Pkt^.Len, 40)
else
Inc(Pkt^.Len, 2);
GetLInt(Pkt, 4); //UIN
MsgType := GetLInt(Pkt, 2); //Message-type
Msg := GetLNTS(Pkt); //Message
if MsgType = $1a then //Probably
advanced msg format
begin
Inc(Pkt^.Len, 20); //20 unknown
bytes
atype := GetDWStr(Pkt); //Advanced msg
sub-type
if Pos ('ICQSMS', aType)<>0 then //Corresponds to
received SMS message in XML formatted message
begin
Inc(Pkt^.Len, 3); //00 00 00
Inc(Pkt^.Len, 4); //4-byte little
endian length of the following data
XML := GetStr(Pkt, GetLInt(Pkt, 4)); //XML entry of SMS
response
XMLSource := GetXMLEntry('source', XML); //Source, usually:
'ICQ'
XMLSender := GetXMLEntry('sender', XML); //Source cellular
number
XMLText := GetXMLEntry('text', XML); //Text of reply
XMLTime := GetXMLEntry('time', XML); //Time of sending
reply
if Assigned(OnSMSReply) then
FOnSMSReply(Self, XMLSource, XMLSender, XMLTime,
UTF8ToStrSmart(XMLText));
end;
Exit;
end;

if (Length(Msg) > 0) then
begin
if MsgType = M_PLAIN then
begin
if FDoPlain then Msg := Rtf2Plain(Msg); //Convert
message from RTF to plaintext when needed
if Assigned(OnMessageRecv) then
FOnMsg(Self, Msg, UIN);
end
else if MsgType = M_URL then
begin
Desc := Copy(Msg, 0, Pos(#$fe, Msg) - 1);
URL := Copy(Msg, Pos(#$fe, Msg) + 1, Length(Msg) - Pos(#$fe,
Msg));
if Assigned(OnURLRecv) then
FOnURL(Self, Desc, URL, UIN);
end else
if MsgType = M_WEB_PAGE then // Updated by Saif.N * To
Support Web Page Message
begin
PSender := Copy(Msg, 1, Pos(#$fe, Msg) - 1);
Msg := Copy(Msg,Length(PSender)+4, Length(Msg));
PEmail := Copy(Msg, 1 , Pos(#$fe, Msg)-1);
Msg := Copy(Msg,Length(PEmail)+1, Length(Msg));
PSenderIP:= Copy(Msg, Pos('IP:', Msg)+4, Pos(#$D,
Msg)-Pos('IP:', Msg)-4);
Msg := Copy(Msg, Pos(#$A,Msg) + 1, Length(Msg));
if Assigned(OnWPagerRecv) then
FonWPager(Self, PSender, PEmail, PSenderIP, Msg);
end;
end;
Exit;
end else
Inc(Pkt^.Len, GetInt(Pkt, 2));
end;
end;
end;
end;


Date: 2007-09-23 12:03
Sender: gamycabrera


hi
I don't understand Russian, please explain me what to do exactly. Another
thing, reading the code on that site it don't math mo code. Please send me
the entire ICQClient.pas or any updated link. My direct email:
gamy.cabrera@hotmail.com or gmail.com
Thanks in advance.


Date: 2007-02-12 17:16
Sender: lousek


Thanks for URL. My IcqClient is :-)


Date: 2007-01-30 17:57
Sender: terebizh


This bug now fixed. You can see code changes by URL:

http://forum.sysman.ru/index.php?showtopic=3304&view=findpost&p=83293



Log in to comment.




Attached File

No Files Currently Attached

Changes ( 6 )

Field Old Value Date By
status_id Closed 2007-01-30 18:16 alek_si
close_date 2007-01-30 18:15 2007-01-30 18:16 alek_si
status_id Open 2007-01-30 18:15 alek_si
resolution_id None 2007-01-30 18:15 alek_si
close_date - 2007-01-30 18:15 alek_si
priority 5 2007-01-28 10:40 alek_si