Index: imagecache.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache/imagecache.module,v
retrieving revision 1.19.2.15.2.10
diff -u -r1.19.2.15.2.10 imagecache.module
--- imagecache.module	19 Apr 2007 23:03:55 -0000	1.19.2.15.2.10
+++ imagecache.module	27 Aug 2007 13:36:55 -0000
@@ -36,12 +36,18 @@
 function imagecache_menu($may_cache) {
   $items = array();
   if ($may_cache) {
-    $items[] = array(
-      'path' => file_directory_path() .'/imagecache', 
+    $items[] = array( // catch public downloads when the file doesn't exist - only works with clean URLs
+      'path' => file_directory_path() .'/imagecache',
+      'callback' => 'imagecache_cache',
+      'access' => TRUE,
+      'type' => MENU_CALLBACK
+    );
+    $items[] = array( // private downloads
+      'path' => 'system/files/imagecache',
       'callback' => 'imagecache_cache',
       'access' => TRUE,
       'type' => MENU_CALLBACK
-    );     
+    );
     $items[] = array(
       'path' => 'admin/settings/imagecache', 
       'title' => t('Image cache'),
@@ -63,33 +69,15 @@
   $t = get_t();
 
   if ($phase == 'runtime') {
-    // Clean URLS.
-    if (!variable_get('clean_url', 0)) {
-      $requirements['clean_urls'] = array(
-        'title' => $t('Clean URLs'),
-        'value' => $t('Not enabled'),
-        'severity' => REQUIREMENT_ERROR,
-        'description' => $t('Imagecache will not operate properly if <a href="!url">Clean URLs</a> is not enabled on your site.', array('!url' => url('admin/settings/clean-urls'))),
-      ); 
-    }
     // Check for an image library.
     if (count(image_get_available_toolkits()) == 0) {
-      $requirements['clean_urls'] = array(
+      $requirements['image_toolkits'] = array(
         'title' => $t('Image Toolkit'),
         'value' => $t('No image toolkits available'),
         'severity' => REQUIREMENT_ERROR,
         'description' => $t('Imagecache requires an imagetoolkit such as <a href="http://php.net/gd">GD2</a> or <a href="http://www.imagemagick.org">Imagemagick</a> be installed on your server.'),
       ); 
     }
-    // Check for public files.
-    if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
-      $requirements['file_system'] = array(
-        'title' => $t('File Download Method'),
-        'value' => $t('Private Downloads'),
-        'severity' => REQUIREMENT_ERROR,
-        'description' => $t('Imagecache will not operate properly using Private Files. Please enable <a href="!url">Public File Transfer</a>.', array('!url' => url('admin/settings/file-system'))),
-      ); 
-    }
     // Check for JPEG/PNG/GIF support.
     if ('gd' == image_get_toolkit()) {
       foreach (array('gif', 'jpeg', 'png') as $format) {
@@ -109,13 +97,9 @@
 }
 
 function imagecache_cache() {
-  $generated = FALSE;
   $args = func_get_args();
   $preset = array_shift($args);
 
-  $preset_id = _imagecache_preset_load_by_name($preset);
-  $actions = _imagecache_actions_get_by_presetid($preset_id);
-
   $path = implode('/', $args); 
   // Verify that the source exists, if not exit. Maybe display a missing image.
   $source = file_create_path($path);
@@ -126,6 +110,21 @@
      //is flagged to provide a not found image.
   }
 
+  // If the file belongs to a node, check the corresponding node access.
+  $file_result = db_query("SELECT nid FROM {files} WHERE filepath = '%s'", $path);
+  $access = TRUE;
+
+  while ($row = db_fetch_object($file_result)) {
+    $node = node_load($row->nid);
+    if (!$node || !node_access('view', $node)) {
+      $access = FALSE;
+      break;
+    }
+  }
+  if (!$access) {
+    return drupal_access_denied();
+  }
+
 
   $destination = file_create_path() .'/imagecache/'. $preset .'/'. $path;
 
@@ -133,33 +132,37 @@
   // multiple presets for the same image are called in rapid succession.
   $tmpdestination = file_directory_temp() .'/'. $preset . str_replace(dirname($path) .'/', '', $path);
 
-  $dir = dirname($destination);
-  // Build the folder for imagecache.
-  if(!file_check_directory($dir)) {
-    $folders = explode("/",$dir);
-   
-    foreach($folders as $folder) {
-      $tpath[] = $folder;
-      $checkpath = implode("/", $tpath);
-      if(!file_check_directory($checkpath)) {
-        $p = implode("/", $tpath);
-        if (!file_exists($p)) {
-          mkdir($p);
+  // Check if the file already exists, also in the temporary location in order
+  // to prevent multiple apache children from trying to generate.
+  if (!is_file($destination) && !is_file($tmpdestination)) {
+    $dir = dirname($destination);
+
+    // Build the folder for imagecache.
+    if(!file_check_directory($dir)) {
+      $folders = explode("/",$dir);
+
+      foreach($folders as $folder) {
+        $tpath[] = $folder;
+        $checkpath = implode("/", $tpath);
+        if(!file_check_directory($checkpath)) {
+          $p = implode("/", $tpath);
+          if (!file_exists($p)) {
+            mkdir($p);
+          }
         }
       }
     }
-  }
 
-  if (!file_check_directory($dir)) {
-    watchdog('imagecache', t('Could not create destination: %dir', array('%dir' => $destination)), WATCHDOG_ERROR);
-    return;
-  }
+    if (!file_check_directory($dir)) {
+      watchdog('imagecache', t('Could not create destination: %dir', array('%dir' => $destination)), WATCHDOG_ERROR);
+      return drupal_not_found();
+    }
 
-  // Check if file exists to prevent multiple apache children from trying to generate.
-  if (!is_file($tmpdestination)) {
-    $generated = TRUE;
     file_copy($source, $tmpdestination);
 
+    $preset_id = _imagecache_preset_load_by_name($preset);
+    $actions = _imagecache_actions_get_by_presetid($preset_id);
+
     foreach ($actions as $action) {
       $size = getimagesize($tmpdestination);
       $new_width = _imagecache_filter('width', $action['data']['width'], $size[0], $size[1]);
@@ -196,11 +199,8 @@
     }
     file_move($tmpdestination, $destination);
   }
-  else {
-    $generated = TRUE;
-  }
 
-  if ($generated)  {
+  if (is_file($destination)) {
     if (function_exists('mime_content_type')) {
       $mime = mime_content_type($destination);
     }
@@ -208,7 +208,11 @@
       $size = getimagesize($destination);
       $mime = $size['mime'];
     }
-    file_transfer($destination, array('Content-Type: '. mime_header_encode($mime), 'Content-Length: '. filesize($destination)));
+    $headers = array('Content-Type: '. mime_header_encode($mime));
+    if ($fileinfo = stat($destination)) {
+      $headers[] = 'Last-Modified: '. gmdate('D, d M Y H:i:s', $fileinfo[9]) .' GMT';
+    }
+    file_transfer($destination, $headers);
   }
   else {
     // Generate an error if image could not generate.
@@ -359,8 +363,6 @@
 }
 
 function imagecache_admin() {
-  //drupal_set_message('<pre>'. print_r($_POST, TRUE) .'</pre>');
-  
   drupal_set_title('Imagecache administration');
   $form = array();
   $form['title'] = array('#type' => 'markup', '#value' => t('Imagecache presets'));
@@ -734,7 +736,18 @@
 
 function theme_imagecache($namespace, $path, $alt = '', $title = '', $attributes = NULL) {
   $attributes = drupal_attributes($attributes);
-  $imagecache_path = file_create_url(file_directory_path() .'/imagecache/'. $namespace .'/'. $path);
+
+  // Public download / Clean URL configurations can't take advantage of
+  // imagecache's "catch the original filepath with a menu path" approach,
+  // so let those act like private downloads instead.
+  if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC
+      && !variable_get('clean_url', 0)) {
+    $imagecache_path = url('system/files/imagecache/'. $namespace .'/'. $path,
+                           NULL, NULL, TRUE);
+  }
+  else {
+    $imagecache_path = file_create_url('imagecache/'. $namespace .'/'. $path);
+  }
   return '<img src="'. $imagecache_path .'" alt="'. check_plain($alt) .'" title="'. check_plain($title) .'" '. $attributes .' />';
 }
 
