⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icqclient.pas

📁 DarkMoon v4.11 (远程控制) 国外收集的代码,控件下载: http://www.winio.cn/Blogs/jishuwenzhang/200712/20071208230135.
💻 PAS
📖 第 1 页 / 共 5 页
字号:
      end;
      //Sending CLI_GOODBYE
      PktInit(@pkt, 4, FSeq);
      PktFinal(@pkt);
      FSock.SendData(pkt, pkt.Len);
      FSock.Disconnect;
      //Assigning new IP and Port to connect to in second attemp
      InitNetICQ;
      FSock.Host := Copy(FData, 0, Pos(':', FData) - 1);
      FSock.Port := StrToInt(Copy(FData, Pos(':', FData) + 1, Length(FData) - Pos(':', FData)));
      if (FSock.Port = 0) then
      begin
        OnIntError(nil, ERR_PROTOCOL, 'Received malformed login packet');
        FTOnConnectError(Self);
        Exit;
      end;
      FSock.Connect;
    end;
  end;
end;

{////////////////////////////////////////////////////////////////////////////////////////////////////}
procedure TICQClient.SetStatus(NewStatus: LongWord);
var
  pkt: TRawPkt;
begin
  if not LoggedIn then Exit;
  if (StatusToStr(FStatus) = 'Invisible') and (StatusToStr(NewStatus) <> 'Invisible') then
  begin
    CreateCLI_ADDINVISIBLE(@pkt, FInvisibleLst, FSeq);
    FSock.SendData(pkt, pkt.Len);
  end else
  if (StatusToStr(NewStatus) = 'Invisible') and (StatusToStr(FStatus) <> 'Invisible') then
  begin
    CreateCLI_ADDVISIBLE(@pkt, FVisibleLst, FSeq);
    FSock.SendData(pkt, pkt.Len);
  end;
  CreateCLI_SETSTATUS_SHORT(@pkt, NewStatus, FSeq);
  FSock.SendData(pkt, pkt.Len);
  FStatus := NewStatus;
end;

{Handling packet with messages}
procedure TICQClient.HSnac0407(Flap: TFlapHdr; Snac: TSnacHdr; Pkt: PRawPkt);
var
  ITime, IRandomID: LongWord;
  ULen: Word;
  c, i: Word;
  ack_pkt: TRawPkt;
  chunks: array[0..49] of Byte;
  Msg, UIN: String;
  MsgType: Word;
  Desc, URL: String;
  v: Byte;
  atype: String;
  XML: String;
  XMLTime, XMLSource, XMLSender, XMLText: String;
  FName, FDesc: String;
  FSize: LongWord;
  FFSeq: Word;
  Rec: TFTRequestRec;
  TCMD: String;
  List: TStringList;
begin
  ITime := GetInt(Pkt, 4);                      //Time
  IRandomID := GetInt(Pkt, 2);                  //RandomID
  Inc(Pkt^.Len, 2);                             //Unknown: empty
  Msg := '';
  {Subtypes}
  case GetInt(Pkt, 2) of
    1:                                          //Simply(old-type) message
    begin
      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);
        Inc(Pkt^.Len, GetInt(Pkt, 2));
      end;
      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
        Inc(Pkt^.Len, 4);                       //Unknown seems to be constant
        Msg := GetStr(Pkt, ULen);               //The actual message text. There will be no ending NULL.
        if (Length(Msg) > 0) and Assigned(OnMessageRecv) then
          FOnMsg(Self, Msg, UIN);
      end;
    end;
    2:                                          //Adnavced(new-type)
    begin
      UIN := GetStr(Pkt, GetInt(Pkt, 1));
      for c := 0 to 5 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
            if GetInt(Pkt, 2) = $2711 then      //Searching for TLV(2711) (with sources)
            begin
              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);
              MsgType := GetInt(Pkt, 1);
              Inc(Pkt^.Len, 5);
              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 := StrToInt(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 TCMD = 'Contacts' 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 TCMD = 'Request For Contacts' 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;
              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 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 := Rtf2Txt(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
              Inc(Pkt^.Len, GetInt(Pkt, 2));
          end;
        end else
          Inc(Pkt^.Len, GetInt(Pkt, 2));
      end;
    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 atype = 'ICQSMS' 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 := Rtf2Txt(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
          Inc(Pkt^.Len, GetInt(Pkt, 2));
      end;
    end;
  end;
end;

{Handling old type packets ICQ_FROMSRV}
procedure TICQClient.HSnac1503(Flap: TFlapHdr; Snac: TSnacHdr; Pkt: PRawPkt);
var
  FMsgType: Word;
  lpkt: TRawPkt;
  FNick, FFirst, FLast, FEmail, FCity,
  FState, FPhone, FFax, FStreet, FCellular,
  FZip, FCountry, FCompany, FDepartment,
  FPosition, FOccupation, FHomePage,
  FLang1, FLang2, FLang3, FAbout: String;
  FTimeZone: Byte;
  FPublishEmail: Boolean;
  FAge, FYear: Word;
  FGender, FMonth, FDay: Byte;
  Msg, UIN, URL, Desc: String;
  List, List2: TStringList;
  C, i: Byte;
  WW: Word;
  FStatus: Word;
  cmd: Word;
  seq: Word;
  FSmsSource, FSmsDeliverable, FSmsNetwork, FMsgId: String;
  FAuthorize: Byte;
begin
  if GetInt(Pkt, 2) = 1 then                      //TLV(1)
  begin
    Inc(Pkt^.Len, 8);
    case GetInt(Pkt, 2) of
      $4100:                                      //SRV_OFFLINEMSG
      begin
        Inc(Pkt^.Len, 2);                         //The sequence number this packet is a response to.
        UIN := IntToStr(GetLInt(Pkt, 4));         //Source UIN
        Inc(Pkt^.Len, 6);                         //Date/time etc...
        FMsgType := GetLInt(Pkt, 2);              //The type of message sent, like URL message or the like.
        Msg := GetLNTS(Pkt);
        if FDoPlain then Msg := Rtf2Txt(Msg);     //Convert message from RTF to plaintext when needed
        if FMsgType = M_PLAIN then
        begin
          if Assigned(OnOfflineMsgRecv) then
            FOnOffMsg(Self, Msg, UIN);
        end else
        if FMsgType = 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(OnOfflineURLRecv) then
            FOnOffURL(Self, Desc, URL, UIN);
        end;
      end;
      $4200: //All offline messages were sent, so we ACKING them
      begin
        FSeq2 := 2;
        CreateCLI_ACKOFFLINEMSGS(@lpkt, FLUIN, FSeq, FSeq2);
        FSock.SendData(lpkt, lpkt.Len);
      end;
      $da07: //SRV_META
      begin
        seq := GetLInt(Pkt, 2);
        cmd := GetInt(Pkt, 2);
        case cmd of
          $0100: //SRV_SMSREFUSED
          begin
            if Assigned(OnSMSRefused) then
              FOnSMSRefused(Self);
          end;
          $9600: //SRV_SMSACK
          begin
            if GetInt(Pkt, 1) <> $0a then Exit;
            Inc(Pkt^.Len, 12);
            Msg := GetStr(Pkt, GetLInt(Pkt, 2));
            FSmsSource := GetXML

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -