1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
urlpreview.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\UrlPreview;
4
5use Bitrix\Main\ArgumentException;
6use Bitrix\Main\Config\Option;
7use Bitrix\Main\Loader;
8use Bitrix\Main\Security\Random;
9use Bitrix\Main\Security\Sign\Signer;
10use Bitrix\Main\Web\HttpClient;
11use Bitrix\Main\Web\Uri;
12use Bitrix\Main\Web\IpAddress;
13use Bitrix\Main\Web\Http\Response;
14use Bitrix\Main\File\Image;
15use Bitrix\Main\Web\MimeType;
16
18{
19 const SIGN_SALT = 'url_preview';
20 const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 (Bitrix link preview)';
22 const MAX_DESCRIPTION = 500;
24 const MAX_FILE_SIZE = 1048576;
26 const FILE_RANGE = 1023;
27
28 const IFRAME_MAX_WIDTH = 640;
29 const IFRAME_MAX_HEIGHT = 340;
30
31 protected static $trustedHosts = [
32 'youtube.com' => 'youtube.com',
33 'youtu.be' => 'youtu.be',
34 'youtube-nocookie.com' => 'youtube-nocookie.com',
35 'www.youtube-nocookie.com' => 'www.youtube-nocookie.com',
36 'vimeo.com' => 'vimeo.com',
37 'player.vimeo.com' => 'player.vimeo.com',
38 'rutube.ru' => 'rutube.ru',
39 'www.rutube.ru' => 'www.rutube.ru',
40 'facebook.com' => 'facebook.com',
41 'fb.watch' => 'fb.watch',
42 'vk.com' => 'vk.com',
43 'vk.ru' => 'vk.ru',
44 'instagram.com' => 'instagram.com',
45 ];
46
55 public static function getMetadataByUrl($url, $addIfNew = true, $reuseExistingMetadata = true)
56 {
57 if (!static::isEnabled())
58 {
59 return false;
60 }
61
62 $url = static::normalizeUrl($url);
63 if ($url == '')
64 {
65 return false;
66 }
67
68 if ($reuseExistingMetadata)
69 {
70 if ($metadata = UrlMetadataTable::getByUrl($url))
71 {
72 if ($metadata['TYPE'] === UrlMetadataTable::TYPE_TEMPORARY && $addIfNew)
73 {
74 $metadata = static::resolveTemporaryMetadata($metadata['ID']);
75 return $metadata;
76 }
77 if ($metadata['TYPE'] !== UrlMetadataTable::TYPE_STATIC
78 || !isset($metadata['DATE_EXPIRE'])
79 || $metadata['DATE_EXPIRE']->getTimestamp() > time()
80 )
81 {
82 return $metadata;
83 }
84 if (static::refreshMetadata($metadata))
85 {
86 return $metadata;
87 }
88 }
89 }
90
91 if (!$addIfNew)
92 {
93 return false;
94 }
95
96 $metadataId = static::reserveIdForUrl($url);
97 $metadata = static::fetchUrlMetadata($url);
98 if (is_array($metadata) && !empty($metadata))
99 {
100 $result = UrlMetadataTable::update($metadataId, $metadata);
101 $metadata['ID'] = $result->getId();
102 return $metadata;
103 }
104
105 return false;
106 }
107
117 public static function showView($userField, $userFieldParams, &$cacheTag, $edit = false)
118 {
119 global $APPLICATION;
120 $edit = !!$edit;
121 $cacheTag = '';
122
123 if (!static::isEnabled())
124 {
125 return null;
126 }
127
128 $metadataId = (int)$userField['VALUE'][0];
129 $metadata = false;
130 if ($metadataId > 0)
131 {
132 $metadata = UrlMetadataTable::getById($metadataId)->fetch();
133 if (isset($metadata['TYPE']) && $metadata['TYPE'] == UrlMetadataTable::TYPE_TEMPORARY)
134 {
135 $metadata = static::resolveTemporaryMetadata($metadata['ID']);
136 }
137 }
138
139 if (is_array($metadata))
140 {
141 $fullUrl = static::unfoldShortLink($metadata['URL']);
142 if ($metadata['TYPE'] == UrlMetadataTable::TYPE_DYNAMIC)
143 {
144 $routeRecord = Router::dispatch(new Uri($fullUrl));
145
146 if (isset($routeRecord['MODULE']) && Loader::includeModule($routeRecord['MODULE']))
147 {
148 $className = $routeRecord['CLASS'];
149 $routeRecord['PARAMETERS']['URL'] = $metadata['URL'];
150 $parameters = $routeRecord['PARAMETERS'];
151
152 if ($edit && (!method_exists($className, 'checkUserReadAccess') || !$className::checkUserReadAccess($parameters, static::getCurrentUserId())))
153 {
154 return null;
155 }
156
157 if (method_exists($className, 'buildPreview'))
158 {
159 $metadata['HANDLER'] = $routeRecord;
160 $metadata['HANDLER']['BUILD_METHOD'] = 'buildPreview';
161 }
162
163 if (method_exists($className, 'getCacheTag'))
164 {
165 $cacheTag = $className::getCacheTag();
166 }
167 }
168 elseif (!$edit)
169 {
170 return null;
171 }
172 }
173 }
174 elseif (!$edit)
175 {
176 return null;
177 }
178
179 ob_start();
180 $APPLICATION->IncludeComponent(
181 'bitrix:main.urlpreview',
182 '',
183 array(
184 'USER_FIELD' => $userField,
185 'METADATA' => is_array($metadata) ? $metadata : [],
186 'PARAMS' => $userFieldParams,
187 'EDIT' => ($edit ? 'Y' : 'N'),
188 'CHECK_ACCESS' => ($edit ? 'Y' : 'N'),
189 )
190 );
191 return ob_get_clean();
192 }
193
201 public static function showEdit($userField, $userFieldParams)
202 {
203 return static::showView($userField, $userFieldParams, $cacheTag, true);
204 }
205
212 public static function isUrlCached($url)
213 {
214 $url = static::normalizeUrl($url);
215 if ($url == '')
216 {
217 return false;
218 }
219
220 return (static::isUrlLocal(new Uri($url)) || !!UrlMetadataTable::getByUrl($url));
221 }
222
232 public static function getMetadataAndHtmlByUrl($url, $addIfNew = true, $reuseExistingMetadata = true)
233 {
234 $metadata = static::getMetadataByUrl($url, $addIfNew, $reuseExistingMetadata);
235 if ($metadata === false)
236 {
237 return false;
238 }
239
240 if ($metadata['TYPE'] == UrlMetadataTable::TYPE_STATIC || $metadata['TYPE'] == UrlMetadataTable::TYPE_FILE)
241 {
242 return $metadata;
243 }
244 elseif ($metadata['TYPE'] == UrlMetadataTable::TYPE_DYNAMIC)
245 {
246 if ($preview = static::getDynamicPreview($url))
247 {
248 $metadata['HTML'] = $preview;
249 return $metadata;
250 }
251
252 }
253
254 return false;
255 }
256
265 public static function getMetadataAndHtmlByIds(array $ids, $checkAccess = true, $userId = 0)
266 {
267 if (!static::isEnabled())
268 {
269 return false;
270 }
271
272 $result = [];
273
274 $queryResult = UrlMetadataTable::getList([
275 'filter' => [
276 'ID' => $ids,
278 ]
279 ]);
280
281 while ($metadata = $queryResult->fetch())
282 {
283 if ($metadata['TYPE'] == UrlMetadataTable::TYPE_DYNAMIC)
284 {
285 $metadata['HTML'] = static::getDynamicPreview($metadata['URL'], $checkAccess, $userId);
286 if ($metadata['HTML'] === false)
287 {
288 continue;
289 }
290 }
291 if ($metadata['TYPE'] == UrlMetadataTable::TYPE_STATIC
292 && isset($metadata['DATE_EXPIRE'])
293 && $metadata['DATE_EXPIRE']->getTimestamp() <= time()
294 )
295 {
296 $refreshResult = static::refreshMetadata($metadata);
297 if (!$refreshResult)
298 {
299 continue;
300 }
301 }
302 $result[$metadata['ID']] = $metadata;
303 }
304
305 return $result;
306 }
307
308 public static function getMetadataByIds(array $ids)
309 {
310 if (!static::isEnabled())
311 {
312 return false;
313 }
314
315 $result = [];
316
317 $queryResult = UrlMetadataTable::getList([
318 'filter' => [
319 'ID' => $ids,
321 ]
322 ]);
323
324 while ($metadata = $queryResult->fetch())
325 {
326 if ($metadata['TYPE'] == UrlMetadataTable::TYPE_STATIC
327 && isset($metadata['DATE_EXPIRE'])
328 && $metadata['DATE_EXPIRE']->getTimestamp() <= time()
329 )
330 {
331 $refreshResult = static::refreshMetadata($metadata);
332 if (!$refreshResult)
333 {
334 continue;
335 }
336 }
337 $result[$metadata['ID']] = $metadata;
338 }
339
340 return $result;
341 }
342
349 public static function reserveIdForUrl($url)
350 {
351 if ($metadata = UrlMetadataTable::getByUrl($url))
352 {
353 $id = $metadata['ID'];
354 }
355 else
356 {
358 'URL' => $url,
360 ));
361 $id = $result->getId();
362 }
363
364 return $id;
365 }
366
375 public static function resolveTemporaryMetadata($id, $checkAccess = true, $userId = 0)
376 {
377 $metadata = UrlMetadataTable::getRowById($id);
378 if (!is_array($metadata))
379 {
380 return false;
381 }
382
383 if ($metadata['TYPE'] == UrlMetadataTable::TYPE_TEMPORARY)
384 {
385 $metadata['URL'] = static::normalizeUrl($metadata['URL']);
386 $metadata = static::fetchUrlMetadata($metadata['URL']);
387 if ($metadata === false)
388 {
390 return false;
391 }
392
393 UrlMetadataTable::update($id, $metadata);
394 return $metadata;
395 }
396 elseif ($metadata['TYPE'] == UrlMetadataTable::TYPE_STATIC || $metadata['TYPE'] == UrlMetadataTable::TYPE_FILE)
397 {
398 return $metadata;
399 }
400 elseif ($metadata['TYPE'] == UrlMetadataTable::TYPE_DYNAMIC)
401 {
402 if ($preview = static::getDynamicPreview($metadata['URL'], $checkAccess, $userId))
403 {
404 $metadata['HTML'] = $preview;
405 return $metadata;
406 }
407 }
408
409 return false;
410 }
411
412 protected static function refreshMetadata(array &$metadata): bool
413 {
414 if ($metadata['TYPE'] !== UrlMetadataTable::TYPE_STATIC)
415 {
416 return false;
417 }
418 $url = static::normalizeUrl($metadata['URL']);
419 $refreshedMetadata = static::fetchUrlMetadata($url);
420 if (!$refreshedMetadata)
421 {
422 return false;
423 }
424 if ($metadata['ID'])
425 {
426 UrlMetadataTable::update($metadata['ID'], $refreshedMetadata);
427 $refreshedMetadata['ID'] = $metadata['ID'];
428 }
429 $metadata = $refreshedMetadata;
430
431 return true;
432 }
433
441 public static function getDynamicPreview($url, $checkAccess = true, $userId = 0)
442 {
443 $routeRecord = Router::dispatch(new Uri(static::unfoldShortLink($url)));
444 if ($routeRecord === false)
445 {
446 return false;
447 }
448
449 if (isset($routeRecord['MODULE']) && Loader::includeModule($routeRecord['MODULE']))
450 {
451 $className = $routeRecord['CLASS'];
452 $parameters = $routeRecord['PARAMETERS'];
453 $parameters['URL'] = $url;
454
455 if ($userId == 0)
456 {
457 $userId = static::getCurrentUserId();
458 }
459
460 if ($checkAccess && (!method_exists($className, 'checkUserReadAccess') || $userId == 0 || !$className::checkUserReadAccess($parameters, $userId)))
461 return false;
462
463 if (method_exists($className, 'buildPreview'))
464 {
465 $preview = $className::buildPreview($parameters);
466 return ($preview <> '' ? $preview : false);
467 }
468 }
469 return false;
470 }
471
479 public static function getImAttach($url, $checkAccess = true, $userId = 0)
480 {
481 return self::getUrlInfoFromExternal($url, 'getImAttach', $checkAccess, $userId);
482 }
483
490 public static function getImRich($url, $checkAccess = true, $userId = 0)
491 {
492 return self::getUrlInfoFromExternal($url, 'getImRich', $checkAccess, $userId);
493 }
494
501 public static function checkDynamicPreviewAccess($url, $userId = 0)
502 {
503 $routeRecord = Router::dispatch(new Uri(static::unfoldShortLink($url)));
504 if ($routeRecord === false)
505 {
506 return false;
507 }
508
509 if (isset($routeRecord['MODULE']) && Loader::includeModule($routeRecord['MODULE']))
510 {
511 $className = $routeRecord['CLASS'];
512 $parameters = $routeRecord['PARAMETERS'];
513
514 if ($userId == 0)
515 {
516 $userId = static::getCurrentUserId();
517 }
518
519 return (method_exists($className, 'checkUserReadAccess') && $userId > 0 && $className::checkUserReadAccess($parameters, $userId));
520 }
521 return false;
522 }
523
531 public static function setMetadataImage($id, $imageUrl)
532 {
533 if (!is_int($id))
534 {
535 throw new ArgumentException("Id of the metadata must be an integer", "id");
536 }
537 if (!is_string($imageUrl) && !is_null($imageUrl))
538 {
539 throw new ArgumentException("Url of the image must be a string", "imageUrl");
540 }
541
543 'select' => array('IMAGE', 'IMAGE_ID', 'EXTRA'),
544 'filter' => array('=ID' => $id)
545 ))->fetch();
546
547 if (isset($metadata['EXTRA']['IMAGES']))
548 {
549 $imageIndex = array_search($imageUrl, $metadata['EXTRA']['IMAGES']);
550 if ($imageIndex === false)
551 {
552 unset($metadata['EXTRA']['SELECTED_IMAGE']);
553 }
554 else
555 {
556 $metadata['EXTRA']['SELECTED_IMAGE'] = $imageIndex;
557 }
558 }
559
560 static::fetchImageMetadata($imageUrl, $metadata);
561
562 return UrlMetadataTable::update($id, $metadata)->isSuccess();
563 }
564
569 public static function isEnabled()
570 {
571 static $result = null;
572 if (is_null($result))
573 {
574 $result = Option::get('main', 'url_preview_enable', 'N') === 'Y';
575 }
576 return $result;
577 }
578
585 public static function sign($id)
586 {
587 $signer = new Signer();
588 return $signer->sign((string)$id, static::SIGN_SALT);
589 }
590
591 protected static function getUrlInfoFromExternal($url, $method, $checkAccess = true, $userId = 0)
592 {
593 //todo: caching
594 $routeRecord = Router::dispatch(new Uri(static::unfoldShortLink($url)));
595 if ($routeRecord === false)
596 {
597 return false;
598 }
599
600 if ($userId == 0)
601 {
602 $userId = static::getCurrentUserId();
603 }
604
605 if (isset($routeRecord['MODULE']) && Loader::includeModule($routeRecord['MODULE']))
606 {
607 $className = $routeRecord['CLASS'];
608 $parameters = $routeRecord['PARAMETERS'];
609 $parameters['URL'] = $url;
610
611 if ($checkAccess && (!method_exists($className, 'checkUserReadAccess') || $userId == 0 || !$className::checkUserReadAccess($parameters, $userId)))
612 return false;
613
614 if (method_exists($className, $method))
615 {
616 return $className::$method($parameters);
617 }
618 }
619 return false;
620 }
621
626 protected static function fetchUrlMetadata($url)
627 {
628 $fullUrl = static::unfoldShortLink($url);
629 $uriParser = new Uri($fullUrl);
630 if (static::isUrlLocal($uriParser))
631 {
632 if (Router::dispatch($uriParser))
633 {
634 $metadata = array(
635 'URL' => $url,
637 );
638 }
639 }
640 else
641 {
642 $metadataRemote = static::getRemoteUrlMetadata($uriParser);
643 if (is_array($metadataRemote) && !empty($metadataRemote))
644 {
645 $metadata = array(
646 'URL' => $url,
647 'TYPE' => $metadataRemote['TYPE'] ?? UrlMetadataTable::TYPE_STATIC,
648 'TITLE' => $metadataRemote['TITLE'] ?? '',
649 'DESCRIPTION' => $metadataRemote['DESCRIPTION'] ?? '',
650 'IMAGE_ID' => $metadataRemote['IMAGE_ID'] ?? null,
651 'IMAGE' => $metadataRemote['IMAGE'] ?? null,
652 'EMBED' => $metadataRemote['EMBED'] ?? null,
653 'EXTRA' => $metadataRemote['EXTRA'] ?? null,
654 'DATE_EXPIRE' => $metadataRemote['DATE_EXPIRE'] ?? null,
655 );
656 }
657 }
658
659 if (isset($metadata['TYPE']))
660 {
661 return $metadata;
662 }
663 return false;
664 }
665
672 protected static function isUrlLocal(Uri $uri)
673 {
674 if ($uri->getHost() == '')
675 {
676 return true;
677 }
678
679 $host = \Bitrix\Main\Context::getCurrent()->getRequest()->getHttpHost();
680 return $uri->getHost() === $host;
681 }
682
687 protected static function getRemoteUrlMetadata(Uri $uri)
688 {
689 $httpClient = (new HttpClient())
690 ->setPrivateIp(false) //prevents proxy to LAN
691 ->setTimeout(5)
692 ->setStreamTimeout(5)
693 ->setHeader('User-Agent', self::USER_AGENT)
694 ;
695
696 $httpClient->shouldFetchBody(function (Response $response) {
697 $contentType = $response->getHeadersCollection()->getContentType();
698 return ($contentType === 'text/html' || MimeType::isImage($contentType));
699 });
700
701 try
702 {
703 if (!$httpClient->query('GET', $uri->getUri()))
704 {
705 return false;
706 }
707 }
708 catch (\ErrorException)
709 {
710 return false;
711 }
712
713 if ($httpClient->getStatus() !== 200)
714 {
715 return false;
716 }
717
718 $peerIpAddress = $httpClient->getPeerAddress();
719
720 if ($httpClient->getHeaders()->getContentType() !== 'text/html')
721 {
722 $metadata = static::getFileMetadata($httpClient);
723 $metadata['EXTRA']['PEER_IP_ADDRESS'] = $peerIpAddress;
724 $metadata['EXTRA']['PEER_IP_PRIVATE'] = (new IpAddress($peerIpAddress))->isPrivate();
725
726 return $metadata;
727 }
728
729 $html = $httpClient->getResult();
730
731 $htmlDocument = new HtmlDocument($html, $uri);
732 $htmlDocument->setEncoding($httpClient->getCharset());
733 ParserChain::extractMetadata($htmlDocument);
734 $metadata = $htmlDocument->getMetadata();
735
736 if (is_array($metadata) && static::validateRemoteMetadata($metadata))
737 {
738 if (isset($metadata['IMAGE']))
739 {
740 static::fetchImageMetadata($metadata['IMAGE'], $metadata);
741 }
742
743 if (isset($metadata['DESCRIPTION']) && mb_strlen($metadata['DESCRIPTION']) > static::MAX_DESCRIPTION)
744 {
745 $metadata['DESCRIPTION'] = mb_substr($metadata['DESCRIPTION'], 0, static::MAX_DESCRIPTION);
746 }
747
748 if (!isset($metadata['EXTRA']) || !is_array($metadata['EXTRA']))
749 {
750 $metadata['EXTRA'] = array();
751 }
752
753 $metadata['EXTRA'] = array_merge($metadata['EXTRA'], array(
754 'PEER_IP_ADDRESS' => $peerIpAddress,
755 'PEER_IP_PRIVATE' => (new IpAddress($peerIpAddress))->isPrivate(),
756 'X_FRAME_OPTIONS' => $httpClient->getHeaders()->get('X-Frame-Options', true),
757 'EFFECTIVE_URL' => $httpClient->getEffectiveUrl(),
758 ));
759
760 return $metadata;
761 }
762
763 return false;
764 }
765
766 protected static function getTempPath(string $fileName): string
767 {
768 $tempFileName = Random::getString(32) . '.' . GetFileExtension($fileName);
769 $tempPath = \CFile::GetTempName('', $tempFileName);
770
771 return $tempPath;
772 }
773
774 protected static function downloadFile(string $url, ?string &$fileName = null, ?int $range = null): ?string
775 {
776 $httpClient = (new HttpClient())
777 ->setPrivateIp(false)
778 ->setTimeout(5)
779 ->setStreamTimeout(5)
780 ->setBodyLengthMax(self::MAX_FILE_SIZE)
781 ;
782
783 if ($range !== null)
784 {
785 $httpClient->setHeader('Range', 'bytes=0-' . $range);
786 }
787
788 $urlComponents = parse_url($url);
789 $fileName = ($urlComponents && $urlComponents["path"] <> '')
790 ? bx_basename($urlComponents["path"])
792 ;
793
794 $tempPath = static::getTempPath($fileName);
795
796 try
797 {
798 if (!$httpClient->download($url, $tempPath))
799 {
800 return null;
801 }
802 }
803 catch (\ErrorException)
804 {
805 return null;
806 }
807
808 if (($name = $httpClient->getHeaders()->getFilename()) !== null)
809 {
811 }
812
813 return $tempPath;
814 }
815
821 protected static function saveImage(string $tempPath, ?string $fileName)
822 {
823 $fileId = false;
824
825 $localFile = \CFile::MakeFileArray($tempPath);
826
827 if (is_array($localFile))
828 {
829 $localFile['MODULE_ID'] = 'main';
830
831 if ($fileName <> '')
832 {
833 $localFile['name'] = $fileName;
834 }
835 if (\CFile::CheckImageFile($localFile, 0, 0, 0, array("IMAGE")) === null)
836 {
837 $fileId = \CFile::SaveFile($localFile, 'urlpreview', true);
838 }
839 }
840
841 return ($fileId === false ? null : $fileId);
842 }
843
844 protected static function fetchImageMetadata(string $imageUrl, array &$metadata): void
845 {
846 $saveImage = static::getOptionSaveImages();
847
848 $tempPath = static::downloadFile($imageUrl, $fileName, ($saveImage ? null : self::FILE_RANGE));
849
850 if ($tempPath !== null)
851 {
852 $info = (new Image($tempPath))->getInfo();
853 if ($info)
854 {
855 $metadata['EXTRA']['IMAGE_INFO'] = [
856 'WIDTH' => $info->getWidth(),
857 'HEIGHT' => $info->getHeight(),
858 ];
859 }
860
861 if ($saveImage)
862 {
863 $metadata['IMAGE_ID'] = static::saveImage($tempPath, $fileName);
864 $metadata['IMAGE'] = null;
865 }
866 else
867 {
868 $metadata['IMAGE'] = $imageUrl;
869 $metadata['IMAGE_ID'] = null;
870 }
871 }
872 }
873
880 protected static function normalizeUrl($url)
881 {
882 if (str_starts_with($url, 'https://') || str_starts_with($url, 'http://'))
883 {
884 //nop
885 }
886 elseif (str_starts_with($url, '//'))
887 {
888 $url = 'http:'.$url;
889 }
890 elseif (str_starts_with($url, '/'))
891 {
892 //nop
893 }
894 else
895 {
896 $url = 'http://'.$url;
897 }
898
899 $parsedUrl = new Uri($url);
900 $parsedUrl->setHost(mb_strtolower($parsedUrl->getHost()));
901
902 return $parsedUrl->getUri();
903 }
904
909 protected static function getOptionSaveImages()
910 {
911 static $result = null;
912 if (is_null($result))
913 {
914 $result = Option::get('main', 'url_preview_save_images', 'N') === 'Y';
915 }
916 return $result;
917 }
918
924 protected static function validateRemoteMetadata(array $metadata)
925 {
926 $result = ((isset($metadata['TITLE']) && isset($metadata['IMAGE'])) || (isset($metadata['TITLE']) && isset($metadata['DESCRIPTION'])) || isset($metadata['EMBED']));
927 return $result;
928 }
929
934 public static function getCurrentUserId()
935 {
936 return ($GLOBALS['USER'] instanceof \CUser) ? (int)$GLOBALS['USER']->getId() : 0;
937 }
938
944 protected static function unfoldShortLink($shortUrl)
945 {
946 static $cache = [];
947 if (isset($cache[$shortUrl]))
948 {
949 return $cache[$shortUrl];
950 }
951
952 $result = $shortUrl;
953 if ($shortUri = \CBXShortUri::GetUri($shortUrl))
954 {
955 $result = $shortUri['URI'];
956 }
957 $cache[$shortUrl] = $result;
958 return $result;
959 }
960
966 protected static function getFileMetadata(HttpClient $client)
967 {
968 $url = $client->getEffectiveUrl();
969 $httpHeaders = $client->getHeaders();
970
971 $mimeType = $httpHeaders->getContentType();
972 $filename = $httpHeaders->getFilename() ?: bx_basename($url);
973 $result = false;
974 if ($mimeType && $filename)
975 {
976 $result = array(
978 'EXTRA' => array(
979 'ATTACHMENT' => strtolower($httpHeaders->getContentDisposition()) === 'attachment' ? 'Y' : 'N',
980 'MIME_TYPE' => $mimeType,
981 'FILENAME' => $filename,
982 'SIZE' => $httpHeaders->get('Content-Length')
983 )
984 );
985
986 if (MimeType::isImage($mimeType))
987 {
988 // download image to temp file to detect dimensions
989 $tempPath = static::getTempPath($filename);
990
991 $client->saveFile($tempPath);
992
993 $info = (new Image($tempPath))->getInfo();
994 if ($info)
995 {
996 $result['EXTRA']['IMAGE_INFO'] = [
997 'WIDTH' => $info->getWidth(),
998 'HEIGHT' => $info->getHeight(),
999 ];
1000 }
1001 }
1002 }
1003 return $result;
1004 }
1005
1011 public static function isIpAddressPrivate($ipAddress)
1012 {
1013 return (new IpAddress($ipAddress))->isPrivate();
1014 }
1015
1022 public static function isHostTrusted(Uri $uri)
1023 {
1024 $result = false;
1025 $domainNameParts = explode('.', $uri->getHost());
1026 if (is_array($domainNameParts) && ($partsCount = count($domainNameParts)) >= 2)
1027 {
1028 $domainName = $domainNameParts[$partsCount-2] . '.' . $domainNameParts[$partsCount-1];
1029 $result = isset(static::$trustedHosts[$domainName]);
1030 }
1031 return $result;
1032 }
1033
1040 public static function fetchVideoMetaData($url)
1041 {
1042 $url = static::unfoldShortLink($url);
1043 $uri = new Uri($url);
1044 if (static::isHostTrusted($uri) || static::isEnabled())
1045 {
1046 $url = static::normalizeUrl($url);
1047 $metadataId = static::reserveIdForUrl($url);
1048 $metadata = static::fetchUrlMetadata($url);
1049 if (is_array($metadata) && !empty($metadata))
1050 {
1051 $result = UrlMetadataTable::update($metadataId, $metadata);
1052 $metadata['ID'] = $result->getId();
1053 }
1054 else
1055 {
1056 return false;
1057 }
1058 if (!empty($metadata['EMBED']) && !str_contains($metadata['EMBED'], '<iframe'))
1059 {
1060 $url = static::getInnerFrameUrl($metadata['ID'], $metadata['EXTRA']['PROVIDER_NAME']);
1061 if (intval($metadata['EXTRA']['VIDEO_WIDTH']) <= 0)
1062 {
1063 $metadata['EXTRA']['VIDEO_WIDTH'] = self::IFRAME_MAX_WIDTH;
1064 }
1065 if (intval($metadata['EXTRA']['VIDEO_HEIGHT']) <= 0)
1066 {
1067 $metadata['EXTRA']['VIDEO_HEIGHT'] = self::IFRAME_MAX_HEIGHT;
1068 }
1069 $metadata['EMBED'] = '<iframe src="'.$url.'" allowfullscreen="" width="'.$metadata['EXTRA']['VIDEO_WIDTH'].'" height="'.$metadata['EXTRA']['VIDEO_HEIGHT'].'" frameborder="0"></iframe>';
1070 }
1071
1072 if ($metadata['EMBED'] || !empty($metadata['EXTRA']['VIDEO']))
1073 {
1074 return $metadata;
1075 }
1076 }
1077
1078 return false;
1079 }
1080
1088 public static function getInnerFrameUrl($id, $provider = '')
1089 {
1090 $result = false;
1091
1092 $componentPath = \CComponentEngine::makeComponentPath('bitrix:main.urlpreview');
1093 if (!empty($componentPath))
1094 {
1095 $componentPath = getLocalPath('components'.$componentPath.'/frame.php');
1096 $uri = new Uri($componentPath);
1097 $uri->addParams(array('id' => $id, 'provider' => $provider));
1098 $result = static::normalizeUrl($uri->getLocator());
1099 }
1100
1101 return $result;
1102 }
1103}
if(!Loader::includeModule('messageservice')) $provider
Определения callback_ednaruimhpx.php:21
global $APPLICATION
Определения include.php:80
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static includeModule($moduleName)
Определения loader.php:67
static getRowById($id, array $parameters=[])
Определения datamanager.php:380
static getById($id)
Определения datamanager.php:364
static getList(array $parameters=array())
Определения datamanager.php:431
static delete($primary)
Определения datamanager.php:1644
static add(array $data)
Определения datamanager.php:877
static update($primary, array $data)
Определения datamanager.php:1256
Определения response.php:5
static dispatch(Uri $uri)
Определения router.php:84
static getByUrl($url)
Определения urlmetadata.php:93
static getImAttach($url, $checkAccess=true, $userId=0)
Определения urlpreview.php:479
static reserveIdForUrl($url)
Определения urlpreview.php:349
static getRemoteUrlMetadata(Uri $uri)
Определения urlpreview.php:687
static fetchImageMetadata(string $imageUrl, array &$metadata)
Определения urlpreview.php:844
static normalizeUrl($url)
Определения urlpreview.php:880
static getDynamicPreview($url, $checkAccess=true, $userId=0)
Определения urlpreview.php:441
static refreshMetadata(array &$metadata)
Определения urlpreview.php:412
static fetchVideoMetaData($url)
Определения urlpreview.php:1040
static saveImage(string $tempPath, ?string $fileName)
Определения urlpreview.php:821
static getOptionSaveImages()
Определения urlpreview.php:909
static getUrlInfoFromExternal($url, $method, $checkAccess=true, $userId=0)
Определения urlpreview.php:591
static downloadFile(string $url, ?string &$fileName=null, ?int $range=null)
Определения urlpreview.php:774
static getMetadataByIds(array $ids)
Определения urlpreview.php:308
static getMetadataByUrl($url, $addIfNew=true, $reuseExistingMetadata=true)
Определения urlpreview.php:55
static getMetadataAndHtmlByUrl($url, $addIfNew=true, $reuseExistingMetadata=true)
Определения urlpreview.php:232
static getImRich($url, $checkAccess=true, $userId=0)
Определения urlpreview.php:490
static showView($userField, $userFieldParams, &$cacheTag, $edit=false)
Определения urlpreview.php:117
const IFRAME_MAX_HEIGHT
Определения urlpreview.php:29
static isHostTrusted(Uri $uri)
Определения urlpreview.php:1022
static getCurrentUserId()
Определения urlpreview.php:934
static checkDynamicPreviewAccess($url, $userId=0)
Определения urlpreview.php:501
static getTempPath(string $fileName)
Определения urlpreview.php:766
static isEnabled()
Определения urlpreview.php:569
static fetchUrlMetadata($url)
Определения urlpreview.php:626
static $trustedHosts
Определения urlpreview.php:31
static isIpAddressPrivate($ipAddress)
Определения urlpreview.php:1011
const MAX_DESCRIPTION
Определения urlpreview.php:22
const IFRAME_MAX_WIDTH
Определения urlpreview.php:28
static getFileMetadata(HttpClient $client)
Определения urlpreview.php:966
static isUrlCached($url)
Определения urlpreview.php:212
static getMetadataAndHtmlByIds(array $ids, $checkAccess=true, $userId=0)
Определения urlpreview.php:265
static isUrlLocal(Uri $uri)
Определения urlpreview.php:672
static showEdit($userField, $userFieldParams)
Определения urlpreview.php:201
static sign($id)
Определения urlpreview.php:585
static resolveTemporaryMetadata($id, $checkAccess=true, $userId=0)
Определения urlpreview.php:375
static setMetadataImage($id, $imageUrl)
Определения urlpreview.php:531
static getInnerFrameUrl($id, $provider='')
Определения urlpreview.php:1088
static validateRemoteMetadata(array $metadata)
Определения urlpreview.php:924
static unfoldShortLink($shortUrl)
Определения urlpreview.php:944
saveFile($filePath)
Определения httpclient.php:654
getEffectiveUrl()
Определения httpclient.php:673
Определения uri.php:17
static GetUri($shortUri)
Определения short_uri.php:84
static makeComponentPath($componentName)
Определения component_engine.php:81
Определения user.php:6037
if( $strWarning=="") if($strWarning=="") $componentPath
Определения component_props2.php:197
$filename
Определения file_edit.php:47
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
if(file_exists($_SERVER['DOCUMENT_ROOT'] . "/urlrewrite.php")) $uri
Определения urlrewrite.php:61
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
Определения backup.php:924
GetFileExtension($path)
Определения tools.php:2972
bx_basename($path, $ext="")
Определения tools.php:3269
getLocalPath($path, $baseFolder="/bitrix")
Определения tools.php:5092
$name
Определения menu_edit.php:35
Определения Color.php:9
$host
Определения mysql_to_pgsql.php:32
$GLOBALS['____1690880296']
Определения license.php:1
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$fileName
Определения quickway.php:305
$contentType
Определения quickway.php:301
</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
$response
Определения result.php:21
$method
Определения index.php:27
$url
Определения iframe.php:7