Index: modules/contact/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v
retrieving revision 1.91
diff -u -p -r1.91 contact.module
--- modules/contact/contact.module	26 Jun 2007 22:21:08 -0000	1.91
+++ modules/contact/contact.module	29 Jun 2007 03:03:38 -0000
@@ -7,6 +7,20 @@
  */
 
 /**
+ * @name Contact flags
+ * @{
+ * Flags for use in access to contact forms.
+ */
+
+define('CONTACT_BY_AUTH', 0x0001);
+define('CONTACT_BY_ANON', 0x0002);
+define('CONTACT_BY_BOTH', CONTACT_BY_AUTH | CONTACT_BY_ANON);
+
+/**
+ * @} End of "Contact flags".
+ */
+
+/**
  * Implementation of hook_help().
  */
 function contact_help($section) {
@@ -35,8 +49,9 @@ function contact_help($section) {
  * Implementation of hook_perm
  */
 function contact_perm() {
-  return array('access site-wide contact form');
+  return array('access site-wide contact form', 'access personal contact forms');
 }
+
 /**
  * Implementation of hook_menu().
  */
@@ -99,41 +114,65 @@ function contact_menu() {
 function _contact_user_tab_access($account) {
   global $user;
   if (!isset($account->contact)) {
-    $account->contact = FALSE;
+    $account->contact = 0;
   }
   return
-    $account &&
+    $account && user_access('access personal contact forms') &&
     (
-      ($user->uid != $account->uid && $account->contact) ||
+      ($user->uid && $user->uid != $account->uid && ($account->contact & CONTACT_BY_AUTH)) || // authenticated users only
+      ($user->uid != $account->uid && ($account->contact & CONTACT_BY_ANON)) || // also anonymous users
       user_access('administer users')
     );
 }
 
 /**
+* Implementation of hook_enable().
+*/
+function contact_enable() {
+  drupal_set_message(t('If you are allowing anonymous users to access personal contact forms, be sure to provide adqeuate protection against malicious use by spam bots.'), 'error');
+}
+
+/**
  * Implementation of hook_user().
  *
  * Allows the user the option of enabling/disabling his personal contact form.
  */
 function contact_user($type, &$edit, &$user, $category = NULL) {
+
   if ($type == 'form' && $category == 'account') {
+
     $form['contact'] = array('#type' => 'fieldset',
       '#title' => t('Contact settings'),
       '#weight' => 5,
       '#collapsible' => TRUE,
     );
-    $form['contact']['contact'] = array('#type' => 'checkbox',
+    $form['contact']['contact'] = array('#type' => 'radios',
       '#title' => t('Personal contact form'),
       '#default_value' => !empty($edit['contact']) ? $edit['contact'] : FALSE,
       '#description' => t('Allow other users to contact you by e-mail via <a href="@url">your personal contact form</a>. 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"))),
+      '#options' => _contact_user_form_options(),
     );
-    return $form;
+  return $form;
   }
   elseif ($type == 'validate') {
     return array('contact' => isset($edit['contact']) ? $edit['contact'] : FALSE);
   }
   elseif ($type == 'insert') {
-    $edit['contact'] = variable_get('contact_default_status', 1);
+    $edit['contact'] = variable_get('contact_default_status', CONTACT_BY_AUTH);
+  }
+}
+
+/**
+ * Builds array for personal contact form options
+ */
+function _contact_user_form_options() {
+  $anon = user_load(0);
+  $options[0] = t('Nobody can contact me via my personal contact form.');
+  $options[CONTACT_BY_AUTH] = t('Registered users with appropriate permissions can contact me via my personal contact form.'); 
+  if (user_access('access personal contact forms', $anon)) { 
+    $options[CONTACT_BY_BOTH] = t('Anonymous users and registered users with appropriate permissions can contact me via my personal contact form.'); 
   }
+  return $options;
 }
 
 /**
@@ -300,7 +339,7 @@ function contact_admin_settings() {
   $form['contact_default_status'] = array(
     '#type' => 'checkbox',
     '#title' => t('Enable personal contact form by default'),
-    '#default_value' => variable_get('contact_default_status', 1),
+    '#default_value' => variable_get('contact_default_status', CONTACT_BY_AUTH),
     '#description' => t('Default status of the personal contact form for new users.'),
   );
   return system_settings_form($form);
@@ -312,7 +351,7 @@ function contact_admin_settings() {
 function contact_user_page($account) {
   global $user;
 
-  if (!valid_email_address($user->mail)) {
+  if ($user->uid && !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")));
   }
   else if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
@@ -327,12 +366,31 @@ function contact_user_page($account) {
 }
 
 function contact_mail_user(&$form_state, $recipient) {
+/**
+ * Generates the personal contact form.
+ */
   global $user;
-  $form['#token'] = $user->name . $user->mail;
-  $form['from'] = array('#type' => 'item',
-    '#title' => t('From'),
-    '#value' => check_plain($user->name) .' &lt;'. check_plain($user->mail) .'&gt;',
-  );
+
+  if ($user->uid) {
+    $form['#token'] = $user->name . $user->mail;
+    $form['from'] = array('#type' => 'item',
+      '#title' => t('From'),
+      '#value' => check_plain($user->name) .' &lt;'. check_plain($user->mail) .'&gt;',
+    );
+  }
+  else {
+    $form['#token'] = $recipient->name . $recipient->mail;
+    $form['name'] = array('#type' => 'textfield',
+      '#title' => t('Your name'),
+      '#maxlength' => 255,
+      '#required' => TRUE,
+    );
+    $form['mail'] = array('#type' => 'textfield',
+      '#title' => t('Your e-mail address'),
+      '#maxlength' => 255,
+      '#required' => TRUE,
+    );
+  }
   $form['to'] = array('#type' => 'item',
     '#title' => t('To'),
     '#value' => check_plain($recipient->name),
@@ -347,8 +405,11 @@ function contact_mail_user(&$form_state,
     '#rows' => 15,
     '#required' => TRUE,
   );
+  // We do not allow anonymous users to send themselves a copy
+  // because it can be abused to spam people.
   $form['copy'] = array('#type' => 'checkbox',
     '#title' => t('Send yourself a copy.'),
+    '#access' => (bool)$user->uid,
   );
   $form['submit'] = array('#type' => 'submit',
     '#value' => t('Send e-mail'),
@@ -356,6 +417,18 @@ function contact_mail_user(&$form_state,
   return $form;
 }
 
+
+/**
+ * Validate the personal contact page form submission.
+ */
+function contact_mail_user_validate($form, &$form_state) {
+  global $user;
+
+  if (!$user->uid && !valid_email_address($form_state['values']['mail'])) {
+    form_set_error('mail', t('You must enter a valid e-mail address.'));
+  }
+}
+
 /**
  * Process the personal contact page form submission.
  */
@@ -365,14 +438,24 @@ function contact_mail_user_submit($form,
   $account = user_load(array('uid' => arg(1), 'status' => 1));
   // Compose the body:
   $message[] = "$account->name,";
-  $message[] = 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)), '!form-url' => url($_GET['q'], array('absolute' => TRUE)), '!site' => variable_get('site_name', 'Drupal')));
-  $message[] = 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))));
+  if ($user->uid) {
+    $message[] = 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)), '@form-url' => url($_GET['q'], array('absolute' => TRUE)), '!site' => variable_get('site_name', 'Drupal')));
+  }
+  else {
+    $message[] = t("@name (@mail) has sent you a message via your contact form (@form-url) at !site.", array('@name' => $form_state['values']['name'], '@mail' => $form_state['values']['mail'], '@form-url' => url($_GET['q'], array('absolute' => TRUE)), '!site' => variable_get('site_name', 'Drupal')));
+  }
+  $message[] = 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))));
   $message[] = t('Message:');
   $message[] = $form_state['values']['message'];
 
   // Prepare all fields:
   $to = $account->mail;
-  $from = $user->mail;
+  if ($user->uid) {
+    $from = $user->mail;
+  }
+  else {
+    $from = $form_state['values']['mail'];
+  }
 
   // Format the subject:
   $subject = '['. variable_get('site_name', 'Drupal') .'] '. $form_state['values']['subject'];
@@ -384,13 +467,18 @@ function contact_mail_user_submit($form,
   drupal_mail('contact-user-mail', $to, $subject, $body, $from);
 
   // Send a copy if requested:
-  if ($form_state['values']['copy']) {
+  if (isset($form_state['values']['copy'])) {
     drupal_mail('contact-user-copy', $from, $subject, $body, $from);
   }
 
   // Log the operation:
   flood_register_event('contact');
-  watchdog('mail', '%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name));
+  if ($user->uid) {
+    watchdog('mail', t('%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name)));
+  }
+  else {
+    watchdog('mail', t('%name-from sent %name-to an e-mail.', array('%name-from' => $form_state['values']['name'] . ', ' . $form_state['values']['mail'] . ',', '%name-to' => $account->name)));
+  }
 
   // Set a status message:
   drupal_set_message(t('The message has been sent.'));
@@ -416,6 +504,9 @@ function contact_site_page() {
   return $output;
 }
 
+/**
+ * Generates the site-wide contact form.
+ */
 function contact_mail_page() {
   global $user;
 
@@ -510,7 +601,7 @@ function contact_mail_page_submit($form,
   $from = $form_state['values']['mail'];
 
   // Compose the body:
-  $message[] = t("!name sent a message using the contact form at !form.", array('!name' => $form_state['values']['name'], '!form' => url($_GET['q'], array('absolute' => TRUE))));
+  $message[] = t("@name sent a message using the contact form at @form.", array('@name' => $form_state['values']['name'], '@form' => url($_GET['q'], array('absolute' => TRUE))));
   $message[] = $form_state['values']['message'];
 
   // Load the category information:
@@ -546,3 +637,4 @@ function contact_mail_page_submit($form,
   $form_state['redirect'] = '';
   return;
 }
+
