BxDolStorageS3v4alt.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. if (!defined('CURL_SSLVERSION_TLSv1'))
  10. define('CURL_SSLVERSION_TLSv1', 1);
  11. if (!defined('BX_DOL_STORAGE_S3V4_MULTIPART_UPLOAD'))
  12. define('BX_DOL_STORAGE_S3V4_MULTIPART_UPLOAD', 5*1024*1024);
  13. define('AKEEBAENGINE', 1);
  14. /**
  15. * Alternatove file storage implementation for Amazon S3
  16. * compatible storge with Signature v4 support.
  17. * @see BxDolStorage
  18. */
  19. class BxDolStorageS3v4alt extends BxDolStorageS3
  20. {
  21. protected function init ($aObject)
  22. {
  23. $oConfiguration = new Akeeba\Engine\Postproc\Connector\S3v4\Configuration(
  24. getParam('sys_storage_s3_access_key'),
  25. getParam('sys_storage_s3_secret_key'),
  26. getParam('sys_storage_s3_sig_ver'),
  27. getParam('sys_storage_s3_region')
  28. );
  29. if ($this->_sEndpoint)
  30. $oConfiguration->setEndpoint($this->_sEndpoint);
  31. $this->_s3 = new Akeeba\Engine\Postproc\Connector\S3v4\Connector($oConfiguration);
  32. }
  33. /**
  34. * Get file url.
  35. * @param $iFileId file
  36. * @return file url
  37. */
  38. public function getFileUrlById($iFileId)
  39. {
  40. $aFile = $this->_oDb->getFileById($iFileId);
  41. if (!$aFile)
  42. return false;
  43. if ($aFile['private']) {
  44. $sFileLocation = $this->getObjectBaseDir($aFile['private']) . $aFile['path'];
  45. $sRet = $this->_s3->getAuthenticatedURL($this->_sBucket, $sFileLocation, $this->_aObject['token_life'], $this->_bSSL);
  46. }
  47. else {
  48. $sRet = $this->getObjectBaseUrl($aFile['private']) . $aFile['path'];
  49. }
  50. if ('s3.wasabisys.com' === $this->_sEndpoint)
  51. $sRet = str_replace('//s3.', '//' . $this->_sBucket . '.s3.', $sRet);
  52. return $sRet;
  53. }
  54. public function setFilePrivate($iFileId, $isPrivate = true)
  55. {
  56. // since in S3v4 lib this feature not implemented then we need to get file and upload it back with new ACL
  57. $aFile = $this->_oDb->getFileById($iFileId);
  58. if (!$aFile)
  59. return false;
  60. $sFileLocation = $this->getObjectBaseDir($aFile['private']) . $aFile['path'];
  61. $sTmpFile = tempnam(BX_DIRECTORY_PATH_TMP, $this->_aObject['object']);
  62. if (!$sTmpFile) {
  63. $this->setErrorCode(BX_DOL_STORAGE_ERR_FILESYSTEM_PERM);
  64. return false;
  65. }
  66. try {
  67. $this->_s3->getObject($this->_sBucket, $sFileLocation, $sTmpFile);
  68. } catch (Exception $e) {
  69. @unlink($sTmpFile);
  70. $this->setErrorCode(BX_DOL_STORAGE_ERR_UNLINK);
  71. return false;
  72. }
  73. $sACL = $isPrivate ? Akeeba\Engine\Postproc\Connector\S3v4\Acl::ACL_AUTHENTICATED_READ : Akeeba\Engine\Postproc\Connector\S3v4\Acl::ACL_PUBLIC_READ;
  74. $aRequestHeaders = $this->generateHeaders('', $isPrivate, $aFile['mime_type']);
  75. if (!$this->_upload($sTmpFile, $sFileLocation, $sACL, $aRequestHeaders))
  76. return false;
  77. return BxDolStorage::setFilePrivate($iFileId, $isPrivate);
  78. }
  79. // ----------------
  80. protected function addFileToEngine($sTmpFile, $sLocalId, $sName, $isPrivate, $iProfileId)
  81. {
  82. $sExt = $this->getFileExt($sName);
  83. $sPath = $this->genPath($sLocalId, $this->_aObject['levels']);
  84. $sRemoteNamePath = $sPath . $sLocalId . ($sExt ? '.' . $sExt : '');
  85. $aRequestHeaders = $this->generateHeaders($sName, $isPrivate);
  86. $sACL = $isPrivate ? Akeeba\Engine\Postproc\Connector\S3v4\Acl::ACL_AUTHENTICATED_READ : Akeeba\Engine\Postproc\Connector\S3v4\Acl::ACL_PUBLIC_READ;
  87. return $this->_upload($sTmpFile, $this->getObjectBaseDir($isPrivate) . $sRemoteNamePath, $sACL, $aRequestHeaders);
  88. }
  89. protected function _upload($sInputFile, $sUri, $sACL, $aRequestHeaders)
  90. {
  91. try {
  92. $oInputFile = Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sInputFile);
  93. if (filesize($sInputFile) < BX_DOL_STORAGE_S3V4_MULTIPART_UPLOAD) {
  94. $this->_s3->putObject($oInputFile, $this->_sBucket, $sUri, $sACL, $aRequestHeaders);
  95. }
  96. else {
  97. $sUploadSessionId = $this->_s3->startMultipart($oInputFile, $this->_sBucket, $sUri, $sACL, $aRequestHeaders);
  98. $sETags = array();
  99. $sETag = null;
  100. $iPartNumber = 0;
  101. do
  102. {
  103. // IMPORTANT: You MUST create the input afresh before each uploadMultipart call
  104. $oInput = Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sInputFile);
  105. $oInput->setUploadID($sUploadSessionId);
  106. $oInput->setPartNumber(++$iPartNumber);
  107. $sETag = $this->_s3->uploadMultipart($oInput, $this->_sBucket, $sUri);
  108. if (!is_null($sETag))
  109. $sETags[] = $sETag;
  110. }
  111. while (!is_null($sETag));
  112. // IMPORTANT: You MUST create the input afresh before finalising the multipart upload
  113. $oInput = Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sInputFile);
  114. $oInput->setUploadID($sUploadSessionId);
  115. $oInput->setEtags($sETags);
  116. $this->_s3->finalizeMultipart($oInput, $this->_sBucket, $sUri);
  117. }
  118. } catch (Exception $e) {
  119. $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD);
  120. return false;
  121. }
  122. return true;
  123. }
  124. protected function deleteFileFromEngine($sFilePath, $isPrivate)
  125. {
  126. $sFileLocation = $this->getObjectBaseDir($isPrivate) . $sFilePath;
  127. try {
  128. $this->_s3->deleteObject($this->_sBucket, $sFileLocation);
  129. } catch (Exception $e) {
  130. $this->setErrorCode(BX_DOL_STORAGE_ERR_UNLINK);
  131. return false;
  132. }
  133. return true;
  134. }
  135. }
  136. /** @} */