You are here

protected_node.module in Protected Node 5

File

protected_node.module
View source
<?php

/*
 * @file
 * Protected node module.
 *
 * This module allows nodes to be protected.
 */

/**
 * Implementation of hook_help().
 * @link http://api.drupal.org/api/function/hook_help/5
 *
 * @param string $section
 * @return string
 */
function protected_node_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('With this module anybody who has edit protected content right can password protect his or her own node.');
      break;
  }
}

/**
 * Implementation of hook_requirements(). Checks for at least role who has access to protected node functionality.
 * @link http://api.drupal.org/api/function/hook_requirements/5
 *
 * @param string $phase
 */
function protected_node_requirements($phase) {
  if ($phase == 'runtime') {
    $perms = protected_node_perm();
    $likes = array();
    foreach ($perms as $perm) {
      $likes[] = "perm LIKE '%" . $perm . "%'";
    }
    $sql = "SELECT rid FROM {permission} WHERE " . implode(' OR ', $likes);
    $roles = db_num_rows(db_query($sql));
    if ($roles) {
      $reqs['protected_node'] = array(
        'title' => t('Protected nodes access rights'),
        'value' => t('At least one of the roles has access to protected contents'),
        'severity' => REQUIREMENT_OK,
      );
    }
    else {
      $reqs['protected_node'] = array(
        'title' => t('Protected nodes access rights'),
        'value' => t('None of the roles has !access', array(
          '!access' => l('access to protected contents', 'admin/user/access', array(), NULL, 'module-protected_node'),
        )),
        'description' => t('Without giving access at least one of the available roles no-one can protect nodes or access protected contents'),
        'severity' => REQUIREMENT_ERROR,
      );
    }
    return $reqs;
  }
}

/**
 * Implementation of hook_perm().
 * @link http://api.drupal.org/api/function/hook_perm/5
 */
function protected_node_perm() {
  $perms = array(
    'access protected content',
    'bypass password protection',
    'edit protected content',
  );
  foreach (array_keys(node_get_types()) as $type) {
    $perms[] = 'edit protected ' . $type;
  }
  return $perms;
}

/**
 * Implementation of hook_form_alter().
 * @link http://api.drupal.org/api/function/hook_form_alter/5
 */
function protected_node_form_alter($form_id, &$form) {

  // check if this node type should be protected
  if ($form['#id'] == 'node-form' && (user_access('edit protected content') || user_access('edit protected ' . $form['type']['#value']))) {
    $form['protected_node'] = array(
      '#type' => 'fieldset',
      '#description' => t('Here if you check the checkbox and provide a password your newly created node will be password protected.'),
      '#title' => t('Protected node'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['protected_node']['is_protected'] = array(
      '#type' => 'checkbox',
      '#title' => t('Node is protected'),
      '#description' => t('Check here if this content should be protected by a password.'),
      '#default_value' => $form['#node']->is_protected,
    );
    $form['protected_node']['was_protected'] = array(
      '#type' => 'hidden',
      '#default_value' => $form['#node']->was_protected,
    );
    $form['protected_node']['password'] = array(
      '#type' => 'password_confirm',
      '#description' => t('Enter the node password here.'),
      '#size' => 20,
      '#default_value' => $form['#node']->password,
    );
  }
}

/**
 * Implementation of hook_nodeapi().
 * @link http://api.drupal.org/api/function/hook_nodeapi/5
 */
function protected_node_nodeapi(&$node, $op, $arg = 0, $page = 0) {
  global $user;
  switch ($op) {
    case 'load':
      $output['is_protected'] = protected_node_isset_protected($node->nid);
      $output['was_protected'] = $output['is_protected'];
      return $output;
      break;
    case 'delete':
      protected_node_unset_protected($node->nid);
      break;
    case 'insert':
      if ($node->is_protected && (!empty($node->password) || isset($_SESSION['_protected_node']['entered_password']))) {
        $pwd = isset($_SESSION['_protected_node']['entered_password']) ? $_SESSION['_protected_node']['entered_password'] : $node->password;
        unset($_SESSION['_protected_node']['entered_password']);
        protected_node_set_protected($node->nid, $pwd);
      }
      break;
    case 'validate':
      if ($node->is_protected && !empty($node->password)) {
        $_SESSION['_protected_node']['entered_password'] = $node->password;
      }
      break;
    case 'update':

      // Protected flag was switched off?
      if ($node->was_protected && !$node->is_protected) {
        protected_node_unset_protected($node->nid);
      }
      if ($node->is_protected && (!empty($node->password) || isset($_SESSION['_protected_node']['entered_password']))) {
        if (db_result(db_query('SELECT count(*) FROM {protected_nodes} WHERE nid = %d', $node->nid)) > 0) {
          $pwd = isset($_SESSION['_protected_node']['entered_password']) ? $_SESSION['_protected_node']['entered_password'] : $node->password;
          unset($_SESSION['_protected_node']['entered_password']);
          protected_node_set_protected($node->nid, $pwd);
        }
        else {
          protected_node_nodeapi($node, 'insert', $arg, $page);
        }
      }
      break;
    case 'view':
      if ($node->is_protected && !user_access('bypass password protection')) {

        // If we have been accessed from cron.php (f.e. search indexing)
        if (variable_get('cron_semaphore', FALSE)) {
          $node->title = '';
          $node->teaser = '';
          $node->body = '';
          $node->content = array();
        }
        else {
          if (!$user->uid && variable_get('cache', 0)) {
            $GLOBALS['conf']['cache'] = FALSE;
          }
          if ($node->uid !== $user->uid) {

            // If node is protected and not teaser nor page view and not owner of node
            if (!isset($_SESSION['_protected_node']['passwords'][$node->nid])) {
              if (!$arg) {
                $_SESSION['_protected_node']['current'] = $node->nid;
                drupal_goto('protected-node', 'destination=' . $_GET['q']);
              }
              else {
                $node->teaser = '';
                $node->body = '';
                $node->content = array();
              }
            }
          }
        }
      }
      break;
  }
}

/**
 * Implementation of hook_menu().
 * @link http://api.drupal.org/api/function/hook_menu/5
 */
function protected_node_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/protected_node',
      'title' => t('Protected node'),
      'description' => t('Here you change protected node settings'),
      'callback' => 'drupal_get_form',
      'callback arguments' => 'protected_node_admin_settings',
      'access' => user_access('administer site configuration'),
    );
    $items[] = array(
      'path' => 'protected-node',
      'title' => t('Protected node - Enter Password'),
      'description' => t('Here you can enter the password for the node'),
      'callback' => 'drupal_get_form',
      'callback arguments' => 'protected_node_enterpassword',
      'access' => user_access('access protected content'),
      'type' => MENU_CALLBACK,
    );
  }
  return $items;
}

/**
 * Implementation of hook_file_download().
 * @link http://api.drupal.org/api/function/hook_file_download/5
 */
function protected_node_file_download($file) {
  global $user;
  $db_file = db_result(db_query('SELECT n.nid FROM {files} f, {protected_nodes} pn, {node} n WHERE pn.nid = f.nid AND f.nid = n.nid AND f.filename = \'%s\'', $file));
  if (db_error() || $db_file === FALSE || $user->uid == $db_file || $_SESSION['_protected_node']['passwords'][$db_file] || user_access('bypass password protection')) {
    return array();
  }
  else {
    return -1;
  }
}

/*
 * Helper functions
 */

/**
 * Simple function to make sure we don't respond with grants when disabling ourselves.
 */
function protected_node_disabling($set = NULL) {
  static $disabling = FALSE;
  if ($set !== NULL) {
    $disabling = $set;
  }
  return $disabling;
}

/**
 *
 */
function protected_node_enterpassword() {
  if (!isset($_GET['destination'])) {

    // Illegal call
    watchdog('protected_node', t('Illegal call to /protected-node'), WATCHDOG_WARN);
    drupal_access_denied();
  }
  $info = variable_get('protected_node_info', '');
  if (module_exists('token')) {
    $info = token_replace($info, 'node', node_load($_SESSION['_protected_node']['current']));
  }
  $form['protected_node'] = array(
    '#value' => check_plain($info),
  );
  $form['protected_node_enterpassword'] = array(
    '#type' => 'fieldset',
    '#description' => t('The node you are trying to view is password protected. Please enter password below to proceed.'),
    '#collapsible' => FALSE,
  );
  $form['protected_node_enterpassword']['password'] = array(
    '#type' => 'password',
    '#title' => t('Node password'),
    '#size' => 20,
  );
  $form['protected_node_enterpassword']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('OK'),
  );
  return $form;
}

/**
 *
 */
function protected_node_enterpassword_validate($form_id, $form) {
  global $_protected_node_salt;
  $cnt = db_result(db_query('SELECT COUNT(*) FROM {protected_nodes} WHERE passwd = \'%s\' AND nid = %d', sha1($_protected_node_salt . $form['password']), $_SESSION['_protected_node']['current']));
  if ($cnt < 1) {
    form_set_error('password', t('Incorrect password!'));
  }
}

/**
 *
 */
function protected_node_enterpassword_submit($form_id, $form) {
  $_SESSION['_protected_node']['passwords'][$_SESSION['_protected_node']['current']] = TRUE;
  unset($_SESSION['_protected_node']['current']);
}

/**
 * Define the settings form
 *
 * @return $form The settings form
 */
function protected_node_admin_settings() {
  $form['protected_node_info'] = array(
    '#type' => 'textarea',
    '#title' => t('Password page info'),
    '#default_value' => variable_get('protected_node_info', ''),
    '#description' => t('You can use node type tokens from the token module if you have installed it previously.'),
  );
  return system_settings_form($form);
}

/**
 * Sets the given node to protected with the provided password.
 * The password cannot be empty.
 *
 * If the node already password protected this method changes the password
 * to the one you provided as $password parameter.
 *
 * @param int $nid The node ID to set protected or change passsword on.
 * @param string $password The password you wish to set.
 * @return boolean TRUE if the action was successful, FALSE otherwise.
 */
function protected_node_set_protected($nid, $password) {
  global $protected_node_salt;
  if (empty($password) || !is_numeric($nid)) {
    return FALSE;
  }
  $success = FALSE;
  if (protected_node_isset_protected($nid)) {
    $success = db_query('UPDATE {protected_nodes} SET passwd = \'%s\' WHERE nid = %d', sha1($protected_node_salt . $password), $nid);
  }
  else {
    $success = db_query('INSERT INTO {protected_nodes} (nid, passwd) VALUES (%d, \'%s\')', $nid, sha1($protected_node_salt . $password));
  }
  return $success !== FALSE;
}

/**
 * This method removes the protected flag from the specified node.
 * If the node wasn't protected this method returns FALSE.
 *
 * @param int $nid The node id you wish to remove protection from.
 * @return boolean TRUE if the action was successful, FALSE otherwise.
 */
function protected_node_unset_protected($nid) {
  if (!is_numeric($nid)) {
    return FALSE;
  }
  $success = db_query('DELETE FROM {protected_nodes} WHERE nid = %d', $nid);
  return $success !== FALSE;
}

/**
 * This method determines the protected flag status for the given node id.
 *
 * @param int $nid The node id you wish to check for.
 * @return boolean TRUE if the node identified by the nid you provided is protected, FALSE otherwise.
 */
function protected_node_isset_protected($nid) {
  if (!is_numeric($nid)) {
    return FALSE;
  }
  $nodes = db_num_rows(db_query('SELECT nid FROM {protected_nodes} WHERE nid = %d', $nid));
  if ($nodes > 0) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}
if (module_exists('views')) {
  include dirname(__FILE__) . DIRECTORY_SEPARATOR . 'protected_node.views.inc';
}

Functions

Namesort descending Description
protected_node_admin_settings Define the settings form
protected_node_disabling Simple function to make sure we don't respond with grants when disabling ourselves.
protected_node_enterpassword
protected_node_enterpassword_submit
protected_node_enterpassword_validate
protected_node_file_download Implementation of hook_file_download(). @link http://api.drupal.org/api/function/hook_file_download/5
protected_node_form_alter Implementation of hook_form_alter(). @link http://api.drupal.org/api/function/hook_form_alter/5
protected_node_help Implementation of hook_help(). @link http://api.drupal.org/api/function/hook_help/5
protected_node_isset_protected This method determines the protected flag status for the given node id.
protected_node_menu Implementation of hook_menu(). @link http://api.drupal.org/api/function/hook_menu/5
protected_node_nodeapi Implementation of hook_nodeapi(). @link http://api.drupal.org/api/function/hook_nodeapi/5
protected_node_perm Implementation of hook_perm(). @link http://api.drupal.org/api/function/hook_perm/5
protected_node_requirements Implementation of hook_requirements(). Checks for at least role who has access to protected node functionality. @link http://api.drupal.org/api/function/hook_requirements/5
protected_node_set_protected Sets the given node to protected with the provided password. The password cannot be empty.
protected_node_unset_protected This method removes the protected flag from the specified node. If the node wasn't protected this method returns FALSE.