Menu

#8 TICQclient can't receive messages

open-fixed
nobody
9
2007-01-30
2007-01-28
No

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. :(

Discussion

  • Alek Silverstone

    • priority: 5 --> 9
     
  • Alek Silverstone

    • status: open --> closed-fixed
     
  • Alek Silverstone

    • status: closed-fixed --> open-fixed
     
  • Milos

    Milos - 2007-02-12

    Logged In: YES
    user_id=1632995
    Originator: NO

    Thanks for URL. My IcqClient is :-)

     
  • Gamy.Cabrera

    Gamy.Cabrera - 2007-09-23

    Logged In: YES
    user_id=1896905
    Originator: NO

    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.

     
  • Nobody/Anonymous

    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;

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.