? sites/default/files ? sites/default/settings.php Index: modules/contact/contact.install =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.install,v retrieving revision 1.11 diff -u -p -r1.11 contact.install --- modules/contact/contact.install 15 Nov 2008 13:01:05 -0000 1.11 +++ modules/contact/contact.install 26 Apr 2009 18:51:07 -0000 @@ -2,6 +2,11 @@ // $Id: contact.install,v 1.11 2008/11/15 13:01:05 dries Exp $ /** + * @file contact.install + * Contains functions for installing contact.module + */ + +/** * Implementation of hook_install(). */ function contact_install() { Index: modules/contact/contact.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v retrieving revision 1.112 diff -u -p -r1.112 contact.module --- modules/contact/contact.module 8 Mar 2009 05:08:22 -0000 1.112 +++ modules/contact/contact.module 26 Apr 2009 18:51:07 -0000 @@ -45,6 +45,10 @@ function contact_perm() { '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.'), + ), ); } @@ -116,15 +120,40 @@ function contact_menu() { */ function _contact_user_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; + } + + // Do not show the contact form when it is turned off. + if (!isset($account->contact) || $account->contact == 0) { + return FALSE; } - return - $account && $user->uid && - ( - ($user->uid != $account->uid && $account->contact) || - user_access('administer users') - ); + + // The user himself always has access to his own contact form, + // even if he is not allowed to access the contact forms of other users, + // unless he has turned his own contact form off. + if ($user->uid == $account->uid) { + return TRUE; + } + + + // Do not show the form if the user is not allowed to access it. + // This does not apply for the user's own contact form. + if (!user_access('access personal contact form')) { + return FALSE; + } + + + // Show the contact form, but only show to anonymous users + // when the user has explicitly opted to show it to them. + if (user_is_logged_in() || $account->contact) { + return TRUE; + } + + // For privacy, do not show the contact form by default. + return FALSE; } /** @@ -141,15 +170,11 @@ function contact_load($cid) { */ function contact_user_form(&$edit, &$user, $category = NULL) { if ($category == 'account') { - $form['contact'] = array('#type' => 'fieldset', - '#title' => t('Contact settings'), - '#weight' => 5, - '#collapsible' => TRUE, - ); - $form['contact']['contact'] = array('#type' => 'checkbox', - '#title' => t('Personal contact form'), + $form['account']['contact'] = array('#type' => 'checkbox', + '#title' => t('Enable personal contact form'), '#default_value' => !empty($edit['contact']) ? $edit['contact'] : FALSE, - '#description' => t('Allow other users to contact you by e-mail via your personal contact form. Note that while your e-mail address is not made public to other members of the community, privileged users such as site administrators are able to contact you even if you choose not to enable this feature.', array('@url' => url("user/$user->uid/contact"))), + '#description' => t('Note that while your e-mail address is not made public to other members of the community, site administrators are able to contact you even if you choose not to enable this feature.'), + '#weight' => 10, ); return $form; } @@ -173,13 +198,19 @@ function contact_user_validate(&$edit, & * Implementation of hook_mail(). */ function contact_mail($key, &$message, $params) { + global $user; $language = $message['language']; switch ($key) { case 'page_mail': case 'page_copy': $contact = $params['contact']; $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language); - $message['body'][] = t("!name sent a message using the contact form at !form.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language))), $language->language); + if (!$user->uid == 0) { + $message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)), '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language); + } + else { + $message['body'][] = t("!name has sent you a message via your contact form (!form-url) at !site.", array('!name' => $params['name'], '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language); + } $message['body'][] = $params['message']; break; case 'page_autoreply': @@ -193,7 +224,7 @@ function contact_mail($key, &$message, $ $account = $params['account']; $message['subject'] .= '[' . variable_get('site_name', 'Drupal') . '] ' . $params['subject']; $message['body'][] = "$account->name,"; - $message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)), '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language); + $message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => $user->uid ? url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)) : $user->mail, '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language); $message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE, 'language' => $language))), $language->language); $message['body'][] = t('Message:', NULL, $language->language); $message['body'][] = $params['message']; Index: modules/contact/contact.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.pages.inc,v retrieving revision 1.17 diff -u -p -r1.17 contact.pages.inc --- modules/contact/contact.pages.inc 21 Apr 2009 09:27:52 -0000 1.17 +++ modules/contact/contact.pages.inc 26 Apr 2009 18:51:07 -0000 @@ -29,6 +29,9 @@ function contact_site_page() { return $output; } +/** + * Provides the form definition for the site-wide contact page. + */ function contact_mail_page() { global $user; @@ -154,7 +157,11 @@ function contact_mail_page_submit($form, function contact_user_page($account) { global $user; - if (!valid_email_address($user->mail)) { + if ($user->uid == 0 && $account->contact) { + drupal_set_title($account->name); + $output = drupal_get_form('contact_mail_user', $account); + } + elseif (!valid_email_address($user->mail) && !$account->contact) { $output = t('You need to provide a valid e-mail address to contact other users. Please update your user information 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')) { @@ -168,66 +175,134 @@ function contact_user_page($account) { return $output; } +/** + * Provides the form definition for the user contact page. + */ function contact_mail_user(&$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) . ' <' . check_plain($user->mail) . '>', + ); + $form['mail'] = array( + '#type' => 'value', + '#value' => check_plain($user->mail), + ); + } + else { + $form['#token'] = 'Anonymous' . variable_get('site_mail'); + $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' => check_plain($user->name) . ' <' . check_plain($user->mail) . '>', - ); $form['to'] = array('#type' => 'item', '#title' => t('To'), '#markup' => check_plain($recipient->name), ); - $form['subject'] = array('#type' => 'textfield', + $form['subject'] = array( + '#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 50, '#required' => TRUE, ); - $form['message'] = array('#type' => 'textarea', + $form['message'] = array( + '#type' => 'textarea', '#title' => t('Message'), '#rows' => 15, '#required' => TRUE, ); - $form['copy'] = array('#type' => 'checkbox', - '#title' => t('Send yourself a copy.'), - ); - $form['submit'] = array('#type' => 'submit', + if ($user->uid) { + $form['copy'] = array( + '#type' => 'checkbox', + '#title' => t('Send yourself a copy.'), + ); + } + else { + drupal_add_js(drupal_get_path('module', 'contact') . '/contact.js'); + $form['copy'] = array( + '#type' => 'value', + '#value' => FALSE, + ); + } + $form['submit'] = array( + '#type' => 'submit', '#value' => t('Send e-mail'), ); return $form; } /** + * Validate the user contact page form submission. + */ +function contact_mail_user_validate($form, &$form_state) { + global $user; + if (!valid_email_address($form_state['values']['mail'])) { + form_set_error('mail', t('You must enter a valid e-mail address.')); + } + if (!$user->uid) { + foreach (array('from' => 'name', 'mail' => 'mail') as $form_field => $cookie_field) { + // Set cookie for 365 days. + if (isset($form_state['values'][$form_field])) { + setcookie('comment_info_' . $cookie_field, $form_state['values'][$form_field], $_SERVER['REQUEST_TIME'] + 31536000, '/'); + } + } + } +} + +/** * Process the personal contact page form submission. */ function contact_mail_user_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('The 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.19 diff -u -p -r1.19 contact.test --- modules/contact/contact.test 21 Apr 2009 09:27:52 -0000 1.19 +++ modules/contact/contact.test 26 Apr 2009 18:51:07 -0000 @@ -190,7 +190,7 @@ class ContactSitewideTestCase extends Dr $edit['reply'] = $reply; $edit['selected'] = ($selected ? '1' : '0'); $this->drupalPost('admin/build/contact/edit/' . $category_id, $edit, t('Save')); - return($category_id); + return ($category_id); } /** @@ -244,7 +244,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. @@ -254,7 +254,7 @@ class ContactSitewideTestCase extends Dr } $this->drupalPost('admin/user/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.')); } } @@ -291,9 +291,10 @@ class ContactPersonalTestCase extends Dr // Reload variables. $this->drupalLogout(); - + // Create web users and attempt to use personal contact forms with default set to true. - $web_user1 = $this->drupalCreateUser(array()); + // Must specify the new 'access personal contact form' permission. + $web_user1 = $this->drupalCreateUser(array('access personal contact form')); $web_user2 = $this->drupalCreateUser(array()); $this->drupalLogin($web_user1); @@ -307,14 +308,66 @@ class ContactPersonalTestCase extends Dr $this->drupalPost(NULL, $edit, t('Send e-mail')); $this->assertText(t('The message has been sent.'), t('Message sent.')); + $this->drupalLogout(); + + // Create web users and attempt to use personal contact forms without + // 'access personal contact form' permissions + $web_user3 = $this->drupalCreateUser(array()); + $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(); + + // Create web user and set the 'allow anonymous access to personal contact form' setting. + // Then attempt to access the form as anonymous + $web_user5 = $this->drupalCreateUser(array()); + + $this->drupalLogin($web_user5); + + $edit = array(); + $edit['contact'] = TRUE; + $this->drupalPost('user/' . $web_user5->uid . '/edit', $edit, t('Save')); + $this->assertText(t('The changes have been saved.')); + + $this->assertTrue($web_user5->contact, t('Contact form enabled.')); + + $this->drupalLogout(); + + $admin_user = $this->drupalCreateUser(array('administer site-wide contact form', 'administer permissions')); + $this->drupalLogin($admin_user); + $this->setPermission('anonymous user', array('access personal contact form' => TRUE)); + $this->drupalLogout(); + + // Access the personal contact form as anonymous. + $this->drupalGet('user/' . $web_user5->uid . '/contact'); + $this->assertResponse(200, t('Access to personal contact form granted.')); + + $edit = array(); + $edit['from'] = "my name"; + $edit['mail'] = "test@example.com"; + $edit['subject'] = $this->randomName(16); + $edit['message'] = $this->randomName(64); + $this->drupalPost(NULL, $edit, t('Send e-mail')); + $this->assertText(t('The message has been sent.'), t('Message sent.')); + $this->drupalLogout(); + // Clear flood table in preparation for flood test and allow other checks to complete. db_delete('flood')->execute(); $num_records_flood = db_query("SELECT COUNT(*) FROM {flood}")->fetchField(); $this->assertIdentical($num_records_flood, '0', t('Flood table emptied.')); // Submit contact form with correct values and check flood interval. + $web_user6 = $this->drupalCreateUser(array('access personal contact form')); + $this->drupalLogin($web_user6); + $edit = array(); + $edit['subject'] = $this->randomName(16); + $edit['message'] = $this->randomName(64); for ($i = 0; $i < $flood_control; $i++) { - $this->drupalGet('user/' . $web_user2->uid . '/contact'); + $this->drupalGet('user/' . $web_user6->uid . '/contact'); $this->drupalPost(NULL, $edit, t('Send e-mail')); $this->assertText(t('The message has been sent.'), t('Message sent.')); } @@ -337,12 +390,36 @@ 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_user4 = $this->drupalCreateUser(array()); + $web_user7 = $this->drupalCreateUser(array('access personal contact form')); + $web_user8 = $this->drupalCreateUser(array()); - $this->drupalLogin($web_user3); + $this->drupalLogin($web_user7); + + $this->drupalGet('user/' . $web_user8->uid . '/contact'); + $this->assertResponse(403, t('Access to personal contact form denied.')); + } + + /** + * Set permission. + * + * @param string $role User role to set permissions for. + * @param array $permissions Key-value array of permissions to set. + */ + function setPermission($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 permission. + $edit = array(); + foreach ($permissions as $name => $value) { + $edit[$rid . '[' . $name . ']'] = $value; + } + + $this->drupalPost('admin/user/permissions', $edit, t('Save permissions')); + $this->assertText(t('The changes have been saved.'), t('[permission] Saved changes.')); - $this->drupalGet('user/' . $web_user4->uid . '/contact'); - $this->assertResponse(403, t('Access to personal contact form denied.')); } }