Menu

New changes in 02.2007?

Help
Emphaser
2007-01-30
2013-03-22
  • Emphaser

    Emphaser - 2007-01-30

    Hi,

    anyone got a clue or solution what recently has changed to the ICQ prot. Any distributions, what must be changed in TICQLIB would be great. I luv u all :)

    cu Markus

     
    • Alexander Terebizh

       
    • padmalcom

      padmalcom - 2007-01-30

      Could anyone translate that please :D

       
    • Alexander Terebizh

      Yes :)

      You should change procedure TICQClient.HSnac0407 (file ICQClient.pas). New procedure :

      ///-- begin new TICQClient.HSnac0407

      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);
                avt_t2 := GetInt(Pkt, 2);
                if avt_t2 <> 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;

      ///-- end new TICQClient.HSnac0407

       

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.