Guest User

uS3Storage

a guest
Jun 16th, 2013
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 10.19 KB | None | 0 0
  1. unit uS3Storage;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. //code by Tim Anderson; used for tutorial in PC Plus http://www.pcplus.co.uk.
  6.  
  7. //The lastest version of this code can be found at:
  8.  
  9. // http://www.itwriting.com/s3.php
  10.  
  11. interface
  12.  
  13. uses
  14.   Sysutils, Classes, strutils, blcksock, httpsend, synautil, synacode, ssl_openssl;
  15.  
  16. type
  17.   TS3Storage = class(TObject)
  18.  
  19.   private
  20.     { Private declarations }
  21.     FError: TstringList;
  22.     Fpublickey: string;
  23.     FHttpPrefix: string;
  24.     mHttp: THttpSend;
  25.     FOnStatusChange: THookSocketStatus;
  26.  
  27.     procedure FSetUseSSL(value: boolean);
  28.     procedure InitHttp;
  29.  
  30.     function FGetUseSSL: boolean;
  31.     function GetAuthString(verb: string; MD5: string; ContentType: string; sDate: string; Request: string): string;
  32.  
  33.  
  34.   public
  35.     { Public declarations }
  36.     property UseSSL: Boolean read FGetUseSSL write FSetUseSSL;
  37.     property Error: TStringList read FError;
  38.     property PublicKey: string read Fpublickey;
  39.     property OnStatusChange: THookSocketStatus read FOnStatusChange write FOnStatusChange;
  40.  
  41.     procedure Abort(); //cancel the data transfer
  42.     procedure OnSocketStatus(Sender: TObject; Reason: THookSocketReason; const Value: string);
  43.  
  44.     function GetS3Object(BucketName: string; ObjectName: string; DestStream: TStream): boolean;
  45.     function PutS3Object(BucketName: string; ObjectName: string; theStream: TStream; isBinary: boolean): boolean;
  46.     function DeleteS3Object(BucketName: string; ObjectName: string): boolean;
  47.     function CreateBucket(BucketName: string): boolean;
  48.     function DeleteBucket(BucketName: string): boolean;
  49.     function ListBucketItems(BucketName: string; DestStream: TMemoryStream): boolean;
  50.     function ListBuckets(DestStream: TMemoryStream): boolean;
  51.  
  52.     function GetUniqueBucketName(BucketName: string): string;
  53.     function StripKeyFromBucketName(BucketName: string): string;
  54.     function EncodeString(s: string): string;
  55.     function DecodeString(s: string): string;
  56.  
  57.     constructor Create(apublickey: string; aprivatekey: string);
  58.     destructor Destroy; override;
  59.  
  60.   end;
  61.  
  62.  
  63. implementation
  64.  
  65. var
  66.   Fprivatekey: string;
  67.  
  68. destructor TS3STorage.Destroy;
  69. begin
  70.   FError.free;
  71.   inherited;
  72. end;
  73.  
  74. constructor TS3Storage.Create(apublickey: string; aprivatekey: string);
  75. begin
  76.   FpublicKey := apublickey;
  77.   FprivateKey := aprivatekey;
  78.   FError := TStringList.Create;
  79.   FHttpPrefix := 'http://';
  80. end;
  81.  
  82. procedure TS3Storage.Abort;
  83. begin
  84.  
  85.   if (mHTTP <> nil) then
  86.   begin
  87.     mHttp.Sock.AbortSocket;
  88.   end;
  89.  
  90. end;
  91.  
  92. function TS3Storage.EncodeString(s: string): string;
  93. begin
  94.   Result := EncodeURLElement(trim(s));
  95. end;
  96.  
  97. function TS3Storage.DecodeString(s: string): string;
  98. begin
  99.   Result := DecodeURL(s);
  100. end;
  101.  
  102. procedure TS3Storage.FSetUSESSL(value: boolean);
  103. begin
  104.  
  105.   if value then
  106.     FHttpPrefix := 'https://'
  107.   else
  108.     FHttpPrefix := 'http://';
  109.  
  110. end;
  111.  
  112. function TS3Storage.FGetUseSSL: boolean;
  113. begin
  114.  
  115.   result := (FHttpPrefix = 'https://');
  116.  
  117. end;
  118.  
  119.  
  120. function TS3Storage.GetUniqueBucketName(BucketName: string): string;
  121. begin
  122.  
  123.   result := FPublicKey + '-' + trim(BucketName);
  124. end;
  125.  
  126. function TS3STorage.StripKeyFromBucketName(BucketName: string): string;
  127. begin
  128.   result := AnsiReplaceStr(BucketName, GetUniqueBucketName(''), '');
  129. end;
  130.  
  131. function TS3Storage.CreateBucket(BucketName: string): boolean;
  132. var
  133.   sRequest: string;
  134.   theResponse: TMemoryStream;
  135.   sDate: string;
  136.   sFinalAuth: string;
  137.  
  138.   begin
  139.  
  140.   inithttp;
  141.  
  142.   try
  143.  
  144.     sRequest := '/' + BucketName;
  145.  
  146.     sDate := RFC822DateTime(now);
  147.  
  148.     mhttp.Headers.Add('Date: ' + sDate);
  149.  
  150.     sFinalAuth := GetAuthString('PUT', '', '', sDate, sRequest);
  151.  
  152.     mhttp.Headers.Add(sFinalAuth);
  153.  
  154.     mhttp.HTTPMethod('PUT', FHttpPrefix + 's3.amazonaws.com' + sRequest);
  155.     theResponse := mhttp.Document;
  156.     theResponse.Position := 0;
  157.     Result := uppercase(mhttp.ResultString) = 'OK';
  158.  
  159.     if not Result then begin
  160.       self.FError.LoadFromStream(theResponse);
  161.       self.FError.Insert(0,'Http Result: ' + mhttp.ResultString);
  162.     end
  163.     else
  164.       self.FError.Clear;
  165.  
  166.   finally
  167.     Freeandnil(mhttp);
  168.   end;
  169.  
  170.  
  171. end;
  172.  
  173. function TS3Storage.DeleteBucket(BucketName: string): boolean;
  174.  
  175. begin
  176.  
  177.   result := DeleteS3Object(BucketName, '');
  178.  
  179. end;
  180.  
  181. function TS3Storage.DeleteS3Object(BucketName: string; ObjectName: string): boolean;
  182. var
  183.   sRequest: string;
  184.   theResponse: TMemoryStream;
  185.   sDate: string;
  186.   sFinalAuth: string;
  187. begin
  188.  
  189.   inithttp;
  190.  
  191.   try
  192.  
  193.     if ObjectName <> '' then
  194.       sRequest := '/' + BucketName + '/' + ObjectName
  195.     else
  196.       sRequest := '/' + BucketName;
  197.  
  198.     sDate := RFC822DateTime(now);
  199.  
  200.     mhttp.Headers.Add('Date: ' + sDate);
  201.  
  202.     sFinalAuth := GetAuthString('DELETE', '', '', sDate, sRequest);
  203.  
  204.     mhttp.Headers.Add(sFinalAuth);
  205.  
  206.     mhttp.HTTPMethod('DELETE', FHttpPrefix + 's3.amazonaws.com' + sRequest);
  207.     theResponse := mhttp.Document;
  208.     theResponse.Position := 0;
  209.     result := (mhttp.ResultCode = 204); //does this prove success?
  210.  
  211.     if not Result then begin
  212.       self.FError.LoadFromStream(theResponse);
  213.       self.FError.Insert(0,'Http Result: ' + mhttp.ResultString);
  214.     end
  215.     else
  216.       self.FError.Clear;
  217.  
  218.   finally
  219.     Freeandnil(mhttp);
  220.   end;
  221.  
  222.  
  223. end;
  224.  
  225.  
  226. function Ts3Storage.PutS3Object(BucketName: string; ObjectName: string; theStream: TStream; isBinary: boolean): boolean;
  227. var
  228.   sRequest: string;
  229.   theResponse: TMemoryStream;
  230.   sDate: string;
  231.   sContentType: string;
  232.   sFinalAuth: string;
  233. begin
  234.  
  235.   inithttp;
  236.  
  237.   try
  238.  
  239.     sRequest := '/' + BucketName + '/' + ObjectName;
  240.  
  241.     sDate := RFC822DateTime(now);
  242.  
  243.     if isBinary then
  244.       sContentType := 'binary/octet-stream'
  245.     else
  246.       sContentType := 'text/html';
  247.  
  248.     mhttp.MimeType := sContentType; //becomes content type
  249.     mhttp.Headers.Add('Date: ' + sDate);
  250.  
  251.     mhttp.Document.LoadFromStream(theStream);
  252.  
  253.     sFinalAuth := self.GetAuthString('PUT', '', sContentType, sDate, sRequest);
  254.  
  255.     mhttp.Headers.Add(sFinalAuth);
  256.  
  257.     mhttp.HTTPMethod('PUT', FHttpPrefix + 's3.amazonaws.com' + sRequest);
  258.     theResponse := mhttp.Document;
  259.     theResponse.Position := 0;
  260.  
  261.     result := uppercase(mhttp.resultstring) = 'OK';
  262.  
  263.     if not Result then begin
  264.       self.FError.LoadFromStream(theResponse);
  265.       self.FError.Insert(0,'Http Result: ' + mhttp.ResultString);
  266.     end;
  267.     FError.Clear;
  268.  
  269.  
  270.   finally
  271.     Freeandnil(mhttp);
  272.   end;
  273.  
  274. end;
  275.  
  276. function TS3Storage.GetS3Object(BucketName: string; ObjectName: string; DestStream: TStream): boolean;
  277. var
  278.   sRequest: string;
  279.   theResponse: TMemoryStream;
  280.  
  281.   sDate: string;
  282.   sFinalAuth: string;
  283. begin
  284.  
  285.   InitHttp;
  286.  
  287.   try
  288.  
  289.     sRequest := '/' + BucketName + '/' + ObjectName;
  290.  
  291.     sDate := RFC822DateTime(now);
  292.  
  293.     mhttp.Headers.Add('Date: ' + sDate);
  294.  
  295.     sFinalAuth := GetAuthString('GET', '', '', sDate, sRequest);
  296.  
  297.     mhttp.Headers.Add(sFinalAuth);
  298.  
  299.     mhttp.HTTPMethod('GET', FHttpPrefix + 's3.amazonaws.com' + sRequest);
  300.     theResponse := mhttp.Document;
  301.     theResponse.Position := 0;
  302.  
  303.     result := uppercase(mhttp.resultstring) = 'OK';
  304.  
  305.     if result then begin
  306.  
  307.       theResponse.SaveToStream(DestStream);
  308.  
  309.       FError.clear;
  310.     end
  311.     else
  312.     begin
  313.       self.FError.LoadFromStream(theResponse);
  314.       self.FError.Insert(0,'Http Result: ' + mhttp.ResultString);
  315.     end;
  316.  
  317.   finally
  318.     Freeandnil(mhttp);
  319.   end;
  320.  
  321. end;
  322.  
  323. function TS3Storage.ListBuckets(DestStream: TMemoryStream): boolean;
  324. var
  325.   sRequest: string;
  326.   theResponse: TMemoryStream;
  327.   sDate: string;
  328.   sFinalAuth: string;
  329. begin
  330.  
  331.   InitHttp;
  332.  
  333.   try
  334.  
  335.     sRequest := '/';
  336.  
  337.     sDate := RFC822DateTime(now);
  338.  
  339.     mhttp.Headers.Add('Date: ' + sDate);
  340.  
  341.     sFinalAuth := GetAuthString('GET', '', '', sDate, sRequest);
  342.  
  343.     mhttp.Headers.Add(sFinalAuth);
  344.  
  345.     mhttp.HTTPMethod('GET', FHttpPrefix + 's3.amazonaws.com' + sRequest);
  346.     theResponse := mhttp.Document;
  347.     theResponse.Position := 0;
  348.  
  349.     result := uppercase(mhttp.resultstring) = 'OK';
  350.  
  351.     if result then begin
  352.       DestStream.LoadFromStream(theResponse);
  353.       FError.clear;
  354.     end
  355.     else
  356.          begin
  357.       self.FError.LoadFromStream(theResponse);
  358.       self.FError.Insert(0,'Http Result: ' + mhttp.ResultString);
  359.     end;
  360.  
  361.   finally
  362.     Freeandnil(mhttp);
  363.   end;
  364.  
  365.  
  366.  
  367. end;
  368.  
  369. function TS3Storage.ListBucketItems(BucketName: string; DestStream: TMemoryStream): boolean;
  370. var
  371.   sRequest: string;
  372.   theResponse: TMemoryStream;
  373.   sDate: string;
  374.   sFinalAuth: string;
  375. begin
  376.  
  377.   initHttp;
  378.  
  379.   try
  380.  
  381.     sRequest := '/' + BucketName;
  382.  
  383.     sDate := RFC822DateTime(now);
  384.  
  385.     mhttp.Headers.Add('Date: ' + sDate);
  386.  
  387.     sFinalAuth := GetAuthString('GET', '', '', sDate, sRequest);
  388.  
  389.     mhttp.Headers.Add(sFinalAuth);
  390.  
  391.     mhttp.HTTPMethod('GET', FHttpPrefix + 's3.amazonaws.com' + sRequest);
  392.     theResponse := mhttp.Document;
  393.     theResponse.Position := 0;
  394.  
  395.     result := uppercase(mhttp.resultstring) = 'OK';
  396.  
  397.     if result then begin
  398.       DestStream.LoadFromStream(theResponse);
  399.       FError.clear;
  400.     end
  401.     else
  402.         begin
  403.       self.FError.LoadFromStream(theResponse);
  404.       self.FError.Insert(0,'Http Result: ' + mhttp.ResultString);
  405.     end;
  406.  
  407.   finally
  408.     Freeandnil(mhttp);
  409.   end;
  410.  
  411. end;
  412.  
  413.  
  414. function TS3Storage.GetAuthString(verb: string; MD5: string; ContentType: string; sDate: string; Request: string): string;
  415. var
  416.   sAuth: string;
  417.   sHMac: string;
  418.   sBase64: string;
  419. begin
  420.  
  421.   sAuth := verb + chr(10) + MD5 + chr(10) + ContentType + chr(10) + sDate + chr(10) + Request;
  422.  
  423. //concert sAuth to hmac-sha1
  424.   sHMac := HMAC_SHA1(sAuth, FPrivateKey);
  425.  
  426. //convert binary string to base 64
  427.   sBase64 := EncodeBase64(sHMac);
  428.  
  429. //return auth string
  430.   Result := 'Authorization: AWS ' + FPublicKey + ':' + sBase64;
  431.  
  432. end;
  433.  
  434. procedure TS3Storage.InitHttp;
  435. begin
  436.  
  437.   if mHttp <> nil then
  438.   begin
  439.     mHttp.Sock.AbortSocket;
  440.     Freeandnil(mhttp);
  441.   end;
  442.  
  443.   mhttp := THttpSend.Create;
  444.   mhttp.Clear;
  445.  // mhttp.Protocol := '1.1';
  446.  
  447.   mhttp.Sock.OnStatus := @OnSocketStatus;
  448.  
  449. end;
  450.  
  451. procedure TS3Storage.OnSocketStatus(Sender: TObject; Reason: THookSocketReason; const Value: string);
  452.  
  453. begin
  454. //could do progress report here
  455. If Assigned(FOnStatusChange) then
  456.  FOnStatusChange(Sender,Reason,Value);
  457.  
  458. end;
  459.  
  460.  
  461. end.
Add Comment
Please, Sign In to add comment