hxUpdate.pas
上传用户:youjie821
上传日期:2013-01-27
资源大小:459k
文件大小:23k
源码类别:

PlugIns编程

开发平台:

Delphi

  1. unit hxUpdate;
  2. interface
  3. uses
  4.   Windows, Classes, Forms, ScktComp, SysUtils, WinSock, hxFileRes, Contnrs,
  5.   SyncObjs;
  6. const
  7.   { 数据包长度 }
  8.   PACKET_SIZE   = 1024;
  9.   { 定义消息 }
  10.   FILE_LIST     = $00000001;
  11.   FILE_INFO     = $00000002;
  12.   FILE_DOWNLOAD = $00000003;
  13.   { 网络超时 }
  14.   G_TIMEOUT     = 60000;
  15.   { 代理信息 }
  16.   SOCKS_VER5 = $05;
  17.   CMD_CONNECT = $01;
  18.   RSV_DEFAULT = $00;
  19.   ATYP_DN = $03;
  20.   REP_SUCCESS = $00;
  21.   ATYP_IPV4 = $01;
  22. type
  23.   TAuthenType = (atNone, atUserPass);
  24.   TDownloadStatus = (dsBegin, dsFileBegin, dsFileData, dsFileEnd, dsEnd, dsError);
  25.   TDownloadCallback = procedure(Sender: TObject; DownloadStatus: TDownloadStatus;
  26.     const WorkCount: Integer) of object;
  27.   //下载进度
  28.   TDownloadProgress = procedure(DownloadStatus: TDownloadStatus; FileName: string;
  29.     WorkCount: Integer);
  30.   { 代理服务器属性 }
  31.   TProxyInfo = record
  32.     Enabled: Boolean;
  33.     IP: string;
  34.     Port: Integer;
  35.     Username: string;
  36.     Password: string;
  37.   end;
  38.   PSocksInfo = ^TSocksInfo;
  39.   TSocksInfo = record
  40.     ProxyIP: PChar;     //代理服务器IP
  41.     ProxyPort: Integer; //代理服务器端口
  42.     ProxyUser: PChar;   //代理服务器用户名
  43.     ProxyPass: PChar;   //代理服务器密码
  44.   end;
  45.   { 项目 }
  46.   TProjectItem = class(TCollectionItem)
  47.   private
  48.     FDescription: string;
  49.     FProjectName: string;
  50.     FResTree: TResTree;
  51.     FRootDir: string;
  52.     function GetResTreeFileName: string;
  53.   public
  54.     constructor Create(Collection: TCollection); override;
  55.     destructor Destroy; override;
  56.     procedure RemoveResTree;
  57.     procedure SaveResTree;
  58.     procedure LoadResTree;
  59.     property ProjectName: string read FProjectName write FProjectName;
  60.     property Description: string read FDescription write FDescription;
  61.     property RootDir: string read FRootDir write FRootDir;
  62.     property ResTree: TResTree read FResTree;
  63.   end;
  64.   { 项目管理器 }
  65.   TProjectCollection = class(TCollection)
  66.   private
  67.     FFileName: string;
  68.     FOwner: TPersistent;
  69.     procedure SaveToFile;
  70.     procedure LoadFromFile;
  71.     function GetItem(Index: Integer): TProjectItem;
  72.   public
  73.     constructor Create(AOwner: TPersistent; FileName: string);
  74.     destructor Destroy; override;
  75.     function Add(ProjectName, Descripton, RootDir: string): TProjectItem;
  76.     procedure Delete(Index: Integer);
  77.     procedure Clear;
  78.     function IndexOf(const ProjectName: string): Integer;
  79.     property Items[Index: Integer]: TProjectItem read GetItem; default;
  80.   end;
  81.   TMyServerClientThread = class(TServerClientThread)
  82.   private
  83.     procedure SendFileList(ProjectName: string);
  84.     procedure SendFile(ProjectName, FileName: string);
  85.   protected
  86.     procedure ClientExecute; override;
  87.   public
  88.     constructor Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket);
  89.     destructor Destroy; override;
  90.   end;
  91.   ThxUpdateServer = class(TObject)
  92.   private
  93.     FServerSocket: TServerSocket;
  94.     procedure FServerSocketGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
  95.       var SocketThread: TServerClientThread);
  96.     procedure FServerSocketThreadStart(Sender: TObject; Thread: TServerClientThread);
  97.     procedure FServerSocketThreadEnd(Sender: TObject; Thread: TServerClientThread);
  98.     procedure FServerSocketListen(Sender: TObject; Socket: TCustomWinSocket);
  99.     function GetActive: Boolean;
  100.   public
  101.     constructor Create(APort: Integer);
  102.     destructor Destroy; override;
  103.     procedure StartService;
  104.     procedure StopServerice;
  105.     property Active: Boolean read GetActive;
  106.   end;
  107.   { 下载文件列表,共用一个连接,下载完毕后连接不断开}
  108.   TDownloadFileListThread = class(TThread)
  109.   private
  110.     FClientSocket: TClientSocket;
  111.     FResTree: TResTree;
  112.     FProjectName: string;
  113.     FDownloadCallback: TDownloadCallback;
  114.     FDownloadStatus: TDownloadStatus;
  115.     FWorkCount: Integer;
  116.     procedure DoDownloadCallback;
  117.     procedure SyncDownloadCallback(DownloadStatus: TDownloadStatus; WorkCount: Integer);
  118.   protected
  119.     procedure Execute; override;
  120.   public
  121.     constructor Create(CreateSuspended: Boolean; ClientSocket: TClientSocket;
  122.       ProjectName: string; ResTree: TResTree; DownloadCallback: TDownloadCallback);
  123.     property ResTree: TResTree read FResTree;
  124.   end;
  125.   ThxUpdateClient = class;
  126.   { 下载多个文件,共用一个连接,下载完毕后连接不断开 }
  127.   TDownloadFilesThread = class(TThread)
  128.   private
  129.     FClientSocket: TClientSocket;
  130.     FFileNames: TStrings;
  131.     FDownloadCallback: TDownloadCallback;
  132.     FUpdateClient: ThxUpdateClient;
  133.     FProjectName: string;
  134.     FDownloadFileName: string;
  135.     FDownloadStatus: TDownloadStatus;
  136.     FWorkCount: Integer;
  137.     procedure DoDownloadCallback;
  138.     procedure SyncDownloadCallback(DownloadStatus: TDownloadStatus; WorkCount: Integer);
  139.     procedure DownloadAFile(AFileName: string);
  140.   protected
  141.     procedure Execute; override;
  142.   public
  143.     constructor Create(UpdateClient: ThxUpdateClient; CreateSuspended: Boolean; ClientSocket: TClientSocket;
  144.       ProjectName: string; FileNames: TStrings; DownloadCallback: TDownloadCallback);
  145.     destructor Destroy; override;
  146.     property DownloadFileName: string read FDownloadFileName;
  147.   end;
  148.   ThxUpdateClient = class(TObject)
  149.   private
  150.     FClientSocket: TClientSocket;
  151.     FResTree: TResTree;
  152.     FProjectName: string;
  153.     FProxyInfo: TProxyInfo;
  154.     function GetActive: Boolean;
  155.     function Handclasp(Socket: TSocket; AuthenType: TAuthenType): Boolean;
  156.     function ConnectByProxy(Socket: TSocket; RemoteIP: string; RemotePort: Integer): Boolean;
  157.   public
  158.     constructor Create(ProjectName: string);
  159.     destructor Destroy; override;
  160.     procedure Open(ServerIP: string; Port: Integer);
  161.     procedure Close;
  162.     procedure DownloadFileList(DownloadCallback: TDownloadCallback);
  163.     procedure DownloadFiles(FileNames: TStrings; DownloadCallback: TDownloadCallback);
  164.     property Active: Boolean read GetActive;
  165.     property ProxyInfo: TProxyInfo read FProxyInfo write FProxyInfo;
  166.   end;
  167.   function GetProjectCollection: TProjectCollection;
  168. implementation
  169. uses
  170.   hxSysUtils, TypInfo;
  171. var
  172.   G_ProjectCollection: TProjectCollection = nil;
  173. function GetProjectCollection: TProjectCollection;
  174. begin
  175.   if G_ProjectCollection = nil then
  176.     G_ProjectCollection:= TProjectCollection.Create(nil, ExtractFilePath(ParamStr(0)) + 'myprjs.dat');
  177.   Result:= G_ProjectCollection;
  178. end;
  179. { TMyServerClientThread }
  180. procedure TMyServerClientThread.ClientExecute;
  181. var
  182.   Stream: TWinSocketStream;
  183.   CMD: Cardinal;
  184.   ProjectName, FileName: string;
  185. begin
  186.   while (not Terminated) and ClientSocket.Connected do
  187.   begin
  188.     try
  189.       Stream := TWinSocketStream.Create(ClientSocket, G_TIMEOUT);
  190.       try
  191.         if Stream.WaitForData(G_TIMEOUT) then
  192.         begin
  193.           if ClientSocket.ReceiveLength = 0 then
  194.           begin
  195.             ClientSocket.Close;
  196.             Break;
  197.           end;
  198.           try
  199.             CMD:= StreamReadInteger(Stream);
  200.             ProjectName:= StreamReadString(Stream);
  201.             if GetProjectCollection.IndexOf(ProjectName) = -1 then
  202.               ClientSocket.Close;
  203.             case CMD of
  204.               // 下载文件列表
  205.               FILE_LIST:
  206.               begin
  207.                 SendFileList(ProjectName);
  208.               end;
  209.               // 下载文件
  210.               FILE_DOWNLOAD:
  211.               begin
  212.                 FileName:= StreamReadString(Stream);
  213.                 SendFile(ProjectName, FileName);
  214.               end;
  215.             end;
  216.           except
  217.             ClientSocket.Close;
  218.           end;
  219.         end
  220.         else
  221.           ClientSocket.Close;
  222.       finally
  223.         Stream.Free;
  224.       end;
  225.     except
  226.       HandleException;
  227.     end;
  228.   end;
  229.   Terminate;
  230. end;
  231. constructor TMyServerClientThread.Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket);
  232. begin
  233.   inherited Create(CreateSuspended, ASocket);
  234.   FreeOnTerminate:= True;
  235. end;
  236. destructor TMyServerClientThread.Destroy;
  237. begin
  238.   inherited Destroy;
  239. end;
  240. procedure TMyServerClientThread.SendFile(ProjectName, FileName: string);
  241. var
  242.   fs: TFileStream;
  243.   wss: TWinSocketStream;
  244.   Buf: array[0..PACKET_SIZE - 1] of char;
  245.   ReadCount: Integer;
  246.   Index: Integer;
  247.   RootDir: string;
  248. begin
  249.   wss:= TWinSocketStream.Create(ClientSocket, G_TIMEOUT);
  250.   try
  251.     Index:= GetProjectCollection.IndexOf(ProjectName);
  252.     RootDir:= FormatDirectoryName(GetProjectCollection.Items[Index].RootDir);
  253.     fs:= TFileStream.Create(RootDir + FileName, fmOpenRead);
  254.     try
  255.       StreamWriteInteger(wss, FILE_DOWNLOAD);
  256.       StreamWriteString(wss, FileName);
  257.       StreamWriteInteger(wss, fs.Size);
  258.       while fs.Position < fs.Size do
  259.       begin
  260.         ReadCount:= fs.Read(Buf, PACKET_SIZE);
  261.         wss.WriteBuffer(Buf, ReadCount);
  262.       end;
  263.     finally
  264.       fs.Free;
  265.     end;
  266.   finally
  267.     wss.Free;
  268.   end;
  269. end;
  270. procedure TMyServerClientThread.SendFileList(ProjectName: string);
  271. var
  272.   Index: Integer;
  273.   wss: TWinSocketStream;
  274. begin
  275.   Index:= GetProjectCollection.IndexOf(ProjectName);
  276.   wss:= TWinSocketStream.Create(ClientSocket, G_TIMEOUT);
  277.   try
  278.     StreamWriteInteger(wss, FILE_LIST);
  279.     // 需要时才加载,可以节约资源
  280.     with GetProjectCollection.Items[Index] do
  281.     begin
  282.       LoadResTree;
  283.       ResTree.SaveToStream(wss);
  284.       //ResTree.Clear;
  285.     end;
  286.   finally
  287.     wss.Free;
  288.   end;
  289. end;
  290. { ThxUpdateServer }
  291. constructor ThxUpdateServer.Create(APort: Integer);
  292. begin
  293.   FServerSocket:= TServerSocket.Create(nil);
  294.   FServerSocket.ServerType:= stThreadBlocking;
  295.   FServerSocket.ThreadCacheSize:= 0;
  296.   FServerSocket.Port:= APort;
  297.   FServerSocket.OnGetThread:= FServerSocketGetThread;
  298.   FServerSocket.OnThreadStart:= FServerSocketThreadStart;
  299.   FServerSocket.OnThreadEnd:= FServerSocketThreadEnd;
  300.   FServerSocket.OnListen:= FServerSocketListen;
  301. end;
  302. destructor ThxUpdateServer.Destroy;
  303. begin
  304.   FServerSocket.Free;
  305.   inherited Destroy;
  306. end;
  307. procedure ThxUpdateServer.FServerSocketGetThread(Sender: TObject;
  308.   ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
  309. begin
  310.   Assert(ClientSocket.Connected);
  311.   SocketThread:= TMyServerClientThread.Create(False, ClientSocket);
  312. end;
  313. procedure ThxUpdateServer.FServerSocketListen(Sender: TObject; Socket: TCustomWinSocket);
  314. begin
  315. end;
  316. procedure ThxUpdateServer.FServerSocketThreadEnd(Sender: TObject; Thread: TServerClientThread);
  317. begin
  318. end;
  319. procedure ThxUpdateServer.FServerSocketThreadStart(Sender: TObject; Thread: TServerClientThread);
  320. begin
  321. end;
  322. function ThxUpdateServer.GetActive: Boolean;
  323. begin
  324.   Result:= FServerSocket.Active;
  325. end;
  326. procedure ThxUpdateServer.StartService;
  327. begin
  328.   FServerSocket.Open;
  329. end;
  330. procedure ThxUpdateServer.StopServerice;
  331. begin
  332.   FServerSocket.Close;
  333. end;
  334. { TDownloadFileListThread }
  335. constructor TDownloadFileListThread.Create(CreateSuspended: Boolean; ClientSocket: TClientSocket;
  336.   ProjectName: string; ResTree: TResTree; DownloadCallback: TDownloadCallback);
  337. begin
  338.   inherited Create(CreateSuspended);
  339.   FreeOnTerminate:= True;
  340.   FClientSocket:= ClientSocket;
  341.   FProjectName:= ProjectName;
  342.   FResTree:= ResTree;
  343.   FDownloadCallback:= DownloadCallback;
  344. end;
  345. procedure TDownloadFileListThread.DoDownloadCallback;
  346. begin
  347.   if Assigned(FDownloadCallback) then
  348.     FDownloadCallback(Self, FDownloadStatus, FWorkCount);
  349. end;
  350. procedure TDownloadFileListThread.Execute;
  351. var
  352.   wss: TWinSocketStream;
  353.   CMD: Cardinal;
  354. begin
  355.   // 下载文件列表
  356.   if (not Terminated) and (FClientSocket.Socket.Connected) then
  357.   begin
  358.     wss:= TWinSocketStream.Create(FClientSocket.Socket, G_TIMEOUT);
  359.     try
  360.       // 请求下载文件列表
  361.       StreamWriteInteger(wss, FILE_LIST);
  362.       StreamWriteString(wss, FProjectName);
  363.       SyncDownloadCallback(dsBegin, 0);
  364.       // 等待下载文件列表
  365.       if wss.WaitForData(G_TIMEOUT) then
  366.       begin
  367.         CMD:= StreamReadInteger(wss);
  368.         Assert(CMD = FILE_LIST);
  369.         FResTree.LoadFromStream(wss);
  370.         SyncDownloadCallback(dsEnd, wss.Size);
  371.         Terminate;
  372.       end
  373.       else
  374.         FClientSocket.Close;
  375.     finally
  376.       wss.Free;
  377.     end;
  378.   end;
  379. end;
  380. { TDownloadFiles }
  381. constructor TDownloadFilesThread.Create(UpdateClient: ThxUpdateClient;  CreateSuspended: Boolean; ClientSocket: TClientSocket;
  382.   ProjectName: string; FileNames: TStrings; DownloadCallback: TDownloadCallback);
  383. begin
  384.   inherited Create(CreateSuspended);
  385.   FUpdateClient:= UpdateClient;
  386.   FreeOnTerminate:= True;
  387.   FClientSocket:= ClientSocket;
  388.   FProjectName:= ProjectName;
  389.   FDownloadCallback:= DownloadCallback;
  390.   FFileNames:= TStringList.Create;
  391.   FFileNames.Assign(FileNames);
  392.   FDownloadFileName:= '';
  393.   Assert(FClientSocket.Socket.Connected = True);
  394. end;
  395. destructor TDownloadFilesThread.Destroy;
  396. begin
  397.   FFileNames.Free;
  398.   inherited Destroy;
  399. end;
  400. procedure TDownloadFilesThread.DownloadAFile(AFileName: string);
  401. var
  402.   CMD: Cardinal;
  403.   wss: TWinSocketStream;
  404.   fs: TFileStream;
  405.   FileName: string;
  406.   FileSize: Integer;
  407.   Buf: array[0..PACKET_SIZE - 1] of char;
  408.   WriteCount: Integer;
  409.   szDir: string;
  410. begin
  411.   Assert(FClientSocket.Socket.Connected = True);
  412.   wss:= TWinSocketStream.Create(FClientSocket.Socket, G_TIMEOUT);
  413.   try
  414.     // 请求下载文件列表
  415.     StreamWriteInteger(wss, FILE_DOWNLOAD);
  416.     StreamWriteString(wss, FProjectName);
  417.     StreamWriteString(wss, AFileName);
  418.     // 等待下载文件列表
  419.     if wss.WaitForData(G_TIMEOUT) then
  420.     begin
  421.       CMD:= StreamReadInteger(wss);
  422.       Assert(CMD = FILE_DOWNLOAD);
  423.       FileName:= StreamReadString(wss);
  424.       FileSize:= StreamReadInteger(wss);
  425.       FDownloadFileName:= FileName;
  426.       //开始下载
  427.       SyncDownloadCallback(dsFileBegin, FileSize);
  428.       //下载指定文件
  429.       FileName:= ExtractFilePath(Application.ExeName) + FDownloadFileName;
  430.       szDir:= ExtractFilePath(FileName);
  431.       if not ForceDirectories(szDir) then
  432.         raise Exception.Create('创建目录失败!');
  433.       fs:= TFileStream.Create(FileName, fmCreate);
  434.       try
  435.         while fs.Size < FileSize do
  436.         begin
  437.           FillChar(Buf, PACKET_SIZE, #0);
  438.           WriteCount:= wss.Read(Buf, PACKET_SIZE);
  439.           fs.WriteBuffer(Buf, WriteCount);
  440.           //下载中....
  441.           SyncDownloadCallback(dsFileData, WriteCount);
  442.         end;
  443.         //下载完毕
  444.         SyncDownloadCallback(dsFileEnd, fs.Size);
  445.       finally
  446.         fs.Free;
  447.       end;
  448.     end
  449.     else
  450.       FClientSocket.Close;
  451.   finally
  452.     wss.Free;
  453.   end;
  454. end;
  455. procedure TDownloadFilesThread.DoDownloadCallback;
  456. begin
  457.   if Assigned(FDownloadCallback) then
  458.     FDownloadCallback(Self, FDownloadStatus, FWorkCount);
  459. end;
  460. procedure TDownloadFilesThread.Execute;
  461. var
  462.   I: Integer;
  463. begin
  464.   Assert(FClientSocket.Socket.Connected = True);
  465.   // 下载指定文件
  466.   for I:= 0 to FFileNames.Count - 1 do
  467.   begin
  468.     if (not Terminated) and (FClientSocket.Socket.Connected) then
  469.       DownloadAFile(FFileNames[I])
  470.     else
  471.       Break;
  472.   end;
  473.   FDownloadFileName:= '';
  474.   SyncDownloadCallback(dsEnd, 0);
  475.   Terminate;
  476. end;
  477. procedure TDownloadFileListThread.SyncDownloadCallback(
  478.   DownloadStatus: TDownloadStatus; WorkCount: Integer);
  479. begin
  480.   FDownloadStatus:= DownloadStatus;
  481.   FWorkCount:= WorkCount;
  482.   if Application.Handle = 0 then
  483.     DoDownloadCallback
  484.   else
  485.     Synchronize(Self, DoDownloadCallback);
  486. end;
  487. { ThxUpdateClient }
  488. procedure ThxUpdateClient.Close;
  489. begin
  490.   FClientSocket.Close;
  491. end;
  492. function ThxUpdateClient.ConnectByProxy(Socket: TSocket; RemoteIP: string;
  493.   RemotePort: Integer): Boolean;
  494. var
  495.   Buf: array[0..1023] of Byte;
  496.   Ret: Integer;
  497.   saRemote: TSockAddr;
  498. begin
  499.   Result:= False;
  500.   FillChar(saRemote, SizeOf(saRemote), #0);
  501.   saRemote.sin_family:= AF_INET;
  502.   saRemote.sin_addr.S_addr:= inet_addr(PChar(RemoteIP));
  503.   saRemote.sin_port:= htons(RemotePort);
  504.   Buf[0]:= SOCKS_VER5;    // 代理协议版本号(Socks5)
  505.   Buf[1]:= CMD_CONNECT;   // Reply
  506.   Buf[2]:= RSV_DEFAULT;   // 保留字段
  507.   Buf[3]:= ATYP_IPV4;     // 地址类型(IPV4)
  508.   CopyMemory(@Buf[4], @saRemote.sin_addr, 4); // 目标地址
  509.   CopyMemory(@Buf[8], @saRemote.sin_port, 2); // 目标端口号
  510.   Ret:= send(Socket, Buf, 10, 0);
  511.   if Ret = -1 then Exit;
  512.   Ret:= recv(Socket, Buf, 1023, 0);
  513.   if Ret = -1 then Exit;
  514.   if Buf[1] <> REP_SUCCESS then Exit;
  515.   Result:= True;
  516. end;
  517. constructor ThxUpdateClient.Create(ProjectName: string);
  518. var
  519.   wsData: TWSAData;
  520. begin
  521.   FProjectName:= ProjectName;
  522.   FResTree:= TResTree.Create;
  523.   Assert(WSAStartup(MAKEWORD(1, 1), wsData) = 0);
  524.   FClientSocket:= TClientSocket.Create(nil);
  525.   FClientSocket.ClientType:= ctBlocking;
  526. end;
  527. destructor ThxUpdateClient.Destroy;
  528. begin
  529.   if FClientSocket.Socket.Connected then
  530.     FClientSocket.Close;
  531.   FreeAndNil(FClientSocket);
  532.   FreeAndNil(FResTree);
  533.   WSACleanup;
  534.   inherited Destroy;
  535. end;
  536. procedure ThxUpdateClient.DownloadFileList(DownloadCallback: TDownloadCallback);
  537. begin
  538.   FResTree.Clear;
  539.   TDownloadFileListThread.Create(False, FClientSocket, FProjectName, FResTree, DownloadCallback);
  540. end;
  541. procedure ThxUpdateClient.DownloadFiles(FileNames: TStrings; DownloadCallback: TDownloadCallback);
  542. begin
  543.   TDownloadFilesThread.Create(Self, False, FClientSocket, FProjectName, FileNames, DownloadCallback);
  544. end;
  545. function ThxUpdateClient.GetActive: Boolean;
  546. begin
  547.   Result:= FClientSocket.Socket.Connected;
  548. end;
  549. function ThxUpdateClient.Handclasp(Socket: TSocket; AuthenType: TAuthenType): Boolean;
  550. var
  551.   Buf: array[0..254] of Byte;
  552.   I, Ret: Integer;
  553.   Username, Password: string;
  554. begin
  555.   Result:= False;
  556.   case AuthenType of
  557.     // 无需验证
  558.     atNone:
  559.     begin
  560.       Buf[0]:= SOCKS_VER5;
  561.       Buf[1]:= $01;
  562.       Buf[2]:= $00;
  563.       Ret:= send(Socket, Buf, 3, 0);
  564.       if Ret = -1 then Exit;
  565.       Ret:= recv(Socket, Buf, 255, 0);
  566.       if Ret < 2 then Exit;
  567.       if Buf[1] <> $00 then Exit;
  568.       Result:= True;
  569.     end;
  570.     // 用户名密码验证
  571.     atUserPass:
  572.     begin
  573.       Buf[0]:= SOCKS_VER5;
  574.       Buf[1]:= $02;
  575.       Buf[2]:= $00;
  576.       Buf[3]:= $02;
  577.       Ret:= send(Socket, Buf, 4, 0);
  578.       if Ret = -1 then Exit;
  579.       FillChar(Buf, 255, #0);
  580.       Ret:= recv(Socket, Buf, 255, 0);
  581.       if Ret < 2 then Exit;
  582.       if Buf[1] <> $02 then Exit;
  583.       Username:= FProxyInfo.Username;
  584.       Password:= FProxyInfo.Password;
  585.       FillChar(Buf, 255, #0);
  586.       Buf[0]:= $01;
  587.       Buf[1]:= Length(Username);
  588.       for I:= 0 to Buf[1] - 1 do
  589.         Buf[2 + I]:= Ord(Username[I + 1]);
  590.       Buf[2 + Length(Username)]:= Length(Password);
  591.       for I:= 0 to Buf[2 + Length(Username)] - 1 do
  592.         Buf[3 + Length(Username) + I]:= Ord(Password[I + 1]);
  593.       Ret:= send(Socket, Buf, Length(Username) + Length(Password) + 3, 0);
  594.       if Ret = -1 then Exit;
  595.       Ret:= recv(Socket, Buf, 255, 0);
  596.       if Ret = -1 then Exit;
  597.       if Buf[1] <> $00 then Exit;
  598.       Result:= True;
  599.     end;
  600.   end;
  601. end;
  602. procedure ThxUpdateClient.Open(ServerIP: string; Port: Integer);
  603. begin
  604.   Assert(FClientSocket.Socket.Connected = False);
  605.   try
  606.     if not FProxyInfo.Enabled then
  607.     begin
  608.       FClientSocket.Host:= ServerIP;
  609.       FClientSocket.Port:= Port;
  610.       FClientSocket.Open;
  611.     end
  612.     else begin  { 使用代理服务器 }
  613.       // 连接到Socks服务器
  614.       FClientSocket.Host:= FProxyInfo.IP;
  615.       FClientSocket.Port:= FProxyInfo.Port;
  616.       FClientSocket.Open;
  617.       if Trim(FProxyInfo.Username) <> '' then
  618.         Handclasp(FClientSocket.Socket.SocketHandle, atUserPass)
  619.       else
  620.         Handclasp(FClientSocket.Socket.SocketHandle, atNone);
  621.       // 连接到目标地址
  622.       ConnectByProxy(FClientSocket.Socket.SocketHandle, ServerIP, Port);
  623.     end;
  624.   except
  625.     raise Exception.Create('无法连接到LiveUpdate服务器,请检查网络配置!');
  626.   end;
  627. end;
  628. { TProjectMgr }
  629. function TProjectCollection.Add(ProjectName, Descripton, RootDir: string): TProjectItem;
  630. begin
  631.   Result:= TProjectItem(inherited Add);
  632.   Result.ProjectName:= ProjectName;
  633.   Result.Description:= Descripton;
  634.   Result.RootDir:= RootDir;
  635. end;
  636. procedure TProjectCollection.Clear;
  637. begin
  638.   inherited Clear;
  639. end;
  640. constructor TProjectCollection.Create(AOwner: TPersistent; FileName: string);
  641. begin
  642.   inherited Create(TProjectItem);
  643.   FOwner:= AOwner;
  644.   FFileName:= FileName;
  645.   LoadFromFile;
  646. end;
  647. procedure TProjectCollection.Delete(Index: Integer);
  648. begin
  649.   inherited Delete(Index);
  650. end;
  651. destructor TProjectCollection.Destroy;
  652. begin
  653.   SaveToFile;
  654.   Clear;
  655.   inherited Destroy;
  656. end;
  657. function TProjectCollection.GetItem(Index: Integer): TProjectItem;
  658. begin
  659.   Result:= TProjectItem(inherited GetItem(Index));
  660. end;
  661. function TProjectCollection.IndexOf(const ProjectName: string): Integer;
  662. var
  663.   I: Integer;
  664. begin
  665.   Result:= -1;
  666.   for I:= 0 to Count - 1 do
  667.     if SameText(TProjectItem(Items[I]).ProjectName, ProjectName) then
  668.     begin
  669.       Result:= I;
  670.       Break;
  671.     end;
  672. end;
  673. procedure TProjectCollection.LoadFromFile;
  674. var
  675.   I, C: Integer;
  676.   Stream: TStream;
  677.   szProjectName, szRootDir, szDescription: string;
  678. begin
  679.   Clear;
  680.   if not FileExists(FFileName) then Exit;
  681.   Stream:= TFileStream.Create(FFileName, fmOpenRead);
  682.   try
  683.     C:= StreamReadInteger(Stream);
  684.     for I:= 0 to C - 1 do
  685.     begin
  686.       szProjectName:= StreamReadString(Stream);
  687.       szRootDir:= StreamReadString(Stream);
  688.       szDescription:= StreamReadString(Stream);;
  689.       Add(szProjectName, szDescription, szRootDir);
  690.     end;
  691.   finally
  692.     Stream.Free;
  693.   end;
  694. end;
  695. procedure TProjectCollection.SaveToFile;
  696. var
  697.   I: Integer;
  698.   Stream: TFileStream;
  699. begin
  700.   Stream:= TFileStream.Create(FFileName, fmCreate);
  701.   try
  702.     StreamWriteInteger(Stream, Count);
  703.     for I:= 0 to Count - 1 do
  704.       with Items[I] do
  705.       begin
  706.         StreamWriteString(Stream, ProjectName);
  707.         StreamWriteString(Stream, RootDir);
  708.         StreamWriteString(Stream, Description);
  709.       end;
  710.   finally
  711.     Stream.Free;
  712.   end;
  713. end;
  714. { TProjectItem }
  715. constructor TProjectItem.Create(Collection: TCollection);
  716. begin
  717.   inherited Create(Collection);
  718.   FResTree:= TResTree.Create;
  719. end;
  720. destructor TProjectItem.Destroy;
  721. begin
  722.   FResTree.Free;
  723.   inherited Destroy;
  724. end;
  725. function TProjectItem.GetResTreeFileName: string;
  726. begin
  727.   Result:= ExtractFilePath(ParamStr(0)) + 'Projects' + FProjectName + '.vf';
  728. end;
  729. procedure TProjectItem.LoadResTree;
  730. begin
  731.   if FileExists(GetResTreeFileName) then
  732.     FResTree.LoadFromFile(GetResTreeFileName);
  733. end;
  734. procedure TProjectItem.RemoveResTree;
  735. var
  736.   ResFileName: string;
  737. begin
  738.   ResFileName:= GetResTreeFileName;
  739.   if FileExists(ResFileName) then
  740.     DeleteFile(ResFileName);
  741. end;
  742. procedure TProjectItem.SaveResTree;
  743. var
  744.   ResFilePath, ResFileName: string;
  745. begin
  746.   ResFileName:=  GetResTreeFileName;
  747.   ResFilePath:= ExtractFilePath(ResFileName);
  748.   if not DirectoryExists(ResFilePath) then
  749.     ForceDirectories(ResFilePath);
  750.   FResTree.SaveToFile(ResFileName);
  751. end;
  752. procedure TDownloadFilesThread.SyncDownloadCallback(
  753.   DownloadStatus: TDownloadStatus; WorkCount: Integer);
  754. begin
  755.   FDownloadStatus:= DownloadStatus;
  756.   FWorkCount:= WorkCount;
  757.   {
  758.   if Application.Handle = 0 then
  759.     DoDownloadCallback
  760.   else
  761.     Synchronize(Self, DoDownloadCallback);
  762.   }
  763.   DoDownloadCallback;
  764. end;
  765. end.