Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.611.2.15 diff -u -F^f -r1.611.2.15 common.inc --- includes/common.inc 22 Jan 2008 09:36:49 -0000 1.611.2.15 +++ includes/common.inc 26 Jan 2008 22:08:15 -0000 @@ -1379,6 +1379,56 @@ function base_path() { } /** + * Returns a rewritten file URL. Allows you to serve files from different + * servers than the server on which Drupal is hosted. + * + * @param $file_path + * Path to a file, relative to the root directory. E.g.: "misc/jquery.js". + * @param $absolute_url + * Whether to generate an absolute URL or not. + * @return + * A valid file URL. + */ +function file_url($file_path, $absolute_url = FALSE) { + static $modules; + $file_url = FALSE; + + if (!isset($modules)) { + $modules = array(); + foreach (module_implements('file_server') as $module) { + $modules[] = array( + 'module' => $module, + 'weight' => variable_get("file_server_{$module}_weight", 0), + ); + } + + // Sort file server types by weight. + uasort($modules, create_function('$a, $b', 'return $a["weight"] > $b["weight"];')); + } + + // Try the first preferred file server to check if it can serve the file. + // Then try the second, and so on. + foreach ($modules as $module) { + $file_url = module_invoke($module['module'], 'file_server', 'url', $file_path, $absolute_url); + + // If the URL rewriting function sucesfully generated a URL, we can stop + // trying to find a server that can serve the file. + if ($file_url) { + break; + } + } + + // Always fall back to Drupal's default file server, to guarantee a working + // file URL. + if (!$file_url) { + $prefix = ($absolute_url) ? $GLOBALS['base_url'] .'/' : base_path(); + $file_url = $prefix . $file_path; + } + + return $file_url; +} + +/** * Provide a substitute clone() function for PHP4. */ function drupal_clone($object) { @@ -1474,15 +1524,15 @@ function drupal_get_css($css = NULL) { // 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"; } } } @@ -1491,7 +1541,7 @@ function drupal_get_css($css = NULL) { if ($is_writable && $preprocess_css) { $filename = md5(serialize($types)) .'.css'; $preprocess_file = drupal_build_css_cache($types, $filename); - $output .= ''. "\n"; + $output .= ''. "\n"; } } @@ -1526,7 +1576,7 @@ function drupal_build_css_cache($types, // Return the path to where this CSS file originated from, stripping off the name of the file at the end of the path. $path = base_path() . substr($file, 0, strrpos($file, '/')) .'/'; // Wraps all @import arguments in url(). - $contents = preg_replace('/@import\s+(?!url)[\'"]?(\S*)\b[\'"]?/i', '@import url("\1")', $contents); + $contents = preg_replace('/@import\s+(?!url)[\'"]?(\S*)\b[\'"]?/i', '@import url("\1")', $contents); // Fix all paths within this CSS file, ignoring absolute paths. $data .= preg_replace('/url\(([\'"]?)(?![a-z]+:)/i', 'url(\1'. $path . '\2', $contents); } @@ -1685,7 +1735,7 @@ function drupal_get_js($scope = 'header' break; default: foreach ($data as $path => $info) { - $output .= '\n"; + $output .= '\n"; } } } Index: includes/file.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/file.inc,v retrieving revision 1.90.2.3 diff -u -F^f -r1.90.2.3 file.inc --- includes/file.inc 7 Jan 2008 01:00:22 -0000 1.90.2.3 +++ includes/file.inc 26 Jan 2008 22:08:16 -0000 @@ -33,7 +33,7 @@ function file_create_url($path) { } switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) { case FILE_DOWNLOADS_PUBLIC: - return $GLOBALS['base_url'] .'/'. file_directory_path() .'/'. str_replace('\\', '/', $path); + return file_url(file_directory_path() .'/'. str_replace('\\', '/', $path), TRUE); case FILE_DOWNLOADS_PRIVATE: return url('system/files/'. $path, NULL, NULL, TRUE); } Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.337.2.2 diff -u -F^f -r1.337.2.2 theme.inc --- includes/theme.inc 31 May 2007 05:52:42 -0000 1.337.2.2 +++ includes/theme.inc 26 Jan 2008 22:08:16 -0000 @@ -322,24 +322,24 @@ function theme_get_setting($setting_name if ($settings['toggle_logo']) { if ($settings['default_logo']) { - $settings['logo'] = base_path() . dirname($theme_object->filename) .'/logo.png'; + $settings['logo'] = file_url(dirname($theme_object->filename) .'/logo.png'); } elseif ($settings['logo_path']) { - $settings['logo'] = base_path() . $settings['logo_path']; + $settings['logo'] = file_url($settings['logo_path']); } } if ($settings['toggle_favicon']) { if ($settings['default_favicon']) { if (file_exists($favicon = dirname($theme_object->filename) .'/favicon.ico')) { - $settings['favicon'] = base_path() . $favicon; + $settings['favicon'] = file_url($favicon); } else { - $settings['favicon'] = base_path() . 'misc/favicon.ico'; + $settings['favicon'] = file_url('misc/favicon.ico'); } } elseif ($settings['favicon_path']) { - $settings['favicon'] = base_path() . $settings['favicon_path']; + $settings['favicon'] = file_url($settings['favicon_path']); } else { $settings['toggle_favicon'] = FALSE; @@ -613,8 +613,7 @@ function theme_links($links, $attributes function theme_image($path, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) { if (!$getsize || (is_file($path) && (list($width, $height, $type, $image_attributes) = @getimagesize($path)))) { $attributes = drupal_attributes($attributes); - $url = (url($path) == $path) ? $path : (base_path() . $path); - return ''. check_plain($alt) .''; + return ''. check_plain($alt) .''; } } Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.440.2.28 diff -u -F^f -r1.440.2.28 system.module --- modules/system/system.module 11 Jan 2008 00:47:17 -0000 1.440.2.28 +++ modules/system/system.module 26 Jan 2008 22:08:18 -0000 @@ -738,9 +738,69 @@ function system_file_system_settings() { '#description' => t('If you want any sort of access control on the downloading of files, this needs to be set to private. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.') ); + $form['file_servers'] = array( + '#tree' => TRUE, + '#type' => 'fieldset', + '#title' => t('File servers'), + '#description' => t( + 'This setting is for advanced users.
+ Enables Drupal to serve files from any kind of file server. Drupal will + automatically fall back to file servers that are lower in the list. +
The web server Drupal is running on will always be used as the + default file server.'), + '#collapsible' => FALSE, + ); + + $modules = array(); + foreach (module_implements('file_server', TRUE) as $module) { + $info = _module_parse_info_file(drupal_get_path('module', $module) ."/$module.info"); + $file_server_info = module_invoke($module, 'file_server', 'info'); + + $modules[$module] = array( + 'type' => $file_server_info['type'], + 'module' => (!isset($file_server_info['configuration_page'])) ? $info['name'] : l($info['name'], $file_server_info['configuration_page']), + 'weight' => variable_get("file_server_{$module}_weight", 0), + ); + } + + // Sort file server types by weight. + uasort($modules, create_function('$a, $b', 'return $a["weight"] > $b["weight"];')); + + foreach ($modules as $module => $settings) { + $form['file_servers']['types'][$module] = array('#value' => $settings['type']); + $form['file_servers']['modules'][$module] = array('#value' => $settings['module']); + $form['file_servers']['weights']["file_server_{$module}_weight"] = array('#type' => 'weight', '#default_value' => $settings['weight']); + } + + // The web server Drupal is running on is always available, and it's the + // default server, i.e. a server we can always fall back to. So it must + // always be at the bottom of the list and don't have a configurable weight. + $form['file_servers']['types']['drupal'] = array('#value' => t('Web server')); + $form['file_servers']['modules']['drupal'] = array('#value' => 'Drupal'); + $form['file_servers']['weights']['file_server_drupal_weight'] = array('#value' => t('Default server')); + return system_settings_form($form); } +function theme_system_file_system_settings($form) { + $header = array(t('Type'), t('Module'), t('Weight')); + $rows = array(); + foreach (element_children($form['file_servers']['modules']) as $module) { + // Don't take form control structures + if (is_array($form['file_servers']['modules'][$module])) { + $rows[] = array( + drupal_render($form['file_servers']['types'][$module]), + drupal_render($form['file_servers']['modules'][$module]), + drupal_render($form['file_servers']['weights']["file_server_{$module}_weight"]), + ); + } + } + + $form['file_servers']['#value'] = theme('table', $header, $rows); + + return drupal_render($form); +} + function system_image_toolkit_settings() { $toolkits_available = image_get_available_toolkits(); if (count($toolkits_available) > 1) {