BxBaseUploaderServices.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 UnaBaseView UNA Base Representation Classes
  7. * @{
  8. */
  9. /**
  10. * System services related to Comments.
  11. */
  12. class BxBaseUploaderServices extends BxDol
  13. {
  14. public function __construct()
  15. {
  16. parent::__construct();
  17. }
  18. /**
  19. * @page service Service Calls
  20. * @section bx_system_cmts System Services
  21. * @subsection bx_system_cmts-general General
  22. * @subsubsection bx_system_cmts-get_data_api get_data_api
  23. *
  24. * @code bx_srv('system', 'get_data_api', [], 'TemplCmtsServices'); @endcode
  25. *
  26. * Get comments data
  27. * @param $aParams array with paramenters :
  28. * "module":"bx_posts","object_id":3,"start_from":5,"order_way":"desc","is_form":false
  29. *
  30. * @see TemplCmtsServices::serviceGetDataApi
  31. */
  32. /**
  33. * @ref bx_system_cmts-get_data_api "get_data_api"
  34. * @api @ref bx_system_cmts-get_data_api "get_data_api"
  35. */
  36. public function serviceGetDataApi($aParams = [])
  37. {
  38. $sUploaderObject = bx_process_input(bx_get('uo'));
  39. $sStorageObject = bx_process_input(bx_get('so'));
  40. $sUniqId = preg_match("/^[\d\w]+$/", bx_get('uid')) ? bx_get('uid') : '';
  41. $isMultiple = bx_get('m') ? true : false;
  42. $sFormat = bx_process_input(bx_get('f'));
  43. if ($sFormat != 'html' && $sFormat != 'json')
  44. $sFormat = 'html';
  45. $iContentId = bx_get('c');
  46. if (false === $iContentId || '' === $iContentId)
  47. $iContentId = false;
  48. else
  49. $iContentId = bx_process_input($iContentId, BX_DATA_INT);
  50. $iProfileId = (int)bx_get_logged_profile_id();
  51. $isPrivate = (int)bx_get('p') ? 1 : 0;
  52. $sAction = bx_process_input(bx_get('a'));
  53. // Direct upload (bypassing the app proxy): the profile comes from a one-time upload token.
  54. $sUploadToken = bx_get('ut');
  55. if($sUploadToken !== false && $sUploadToken !== '') {
  56. $sUploadToken = bx_process_input($sUploadToken);
  57. $aToken = BxDolKey::getInstance()->getKeyData($sUploadToken, 'uploader');
  58. if(!in_array($sAction, ['upload', 'upload_inline']) || !$this->isUploadTokenValid($aToken, $sUploaderObject, $sStorageObject))
  59. return ['error' => _t('_Access denied'), 'code' => 403];
  60. $iProfileId = (int)$aToken['profile_id'];
  61. }
  62. $oUploader = BxDolUploader::getObjectInstance($sUploaderObject, $sStorageObject, $sUniqId);
  63. switch ($sAction) {
  64. case 'restore_ghosts':
  65. $sImagesTranscoder = bx_process_input(bx_get('img_trans'));
  66. $oData = $oUploader->getGhostsWithOrder($iProfileId, $sFormat, $sImagesTranscoder, $iContentId);
  67. $aRv = isset($oData['g']) ? [$oData['g'], $oData['o']] : [];
  68. return $aRv;
  69. break;
  70. case 'delete':
  71. header('Content-type: text/html; charset=utf-8');
  72. $iFileId = bx_process_input(bx_get('id'), BX_DATA_INT);
  73. return $oUploader->deleteGhost($iFileId, $iProfileId);
  74. break;
  75. case 'upload':
  76. if(($aFile = $_FILES['file'] ?? false)) {
  77. $aResult = $oUploader->handleUploads($iProfileId, $aFile, $isMultiple, $iContentId, $isPrivate);
  78. // One-time token: burn it once the file is stored.
  79. if(!empty($sUploadToken))
  80. BxDolKey::getInstance()->removeKey($sUploadToken);
  81. if(($iId = (int)($aResult['id'] ?? 0)) && ($sImagesTranscoder = bx_get('img_trans')) !== false) {
  82. $aGhosts = $oUploader->getGhosts($iProfileId, 'array', bx_process_input($sImagesTranscoder), $iContentId);
  83. if(isset($aGhosts[$iId]))
  84. $aResult['ghost'] = $aGhosts[$iId];
  85. }
  86. return $aResult;
  87. }
  88. break;
  89. case 'upload_inline':
  90. // The upload token is bound to `so`; the inline storage must be the same one.
  91. $sInlineStorage = bx_process_input(bx_get('o'));
  92. if(!empty($sUploadToken) && $sInlineStorage !== $sStorageObject)
  93. return ['error' => _t('_Access denied'), 'code' => 403];
  94. $sStorageObject = $sInlineStorage;
  95. $sFile = bx_process_input(bx_get('f'));
  96. $oStorage = BxDolStorage::getObjectInstance($sStorageObject);
  97. if (!$oStorage || empty($_FILES['file']))
  98. return array('error' => '1');
  99. if (!($iId = $oStorage->storeFileFromForm($_FILES['file'], false, $iProfileId))) {
  100. return array('error' => '1');
  101. exit;
  102. }
  103. if(!empty($sUploadToken))
  104. BxDolKey::getInstance()->removeKey($sUploadToken);
  105. $oStorage->afterUploadCleanup($iId, $iProfileId);
  106. $aFileInfo = $oStorage->getFile($iId);
  107. // Video: queue transcoding and return stable image_transcoder.php links
  108. // (`vt` - mp4 transcoder, `pt` - poster transcoder); they redirect once ready.
  109. if ($aFileInfo && 0 === strncmp($aFileInfo['mime_type'], 'video/', 6) && ($sVideoTranscoder = bx_get('vt'))) {
  110. $aResult = ['link' => '', 'poster' => '', 'video' => 1];
  111. foreach (['link' => $sVideoTranscoder, 'poster' => bx_get('pt')] as $sKey => $sTranscoder) {
  112. if (!$sTranscoder)
  113. continue;
  114. $sTranscoder = bx_process_input($sTranscoder);
  115. // Only transcoders fed by this storage, so `h` can't point at foreign files.
  116. $aTranscoder = BxDolTranscoderQuery::getTranscoderObject($sTranscoder);
  117. $aSource = !empty($aTranscoder['source_params']) ? unserialize($aTranscoder['source_params']) : [];
  118. if (($aSource['object'] ?? '') !== $sStorageObject || !($oTranscoder = BxDolTranscoder::getObjectInstance($sTranscoder)))
  119. continue;
  120. $oTranscoder->getFileUrl($iId); // adds the file to the transcoding queue
  121. $aResult[$sKey] = BX_DOL_URL_ROOT . 'image_transcoder.php?o=' . $sTranscoder . '&h=' . $iId;
  122. }
  123. return $aResult['link'] ? $aResult : ['link' => $oStorage->getFileUrlById($iId)];
  124. }
  125. if ($aFileInfo && in_array($aFileInfo['ext'], array('jpg', 'jpeg', 'jpe', 'png'))) {
  126. $oTranscoder = BxDolTranscoderImage::getObjectInstance(bx_get('t'));
  127. $sUrl = $oTranscoder->getFileUrl($iId);
  128. }
  129. else {
  130. $sUrl = $oStorage->getFileUrlById($iId);
  131. }
  132. return ['link' => $sUrl];
  133. break;
  134. }
  135. }
  136. public function serviceGetUploadToken()
  137. {
  138. $iProfileId = (int)bx_get_logged_profile_id();
  139. if(!$iProfileId)
  140. return ['error' => _t('_Access denied'), 'code' => 403];
  141. $sUploaderObject = bx_process_input(bx_get('uo'));
  142. $sStorageObject = bx_process_input(bx_get('so'));
  143. if(!$sUploaderObject || !$sStorageObject || !BxDolUploader::getObjectInstance($sUploaderObject, $sStorageObject, 'token'))
  144. return ['error' => _t('_sys_request_page_not_found_cpt'), 'code' => 404];
  145. $iLifetime = 900;
  146. $sToken = BxDolKey::getInstance()->getNewKey([
  147. 'profile_id' => $iProfileId,
  148. 'uo' => $sUploaderObject,
  149. 'so' => $sStorageObject,
  150. 'expire' => time() + $iLifetime,
  151. ], $iLifetime, 'uploader');
  152. if(!$sToken)
  153. return ['error' => _t('_error occured'), 'code' => 500];
  154. return [
  155. 'token' => $sToken,
  156. 'url' => BX_DOL_URL_ROOT . 'api.php',
  157. 'expire' => $iLifetime,
  158. ];
  159. }
  160. // sys_keys doesn't check expiration on read (only prune does), so the token keeps its own.
  161. public function isUploadTokenValid($aToken, $sUploaderObject, $sStorageObject)
  162. {
  163. return !empty($aToken) && is_array($aToken)
  164. && (int)($aToken['profile_id'] ?? 0) > 0
  165. && (int)($aToken['expire'] ?? 0) >= time()
  166. && ($aToken['uo'] ?? '') === $sUploaderObject
  167. && ($aToken['so'] ?? '') === $sStorageObject;
  168. }
  169. }
  170. /** @} */