summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/ContactPage/includes/SpecialContact.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/ContactPage/includes/SpecialContact.php')
-rw-r--r--www/wiki/extensions/ContactPage/includes/SpecialContact.php508
1 files changed, 508 insertions, 0 deletions
diff --git a/www/wiki/extensions/ContactPage/includes/SpecialContact.php b/www/wiki/extensions/ContactPage/includes/SpecialContact.php
new file mode 100644
index 00000000..d17a3e3e
--- /dev/null
+++ b/www/wiki/extensions/ContactPage/includes/SpecialContact.php
@@ -0,0 +1,508 @@
+<?php
+/**
+ * Speclial:Contact, a contact form for visitors.
+ * Based on SpecialEmailUser.php
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Daniel Kinzler, brightbyte.de
+ * @copyright © 2007-2014 Daniel Kinzler, Sam Reed
+ * @license GPL-2.0-or-later
+ */
+
+/**
+ * Provides the contact form
+ * @ingroup SpecialPage
+ */
+class SpecialContact extends UnlistedSpecialPage {
+
+ /**
+ * Set default value after registration
+ */
+ public static function onRegistration() {
+ global $wgContactConfig, $wgSitename;
+ if ( $wgContactConfig['default']['SenderName'] === null ) {
+ $wgContactConfig['default']['SenderName'] = "Contact Form on $wgSitename";
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public function __construct() {
+ parent::__construct( 'Contact' );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ function getDescription() {
+ return $this->msg( 'contactpage' )->text();
+ }
+
+ /**
+ * @var string
+ */
+ protected $formType;
+
+ /**
+ * @return array
+ */
+ protected function getTypeConfig() {
+ global $wgContactConfig;
+ if ( isset( $wgContactConfig[$this->formType] ) ) {
+ return $wgContactConfig[$this->formType] + $wgContactConfig['default'];
+ }
+ return $wgContactConfig['default'];
+ }
+
+ /**
+ * Main execution function
+ *
+ * @param string|null $par Parameters passed to the page
+ * @throws UserBlockedError
+ * @throws ErrorPageError
+ */
+ public function execute( $par ) {
+ global $wgEnableEmail;
+
+ if ( !$wgEnableEmail ) {
+ // From Special:EmailUser
+ throw new ErrorPageError( 'usermaildisabled', 'usermaildisabledtext' );
+ }
+
+ $request = $this->getRequest();
+ $this->formType = strtolower( $request->getText( 'formtype', $par ) );
+
+ $config = $this->getTypeConfig();
+ if ( !$config['RecipientUser'] ) {
+ $this->getOutput()->showErrorPage( 'contactpage-config-error-title',
+ 'contactpage-config-error' );
+ return;
+ }
+
+ $user = $this->getUser();
+
+ $nu = User::newFromName( $config['RecipientUser'] );
+ if ( is_null( $nu ) || !$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()->mBlock );
+ }
+
+ $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,
+ ],
+ 'FromInfo' => [
+ 'label' => '',
+ 'type' => 'info',
+ 'default' => Html::rawElement( 'small', [],
+ $this->msg( 'contactpage-formfootnotes' )->text()
+ ),
+ 'raw' => true,
+ ],
+ 'Subject' => [
+ 'label-message' => 'emailsubject',
+ 'type' => 'text',
+ 'default' => $subject,
+ ],
+ ] + $additional + [
+ 'CCme' => [
+ 'label-message' => 'emailccme',
+ 'type' => 'check',
+ 'default' => $this->getUser()->getBoolOption( 'ccmeonemails' ),
+ ],
+ 'FormType' => [
+ 'class' => 'HTMLHiddenField',
+ 'label' => 'Type',
+ 'default' => $this->formType,
+ ]
+ ];
+
+ if ( $config['IncludeIP'] && $user->isLoggedIn() ) {
+ $formItems['IncludeIP'] = [
+ 'label-message' => 'contactpage-includeip',
+ 'type' => 'check',
+ ];
+ }
+
+ if ( $this->useCaptcha() ) {
+ $formItems['Captcha'] = [
+ 'label-message' => 'captcha-label',
+ 'type' => 'info',
+ 'default' => $this->getCaptcha(),
+ 'raw' => true,
+ ];
+ }
+
+ $form = HTMLForm::factory( 'ooui',
+ $formItems, $this->getContext(), "contactpage-{$this->formType}"
+ );
+ $form->setWrapperLegendMsg( 'contactpage-legend' );
+ $form->setSubmitTextMsg( 'emailsend' );
+ if ( $this->formType != '' ) {
+ $form->setId( Sanitizer::escapeId( "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 $wgUserEmailUseReplyTo, $wgPasswordSender, $wgCaptcha;
+
+ $config = $this->getTypeConfig();
+
+ $request = $this->getRequest();
+ $user = $this->getUser();
+
+ $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(
+ $config['SenderEmail'] ?: $wgPasswordSender,
+ $config['SenderName']
+ );
+
+ $replyTo = null;
+
+ $fromAddress = $formData['FromAddress'];
+ $fromName = $formData['FromName'];
+ if ( !$fromAddress ) {
+ // No email address entered, so use $contactSender instead
+ $senderAddress = $contactSender;
+ } else {
+ // Use user submitted details
+ $senderAddress = new MailAddress( $fromAddress, $fromName );
+ if ( $wgUserEmailUseReplyTo ) {
+ // Define reply-to address
+ $replyTo = $senderAddress;
+ }
+ }
+
+ $includeIP = isset( $config['IncludeIP'] ) && $config['IncludeIP']
+ && ( $user->isAnon() || $formData['IncludeIP'] );
+ $subject = $formData['Subject'];
+
+ if ( $fromName !== '' ) {
+ if ( $includeIP ) {
+ $subject = $this->msg(
+ 'contactpage-subject-and-sender-withip',
+ $subject,
+ $fromName,
+ $senderIP
+ )->inContentLanguage()->text();
+ } else {
+ $subject = $this->msg(
+ 'contactpage-subject-and-sender',
+ $subject,
+ $fromName
+ )->inContentLanguage()->text();
+ }
+ } elseif ( $fromAddress !== '' ) {
+ if ( $includeIP ) {
+ $subject = $this->msg(
+ 'contactpage-subject-and-sender-withip',
+ $subject,
+ $fromAddress,
+ $senderIP
+ )->inContentLanguage()->text();
+ } else {
+ $subject = $this->msg(
+ 'contactpage-subject-and-sender',
+ $subject,
+ $fromAddress
+ )->inContentLanguage()->text();
+ }
+ } elseif ( $includeIP ) {
+ $subject = $this->msg(
+ 'contactpage-subject-and-sender',
+ $subject,
+ $senderIP
+ )->inContentLanguage()->text();
+ }
+
+ $text = '';
+ foreach ( $config['AdditionalFields'] as $name => $field ) {
+ $class = HTMLForm::getClassFromDescriptor( $name, $field );
+
+ $value = '';
+ // TODO: Support selectandother/HTMLSelectAndOtherField
+ // options, options-messages and options-message
+ 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'];
+ }
+
+ $text .= "{$name}: $value\n";
+ }
+
+ /* @var SimpleCaptcha $wgCaptcha */
+ if ( $this->useCaptcha() && !$wgCaptcha->passCaptchaFromRequest( $request, $user ) ) {
+ return $this->msg( 'contactpage-captcha-error' )->plain();
+ }
+
+ // 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"
+ );
+ $mailResult = UserMailer::send(
+ $contactRecipientAddress,
+ $senderAddress,
+ $subject,
+ $text,
+ [ 'replyTo' => $replyTo ]
+ );
+
+ if ( !$mailResult->isOK() ) {
+ wfDebug( __METHOD__ . ': got error from UserMailer: ' . $mailResult->getMessage() . "\n" );
+ return $this->msg( 'contactpage-usermailererror' )->text() . $mailResult->getMessage();
+ }
+
+ // 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();
+ }
+ }
+ }
+
+ 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();
+ }
+
+ /**
+ * @return boolean True if CAPTCHA should be used, false otherwise
+ */
+ private function useCaptcha() {
+ global $wgCaptchaClass, $wgCaptchaTriggers;
+
+ return $wgCaptchaClass &&
+ isset( $wgCaptchaTriggers['contactpage'] ) &&
+ $wgCaptchaTriggers['contactpage'] &&
+ !$this->getUser()->isAllowed( 'skipcaptcha' );
+ }
+
+ /**
+ * @return string CAPTCHA form HTML
+ */
+ private function getCaptcha() {
+ // NOTE: make sure we have a session. May be required for CAPTCHAs to work.
+ \MediaWiki\Session\SessionManager::getGlobalSession()->persist();
+
+ $captcha = ConfirmEditHooks::getInstance();
+ $captcha->setTrigger( 'contactpage' );
+ $captcha->setAction( 'contact' );
+
+ $formInformation = $captcha->getFormInformation();
+ $formMetainfo = $formInformation;
+ unset( $formMetainfo['html'] );
+ $captcha->addFormInformationToOutput( $this->getOutput(), $formMetainfo );
+
+ return '<div class="captcha">' .
+ $formInformation['html'] .
+ "</div>\n";
+ }
+}