? jsomers_233997_hook_file_transferred.patch
? sites/default/files
? sites/default/settings.php
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.165
diff -u -p -r1.165 file.inc
--- includes/file.inc	13 Apr 2009 19:06:32 -0000	1.165
+++ includes/file.inc	15 Apr 2009 21:27:28 -0000
@@ -1320,10 +1320,10 @@ function file_transfer($source, $headers
     drupal_set_header($header);
   }
 
-  $source = file_create_path($source);
-
   // Transfer file in 1024 byte chunks to save memory usage.
-  if ($fd = fopen($source, 'rb')) {
+  if ($fd = fopen(file_create_path($source), 'rb')) {
+    // Notify other modules that the given file is transferred.
+    module_invoke_all('file_transferring', $source, $headers);
     while (!feof($fd)) {
       print fread($fd, 1024);
     }
Index: modules/simpletest/tests/file.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/file.test,v
retrieving revision 1.27
diff -u -p -r1.27 file.test
--- modules/simpletest/tests/file.test	31 Mar 2009 01:49:53 -0000	1.27
+++ modules/simpletest/tests/file.test	15 Apr 2009 21:27:29 -0000
@@ -1874,7 +1874,7 @@ class FileSaveDataTest extends FileHookT
 /**
  * Tests for download/file transfer functions.
  */
-class FileDownloadTest extends FileTestCase {
+class FileDownloadTest extends FileHookTestCase {
   public static function getInfo() {
     return array(
       'name' => t('File download'),
@@ -1905,6 +1905,9 @@ class FileDownloadTest extends FileTestC
     $this->assertEqual($headers['x-foo'] , 'Bar', t('Found header set by file_test module on private download.'));
     $this->assertResponse(200, t('Correctly allowed access to a file when file_test provides headers.'));
 
+    // Check whether required hooks were called.    
+    $this->assertFileHooksCalled(array('download', 'transferring'));
+
     // Deny access to all downloads via a -1 header.
     file_test_set_return('download', -1);
     $this->drupalHead($url);
Index: modules/simpletest/tests/file_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/file_test.module,v
retrieving revision 1.8
diff -u -p -r1.8 file_test.module
--- modules/simpletest/tests/file_test.module	20 Jan 2009 02:56:05 -0000	1.8
+++ modules/simpletest/tests/file_test.module	15 Apr 2009 21:27:29 -0000
@@ -78,6 +78,7 @@ function file_test_reset() {
     'load' => array(),
     'validate' => array(),
     'download' => array(),
+    'transferring' => array(),
     'references' => array(),
     'insert' => array(),
     'update' => array(),
@@ -102,7 +103,7 @@ function file_test_reset() {
  *
  * @param $op
  *   One of the hook_file_* operations: 'load', 'validate', 'download',
- *   'references', 'insert', 'update', 'copy', 'move', 'delete'.
+ *   'references', 'insert', 'update', 'copy', 'move', 'delete', 'transferring'.
  * @returns
  *   Array of the parameters passed to each call.
  * @see _file_test_log_call() and file_test_reset()
@@ -117,8 +118,8 @@ function file_test_get_calls($op) {
  *
  * @return
  *   An array keyed by hook name ('load', 'validate', 'download',
- *   'references', 'insert', 'update', 'copy', 'move', 'delete') with values
- *   being arrays of parameters passed to each call.
+ *   'references', 'insert', 'update', 'copy', 'move', 'delete', 'transferring')
+ *   with values being arrays of parameters passed to each call.
  */
 function file_test_get_all_calls() {
   return variable_get('file_test_results', array());
@@ -129,7 +130,7 @@ function file_test_get_all_calls() {
  *
  * @param $op
  *   One of the hook_file_* operations: 'load', 'validate', 'download',
- *   'references', 'insert', 'update', 'copy', 'move', 'delete'.
+ *   'references', 'insert', 'update', 'copy', 'move', 'delete', 'transferring'.
  * @param $args
  *   Values passed to hook.
  * @see file_test_get_calls() and file_test_reset()
@@ -239,3 +240,10 @@ function file_test_file_move($file, $sou
 function file_test_file_delete($file) {
   _file_test_log_call('delete', array($file));
 }
+
+/**
+ * Implementation of hook_file_transferring().
+ */
+function file_test_file_transferring($source, $headers) {
+  _file_test_log_call('transferring', array($source, $headers));
+}
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.25
diff -u -p -r1.25 system.api.php
--- modules/system/system.api.php	29 Mar 2009 23:11:09 -0000	1.25
+++ modules/system/system.api.php	15 Apr 2009 21:27:30 -0000
@@ -1256,6 +1256,21 @@ function hook_file_download($filepath) {
 }
 
 /**
+ * Respond to a file which is being transferred.
+ *
+ * This hook is called when a file has begun transferring.
+ *
+ * @param $source
+ *   String specifying the file path to transfer.
+ * @param $headers
+ *   An array of HTTP headers to send along with file.
+ *
+ * @see file_transfer()
+ */
+function hook_file_transferring($source, $headers) {
+}
+
+/**
  * Check installation requirements and do status reporting.
  *
  * This hook has two closely related uses, determined by the $phase argument:
