Elgg  Version 6.3
ImageFetcherService.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Assets;
4 
6 use Elgg\Config;
9 use GuzzleHttp\Cookie\CookieJar;
10 use GuzzleHttp\Exception\TransferException;
11 use GuzzleHttp\RequestOptions;
12 
19 
20  protected const CACHE_PREFIX = 'image_fetcher_';
21 
25  protected $client;
26 
34  public function __construct(
35  protected Config $config,
36  protected SystemCache $cache,
37  protected \ElggSession $session
38  ) {
39  $this->client = elgg_get_http_client();
40  }
41 
54  public function getImage(string $image_url) {
55  if (empty($image_url)) {
56  throw new InvalidArgumentException('a non-empty image url is required for image fetching');
57  }
58 
59  $image_url = htmlspecialchars_decode($image_url);
60  $image_url = elgg_normalize_url($image_url);
61 
62  $cache_key = $this->makeCacheKey($image_url);
63  $cache = $this->cache->load($cache_key);
64  if (isset($cache)) {
65  return $cache;
66  }
67 
69  $options = [];
70 
71  if (stripos($image_url, $site->getURL()) === 0) {
72  // internal url, can use session cookie
73  $cookie_config = $this->config->getCookieConfig();
74 
75  $cookies = [
76  $cookie_config['session']['name'] => $this->session->getID(),
77  ];
78 
79  $domain = $cookie_config['session']['domain'] ?: $site->getDomain();
80 
81  $cookiejar = CookieJar::fromArray($cookies, $domain);
82  $options[RequestOptions::COOKIES] = $cookiejar;
83  }
84 
85  try {
86  $response = $this->client->get($image_url, $options);
87  } catch (TransferException $e) {
88  // this shouldn't happen, but just in case
89  $this->cache->save($cache_key, false);
90  return false;
91  }
92 
93  if ($response->getStatusCode() !== ELGG_HTTP_OK) {
94  $this->cache->save($cache_key, false);
95  return false;
96  }
97 
98  $image_contents = $response->getBody()->getContents();
99  if (!$this->validateImageData($image_contents)) {
100  $this->cache->save($cache_key, false);
101  return false;
102  }
103 
104  $result = [
105  'data' => $image_contents,
106  'content-type' => $response->getHeaderLine('content-type') ?: 'application/octet-stream',
107  'name' => basename($image_url),
108  ];
109 
110  $this->cache->save($cache_key, $result);
111 
112  return $result;
113  }
114 
122  protected function makeCacheKey(string $image_url): string {
123  return self::CACHE_PREFIX . md5($image_url);
124  }
125 
133  protected function validateImageData(string $image_data): bool {
134  if (empty($image_data)) {
135  return false;
136  }
137 
138  $tmp = new \ElggTempFile();
139  try {
140  $tmp->open('write');
141  $tmp->write($image_data);
142  $tmp->close();
143  } catch (ExceptionInterface $e) {
144  // file error
145  return false;
146  }
147 
148  $info = getimagesize($tmp->getFilenameOnFilestore());
149 
150  return is_array($info);
151  }
152 }
$site
Definition: icons.php:5
return[ 'admin/delete_admin_notices'=>['access'=> 'admin'], 'admin/menu/save'=>['access'=> 'admin'], 'admin/plugins/activate'=>['access'=> 'admin'], 'admin/plugins/activate_all'=>['access'=> 'admin'], 'admin/plugins/deactivate'=>['access'=> 'admin'], 'admin/plugins/deactivate_all'=>['access'=> 'admin'], 'admin/plugins/set_priority'=>['access'=> 'admin'], 'admin/security/security_txt'=>['access'=> 'admin'], 'admin/security/settings'=>['access'=> 'admin'], 'admin/security/regenerate_site_secret'=>['access'=> 'admin'], 'admin/site/cache/invalidate'=>['access'=> 'admin'], 'admin/site/flush_cache'=>['access'=> 'admin'], 'admin/site/icons'=>['access'=> 'admin'], 'admin/site/set_maintenance_mode'=>['access'=> 'admin'], 'admin/site/set_robots'=>['access'=> 'admin'], 'admin/site/theme'=>['access'=> 'admin'], 'admin/site/unlock_upgrade'=>['access'=> 'admin'], 'admin/site/settings'=>['access'=> 'admin'], 'admin/upgrade'=>['access'=> 'admin'], 'admin/upgrade/reset'=>['access'=> 'admin'], 'admin/user/ban'=>['access'=> 'admin'], 'admin/user/bulk/ban'=>['access'=> 'admin'], 'admin/user/bulk/delete'=>['access'=> 'admin'], 'admin/user/bulk/unban'=>['access'=> 'admin'], 'admin/user/bulk/validate'=>['access'=> 'admin'], 'admin/user/change_email'=>['access'=> 'admin'], 'admin/user/delete'=>['access'=> 'admin'], 'admin/user/login_as'=>['access'=> 'admin'], 'admin/user/logout_as'=>[], 'admin/user/makeadmin'=>['access'=> 'admin'], 'admin/user/resetpassword'=>['access'=> 'admin'], 'admin/user/removeadmin'=>['access'=> 'admin'], 'admin/user/unban'=>['access'=> 'admin'], 'admin/user/validate'=>['access'=> 'admin'], 'annotation/delete'=>[], 'avatar/upload'=>[], 'comment/save'=>[], 'diagnostics/download'=>['access'=> 'admin'], 'entity/chooserestoredestination'=>[], 'entity/delete'=>[], 'entity/mute'=>[], 'entity/restore'=>[], 'entity/subscribe'=>[], 'entity/trash'=>[], 'entity/unmute'=>[], 'entity/unsubscribe'=>[], 'login'=>['access'=> 'logged_out'], 'logout'=>[], 'notifications/mute'=>['access'=> 'public'], 'plugins/settings/remove'=>['access'=> 'admin'], 'plugins/settings/save'=>['access'=> 'admin'], 'plugins/usersettings/save'=>[], 'register'=>['access'=> 'logged_out', 'middleware'=>[\Elgg\Router\Middleware\RegistrationAllowedGatekeeper::class,],], 'river/delete'=>[], 'settings/notifications'=>[], 'settings/notifications/subscriptions'=>[], 'user/changepassword'=>['access'=> 'public'], 'user/requestnewpassword'=>['access'=> 'public'], 'useradd'=>['access'=> 'admin'], 'usersettings/save'=>[], 'widgets/add'=>[], 'widgets/delete'=>[], 'widgets/move'=>[], 'widgets/save'=>[],]
Definition: actions.php:73
Elgg Session Management.
Definition: ElggSession.php:19
Fetch external images server side.
__construct(protected Config $config, protected SystemCache $cache, protected \ElggSession $session)
Constructor.
validateImageData(string $image_data)
Validate that the fetched image data is an actual image.
getImage(string $image_url)
Get an image.
makeCacheKey(string $image_url)
Get the cache key for a given url.
Exception thrown if an argument is not of the expected type.
const ELGG_HTTP_OK
Definition: constants.php:45
if($who_can_change_language==='nobody') elseif($who_can_change_language==='admin_only' &&!elgg_is_admin_logged_in()) $options
Definition: language.php:20
$config
Advanced site settings, debugging section.
Definition: debugging.php:6
elgg_get_http_client(array $options=[])
Returns a Guzzle HTTP client.
Definition: elgglib.php:221
elgg_get_site_entity()
Get the current site entity.
Definition: entities.php:99
Generic interface which allows catching of all exceptions thrown in Elgg.
if(isset($_COOKIE['elggperm'])) $session
Definition: login_as.php:29
elgg_normalize_url(string $url)
Definition: output.php:163
if(parse_url(elgg_get_site_url(), PHP_URL_PATH) !=='/') if(file_exists(elgg_get_root_path() . 'robots.txt'))
Set robots.txt.
Definition: robots.php:10
$domain
Definition: layout.php:32
$response
Definition: content.php:10