You are here

function cdn_file_url_alter in CDN 7.2

Same name and namespace in other branches
  1. 8.3 cdn.module \cdn_file_url_alter()
  2. 6.2 cdn.module \cdn_file_url_alter()

Implements hook_file_url_alter().

2 calls to cdn_file_url_alter()
CDNOriginPullFarFutureTestCase::testFileUrlAlterHook in tests/cdn.test
CDNOriginPullTestCase::testFileUrlAlterHook in tests/cdn.test

File

./cdn.module, line 18

Code

function cdn_file_url_alter(&$original_uri) {
  $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
  $farfuture = variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT);
  $stats = variable_get(CDN_STATS_VARIABLE, FALSE) && user_access(CDN_PERM_ACCESS_STATS);
  $https_support = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
  $maintenance_mode = variable_get('maintenance_mode', FALSE);
  $is_https_page = cdn_request_is_https();

  // Don't alter file URLs when running update.php.
  if (defined('MAINTENANCE_MODE')) {
    return;
  }
  if (cdn_status_is_enabled()) {
    $scheme = file_uri_scheme($original_uri);

    // If the current URI is an absolute or protocol-relative URI, return
    // immediately.
    if ($scheme && ($scheme == 'http' || $scheme == 'https') || drupal_substr($original_uri, 0, 2) == '//') {
      return;
    }
    elseif ($scheme) {

      // Only alter URLs for local stream wrappers. If a file is served
      // remotely, it doesn't make sense to serve it from a CDN.
      $local_schemes = array_keys(file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL));
      if (!in_array($scheme, $local_schemes)) {
        return;
      }
      elseif ($scheme === 'private') {
        return;
      }

      // Attempt to get an external URL using the appropriate wrapper.
      if ($wrapper = file_stream_wrapper_get_instance_by_uri($original_uri)) {
        $uri = str_replace($GLOBALS['base_url'] . '/', '', $wrapper
          ->getExternalUrl());
      }
      else {
        return;
      }
    }
    else {
      $uri = $original_uri;
    }
    if (!cdn_check_protocol()) {
      return;
    }
    if (!cdn_check_drupal_path(current_path())) {
      return;
    }
    if (!cdn_check_file($uri)) {
      return;
    }
    if ($stats) {
      cdn_load_include('stats');
      $start = microtime(TRUE);
    }

    // Alter the file path when using Origin Pull mode and using that mode's
    // Far Future setting.
    if ($mode == CDN_MODE_BASIC && $farfuture && !$maintenance_mode) {
      cdn_load_include('basic.farfuture');

      // We need the unescaped version of the URI to perform file operations.
      $uri = urldecode($uri);

      // If the file does not yet exist, perform a normal HTTP request to this
      // file, to generate it. (E.g. when ImageCache is used, this will
      // generate the derivative file.) When that fails, don't serve it from
      // the CDN.
      if (!file_exists($uri) && !_cdn_basic_farfuture_generate_file($uri, $original_uri)) {
        $path = drupal_encode_path($uri);
        return;
      }

      // Generate a unique file identifier (UFI).
      $ufi = cdn_basic_farfuture_get_identifier($uri);

      // Now that file operations have been performed, re-encode the URI.
      $uri = drupal_encode_path($uri);

      // Generate the new path.
      $uri_before_farfuture = $uri;

      // Generate a unique token to verify that the request was generated by
      // CDN. We cannot use drupal_get_token() since it depends on the user
      // session.
      $path_info = pathinfo(urldecode($uri));
      $token = drupal_hmac_base64($ufi . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt());
      $uri = "cdn/farfuture/{$token}/{$ufi}/{$uri}";
    }

    // Load the include file that contains the logic for the mode that's
    // currently enabled.
    cdn_load_include($mode == CDN_MODE_BASIC ? 'basic' : 'advanced');

    // Depending on the mode, use a different function to get the servers on
    // which the file is available.
    $servers = $mode == CDN_MODE_BASIC ? cdn_basic_get_servers($uri) : cdn_advanced_get_servers($uri);

    // The file is not available on any server.
    if (count($servers) == 0) {
      $cdn_url = FALSE;
      $server = FALSE;
    }
    elseif (count($servers) > 1 && function_exists('cdn_pick_server')) {
      $picked_server = cdn_pick_server($servers);
      $cdn_url = $picked_server['url'];
      $server = $picked_server['server'];
    }
    elseif (count($servers) > 1) {
      $filename = basename($servers[0]['url']);
      $unique_file_id = hexdec(substr(md5($filename), 0, 5));
      $choice = $unique_file_id % count($servers);
      $cdn_url = $servers[$choice]['url'];
      $server = $servers[$choice]['server'];
    }
    else {
      $cdn_url = $servers[0]['url'];
      $server = $servers[0]['server'];
    }

    // If the current page is being served via HTTPS, and the CDN supports
    // HTTPS, then use the HTTPS file URL.
    if ($is_https_page && $https_support && !empty($cdn_url)) {
      $cdn_url = preg_replace('/^http:/', 'https:', $cdn_url);
    }

    // If the user can access it, add this to the per-page statistics.
    if ($stats) {
      $end = microtime(TRUE);
      $source_uri = $mode == CDN_MODE_BASIC && $farfuture && !$maintenance_mode ? $uri_before_farfuture : $original_uri;
      _cdn_devel_page_stats($source_uri, $cdn_url, $server, $end - $start);
    }

    // Override the path with the corresponding CDN URL, *if* the file is
    // available on the CDN (it may only be not available in advanced mode).
    if ($cdn_url !== FALSE) {
      $original_uri = $cdn_url;
    }
  }
}