--- C:\wamp\www\drupal3\sites\all\modules\apachesolr\apachesolr_search.module	2008-07-20 02:22:44.000000000 +1200
+++ C:\wamp\www\drupal3\sites\all\modules\apachesolr\apachesolr_search.module.new	2008-09-12 23:19:00.839688600 +1200
@@ -75,9 +75,54 @@
           }
         }
         $params['start'] = $_GET['page'] * $params['rows'];
+        
+        /* Access Control Stuff */
+        $start = microtime();
+        global $fc;
+        $params_access = $params;
+        $params_access['fl']= 'nid,type,'. implode(',', $params['facet.field']); //we only need nid, type and status to call node_access, but to correct the facet numbering we need all the facated fields too.
+        $response = $solr->search($query->get_query(), 0, 1000000, $params_access);//I can't see a way of returning everything, so I just use a high limit for the max rows
+        $total = $response->numFound;
+        foreach ($response->documents as $doc) {
+          $node->nid = $doc->nid;  //build a thin node object for passing to node_access
+          $node->type = $doc->type;
+          $node->status = 1;
+          if (node_access('view', $node)) {
+            if (count($nid_granted) < $params['rows'] && $result_rows >= $params['start']) { //if we are looking at a node that should be displayed on the current page
+              $nid_granted[] = $node->nid; //remember the node
+            }
+          }
+          else { //access denied
+            $total--;  //decrease the overall total number of results
+            foreach ($response->facets as $field => $field_items){ //step through each facet field and count the number of terms that should be removed
+              $terms_to_subtract = array_intersect((array)array_keys($field_items), array_values((array)$doc->$field)); //cast as array for when there is only one result
+              foreach ($terms_to_subtract as $term) {
+                $fc[$field][$term]++;
+              }
+            }
+            if(count($nid_granted) < $params['rows'] && $result_rows >= $params['start']) {  //work out how many extra rows need to be appended to the result set of the current page, so that when the list is filtered, there are the correct number of nodes left.
+              $extra_rows++;
+            }
+          }
+          $result_rows++;  //keep track of how far through the result set we are
+        }
+        $params['rows'] += $extra_rows; //add on those extra rows 
+        $start_norm = microtime();
+        /* End Access Control Stuff */
         $response = $solr->search($query->get_query(), $params['start'], $params['rows'], $params);
         apachesolr_has_searched(TRUE);
-        $total = $response->numFound;
+        /* Facet correction */
+        $end_norm = microtime();
+        foreach ((array)$response->facets as $field => $field_items) { //subtract off the number of facet terms that belong to the access denied nodes
+          foreach ((array)$field_items as $term => $count) {
+            $c = $response->facets->$field;  //this $c business is to get around a php "cannot access empty property" error  see http://bugs.php.net/bug.php?id=28444.  There could be a cleaner way of doing this, but I don't use ojects much (for reasons such as this)
+            $c[$term] = $c[$term] - $fc[$field][$term];  //subtract off the facet list the number of terms that present in the access denied list
+            $response->facets->$field = $c;
+          }
+        }
+        $end = microtime();
+        /* End Facet correction */
+
         // The response is cached so that it is accessible to the blocks and anything
         // else that needs it beyond the initial search.
         apachesolr_static_response_cache($response);
@@ -85,6 +130,14 @@
         if ($total > 0) {
           static $users = array();
           foreach ($response->documents as $doc) {
+            /*access control stuff*/
+            if ($doc->nid == $nid_granted[0]) {  //knock out the access denied nodes
+              array_shift($nid_granted);
+            }
+            else {
+              continue; //skip this result then carry on
+            }
+            /*end access control stuff */
             $extra = node_invoke_nodeapi(&$doc, 'search result');
             $extra['score'] = $doc->score;
             $snippet = search_excerpt($keys, $doc->body);
@@ -104,6 +157,11 @@
         }
         // Set breadcrumb
         drupal_set_breadcrumb($query->get_breadcrumb());
+        /* access control debug */
+        $performance_hit = $end - $start - ($end_norm - $start_norm);
+        $change = sprintf('%d',($end_norm - $start_norm) /  ($end - $start) * 100);
+        drupal_set_message("The access control implementation had a performance hit of $performance_hit ms for this query, adding $change% to the time it would have otherwise taken");
+        /* end access control debug */
         return $results;
 
       } // try
