Index: modules/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact.module,v
retrieving revision 1.26
diff -u -r1.26 contact.module
--- modules/contact.module	11 Oct 2005 19:44:34 -0000	1.26
+++ modules/contact.module	14 Oct 2005 15:30:24 -0000
@@ -121,6 +121,11 @@
 
 function contact_user_mail_execute($form_id, $edit) {
   global $user;
+  
+  if (contact_check_exploit($edit)) {
+    drupal_set_message(t('Invalid data in form.'), 'error');
+    drupal_goto('contact');
+  }
 
   $account = user_load(array('uid' => arg(1), 'status' => 1));
   // Compose the body:
@@ -145,21 +150,23 @@
   // Prepare the body:
   $body = implode("\n\n", $message);
 
+  $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
+
   // Send the e-mail:
-  user_mail($to, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
+  user_mail($to, $subject, $body, $headers);
 
+  // Set a status message:
+  drupal_set_message(t('The message has been sent.'));
   // Send a copy if requested:
   if ($edit['copy']) {
-    user_mail($from, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
+    user_mail($from, $subject, $body, $headers);
+    drupal_set_message(t('A copy of the message has been sent to you.'));
   }
 
   // Log the operation:
   flood_register_event('contact');
   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('The message has been sent.'));
-
   // Jump to the user's profile page:
   drupal_goto("user/$account->uid");
 }
@@ -279,6 +286,11 @@
 
 function contact_mail_page_execute($form_id, $edit) {
 
+  if (contact_check_exploit($edit)) {
+    drupal_set_message(t('Invalid data in form.'), 'error');
+    drupal_goto('contact');
+  }
+
   // Prepare the sender:
   $from = $edit['mail'];
 
@@ -300,12 +312,18 @@
   // Load the category information:
   $contact = db_fetch_object(db_query("SELECT * FROM {contact} WHERE category = '%s'", $edit['category']));
 
+  $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
+
   // Send the e-mail to the recipients:
-  user_mail($contact->recipients, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
+  user_mail($contact->recipients, $subject, $body, $headers);
+
+  // Set a status message:subject
+  drupal_set_message(t('Your message has been sent.'));
 
   // If the user requests it, send a copy.
   if ($edit['copy']) {
-    user_mail($from, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
+    user_mail($from, $subject, $body, $headers);
+    drupal_set_message(t('A copy of the message has been sent to you.'));
   }
 
   // Send an auto-reply if necessary:
@@ -317,9 +335,33 @@
   flood_register_event('contact');
   watchdog('mail', t('%name-from sent an e-mail regarding %category.', array('%name-from' => theme('placeholder', $edit['name'] ." <$from>"), '%category' => theme('placeholder', $contact->category))));
 
-  // Set a status message:subject
-  drupal_set_message(t('Your message has been sent.'));
-
   // Jump to contact page:
   drupal_goto('contact');
 }
+
+function contact_check_exploit($edit) {
+  $bad_strings = array (
+    'To:',
+    'Cc:',
+    'Bcc:',
+    'Content-Type:',
+    'MIME-Version:',
+    'Content-Transfer-Encoding:');
+
+  foreach($edit as $key => $data) {
+    switch($key) {
+      case 'mail':
+      case 'subject':
+      case 'message':
+        foreach($bad_strings as $str) {
+          if (stristr($data, $str)) {
+            watchdog ('user', t('Attempt to relay spam using "%key" field. Field content: "%data"',
+            array('%key'=>$key, '%data'=>$data)));
+            return true;
+          }
+        }
+        break;
+    }
+  }
+  return false;
+}
