How is it possible for a module to detect when Drupal is outputting the "access denied" page?
I know how to do it with Drupal 6; I need to know how to do it with Drupal 7 or higher version.

share|improve this question

5 Answers

I do this in Boost 7.x. It's not pretty, but it does get the job done.

function boost_page_delivery_callback_alter(&$callback, $set = FALSE) {
  if ($callback == 'drupal_deliver_html_page') {
    $callback = 'boost_deliver_html_page';
  }
}

function boost_deliver_html_page($page_callback_result) {
  global $_boost;

  // Menu status constants are integers; page content is a string or array.
  if (is_int($page_callback_result)) {
    // @todo: Break these up into separate functions?
    switch ($page_callback_result) {

      // …

      case MENU_ACCESS_DENIED:
        // 403 page.
        $_boost['menu_item']['status'] = 403;
        break;

      // …

    }
    // …
  }
  // …   
}
share|improve this answer

You can set which pages are displayed when 403 & 404 errors occurs (admin/settings/error-reporting).

I guess you can add a new page in your hook_menu(), then set this page as the 403 error callback. When your custom menu callback is hit, you know you're outputting the "access denied" page!

share|improve this answer

Your module could intercept the value of "Default 403 (access denied) page" which is modified by the page "Administer > Site configuration > Error reporting":

  1. In hook_enable, using variable_get/variable_set, copy the existing value to a secondary variable and replace the variable by your own path (which you registered using hook_menu).

  2. alter the "Error reporting" form using hook_form_FORM_ID_alter to read from/write to the secondary variable

  3. If you want to be completely invisible to the user, your page callback to could call drupal_goto( the_value_of_the_secondary_variable ).

  4. In hook_disable, restore the value from the secondary variable.


And that's it, your module gets notified in a clean way (and invisible to the user) when "Access denied" is triggered.

share|improve this answer

Surely you could use PHP's get_headers() function?

http://php.net/manual/en/function.get-headers.php

The first element in the array returned will be the response code. If it contains '403' then Drupal returned an "access denied" page.

I'm not sure where the best place to call it would be. Probably hook_exit(), depending on your needs:

http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_exit/6

share|improve this answer
up vote 2 down vote accepted

In Drupal 7, the function that returns the already set HTTP headers is drupal_get_http_header(), which requires the HTTP header name as parameter. Looking at authorize_access_denied_page(), and drupal_fast_404() code makes clear which values to pass to that function.

  // authorize_access_denied_page()
  drupal_add_http_header('Status', '403 Forbidden');
  watchdog('access denied', 'authorize.php', NULL, WATCHDOG_WARNING);
  drupal_set_title('Access denied');
  return t('You are not allowed to access this page.');
// drupal_fast_404()
if ($fast_paths && preg_match($fast_paths, $_GET['q'])) {
  drupal_add_http_header('Status', '404 Not Found');
  $fast_404_html = variable_get('404_fast_html', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>');
  // Replace @path in the variable with the page path.
  print strtr($fast_404_html, array('@path' => check_plain(request_uri())));
  exit;
}

When the "Status" header starts with 403, then Drupal output an access denied page.

Make sure the call to drupal_get_http_header('Status') happens late. Calling during hook_init() is too soon, but calling it during hook_page_alter() (or any theme preprocess hook) will have the updated header information.

share|improve this answer

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.