msg('contactpage')->text(); } /** * @var string */ protected $formType; /** * @return array */ protected function getTypeConfig() { $contactConfig = $this->getConfig()->get('ContactConfig'); if ($contactConfig['default']['SenderName'] === null) { $sitename = $this->getConfig()->get('Sitename'); $contactConfig['default']['SenderName'] = "Contact Form on $sitename"; } if (isset($contactConfig[$this->formType])) { return $contactConfig[$this->formType] + $contactConfig['default']; } return $contactConfig['default']; } /** * Main execution function * * @param string|null $par Parameters passed to the page * @throws UserBlockedError * @throws ErrorPageError */ public function execute($par) { global $wgReCaptchaSiteKey, $wgReCaptchaSecretKey; if (!$this->getConfig()->get('EnableEmail')) { // From Special:EmailUser throw new ErrorPageError('usermaildisabled', 'usermaildisabledtext'); } $request = $this->getRequest(); $this->formType = strtolower($request->getText('formtype', $par)); $config = $this->getTypeConfig(); if ($config['MustBeLoggedIn']) { $this->requireLogin('contactpage-mustbeloggedin'); } if (!$config['RecipientUser']) { $this->getOutput()->showErrorPage( 'contactpage-config-error-title', 'contactpage-config-error' ); return; } $user = $this->getUser(); $nu = User::newFromName($config['RecipientUser']); if ($nu === null || !$nu->canReceiveEmail()) { $this->getOutput()->showErrorPage('noemailtitle', 'noemailtext'); return; } // Blocked users cannot use the contact form if they're disabled from sending email. if ($user->isBlockedFromEmailuser()) { throw new UserBlockedError($this->getUser()->getBlock()); } $pageTitle = ''; if ($this->formType != '') { $message = $this->msg('contactpage-title-' . $this->formType); if (!$message->isDisabled()) { $pageTitle = $message; } } if ($pageTitle === '') { $pageTitle = $this->msg('contactpage-title'); } $this->getOutput()->setPageTitle($pageTitle); $subject = ''; # Check for type in [[Special:Contact/type]]: change pagetext and prefill form fields if ($this->formType != '') { $message = $this->msg('contactpage-pagetext-' . $this->formType); if (!$message->isDisabled()) { $formText = $message->parseAsBlock(); } else { $formText = $this->msg('contactpage-pagetext')->parseAsBlock(); } $message = $this->msg('contactpage-subject-' . $this->formType); if (!$message->isDisabled()) { $subject = $message->inContentLanguage()->plain(); } } else { $formText = $this->msg('contactpage-pagetext')->parseAsBlock(); } $subject = trim($subject); if ($subject === '') { $subject = $this->msg('contactpage-defsubject')->inContentLanguage()->text(); } $fromAddress = ''; $fromName = ''; if ($user->isLoggedIn()) { // Use real name if set $realName = $user->getRealName(); if ($realName) { $fromName = $realName; } else { $fromName = $user->getName(); } $fromAddress = $user->getEmail(); } $additional = $config['AdditionalFields']; $formItems = [ 'FromName' => [ 'label-message' => 'contactpage-fromname', 'type' => 'text', 'required' => $config['RequireDetails'], 'default' => $fromName, ], 'FromAddress' => [ 'label-message' => 'contactpage-fromaddress', 'type' => 'email', 'required' => $config['RequireDetails'], 'default' => $fromAddress, ], 'Subject' => [ 'label-message' => 'emailsubject', 'type' => 'text', 'required' => $config['RequireDetails'], 'default' => $subject, ], ] + $additional + [ 'CCme' => [ 'label-message' => 'emailccme', 'type' => 'check', 'default' => $this->getUser()->getBoolOption('ccmeonemails'), ], 'FormType' => [ 'class' => 'HTMLHiddenField', 'label' => 'Type', 'default' => $this->formType, ], 'Captcha' => [ 'type' => 'info', 'default' => "
", 'raw' => true, ], ]; $form = HTMLForm::factory( 'ooui', $formItems, $this->getContext(), "contactpage-{$this->formType}" ); $form->setWrapperLegendMsg('contactpage-legend'); $form->setSubmitTextMsg('emailsend'); if ($this->formType != '') { $form->setId("contactpage-{$this->formType}"); $msg = $this->msg("contactpage-legend-{$this->formType}"); if (!$msg->isDisabled()) { $form->setWrapperLegendMsg($msg); } $msg = $this->msg("contactpage-emailsend-{$this->formType}"); if (!$msg->isDisabled()) { $form->setSubmitTextMsg($msg); } } $form->setSubmitCallback([ $this, 'processInput' ]); $form->loadData(); // Stolen from Special:EmailUser if (!Hooks::run('EmailUserForm', [ &$form ])) { return; } $result = $form->show(); if ($result === true || ($result instanceof Status && $result->isGood())) { $out = $this->getOutput(); $pageTitle = $this->msg('emailsent'); $pageText = 'emailsenttext'; if ($this->formType !== '') { $msg = $this->msg("contactpage-emailsent-{$this->formType}"); if (!$msg->isDisabled()) { $pageTitle = $msg; } if (!$this->msg("contactpage-emailsenttext-{$this->formType}")->isDisabled()) { $pageText = "contactpage-emailsenttext-{$this->formType}"; } } $out->setPageTitle($pageTitle); $out->addWikiMsg($pageText); $out->returnToMain(false); } else { if ($config['RLStyleModules']) { $this->getOutput()->addModuleStyles($config['RLStyleModules']); } if ($config['RLModules']) { $this->getOutput()->addModules($config['RLModules']); } $this->getOutput()->prependHTML(trim($formText)); } } /** * @param array $formData * @return bool|string * true: Form won't be displayed * false: Form will be redisplayed * string: Error message to display */ public function processInput($formData) { global $wgRequest; $config = $this->getTypeConfig(); $request = $this->getRequest(); $user = $this->getUser(); // get the sender's real IP if (!is_null($wgRequest->getHeader('CF-Connecting-IP'))) { // if the website is behind cloudflare $senderIP = $wgRequest->getHeader('CF-Connecting-IP'); } elseif (!is_null($wgRequest->getHeader('X-Forwarded-For'))) { // if the website is behind a reverse proxy $senderIP = $wgRequest->getHeader('X-Forwarded-For'); } else { $senderIP = $request->getIP(); } // Setup user that is going to recieve the contact page response $contactRecipientUser = User::newFromName($config['RecipientUser']); $contactRecipientAddress = MailAddress::newFromUser($contactRecipientUser); // Used when user hasn't set an email, or when sending CC email to user $contactSender = new MailAddress( $this->getConfig()->get('PasswordSender'), $config['SenderName'] ); $replyTo = null; $fromAddress = $formData['FromAddress']; $fromName = $formData['FromName']; // verify the user actually entered an email address // the frontend form should verify the email but this is just a backup for spammers if (!filter_var($fromAddress, FILTER_VALIDATE_EMAIL)) { throw new Exception("$fromAddress is not a valid email address."); } $contactSender = new MailAddress( $this->getConfig()->get('PasswordSender'), $config['SenderName'] ); $msgSubject = $formData['Subject']; $subject = "❗❗ New Contact Me Form ❗❗"; $senderAddress = new MailAddress( $this->getConfig()->get('PasswordSender'), $config['SenderName'] ); $replyTo = new MailAddress($fromAddress, $fromName); // email subject line $subject = $this->msg( 'contactpage-subject-and-sender' )->inContentLanguage()->text(); $text = ''; // add main fields $text .= "Email: {$fromAddress}
Name: {$fromName}
IP: {$senderIP}

Subject: {$msgSubject}
"; foreach ($config['AdditionalFields'] as $name => $field) { $class = HTMLForm::getClassFromDescriptor($name, $field); $value = ''; if (isset($field['options-messages'])) { // Multiple values! if (is_string($formData[$name])) { $optionValues = array_flip($field['options-messages']); if (isset($optionValues[$formData[$name]])) { $value = $this->msg($optionValues[$formData[$name]])->inContentLanguage()->text(); } else { $value = $formData[$name]; } } elseif (count($formData[$name])) { $formValues = array_flip($formData[$name]); $value .= "\n"; foreach ($field['options-messages'] as $msg => $optionValue) { $msg = $this->msg($msg)->inContentLanguage()->text(); $optionValue = $this->getYesOrNoMsg(isset($formValues[$optionValue])); $value .= "\t$msg: $optionValue\n"; } } } elseif (isset($field['options'])) { if (is_string($formData[$name])) { $value = $formData[$name]; } elseif (count($formData[$name])) { $formValues = array_flip($formData[$name]); $value .= "\n"; foreach ($field['options'] as $msg => $optionValue) { $optionValue = $this->getYesOrNoMsg(isset($formValues[$optionValue])); $value .= "\t$msg: $optionValue\n"; } } } elseif ($class === 'HTMLCheckField') { $value = $this->getYesOrNoMsg($formData[$name] xor (isset($field['invert']) && $field['invert'])); } elseif (isset($formData[$name])) { // HTMLTextField, HTMLTextAreaField // HTMLFloatField, HTMLIntField // Just dump the value if its wordy $value = $formData[$name]; } else { continue; } if (isset($field['contactpage-email-label'])) { $name = $field['contactpage-email-label']; } elseif (isset($field['label-message'])) { $name = $this->msg($field['label-message'])->inContentLanguage()->text(); } else { $name = $field['label']; } $value = htmlspecialchars(html_entity_decode($value)); // convert html to plain text $text .= "{$name}
{$value}
"; } // Stolen from Special:EmailUser $error = ''; if (!Hooks::run('EmailUser', [ &$contactRecipientAddress, &$senderAddress, &$subject, &$text, &$error ]) ) { return $error; } if (!Hooks::run('ContactForm', [ &$contactRecipientAddress, &$replyTo, &$subject, &$text, $this->formType, $formData ]) ) { return false; // TODO: Need to do some proper error handling here } wfDebug( __METHOD__ . ': sending mail from ' . $senderAddress->toString() . ' to ' . $contactRecipientAddress->toString() . ' replyto ' . ($replyTo == null ? '-/-' : $replyTo->toString()) . "\n" ); // verify captcha $verify = self::verifyCaptcha($request->getVal("g-recaptcha-response")); if (!$verify) { throw new Exception("captcha verification failed"); } $mailResult = UserMailer::send( $contactRecipientAddress, $senderAddress, $subject, $text, ['replyTo' => $replyTo, 'contentType' => 'text/html'] ); if (!$mailResult->isOK()) { wfDebug(__METHOD__ . ': got error from UserMailer: ' . $mailResult->getMessage()->text() . "\n"); return $this->msg('contactpage-usermailererror')->text() . $mailResult->getMessage()->text(); } // if the user requested a copy of this mail, do this now, // unless they are emailing themselves, in which case one copy of the message is sufficient. if ($formData['CCme'] && $fromAddress) { $cc_subject = $this->msg('emailccsubject', $contactRecipientUser->getName(), $subject)->text(); if (Hooks::run( 'ContactForm', [ &$senderAddress, &$contactSender, &$cc_subject, &$text, $this->formType, $formData ] ) ) { wfDebug( __METHOD__ . ': sending cc mail from ' . $contactSender->toString() . ' to ' . $senderAddress->toString() . "\n" ); $ccResult = UserMailer::send($senderAddress, $contactSender, $cc_subject, $text); if (!$ccResult->isOK()) { // At this stage, the user's CC mail has failed, but their // original mail has succeeded. It's unlikely, but still, what to do? // We can either show them an error, or we can say everything was fine, // or we can say we sort of failed AND sort of succeeded. Of these options, // simply saying there was an error is probably best. return $this->msg('contactpage-usermailererror')->text() . $ccResult->getMessage()->text(); } } } Hooks::run('ContactFromComplete', [ $contactRecipientAddress, $replyTo, $subject, $text ]); return true; } /** * @param bool $value * @return string */ private function getYesOrNoMsg($value) { return $this->msg($value ? 'htmlform-yes' : 'htmlform-no')->inContentLanguage()->text(); } private function verifyCaptcha($recaptchaResponse) { global $wgRequest, $wgReCaptchaSecretKey; $x = $wgRequest->getHeader("REMOTE_ADDR"); echo $x; $post_data = http_build_query( array( 'secret' => $wgReCaptchaSecretKey, 'response' => $_POST['g-recaptcha-response'], 'remoteip' => $_SERVER['REMOTE_ADDR'] ) ); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $post_data ) ); $context = stream_context_create($opts); $response = file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, $context); $result = json_decode($response); if (!$result->success) { return false; // throw new Exception('CAPTCHA verification failed.', 1); } else { return true; } } }