| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- unit MessageSenderUnit;
- {$WARN SYMBOL_PLATFORM OFF}
- interface
- uses
- ComObj, ActiveX, AxCtrls, Classes, RealOAMessenger_TLB, StdVcl, SysUtils,
- BlockingTCPClient, RealICQProxy, MD5, EncdDecd;
- type
- TMessageSender = class(TAutoObject, IConnectionPointContainer, IMessageSender)
- private
- { Private declarations }
- FConnectionPoints: TConnectionPoints;
- FConnectionPoint: TConnectionPoint;
- FEvents: IMessageSenderEvents;
- { note: FEvents maintains a *single* event sink. For access to more
- than one event sink, use FConnectionPoint.SinkList, and iterate
- through the list of sinks. }
- FBlockingTCPClient: TBlockingTCPClient;
- FServerAddress: String;
- FServerPort: SYSINT;
- FProxyType: Shortint;
- FProxyAddress: String;
- FProxyPort: SYSINT;
- FProxyPassword: String;
- FProxyUsername: String;
- FProxyDomain: String;
- FUsername: String;
- FPassword: String;
- FLogined: Boolean;
- FMessageType: Integer;
- FAutoOpenWindow: Boolean;
- FPosition,
- FLeft,
- FTop,
- FWidth,
- FHeight: Integer;
- FTitle,
- FContent,
- FUrl: String;
- FAutoCloseTime: Integer;
- FUsers: String;
- FWaitTimes: Integer;
-
- procedure ReceivedData(Sender: TObject; RecvThread:
- TBlockingTCPClientRecvThread; RecvBytes: Integer);
- procedure Connect;
- procedure Login;
- procedure Send;
-
- procedure ProcessLoginResult(Data: Array of Byte);
- procedure ProcessSendSystemMessageResult(Data: Array of Byte);
- public
- procedure Initialize; override;
- protected
- { Protected declarations }
- property ConnectionPoints: TConnectionPoints read FConnectionPoints
- implements IConnectionPointContainer;
- procedure EventSinkChanged(const EventSink: IUnknown); override;
- function Get_ServerAddress: OleVariant; safecall;
- procedure Set_ServerAddress(Value: OleVariant); safecall;
- function Get_ServerPort: OleVariant; safecall;
- procedure Set_ServerPort(Value: OleVariant); safecall;
- function Get_ProxyType: OleVariant; safecall;
- procedure Set_ProxyType(Value: OleVariant); safecall;
- function Get_ProxyAddress: OleVariant; safecall;
- procedure Set_ProxyAddress(Value: OleVariant); safecall;
- function Get_ProxyPort: OleVariant; safecall;
- procedure Set_ProxyPort(Value: OleVariant); safecall;
- function Get_ProxyPassword: OleVariant; safecall;
- function Get_ProxyUsername: OleVariant; safecall;
- procedure Set_ProxyPassword(Value: OleVariant); safecall;
- procedure Set_ProxyUsername(Value: OleVariant); safecall;
- function Get_ProxyDomain: OleVariant; safecall;
- procedure Set_ProxyDomain(Value: OleVariant); safecall;
- function Get_Username: OleVariant; safecall;
- procedure Set_Username(Value: OleVariant); safecall;
- function Get_Password: OleVariant; safecall;
- procedure Set_Password(Value: OleVariant); safecall;
- procedure SendSystemMessage(MessageType, AutoOpenWindow, Position, Left,
- Top, Width, Height, Title, Content, Url, AutoCloseTime,
- Users: OleVariant); safecall;
- end;
-
- TRealICQLoginResultType = ( rtLoginOK = 0,
- rtCanUpdate = 1,
- rtMustUpdate = 2,
- rtVersionError = 3,
- rtAuthorizationError = 4,
- rtOther = 5);
- implementation
- uses ComServ, Windows, Forms;
- procedure TMessageSender.EventSinkChanged(const EventSink: IUnknown);
- begin
- FEvents := EventSink as IMessageSenderEvents;
- end;
- procedure TMessageSender.Initialize;
- begin
- inherited Initialize;
- FConnectionPoints := TConnectionPoints.Create(Self);
- if AutoFactory.EventTypeInfo <> nil then
- FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
- AutoFactory.EventIID, ckSingle, EventConnect)
- else FConnectionPoint := nil;
- FServerAddress := '';
- FServerPort := 0;
- FProxyType := 0;
- FProxyAddress := '';
- FProxyPort := 0;
- FProxyPassword := '';
- FProxyUsername := '';
- FProxyDomain := '';
- FUsername := '';
- FPassword := '';
- FLogined := False;
- FWaitTimes := 0;
- end;
- function TMessageSender.Get_ServerAddress: OleVariant;
- begin
- Result := FServerAddress;
- end;
- procedure TMessageSender.Set_ServerAddress(Value: OleVariant);
- begin
- FServerAddress := Value;
- end;
- function TMessageSender.Get_ServerPort: OleVariant;
- begin
- Result := FServerPort;
- end;
- procedure TMessageSender.Set_ServerPort(Value: OleVariant);
- begin
- FServerPort := Value;
- end;
- function TMessageSender.Get_ProxyType: OleVariant;
- begin
- Result := FProxyType;
- end;
- procedure TMessageSender.Set_ProxyType(Value: OleVariant);
- begin
- FProxyType := Value;
- end;
- function TMessageSender.Get_ProxyAddress: OleVariant;
- begin
- Result := FProxyAddress;
- end;
- procedure TMessageSender.Set_ProxyAddress(Value: OleVariant);
- begin
- FProxyAddress := Value;
- end;
- function TMessageSender.Get_ProxyPort: OleVariant;
- begin
- Result := FProxyPort;
- end;
- procedure TMessageSender.Set_ProxyPort(Value: OleVariant);
- begin
- FProxyPort := Value;
- end;
- function TMessageSender.Get_ProxyPassword: OleVariant;
- begin
- Result := FProxyPassword;
- end;
- function TMessageSender.Get_ProxyUsername: OleVariant;
- begin
- Result := FProxyUsername;
- end;
- procedure TMessageSender.Set_ProxyPassword(Value: OleVariant);
- begin
- FProxyPassword := Value;
- end;
- procedure TMessageSender.Set_ProxyUsername(Value: OleVariant);
- begin
- FProxyUsername := Value;
- end;
- function TMessageSender.Get_ProxyDomain: OleVariant;
- begin
- Result := FProxyDomain;
- end;
- procedure TMessageSender.Set_ProxyDomain(Value: OleVariant);
- begin
- FProxyDomain := Value;
- end;
- function TMessageSender.Get_Username: OleVariant;
- begin
- Result := FUsername;
- end;
- procedure TMessageSender.Set_Username(Value: OleVariant);
- begin
- FUsername := Value;
- end;
- function TMessageSender.Get_Password: OleVariant;
- begin
- Result := FPassword;
- end;
- procedure TMessageSender.Set_Password(Value: OleVariant);
- begin
- FPassword := Value;
- end;
- procedure TMessageSender.ReceivedData(Sender: TObject; RecvThread:
- TBlockingTCPClientRecvThread; RecvBytes: Integer);
- var
- TCPClientRecvThread: TBlockingTCPClientRecvThread;
- ProtocolType: Byte;
- ProtocolLengthBytes: Array[0..1] of Byte;
- ProtocolDataBytes: Array of Byte;
- ProtocolLength: SmallInt;
- begin
- try
- TCPClientRecvThread := RecvThread;
- while TCPClientRecvThread.NotProcessedBufferLength >= 3 do
- begin
- TCPClientRecvThread.CopyRecvBufferTo(ProtocolType, 0, 1);
- TCPClientRecvThread.CopyRecvBufferTo(ProtocolLengthBytes[0], 1, 2);
- CopyMemory(@ProtocolLength, @ProtocolLengthBytes[0], 2);
- if TCPClientRecvThread.NotProcessedBufferLength < ProtocolLength then Break;
- SetLength(ProtocolDataBytes, ProtocolLength - 3);
- TCPClientRecvThread.CutRecvBufferTo(ProtocolDataBytes[0], 3, ProtocolLength - 3);
- case ProtocolType of
- $02: ProcessLoginResult(ProtocolDataBytes);
- $42: begin
- ProcessSendSystemMessageResult(ProtocolDataBytes);
- Exit;
- end;
- else
- FBlockingTCPClient.Disconnect;
- FreeAndNil(FBlockingTCPClient);
- FWaitTimes := 10000;
- raise Exception.Create('数据协议不对,连接关闭');
- end;
- end;
- except
- on E: Exception do
- begin
- FBlockingTCPClient.Disconnect;
- FreeAndNil(FBlockingTCPClient);
- FWaitTimes := 10000;
- raise Exception.Create('处理TCP数据时出错:' + E.Message);
- end;
- end;
- end;
- //------------------------------------------------------------------------------
- procedure TMessageSender.ProcessSendSystemMessageResult(Data: Array of Byte);
- var
- nIndex: Integer;
- MessageSended: Boolean;
- begin
- nIndex := 0;
- //取 (3)反馈类型 1byte
- MessageSended := (Data[nIndex] = 1);
- //Inc(nIndex, 1);
-
- FBlockingTCPClient.Disconnect;
- FreeAndNil(FBlockingTCPClient);
- FWaitTimes := 10000;
- if not MessageSended then raise Exception.Create('消息发送失败');
- end;
- //------------------------------------------------------------------------------
- procedure TMessageSender.ProcessLoginResult(Data: Array of Byte);
- var
- nIndex: Integer;
- LoginResultType: TRealICQLoginResultType;
- begin
- nIndex := 0;
- //取 (3)反馈类型 1byte
- LoginResultType := TRealICQLoginResultType(Data[nIndex]);
- //Inc(nIndex, 1);
- if (LoginResultType = rtLoginOK) or (LoginResultType = rtCanUpdate) then
- begin
- FLogined := True;
- Send;
- end
- else
- begin
- FLogined := False;
-
- FBlockingTCPClient.Disconnect;
- FreeAndNil(FBlockingTCPClient);
- FWaitTimes := 10000;
- raise Exception.Create('登录失败,错误号:' + IntToStr(Integer(LoginResultType)));
- end;
- end;
- procedure TMessageSender.Connect;
- begin
- FLogined := False;
- if FBlockingTCPClient <> nil then FreeAndNil(FBlockingTCPClient);
-
- FBlockingTCPClient := TBlockingTCPClient.Create;
- FBlockingTCPClient.OnReceivedData := ReceivedData;
- FBlockingTCPClient.RemoteAddress := FServerAddress;
- FBlockingTCPClient.RemotePort := FServerPort;
- FBlockingTCPClient.Proxy.ProxyType := TProxyType(FProxyType);
- FBlockingTCPClient.Proxy.Address := FProxyAddress;
- FBlockingTCPClient.Proxy.Port := FProxyPort;
- FBlockingTCPClient.Proxy.Username := FProxyUsername;
- FBlockingTCPClient.Proxy.Password := FProxyPassword;
- FBlockingTCPClient.Proxy.Domain := FProxyDomain;
- FBlockingTCPClient.Connect;
- end;
- procedure TMessageSender.Login;
- var
- EncryptedPassword: String;
- nIndex,
- UsernameLength,
- PasswordLength,
- BufferLength: SmallInt;
- InternalVersion: Word;
- SendBuffer: Array of Byte;
- begin
- UsernameLength := Length(FUsername);
- EncryptedPassword := MD5Print(MD5String(FPassword));
- PasswordLength := Length(EncryptedPassword);
- BufferLength := 7 + UsernameLength + PasswordLength;
- SetLength(SendBuffer, BufferLength);
- nIndex := 0;
- //填充 (1)协议类型(0x01) 1byte
- SendBuffer[nIndex] := $01;
- Inc(nIndex, 1);
- //填充 (2)消息总长度 2byte
- CopyMemory(@SendBuffer[nIndex], @BufferLength, 2);
- Inc(nIndex, 2);
- //填充 (3)当前客户端的内部版本号 2byte
- InternalVersion := $01;
- CopyMemory(@SendBuffer[nIndex], @InternalVersion, 2);
- Inc(nIndex, 2);
- //填充 (4)用户名长度 1byte
- SendBuffer[nIndex] := Byte(UsernameLength);
- Inc(nIndex, 1);
- //填充 (5)用户名 动态长度,由(4)指定
- CopyMemory(@SendBuffer[nIndex], PChar(FUsername), UsernameLength);
- Inc(nIndex, UsernameLength);
- //填充 (6)密码长度 1byte
- SendBuffer[nIndex] := Byte(PasswordLength);
- Inc(nIndex, 1);
- //填充 (7)密码 动态长度,由(6)指定
- CopyMemory(@SendBuffer[nIndex], PChar(EncryptedPassword), PasswordLength);
- //Inc(nIndex, PasswordLength);
- FBlockingTCPClient.SendBuffer(SendBuffer[0], BufferLength);
- end;
- procedure TMessageSender.Send;
- var
- nIndex,
- BufferLength: SmallInt;
- UsersLength: Word;
- SendBuffer: Array of Byte;
- SystemMessageStr,
- DisplayMode,
- Rectangle: String;
- begin
- BufferLength := 4;
- UsersLength := Length(FUsers);
- if UsersLength > 0 then
- begin
- Inc(BufferLength, 2);
- Inc(BufferLength, UsersLength);
- end;
- if FAutoOpenWindow then
- DisplayMode := '0'
- else
- DisplayMode := '1';
- if FPosition = 2 then
- Rectangle := '{' + IntToStr(FLeft) + ',' + IntToStr(FTop) + ',' + IntToStr(FWidth) + ',' + IntToStr(FHeight) + '}'
- else
- Rectangle := '{' + IntToStr(FWidth) + ',' + IntToStr(FHeight) + '}';
-
- SystemMessageStr := IntToStr(FMessageType) + Chr(9) +
- DisplayMode + Chr(9) +
- FUrl + Chr(9) +
- IntToStr(FPosition) + Chr(9) +
- Rectangle + Chr(9) +
- EncodeString(FTitle) + Chr(9) +
- IntToStr(FAutoCloseTime) + Chr(9) +
- EncodeString(FContent);
- Inc(BufferLength, Length(SystemMessageStr));
- SetLength(SendBuffer, BufferLength);
- nIndex := 0;
- //填充 (1)协议类型(0x41) 1byte
- SendBuffer[nIndex] := $41;
- Inc(nIndex, 1);
- //填充 (2)消息总长度 2byte
- CopyMemory(@SendBuffer[nIndex], @BufferLength, 2);
- Inc(nIndex, 2);
- //填充 (3)用户类型 1byte
- if UsersLength > 0 then
- SendBuffer[nIndex] := $0
- else
- SendBuffer[nIndex] := $1;
- Inc(nIndex, 1);
- if UsersLength > 0 then
- begin
- //填充 (4)用户名长度 1byte
- CopyMemory(@SendBuffer[nIndex], @UsersLength, 2);
- Inc(nIndex, 2);
- //填充 (5)用户名 动态长度,由(4)指定
- CopyMemory(@SendBuffer[nIndex], PChar(FUsers), UsersLength);
- Inc(nIndex, UsersLength);
- end;
- //填充 (6)系统消息 动态长度
- CopyMemory(@SendBuffer[nIndex], PChar(SystemMessageStr), Length(SystemMessageStr));
- //Inc(nIndex, Length(SystemMessageStr));
-
- FBlockingTCPClient.SendBuffer(SendBuffer[0], BufferLength);
- end;
- procedure TMessageSender.SendSystemMessage(MessageType, AutoOpenWindow,
- Position, Left, Top, Width, Height, Title, Content, Url, AutoCloseTime,
- Users: OleVariant);
- begin
- FMessageType := MessageType;
- FAutoOpenWindow := AutoOpenWindow;
- FPosition := Position;
- FLeft := Left;
- FTop := Top;
- FWidth := Width;
- FHeight := Height;
- FTitle := Title;
- FContent := Content;
- FUrl := Url;
- FAutoCloseTime := AutoCloseTime;
- FUsers := Users;
- try
- Connect;
- Login;
- while FWaitTimes < 2000 do
- begin
- Application.ProcessMessages;
- Sleep(10);
- Inc(FWaitTimes);
- end;
- finally
- if FBlockingTCPClient <> nil then FreeAndNil(FBlockingTCPClient);
- end;
- end;
- initialization
- TAutoObjectFactory.Create(ComServer, TMessageSender, Class_MessageSender,
- ciMultiInstance, tmApartment);
- end.
|