Index: file.inc
===================================================================
--- file.inc	(revision 128)
+++ file.inc	(working copy)
@@ -1133,7 +1133,7 @@
       $row = db_fetch_object(db_query("SELECT f.nid, f.vid FROM {file_nodes} f WHERE f.uri = '%s' AND f.vid = %d", $parent_uri, $vid));
     if (is_object($row)) {
       $node = node_load($row->nid, $row->vid);
-      return node_access('view', $node) ? $node : FALSE;
+      return file_check_access('view', $node) ? $node : FALSE;
     }
   }
 
Index: file.module
===================================================================
--- file.module	(revision 128)
+++ file.module	(working copy)
@@ -167,7 +167,7 @@
       'type' => MENU_CALLBACK,
       'page callback' => 'file_embed',
       'page arguments' => array(1, 3),
-      'access callback' => 'node_access',
+      'access callback' => 'file_check_access',
       'access arguments' => array('view', 1),
       'file' => 'file.pages.inc',
     ),
@@ -176,7 +176,7 @@
       'type' => MENU_CALLBACK,
       'page callback' => 'file_serve',
       'page arguments' => array(1, 3, 'attachment'),
-      'access callback' => 'node_access',
+      'access callback' => 'file_check_access',
       'access arguments' => array('view', 1),
       'file' => 'file.pages.inc',
     ),
@@ -185,7 +185,7 @@
       'type' => MENU_CALLBACK,
       'page callback' => 'file_serve',
       'page arguments' => array(1, 3, 'inline'),
-      'access callback' => 'node_access',
+      'access callback' => 'file_check_access',
       'access arguments' => array('view', 1),
       'file' => 'file.pages.inc',
     ),
@@ -194,7 +194,7 @@
       'type' => MENU_CALLBACK,
       'page callback' => 'file_wrapper_html',
       'page arguments' => array(1, 3, array()),
-      'access callback' => 'node_access',
+      'access callback' => 'file_check_access',
       'access arguments' => array('view', 1),
       'file' => 'file.inc',
     ),
@@ -218,7 +218,7 @@
       'type' => MENU_CALLBACK,
       'page callback' => 'theme',
       'page arguments' => array('file_info', 1),
-      'access callback' => 'node_access',
+      'access callback' => 'file_check_access',
       'access arguments' => array('view', 1),
     ),
     'node/%node/browser' => array(
@@ -248,7 +248,7 @@
  * Check if a properties tab should be printed..
  */
 function file_page_metadata_access($node) {
-  return FILE_PROPERTIES_TAB ? node_access('view', $node) : FALSE;
+  return FILE_PROPERTIES_TAB ? file_check_access('view', $node) : FALSE;
 }
 
 /**
@@ -738,7 +738,7 @@
 function _file_block_properties() {
   if (arg(0) == 'node' && preg_match('/(\d+)/', arg(1), $matches)) {
     $file_node = node_load($matches[1]);
-    if (is_object($file_node) && $file_node->type == 'file' && node_access('view', $file_node) && !empty($file_node->file)) {
+    if (is_object($file_node) && $file_node->type == 'file' && file_check_access('view', $file_node) && !empty($file_node->file)) {
       $metadata = array();
       $namespaces = rdf_get_namespaces();
       $info = file_get_metadata_info();
@@ -803,3 +803,36 @@
   }
 }
 
+/*
+ * checks, weather there is a custom implementation of the access check
+ * if yes, only use it, otherwise use the default node_accesss
+ */
+function file_check_access($op, $node) {
+     if(count(module_implements('file_custom_access')) > 0) {
+         // we have custom implementations, so lets call them onl
+         // TODO: it shoule be somehow configureable, weather all custom implemetations
+         // should be ORed or ANDed. It is possible to let the hook itself return a operator
+         // we have to watch the parethis then
+        return file_no_false(module_invoke_all('file_custom_access', $op, $node));
+    }
+
+    // else do the default access check
+    return node_access($op, $node);
+}
+
+/*
+ * checks if the array has any false values.
+ * Returns true if nothing found
+ * In the case, the array is empty, true is returned
+ */
+function file_no_false($results) {
+    if(!is_array($results) || count($results) == 0)
+        return true;
+
+    foreach($results as $result) {
+        if($result === false)
+            return false;
+    }
+    // else
+    return true;
+}
Index: file.pages.inc
===================================================================
--- file.pages.inc	(revision 128)
+++ file.pages.inc	(working copy)
@@ -143,7 +143,7 @@
 
   if (is_numeric($nid)) {
     $node = node_load($nid);
-    if (node_access('view', $node) && $node->type == 'file' && db_result(db_query("SELECT f.* FROM {file_nodes} f WHERE f.nid = %d AND (f.uri = '%s' OR f.uri = '%s')", $node->nid, $uri, $parent_uri))) {
+    if (file_check_access('view', $node) && $node->type == 'file' && db_result(db_query("SELECT f.* FROM {file_nodes} f WHERE f.nid = %d AND (f.uri = '%s' OR f.uri = '%s')", $node->nid, $uri, $parent_uri))) {
       $access = TRUE;
     }
   }
Index: contrib/attach/file_attach.module
===================================================================
--- contrib/attach/file_attach.module	(revision 128)
+++ contrib/attach/file_attach.module	(working copy)
@@ -1,7 +1,7 @@
 <?php
 // $Id: file_attach.module,v 1.41 2009/02/25 14:17:47 miglius Exp $
 
-/**
+/**file_attach_no_falsefile_attach_no_false
  * @file
  * Allows attaching uploaded files to nodes and comments
  */
@@ -431,7 +431,7 @@
       if (preg_match('/^n_(\d+)$/', $fid, $matches)) {
         $node = node_load($matches[1]);
         $form_state['values']['files'][$fid] = array_merge((array)$node->file, $file);
-        if (!node_access('update', $node)) {
+        if (!file_attach_check_access('update', $node)) {
           $form_state['values']['files'][$fid]['nochange'] = 1;
         }
       }
@@ -460,9 +460,9 @@
   // Attach already saved file node.
   if (isset($form_state['values']['attach_saved']) && preg_match('/^\[(\d+)\]/', $form_state['values']['attach_saved'], $matches)) {
     if (($node = node_load($matches[1])) && is_object($node->file)) {
-      if (node_access('view', $node)) {
+      if (file_attach_check_access('view', $node)) {
         $node->file->name = $node->title;
-        if (!node_access('update', $node)) {
+        if (!file_attach_check_access('update', $node)) {
           $node->file->nochange = 1;
         }
         _file_attach_file($form_state, $node->file);
@@ -603,7 +603,7 @@
     $i = 0;
     while (($row = db_fetch_object($result)) && $i < 10) {
       $node = node_load($row->nid);
-      if (node_access('view', $node)) {
+      if (file_attach_check_access('view', $node) ) {
         $matches[] = array(
           'nid'     => $node->nid,
           'title'   => check_plain($node->title),
@@ -781,12 +781,13 @@
  */
 function _file_attach_load($nid, $vid, $cid = 0) {
   $files = array();
+
   $result = db_query('SELECT fa.* FROM {file_attachments} fa WHERE fa.nid = %d AND fa.vid = %d AND fa.cid = %d ORDER BY fa.weight', $nid, $vid, $cid);
   while ($row = db_fetch_object($result)) {
     $node_file = node_load($row->fnid);
-    if (node_access('view', $node_file)) {
+    if (file_attach_check_access('view', $node_file)) {
       $extras = array('name' => $node_file->title, 'list' => $row->list, 'weight' => $row->weight);
-      if (!node_access('update', $node_file)) {
+      if (!file_attach_check_access('update', $node_file)) {
         $extras['nochange'] = 1;
       }
       $files['n_'. $row->fnid] = (object)array_merge((array)$node_file->file, $extras);
@@ -922,7 +923,7 @@
 
       // Save a new file node title.
       $file_node = node_load($file->nid);
-      if (node_access('update', $file_node)) {
+      if (file_attach_check_access('update', $file_node)) {
         if ($file_node->title != trim($file->name)) {
           $file_node->title = trim($file->name);
           node_save($file_node);
@@ -952,7 +953,7 @@
     if (is_object($file_node) && $file_node->type == 'file' && !empty($file_node->file)) {
       $result = db_query(db_rewrite_sql("SELECT n.* FROM {node} n INNER JOIN {file_attachments} fa  ON n.nid = fa.nid WHERE n.vid = fa.vid AND fa.list = '1' AND fa.fnid = %d"), $file_node->nid);
       while ($node = db_fetch_object($result)) {
-        if (node_access('view', $node)) {
+        if (file_attach_check_access('view', $node)) {
           $nodes[] = $node;
         }
       }
@@ -989,3 +990,25 @@
   }
 }
 
+/*
+ * implementes the file_access_check_hook *
+ */
+function file_attach_file_custom_access($op,$node)  {
+    return file_attach_check_access($op,$node);
+}
+/*
+ * checks, weather there is a custom implementation of the access check
+ * if yes, only use it, otherwise use the default node_accesss
+ */
+function file_attach_check_access($op,$node) {
+    if(count(module_implements('file_attach_custom_access')) > 0) {
+         // we have custom implementations, so lets call them onl
+         // TODO: it shoule be somehow configureable, weather all custom implemetations
+         // should be ORed or ANDed. It is possible to let the hook itself return a operator
+         // we have to watch the parethis then
+        return file_no_false(module_invoke_all('file_attach_custom_access', $op, $node));
+    }
+
+    // else do the default access check
+    return node_access($op, $node);
+}
\ No newline at end of file

