复件 MessageSenderUnit.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. unit MessageSenderUnit;
  2. {$WARN SYMBOL_PLATFORM OFF}
  3. interface
  4. uses
  5. ComObj, ActiveX, AxCtrls, Classes, RealOAMessenger_TLB, StdVcl, SysUtils,
  6. BlockingTCPClient, RealICQProxy, MD5, EncdDecd;
  7. type
  8. TMessageSender = class(TAutoObject, IConnectionPointContainer, IMessageSender)
  9. private
  10. { Private declarations }
  11. FConnectionPoints: TConnectionPoints;
  12. FConnectionPoint: TConnectionPoint;
  13. FEvents: IMessageSenderEvents;
  14. { note: FEvents maintains a *single* event sink. For access to more
  15. than one event sink, use FConnectionPoint.SinkList, and iterate
  16. through the list of sinks. }
  17. FBlockingTCPClient: TBlockingTCPClient;
  18. FServerAddress: String;
  19. FServerPort: SYSINT;
  20. FProxyType: Shortint;
  21. FProxyAddress: String;
  22. FProxyPort: SYSINT;
  23. FProxyPassword: String;
  24. FProxyUsername: String;
  25. FProxyDomain: String;
  26. FUsername: String;
  27. FPassword: String;
  28. FLogined: Boolean;
  29. FMessageType: Integer;
  30. FAutoOpenWindow: Boolean;
  31. FPosition,
  32. FLeft,
  33. FTop,
  34. FWidth,
  35. FHeight: Integer;
  36. FTitle,
  37. FContent,
  38. FUrl: String;
  39. FAutoCloseTime: Integer;
  40. FUsers: String;
  41. FWaitTimes: Integer;
  42. procedure ReceivedData(Sender: TObject; RecvThread:
  43. TBlockingTCPClientRecvThread; RecvBytes: Integer);
  44. procedure Connect;
  45. procedure Login;
  46. procedure Send;
  47. procedure ProcessLoginResult(Data: Array of Byte);
  48. procedure ProcessSendSystemMessageResult(Data: Array of Byte);
  49. public
  50. procedure Initialize; override;
  51. protected
  52. { Protected declarations }
  53. property ConnectionPoints: TConnectionPoints read FConnectionPoints
  54. implements IConnectionPointContainer;
  55. procedure EventSinkChanged(const EventSink: IUnknown); override;
  56. function Get_ServerAddress: OleVariant; safecall;
  57. procedure Set_ServerAddress(Value: OleVariant); safecall;
  58. function Get_ServerPort: OleVariant; safecall;
  59. procedure Set_ServerPort(Value: OleVariant); safecall;
  60. function Get_ProxyType: OleVariant; safecall;
  61. procedure Set_ProxyType(Value: OleVariant); safecall;
  62. function Get_ProxyAddress: OleVariant; safecall;
  63. procedure Set_ProxyAddress(Value: OleVariant); safecall;
  64. function Get_ProxyPort: OleVariant; safecall;
  65. procedure Set_ProxyPort(Value: OleVariant); safecall;
  66. function Get_ProxyPassword: OleVariant; safecall;
  67. function Get_ProxyUsername: OleVariant; safecall;
  68. procedure Set_ProxyPassword(Value: OleVariant); safecall;
  69. procedure Set_ProxyUsername(Value: OleVariant); safecall;
  70. function Get_ProxyDomain: OleVariant; safecall;
  71. procedure Set_ProxyDomain(Value: OleVariant); safecall;
  72. function Get_Username: OleVariant; safecall;
  73. procedure Set_Username(Value: OleVariant); safecall;
  74. function Get_Password: OleVariant; safecall;
  75. procedure Set_Password(Value: OleVariant); safecall;
  76. procedure SendSystemMessage(MessageType, AutoOpenWindow, Position, Left,
  77. Top, Width, Height, Title, Content, Url, AutoCloseTime,
  78. Users: OleVariant); safecall;
  79. end;
  80. TRealICQLoginResultType = ( rtLoginOK = 0,
  81. rtCanUpdate = 1,
  82. rtMustUpdate = 2,
  83. rtVersionError = 3,
  84. rtAuthorizationError = 4,
  85. rtOther = 5);
  86. implementation
  87. uses ComServ, Windows, Forms;
  88. procedure TMessageSender.EventSinkChanged(const EventSink: IUnknown);
  89. begin
  90. FEvents := EventSink as IMessageSenderEvents;
  91. end;
  92. procedure TMessageSender.Initialize;
  93. begin
  94. inherited Initialize;
  95. FConnectionPoints := TConnectionPoints.Create(Self);
  96. if AutoFactory.EventTypeInfo <> nil then
  97. FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
  98. AutoFactory.EventIID, ckSingle, EventConnect)
  99. else FConnectionPoint := nil;
  100. FServerAddress := '';
  101. FServerPort := 0;
  102. FProxyType := 0;
  103. FProxyAddress := '';
  104. FProxyPort := 0;
  105. FProxyPassword := '';
  106. FProxyUsername := '';
  107. FProxyDomain := '';
  108. FUsername := '';
  109. FPassword := '';
  110. FLogined := False;
  111. FWaitTimes := 0;
  112. end;
  113. function TMessageSender.Get_ServerAddress: OleVariant;
  114. begin
  115. Result := FServerAddress;
  116. end;
  117. procedure TMessageSender.Set_ServerAddress(Value: OleVariant);
  118. begin
  119. FServerAddress := Value;
  120. end;
  121. function TMessageSender.Get_ServerPort: OleVariant;
  122. begin
  123. Result := FServerPort;
  124. end;
  125. procedure TMessageSender.Set_ServerPort(Value: OleVariant);
  126. begin
  127. FServerPort := Value;
  128. end;
  129. function TMessageSender.Get_ProxyType: OleVariant;
  130. begin
  131. Result := FProxyType;
  132. end;
  133. procedure TMessageSender.Set_ProxyType(Value: OleVariant);
  134. begin
  135. FProxyType := Value;
  136. end;
  137. function TMessageSender.Get_ProxyAddress: OleVariant;
  138. begin
  139. Result := FProxyAddress;
  140. end;
  141. procedure TMessageSender.Set_ProxyAddress(Value: OleVariant);
  142. begin
  143. FProxyAddress := Value;
  144. end;
  145. function TMessageSender.Get_ProxyPort: OleVariant;
  146. begin
  147. Result := FProxyPort;
  148. end;
  149. procedure TMessageSender.Set_ProxyPort(Value: OleVariant);
  150. begin
  151. FProxyPort := Value;
  152. end;
  153. function TMessageSender.Get_ProxyPassword: OleVariant;
  154. begin
  155. Result := FProxyPassword;
  156. end;
  157. function TMessageSender.Get_ProxyUsername: OleVariant;
  158. begin
  159. Result := FProxyUsername;
  160. end;
  161. procedure TMessageSender.Set_ProxyPassword(Value: OleVariant);
  162. begin
  163. FProxyPassword := Value;
  164. end;
  165. procedure TMessageSender.Set_ProxyUsername(Value: OleVariant);
  166. begin
  167. FProxyUsername := Value;
  168. end;
  169. function TMessageSender.Get_ProxyDomain: OleVariant;
  170. begin
  171. Result := FProxyDomain;
  172. end;
  173. procedure TMessageSender.Set_ProxyDomain(Value: OleVariant);
  174. begin
  175. FProxyDomain := Value;
  176. end;
  177. function TMessageSender.Get_Username: OleVariant;
  178. begin
  179. Result := FUsername;
  180. end;
  181. procedure TMessageSender.Set_Username(Value: OleVariant);
  182. begin
  183. FUsername := Value;
  184. end;
  185. function TMessageSender.Get_Password: OleVariant;
  186. begin
  187. Result := FPassword;
  188. end;
  189. procedure TMessageSender.Set_Password(Value: OleVariant);
  190. begin
  191. FPassword := Value;
  192. end;
  193. procedure TMessageSender.ReceivedData(Sender: TObject; RecvThread:
  194. TBlockingTCPClientRecvThread; RecvBytes: Integer);
  195. var
  196. TCPClientRecvThread: TBlockingTCPClientRecvThread;
  197. ProtocolType: Byte;
  198. ProtocolLengthBytes: Array[0..1] of Byte;
  199. ProtocolDataBytes: Array of Byte;
  200. ProtocolLength: SmallInt;
  201. begin
  202. try
  203. TCPClientRecvThread := RecvThread;
  204. while TCPClientRecvThread.NotProcessedBufferLength >= 3 do
  205. begin
  206. TCPClientRecvThread.CopyRecvBufferTo(ProtocolType, 0, 1);
  207. TCPClientRecvThread.CopyRecvBufferTo(ProtocolLengthBytes[0], 1, 2);
  208. CopyMemory(@ProtocolLength, @ProtocolLengthBytes[0], 2);
  209. if TCPClientRecvThread.NotProcessedBufferLength < ProtocolLength then Break;
  210. SetLength(ProtocolDataBytes, ProtocolLength - 3);
  211. TCPClientRecvThread.CutRecvBufferTo(ProtocolDataBytes[0], 3, ProtocolLength - 3);
  212. case ProtocolType of
  213. $02: ProcessLoginResult(ProtocolDataBytes);
  214. $42: begin
  215. ProcessSendSystemMessageResult(ProtocolDataBytes);
  216. Exit;
  217. end;
  218. else
  219. FBlockingTCPClient.Disconnect;
  220. FreeAndNil(FBlockingTCPClient);
  221. FWaitTimes := 10000;
  222. raise Exception.Create('数据协议不对,连接关闭');
  223. end;
  224. end;
  225. except
  226. on E: Exception do
  227. begin
  228. FBlockingTCPClient.Disconnect;
  229. FreeAndNil(FBlockingTCPClient);
  230. FWaitTimes := 10000;
  231. raise Exception.Create('处理TCP数据时出错:' + E.Message);
  232. end;
  233. end;
  234. end;
  235. //------------------------------------------------------------------------------
  236. procedure TMessageSender.ProcessSendSystemMessageResult(Data: Array of Byte);
  237. var
  238. nIndex: Integer;
  239. MessageSended: Boolean;
  240. begin
  241. nIndex := 0;
  242. //取 (3)反馈类型 1byte
  243. MessageSended := (Data[nIndex] = 1);
  244. //Inc(nIndex, 1);
  245. FBlockingTCPClient.Disconnect;
  246. FreeAndNil(FBlockingTCPClient);
  247. FWaitTimes := 10000;
  248. if not MessageSended then raise Exception.Create('消息发送失败');
  249. end;
  250. //------------------------------------------------------------------------------
  251. procedure TMessageSender.ProcessLoginResult(Data: Array of Byte);
  252. var
  253. nIndex: Integer;
  254. LoginResultType: TRealICQLoginResultType;
  255. begin
  256. nIndex := 0;
  257. //取 (3)反馈类型 1byte
  258. LoginResultType := TRealICQLoginResultType(Data[nIndex]);
  259. //Inc(nIndex, 1);
  260. if (LoginResultType = rtLoginOK) or (LoginResultType = rtCanUpdate) then
  261. begin
  262. FLogined := True;
  263. Send;
  264. end
  265. else
  266. begin
  267. FLogined := False;
  268. FBlockingTCPClient.Disconnect;
  269. FreeAndNil(FBlockingTCPClient);
  270. FWaitTimes := 10000;
  271. raise Exception.Create('登录失败,错误号:' + IntToStr(Integer(LoginResultType)));
  272. end;
  273. end;
  274. procedure TMessageSender.Connect;
  275. begin
  276. FLogined := False;
  277. if FBlockingTCPClient <> nil then FreeAndNil(FBlockingTCPClient);
  278. FBlockingTCPClient := TBlockingTCPClient.Create;
  279. FBlockingTCPClient.OnReceivedData := ReceivedData;
  280. FBlockingTCPClient.RemoteAddress := FServerAddress;
  281. FBlockingTCPClient.RemotePort := FServerPort;
  282. FBlockingTCPClient.Proxy.ProxyType := TProxyType(FProxyType);
  283. FBlockingTCPClient.Proxy.Address := FProxyAddress;
  284. FBlockingTCPClient.Proxy.Port := FProxyPort;
  285. FBlockingTCPClient.Proxy.Username := FProxyUsername;
  286. FBlockingTCPClient.Proxy.Password := FProxyPassword;
  287. FBlockingTCPClient.Proxy.Domain := FProxyDomain;
  288. FBlockingTCPClient.Connect;
  289. end;
  290. procedure TMessageSender.Login;
  291. var
  292. EncryptedPassword: String;
  293. nIndex,
  294. UsernameLength,
  295. PasswordLength,
  296. BufferLength: SmallInt;
  297. InternalVersion: Word;
  298. SendBuffer: Array of Byte;
  299. begin
  300. UsernameLength := Length(FUsername);
  301. EncryptedPassword := MD5Print(MD5String(FPassword));
  302. PasswordLength := Length(EncryptedPassword);
  303. BufferLength := 7 + UsernameLength + PasswordLength;
  304. SetLength(SendBuffer, BufferLength);
  305. nIndex := 0;
  306. //填充 (1)协议类型(0x01) 1byte
  307. SendBuffer[nIndex] := $01;
  308. Inc(nIndex, 1);
  309. //填充 (2)消息总长度 2byte
  310. CopyMemory(@SendBuffer[nIndex], @BufferLength, 2);
  311. Inc(nIndex, 2);
  312. //填充 (3)当前客户端的内部版本号 2byte
  313. InternalVersion := $01;
  314. CopyMemory(@SendBuffer[nIndex], @InternalVersion, 2);
  315. Inc(nIndex, 2);
  316. //填充 (4)用户名长度 1byte
  317. SendBuffer[nIndex] := Byte(UsernameLength);
  318. Inc(nIndex, 1);
  319. //填充 (5)用户名 动态长度,由(4)指定
  320. CopyMemory(@SendBuffer[nIndex], PChar(FUsername), UsernameLength);
  321. Inc(nIndex, UsernameLength);
  322. //填充 (6)密码长度 1byte
  323. SendBuffer[nIndex] := Byte(PasswordLength);
  324. Inc(nIndex, 1);
  325. //填充 (7)密码 动态长度,由(6)指定
  326. CopyMemory(@SendBuffer[nIndex], PChar(EncryptedPassword), PasswordLength);
  327. //Inc(nIndex, PasswordLength);
  328. FBlockingTCPClient.SendBuffer(SendBuffer[0], BufferLength);
  329. end;
  330. procedure TMessageSender.Send;
  331. var
  332. nIndex,
  333. BufferLength: SmallInt;
  334. UsersLength: Word;
  335. SendBuffer: Array of Byte;
  336. SystemMessageStr,
  337. DisplayMode,
  338. Rectangle: String;
  339. begin
  340. BufferLength := 4;
  341. UsersLength := Length(FUsers);
  342. if UsersLength > 0 then
  343. begin
  344. Inc(BufferLength, 2);
  345. Inc(BufferLength, UsersLength);
  346. end;
  347. if FAutoOpenWindow then
  348. DisplayMode := '0'
  349. else
  350. DisplayMode := '1';
  351. if FPosition = 2 then
  352. Rectangle := '{' + IntToStr(FLeft) + ',' + IntToStr(FTop) + ',' + IntToStr(FWidth) + ',' + IntToStr(FHeight) + '}'
  353. else
  354. Rectangle := '{' + IntToStr(FWidth) + ',' + IntToStr(FHeight) + '}';
  355. SystemMessageStr := IntToStr(FMessageType) + Chr(9) +
  356. DisplayMode + Chr(9) +
  357. FUrl + Chr(9) +
  358. IntToStr(FPosition) + Chr(9) +
  359. Rectangle + Chr(9) +
  360. EncodeString(FTitle) + Chr(9) +
  361. IntToStr(FAutoCloseTime) + Chr(9) +
  362. EncodeString(FContent);
  363. Inc(BufferLength, Length(SystemMessageStr));
  364. SetLength(SendBuffer, BufferLength);
  365. nIndex := 0;
  366. //填充 (1)协议类型(0x41) 1byte
  367. SendBuffer[nIndex] := $41;
  368. Inc(nIndex, 1);
  369. //填充 (2)消息总长度 2byte
  370. CopyMemory(@SendBuffer[nIndex], @BufferLength, 2);
  371. Inc(nIndex, 2);
  372. //填充 (3)用户类型 1byte
  373. if UsersLength > 0 then
  374. SendBuffer[nIndex] := $0
  375. else
  376. SendBuffer[nIndex] := $1;
  377. Inc(nIndex, 1);
  378. if UsersLength > 0 then
  379. begin
  380. //填充 (4)用户名长度 1byte
  381. CopyMemory(@SendBuffer[nIndex], @UsersLength, 2);
  382. Inc(nIndex, 2);
  383. //填充 (5)用户名 动态长度,由(4)指定
  384. CopyMemory(@SendBuffer[nIndex], PChar(FUsers), UsersLength);
  385. Inc(nIndex, UsersLength);
  386. end;
  387. //填充 (6)系统消息 动态长度
  388. CopyMemory(@SendBuffer[nIndex], PChar(SystemMessageStr), Length(SystemMessageStr));
  389. //Inc(nIndex, Length(SystemMessageStr));
  390. FBlockingTCPClient.SendBuffer(SendBuffer[0], BufferLength);
  391. end;
  392. procedure TMessageSender.SendSystemMessage(MessageType, AutoOpenWindow,
  393. Position, Left, Top, Width, Height, Title, Content, Url, AutoCloseTime,
  394. Users: OleVariant);
  395. begin
  396. FMessageType := MessageType;
  397. FAutoOpenWindow := AutoOpenWindow;
  398. FPosition := Position;
  399. FLeft := Left;
  400. FTop := Top;
  401. FWidth := Width;
  402. FHeight := Height;
  403. FTitle := Title;
  404. FContent := Content;
  405. FUrl := Url;
  406. FAutoCloseTime := AutoCloseTime;
  407. FUsers := Users;
  408. try
  409. Connect;
  410. Login;
  411. while FWaitTimes < 2000 do
  412. begin
  413. Application.ProcessMessages;
  414. Sleep(10);
  415. Inc(FWaitTimes);
  416. end;
  417. finally
  418. if FBlockingTCPClient <> nil then FreeAndNil(FBlockingTCPClient);
  419. end;
  420. end;
  421. initialization
  422. TAutoObjectFactory.Create(ComServer, TMessageSender, Class_MessageSender,
  423. ciMultiInstance, tmApartment);
  424. end.