32 return 'S3 compatible storage';
54 $arSettings = $_POST[
'SETTINGS'][$this->
GetID()];
58 $arSettings = unserialize($arBucket[
'SETTINGS'], [
'allowed_classes' =>
false]);
61 if (!is_array($arSettings))
71 $show = (($cur_SERVICE_ID === $this->
GetID()) || !$bServiceSet) ?
'' :
'none';
72 $useHttps = $arSettings[
'USE_HTTPS'] ??
'N';
75 <tr id="SETTINGS_0_' . $htmlID .
'" style="display:' . $show .
'" class="settings-tr adm-detail-required-field">
76 <td>' .
GetMessage(
'CLO_STORAGE_S3_EDIT_HOST') .
':</td>
77 <td><input type="hidden" name="SETTINGS[' . $htmlID .
'][HOST]" id="' . $htmlID .
'HOST" value="' .
htmlspecialcharsbx($arSettings[
'HOST']) .
'"><input type="text" size="55" name="' . $htmlID .
'INP_HOST" id="' . $htmlID .
'INP_HOST" value="' .
htmlspecialcharsbx($arSettings[
'HOST']) .
'" ' . ($arBucket[
'READ_ONLY'] ==
'Y' ?
'"disabled"' :
'') .
' onchange="BX(\'' . $htmlID .
'HOST\').value = this.value"></td>
79 <tr id="SETTINGS_1_' . $htmlID .
'" style="display:' . $show .
'" class="settings-tr adm-detail-required-field">
80 <td>' .
GetMessage(
'CLO_STORAGE_S3_EDIT_ACCESS_KEY') .
':</td>
81 <td><input type="hidden" name="SETTINGS[' . $htmlID .
'][ACCESS_KEY]" id="' . $htmlID .
'ACCESS_KEY" value="' .
htmlspecialcharsbx($arSettings[
'ACCESS_KEY']) .
'"><input type="text" size="55" name="' . $htmlID .
'INP_ACCESS_KEY" id="' . $htmlID .
'INP_ACCESS_KEY" value="' .
htmlspecialcharsbx($arSettings[
'ACCESS_KEY']) .
'" ' . ($arBucket[
'READ_ONLY'] ===
'Y' ?
'"disabled"' :
'') .
' onchange="BX(\'' . $htmlID .
'ACCESS_KEY\').value = this.value"></td>
83 <tr id="SETTINGS_2_' . $htmlID .
'" style="display:' . $show .
'" class="settings-tr adm-detail-required-field">
84 <td>' .
GetMessage(
'CLO_STORAGE_S3_EDIT_SECRET_KEY') .
':</td>
85 <td><input type="hidden" name="SETTINGS[' . $htmlID .
'][SECRET_KEY]" id="' . $htmlID .
'SECRET_KEY" value="' .
htmlspecialcharsbx($arSettings[
'SECRET_KEY']) .
'"><input type="text" size="55" name="' . $htmlID .
'INP_SECRET_KEY" id="' . $htmlID .
'INP_SECRET_KEY" value="' .
htmlspecialcharsbx($arSettings[
'SECRET_KEY']) .
'" autocomplete="off" ' . ($arBucket[
'READ_ONLY'] ===
'Y' ?
'"disabled"' :
'') .
' onchange="BX(\'' . $htmlID .
'SECRET_KEY\').value = this.value"></td>
87 <tr id="SETTINGS_3_' . $htmlID .
'" style="display:' . $show .
'" class="settings-tr">
88 <td>' .
GetMessage(
'CLO_STORAGE_S3_EDIT_USE_HTTPS') .
':</td>
89 <td><input type="hidden" name="SETTINGS[' . $htmlID .
'][USE_HTTPS]" id="' . $htmlID .
'KEY" value="N"><input type="checkbox" name="SETTINGS[' . $htmlID .
'][USE_HTTPS]" id="' . $htmlID .
'USE_HTTPS" value="Y" ' . ($useHttps ==
'Y' ?
'checked="checked"' :
'') .
'></td>
106 'HOST' => is_array($arSettings) ? trim($arSettings[
'HOST']) :
'',
107 'ACCESS_KEY' => is_array($arSettings) ? trim($arSettings[
'ACCESS_KEY']) :
'',
108 'SECRET_KEY' => is_array($arSettings) ? trim($arSettings[
'SECRET_KEY']) :
'',
109 'USE_HTTPS' => is_array($arSettings) && $arSettings[
'USE_HTTPS'] ==
'Y' ?
'Y' :
'N',
112 if ($arBucket[
'READ_ONLY'] !==
'Y' &&
$result[
'HOST'] ===
'')
115 'id' => $this->
GetID() .
'INP_HOST',
116 'text' =>
GetMessage(
'CLO_STORAGE_S3_EMPTY_HOST'),
120 if ($arBucket[
'READ_ONLY'] !==
'Y' &&
$result[
'ACCESS_KEY'] ===
'')
123 'id' => $this->
GetID() .
'INP_ACCESS_KEY',
124 'text' =>
GetMessage(
'CLO_STORAGE_S3_EMPTY_ACCESS_KEY'),
128 if ($arBucket[
'READ_ONLY'] !==
'Y' &&
$result[
'SECRET_KEY'] ===
'')
131 'id' => $this->
GetID() .
'INP_SECRET_KEY',
132 'text' =>
GetMessage(
'CLO_STORAGE_S3_EMPTY_SECRET_KEY'),
157 if (mb_strlen(
$key) > 64)
161 $key = str_pad(
$key, 64, chr(0x00));
162 $ipad = str_repeat(chr(0x36), 64);
163 $opad = str_repeat(chr(0x5c), 64);
164 $hmac = pack(
'H*', sha1((
$key ^ $opad) . pack(
'H*', sha1((
$key ^ $ipad) .
$data))));
179 public function SignRequest($arSettings, $RequestMethod, $bucket, $RequestURI, $ContentType, $additional_headers,
$params =
'',
$content =
'', $Service =
's3')
184 $hashResource = hash_init(
'sha256');
185 hash_update_stream($hashResource,
$content);
186 $HashedPayload = hash_final($hashResource);
191 $HashedPayload = hash(
'sha256',
$content,
false);
193 $additional_headers[
'x-amz-content-sha256'] = $HashedPayload;
196 $RequestDate = gmdate(
'Ymd', $Time);
197 $RequestTime = gmdate(
'Ymd', $Time) .
'T' . gmdate(
'His', $Time) .
'Z';
198 $additional_headers[
'x-amz-date'] = $RequestTime;
202 $CanonicalizedResource = $RequestURI !==
'' ? str_replace(
'%2F',
'/', $RequestURI) :
'/';
204 while (strpos($CanonicalizedResource,
'%2F') !==
false);
206 $CanonicalQuery = explode(
'&', ltrim(
$params,
'?'));
207 sort($CanonicalQuery);
208 $CanonicalQueryString = str_replace(
'%7E',
'~', implode(
'&', $CanonicalQuery));
210 $CanonicalHeaders = [];
211 foreach ($additional_headers as
$key => $value)
214 if (isset($CanonicalHeaders[
$key]))
216 $CanonicalHeaders[
$key] .=
',';
220 $CanonicalHeaders[
$key] =
$key .
':';
222 $CanonicalHeaders[
$key] .= trim($value,
" \t\n\r");
224 ksort($CanonicalHeaders);
225 $CanonicalHeadersString = implode(
"\n", $CanonicalHeaders);
226 $SignedHeaders = implode(
';', array_keys($CanonicalHeaders));
228 $CanonicalRequest =
'';
229 $CanonicalRequest .= $RequestMethod .
"\n";
230 $CanonicalRequest .= $CanonicalizedResource .
"\n";
231 $CanonicalRequest .= $CanonicalQueryString .
"\n";
232 $CanonicalRequest .= $CanonicalHeadersString .
"\n\n";
233 $CanonicalRequest .= $SignedHeaders .
"\n";
234 $CanonicalRequest .= $HashedPayload;
236 $Algorithm =
'AWS4-HMAC-SHA256';
237 $Region = $this->location ?:
'us-east-1';
238 $Scope = $RequestDate .
'/' . $Region .
'/' . $Service .
'/aws4_request';
241 $StringToSign .= $Algorithm .
"\n";
242 $StringToSign .= $RequestTime .
"\n";
243 $StringToSign .= $Scope .
"\n";
244 $StringToSign .= hash(
'sha256', $CanonicalRequest,
false);
246 $kSecret = $arSettings[
'SECRET_KEY'];
247 $kDate = hash_hmac(
'sha256', $RequestDate,
'AWS4' . $kSecret,
true);
248 $kRegion = hash_hmac(
'sha256', $Region, $kDate,
true);
249 $kService = hash_hmac(
'sha256', $Service, $kRegion,
true);
250 $kSigning = hash_hmac(
'sha256',
'aws4_request', $kService,
true);
252 $Signature = hash_hmac(
'sha256', $StringToSign, $kSigning,
false);
254 $Authorization = $Algorithm .
' Credential=' . $arSettings[
'ACCESS_KEY'] .
'/' . $Scope .
',SignedHeaders=' . $SignedHeaders .
',Signature=' . $Signature;
257 'Date' => $RequestTime,
258 'Authorization' => $Authorization,
259 'x-amz-date' => $RequestTime,
260 'x-amz-content-sha256' => $HashedPayload,
276 $this->location =
'';
287 $this->new_end_point !=
''
288 && preg_match(
'#^(http|https)://' . preg_quote($bucket,
'#') .
'(.+?)/#', $this->new_end_point, $match) > 0
291 return $bucket . $match[2];
297 return $bucket .
'.' . $arSettings[
'HOST'];
301 return $arSettings[
'HOST'];
323 'streamTimeout' => $this->streamTimeout,
325 if (isset($additional_headers[
'option-file-result']))
327 $request->setOutputStream($additional_headers[
'option-file-result']);
330 if (isset($additional_headers[
'Content-Type']))
332 $ContentType = $additional_headers[
'Content-Type'];
336 $ContentType =
$content !==
'' ?
'text/plain' :
'';
338 unset($additional_headers[
'Content-Type']);
340 foreach ($this->set_headers as
$key => $value)
342 $additional_headers[
$key] = $value;
345 if (array_key_exists(
'SESSION_TOKEN', $arSettings))
347 $additional_headers[
'x-amz-security-token'] = $arSettings[
'SESSION_TOKEN'];
357 foreach ($additional_headers as
$key => $value)
359 if (!preg_match(
'/^option-/',
$key))
366 $this->new_end_point =
'';
368 $useHttps = $arSettings[
'USE_HTTPS'] ??
'N';
372 $this->url = ($useHttps ===
'Y' ?
'https' :
'http') .
'://' .
$host . $file_name .
$params;
380 if (defined(
'BX_CLOUDS_TRACE') &&
$verb !==
'GET' &&
$verb !==
'HEAD')
382 $stime = microtime(1);
384 'request_id' => md5((
string)mt_rand()),
389 if (function_exists(
'getmypid'))
391 $logRequest[
'pid'] = getmypid();
396 $request->setHeader(
'Content-type', $ContentType);
399 $this->status =
$request->getStatus();
402 $this->headers[
$key] = is_array($value) ? $value[0] : $value;
404 $this->errstr = implode(
"\n",
$request->getError());
405 $this->errno = $this->errstr ? 255 : 0;
406 $this->result =
$request->getResult();
411 $logRequest[
'time'] = round(microtime(
true) - $stime, 6);
416 if ($this->status == 200)
419 isset($additional_headers[
'option-raw-result'])
420 || isset($additional_headers[
'option--result'])
425 elseif ($this->result !==
'')
428 $text = preg_replace(
'/<' .
'\\?XML.*?\\?' .
'>/i',
'', $this->result);
429 if ($obXML->LoadString(
$text))
431 $arXML = $obXML->GetArray();
432 if (is_array($arXML))
438 $e =
new CApplicationException(
GetMessage(
'CLO_STORAGE_S3_XML_PARSE_ERROR', [
'#errno#' =>
'1']));
450 && isset($this->headers[
'Location'])
451 && $was_end_point ===
''
454 $this->new_end_point = $this->headers[
'Location'];
465 elseif ($this->status > 0)
467 if ($this->result !==
'')
470 if ($obXML->LoadString($this->result))
472 $node = $obXML->SelectNodes(
'/Error/Message');
473 if (is_object($node))
476 $e =
new CApplicationException(
GetMessage(
'CLO_STORAGE_S3_XML_ERROR', [
482 $node = $obXML->SelectNodes(
'/Error/Code');
483 if (is_object($node))
486 $e =
new CApplicationException(
GetMessage(
'CLO_STORAGE_S3_XML_ERROR', [
494 $e =
new CApplicationException(
GetMessage(
'CLO_STORAGE_S3_XML_PARSE_ERROR', [
'#errno#' =>
'2']));
500 $e =
new CApplicationException(
GetMessage(
'CLO_STORAGE_S3_XML_PARSE_ERROR', [
'#errno#' =>
'3']));
517 $arBucket[
'SETTINGS'],
527 && isset(
$response[
'ListAllMyBucketsResult'])
528 && is_array(
$response[
'ListAllMyBucketsResult'])
529 && isset(
$response[
'ListAllMyBucketsResult'][
'#'])
530 && is_array(
$response[
'ListAllMyBucketsResult'][
'#'])
533 $ListAllMyBucketsResult =
$response[
'ListAllMyBucketsResult'][
'#'];
535 isset($ListAllMyBucketsResult[
'Buckets'])
536 && is_array($ListAllMyBucketsResult[
'Buckets'])
537 && isset($ListAllMyBucketsResult[
'Buckets'][0])
538 && is_array($ListAllMyBucketsResult[
'Buckets'][0])
539 && isset($ListAllMyBucketsResult[
'Buckets'][0][
'#'])
540 && is_array($ListAllMyBucketsResult[
'Buckets'][0][
'#'])
543 foreach ($ListAllMyBucketsResult[
'Buckets'][0][
'#'][
'Bucket'] as $Bucket)
545 $Name = $Bucket[
'#'][
'Name'][0][
'#'];
546 $CreationDate = $Bucket[
'#'][
'CreationDate'][0][
'#'];
547 $result[
'bucket'][] = urldecode($Name);
548 $result[
'ctime'][] = strtotime($CreationDate);
554 $this->tokenHasExpired =
true;
559 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
588 && $arBucket[
'LOCATION'] !=
''
596 if ($arBucket[
'LOCATION'] !=
'')
599 '<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'
600 .
'<LocationConstraint>' . $arBucket[
'LOCATION'] .
'</LocationConstraint>'
601 .
'</CreateBucketConfiguration>';
610 $arBucket[
'SETTINGS'],
613 '/' . $arBucket[
'BUCKET'],
618 if ($this->status == 409)
629 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
647 $arBucket[
'SETTINGS'],
650 '/' . $arBucket[
'BUCKET'],
651 '?max-keys=1' . ($arBucket[
'PREFIX'] !=
'' ?
'&prefix=' . $arBucket[
'PREFIX'] .
'/' :
'')
654 if ($this->status == 404 || $this->status == 403)
663 || !is_array(
$response[
'ListBucketResult'])
664 || !isset(
$response[
'ListBucketResult'][
'#'])
665 || !is_array(
$response[
'ListBucketResult'][
'#'])
666 || !isset(
$response[
'ListBucketResult'][
'#'][
'Contents'])
667 || !is_array(
$response[
'ListBucketResult'][
'#'][
'Contents'])
676 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
692 if ($arBucket[
'PREFIX'] !=
'')
706 $arBucket[
'SETTINGS'],
709 '/' . $arBucket[
'BUCKET']
714 || $this->status == 404
715 || $this->status == 403
727 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
741 public function GetFileSRC($arBucket, $arFile, $encoded =
true)
743 if ($arBucket[
'SETTINGS'][
'USE_HTTPS'] ===
'Y')
750 $request = \Bitrix\Main\Context::getCurrent()->getRequest();
751 $proto =
$request->isHttps() ?
'https' :
'http';
754 if ($arBucket[
'CNAME'] !=
'')
756 $host = $arBucket[
'CNAME'];
761 $host = $arBucket[
'SETTINGS'][
'HOST'];
762 $pref = $arBucket[
'BUCKET'];
765 if (is_array($arFile))
767 $URI = ltrim($arFile[
'SUBDIR'] .
'/' . $arFile[
'FILE_NAME'],
'/');
771 $URI = ltrim($arFile,
'/');
774 if ($arBucket[
'PREFIX'] !=
'')
776 if (mb_substr($URI, 0, mb_strlen($arBucket[
'PREFIX']) + 1) !== $arBucket[
'PREFIX'] .
'/')
778 $URI = $arBucket[
'PREFIX'] .
'/' . $URI;
784 $URI = $pref .
'/' . $URI;
793 return $proto .
'://' .
$host .
'/' . $URI;
806 if ($arBucket[
'PREFIX'] !=
'')
808 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
810 $filePath =
'/' . $arBucket[
'PREFIX'] .
'/' . ltrim($filePath,
'/');
817 $arBucket[
'SETTINGS'],
820 '/' . $arBucket[
'BUCKET'] . $filePath
823 if ($this->status == 200)
825 if (isset($this->headers[
'Content-Length']) && $this->headers[
'Content-Length'] > 0)
827 return $this->headers[
'Content-Length'];
834 elseif ($this->status == 206)
841 $this->tokenHasExpired =
true;
851 public function FileCopy($arBucket, $arFile, $filePath)
855 if ($arBucket[
'PREFIX'])
857 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
859 $filePath =
'/' . $arBucket[
'PREFIX'] .
'/' . ltrim($filePath,
'/');
863 $sourcePath =
'/' . $arBucket[
'BUCKET'] .
'/' . ($arBucket[
'PREFIX'] ? $arBucket[
'PREFIX'] .
'/' :
'') . ($arFile[
'SUBDIR'] ? $arFile[
'SUBDIR'] .
'/' :
'') . $arFile[
'FILE_NAME'];
864 $additional_headers = [];
867 $additional_headers[
'x-amz-acl'] =
'public-read';
870 $additional_headers[
'Content-Type'] = $arFile[
'CONTENT_TYPE'];
873 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
874 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
882 $arBucket[
'SETTINGS'],
892 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
893 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
900 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
901 && $this->status == 200
902 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
908 if ($this->status == 200)
910 return $this->
GetFileSRC($arBucket, $filePath);
914 $this->tokenHasExpired =
true;
921 && preg_match(
'/The specified copy source is larger than the maximum allowable size for a copy source: (\d+)/i', $e->GetString(), $match)
924 $sizeLimit = $match[1];
926 $arBucket[
'SETTINGS'],
929 '/' . $arBucket[
'BUCKET'] .
CCloudUtil::URLEncode(
'/' . ($arBucket[
'PREFIX'] ? $arBucket[
'PREFIX'] .
'/' :
'') . ($arFile[
'SUBDIR'] ? $arFile[
'SUBDIR'] .
'/' :
'') . $arFile[
'FILE_NAME'],
'UTF-8',
true)
933 if ($this->status == 200)
935 if (isset($this->headers[
'Content-Length']) && $this->headers[
'Content-Length'] > 0)
937 $fileSize = $this->headers[
'Content-Length'];
943 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
951 $additional_headers = [];
954 $additional_headers[
'x-amz-acl'] =
'public-read';
956 $additional_headers[
'Content-Type'] = $arFile[
'CONTENT_TYPE'];
959 $arBucket[
'SETTINGS'],
971 && isset(
$response[
'InitiateMultipartUploadResult'])
972 && is_array(
$response[
'InitiateMultipartUploadResult'])
973 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'])
974 && is_array(
$response[
'InitiateMultipartUploadResult'][
'#'])
975 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'])
976 && is_array(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'])
977 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0])
978 && is_array(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0])
979 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0][
'#'])
980 && is_string(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0][
'#'])
983 $uploadId =
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0][
'#'];
989 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
998 while ($pos < $fileSize)
1000 $additional_headers = [];
1001 $additional_headers[
'x-amz-copy-source'] =
CCloudUtil::URLEncode(
'/' . $arBucket[
'BUCKET'] .
'/' . ($arBucket[
'PREFIX'] ? $arBucket[
'PREFIX'] .
'/' :
'') . ($arFile[
'SUBDIR'] ? $arFile[
'SUBDIR'] .
'/' :
'') . $arFile[
'FILE_NAME'],
'UTF-8',
true);
1002 $additional_headers[
'x-amz-copy-source-range'] =
'bytes=' . $pos .
'-' . (min($fileSize, $pos + $sizeLimit) - 1);
1005 $arBucket[
'SETTINGS'],
1009 '?partNumber=' . ($part_no + 1) .
'&uploadId=' . rawurlencode($uploadId),
1015 $this->status == 200
1018 && is_array(
$response[
'CopyPartResult'])
1019 && isset(
$response[
'CopyPartResult'][
'#'])
1020 && is_array(
$response[
'CopyPartResult'][
'#'])
1021 && isset(
$response[
'CopyPartResult'][
'#'][
'ETag'])
1022 && is_array(
$response[
'CopyPartResult'][
'#'][
'ETag'])
1023 && isset(
$response[
'CopyPartResult'][
'#'][
'ETag'][0])
1024 && is_array(
$response[
'CopyPartResult'][
'#'][
'ETag'][0])
1025 && isset(
$response[
'CopyPartResult'][
'#'][
'ETag'][0][
'#'])
1026 && is_string(
$response[
'CopyPartResult'][
'#'][
'ETag'][0][
'#'])
1029 $parts[$part_no] = trim(
$response[
'CopyPartResult'][
'#'][
'ETag'][0][
'#'],
'"');
1034 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1046 foreach ($parts as $PartNumber => $ETag)
1048 $data .=
'<Part><PartNumber>' . ($PartNumber + 1) .
'</PartNumber><ETag>' . $ETag .
"</ETag></Part>\n";
1052 $arBucket[
'SETTINGS'],
1056 '?uploadId=' . rawurlencode($uploadId),
1057 '<CompleteMultipartUpload>' .
$data .
'</CompleteMultipartUpload>'
1060 if ($this->status == 200)
1062 return $this->
GetFileSRC($arBucket, $filePath);
1066 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1075 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1087 if ($arBucket[
'PREFIX'])
1089 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1091 $filePath =
'/' . $arBucket[
'PREFIX'] .
'/' . ltrim($filePath,
'/');
1098 $arBucket[
'SETTINGS'],
1101 '/' . $arBucket[
'BUCKET'] . $filePath
1105 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1106 && $this->status == 204
1107 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1113 if ($this->status == 204)
1120 $this->tokenHasExpired =
true;
1126 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1134 public function SaveFile($arBucket, $filePath, $arFile)
1138 if ($arBucket[
'PREFIX'])
1140 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1142 $filePath =
'/' . $arBucket[
'PREFIX'] .
'/' . ltrim($filePath,
'/');
1147 $additional_headers = [];
1150 $additional_headers[
'x-amz-acl'] =
'public-read';
1152 $additional_headers[
'Content-Type'] = $arFile[
'type'];
1153 $additional_headers[
'Content-Length'] = (array_key_exists(
'content', $arFile) ? strlen($arFile[
'content']) : filesize($arFile[
'tmp_name']));
1156 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1157 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1165 $arBucket[
'SETTINGS'],
1168 '/' . $arBucket[
'BUCKET'] . $filePath,
1170 $arFile[
'content'] ?? fopen($arFile[
'tmp_name'],
'rb'),
1175 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1176 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1183 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1184 && $this->status == 200
1185 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1191 if ($this->status == 200)
1197 $this->tokenHasExpired =
true;
1200 elseif ($this->status == 403)
1202 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1211 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1221 static $search = [
'%7E'];
1222 static $replace = [
'~'];
1232 $filePath = trim($filePath,
'/');
1233 if ($filePath !==
'')
1238 if ($arBucket[
'PREFIX'])
1240 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1242 $filePath = $arBucket[
'PREFIX'] .
'/' . ltrim($filePath,
'/');
1247 $marker =
$pageSize > 0 ? $filePath . $pageMarker :
'';
1251 $arBucket[
'SETTINGS'],
1254 '/' . $arBucket[
'BUCKET'],
1255 '?' . ($bRecursive ?
'' :
'delimiter=%2F&') .
'prefix=' . str_replace($search, $replace, rawurlencode($filePath))
1256 .
'&marker=' . rawurlencode($marker)
1260 $this->status == 200
1263 && is_array(
$response[
'ListBucketResult'])
1264 && isset(
$response[
'ListBucketResult'][
'#'])
1265 && is_array(
$response[
'ListBucketResult'][
'#'])
1269 isset(
$response[
'ListBucketResult'][
'#'][
'CommonPrefixes'])
1270 && is_array(
$response[
'ListBucketResult'][
'#'][
'CommonPrefixes'])
1273 foreach (
$response[
'ListBucketResult'][
'#'][
'CommonPrefixes'] as
$a)
1275 $dir_name = mb_substr(rtrim(
$a[
'#'][
'Prefix'][0][
'#'],
'/'), mb_strlen($filePath));
1282 isset(
$response[
'ListBucketResult'][
'#'][
'Contents'])
1283 && is_array(
$response[
'ListBucketResult'][
'#'][
'Contents'])
1286 foreach (
$response[
'ListBucketResult'][
'#'][
'Contents'] as
$a)
1288 $file_name = mb_substr(
$a[
'#'][
'Key'][0][
'#'], mb_strlen($filePath));
1289 if ($file_name !==
'' && mb_substr($file_name, -1) !==
'/')
1291 $result[
'file'][] = $file_name;
1292 $result[
'file_size'][] =
$a[
'#'][
'Size'][0][
'#'];
1293 $result[
'file_mtime'][] = mb_substr(
$a[
'#'][
'LastModified'][0][
'#'], 0, 19);
1294 $result[
'file_hash'][] = trim(
$a[
'#'][
'ETag'][0][
'#'],
'"');
1295 $result[
'last_key'] = $file_name;
1296 $lastKey =
$a[
'#'][
'Key'][0][
'#'];
1306 isset(
$response[
'ListBucketResult'][
'#'][
'IsTruncated'])
1307 && is_array(
$response[
'ListBucketResult'][
'#'][
'IsTruncated'])
1308 &&
$response[
'ListBucketResult'][
'#'][
'IsTruncated'][0][
'#'] ===
'true'
1311 if (
$response[
'ListBucketResult'][
'#'][
'NextMarker'][0][
'#'] <>
'')
1313 $marker =
$response[
'ListBucketResult'][
'#'][
'NextMarker'][0][
'#'];
1316 elseif ($lastKey !==
null)
1327 $this->tokenHasExpired =
true;
1332 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1347 if ($arBucket[
'PREFIX'] !=
'')
1349 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1351 $filePath =
'/' . $arBucket[
'PREFIX'] .
'/' . ltrim($filePath,
'/');
1358 $arBucket[
'SETTINGS'],
1361 '/' . $arBucket[
'BUCKET'] . $filePath
1364 if ($this->status == 200)
1367 foreach ($this->headers as
$name => $value)
1370 if (
$name ===
'content-length')
1376 $result[
'hash'] = trim($value,
'"');
1380 $ts = strtotime($value);
1381 $result[
'mtime'] = mb_substr(gmdate(
'c', $ts), 0, 19);
1389 $this->tokenHasExpired =
true;
1401 $filePath =
'/' . trim($filePath,
'/');
1402 if ($arBucket[
'PREFIX'])
1404 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1406 $filePath =
'/' . $arBucket[
'PREFIX'] . $filePath;
1411 $additional_headers = [];
1414 $additional_headers[
'x-amz-acl'] =
'public-read';
1416 $additional_headers[
'Content-Type'] = $ContentType;
1420 $arBucket[
'SETTINGS'],
1423 '/' . $arBucket[
'BUCKET'] . $filePathU,
1430 $this->status == 200
1432 && isset(
$response[
'InitiateMultipartUploadResult'])
1433 && is_array(
$response[
'InitiateMultipartUploadResult'])
1434 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'])
1435 && is_array(
$response[
'InitiateMultipartUploadResult'][
'#'])
1436 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'])
1437 && is_array(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'])
1438 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0])
1439 && is_array(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0])
1440 && isset(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0][
'#'])
1441 && is_string(
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0][
'#'])
1445 'filePath' => $filePath,
1446 'UploadId' =>
$response[
'InitiateMultipartUploadResult'][
'#'][
'UploadId'][0][
'#'],
1453 $this->tokenHasExpired =
true;
1458 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1468 return BX_S3_MIN_UPLOAD_PART_SIZE;
1473 $filePath =
'/' . trim(
$NS[
'filePath'],
'/');
1474 if ($arBucket[
'PREFIX'])
1476 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1478 $filePath =
'/' . $arBucket[
'PREFIX'] . $filePath;
1485 $arBucket[
'SETTINGS'],
1488 '/' . $arBucket[
'BUCKET'] . $filePath,
1489 '?partNumber=' . ($part_no + 1) .
'&uploadId=' . rawurlencode(
$NS[
'UploadId']),
1493 if ($this->status == 200 && is_array($this->headers))
1495 foreach ($this->headers as
$key => $value)
1497 if (mb_strtolower(
$key) ===
'etag')
1499 $NS[
'Parts'][$part_no] = $value;
1505 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1530 $filePath =
'/' . trim(
$NS[
'filePath'],
'/');
1531 if ($arBucket[
'PREFIX'])
1533 if (mb_substr($filePath, 0, mb_strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1535 $filePath =
'/' . $arBucket[
'PREFIX'] . $filePath;
1540 ksort(
$NS[
'Parts']);
1542 foreach (
$NS[
'Parts'] as $PartNumber => $ETag)
1544 $data .=
'<Part><PartNumber>' . ($PartNumber + 1) .
'</PartNumber><ETag>' . $ETag .
"</ETag></Part>\n";
1548 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1549 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1557 $arBucket[
'SETTINGS'],
1560 '/' . $arBucket[
'BUCKET'] . $filePath,
1561 '?uploadId=' . rawurlencode(
$NS[
'UploadId']),
1562 '<CompleteMultipartUpload>' .
$data .
'</CompleteMultipartUpload>'
1566 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1567 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1574 defined(
'BX_CLOUDS_COUNTERS_DEBUG')
1575 && $this->status == 200
1576 && !preg_match(constant(
'BX_CLOUDS_COUNTERS_DEBUG'), $filePath)
1582 if ($this->status == 200)
1588 if (defined(
'BX_CLOUDS_ERROR_DEBUG'))
1603 $filePath =
'/' . trim(
$NS[
'filePath'],
'/');
1604 if ($arBucket[
'PREFIX'])
1606 if (substr($filePath, 0, strlen($arBucket[
'PREFIX']) + 2) !==
'/' . $arBucket[
'PREFIX'] .
'/')
1608 $filePath =
'/' . $arBucket[
'PREFIX'] . $filePath;
1613 if (
$NS[
'UploadId'])
1617 $arBucket[
'SETTINGS'],
1620 '/' . $arBucket[
'BUCKET'] . $filePath,
1621 '?uploadId=' . rawurlencode(
$NS[
'UploadId']),
1633 $this->_public = $state !==
false;
1643 $this->set_headers[
$name] = $value;
1652 unset($this->set_headers[
$name]);
1662 if (
$status == 400 && mb_strpos(
$result,
'ExpiredToken') !==
false)
1666 if (
$status == 400 && mb_strpos(
$result,
'token is malformed') !==
false)
1674 if (
$status == 403 && mb_strpos(
$result,
'The AWS Access Key Id you provided does not exist in our records.') !==
false)
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
DeleteFile($arBucket, $filePath)
GetRequestHost($bucket, $arSettings)
checkForTokenExpiration($status, $result)
GetFileInfo($arBucket, $filePath)
InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType)
FileExists($arBucket, $filePath)
UploadPart($arBucket, &$NS, $data)
ListFiles($arBucket, $filePath, $bRecursive=false, $pageSize=0, $pageMarker='')
GetFileSRC($arBucket, $arFile, $encoded=true)
FileCopy($arBucket, $arFile, $filePath)
UploadPartNo($arBucket, &$NS, $data, $part_no)
CompleteMultipartUpload($arBucket, &$NS)
SendRequest($arSettings, $verb, $bucket, $file_name='/', $params='', $content='', $additional_headers=[])
SaveFile($arBucket, $filePath, $arFile)
CancelMultipartUpload($arBucket, &$NS)
SignRequest($arSettings, $RequestMethod, $bucket, $RequestURI, $ContentType, $additional_headers, $params='', $content='', $Service='s3')
CheckSettings($arBucket, &$arSettings)
GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm)
GetLastRequestHeader($headerName)
static URLEncode($str, $charset, $file_name=false)
static getInstance($action='counters')
while($arParentIBlockProperty=$dbParentIBlockProperty->Fetch()) $errorMessage
$_SERVER["DOCUMENT_ROOT"]
if(!defined('NOT_CHECK_PERMISSIONS')) $NS
AddMessage2Log($text, $module='', $traceDepth=6, $showArgs=false)
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
GetMessage($name, $aReplace=null)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']