Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.174.2.3 diff -u -p -r1.174.2.3 form.inc --- includes/form.inc 29 Jan 2007 21:51:53 -0000 1.174.2.3 +++ includes/form.inc 25 Jul 2007 19:14:56 -0000 @@ -249,7 +249,7 @@ function drupal_process_form($form_id, & $form_button_counter = array(0, 0); drupal_prepare_form($form_id, $form); - if (($form['#programmed']) || (!empty($_POST) && (($_POST['form_id'] == $form_id) || ($_POST['form_id'] == $form['#base'])))) { + if (($form['#programmed']) || (!empty($_POST) && (($_POST['form_id'] == $form_id)))) { drupal_validate_form($form_id, $form); // IE does not send a button value when there is only one submit button (and no non-submit buttons) // and you submit by pressing enter. Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.520.2.2 diff -u -p -r1.520.2.2 comment.module --- modules/comment/comment.module 29 Jan 2007 21:51:53 -0000 1.520.2.2 +++ modules/comment/comment.module 25 Jul 2007 19:14:56 -0000 @@ -1075,23 +1075,8 @@ function comment_delete($cid = NULL) { $output = ''; - // We'll only delete if the user has confirmed the - // deletion using the form in our else clause below. - if (is_object($comment) && is_numeric($comment->cid) && $_POST['confirm']) { - drupal_set_message(t('The comment and all its replies have been deleted.')); - - // Delete comment and its replies. - _comment_delete_thread($comment); - - _comment_update_node_statistics($comment->nid); - - // Clear the cache so an anonymous user sees that his comment was deleted. - cache_clear_all(); - - drupal_goto("node/$comment->nid"); - } - else if (is_object($comment) && is_numeric($comment->cid)) { - $output = drupal_get_form('comment_confirm_delete', $comment->subject, $comment->nid); + if (is_object($comment) && is_numeric($comment->cid)) { + $output = drupal_get_form('comment_confirm_delete', $comment); } else { drupal_set_message(t('The comment no longer exists.')); @@ -1100,16 +1085,38 @@ function comment_delete($cid = NULL) { return $output; } -function comment_confirm_delete($subject, $nid) { +function comment_confirm_delete($comment) { + + $form = array(); + $form['comment'] = array( + '#type' => 'value', + '#value' => $comment, + ); + return confirm_form( - array(), - t('Are you sure you want to delete the comment %title?', array('%title' => $subject)), - 'node/'. $nid, + $form, + t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject)), + 'node/'. $comment->nid, t('Any replies to this comment will be lost. This action cannot be undone.'), t('Delete'), t('Cancel')); } +function comment_confirm_delete_submit($form_id, $form_values) { + $comment = $form_values['comment']; + + // Delete comment and its replies. + _comment_delete_thread($comment); + _comment_update_node_statistics($comment->nid); + // Clear the cache so an anonymous user sees that his comment was deleted. + cache_clear_all(); + + drupal_set_message(t('The comment and all its replies have been deleted.')); + + return "node/$comment->nid"; +} + + /** * Comment operations. We offer different update operations depending on * which comment administration page we're on. Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.100 diff -u -p -r1.100 menu.module --- modules/menu/menu.module 5 Jan 2007 19:05:54 -0000 1.100 +++ modules/menu/menu.module 25 Jul 2007 19:14:56 -0000 @@ -68,7 +68,8 @@ function menu_menu($may_cache) { 'type' => MENU_CALLBACK); $items[] = array('path' => 'admin/build/menu/item/disable', 'title' => t('Disable menu item'), - 'callback' => 'menu_disable_item', + 'callback' => 'drupal_get_form', + 'callback arguments' => array('menu_confirm_disable_item'), 'access' => user_access('administer menu'), 'type' => MENU_CALLBACK); $items[] = array('path' => 'admin/build/menu/item/delete', @@ -481,14 +482,24 @@ function menu_reset_item_submit($form_id /** * Menu callback; hide a menu item. + * + * Presents a confirmation form to protect against cross site request forgeries. */ -function menu_disable_item($mid) { +function menu_confirm_disable_item($mid, $token = NULL) { + global $user; $item = menu_get_item($mid); - $type = $item['type']; + $form = array(); + $form['mid'] = array('#type' => 'value', '#value' => $mid); + $form['item'] = array('#type' => 'value', '#value' => $item); + return confirm_form($form, t('Are you sure you want to disable the menu item %menu-item?', array('%menu-item' => $item['title'])), 'admin/build/menu', ' ', t('Disable'), t('Cancel')); +} + +function menu_confirm_disable_item_submit($form_id, $form_values) { + $type = $form_values['item']['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); + db_query('UPDATE {menu} SET type = %d WHERE mid = %d', $type, $form_values['mid']); drupal_set_message(t('The menu item has been disabled.')); drupal_goto('admin/build/menu'); } Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.776.2.1 diff -u -p -r1.776.2.1 node.module --- modules/node/node.module 29 Jan 2007 21:51:53 -0000 1.776.2.1 +++ modules/node/node.module 25 Jul 2007 19:14:56 -0000 @@ -35,7 +35,7 @@ function node_help($section) { return '

'. t('To create a new content type, enter the human-readable name, the machine-readable name, and all other relevant fields that are on this page. Once created, users of your site will be able to create posts that are instances of this content type.') .'

'; } - if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'revisions') { + if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'revisions' && arg(3) == NULL) { return '

'. t('The revisions let you track differences between multiple versions of a post.') .'

'; } @@ -1195,11 +1195,26 @@ function node_menu($may_cache) { 'weight' => 1, 'type' => MENU_CALLBACK); $revisions_access = ((user_access('view revisions') || user_access('administer nodes')) && node_access('view', $node) && db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', arg(1))) > 1); - $items[] = array('path' => 'node/'. arg(1) .'/revisions', 'title' => t('Revisions'), + $items[] = array( + 'path' => 'node/'. arg(1) .'/revisions', + 'title' => t('Revisions'), 'callback' => 'node_revisions', 'access' => $revisions_access, 'weight' => 2, - 'type' => MENU_LOCAL_TASK); + 'type' => MENU_LOCAL_TASK, + ); + if (!is_null(arg(3))) { + $items[] = array( + 'path' => 'node/'. arg(1) .'/revisions/'. arg(3) .'/delete', + 'callback' => 'node_revision_delete', + 'callback arguments' => array(arg(1), arg(3)), + ); + $items[] = array( + 'path' => 'node/'. arg(1) .'/revisions/'. arg(3) .'/revert', + 'callback' => 'node_revision_revert', + 'callback arguments' => array(arg(1), arg(3)), + ); + } } } @@ -1681,16 +1696,7 @@ function node_revision_revert($nid, $rev $node = node_load($nid, $revision); if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) { if ($node->vid) { - $node->revision = 1; - $node->log = t('Copy of the revision from %date.', array('%date' => format_date($node->revision_timestamp))); - if (module_exists('taxonomy')) { - $node->taxonomy = array_keys($node->taxonomy); - } - - node_save($node); - - drupal_set_message(t('%title has been reverted back to the revision from %revision-date', array('%revision-date' => format_date($node->revision_timestamp), '%title' => $node->title))); - watchdog('content', t('@type: reverted %title revision %revision.', array('@type' => t($node->type), '%title' => $node->title, '%revision' => $revision))); + return drupal_get_form('node_revision_revert_confirm', $node); } else { drupal_set_message(t('You tried to revert to an invalid revision.'), 'error'); @@ -1701,6 +1707,31 @@ function node_revision_revert($nid, $rev } /** + * Ask for confirmation of the reversion to prevent against CSRF attacks. + */ +function node_revision_revert_confirm($node) { + $form['node'] = array('#type' => 'value', '#value' => $node); + return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node->revision_timestamp))), 'node/'. $node->nid .'/revisions', '', t('Revert'), t('Cancel')); +} + +function node_revision_revert_confirm_submit($form_id, $form_values) { + $node = $form_values['node']; + + $node->revision = 1; + $node->log = t('Copy of the revision from %date.', array('%date' => format_date($node->revision_timestamp))); + if (module_exists('taxonomy')) { + $node->taxonomy = array_keys($node->taxonomy); + } + + node_save($node); + + drupal_set_message(t('%title has been reverted back to the revision from %revision-date', array('%revision-date' => format_date($node->revision_timestamp), '%title' => $node->title))); + watchdog('content', t('@type: reverted %title revision %revision.', array('@type' => t($node->type), '%title' => $node->title, '%revision' => $revision))); + + return 'node/'. $node->nid .'/revisions'; +} + +/** * Delete the revision with specified revision number. A "delete revision" nodeapi event is invoked when a * revision is deleted. */ @@ -1710,22 +1741,22 @@ function node_revision_delete($nid, $rev if (node_access('delete', $node)) { // Don't delete the current revision if ($revision != $node->vid) { - $node = node_load($nid, $revision); - - db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision); - node_invoke_nodeapi($node, 'delete revision'); - drupal_set_message(t('Deleted %title revision %revision.', array('%title' => $node->title, '%revision' => $revision))); - watchdog('content', t('@type: deleted %title revision %revision.', array('@type' => t($node->type), '%title' => $node->title, '%revision' => $revision))); + if ($node = node_load($nid, $revision)) { + return drupal_get_form('node_revision_delete_confirm', $node); + } + else { + drupal_set_message(t('Deletion failed. You tried to delete a non-existing revision.')); + } } - else { drupal_set_message(t('Deletion failed. You tried to delete the current revision.')); } + if (db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $nid)) > 1) { - drupal_goto("node/$nid/revisions"); + drupal_goto('node/'. $nid .'/revisions'); } else { - drupal_goto("node/$nid"); + drupal_goto('node/'. $nid); } } } @@ -1734,6 +1765,29 @@ function node_revision_delete($nid, $rev } /** + * Ask confirmation for revision deletion to prevent against CSRF attacks. + */ +function node_revision_delete_confirm($node) { + $form['node'] = array('#type' => 'value', '#value' => $node); + return confirm_form($form, t('Are you sure you want to delete the revision from %revision-date?', array('%revision-date' => format_date($node->revision_timestamp))), 'node/'. $node->nid .'/revisions', t('This action cannot be undone.'), t('Delete'), t('Cancel')); +} + +function node_revision_delete_confirm_submit($form_id, $form_values) { + $node = $form_values['node']; + db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $node->nid, $node->vid); + node_invoke_nodeapi($node, 'delete revision'); + drupal_set_message(t('Deleted %title revision %revision.', array('%title' => $node->title, '%revision' => $node->vid))); + watchdog('content', t('@type: deleted %title revision %revision.', array('@type' => t($node->type), '%title' => $node->title, '%revision' => $node->vid))); + + if (db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $node->nid)) > 1) { + return 'node/'. $node->nid .'/revisions'; + } + else { + return 'node/'. $node->nid; + } +} + +/** * Return a list of all the existing revision numbers. */ function node_revision_list($node) { @@ -2355,12 +2409,6 @@ function node_revisions() { } } break; - case 'revert': - node_revision_revert(arg(1), arg(3)); - break; - case 'delete': - node_revision_delete(arg(1), arg(3)); - break; } } drupal_not_found();