'feedback', 'title' => t('Feedback'), 'callback' => 'feedback_mail_page', 'access' => user_access('can send feedback'), 'type' => MENU_SUGGESTED_ITEM, ); $items[] = array ( 'path' => 'admin/settings/feedback', 'title' => t('Feedback'), 'description' => t('Configure the feedback page'), 'callback' => 'feedback_settings_page', 'access' => user_access('administer feedback'), 'type' => MENU_NORMAL_ITEM, ); } return $items; } /** * Implementation of hook_perm(). */ function feedback_perm() { return array ('can send feedback', 'administer feedback'); } /** * feedback admin center */ function feedback_settings_page() { $page = arg(3); if (empty($page)) { $output = feedback_settings_overview($page); } else if (arg(4) == 'delete' && $page != 'default') { $output = feedback_settings_delete($page); } else { $output = drupal_get_form('feedback_settings_form', $page); } print theme('page', $output); } /** * admin settings overview page */ function feedback_settings_overview($page) { //show feedback pages overview $header = array (t('Feedback page name'), t('Feedback page location'), ''); $pages = _feedback_get_page_names(); foreach ($pages as $page) { $delete = ($page != 'default') ? ' '.l(t('delete'), 'admin/settings/feedback/'.$page.'/delete') : ''; $path = ($page != 'default') ? 'feedback/'.$page : 'feedback'; $rows[] = array ($page, l(url($path), $path), l(t('edit'), 'admin/settings/feedback/'.$page) . $delete); } $output = theme('table', $header, $rows); $output .= drupal_get_form('feedback_settings_overview_add', $pages); return $output; } function feedback_settings_overview_add($pages) { $form['group']['page_name'] = array( '#type' => 'textfield', '#title' => t('Feedback page name'), '#size' => 50, '#maxlength' => 60, '#required' => TRUE, ); $form['group'][] = array( '#type' => 'submit', '#value' => t('Add page'), ); $form['group'] += array( '#type' => 'fieldset', '#title' => t('Add a further feedback page'), ); $form['pages'] = array('#type' => 'value', '#value' => $pages); return $form; } function feedback_settings_overview_add_validate($form_id, &$edit) { if (in_array($edit['page_name'], $edit['pages'])) { form_set_error('page_name', t('This page already exists.')); } } function feedback_settings_overview_add_submit($form_id, &$edit) { _feedback_add_page($edit['page_name']); drupal_set_message(t('Your feedback page has been added.')); } /** * Shows a form for editing a feedback page */ function feedback_settings_form($pagename) { $page = _feedback_get_page($pagename); $form['email'] = array( '#type' => 'textfield', '#title' => t('Default Email Address'), '#default_value' => $page->email, '#size' => 80, '#maxlength' => 300, '#description' => t('The email address which should receive all form submissions'), '#required' => TRUE, ); $form['title'] = array( '#type' => 'textfield', '#title' => t('Title of the feedback page'), '#default_value' => $page->title, '#size' => 80, '#maxlength' => 80, '#required' => TRUE, ); $form['instructions'] = array( '#type' => 'textarea', '#title' => t('Instructions'), '#default_value' => $page->instructions, '#cols' => 60, '#rows' => 10, '#description' => t('The instructions that will be displayed for the user on how to fill the form'), ); $form['subject'] = array( '#type' => 'fieldset', '#title' => t('Subject'), ); $form['subject']['subject_prefix'] = array( '#type' => 'textfield', '#title' => t('Subject Prefix'), '#default_value' => $page->subject_prefix, '#size' => 80, '#maxlength' => 80, '#description' => t('The prefix that should be added before the subject on each email'), ); $form['subject']['field_subject'] = array( '#type' => 'checkbox', '#title' => t('Include a subject textfield'), '#return_value' => 1, '#default_value' => $page->field_subject, ); $form['subject']['field_category'] = array( '#type' => 'textarea', '#title' => t('Categories'), '#default_value' => $page->field_category, '#cols' => 40, '#rows' => 6, '#description' => t('Put each subject category on a separate line or separate them by commas. No HTML allowed.').'
'.t('Leave this field empty to disable this feature.'), ); $form['fields'] = array( '#type' => 'fieldset', '#title' => t('Fields to include on the form'), ); $form['fields']['field_name'] = array( '#type' => 'checkbox', '#title' => t('Sender Name'), '#return_value' => 1, '#default_value' => $page->field_name, ); $form['fields']['field_postal'] = array( '#type' => 'checkbox', '#title' => t('Postal Address'), '#return_value' => 1, '#default_value' => $page->field_postal, ); $form['fields']['field_phone'] = array( '#type' => 'checkbox', '#title' => t('Phone Number'), '#return_value' => 1, '#default_value' => $page->field_phone, ); $form['fields']['field_body'] = array( '#type' => 'checkbox', '#title' => t('Message Body'), '#return_value' => 1, '#default_value' => $page->field_body, ); $form['misc'] = array( '#type' => 'fieldset', '#title' => t('Miscellaneous Settings'), ); $form['misc']['hourly_threshold'] = array( '#type' => 'select', '#title' => t('Hourly threshold'), '#default_value' => $page->hourly_threshold, '#options' => drupal_map_assoc(array (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50)), '#description' => t('The maximum number of form submissions a user can perform per hour.'), ); $form['misc']['logging'] = array( '#type' => 'checkbox', '#title' => t('Log all feedback attempts to watchdog'), '#return_value' => 1, '#default_value' => $page->logging, ); $form['page'] = array('#type' => 'value', '#value' => $page); $form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') ); return $form; } function feedback_settings_form_submit($form_id, $edit) { $page = $edit['page']; unset($edit['submit'], $edit['form_id'], $edit['page']); db_query("UPDATE {feedback_pages} SET data = '%s' WHERE name = '%s'", serialize($edit), $page->name); drupal_set_message(t('The configuration options have been saved.')); return array('admin/settings/feedback'); } /** * Deletes a feedback page, if the user confirms */ function feedback_settings_delete($pagename) { if ($_POST['op'] == t('Delete')) { db_query("DELETE FROM {feedback_pages} WHERE name ='%s'", $pagename); drupal_set_message(t('The feedback page has been deleted.')); drupal_goto('admin/settings/feedback'); } else { $message = t('Are you sure you want to delete the feedback page "!page"?', array('!page' => $pagename)); $output = drupal_get_form('confirm_form', array(), $message, 'admin/settings/feedback', $message, t('Delete'), t('Cancel')); return $output; } } /** * Site-wide feedback page */ function feedback_mail_page() { if ($pagename = arg(1)) { //check if this feedback page exists $pages = _feedback_get_page_names(); if (!in_array($pagename, $pages)) { drupal_not_found(); exit(); } } else { $pagename = 'default'; } $page = _feedback_get_page($pagename); $breadcrumb[] = array ('path' => 'feedback', 'title' => $page->title); menu_set_location($breadcrumb); drupal_set_title($page->title); if (!flood_is_allowed('feedback'.$page->name, $page->hourly_threshold)) { $message = t('You cannot send more than !number messages per hour. Please try again later.', array ('!number' => $page->hourly_threshold)); drupal_set_message($message, 'error'); return; } return drupal_get_form('feedback_mail_form', $page); } function feedback_mail_form($page) { global $user; $form['instructions'] = array('#value' => $page->instructions); if ($page->field_name) { $form['emailname'] = array( '#type' => 'textfield', '#title' => t('Your full name'), '#default_value' => ($user->uid) ? $user->name : '', '#size' => 60, '#maxlength' => 64, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); } $form['mail'] = array( '#type' => 'textfield', '#title' => t('Your e-mail address'), '#default_value' => ($user->uid) ? $user->mail : '', '#size' => 60, '#maxlength' => 64, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); if ($page->field_postal) { $form['postal'] = array( '#type' => 'textarea', '#title' => t('Your postal address'), '#cols' => 50, '#rows' => 4, ); } if ($page->field_phone) { $form['phone'] = array( '#type' => 'textfield', '#title' => t('Your phone number'), '#size' => 60, '#maxlength' => 64, ); } if ($page->field_subject) { $form['subject'] = array( '#type' => 'textfield', '#title' => t('Subject'), '#size' => 60, '#maxlength' => 64, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); } if ($page->field_category) { $form['category'] = array( '#type' => 'select', '#title' => t('Category'), '#options' => _feedback_get_options($page->field_category), '#description' => NULL, '#extra' => 0, '#multiple' => FALSE, '#required' => TRUE, ); } if ($page->field_body) { $form['body'] = array( '#type' => 'textarea', '#title' => t('Message'), '#cols' => 60, '#rows' => 15, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); } $form['referer'] = array( '#type' => 'hidden', '#value' => $_SERVER[HTTP_REFERER], ); $form['op'] = array( '#type' => 'submit', '#value' => t('Send message'), ); $form['page'] = array('#type' => 'value', '#value' => $page); return $form; } /** * Validate the site-wide form submission. */ function feedback_mail_form_validate($form_id, &$edit) { $page = $edit['page']; if (!valid_email_address($edit['mail'])) { form_set_error('mail', t('You must enter a valid e-mail address.')); } if (preg_match("/\r|\n/", $edit['subject'])) { form_set_error('subject', t('The subject cannot contain linebreaks.')); watchdog('mail', 'Email injection exploit attempted in feedback form subject: '.check_plain($edit['subject']), WATCHDOG_NOTICE); } if (!$edit['emailname'] && $page->field_name) { form_set_error('emailname', t('Please enter your full name')); } else if ($page->field_name && drupal_strlen($edit['emailname']) > FEEDBACK_MAX_NAME) { form_set_error('emailname', t('Too long input.')); } if ($page->field_category && (!$edit['category'] || !in_array($edit['category'], _feedback_get_options($page->field_category)))) { form_set_error('category', t('Please choose a category')); } if (!$edit['subject'] && $page->field_subject) { form_set_error('subject', t('Please enter a subject')); } else if ($page->field_subject && drupal_strlen($edit['subject']) > FEEDBACK_MAX_SUBJECT) { form_set_error('subject', t('Too long input.')); } if (!$edit['body'] && $page->field_body) { form_set_error('body', t('Please enter your message.')); } else if ($page->field_body && drupal_strlen($edit['body']) > FEEDBACK_MAX_BODY) { form_set_error('body', t('Please shorten your input. Up to !limit characters are allowed.', array ('!limit' => FEEDBACK_MAX_BODY))); } if ($page->field_postal && drupal_strlen($edit['postal']) > FEEDBACK_MAX_POSTAL) { form_set_error('postal', t('Please shorten your input. Up to !limit characters are allowed.', array ('!limit' => FEEDBACK_MAX_POSTAL))); } if ($page->field_phone && drupal_strlen($edit['phone']) > 64) { form_set_error('phone', t('Too long input.')); } } /** * Process the site-wide form submission. */ function feedback_mail_form_submit($form_id, &$edit) { // Prepare the sender: $from = feedback_plain_text($edit['mail']); $page = $edit['page']; // Compose the body: if ($page->field_category) { $message[] = t('Category') . ': ' . check_plain($edit['category']); } if ($page->field_body) { $message[] = feedback_plain_text($edit['body']); } $message[] = t('Sent from @form by @name.', array ('@name' => $edit['emailname'], '@form' => url($_GET['q'], NULL, NULL, TRUE))); $message[] = _feedback_user_info($edit, $page); // Tidy up the body: foreach ($message as $key => $value) { $message[$key] = wordwrap($value); } // Prepare the body: $body = implode("\n\n", $message); $category = $page->field_category ? ' ['.$edit['category'].'] ' : ' '; $subject = $page->subject_prefix . $category . $edit['subject']; // Send the e-mail to the recipients: drupal_mail('feedback', $page->email, $subject, $body, $from); // Log the operation: flood_register_event('feedback'. $page->name); if ($page->logging) { watchdog('mail', t('@name-from sent a feedback e-mail', array ('@name-from' => $edit['emailname'] . " <$from>"))); } // Update user: drupal_set_message(t('Your message has been sent.')); // Jump to home page rather than back to feedback page to avoid contradictory messages if flood control has been activated. drupal_goto(); } /* * Returns some additional user information to append to the mail */ function _feedback_user_info(&$edit, $page) { global $user; $info = "\n".t('Site Name').': '.variable_get('site_name', ''); if ($user->name) { $info .= "\n".t('Registered name').': '.feedback_plain_text($user->name); } if ($page->field_name) { $info .= "\n".t('Entered Name').': '.feedback_plain_text($edit['emailname']); } $info .= "\n".t('E-mail address').': '.$edit['mail']; if ($page->field_postal) { $info .= "\n".t('Postal address').': '.feedback_plain_text($edit['postal']); } if ($page->field_phone) { $info .= "\n".t('Phone Number').': '.feedback_plain_text($edit['phone']); } if ($edit['referer']) { $info .= "\n".t('Referring page').': '.feedback_plain_text($edit['referer']); } if (isset ($_SERVER['REMOTE_ADDR'])) { $info .= "\n".t('IP Address').': '.'http://whois.domaintools.com/'.feedback_plain_text($_SERVER['REMOTE_ADDR']); } if (isset ($_SERVER['REMOTE_HOST'])) { $info .= "\n".t('Machine name').': '.feedback_plain_text($_SERVER['REMOTE_HOST']); } if (isset ($_SERVER['HTTP_USER_AGENT'])) { $info .= "\n".t('Browser info').': '.feedback_plain_text($_SERVER['HTTP_USER_AGENT']); } return $info; } /* * Strips tags and makes entities readable */ function feedback_plain_text($string) { return html_entity_decode(strip_tags($string), ENT_QUOTES); } function _feedback_get_options($text) { $options = array ('0' => '--'); $lines = split("[,\n\r]", $text); foreach ($lines as $line) { if ($line = trim($line)) { $options[$line] = $line; } } return $options; } /* * Returns an array of all available feedback page names */ function _feedback_get_page_names() { $result = db_query('SELECT name from {feedback_pages}'); $pages = array(); while ($row = db_fetch_object($result)) { $pages[] = $row->name; } return $pages; } /* * Returns a data object from a feedback page */ function _feedback_get_page($name) { $result = db_query("SELECT * from {feedback_pages} WHERE name = '%s'", $name); if ($row = db_fetch_array($result)) { $row += (array)unserialize($row['data']); unset($row['data']); } return (object)$row; } function _feedback_add_page($pagename) { $defaults = array( 'email' => variable_get('site_mail', ini_get('sendmail_from')), 'title' => t('feedback'), 'hourly_threshold' => 3, 'logging' => 1, 'field_name' => 1, 'field_body' => 1, ); db_query("INSERT INTO {feedback_pages} (name, data) VALUES('%s','%s')", $pagename, serialize($defaults)); }