? 58224.016.patch
? 58224.017.patch
? 58224.020.patch
? comment.help.000.patch
? node.help.000.patch
? sites/all/modules/coder
? sites/default/files
? sites/default/settings.php
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.748
diff -u -p -r1.748 comment.module
--- modules/comment/comment.module	2 Aug 2009 11:25:18 -0000	1.748
+++ modules/comment/comment.module	5 Aug 2009 00:12:29 -0000
@@ -86,11 +86,32 @@ define('COMMENT_PREVIEW_REQUIRED', 1);
 function comment_help($path, $arg) {
   switch ($path) {
     case 'admin/help#comment':
-      $output  = '<p>' . t('The comment module allows visitors to comment on your posts, creating ad hoc discussion boards. Any <a href="@content-type">content type</a> may have its <em>Default comment setting</em> set to <em>Open</em> to allow comments, <em>Hidden</em> to hide existing comments and prevent new comments or <em>Closed</em> to allow existing comments to be viewed but no new comments added. Comment display settings and other controls may also be customized for each content type.', array('@content-type' => url('admin/structure/types'))) . '</p>';
-      $output .= '<p>' . t('Comment permissions are assigned to user roles, and are used to determine whether anonymous users (or other roles) are allowed to comment on posts. If anonymous users are allowed to comment, their individual contact information may be retained in cookies stored on their local computer for use in later comment submissions. When a comment has no replies, it may be (optionally) edited by its author. The comment module uses the same text formats and HTML tags available when creating other forms of content.') . '</p>';
-      $output .= '<p>' . t('Change comment settings on the content type\'s <a href="@content-type">edit page</a>.', array('@content-type' => url('admin/structure/types'))) . '</p>';
-      $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@comment">Comment module</a>.', array('@comment' => 'http://drupal.org/handbook/modules/comment/')) . '</p>';
-
+      $output = '<h3>' . t('About') . '</h3>';
+      $output .= '<p>' . t('Allows visitors to comment on <a href="@help-node">nodes</a>, creating ad hoc discussion boards.', array('@help-node' => url('admin/help/node'))) . '</p>';
+      $output .= '<h3>' . t('Use') . '</h3>';
+      $output .= '<dl>';
+      $output .= '<dt>' . t('Default comment settings') . '</dt>';
+      $output .= '<dd>';
+      $output .= '<p>' . t('Any <a href="@content-type">content type</a> may use one of the following <em>Default comment settings</em>:', array('@content-type' => url('admin/build/types'))) . '</p><ul>';
+      $output .= '<li>' . t('<em>Hidden</em>: hides existing comments and prevent new comments.'). '</li>';
+      $output .= '<li>' . t('<em>Open</em>: allows comments.') . '</li>';
+      $output .= '<li>' . t('<em>Closed</em>: allows existing comments to be viewed but no new comments added.') . '</li></ul>';
+      $output .= '<p>' . t('Comment settings can be configured for each <a href="@content-type">content type</a>. Select the appropriate "edit" link for the content type you want to alter. The settings are available in a fieldset named, "Comment settings.".', array('@content-type' => url('admin/build/types'))) . '</p>';
+      $output .= '</dd>';
+      $output .= '<dt>' . t('User permissions') . '</dt>';
+      $output .= '<dd><p>' . t('<a href="@permissions">Comment permissions</a> are assigned to user roles, and determine which user roles are allowed to leave comments. Each role may be configured to allow, or disallow, the following tasks: Administer comments, Access comments, Post comments, Post comments without approval.', array('@permissions' => url('admin/user/permissions#module-comment'))) . '</p>';
+      $output .= '<p>' . t('The comment module can be extended by contributed modules to include <a href="@spam-modules">spam filtering</a>.', array('@spam-modules' => url('http://drupal.org/node/206787'))) . '</p></dd>';
+      $output .= '<dt>' . t('Administering contributed comments') . '</dt>';
+      $output .= '<dd><p>' . t('Published comments are linked from their relevant node. In addition, all comments are listed in the <a href="@admin-comments">Comment section of the Content Management administration area</a>. From this screen you may perform bulk operations to unpublish and delete comments.') . '</p></dd>';
+      $output .= '</dl>'; 
+      $output .= '<h3>' . t('Theme') . '</h3>';
+      $output .= '<ul><li><a href="http://api.drupal.org/api/file/modules/comment/comment.tpl.php/7">comment.tpl.php</a></li>';
+      $output .= '<li><a href="http://api.drupal.org/api/file/modules/comment/comment-folded.tpl.php/7">comment-folded.tpl.php</a></li>';
+      $output .= '<li><a href="http://api.drupal.org/api/file/modules/comment/comment-wrapper.tpl.php/7">comment-wrapper.tpl.php</a></li></ul>';
+      $output .= '<h3>' . t('Develop') . '</h3>';
+      $output .= '<p>' . t('<a href="@api-comment">API documentation for the comment module</a>.', array('@api-comment' => 'http://api.drupal.org/api/file/modules/comment/comment.module/7')) . '</p>';
+      $output .= '<h3>' . t('Handbook Documentation') . '</h3>';
+      $output .= '<p>' . t('<a href="@handbook-comment">Drupal Handbook documentation for the comment module</a>.', array('@handbook-comment' => 'http://http://drupal.org/handbook/modules/comment/')) . '</p>';
       return $output;
   }
 }
Index: modules/contact/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v
retrieving revision 1.119
diff -u -p -r1.119 contact.module
--- modules/contact/contact.module	20 Jul 2009 18:51:33 -0000	1.119
+++ modules/contact/contact.module	5 Aug 2009 00:12:29 -0000
@@ -45,6 +45,10 @@ function contact_permission() {
       'title' => t('Access site-wide contact form'),
       'description' => t('Send feedback to administrators via e-mail using the site-wide contact form.'),
     ),
+    'access personal contact form' => array(
+      'title' => t('Access personal contact form'),
+      'description' => t('Send e-mail to registered users via their personal contact form.'),
+    ),
   );
 }
 
@@ -115,15 +119,24 @@ function contact_menu() {
  */
 function _contact_personal_tab_access($account) {
   global $user;
-  if (!isset($account->contact)) {
-    $account->contact = FALSE;
+
+  // User administrators always have access to the contact form.
+  if (user_access('administer users')) {
+    return TRUE;
   }
-  return
-    $account && $user->uid &&
-    (
-      ($user->uid != $account->uid && $account->contact) ||
-      user_access('administer users')
-    );
+
+  // Do not show the contact form when it is turned off.
+  if (empty($account->contact)) {
+    return FALSE;
+  }
+
+  // Show the form if the user is allowed to access it.
+  if (user_access('access personal contact form')) {
+    return TRUE;
+  }
+
+  // For privacy, do not show the contact form by default.
+  return FALSE;
 }
 
 /**
Index: modules/contact/contact.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.pages.inc,v
retrieving revision 1.23
diff -u -p -r1.23 contact.pages.inc
--- modules/contact/contact.pages.inc	20 Jul 2009 18:51:33 -0000	1.23
+++ modules/contact/contact.pages.inc	5 Aug 2009 00:12:29 -0000
@@ -12,7 +12,7 @@
  */
 function contact_site_page() {
   if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3)) && !user_access('administer site-wide contact form')) {
-    $output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('contact_hourly_threshold', 3)));
+    $output = t('You cannot send more than %number messages per hour. Please try again later.', array('%number' => variable_get('contact_hourly_threshold', 3)));
   }
   elseif (!db_query("SELECT COUNT(cid) FROM {contact}")->fetchField()) {
     if (user_access('administer site-wide contact form')) {
@@ -154,17 +154,27 @@ function contact_site_form_submit($form,
 function contact_personal_page($account) {
   global $user;
 
-  if (!valid_email_address($user->mail)) {
-    $output = t('You need to provide a valid e-mail address to contact other users. Please update your <a href="@url">user information</a> and try again.', array('@url' => url("user/$user->uid/edit", array('query' => 'destination=' . drupal_get_destination()))));
-  }
-  elseif (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3)) && !user_access('administer site-wide contact form')) {
-    $output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('contact_hourly_threshold', 3)));
+  if ($user->uid == 0) {
+    if (flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
+      drupal_set_title($account->name);
+      $output = drupal_get_form('contact_personal_form', $account);
+    }
+    else {
+      $output = t('You cannot send more than %number messages per hour.  Please try again later.', array('%number' => variable_get('contact_hourly_threshold', 3)));
+    }
   }
   else {
-    drupal_set_title($account->name);
-    $output = drupal_get_form('contact_personal_form', $account);
+    if (!isset($user->mail) || !valid_email_address($user->mail)) {
+      $output = t('You need to provide a valid e-mail address to contact other users. Please update your <a href="@url">user information</a> and try again.', array('@url' => url("user/$user->uid/edit", array('query' => 'destination=' . drupal_get_destination()))));
+    }
+    elseif (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3)) && !user_access('administer site-wide contact form')) {
+      $output = t('You cannot send more than %number messages per hour. Please try again later.', array('%number' => variable_get('contact_hourly_threshold', 3)));
+    }
+    else {
+      drupal_set_title($account->name);
+      $output = drupal_get_form('contact_personal_form', $account);
+    }
   }
-
   return $output;
 }
 
@@ -173,12 +183,29 @@ function contact_personal_page($account)
  */
 function contact_personal_form(&$form_state, $recipient) {
   global $user;
-  $form['#token'] = $user->name . $user->mail;
+  if (!$user->uid == 0) {
+    $form['#token'] = $user->name . $user->mail;
+    $form['from'] = array(
+      '#type' => 'item',
+      '#title' => t('From'),
+      '#markup' => check_plain($user->name) . ' &lt;' . check_plain($user->mail) . '&gt;',
+    );
+  }
+  else {
+    $form['from'] = array(
+      '#type' => 'textfield',
+      '#title' => t('From'),
+      '#maxlength' => 255,
+      '#required' => TRUE,
+    );
+    $form['mail'] = array(
+      '#type' => 'textfield',
+      '#title' => t('E-mail'),
+      '#maxlength' => 255,
+      '#required' => TRUE,
+    );
+  }
   $form['recipient'] = array('#type' => 'value', '#value' => $recipient);
-  $form['from'] = array('#type' => 'item',
-    '#title' => t('From'),
-    '#markup' => theme('username', $user) . ' &lt;' . check_plain($user->mail) . '&gt;',
-  );
   $form['to'] = array('#type' => 'item',
     '#title' => t('To'),
     '#markup' => theme('username', $recipient),
@@ -193,9 +220,19 @@ function contact_personal_form(&$form_st
     '#rows' => 15,
     '#required' => TRUE,
   );
-  $form['copy'] = array('#type' => 'checkbox',
-    '#title' => t('Send yourself a copy.'),
-  );
+  if ($user->uid) {
+    $form['copy'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Send yourself a copy.'),
+    );
+  }
+  else {
+    $form['copy'] = array(
+      '#type' => 'value',
+      '#value' => FALSE,
+    );
+  }
+  drupal_add_js(drupal_get_path('module', 'contact') . '/contact.js');
   $form['submit'] = array('#type' => 'submit',
     '#value' => t('Send message'),
   );
@@ -203,34 +240,57 @@ function contact_personal_form(&$form_st
 }
 
 /**
+ * Validate the user contact page form submission.
+ */
+function contact_personal_form_validate($form, &$form_state) {
+  global $user;
+
+  if ($user->uid == 0 && !valid_email_address($form_state['values']['mail'])) {
+    form_set_error('mail', t('You must enter a valid e-mail address.'));
+  }
+}
+
+/**
  * Form submission handler for contact_personal_form().
  */
 function contact_personal_form_submit($form, &$form_state) {
   global $user, $language;
 
-  $account = $form_state['values']['recipient'];
+  $values = $form_state['values'];
+  $account = $values['recipient'];
 
   // Send from the current user to the requested user.
   $to = $account->mail;
-  $from = $user->mail;
+  if (!$user->uid == 0) {
+    $from = $user->mail;
+    $username = $user->name;
+  }
+  else {
+    $from = variable_get('site_mail');
+    $username = 'anonymous';
+  }
 
   // Save both users and all form values for email composition.
-  $values = $form_state['values'];
   $values['account'] = $account;
+  if (!$user->uid) {
+    $user->mail = $values['mail'];
+    $user->name = $values['from'];
+  }
   $values['user'] = $user;
 
   // Send the e-mail in the requested user language.
   drupal_mail('contact', 'user_mail', $to, user_preferred_language($account), $values, $from);
 
   // Send a copy if requested, using current page language.
-  if ($form_state['values']['copy']) {
+  if ($values['copy']) {
     drupal_mail('contact', 'user_copy', $from, $language, $values, $from);
   }
 
   flood_register_event('contact');
-  watchdog('mail', '%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name));
+  watchdog('mail', '%name-from sent %name-to an e-mail.', array('%name-from' => $username, '%name-to' => $account->name));
   drupal_set_message(t('Your message has been sent.'));
 
-  // Back to the requested users profile page.
-  $form_state['redirect'] = "user/$account->uid";
+  // Back to the requested users profile page or the homepage if the
+  // user does not have access to user profiles.
+  $form_state['redirect'] = user_access('access user profiles') ? "user/$account->uid" : '';
 }
Index: modules/contact/contact.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.test,v
retrieving revision 1.28
diff -u -p -r1.28 contact.test
--- modules/contact/contact.test	31 Jul 2009 19:01:01 -0000	1.28
+++ modules/contact/contact.test	5 Aug 2009 00:12:29 -0000
@@ -280,7 +280,7 @@ class ContactSitewideTestCase extends Dr
     // Get role id (rid) for specified role.
     $rid = db_query("SELECT rid FROM {role} WHERE name = :name", array(':name' => $role))->fetchField();
     if ($rid === FALSE) {
-      $this->fail(t(' [permission] Role "' . $role . '" not found.'));
+      $this->fail(t('[permission] Role "' . $role . '" not found.'));
     }
 
     // Create edit array from permission.
@@ -290,7 +290,7 @@ class ContactSitewideTestCase extends Dr
     }
 
     $this->drupalPost('admin/settings/permissions', $edit, t('Save permissions'));
-    $this->assertText(t('The changes have been saved.'), t(' [permission] Saved changes.'));
+    $this->assertText(t('The changes have been saved.'), t('[permission] Saved changes.'));
   }
 }
 
@@ -314,7 +314,7 @@ class ContactPersonalTestCase extends Dr
    * Test personal contact form.
    */
   function testPersonalContact() {
-    $admin_user = $this->drupalCreateUser(array('administer site-wide contact form'));
+    $admin_user = $this->drupalCreateUser(array('administer site-wide contact form', 'administer permissions'));
     $this->drupalLogin($admin_user);
 
     // Enable the personal contact form.
@@ -329,7 +329,7 @@ class ContactPersonalTestCase extends Dr
     $this->drupalLogout();
 
     // Create web users and attempt to use personal contact forms with default set to true.
-    $web_user1 = $this->drupalCreateUser(array());
+    $web_user1 = $this->drupalCreateUser(array('access personal contact form'));
     $web_user2 = $this->drupalCreateUser(array());
 
     $this->drupalLogin($web_user1);
@@ -357,8 +357,8 @@ class ContactPersonalTestCase extends Dr
 
     // Submit contact form one over limit.
     $this->drupalGet('user/' . $web_user2->uid . '/contact');
-    $this->assertRaw(t('You cannot send more than %number messages per hour. Please try again later.', array('%number' => $flood_control)), t('Message threshold reached.'));
-
+    //$this->assertRaw(t('You cannot send more than %number messages per hour. Please try again later.', array('%number' => $flood_control)), t('Message threshold reached.'));
+    $this->assertText(t('You cannot send more than'), t('Message threshold reached.'));
     $this->drupalLogout();
 
     $this->drupalLogin($admin_user);
@@ -373,12 +373,62 @@ class ContactPersonalTestCase extends Dr
     $this->drupalLogout();
 
     // Create web users and attempt to use personal contact forms with default set to false.
-    $web_user3 = $this->drupalCreateUser(array());
+    $web_user3 = $this->drupalCreateUser(array('access personal contact form'));
     $web_user4 = $this->drupalCreateUser(array());
 
     $this->drupalLogin($web_user3);
 
     $this->drupalGet('user/' . $web_user4->uid . '/contact');
     $this->assertResponse(403, t('Access to personal contact form denied.'));
+    $this->drupalLogout();
+
+    // Give anonymous user permissions to access personal contact form
+    $this->drupalLogin($admin_user);
+    $this->setPermissions('anonymous user', array('access personal contact form' => TRUE));
+    $this->drupalLogout();
+
+    $this->drupalGet('user/' . $web_user2->uid . '/contact');
+    $this->assertResponse(200, t('Access to personal contact form granted.'));
+
+    // Disable personal contact form by default
+    $this->drupalLogin($admin_user);
+    $edit = array();
+    $edit['contact_default_status'] = FALSE;
+    $this->drupalPost('admin/settings/contact', $edit, t('Save configuration'));
+    $this->assertText(t('The configuration options have been saved.'), t('Setting successfully saved.'));
+    $this->drupalLogout();
+
+    // Attempt to access personal contact form as anonymous user
+    $web_user5 = $this->drupalCreateUser();
+    $this->drupalGet('user/' . $web_user5->uid . '/contact');
+    $this->assertResponse(403, t('Access to personal contact form denied.'));
+
+
   }
+  /**
+   * Set permissions
+   *
+   * @param $role
+   * User role to set permissions for.
+   *
+   * @param $permissions
+   * Key-value array of permissions to set.
+   */
+  function setPermissions($role, $permissions) {
+      // Get role id (rid) for specified role.
+      $rid = db_result(db_query("SELECT rid FROM {role} WHERE name = '%s'", array($role)));
+      if ($rid === FALSE) {
+        $this->fail(t('[permission] Role "' . $role . '" not found.'));
+      }
+
+      // Create edit array from permissions
+      $edit = array();
+      foreach ($permissions as $name => $value) {
+        $edit[$rid . '[' . $name . ']'] = $value;
+      }
+
+    $this->drupalPost('admin/settings/permissions', $edit, t('Save permissions'));
+    $this->assertText(t('The changes have been saved.'), t('[permission] Saved changes.'));
+  }
+
 }
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1090
diff -u -p -r1.1090 node.module
--- modules/node/node.module	31 Jul 2009 19:01:02 -0000	1.1090
+++ modules/node/node.module	5 Aug 2009 00:12:30 -0000
@@ -35,8 +35,8 @@ function node_help($path, $arg) {
 
   switch ($path) {
     case 'admin/help#node':
-      $output = '<p>' . t('The node module manages content on your site, and stores all posts (regardless of type) as a "node" . In addition to basic publishing settings, including whether the post has been published, promoted to the site front page, or should remain present (or sticky) at the top of lists, the node module also records basic information about the author of a post. Optional revision control over edits is available. For additional functionality, the node module is often extended by other modules.') . '</p>';
-      $output .= '<p>' . t('Though each post on your site is a node, each post is also of a particular <a href="@content-type">content type</a>. <a href="@content-type">Content types</a> are used to define the characteristics of a post, including the title and description of the fields displayed on its add and edit pages. Each content type may have different default settings for <em>Publishing options</em> and other workflow controls. By default, the two content types in a standard Drupal installation are <em>Page</em> and <em>Story</em>. Use the <a href="@content-type">content types page</a> to add new or edit existing content types. Additional content types also become available as you enable additional core, contributed and custom modules.', array('@content-type' => url('admin/structure/types'))) . '</p>';
+      $output = '<p>' . t('The node module manages content on your site, and stores all content (regardless of type) as a "node." In addition to basic publishing settings, including whether the content has been published, promoted to the site front page, or should remain present (or sticky) at the top of lists, the node module also records basic information about the author of a content item. Optional revision control over edits is available. For additional functionality, the node module is often extended by other modules.') . '</p>';
+      $output .= '<p>' . t('Though each content item on your site is a node, each content item is also of a particular <a href="@content-type">content type</a>. <a href="@content-type">Content types</a> are used to define the characteristics of a content item, including the title and description of the fields displayed on its add and edit pages. Each content type may have different default settings for <em>Publishing options</em> and other workflow controls. By default, the two content types in a standard Drupal installation are <em>Page</em> and <em>Article</em>. Use the <a href="@content-type">content types page</a> to add new or edit existing content types. Additional content types also become available as you enable additional core, contributed and custom modules.', array('@content-type' => url('admin/structure/types'))) . '</p>';
       $output .= '<p>' . t('The administrative <a href="@content">content page</a> allows you to review and manage your site content. The node module makes a number of permissions available for each content type, which may be set by role on the <a href="@permissions">permissions page</a>.', array('@content' => url('admin/content'), '@permissions' => url('admin/settings/permissions'))) . '</p>';
       $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@node">Node module</a>.', array('@node' => 'http://drupal.org/handbook/modules/node/')) . '</p>';
       return $output;
