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

📄 qqkernel.pas

📁 application with delphi
💻 PAS
字号:
{
QQ[OICQ] Runer Ver 1.01

Copyright (C) 2006 HellFish

E-Mail: hellfish@qq.com,sgfree@hotmail.com
QQ[OICQ]: 4427968

保留以上信息,保留对作者最基本的尊重
}

unit QQKernel;

interface

Uses Windows,SysUtils,WinSock,WSocket,
     QQPROTO,QQVars,QQInPacket,QQOutPacket,MD5;

type
  TQQRuner = class(TObject)
  private
    FUdpSocket: TWSocket;
    procedure OnError(Sender : TObject; E:Exception;var CanClose : Boolean);
    procedure OnRecv(Sender: TObject; Error: Word);
    procedure OnState(Sender: TObject; OldState, NewState : TSocketState);
    procedure QQLogin;
    procedure QQImReply(RecvQQ:Integer;SendIP,Serial:Array of Byte);
  public
    FInfo:TQQInfo;
    constructor Create;
    destructor Destroy; override;
    procedure QQStart;
    procedure QQStop;
    procedure QQReLogin;
    procedure QQKeepLive;
    procedure QQChangeStat(iMode:Boolean);
    procedure QQSendIM(SendQQ:Integer;Text:String;tSize:Byte=32;tMode:Byte=$29;cR:Byte=$0;cG:Byte=$0;cB:Byte=$0);
  end;

implementation

constructor TQQRuner.Create;
begin
inherited;
FInfo.State:=QsNone;
FInfo.Number:=0;
FInfo.Server:=QQServers[0];
FInfo.Hide:=False;
FInfo.Password:='';
FInfo.AutoReply:='';
FInfo.ErrorCount:=0;
FInfo.ErrorString:='';
FInfo.LoginTime:='';
FInfo.NowTime:=0;
ZeroMemory(@FInfo.PasswordKey[0],16);
ZeroMemory(@FInfo.InitKey[0],16);
ZeroMemory(@FInfo.SessionKey[0],16);
end;

destructor TQQRuner.Destroy;
begin
QQStop;
inherited;
end;

procedure TQQRuner.QQStart;
begin
if Finfo.State<>QsLoginSucess then
begin
FUdpSocket:=TWSocket.Create(nil);
FUdpSocket.Proto:='udp';
FUdpSocket.OnDataAvailable:=OnRecv;
FUdpSocket.OnBgException:=OnError;
FUdpSocket.OnChangeState:=OnState;
FUdpSocket.Addr:=Finfo.Server;
FUdpSocket.Port:=QQ_UDPPORT;
FUdpSocket.LocalPort:='0';
try
FUdpSocket.Connect;
except
Inc(FInfo.ErrorCount);
FInfo.ErrorString:=Format(String_SocketError,[String_CanConn,WSAGetLastError]);
end;
end;
end;

procedure TQQRuner.QQStop;
var
Buf:TQQBuff;
I:Integer;
begin
if Finfo.State=QsLoginSucess then
begin
Buf:=BuildLogout(Finfo.Number,FInfo.SessionKey,FInfo.PassWordKey);
for I:=1 to SENDTIME_NOPACK do FUdpSocket.Send(@Buf[0],Length(Buf));
end;
FUdpSocket.Close;
FUdpSocket.Destroy;
FInfo.State:=QsNone;
end;

procedure TQQRuner.QQKeepLive;
var
Buf:TQQBuff;
begin
Buf:=BuildKeepLive(Finfo.Number,FInfo.SessionKey);
FUdpSocket.Send(@Buf[0],Length(Buf));
end;

procedure TQQRuner.QQLogin;
var
Buf:TQQBuff;
MD5One,MD5Key:MD5Digest;
TmpStr:String;
I:Integer;
begin
For I:=0 To 15 do FInfo.InitKey[I]:=Trunc(Random * 256); //初始秘匙
MD5One:=MD5String(FInfo.Password);
SetLength(TmpStr,16);
CopyMemory(@TmpStr[1],@MD5One[0],16);
MD5Key:=MD5String(TmpStr);
CopyMemory(@Finfo.PasswordKey[0],@MD5Key[0],16); //PasswordKey
Buf:=BuildLogin(Finfo.Number,Finfo.Hide,Finfo.InitKey,Finfo.PasswordKey,FInfo.LoginToKen,Length(FInfo.LoginToKen));
FUdpSocket.Send(@Buf[0],Length(Buf));
end;

procedure TQQRuner.QQReLogin;
begin
Finfo.State:=QsReLogin;
FInfo.KeepAliveCount:=0;
FInfo.TimerCount:=0;
QQStop;
QQStart;
end;

procedure TQQRuner.QQSendIM(SendQQ:Integer;Text:String;tSize:Byte=$20;tMode:Byte=$29;cR:Byte=$0;cG:Byte=$0;cB:Byte=$0);
var
Buf:TQQBuff;
begin
Buf:=BuildSendIM(Finfo.Number,Finfo.NowTime,SendQQ,Text,Finfo.SessionKey,tSize,tMode,cR,cG,cB);
FUdpSocket.Send(@Buf[0],Length(Buf));
end;

procedure TQQRuner.QQChangeStat(iMode:Boolean);
var
Buf:TQQBuff;
Mode:Byte;
begin
FInfo.Hide:=iMode;
if iMode then Mode:=STATUS_HIDE else Mode:=STATUS_ONLINE;
//Mode:=STATUS_AWAY;
Buf:=BuildChangeStat(Finfo.Number,Mode,Finfo.SessionKey);
FUdpSocket.Send(@Buf[0],Length(Buf));
end;

procedure TQQRuner.QQImReply(RecvQQ:Integer;SendIP,Serial:Array of Byte);
var
Buf:TQQBuff;
begin
Buf:=BuildIMReply(Finfo.Number,RecvQQ,SendIP,Serial,FInfo.SessionKey);
FUdpSocket.Send(@Buf[0],Length(Buf));
end;

procedure TQQRuner.OnState(Sender: TObject; OldState, NewState : TSocketState);
var
Buf:TQQBuff;
I:Integer;
begin
if (NewState=wsConnected) then
begin
Try
Buf:=BuildTokenReq(Finfo.Number);
for I := 0 to 3 do FUdpSocket.Send(@Buf[0],Length(Buf));
FInfo.State:=QsToKen;
except
end;
end;
end;

procedure TQQRuner.OnError(Sender : TObject; E:Exception;var CanClose : Boolean);
begin
Inc(FInfo.ErrorCount);
FInfo.ErrorString:=Format(String_SocketError,[E.Message,WSAGetLastError]);
FInfo.State:=QsError;
end;

procedure TQQRuner.OnRecv(Sender: TObject; Error: Word);
var
Buff,ProcBuf:TQQBuff;
BufLen:Integer;
LoginReply:TLoginReply;
RecvMsg:TRecvIM;
begin
SetLength(Buff,1000);
ZeroMemory(Buff,1000);
BufLen:=FUdpSocket.Receive(@Buff[0],1000);
If BufLen<LENGTH05_BASICIN then Exit;
SetLength(Buff,BufLen);
case Buff[4] of
QCMD_REQ_LOGINTOKEN:
begin
ProcBuf:=ProcessToken(Buff);
SetLength(FInfo.LoginToKen,Length(ProcBuf));
CopyMemory(@FInfo.LoginToKen[0],@ProcBuf[0],Length(ProcBuf));
QQLogin;
end;

QCMD_LOGIN:
begin
LoginReply:=ProcessLogin(Buff,Finfo.InitKey,FInfo.PasswordKey);
Case LoginReply.Stat of
LsRedirect:
begin
FInfo.Server:=LoginReply.RedirectServer;
QQReLogin;
end;
LsPwdErr:
begin
FInfo.ErrorString:=LoginReply.ErrorMessage;
FInfo.State:=QsPassWordError;
Inc(FInfo.ErrorCount);
end;
LsSucess:
begin
FInfo.ErrorString:='';
FInfo.State:=QsLoginSucess;
FInfo.LoginTime:=DateTimeToStr(Now);
CopyMemory(@Finfo.SessionKey[0],@LoginReply.SessionKey[0],16);
CopyMemory(@Finfo.ClientKey[0],@LoginReply.ClientKey[0],32);
QQKeepLive;
end;
end;//Case LoginReply.Stat
end;

QCMD_KEEPALIVE:
begin
ProcessKeepLive(Buff,Finfo.SessionKey);
Inc(FInfo.KeepAliveCount);
end;

QCMD_RECVIM:
begin
RecvMsg:=ProcessRecvIM(Buff,Buff[4],FInfo.SessionKey);
Finfo.NowTime:=RecvMsg.SendTime;
//回复确认包
QQImReply(RecvMsg.SendQQ,RecvMsg.SendIP,RecvMsg.Serial);
if (RecvMsg.MessageType=$FF) or (RecvMsg.Messages='') then Exit; //空消息退出;
//被踢
if (RecvMsg.SendQQ=10000) and (Pos(String_KickMsg,RecvMsg.Messages)>0) then Finfo.State:=QsKickOut;
//消息处理
if (Finfo.LastMessages<>RecvMsg.Messages) then
begin
Finfo.Messages:=RecvMsg.Messages;
FInfo.LastMessages:=RecvMsg.Messages;
Finfo.MessageQQ:=RecvMsg.SendQQ;
//自动回复
if (Finfo.AutoReply<>'') and (RecvMsg.MessageType<>RECV_IM_SYS) and (RecvMsg.SendQQ<>10000) then
QQSendIM(RecvMsg.SendQQ,Finfo.AutoReply,$20,$29,Finfo.RCR,Finfo.RCG,Finfo.RCB);
end;
end;

QCMD_SENDIM: ProcessSendIM(Buff,Finfo.SessionKey);

QCMD_REQKEY: ProcessReqKey(Buff,Finfo.SessionKey);

QCMD_CHANGESTATUS: ProcessChangeStatus(Buff,Finfo.SessionKey);

QCMD_RECV_KICKOUT:
begin
ProcessKickOut(Buff,Finfo.SessionKey);
Finfo.State:=QsKickOut;
end;
end;

SetLength(Buff,0);
end;

end.

⌨️ 快捷键说明

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