Index: index.php
===================================================================
RCS file: /cvs/drupal/drupal/index.php,v
retrieving revision 1.82
diff -u -Ffunction -r1.82 index.php
--- index.php 21 Aug 2004 06:42:34 -0000 1.82
+++ index.php 18 Oct 2006 16:19:58 -0000
@@ -14,6 +14,7 @@
include_once 'includes/common.inc';
fix_gpc_magic();
+drupal_check_token();
$status = menu_execute_active_handler();
switch ($status) {
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.147
diff -u -Ffunction -r1.147 update.php
--- update.php 6 Apr 2005 19:04:02 -0000 1.147
+++ update.php 18 Oct 2006 16:31:17 -0000
@@ -208,6 +208,9 @@ function update_info() {
if (isset($_GET["op"])) {
include_once "includes/bootstrap.inc";
include_once "includes/common.inc";
+
+ // Protect against cross site request forgeries
+ drupal_check_token();
// Access check:
if (($access_check == 0) || ($user->uid == 1)) {
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.434.2.20
diff -u -Ffunction -r1.434.2.20 common.inc
--- includes/common.inc 13 Mar 2006 21:29:57 -0000 1.434.2.20
+++ includes/common.inc 18 Oct 2006 16:19:58 -0000
@@ -912,6 +912,61 @@ function format_name($object) {
*/
/**
+ * Check the form token if there is POST data for an authenticated user to defend against cross site request forgeries.
+ *
+ * $_POST will be cleared if the token is absent or incorrect.
+ *
+ */
+function drupal_check_token() {
+ global $user;
+ if ($user->uid && ($_SERVER['REQUEST_METHOD'] == 'POST') && !(isset($_POST['edit']) && isset($_POST['edit']['token']) && drupal_valid_token($_POST['edit']['token']))) {
+ drupal_set_message(t('Validation error. Please try again.'), 'error');
+ $_POST = array();
+ }
+}
+
+/**
+ * Ensure the private key variable used to generate tokens is set.
+ *
+ * @return
+ * The private key
+ */
+function drupal_get_private_key() {
+ if (!($key = variable_get('drupal_private_key', 0))) {
+ $key = mt_rand();
+ variable_set('drupal_private_key', $key);
+ }
+ return $key;
+}
+
+/**
+ * Generate a token based on $value, the current user session and private key.
+ *
+ * @param $value
+ * An additional value to base the token on
+ */
+function drupal_get_token($value = '') {
+ $private_key = drupal_get_private_key();
+ return md5(session_id() . $value . $private_key);
+}
+
+/**
+ * Validate a token based on $value, the current user session and private key or penultimate private key.
+ *
+ * @param $token
+ * The token to be validated.
+ * @param $value
+ * An additional value to base the token on
+ * @return
+ * True for a valid token, False for an invalid token.
+ */
+function drupal_valid_token($token, $value = '') {
+ return ($token == md5(session_id() . $value . variable_get('drupal_private_key', '')));
+}
+
+
+
+/**
* @defgroup form Form generation
* @{
* Functions to enable output of HTML forms and form elements.
@@ -922,6 +977,13 @@ * Drupal uses these functions to achiev
*/
/**
+ * Generate a form token based on the session and the private key to defend against cross site request forgeries.
+ */
+function form_token() {
+ return form_hidden('token', drupal_get_token());
+}
+
+/**
* Generate a form from a set of form elements.
*
* @param $form
@@ -939,7 +1001,7 @@ function form($form, $method = 'post', $
if (!$action) {
$action = request_uri();
}
- return '
\n";
+ return '\n";
}
/**
Index: modules/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/Attic/block.module,v
retrieving revision 1.162.2.5
diff -u -Ffunction -r1.162.2.5 block.module
--- modules/block.module 20 Jul 2005 11:41:57 -0000 1.162.2.5
+++ modules/block.module 18 Oct 2006 16:19:58 -0000
@@ -110,6 +110,7 @@ function block_block($op = 'list', $delt
}
function block_admin_save($edit) {
+ unset($edit['token']);
foreach ($edit as $module => $blocks) {
foreach ($blocks as $delta => $block) {
db_query("UPDATE {blocks} SET region = %d, status = %d, weight = %d, throttle = %d WHERE module = '%s' AND delta = '%s'",
Index: modules/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/Attic/comment.module,v
retrieving revision 1.347.2.10
diff -u -Ffunction -r1.347.2.10 comment.module
--- modules/comment.module 4 Apr 2006 07:09:11 -0000 1.347.2.10
+++ modules/comment.module 18 Oct 2006 16:19:58 -0000
@@ -761,7 +761,7 @@ function comment_render($node, $cid = 0)
if ((comment_user_can_moderate($node)) && $user->uid != $comment->uid && !(comment_already_moderated($user->uid, $comment->users))) {
$output .= ''. form_submit(t('Moderate comment')) .'
';
}
- $output .= '';
+ $output .= '' . form_token() . '';
}
else {
// Multiple comment view
@@ -863,7 +863,7 @@ function comment_render($node, $cid = 0)
$output .= '';
+ $output .= '' . form_token() . '';
}
$output .= '';
+ $output .= '' . form_token() . '';
if (db_num_rows($result) && (variable_get('comment_controls', 3) == 1 || variable_get('comment_controls', 3) == 2)) {
$output .= '';
+ $output .= '' . form_token() . '';
}
}
Index: modules/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/Attic/locale.module,v
retrieving revision 1.120.2.1
diff -u -Ffunction -r1.120.2.1 locale.module
--- modules/locale.module 3 May 2005 05:22:41 -0000 1.120.2.1
+++ modules/locale.module 18 Oct 2006 16:19:58 -0000
@@ -430,9 +430,23 @@ function locale_admin_string() {
$edit =& $_POST['edit'];
switch ($op) {
+ case t('Delete'):
case 'delete':
- $output .= _locale_string_delete(db_escape_string(arg(4)));
- $output .= _locale_string_seek();
+ if($edit['confirm']) {
+ $output .= _locale_string_delete(db_escape_string(arg(4)));
+ $output .= _locale_string_seek();
+ drupal_goto('admin/locale/string/search');
+ }
+ else {
+ $string = db_result(db_query("SELECT source FROM {locales_source} WHERE lid = %d", arg(4)));
+ $output = theme('confirm',
+ t('Are you sure you want to delete the following string?'),
+ 'admin/locale/string/search',
+ t('This action cannot be undone.'),
+ t('Delete'),
+ t('Cancel'),
+ check_plain($string));
+ }
break;
case 'edit':
$output .= _locale_string_edit(db_escape_string(arg(4)));
Index: modules/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/Attic/menu.module,v
retrieving revision 1.29
diff -u -Ffunction -r1.29 menu.module
--- modules/menu.module 31 Mar 2005 21:18:08 -0000 1.29
+++ modules/menu.module 18 Oct 2006 16:19:58 -0000
@@ -212,14 +212,26 @@ function menu_delete_item($mid) {
* Menu callback; hide a menu item.
*/
function menu_disable_item($mid) {
- $menu = menu_get_menu();
- $type = $menu['items'][$mid]['type'];
- $type &= ~MENU_VISIBLE_IN_TREE;
- $type &= ~MENU_VISIBLE_IN_BREADCRUMB;
- $type |= MENU_MODIFIED_BY_ADMIN;
- db_query('UPDATE {menu} SET type = %d WHERE mid = %d', $type, $mid);
- drupal_set_message(t('Menu item disabled.'));
- drupal_goto('admin/menu');
+ $op = $_POST['op'];
+ $menu = menu_get_menu();
+ switch ($op) {
+ case t('Disable'):
+ $type = $menu['items'][$mid]['type'];
+ $type &= ~MENU_VISIBLE_IN_TREE;
+ $type &= ~MENU_VISIBLE_IN_BREADCRUMB;
+ $type |= MENU_MODIFIED_BY_ADMIN;
+ db_query('UPDATE {menu} SET type = %d WHERE mid = %d', $type, $mid);
+ drupal_set_message(t('Menu item disabled.'));
+ drupal_goto('admin/menu');
+ break;
+ default:
+ $output = theme('confirm',
+ t('Are you sure you want disable %menu-item?', array('%menu-item' => theme('placeholder', $menu['items'][$mid]['title']))),
+ 'admin/menu',
+ ' ',
+ t('Disable'));
+ print theme('page', $output);
+ }
}
/**
Index: modules/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/Attic/node.module,v
retrieving revision 1.485.2.16
diff -u -Ffunction -r1.485.2.16 node.module
--- modules/node.module 9 Jul 2006 11:27:38 -0000 1.485.2.16
+++ modules/node.module 18 Oct 2006 16:19:58 -0000
@@ -705,6 +705,16 @@ function node_menu($may_cache) {
'access' => user_access('administer nodes'),
'weight' => 2,
'type' => MENU_LOCAL_TASK);
+ $items[] = array('path' => 'node/'. arg(1) .'/rollback-revision', 'title' => t('Revert revision'),
+ 'callback' => 'node_page',
+ 'access' => user_access('administer nodes'),
+ 'weight' => 1,
+ 'type' => MENU_CALLBACK);
+ $items[] = array('path' => 'node/'. arg(1) .'/delete-revision', 'title' => t('Delete revision'),
+ 'callback' => 'node_page',
+ 'access' => user_access('administer nodes'),
+ 'weight' => 1,
+ 'type' => MENU_CALLBACK);
}
}
}
@@ -1026,31 +1036,33 @@ function node_revision_create($node) {
*/
function node_revision_rollback($nid, $revision) {
global $user;
-
if (user_access('administer nodes')) {
$node = node_load(array('nid' => $nid));
-
// Extract the specified revision:
$rev = $node->revisions[$revision]['node'];
-
- // Inherit all the past revisions:
- $rev->revisions = $node->revisions;
-
- // Save the original/current node:
- $rev->revisions[] = array('uid' => $user->uid, 'timestamp' => time(), 'node' => $node);
-
- // Remove the specified revision:
- unset($rev->revisions[$revision]);
-
- // Save the node:
- foreach ($node as $key => $value) {
- $filter[] = $key;
+ if ($_POST['edit']['confirm']) {
+ // Inherit all the past revisions:
+ $rev->revisions = $node->revisions;
+ // Save the original/current node:
+ $rev->revisions[] = array('uid' => $user->uid, 'timestamp' => time(), 'node' => $node);
+ // Remove the specified revision:
+ unset($rev->revisions[$revision]);
+ // Save the node:
+ foreach ($node as $key => $value) {
+ $filter[] = $key;
+ }
+ node_save($rev, $filter);
+ drupal_set_message(t('Rolled back to revision %revision of %title', array('%revision' => "#$revision", '%title' => theme('placeholder', $node->title))));
+ drupal_goto('node/'. $nid .'/revisions');
+ }
+ else {
+ $output = theme('confirm',
+ t('Are you sure you want to revert %title? to the revision from %revision-date?', array('%title' => theme('placeholder', $node->title), '%revision-date' => theme('placeholder', format_date($node->revisions[$revision]['timestamp'])))),
+ 'node/'. $nid .'/revisions',
+ t('This action cannot be undone.'),
+ t('Revert'));
+ print theme('page', $output);
}
-
- node_save($rev, $filter);
-
- drupal_set_message(t('Rolled back to revision %revision of %title', array('%revision' => "#$revision", '%title' => theme('placeholder', $node->title))));
- drupal_goto('node/'. $nid .'/revisions');
}
}
@@ -1060,16 +1072,31 @@ function node_revision_rollback($nid, $r
function node_revision_delete($nid, $revision) {
if (user_access('administer nodes')) {
$node = node_load(array('nid' => $nid));
+ if ($_POST['edit']['confirm']) {
+ unset($node->revisions[$revision]);
- unset($node->revisions[$revision]);
-
- node_save($node, array('nid', 'revisions'));
+ // If the array is empty, replace the array by an empty string, or
+ // else we'll generate an SQL warning when we try to save the node.
+ if (count($node->revisions) == 0) {
+ $node->revisions = '';
+ }
+ node_save($node, array('nid', 'revisions'));
- drupal_set_message(t('Deleted revision %revision of %title', array('%revision' => "#$revision", '%title' => theme('placeholder', $node->title))));
- drupal_goto('node/'. $nid . (count($node->revisions) ? '/revisions' : ''));
+ drupal_set_message(t('Deleted revision %revision of %title', array('%revision' => "#$revision", '%title' => theme('placeholder', $node->title))));
+ drupal_goto('node/'. $nid . (count($node->revisions) ? '/revisions' : ''));
+ }
+ else {
+ $output = theme('confirm',
+ t('Are you sure you want to delete the revision of %title from %revision-date?', array('%title' => theme('placeholder', $node->title), '%revision-date' => theme('placeholder', format_date($node->revisions[$revision]['timestamp'])))),
+ 'node/'. $nid .'/revisions',
+ t('This action cannot be undone.'),
+ t('Delete revision'));
+ print theme('page', $output);
+ }
}
}
+
/**
* Return a list of all the existing revision numbers.
*/
@@ -1650,6 +1677,7 @@ Drupal comes with various modul
* Menu callback; dispatches control to the appropriate operation handler.
*/
function node_page() {
+ global $user;
$op = $_POST['op'] ? $_POST['op'] : arg(1);
$edit = $_POST['edit'];
@@ -1670,9 +1698,11 @@ function node_page() {
case 'revisions':
print theme('page', node_revision_overview(arg(1)));
break;
+ case t('Revert'):
case 'rollback-revision':
node_revision_rollback(arg(1), arg(3));
break;
+ case t('Delete revision'):
case 'delete-revision':
node_revision_delete(arg(1), arg(3));
break;