1 image.module image_style_deliver($style, $scheme)

Menu callback; Given a style and image path, generate a derivative.

After generating an image, transfer it to the requesting agent.

Parameters

$style: The image style

$scheme: The file scheme, for example 'public' for public files.

File

core/modules/image/image.module, line 691
Exposes global functionality for creating image styles.

Code

function image_style_deliver($style, $scheme) {
  // Check that the style is defined and the scheme is valid.
  if (!$style || !file_stream_wrapper_valid_scheme($scheme)) {
    backdrop_add_http_header('Status', '400 Bad Request');
    backdrop_add_http_header('Content-Type', 'text/html; charset=utf-8');
    print t('Invalid request.');
    backdrop_exit();
  }

  $args = func_get_args();
  array_shift($args);
  array_shift($args);
  $target = implode('/', $args);
  $image_uri = $scheme . '://' . $target;
  $image_uri = file_uri_normalize_dot_segments($image_uri);

  $derivative_uri = image_style_path($style['name'], $image_uri);
  $derivative_scheme = file_uri_scheme($derivative_uri);

  // Image styles are not allowed to modify previously generated style images.
  if (strpos($image_uri, $scheme . '://styles/') === 0) {
    backdrop_add_http_header('Status', '400 Bad Request');
    backdrop_add_http_header('Content-Type', 'text/html; charset=utf-8');
    print t('Image styles are not allowed to modify images generated by other styles.');
    backdrop_exit();
  }

  $core_schemes = array('public', 'private', 'temporary');
  $additional_public_schemes = array_diff((array) config_get('system.core', 'file_additional_public_schemes'), $core_schemes);
  $public_schemes = array_merge(array('public'), $additional_public_schemes);
  $is_public = in_array($derivative_scheme, $public_schemes, TRUE);

  if ($scheme == 'private' && file_exists($derivative_uri)) {
    file_download($scheme, file_uri_target($derivative_uri));
  }

  // Other non-public schemes may add additional headers and control access to
  // the file.
  if (!$is_public) {
    $headers = file_download_headers($image_uri);
    if (empty($headers)) {
      return MENU_ACCESS_DENIED;
    }
    if (count($headers)) {
      foreach ($headers as $name => $value) {
        backdrop_add_http_header($name, $value);
      }
    }
  }

  // Check if image_style_url() marked this image for creation.
  $allowed_uris = image_style_get_allowed_uris();
  if (!isset($allowed_uris[$derivative_uri])) {
    // If an unknown request, limit using locking.
    $flood_lock_name = image_style_flood_lock_name();
    $flood_lock_acquired = (bool) $flood_lock_name;
    if (!$flood_lock_acquired) {
      backdrop_add_http_header('Status', '403 Access Denied');
      backdrop_add_http_header('Content-Type', 'text/html; charset=utf-8');
      print t('Image generation throttled after reaching maximum.');
      backdrop_exit();
    }
  }

  // Confirm that the original source image exists before trying to process it.
  if (!_image_source_image_exists($image_uri)) {
    watchdog('image', 'Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri));
    backdrop_add_http_header('Status', '404 Not Found');
    backdrop_add_http_header('Content-Type', 'text/html; charset=utf-8');
    print t('Source image not found.');
    backdrop_exit();
  }

  // Don't start generating the image if the derivative already exists or if
  // generation is in progress in another thread.
  $generation_lock_name = 'image_style_deliver:' . $style['name'] . ':' . backdrop_hash_base64($image_uri);
  if (!file_exists($derivative_uri)) {
    $generation_lock_acquired = lock_acquire($generation_lock_name);
    if (!$generation_lock_acquired) {
      // Tell client to retry again in 3 seconds. Currently no browsers are known
      // to support Retry-After.
      backdrop_add_http_header('Status', '503 Service Unavailable');
      backdrop_add_http_header('Content-Type', 'text/html; charset=utf-8');
      backdrop_add_http_header('Retry-After', 3);
      print t('Image generation in progress. Try again shortly.');
      backdrop_exit();
    }
  }

  // Try to generate the image, unless another thread just did it while we were
  // acquiring the lock.
  $success = file_exists($derivative_uri) || image_style_create_derivative($style, $image_uri, $derivative_uri);

  // Release all locks.
  if (!empty($flood_lock_acquired)) {
    lock_release($flood_lock_name);
  }
  if (!empty($generation_lock_acquired)) {
    lock_release($generation_lock_name);
  }

  if ($success) {
    image_style_remove_allowed_uri($derivative_uri);

    $image = image_load($derivative_uri);
    file_transfer($image->source, array('Content-Type' => $image->info['mime_type'], 'Content-Length' => $image->info['file_size']));
  }
  else {
    watchdog('image', 'Unable to generate the derived image located at %path.', array('%path' => $derivative_uri));
    backdrop_add_http_header('Status', '500 Internal Server Error');
    backdrop_add_http_header('Content-Type', 'text/html; charset=utf-8');
    print t('Error generating image.');
    backdrop_exit();
  }
}