Commit 303ee0f6 authored by Gerhard Killesreiter's avatar Gerhard Killesreiter

remove trailing spaces

parent a3ddefb3
Drupal 4.6.10, 2006-10-18
------------------------
- fixed security issue (XSS), see SA-2006-024
- fixed security issue (CSRF), see SA-2006-025
- fixed security issue (Form action attribute injection), see SA-2006-026
Drupal 4.6.9, 2006-08-02
------------------------
- fixed security issue (XSS), see SA-2006-011
......
......@@ -911,6 +911,61 @@ function format_name($object) {
* @} End of "defgroup format".
*/
/**
* 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
* @{
......@@ -921,6 +976,13 @@ function format_name($object) {
* must be explicitly generated by modules.
*/
/**
* 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.
*
......@@ -939,7 +1001,7 @@ function form($form, $method = 'post', $action = NULL, $attributes = NULL) {
if (!$action) {
$action = request_uri();
}
return '<form action="'. check_url($action) .'" method="'. $method .'"'. drupal_attributes($attributes) .">\n". $form ."\n</form>\n";
return '<form action="'. check_url($action) .'" method="'. $method .'"'. drupal_attributes($attributes) .">\n". $form . form_token() ."\n</form>\n";
}
/**
......@@ -1600,7 +1662,7 @@ function drupal_xml_parser_create(&$data) {
$data = ereg_replace('^(<\?xml[^>]+encoding)="([^"]+)"', '\\1="utf-8"', $out);
}
else {
watchdog('php', t("Could not convert XML encoding '%s' to UTF-8.", array('%s' => $encoding)), WATCHDOG_WARNING);
watchdog('php', t("Could not convert XML encoding '%s' to UTF-8.", array('%s' => theme('placeholder', $encoding))), WATCHDOG_WARNING);
return 0;
}
}
......
......@@ -14,6 +14,7 @@
include_once 'includes/common.inc';
fix_gpc_magic();
drupal_check_token();
$status = menu_execute_active_handler();
switch ($status) {
......
......@@ -110,6 +110,7 @@ function block_block($op = 'list', $delta = 0, $edit = array()) {
}
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'",
......
......@@ -125,7 +125,7 @@ function blog_page_user($uid) {
$account = user_load(array((is_numeric($uid) ? 'uid' : 'name') => $uid, 'status' => 1));
if ($account->uid) {
drupal_set_title($title = t("%name's blog", array('%name' => $account->name)));
drupal_set_title($title = t("%name's blog", array('%name' => check_plain($account->name))));
if (($account->uid == $user->uid) && user_access('edit own blog')) {
$output = '<li>'. l(t('Post new blog entry.'), "node/add/blog") .'</li>';
......
......@@ -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 .= '<div style="text-align: center;">'. form_submit(t('Moderate comment')) .'</div><br />';
}
$output .= '</div></form>';
$output .= '</div>' . form_token() . '</form>';
}
else {
// Multiple comment view
......@@ -863,7 +863,7 @@ function comment_render($node, $cid = 0) {
$output .= '<form method="post" action="'. url('comment') ."\"><div>\n";
$output .= theme('comment_controls', $threshold, $mode, $order, $comments_per_page);
$output .= form_hidden('nid', $nid);
$output .= '</div></form>';
$output .= '</div>' . form_token() . '</form>';
}
$output .= '<form method="post" action="'. url('comment') ."\"><div>\n";
......@@ -898,13 +898,13 @@ function comment_render($node, $cid = 0) {
$output .= '<div id="comment-moderation-button">'. form_submit(t('Moderate comments')) .'</div>';
}
$output .= '</div></form>';
$output .= '</div>' . form_token() . '</form>';
if (db_num_rows($result) && (variable_get('comment_controls', 3) == 1 || variable_get('comment_controls', 3) == 2)) {
$output .= '<form method="post" action="'. url('comment') ."\"><div>\n";
$output .= theme('comment_controls', $threshold, $mode, $order, $comments_per_page);
$output .= form_hidden('nid', $nid);
$output .= '</div></form>';
$output .= '</div>' . form_token() . '</form>';
}
}
......
......@@ -55,10 +55,10 @@ function contact_mail_user() {
if ($account = user_load(array('uid' => arg(1), 'status' => 1))) {
if (!$account->contact && !user_access('administer users')) {
$output = t('%name is not accepting e-mails.', array('%name' => $account->name));
$output = t('%name is not accepting e-mails.', array('%name' => check_plain($account->name)));
}
else if (!$user->uid) {
$output = t('Please <a href="%login">login</a> or <a href="%register">register</a> to send %name a message.', array('%login' => url('user/login'), '%register' => url('user/register'), '%name' => $account->name));
$output = t('Please <a href="%login">login</a> or <a href="%register">register</a> to send %name a message.', array('%login' => url('user/login'), '%register' => url('user/register'), '%name' => check_plain($account->name)));
}
else if (!valid_email_address($user->mail)) {
$output = t('You need to provide a valid e-mail address to contact other users. Please edit your <a href="%url">user information</a>.', array('%url' => url("user/$user->uid/edit")));
......@@ -106,7 +106,7 @@ function contact_mail_user() {
// Log the operation:
flood_register_event('contact');
watchdog('mail', t('%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name)));
watchdog('mail', t('%name-from sent %name-to an e-mail.', array('%name-from' => theme('placeholder', $user->name), '%name-to' => theme('placeholder', $account->name))));
// Set a status message:
drupal_set_message(t('Your message has been sent.'));
......@@ -119,8 +119,8 @@ function contact_mail_user() {
$edit['mail'] = $user->mail;
}
$output = form_item(t('From'), $user->name .' &lt;'. $user->mail .'&gt;');
$output .= form_item(t('To'), $account->name);
$output = form_item(t('From'), check_plain($user->name) .' &lt;'. $user->mail .'&gt;');
$output .= form_item(t('To'), check_plain($account->name));
$output .= form_textfield(t('Subject'), 'subject', $edit['subject'], 50, 50, NULL, NULL, TRUE);
$output .= form_textarea(t('Message'), 'message', $edit['message'], 70, 8, NULL, NULL, TRUE);
$output .= form_submit(t('Send e-mail'));
......
......@@ -1235,15 +1235,21 @@ function filter_xss_bad_protocol($string, $decode = TRUE) {
if ($decode) {
$string = decode_entities($string);
}
// Remove soft hyphen
$string = str_replace(chr(194) . chr(173), '', $string);
// Strip protocols
// Iteratively remove any invalid protocol found.
do {
$before = $string;
$colonpos = strpos($string, ':');
if ($colonpos > 0) {
// We found a colon, possibly a protocol. Verify.
$protocol = substr($string, 0, $colonpos);
// If a colon is preceded by a slash, question mark or hash, it cannot
// possibly be part of the URL scheme. This must be a relative URL,
// which inherits the (safe) protocol of the base document.
if (preg_match('![/?#]!', $protocol)) {
break;
}
// Check if this is a disallowed protocol
if (!isset($allowed_protocols[$protocol])) {
$string = substr($string, $colonpos + 1);
}
......
......@@ -777,7 +777,7 @@ function theme_forum_display($forums, $topics, $parents, $tid, $sortby, $forum_p
}
}
drupal_set_title($title);
drupal_set_title(check_plain($title));
$breadcrumb[] = array('path' => $_GET['q']);
menu_set_location($breadcrumb);
......
......@@ -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)));
......
......@@ -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);
}
}
/**
......
......@@ -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' => "<em>#$revision</em>", '%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' => "<em>#$revision</em>", '%title' => theme('placeholder', $node->title))));
drupal_goto('node/'. $nid .'/revisions');
}
}
......@@ -1060,18 +1072,27 @@ function node_revision_rollback($nid, $revision) {
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]);
// 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'));
// 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 = '';
drupal_set_message(t('Deleted revision %revision of %title', array('%revision' => "<em>#$revision</em>", '%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);
}
node_save($node, array('nid', 'revisions'));
drupal_set_message(t('Deleted revision %revision of %title', array('%revision' => "<em>#$revision</em>", '%title' => theme('placeholder', $node->title))));
drupal_goto('node/'. $nid . (count($node->revisions) ? '/revisions' : ''));
}
}
......@@ -1655,6 +1676,7 @@ function node_page_default() {
* Menu callback; dispatches control to the appropriate operation handler.
*/
function node_page() {
global $user;
$op = $_POST['op'] ? $_POST['op'] : arg(1);
$edit = $_POST['edit'];
......@@ -1675,9 +1697,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;
......
......@@ -107,7 +107,7 @@ function path_admin_edit($pid = 0) {
}
elseif ($pid) {
$alias = path_load($pid);
drupal_set_title($alias['dst']);
drupal_set_title(check_plain($alias['dst']));
$output = path_form(path_load($pid));
}
else {
......
......@@ -117,7 +117,7 @@ function profile_browse() {
}
$output .= '</div>';
drupal_set_title($title);
drupal_set_title(check_plain($title));
print theme('page', $output);
}
else if ($name && !$field->id) {
......@@ -491,7 +491,7 @@ function profile_admin_edit($fid) {
$data = db_fetch_array(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid));
}
drupal_set_title(t('Edit %type', array('%type' => $data['type'])));
drupal_set_title(t('Edit %type', array('%type' => check_plain($data['type']))));
print theme('page', _profile_field_form($data['type'], $data));
}
......
......@@ -211,7 +211,7 @@ function statistics_user_tracker() {
$rows[] = array(array('data' => $pager, 'colspan' => '3'));
}
drupal_set_title($account->name);
drupal_set_title(check_plain($account->name));
print theme('page', theme('table', $header, $rows));
}
else {
......
......@@ -59,7 +59,7 @@ function tracker_menu($may_cache) {
*/
function tracker_track_user() {
if ($account = user_load(array('uid' => arg(1)))) {
drupal_set_title($account->name);
drupal_set_title(check_plain($account->name));
tracker_page($account->uid);
}
}
......
......@@ -215,6 +215,18 @@ function user_validate_name($name) {
if (substr($name, -1) == ' ') return t('The username cannot end with a space.');
if (ereg(' ', $name)) return t('The username cannot contain multiple spaces in a row.');
if (ereg("[^\x80-\xF7 [:alnum:]@_.-]", $name)) return t('The username contains an illegal character.');
if (preg_match('/[\x{80}-\x{A0}'. // Non-printable ISO-8859-1 + NBSP
'\x{AD}'. // Soft-hyphen
'\x{2000}-\x{200F}'. // Various space characters
'\x{2028}-\x{202F}'. // Bidirectional text overrides
'\x{205F}-\x{206F}'. // Various text hinting characters
'\x{FEFF}'. // Byte order mark
'\x{FF01}-\x{FF60}'. // Full-width latin
'\x{FFF9}-\x{FFFD}'. // Replacement characters
'\x{0}]/u', // NULL byte
$name)) {
return t('The username contains an illegal character.');
}
if (ereg('@', $name) && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t('The username is not a valid authentication ID.');
if (strlen($name) > 56) return t('The username %name is too long: it must be less than 56 characters.', array('%name' => theme('placeholder', $name)));
}
......@@ -523,7 +535,7 @@ function user_block($op = 'list', $delta = 0, $edit = array()) {
case 1:
if ($menu = theme('menu_tree')) {
$block['subject'] = $user->uid ? $user->name : t('Navigation');
$block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation');
$block['content'] = '<div class="menu">'. $menu .'</div>';
}
return $block;
......@@ -1191,7 +1203,7 @@ function user_edit($category = 'account') {
}
$output = form($output, 'post', 0, array('enctype' => 'multipart/form-data'));
drupal_set_title($account->name);
drupal_set_title(check_plain($account->name));
print theme('page', $output);
}
......@@ -1209,7 +1221,7 @@ function user_view($uid = 0) {
}
}
drupal_set_title($account->name);
drupal_set_title(check_plain($account->name));
print theme('page', theme('user_profile', $account, $fields));
}
else {
......
......@@ -209,6 +209,9 @@ function update_info() {
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)) {
update_page();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment