Guest User

Untitled

a guest
Jun 7th, 2012
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 6.28 KB | None | 0 0
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   sysutils, Classes, lnet, strutils, fgl
  10.   { you can add units after this };
  11.  
  12. Var
  13.   TEMP_DIR: String = '';
  14.  
  15. Function GetJSStr(Const aSource, aIndex: String): String;
  16. Var
  17.   aPos: Integer;
  18. Begin
  19.   aPos := Pos('"' + aIndex + '":"', aSource);
  20.   If aPos = 0 Then Exit('');
  21.   aPos := aPos + Length('"' + aIndex + '":"');
  22.   Result := Copy(aSource, aPos, PosEx('"',aSource, aPos) - aPos);
  23. end;
  24.  
  25. Type
  26.  
  27. { BFileSocketClass }
  28.  
  29.  BFileSocketClass = Class
  30.   Private
  31.     bKind: String;
  32.     bTempDir: String;
  33.     bFileName: String;
  34.     bFileSize: Integer;
  35.     bSocket: TLSocket;
  36.     bStream: TFileStream;
  37.     Procedure BufferSend;
  38.   Public
  39.     Property Kind: String Read bKind;
  40.     Property Stream: TFileStream Read bStream;
  41.     Property Socket: TLSocket Read bSocket;
  42.     Property FileName: String Read bFileName;
  43.     Property FileSize: Integer Read bFileSize;
  44.  
  45.     Function Execute: Boolean;
  46.  
  47.     Constructor Build(Const aKind: String;
  48.       Const aSocket: TLSocket; Const aFileName: String;
  49.       Const aFileSize: Integer);
  50.     Destructor Burn;
  51. End;
  52.  
  53. Type
  54.  
  55. { BServerClass }
  56.  
  57.  BServerClass = Class
  58.   Private
  59.     bConnection: TLTcp;
  60.     bTerminated: Boolean;
  61.  
  62.     Procedure ProcessReceive(aSocket: TLSocket);
  63.     Procedure ProcessDisconnect(aSocket: TLSocket);
  64.     Procedure ProcessOnCanSend(aSocket: TLSocket);
  65.  
  66.     Function FileProcess(Const aSocket: TLSocket): Boolean;
  67.     Procedure GetFile(Const aSocket: TLSocket; Const aName: String);
  68.     Procedure PutFile(Const aSocket: TLSocket; Const aName: String;
  69.       Const aSize: Integer);
  70.   Public
  71.     Procedure Run;
  72.     Constructor Build;
  73.     Destructor Burn;
  74. End;
  75.  
  76. { BFileSocketClass }
  77.  
  78. Procedure BFileSocketClass.BufferSend;
  79. Var
  80.   aCount: Integer;
  81.   aBuffer: Array[0..2047] Of Byte;
  82.   aSendCount: Integer;
  83. Begin
  84.   Repeat
  85.     aCount := bStream.Read(aBuffer, 2048);
  86.     If aCount > 0 Then
  87.       Begin
  88.         aSendCount := bSocket.Send(aBuffer, aCount);
  89.         If Not(aSendCount = aCount) Then
  90.           bStream.Seek(aSendCount - aCount, soFromCurrent);
  91.       End;
  92.   Until (aCount < 2048) Or Not(aSendCount = aCount);
  93. End;
  94.  
  95. Function BFileSocketClass.Execute: Boolean;
  96. Var
  97.   aBuffer: Array [0..2047] Of Byte;
  98.   aCount: Integer;
  99. Begin
  100.   Case Kind Of
  101.     'PUT':
  102.       Begin
  103.         Result := FALSE;
  104.         aCount := Socket.Get(aBuffer, 2048);
  105.         if aCount > 0 Then
  106.           bStream.Write(aBuffer, aCount);
  107.         Result := bStream.Size = FileSize;
  108.       End;
  109.     'GET':
  110.       Begin
  111.         BufferSend;
  112.         Result := bStream.Position = bStream.Size;
  113.       End;
  114.   End;
  115. End;
  116.  
  117. Constructor BFileSocketClass.Build(Const aKind: String;
  118.   Const aSocket: TLSocket; Const aFileName: String; Const aFileSize: Integer);
  119. Begin
  120.   bKind := aKind;
  121.   bSocket := aSocket;
  122.   bFileName := TEMP_DIR + ExtractFileName(aFileName);
  123.   Case Kind Of
  124.     'PUT':
  125.       Begin
  126.         bStream :=  TFileStream.Create(FileName, fmCreate);
  127.         bFileSize := aFileSize;
  128.       End;
  129.     'GET':
  130.       Begin
  131.         bStream :=  TFileStream.Create(FileName, fmOpenRead);
  132.         bFileSize := bStream.Size;
  133.       End;
  134.   End;
  135. End;
  136.  
  137. Destructor BFileSocketClass.Burn;
  138. Begin
  139.   bStream.Free;
  140. End;
  141.  
  142. { BServerClass }
  143.  
  144. Procedure BServerClass.ProcessDisconnect(aSocket: TLSocket);
  145. Begin
  146.   If Not(aSocket.UserData = nil) Then
  147.     Begin
  148.       BFileSocketClass(aSocket.UserData).Burn;
  149.       aSocket.UserData := nil;
  150.     End;
  151. end;
  152.  
  153. Procedure BServerClass.ProcessOnCanSend(aSocket: TLSocket);
  154. Var
  155.   aFileSocket: BFileSocketClass;
  156. Begin
  157.   If aSocket.UserData = nil Then Exit;
  158.   aFileSocket := BFileSocketClass(aSocket.UserData);
  159.   If aFileSocket.Execute Then
  160.     Begin
  161.       aSocket.UserData := nil;
  162.       aFileSocket.Burn;
  163.     End;
  164.   bConnection.CallAction;
  165. end;
  166.  
  167. Function BServerClass.FileProcess(Const aSocket: TLSocket): Boolean;
  168. Var
  169.   aFileSocket: BFileSocketClass;
  170. Begin
  171.   Result := FALSE;
  172.   If aSocket.UserData = nil Then Exit;
  173.   aFileSocket := BFileSocketClass(aSocket.UserData);
  174.   If aFileSocket.Execute Then
  175.     Begin
  176.       aSocket.UserData := nil;
  177.       aFileSocket.Burn;
  178.     End;
  179.   Result := TRUE
  180. End;
  181.  
  182. Procedure BServerClass.ProcessReceive(aSocket: TLSocket);
  183. var
  184.   aType, aName, aMessage: String;
  185.   aSize: Integer;
  186. begin
  187.   If Not(aSocket.UserData = nil) Then
  188.   If FileProcess(aSocket) Then
  189.     Begin
  190.       bConnection.CallAction;
  191.       Exit;
  192.     End;
  193.   If aSocket.GetMessage(aMessage) > 0 Then
  194.     Begin
  195.       aType := GetJSStr(aMessage, 'type');
  196.       aName := GetJSStr(aMessage, 'name');
  197.       aSize := StrToIntDef(GetJSStr(aMessage, 'size'), -1);
  198.       Case aType Of
  199.        'GET': GetFile(aSocket, aName);
  200.        'PUT': PutFile(aSocket, aName, aSize);
  201.       End;
  202.     End;
  203. end;
  204.  
  205. Procedure BServerClass.GetFile(Const aSocket: TLSocket; Const aName: String);
  206. Var
  207.   aFileSocket: BFileSocketClass;
  208.   aResponse: String;
  209. Begin
  210.   aFileSocket := BFileSocketClass.Build('GET', aSocket, aName, -1);
  211.   aSocket.UserData := aFileSocket;
  212.   aResponse := Format('{"type":"GET","name":"%s","size":"%d"}',
  213.     [aFileSocket.FileName, aFileSocket.FileSize]);
  214.   aSocket.SendMessage(aResponse);
  215.   If aFileSocket.Execute Then
  216.     Begin
  217.       aSocket.UserData := nil;
  218.       aFileSocket.Burn;
  219.     End;
  220. End;
  221.  
  222. Procedure BServerClass.PutFile(Const aSocket: TLSocket; Const aName: String;
  223.   Const aSize: Integer);
  224. Var
  225.   aRequest: String;
  226. Begin
  227.   aSocket.UserData := BFileSocketClass.Build('PUT', aSocket, aName, aSize);
  228.   aRequest := Format('{"type":"PUT","name":"%s","size":"%d"}', [aName, aSize]);
  229.   aSocket.SendMessage(aRequest);
  230. End;
  231.  
  232. Procedure BServerClass.Run;
  233. Begin
  234.   If  bConnection.Listen(7447) Then
  235.     Repeat
  236.       bConnection.CallAction
  237.     Until FALSE;
  238. End;
  239.  
  240. Constructor BServerClass.Build;
  241. Begin
  242.   bTerminated := FALSE;
  243.   bConnection := TLTcp.Create(nil);
  244.   bConnection.OnReceive := @ProcessReceive;
  245.   bConnection.OnDisconnect := @ProcessDisconnect;
  246.   bConnection.OnCanSend := @ProcessOnCanSend;
  247.   bConnection.Timeout := 1000;
  248. End;
  249.  
  250. Destructor BServerClass.Burn;
  251. Begin
  252. End;
  253.  
  254. Begin
  255.   TEMP_DIR := GetTempDir(FALSE) + 'upload/';
  256.   If Not(DirectoryExists(TEMP_DIR)) Then mkdir(TEMP_DIR);
  257.   With BServerClass.Build Do
  258.     Begin
  259.       Run;
  260.       Burn;
  261.     End;
  262. end.
Advertisement
Add Comment
Please, Sign In to add comment