diff --git a/cdn.basic.css.inc b/cdn.basic.css.inc
index 30c1e50..e20b0a6 100644
--- a/cdn.basic.css.inc
+++ b/cdn.basic.css.inc
@@ -12,6 +12,12 @@
* Mostly based on drupal_get_css().
*/
function _cdn_css_aggregate(&$vars) {
+ // Don't override Drupal core's aggregation if this page is not going to use
+ // a CDN anyway.
+ if (!cdn_check_protocol() && !cdn_check_drupal_path($_GET['q'])) {
+ return;
+ }
+
$output = '';
$prefix = $suffix = '' . "\n";
@@ -20,6 +26,7 @@ function _cdn_css_aggregate(&$vars) {
$no_module_preprocess = '';
$no_theme_preprocess = '';
+ $query_string = variable_get('css_js_query_string', '0');
$preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
$directory = file_directory_path();
$is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
@@ -46,18 +53,24 @@ function _cdn_css_aggregate(&$vars) {
// Only include the stylesheet if it exists.
if (file_exists($file)) {
if (!$preprocess || !($is_writable && $preprocess_css)) {
+ // Also build CSS cache files for other files; so that the file
+ // URLs in them are altered to point to the CDN.
+ $fake_types = array($type => array($file => TRUE));
+ $filename = 'cdn_css_' . md5(serialize($types) . $query_string . 'cdn') .'_'. basename($file);
+ $file = _cdn_build_css_cache($fake_types, $filename);
+
// If a CSS file is not to be preprocessed and it's a module CSS file, it needs to *always* appear at the *top*,
// regardless of whether preprocessing is on or off.
if (!$preprocess && $type == 'module') {
- $no_module_preprocess .= ''."\n";
+ $no_module_preprocess .= ''."\n";
}
// If a CSS file is not to be preprocessed and it's a theme CSS file, it needs to *always* appear at the *bottom*,
// regardless of whether preprocessing is on or off.
else if (!$preprocess && $type == 'theme') {
- $no_theme_preprocess .= ''."\n";
+ $no_theme_preprocess .= ''."\n";
}
else {
- $output .= ''."\n";
+ $output .= ''."\n";
}
}
}
@@ -67,10 +80,9 @@ function _cdn_css_aggregate(&$vars) {
if ($is_writable && $preprocess_css) {
// Prefix filename to prevent blocking by firewalls which reject files
// starting with "ad*".
- $query_string = variable_get('css_js_query_string', '0');
- $filename = 'css_'. md5(serialize($types) . $query_string . 'cdn') .'.css';
+ $filename = 'cdn_css_'. md5(serialize($types) . $query_string . 'cdn') .'.css';
$preprocess_file = _cdn_build_css_cache($types, $filename);
- $output .= ''."\n";
+ $output .= ''."\n";
}
}
@@ -127,5 +139,27 @@ function _cdn_build_css_path($matches, $base = NULL) {
$path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
}
- return 'url('. file_create_url($path) .')';
+ return 'url('. _cdn_css_file_create_url($path) .')';
+}
+
+/**
+ * Generate CDN file URL without file_create_url() if the core patch has not
+ * been applied.
+ */
+function _cdn_css_file_create_url($path) {
+ if (variable_get(CDN_THEME_LAYER_FALLBACK_VARIABLE, FALSE) == TRUE) {
+ // Store the current path as the old path, then let cdn_file_url_alter()
+ // do its magic by invoking all file_url_alter hooks. When the path hasn't
+ // changed and is not already root-relative or protocol-relative, then
+ // generate a file URL as Drupal core would: prepend the base path.
+ $old_path = $path;
+ drupal_alter('file_url', $path);
+ if ($path == $old_path && drupal_substr($path, 0, 1) != '/' && drupal_substr($path, 0, 2) != '//') {
+ $path = base_path() . $path;
+ }
+ return $path;
+ }
+ else {
+ return file_create_url($path);
+ }
}
diff --git a/cdn.module b/cdn.module
index 8e66b7a..ab256cc 100644
--- a/cdn.module
+++ b/cdn.module
@@ -70,15 +70,9 @@ function cdn_file_url_alter(&$path) {
$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);
- $file_path_blacklist = variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT);
- $file_path_whitelist = variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT);
- $drupal_path_blacklist = variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT);
- $auth_users_blacklist = variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT);
$https_support = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
$maintenance_mode = variable_get('maintenance_mode', FALSE);
$is_https_page = cdn_request_is_https();
- $module_blacklist = cdn_get_blacklist();
- global $user;
// Don't alter file URLs when running update.php.
if (defined('MAINTENANCE_MODE')) {
@@ -92,35 +86,13 @@ function cdn_file_url_alter(&$path) {
return;
}
- // If the current page is being served via HTTPS, and the CDN does not
- // support HTTPS, then don't rewrite the file URL, because it would make the
- // visit insecure.
- if ($is_https_page && !$https_support) {
+ if (!cdn_check_protocol()) {
return;
}
-
- // If the current file path matches one of the blacklisted file paths,
- // return immediately, except when the current file path also matches one
- // of the whitelisted file paths.
- if ((
- drupal_match_path($path, $file_path_blacklist)
- ||
- drupal_match_path($path, $module_blacklist)
- )
- && !drupal_match_path($path, $file_path_whitelist)
- )
- {
- return;
- }
-
- // If the current Drupal path matches one of the blacklisted Drupal paths,
- // return immediately.
- if (drupal_match_path($_GET['q'], $drupal_path_blacklist)) {
+ if (!cdn_check_drupal_path($_GET['q'])) {
return;
}
-
- // If logged in user, apply a secondary blacklist.
- if ($user->uid > 0 && drupal_match_path($_GET['q'], $auth_users_blacklist)) {
+ if (!cdn_check_file($path)) {
return;
}
@@ -690,6 +662,76 @@ function cdn_request_is_https() {
}
/**
+ * Check if the current protocol is supported by the CDN.
+ *
+ * Note: currently only checks HTTPS, in the future possibly also SPDY.
+ */
+function cdn_check_protocol() {
+ $https_support = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
+
+ // If the current page is being served via HTTPS, and the CDN does not
+ // support HTTPS, then don't rewrite the file URL, because it would make the
+ // visit insecure.
+ if (cdn_request_is_https() && !$https_support) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Check if a Drupal path should serve files from the CDN (i.e.: is the Drupal
+ * path blacklisted?).
+ *
+ * @param $path
+ * A Drupal path.
+ */
+function cdn_check_drupal_path($path) {
+ global $user;
+ $blacklist = variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT);
+ $auth_blacklist = variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT);
+
+ // Check if the Drupal path matches one of the blacklisted Drupal paths.
+ if (drupal_match_path($path, $blacklist)) {
+ return FALSE;
+ }
+
+ // If logged in user, apply a secondary blacklist.
+ if ($user->uid > 0 && drupal_match_path($path, $auth_blacklist)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Check if a file should be served from the CDN.
+ *
+ * @param $path
+ * Path to a file; relative to the Drupal root directory.
+ */
+function cdn_check_file($path) {
+ $file_path_blacklist = variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT);
+ $file_path_whitelist = variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT);
+ $module_blacklist = cdn_get_blacklist();
+
+ // A file should not be served from a CDN when it matches one of the
+ // blacklists, except when it matches the whitelist.
+ if ((
+ drupal_match_path($path, $file_path_blacklist)
+ ||
+ drupal_match_path($path, $module_blacklist)
+ )
+ && !drupal_match_path($path, $file_path_whitelist)
+ )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* Helper function to efficiently load include files for this module.
*/
function cdn_load_include($basename) {