public function contact_submit() { // ---- Basic validation ---- $this->form_validation->set_rules('name', 'Name', 'trim|required|min_length[2]|max_length[100]|xss_clean'); $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email|max_length[150]|xss_clean'); $this->form_validation->set_rules('message', 'Message', 'trim|required|min_length[5]|max_length[2000]|xss_clean'); if ($this->form_validation->run() == false) { $this->session->set_flashdata('contact_error', validation_errors()); redirect('contact', 'refresh'); } $name = trim($this->input->post('name')); $email = trim($this->input->post('email')); $message = trim($this->input->post('message')); // ============================================================ // SPAM GUARD — silently rejects bots without revealing why // ============================================================ // 1. Honeypot check — if "website" field has anything, it's a bot $honeypot = $this->input->post('website'); if (!empty($honeypot)) { log_message('error', 'Contact spam blocked [honeypot]: ' . $email); $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent.'); redirect('contact', 'refresh'); } // 2. Timestamp check — reject if submitted under 3 seconds (too fast for humans) $loaded_at = (int) $this->input->post('form_loaded_at'); if ($loaded_at > 0 && (time() - $loaded_at) < 3) { log_message('error', 'Contact spam blocked [too fast]: ' . $email); $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent.'); redirect('contact', 'refresh'); } // 3. Reject if message contains more than 2 URLs $url_count = preg_match_all('#https?://#i', $message, $m); if ($url_count > 2) { log_message('error', 'Contact spam blocked [too many URLs]: ' . $email); $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent.'); redirect('contact', 'refresh'); } // 4. Reject BBCode-style link tags: [url=...], [link=...] if (stripos($message, '[url=') !== false || stripos($message, '[link=') !== false) { log_message('error', 'Contact spam blocked [bbcode link]: ' . $email); $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent.'); redirect('contact', 'refresh'); } // 5. Reject non-Latin scripts (Japanese, Chinese, Cyrillic, Arabic, etc.) // If your audience is English-only, this catches 90% of SEO spam. // Remove this check if you accept messages in other scripts. if (preg_match('/[\x{0400}-\x{04FF}\x{0600}-\x{06FF}\x{3040}-\x{30FF}\x{4E00}-\x{9FAF}\x{AC00}-\x{D7AF}]/u', $name . $message)) { log_message('error', 'Contact spam blocked [non-latin script]: ' . $email); $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent.'); redirect('contact', 'refresh'); } // 6. Reject classic spam keywords $spam_keywords = ['viagra', 'casino', 'poker', 'cialis', 'tramadol', 'payday loan', 'bitcoin wallet', 'crypto wallet']; $haystack = strtolower($name . ' ' . $message); foreach ($spam_keywords as $kw) { if (strpos($haystack, $kw) !== false) { log_message('error', 'Contact spam blocked [keyword]: ' . $email); $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent.'); redirect('contact', 'refresh'); } } // ============================================================ // END SPAM GUARD — clean submission, process normally // ============================================================ // Save as visitor record (matches your existing system) $visitor_data = array( 'name' => $name, 'source' => 'Online', 'email' => $email, 'purpose' => 'Contact Form', 'date' => date('Y-m-d'), 'note' => $message . " (Sent from contact form)", ); $this->Visitors_model->add($visitor_data); // Send email to the school $setting_data = $this->setting_model->get(); $school_email = !empty($setting_data[0]['email']) ? $setting_data[0]['email'] : 'ycucampus@gmail.com'; $mail_subject = 'New Contact Form Submission — ' . $name; $mail_body = "

Name: " . htmlspecialchars($name) . "

"; $mail_body .= "

Email: " . htmlspecialchars($email) . "

"; $mail_body .= "

Message:

" . nl2br(htmlspecialchars($message)) . "

"; $mail_body .= "

Sent from: " . $this->input->ip_address() . "

"; try { $this->mailer->send_mail($school_email, $mail_subject, $mail_body); } catch (Exception $e) { log_message('error', 'Contact email failed: ' . $e->getMessage()); } $this->session->set_flashdata('contact_success', 'Thank you! Your message has been sent. We will be in touch soon.'); redirect('contact', 'refresh'); }