1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
storage_service_openstack.php
См. документацию.
1<?php
3
5{
6 public function GetObject()
7 {
9 }
10
11 public function GetID()
12 {
13 return 'openstack_storage';
14 }
15
16 public function GetName()
17 {
18 return 'OpenStack Object Storage';
19 }
20
21 public function GetLocationList()
22 {
23 return [
24 '' => 'N/A',
25 ];
26 }
27
28 public function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm)
29 {
31 {
32 $arSettings = $_POST['SETTINGS'][$this->GetID()];
33 }
34 else
35 {
36 $arSettings = unserialize($arBucket['SETTINGS'], ['allowed_classes' => false]);
37 }
38
39 if (!is_array($arSettings))
40 {
41 $arSettings = [
42 'HOST' => '',
43 'USER' => '',
44 'KEY' => '',
45 'FORCE_HTTP' => 'N',
46 ];
47 }
48
49 $htmlID = htmlspecialcharsbx($this->GetID());
50 $show = (($cur_SERVICE_ID == $this->GetID()) || !$bServiceSet) ? '' : 'none';
51
52 $result = '
53 <tr id="SETTINGS_2_' . $htmlID . '" style="display:' . $show . '" class="settings-tr adm-detail-required-field">
54 <td>' . GetMessage('CLO_STORAGE_OPENSTACK_EDIT_HOST') . ':</td>
55 <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>
56 </tr>
57 <tr id="SETTINGS_0_' . $htmlID . '" style="display:' . $show . '" class="settings-tr adm-detail-required-field">
58 <td>' . GetMessage('CLO_STORAGE_OPENSTACK_EDIT_USER') . ':</td>
59 <td><input type="hidden" name="SETTINGS[' . $htmlID . '][USER]" id="' . $htmlID . 'USER" value="' . htmlspecialcharsbx($arSettings['USER']) . '"><input type="text" size="55" name="' . $htmlID . 'INP_" id="' . $htmlID . 'INP_USER" value="' . htmlspecialcharsbx($arSettings['USER']) . '" ' . ($arBucket['READ_ONLY'] == 'Y' ? '"disabled"' : '') . ' onchange="BX(\'' . $htmlID . 'USER\').value = this.value"></td>
60 </tr>
61 <tr id="SETTINGS_1_' . $htmlID . '" style="display:' . $show . '" class="settings-tr adm-detail-required-field">
62 <td>' . GetMessage('CLO_STORAGE_OPENSTACK_EDIT_KEY') . ':</td>
63 <td><input type="hidden" name="SETTINGS[' . $htmlID . '][KEY]" id="' . $htmlID . 'KEY" value="' . htmlspecialcharsbx($arSettings['KEY']) . '"><input type="text" size="55" name="' . $htmlID . 'INP_KEY" id="' . $htmlID . 'INP_KEY" value="' . htmlspecialcharsbx($arSettings['KEY']) . '" autocomplete="off" ' . ($arBucket['READ_ONLY'] == 'Y' ? '"disabled"' : '') . ' onchange="BX(\'' . $htmlID . 'KEY\').value = this.value"></td>
64 </tr>
65 <tr id="SETTINGS_3_' . $htmlID . '" style="display:' . $show . '" class="settings-tr">
66 <td>' . GetMessage('CLO_STORAGE_OPENSTACK_FORCE_HTTP') . ':</td>
67 <td><input type="hidden" name="SETTINGS[' . $htmlID . '][FORCE_HTTP]" id="' . $htmlID . 'KEY" value="N"><input type="checkbox" name="SETTINGS[' . $htmlID . '][FORCE_HTTP]" id="' . $htmlID . 'FORCE_HTTP" value="Y" ' . ($arSettings['FORCE_HTTP'] == 'Y' ? 'checked="checked"' : '') . '></td>
68 </tr>
69 ';
70 return $result;
71 }
72
73 public function CheckSettings($arBucket, &$arSettings)
74 {
75 global $APPLICATION;
76 $aMsg = [];
77
78 $result = [
79 'HOST' => is_array($arSettings) ? trim($arSettings['HOST']) : '',
80 'USER' => is_array($arSettings) ? trim($arSettings['USER']) : '',
81 'KEY' => is_array($arSettings) ? trim($arSettings['KEY']) : '',
82 'FORCE_HTTP' => is_array($arSettings) && $arSettings['FORCE_HTTP'] == 'Y' ? 'Y' : 'N',
83 ];
84
85 if ($arBucket['READ_ONLY'] !== 'Y' && !mb_strlen($result['HOST']))
86 {
87 $aMsg[] = ['id' => $this->GetID() . 'INP_HOST', 'text' => GetMessage('CLO_STORAGE_OPENSTACK_EMPTY_HOST')];
88 }
89
90 if ($arBucket['READ_ONLY'] !== 'Y' && !mb_strlen($result['USER']))
91 {
92 $aMsg[] = ['id' => $this->GetID() . 'INP_USER', 'text' => GetMessage('CLO_STORAGE_OPENSTACK_EMPTY_USER')];
93 }
94
95 if ($arBucket['READ_ONLY'] !== 'Y' && !mb_strlen($result['KEY']))
96 {
97 $aMsg[] = ['id' => $this->GetID() . 'INP_KEY', 'text' => GetMessage('CLO_STORAGE_OPENSTACK_EMPTY_KEY')];
98 }
99
100 if (empty($aMsg))
101 {
102 if (!$this->_GetToken($result['HOST'], $result['USER'], $result['KEY']))
103 {
104 $aMsg[] = ['text' => GetMessage('CLO_STORAGE_OPENSTACK_ERROR_GET_TOKEN')];
105 }
106 }
107
108 if (!empty($aMsg))
109 {
110 $e = new CAdminException($aMsg);
111 $APPLICATION->ThrowException($e);
112 return false;
113 }
114 else
115 {
116 $arSettings = $result;
117 }
118
119 return true;
120 }
121
122 public function _GetToken($host, $user, $key)
123 {
124 global $APPLICATION;
125 static $results = [];
126 $cache_id = 'v0|' . $host . '|' . $user . '|' . $key;
127
128 if (array_key_exists($cache_id, $results))
129 {
130 $result = $results[$cache_id];
131 }
132 else
133 {
134 $result = false;
135 $obCache = new CPHPCache;
136
137 if ($obCache->InitCache(600, $cache_id, '/')) /*TODO make setting*/
138 {
139 $result = $obCache->GetVars();
140 }
141 else
142 {
143 $this->status = 0;
144 $this->host = $host;
145 $this->verb = 'GET';
146 $this->url = 'http://' . $host . '/v1.0';
147 $this->headers = [];
148 $this->errno = 0;
149 $this->errstr = '';
150 $this->result = '';
151
152 $stime = 0;
153 $logRequest = false;
154 if (defined('BX_CLOUDS_TRACE') && $this->verb !== 'GET' && $this->verb !== 'HEAD')
155 {
156 $stime = microtime(1);
157 $logRequest = [
158 'request_id' => md5((string)mt_rand()),
159 'portal' => $_SERVER['HTTP_HOST'],
160 'verb' => $this->verb,
161 'url' => $this->url,
162 ];
163 AddMessage2Log(json_encode($logRequest), 'clouds', 20);
164 }
165
167 'redirect' => false,
168 'streamTimeout' => $this->streamTimeout,
169 ]);
170 $request->setHeader('X-Auth-User', $user);
171 $request->setHeader('X-Auth-Key', $key);
172 $request->query($this->verb, $this->url);
173
174 $this->status = $request->getStatus();
175 foreach ($request->getHeaders() as $headerKey => $headerValue)
176 {
177 $this->headers[$headerKey] = is_array($headerValue) ? $headerValue[0] : $headerValue;
178 }
179 $this->errstr = implode("\n", $request->getError());
180 $this->errno = $this->errstr ? 255 : 0;
181 $this->result = $request->getResult();
182
183 if ($logRequest)
184 {
185 $logRequest['status'] = $this->status;
186 $logRequest['time'] = round(microtime(true) - $stime, 6);
187 $logRequest['headers'] = $this->headers;
188 AddMessage2Log(json_encode($logRequest), 'clouds', 0);
189 }
190
191 if ($this->status == 412)
192 {
193 $APPLICATION->ResetException();
194
195 $this->status = 0;
196 $this->host = $host;
197 $this->verb = 'GET';
198 $this->url = 'http://' . $host . '/auth/v1.0';
199 $this->headers = [];
200 $this->errno = 0;
201 $this->errstr = '';
202 $this->result = '';
203
204 $logRequest = false;
205 if (defined('BX_CLOUDS_TRACE') && $this->verb !== 'GET' && $this->verb !== 'HEAD')
206 {
207 $stime = microtime(1);
208 $logRequest = [
209 'request_id' => md5((string)mt_rand()),
210 'portal' => $_SERVER['HTTP_HOST'],
211 'verb' => $this->verb,
212 'url' => $this->url,
213 ];
214 AddMessage2Log(json_encode($logRequest), 'clouds', 20);
215 }
216
218 'redirect' => false,
219 'streamTimeout' => $this->streamTimeout,
220 ]);
221 $request->setHeader('X-Auth-User', $user);
222 $request->setHeader('X-Auth-Key', $key);
223 $request->query($this->verb, $this->url);
224
225 $this->status = $request->getStatus();
226 foreach ($request->getHeaders() as $headerKey => $headerValue)
227 {
228 $this->headers[$headerKey] = is_array($headerValue) ? $headerValue[0] : $headerValue;
229 }
230 $this->errstr = implode("\n", $request->getError());
231 $this->errno = $this->errstr ? 255 : 0;
232 $this->result = $request->getResult();
233
234 if ($logRequest)
235 {
236 $logRequest['status'] = $this->status;
237 $logRequest['time'] = round(microtime(true) - $stime, 6);
238 $logRequest['headers'] = $this->headers;
239 AddMessage2Log(json_encode($logRequest), 'clouds', 0);
240 }
241 }
242
243 if ($this->status == 204 || $this->status == 200)
244 {
245 $arStorage = [];
246 if (preg_match('#^http://(.*?)(|:\d+)(/.*)$#', $this->headers['X-Storage-Url'], $arStorage))
247 {
249 $result['X-Storage-NoProtoUrl'] = $arStorage[1] . ($arStorage[2] === ':80' ? '' : $arStorage[2]) . $arStorage[3];
250 $result['X-Storage-Host'] = $arStorage[1];
251 $result['X-Storage-Port'] = $arStorage[2] ? mb_substr($arStorage[2], 1) : 80;
252 $result['X-Storage-Urn'] = $arStorage[3];
253 $result['X-Storage-Proto'] = '';
254 }
255 }
256 }
257
258 if (is_array($result))
259 {
260 if ($obCache->StartDataCache())
261 {
262 $obCache->EndDataCache($result);
263 }
264 }
265
266 $results[$cache_id] = $result;
267 }
268
269 return $result;
270 }
271
272 public function SendRequest($settings, $verb, $bucket, $file_name='', $params='', $content=false, $additional_headers=[])
273 {
274 $arToken = $this->_GetToken($settings['HOST'], $settings['USER'], $settings['KEY']);
275 if (!$arToken)
276 {
277 return false;
278 }
279
281 'redirect' => false,
282 'streamTimeout' => $this->streamTimeout,
283 ]);
284 if (isset($additional_headers['option-file-result']))
285 {
286 $request->setOutputStream($additional_headers['option-file-result']);
287 }
288
289 $RequestURI = $file_name;
290
291 $ContentType = 'N';
292 $request->setHeader('X-Auth-Token', $arToken['X-Auth-Token']);
293 foreach ($additional_headers as $key => $value)
294 {
295 if ($key == 'Content-Type')
296 {
297 $ContentType = $value;
298 }
299 else
300 {
301 $request->setHeader($key, $value);
302 }
303 }
304
305 $this->status = 0;
306 $this->host = $arToken['X-Storage-Host'];
307 $this->port = $arToken['X-Storage-Port'];
308 $this->verb = $verb;
309 $this->url = rtrim($arToken['X-Storage-Url'], '/') . '/' . $bucket . $RequestURI . $params;
310 $this->headers = [];
311 $this->errno = 0;
312 $this->errstr = '';
313 $this->result = '';
314
315 $stime = 0;
316 $logRequest = false;
317 if (defined('BX_CLOUDS_TRACE') && $this->verb !== 'GET' && $this->verb !== 'HEAD')
318 {
319 $stime = microtime(1);
320 $logRequest = [
321 'request_id' => md5((string)mt_rand()),
322 'portal' => $_SERVER['HTTP_HOST'],
323 'verb' => $this->verb,
324 'url' => $this->url,
325 ];
326 AddMessage2Log(json_encode($logRequest), 'clouds', 20);
327 }
328
329 $request->setHeader('Content-type', $ContentType);
330 $request->query($this->verb, $this->url, $content);
331
332 $this->status = $request->getStatus();
333 foreach ($request->getHeaders() as $key => $value)
334 {
335 $this->headers[$key] = is_array($value) ? $value[0] : $value;
336 }
337 $this->errstr = implode("\n", $request->getError());
338 $this->errno = $this->errstr ? 255 : 0;
339 $this->result = $request->getResult();
340
341 if ($logRequest)
342 {
343 $logRequest['status'] = $this->status;
344 $logRequest['time'] = round(microtime(true) - $stime, 6);
345 $logRequest['headers'] = $this->headers;
346 AddMessage2Log(json_encode($logRequest), 'clouds', 0);
347 }
348
349 return $request;
350 }
351
352 public function CreateBucket($arBucket)
353 {
354 $this->SendRequest(
355 $arBucket['SETTINGS'],
356 'PUT',
357 $arBucket['BUCKET'],
358 '', //filename
359 '', //params
360 false, //content
361 [
362 'X-Container-Read' => '.r:*',
363 'X-Container-Meta-Web-Listings' => 'false',
364 'X-Container-Meta-Type' => 'public',
365 ]
366 );
367
368 return ($this->status == 201)/*Created*/ || ($this->status == 202) /*Accepted*/;
369 }
370
371 public function DeleteBucket($arBucket)
372 {
373 if ($arBucket['PREFIX'])
374 {
375 //Do not delete bucket if there is some files left
376 if (!$this->IsEmptyBucket($arBucket))
377 {
378 return false;
379 }
380
381 //Do not delete bucket if there is some files left in other prefixes
382 $arAllBucket = $arBucket;
383 $arBucket['PREFIX'] = '';
384 if (!$this->IsEmptyBucket($arAllBucket))
385 {
386 return true;
387 }
388 }
389
390 $this->SendRequest(
391 $arBucket['SETTINGS'],
392 'DELETE',
393 $arBucket['BUCKET']
394 );
395
396 if (
397 $this->status == 204/*No Content*/
398 || $this->status == 404/*Not Found*/
399 )
400 {
401 return true;
402 }
403 else
404 {
405 return false;
406 }
407 }
408
409 public function IsEmptyBucket($arBucket)
410 {
411 $this->SendRequest(
412 $arBucket['SETTINGS'],
413 'GET',
414 $arBucket['BUCKET'],
415 '',
416 '?limit=1&format=xml' . ($arBucket['PREFIX'] ? '&prefix=' . $arBucket['PREFIX'] : '')
417 );
418
419 $arXML = false;
420 if ($this->status && $this->result)
421 {
422 $obXML = new CDataXML;
423 $text = preg_replace('/<' . '\\?XML.*?\\?' . '>/i', '', $this->result);
424 if ($obXML->LoadString($text))
425 {
426 $arXML = $obXML->GetArray();
427 }
428 }
429
430 if ($this->status == 404)
431 {
432 return true;
433 }
434 elseif (is_array($arXML))
435 {
436 return
437 !isset($arXML['container'])
438 || !is_array($arXML['container'])
439 || !isset($arXML['container']['#'])
440 || !is_array($arXML['container']['#'])
441 || !isset($arXML['container']['#']['object'])
442 || !is_array($arXML['container']['#']['object']);
443 }
444 else
445 {
446 return false;
447 }
448 }
449
456 public function GetFileSRC($arBucket, $arFile, $encoded = true)
457 {
458 $forceHttp = $arBucket['SETTINGS']['FORCE_HTTP'] ?? 'N';
459 if ($forceHttp === 'Y')
460 {
461 $proto = 'http';
462 }
463 else
464 {
465 /* @var \Bitrix\Main\HttpRequest $request */
466 $request = \Bitrix\Main\Context::getCurrent()->getRequest();
467 $proto = $request->isHttps() ? 'https' : 'http';
468 }
469
470 if ($arBucket['CNAME'])
471 {
472 $host = $proto . '://' . $arBucket['CNAME'];
473 }
474 else
475 {
476 $arToken = $this->_GetToken(
477 $arBucket['SETTINGS']['HOST'],
478 $arBucket['SETTINGS']['USER'],
479 $arBucket['SETTINGS']['KEY']
480 );
481
482 if (is_array($arToken))
483 {
484 if ($arToken['X-Storage-NoProtoUrl'])
485 {
486 $host = $proto . '://' . $arToken['X-Storage-NoProtoUrl'] . '/' . $arBucket['BUCKET'];
487 }
488 else
489 {
490 $host = $arToken['X-Storage-Url'] . '/' . $arBucket['BUCKET'];
491 }
492 }
493 else
494 {
495 return '/404.php';
496 }
497 }
498
499 if (is_array($arFile))
500 {
501 $URI = ltrim($arFile['SUBDIR'] . '/' . $arFile['FILE_NAME'], '/');
502 }
503 else
504 {
505 $URI = ltrim($arFile, '/');
506 }
507
508 if ($arBucket['PREFIX'])
509 {
510 if (mb_substr($URI, 0, mb_strlen($arBucket['PREFIX']) + 1) !== $arBucket['PREFIX'] . '/')
511 {
512 $URI = $arBucket['PREFIX'] . '/' . $URI;
513 }
514 }
515
516 if ($encoded)
517 {
518 return $host . '/' . CCloudUtil::URLEncode($URI, 'UTF-8', true);
519 }
520 else
521 {
522 return $host . '/' . $URI;
523 }
524 }
525
526 public function FileExists($arBucket, $filePath)
527 {
528 global $APPLICATION;
529
530 if ($arBucket['PREFIX'])
531 {
532 if (mb_substr($filePath, 0, mb_strlen($arBucket['PREFIX']) + 2) !== '/' . $arBucket['PREFIX'] . '/')
533 {
534 $filePath = '/' . $arBucket['PREFIX'] . '/' . ltrim($filePath, '/');
535 }
536 }
537 $filePath = CCloudUtil::URLEncode($filePath, 'UTF-8', true);
538
539 $this->SendRequest(
540 $arBucket['SETTINGS'],
541 'HEAD',
542 $arBucket['BUCKET'],
543 $filePath
544 );
545
546 if ($this->status == 200)
547 {
548 if (isset($this->headers['Content-Length']) && $this->headers['Content-Length'] > 0)
549 {
550 return $this->headers['Content-Length'];
551 }
552 else
553 {
554 return true;
555 }
556 }
557 elseif ($this->status == 206)
558 {
559 $APPLICATION->ResetException();
560 return true;
561 }
562 else//if($this->status == 404)
563 {
564 $APPLICATION->ResetException();
565 return false;
566 }
567 }
568
569 public function FileCopy($arBucket, $arFile, $filePath)
570 {
571 if ($arBucket['PREFIX'])
572 {
573 if (mb_substr($filePath, 0, mb_strlen($arBucket['PREFIX']) + 2) !== '/' . $arBucket['PREFIX'] . '/')
574 {
575 $filePath = '/' . $arBucket['PREFIX'] . '/' . ltrim($filePath, '/');
576 }
577 }
578 $fileSource = CCloudUtil::URLEncode('/' . $arBucket['BUCKET'] . '/' . ($arBucket['PREFIX'] ? $arBucket['PREFIX'] . '/' : '') . ($arFile['SUBDIR'] ? $arFile['SUBDIR'] . '/' : '') . $arFile['FILE_NAME'], 'UTF-8', true);
579
580 $this->SendRequest(
581 $arBucket['SETTINGS'],
582 'PUT',
583 $arBucket['BUCKET'],
584 CCloudUtil::URLEncode($filePath, 'UTF-8', true),
585 '',
586 false,
587 [
588 'X-Copy-From' => $fileSource,
589 'Content-Type' => $arFile['CONTENT_TYPE'],
590 ]
591 );
592
593 if ($this->status == 200 || $this->status == 201)
594 {
595 return $this->GetFileSRC($arBucket, $filePath);
596 }
597 else
598 {
599 return false;
600 }
601 }
602
603 public function DeleteFile($arBucket, $filePath)
604 {
605 global $APPLICATION;
606
607 if ($arBucket['PREFIX'])
608 {
609 if (mb_substr($filePath, 0, mb_strlen($arBucket['PREFIX']) + 2) !== '/' . $arBucket['PREFIX'] . '/')
610 {
611 $filePath = '/' . $arBucket['PREFIX'] . '/' . ltrim($filePath, '/');
612 }
613 }
614 $filePath = CCloudUtil::URLEncode($filePath, 'UTF-8', true);
615
616 $this->SendRequest(
617 $arBucket['SETTINGS'],
618 'DELETE',
619 $arBucket['BUCKET'],
620 $filePath
621 );
622
623 //Try to fix space in the path
624 if ($this->status == 404 && mb_strpos($filePath, '+') !== false)
625 {
626 $filePath = str_replace('+', '%20', $filePath);
627 $this->SendRequest(
628 $arBucket['SETTINGS'],
629 'DELETE',
630 $arBucket['BUCKET'],
631 $filePath
632 );
633 }
634
635 if ($this->status == 204 || $this->status == 404)
636 {
637 $APPLICATION->ResetException();
638 return true;
639 }
640 else
641 {
642 $APPLICATION->ResetException();
643 return false;
644 }
645 }
646
647 public function SaveFile($arBucket, $filePath, $arFile)
648 {
649 if ($arBucket['PREFIX'])
650 {
651 if (mb_substr($filePath, 0, mb_strlen($arBucket['PREFIX']) + 2) !== '/' . $arBucket['PREFIX'] . '/')
652 {
653 $filePath = '/' . $arBucket['PREFIX'] . '/' . ltrim($filePath, '/');
654 }
655 }
656 $filePath = CCloudUtil::URLEncode($filePath, 'UTF-8', true);
657
658 if (array_key_exists('content', $arFile))
659 {
660 $this->SendRequest(
661 $arBucket['SETTINGS'],
662 'PUT',
663 $arBucket['BUCKET'],
664 $filePath,
665 '',
666 $arFile['content'],
667 [
668 'Content-Type' => $arFile['type'],
669 'Content-Length' => strlen($arFile['content']),
670 ]
671 );
672 }
673 else
674 {
675 $this->SendRequest(
676 $arBucket['SETTINGS'],
677 'PUT',
678 $arBucket['BUCKET'],
679 $filePath,
680 '',
681 fopen($arFile['tmp_name'], 'rb'),
682 [
683 'Content-Type' => $arFile['type'],
684 'Content-Length' => filesize($arFile['tmp_name']),
685 ]
686 );
687 }
688
689 if ($this->status == 201)
690 {
691 return true;
692 }
693 else
694 {
695 return false;
696 }
697 }
698
699 public function ListFiles($arBucket, $filePath, $bRecursive = false)
700 {
701 $result = [
702 'dir' => [],
703 'file' => [],
704 'file_size' => [],
705 'file_mtime' => [],
706 'file_hash' => [],
707 'last_key' => '',
708 ];
709
710 $filePath = trim($filePath, '/');
711 if ($filePath !== '')
712 {
713 $filePath .= '/';
714 }
715
716 if ($arBucket['PREFIX'])
717 {
718 if (mb_substr($filePath, 0, mb_strlen($arBucket['PREFIX']) + 2) !== '/' . $arBucket['PREFIX'] . '/')
719 {
720 $filePath = $arBucket['PREFIX'] . '/' . ltrim($filePath, '/');
721 }
722 }
723 $filePath = str_replace(' ', '+', $filePath);
724
725 $marker = '';
726 $new_marker = false;
727 while (true)
728 {
729 $this->SendRequest(
730 $arBucket['SETTINGS'],
731 'GET',
732 $arBucket['BUCKET'],
733 '/',
734 $s = '?format=xml&' . ($bRecursive ? '' : '&delimiter=/') . '&prefix=' . urlencode($filePath) . '&marker=' . urlencode($marker)
735 );
736 $bFound = false;
737 if ($this->result && $this->status == 200)
738 {
739 $obXML = new CDataXML;
740 $text = preg_replace('/<' . '\\?XML.*?\\?' . '>/i', '', $this->result);
741 if ($obXML->LoadString($text))
742 {
743 $arXML = $obXML->GetArray();
744 if (
745 isset($arXML['container'])
746 && is_array($arXML['container'])
747 && isset($arXML['container']['#'])
748 && is_array($arXML['container']['#'])
749 && !empty($arXML['container']['#'])
750 )
751 {
752 if (
753 isset($arXML['container']['#']['object'])
754 && is_array($arXML['container']['#']['object'])
755 && !empty($arXML['container']['#']['object'])
756 )
757 {
758 $bFound = true;
759 foreach ($arXML['container']['#']['object'] as $a)
760 {
761 $new_marker = $a['#']['name'][0]['#'];
762 if ($a['#']['content_type'][0]['#'] === 'application/directory')
763 {
764 $dir_name = trim(mb_substr($a['#']['name'][0]['#'], mb_strlen($filePath)), '/');
765 $result['dir'][$dir_name] = true;
766 }
767 else
768 {
769 $file_name = mb_substr($a['#']['name'][0]['#'], mb_strlen($filePath));
770 if (!in_array($file_name, $result['file'], true))
771 {
772 $result['file'][] = $file_name;
773 $result['file_size'][] = $a['#']['bytes'][0]['#'];
774 $result['file_mtime'][] = mb_substr($a['#']['last_modified'][0]['#'], 0, 19);
775 $result['file_hash'][] = $a['#']['hash'][0]['#'];
776 $result['last_key'] = $file_name;
777 }
778 }
779 }
780 }
781
782 if (
783 isset($arXML['container']['#']['subdir'])
784 && is_array($arXML['container']['#']['subdir'])
785 && !empty($arXML['container']['#']['subdir'])
786 )
787 {
788 $bFound = true;
789 foreach ($arXML['container']['#']['subdir'] as $a)
790 {
791 $new_marker = $a['@']['name'];
792 $dir_name = trim(mb_substr($a['@']['name'], mb_strlen($filePath)), '/');
793 $result['dir'][rawurldecode($dir_name)] = true;
794 }
795 }
796 }
797 }
798 }
799 else
800 {
801 return false;
802 }
803
804 if ($new_marker === $marker)
805 {
806 break;
807 }
808
809 if (!$bFound)
810 {
811 break;
812 }
813
814 $marker = $new_marker;
815 }
816
817 $result['dir'] = array_keys($result['dir']);
818
819 return $result;
820 }
821
822 public function InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType)
823 {
824 $filePath = '/' . trim($filePath, '/');
825 if ($arBucket['PREFIX'])
826 {
827 if (mb_substr($filePath, 0, mb_strlen($arBucket['PREFIX']) + 2) !== '/' . $arBucket['PREFIX'] . '/')
828 {
829 $filePath = '/' . $arBucket['PREFIX'] . $filePath;
830 }
831 }
832
833 $NS = [
834 'filePath' => $filePath,
835 'fileTemp' => CCloudStorage::translit('/tmp' . str_replace(' ', '_', $filePath), '/'),
836 'partsCount' => 0,
837 'Parts' => [],
838 'Content-Type' => $ContentType,
839 ];
840
841 return true;
842 }
843
844 public function GetMinUploadPartSize()
845 {
846 return 5 * 1024 * 1024; //5MB
847 }
848
849 public function UploadPartNo($arBucket, &$NS, $data, $part_no)
850 {
851 $filePath = $NS['fileTemp'] . '/' . sprintf('%06d', $part_no + 1);
852 $filePath = CCloudUtil::URLEncode($filePath, 'UTF-8', true);
853
854 $this->SendRequest(
855 $arBucket['SETTINGS'],
856 'PUT',
857 $arBucket['BUCKET'],
858 $filePath,
859 '',
860 $data
861 );
862
863 if ($this->status == 201)
864 {
865 $NS['partsCount']++;
866 $NS['Parts'][$part_no] = $filePath;
867 return true;
868 }
869 else
870 {
871 return false;
872 }
873 }
874
875 public function UploadPart($arBucket, &$NS, $data)
876 {
877 return $this->UploadPartNo($arBucket, $NS, $data, count($NS['Parts']));
878 }
879
880 public function CompleteMultipartUpload($arBucket, &$NS)
881 {
882 $filePath = CCloudUtil::URLEncode($NS['fileTemp'], 'UTF-8', true);
883
884 $this->SendRequest(
885 $arBucket['SETTINGS'],
886 'PUT',
887 $arBucket['BUCKET'],
888 $filePath,
889 '',
890 false,
891 [
892 'Content-Length' => 0,
893 'Content-Type' => $NS['Content-Type'],
894 'X-Object-Manifest' => $arBucket['BUCKET'] . $filePath . '/',
895 ]
896 );
897
898 if ($this->status == 201)
899 {
900 $fileSource = CCloudUtil::URLEncode('/' . $arBucket['BUCKET'] . $NS['fileTemp'], 'UTF-8', true);
901
902 $this->SendRequest(
903 $arBucket['SETTINGS'],
904 'PUT',
905 $arBucket['BUCKET'],
906 CCloudUtil::URLEncode($NS['filePath'], 'UTF-8', true),
907 '',
908 false,
909 [
910 'Content-Type' => $NS['Content-Type'],
911 'X-Copy-From' => $fileSource,
912 ]
913 );
914
915 if (
916 $this->status == 201
917 || $this->status == 200
918 )
919 {
920 $result = true;
921 }
922 else
923 {
924 $result = false;
925 }
926
927 $this->DeleteFile($arBucket, $NS['fileTemp']);
928 ksort($NS['Parts']);
929 foreach ($NS['Parts'] as $tmpPath)
930 {
931 $this->DeleteFile($arBucket, $tmpPath);
932 }
933
934 return $result;
935 }
936 else
937 {
938 //May be delete uploaded tmp file?
939 AddMessage2Log($this);
940 return false;
941 }
942 }
943}
global $APPLICATION
Определения include.php:80
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
Определения catalog_reindex.php:36
static translit($file_name, $safe_chars='')
Определения storage.php:1883
DeleteFile($arBucket, $filePath)
Определения storage_service_openstack.php:603
InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType)
Определения storage_service_openstack.php:822
FileExists($arBucket, $filePath)
Определения storage_service_openstack.php:526
UploadPart($arBucket, &$NS, $data)
Определения storage_service_openstack.php:875
GetFileSRC($arBucket, $arFile, $encoded=true)
Определения storage_service_openstack.php:456
FileCopy($arBucket, $arFile, $filePath)
Определения storage_service_openstack.php:569
UploadPartNo($arBucket, &$NS, $data, $part_no)
Определения storage_service_openstack.php:849
CompleteMultipartUpload($arBucket, &$NS)
Определения storage_service_openstack.php:880
SaveFile($arBucket, $filePath, $arFile)
Определения storage_service_openstack.php:647
SendRequest($settings, $verb, $bucket, $file_name='', $params='', $content=false, $additional_headers=[])
Определения storage_service_openstack.php:272
ListFiles($arBucket, $filePath, $bRecursive=false)
Определения storage_service_openstack.php:699
CheckSettings($arBucket, &$arSettings)
Определения storage_service_openstack.php:73
GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm)
Определения storage_service_openstack.php:28
static URLEncode($str, $charset, $file_name=false)
Определения util.php:10
Определения xml.php:396
$content
Определения commerceml.php:144
$data['IS_AVAILABLE']
Определения .description.php:13
$bVarsFromForm
Определения file_edit.php:44
$bFound
Определения get_search.php:40
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
if(!defined('NOT_CHECK_PERMISSIONS')) $NS
Определения backup.php:24
AddMessage2Log($text, $module='', $traceDepth=6, $showArgs=false)
Определения tools.php:3941
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
Определения tools.php:2701
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$settings
Определения product_settings.php:43
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
$text
Определения template_pdf.php:79
</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."%"
Определения waybill.php:936
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
else $a
Определения template.php:137