You are here

protected_node.install in Protected Node 6

File

protected_node.install
View source
<?php

/*
 * @file
 * Protected node module: install the protected nodes schema.
 */

/**
 * Implementation of hook_requirements().
 *
 * Checks whether any role has access to protected nodes.
 *
 * @link http://api.drupal.org/api/function/hook_requirements/6
 *
 * @param string $phase  The current phase.
 */
function protected_node_requirements($phase) {
  $reqs = array();
  if ($phase == 'runtime') {

    // test whether any roles were given rights to the handle protected nodes
    // Note: since this is the runtime phase we do not have to force a
    //       load of the .module file.
    $perms = protected_node_perm();
    $likes = array();
    foreach ($perms as $perm) {
      $likes[] = "perm LIKE '%%%s%%'";
    }
    $sql = "SELECT COUNT(rid) FROM {permission} WHERE " . implode(' OR ', $likes);
    $roles = db_result(db_query($sql, $perms));
    if ($roles) {
      $reqs['protected_node_rights'] = array(
        'title' => t('Protected nodes access rights'),
        'value' => format_plural($roles, 'One role has access to protected nodes. (!edit)', '@count roles have access to protected nodes. (!edit)', array(
          '!edit' => l('edit permissions', 'admin/user/permissions', array(
            'fragment' => 'module-protected_node',
          )),
        )),
        'severity' => REQUIREMENT_OK,
      );
    }
    else {
      $reqs['protected_node_rights'] = array(
        'title' => t('Protected nodes access rights'),
        'value' => t('None of the existing roles has !access', array(
          '!access' => l('permission to access protected nodes', 'admin/user/permissions', array(
            'fragment' => 'module-protected_node',
          )),
        )),
        'description' => t('Without giving access to at least one role, no-one other than the administrator (UID=1) can created protected nodes or view protected nodes'),
        'severity' => REQUIREMENT_ERROR,
      );
    }

    // File attachment are not currently protected
    switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
      case FILE_DOWNLOADS_PRIVATE:
        if (!module_exists('upload')) {
          $reqs['protected_node_attachments'] = array(
            'title' => t('Protected nodes attachments'),
            'value' => t('Private attachments protection cannot work without the !upload.', array(
              '!upload' => l('upload module', 'admin/build/modules', array(
                'fragment' => 'edit-status-upload',
              )),
            )),
            'description' => t('Please, install the upload module to protect private attachments with the node password.'),
            'severity' => REQUIREMENT_ERROR,
          );
        }
        else {
          $reqs['protected_node_attachments'] = array(
            'title' => t('Protected nodes attachments'),
            'value' => t('Private attachments are protected by Protected node'),
            'description' => t('Remember that your file are really protected only if uploaded as attachments. Other methods may make your files public and thus unprotectable.'),
            'severity' => REQUIREMENT_OK,
          );
        }
        break;
      default:
        $reqs['protected_node_attachments'] = array(
          'title' => t('Protected nodes attachments'),
          'value' => t('Public attachments are never protected by Protected node'),
          'description' => t('Public attachments are by definition public and the Protected node module cannot intervene since your web server answers those requests on its own without any interventions by Drupal. This obviously means there is no way we could prevent the download of a public file.'),
          'severity' => REQUIREMENT_WARNING,
        );
        break;
    }
  }
  return $reqs;
}

/**
 * Implementation of hook_schema().
 */
function protected_node_schema() {
  $schema['protected_nodes'] = array(
    'description' => t('The table to store the node - password hash pairs.'),
    'fields' => array(
      'nid' => array(
        'description' => t('The primary identifier for a node'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'protected_node_is_protected' => array(
        'description' => t('Whether this node is currently protected.'),
        'type' => 'int',
        'size' => 'small',
        'not null' => TRUE,
        'default' => 0,
      ),
      'protected_node_passwd' => array(
        'description' => t('The sha1 hashed password for the given node.'),
        'type' => 'char',
        'length' => 40,
        'not null' => TRUE,
        'default' => '',
      ),
      'protected_node_passwd_changed' => array(
        'description' => t('Date when the password was last changed'),
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'protected_node_show_title' => array(
        'description' => t('Whether the title of the node should also be protected.'),
        'type' => 'int',
        'size' => 'small',
        'not null' => TRUE,
        'default' => 0,
      ),
      'protected_node_hint' => array(
        'description' => t('A hint about the password on this node.'),
        'type' => 'text',
      ),
    ),
    'indexes' => array(
      'protected_is_protected' => array(
        'protected_node_is_protected',
      ),
      'protected_passwd' => array(
        'protected_node_passwd',
      ),
    ),
    'primary key' => array(
      'nid',
    ),
  );
  return $schema;
}

/**
 * Implementation of hook_install().
 */
function protected_node_install() {
  drupal_install_schema('protected_node');
  db_query("UPDATE {system} SET weight = 80 WHERE name = 'protected_node' AND type = 'module'");
}

/**
 * Implementation of hook_uninstall().
 */
function protected_node_uninstall() {
  drupal_uninstall_schema('protected_node');
  db_query("DELETE FROM {variable} WHERE name LIKE 'protected_node_%%'");
}

/**
 * Implementation of hook_update_N().
 *
 * We don't need a variable length column just 40 char one for the sha1 hash
 */
function protected_node_update_3() {
  $ret = array();
  db_change_field($ret, 'protected_nodes', 'passwd', 'passwd', array(
    'type' => 'char',
    'length' => 40,
    'not null' => TRUE,
  ));
  return $ret;
}

/**
 * Implementation of hook_update-N()
 *
 * Altering node weight from 100 to 80
 * fixing issue #296685
 *
 */
function protected_node_update_4() {
  $ret = array();
  $ret[] = update_sql("UPDATE {system} SET weight = 80 WHERE name = 'protected_node' AND type = 'module'");
  return $ret;
}

/**
 * Implementation of hook_update_N().
 */
function protected_node_update_6000() {
  global $db_type;
  $ret = array();

  // we want an is_protected field so we can load it easily and
  // we can keep the other parameters even when we unprotect
  // a node (although it's not that important right now.)
  $field = array(
    'type' => 'int',
    'size' => 'small',
    'not null' => TRUE,
    'default' => 0,
  );
  db_add_field($ret, 'protected_nodes', 'protected_node_is_protected', $field);
  db_add_index($ret, 'protected_nodes', 'protected_is_protected', array(
    'protected_node_is_protected',
  ));

  // at this time all the protected node entries meant that the
  // nodes were protected; yet, we don't want the default to be 1
  $sql = "UPDATE {protected_nodes} SET protected_node_is_protected = 1";
  $ret[] = update_sql($sql);

  // rename the password so we can directly append to the $node object
  // without too much potential for clashes

  //$field = array(

  //  'description' => t('The sha1 hashed password for the given node.'),
  //  'type' => 'char',
  //  'length' => 40,
  //  'not null' => TRUE,
  //  'default' => '',

  //);

  //db_change_field($ret, 'protected_nodes', 'passwd', 'protected_node_passwd', $field);

  //
  // Core destroys the data in this case because it uses a CAST(passwd AS char) instead
  // of CHAR(40). (at least that breaks under PostgreSQL.)
  // And of course MySQL does not support the RENAME COLUMN feature...
  switch ($db_type) {
    case 'mysql':
    case 'mysqli':
      $sql = "ALTER TABLE {protected_nodes} CHANGE passwd protected_node_passwd CHAR(40) NOT NULL";
      break;
    case 'pgsql':

      // also works in Oracle9i+
      $sql = "ALTER TABLE {protected_nodes} RENAME COLUMN passwd TO protected_node_passwd";
      break;
  }
  $ret[] = update_sql($sql);

  // create a column for the show title flag
  // then copy the flag status from the {variable} table
  $field = array(
    'description' => t('Whether the title of the node should also be protected.'),
    'type' => 'int',
    'size' => 'small',
    'not null' => TRUE,
    'default' => 0,
  );
  db_add_field($ret, 'protected_nodes', 'protected_node_show_title', $field);

  // the variable value is TRUE, no need to read it
  $sql_var = "SELECT name FROM {variable} WHERE name LIKE 'protected_node-%-show_title'";
  $sql_update = "UPDATE {protected_nodes} SET protected_node_show_title = 1 WHERE nid = %d";
  $result = db_query($sql_var);
  $ret[] = array(
    'success' => $result !== FALSE,
    'query' => check_plain($sql_var),
  );
  while ($row = db_fetch_array($result)) {

    // get the node identifier
    preg_match('/protected_node-([0-9]+)-show_title/', $row['name'], $match);

    // the update may do nothing if the node was deleted
    $r = db_query($sql_update, $match[1]);
    if ($r === FALSE) {

      // only record failures otherwise we could get thousands of entries...
      $ret[] = array(
        'success' => FALSE,
        'query' => check_plain($sql_update),
      );
    }

    // remove the variable
    variable_del($row['name']);
  }
  $field = array(
    'description' => t('Date when the password was last changed'),
    'type' => 'int',
    'not null' => TRUE,
    'default' => 0,
  );
  db_add_field($ret, 'protected_nodes', 'protected_node_passwd_changed', $field);

  // request for a rebuild of the node access table

  //node_access_needs_rebuild(TRUE);
  return $ret;
}

/**
 * Implementation of hook_update_N().
 */
function protected_node_update_6001() {
  $ret = array();

  // we want an is_protected field so we can load it easily and
  // we can keep the other parameters even when we unprotect
  // a node (although it's not that important right now.)
  $field = array(
    'description' => t('A hint about the password on this node.'),
    'type' => 'text',
  );
  db_add_field($ret, 'protected_nodes', 'protected_node_hint', $field);
  $result = db_query('SELECT rid, perm FROM {permission}');
  while ($row = db_fetch_object($result)) {
    if (strpos($row->perm, 'edit protected ') !== FALSE) {
      $updated_perm = str_replace('edit protected content', 'edit any password', $row->perm);
      $updated_perm = preg_replace('/edit protected ([^,]+)/', 'edit \\1 password', $updated_perm);
      $sql = "UPDATE {permission} SET perm = '%s' WHERE rid = %d";
      $r = db_query($sql, $updated_perm, $row->rid);
      $ret[] = array(
        'success' => $r !== FALSE,
        'query' => check_plain($sql),
      );
    }
  }
  return $ret;
}

/**
 * Implementation of hook_update_N().
 */
function protected_node_update_6002() {
  $ret = array();

  // change the nid field from a serial to an int
  $field = array(
    'description' => t('The primary identifier for a node'),
    'type' => 'int',
    'unsigned' => TRUE,
    'not null' => TRUE,
  );
  db_change_field($ret, 'protected_nodes', 'nid', 'nid', $field);
  return $ret;
}

/**
 * Implementation of hook_update_N().
 *
 * Make sure the global password isn't saved in clear.
 * (unfortunately this doesn't fix it in backups...)
 */
function protected_node_update_6003() {
  $ret = array();
  variable_del('protected_node_global_password_field');
  drupal_set_message(t('Please change your global Protected node password as it may have been compromised.'), 'warning');
  return $ret;
}

// vim: ts=2 sw=2 et syntax=php

Functions

Namesort descending Description
protected_node_install Implementation of hook_install().
protected_node_requirements Implementation of hook_requirements().
protected_node_schema Implementation of hook_schema().
protected_node_uninstall Implementation of hook_uninstall().
protected_node_update_3 Implementation of hook_update_N().
protected_node_update_4 Implementation of hook_update-N()
protected_node_update_6000 Implementation of hook_update_N().
protected_node_update_6001 Implementation of hook_update_N().
protected_node_update_6002 Implementation of hook_update_N().
protected_node_update_6003 Implementation of hook_update_N().