msg( 'contactpage' )->text(); } /** * Main execution function * * @param $par Mixed: Parameters passed to the page * @throws UserBlockedError */ public function execute( $par ) { global $wgEnableEmail, $wgContactUser; if( !$wgEnableEmail || !$wgContactUser ) { $this->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); return; } $request = $this->getRequest(); $user = $this->getUser(); $action = $request->getVal( 'action' ); $nu = User::newFromName( $wgContactUser ); if( is_null( $nu ) || !$nu->canReceiveEmail() ) { wfDebug( "Target is invalid user or can't receive.\n" ); $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 ); } $f = new EmailContactForm( $nu, $par ); if ( 'success' == $action ) { wfDebug( __METHOD__ . ": success.\n" ); $f->showSuccess(); } elseif ( 'submit' == $action && $request->wasPosted() && $f->hasAllInfo() ) { $token = $request->getVal( 'wpEditToken' ); if( $user->isAnon() ) { # Anonymous users may not have a session # open. Check for suffix anyway. $tokenOk = ( EDIT_TOKEN_SUFFIX == $token ); } else { $tokenOk = $user->matchEditToken( $token ); } if ( !$tokenOk ) { wfDebug( __METHOD__ . ": bad token (" . ( $user->isAnon() ? 'anon' : 'user' ) . "): $token\n" ); $this->getOutput()->addWikiMsg( 'sessionfailure' ); $f->showForm(); } elseif ( !$f->passCaptcha() ) { wfDebug( __METHOD__ . ": captcha failed" ); $this->getOutput()->addWikiMsg( 'contactpage-captcha-failed' ); $f->showForm(); } else { wfDebug( __METHOD__ . ": submit\n" ); $f->doSubmit(); } } else { wfDebug( __METHOD__ . ": form\n" ); $f->showForm(); } } } /** * @todo document * @ingroup SpecialPage */ class EmailContactForm { var $target; var $text, $subject; var $cc_me; // Whether user requested to be sent a separate copy of their email. /** * @param User $target * @param $par */ function __construct( $target, $par ) { global $wgRequest, $wgUser; $this->wasPosted = $wgRequest->wasPosted(); $this->formType = $wgRequest->getText( 'formtype', $par ); # Check for type in [[Special:Contact/type]]: change pagetext and prefill form fields if ( $this->formType != '' ) { $message = 'contactpage-pagetext-' . $this->formType; $text = wfMessage( $message )->parseAsBlock(); if ( !wfMessage( $message, $text )->isDisabled() ) { $this->formularText = $text; } else { $this->formularText = wfMessage( 'contactpage-pagetext' )->parseAsBlock(); } $message = 'contactpage-subject-' . $this->formType; $text = wfMessage( $message )->inContentLanguage()->plain(); if ( !wfMessage( $message, $text )->isDisabled() ) { $this->subject = $wgRequest->getText( 'wpSubject', $text ); } else { $this->subject = $wgRequest->getText( 'wpSubject' ); } $message = 'contactpage-text-' . $this->formType; $text = wfMessage( $message )->inContentLanguage()->plain(); if ( !wfMessage( $message, $text )->isDisabled() ) { $this->text = $wgRequest->getText( 'wpText', $text ); } else { $this->text = $wgRequest->getText( 'wpText' ); } } else { $this->formularText = wfMessage( 'contactpage-pagetext' )->parseAsBlock(); $this->text = $wgRequest->getText( 'wpText' ); $this->subject = $wgRequest->getText( 'wpSubject' ); } $this->target = $target; $this->cc_me = $wgRequest->getBool( 'wpCCMe' ); $this->includeIP = $wgRequest->getBool( 'wpIncludeIP' ); $this->fromname = $wgRequest->getText( 'wpFromName' ); $this->fromaddress = $wgRequest->getText( 'wpFromAddress' ); if( $wgUser->isLoggedIn() ) { if( !$this->fromname ) { $this->fromname = $wgUser->getName(); } if( !$this->fromaddress ) { $this->fromaddress = $wgUser->getEmail(); } } // prepare captcha if applicable if ( $this->useCaptcha() ) { $captcha = ConfirmEditHooks::getInstance(); $captcha->trigger = 'contactpage'; $captcha->action = 'contact'; } } function hasAllInfo() { global $wgContactRequireAll; if ( $this->text === null ) { return false; } else { $this->text = trim( $this->text ); } if ( $this->text === '' ) { return false; } if ( $wgContactRequireAll ) { if ( $this->fromname === null ) { return false; } else { $this->fromname = trim( $this->fromname ); } if ( $this->fromname === '' ) { return false; } if ( $this->fromaddress === null ) { return false; } else { $this->fromaddress = trim( $this->fromaddress ); } if ( $this->fromaddress === '' ) { return false; } } return true; } function showForm() { global $wgOut, $wgUser, $wgContactRequireAll, $wgContactIncludeIP; # @todo Show captcha $wgOut->setPageTitle( wfMessage( 'contactpage-title' ) ); $wgOut->addHTML( $this->formularText ); if ( $this->subject === '' ) { $this->subject = wfMessage( 'contactpage-defsubject' )->inContentLanguage()->text(); } $msgSuffix = $wgContactRequireAll ? '-required' : ''; $titleObj = SpecialPage::getTitleFor( 'Contact' ); $action = $titleObj->getLocalURL( 'action=submit' ); $token = $wgUser->isAnon() ? EDIT_TOKEN_SUFFIX : $wgUser->getEditToken(); //this kind of sucks, really... $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'emailuser' ) ) . Xml::openElement( 'fieldset' ) . Xml::element( 'legend', null, wfMessage( 'contactpage-legend' )->text() ) . Xml::openElement( 'table', array( 'id' => 'mailheader' ) ) . ' ' . Xml::label( wfMessage( 'emailsubject' )->text(), 'wpSubject' ) . ' ' . Xml::input( 'wpSubject', 60, $this->subject, array( 'type' => 'text', 'maxlength' => 200 ) ) . ' ' . Xml::label( wfMessage( "contactpage-fromname$msgSuffix" )->text(), 'wpFromName' ) . ' ' . Xml::input( 'wpFromName', 60, $this->fromname, array( 'type' => 'text', 'maxlength' => 200 ) ) . ' ' . Xml::label( wfMessage( "contactpage-fromaddress$msgSuffix" )->text(), 'wpFromAddress' ) . ' ' . Xml::input( 'wpFromAddress', 60, $this->fromaddress, array( 'type' => 'text', 'maxlength' => 200 ) ) . ' '; // Allow other extensions to add more fields into Special:Contact wfRunHooks( 'ContactFormBeforeMessage', array( $this, &$form ) ); // @todo FIXME: Unescaped text is inserted into HTML here. $form .= ' ' . wfMessage( "contactpage-formfootnotes$msgSuffix" )->text() . ' ' . Xml::label( wfMessage( 'emailmessage' )->text(), 'wpText' ) . ' ' . Xml::textarea( 'wpText', $this->text, 80, 20, array( 'id' => 'wpText' ) ) . ' '; if ( $wgContactIncludeIP && $wgUser->isLoggedIn() ) { $form .= ' ' . Xml::checkLabel( wfMessage( 'contactpage-includeip' )->text(), 'wpIncludeIP', 'wpIncludeIP', false ) . ' '; } $ccme = $this->wasPosted ? $this->cc_me : $wgUser->getBoolOption( 'ccmeonemails' ); $form .= ' ' . Xml::checkLabel( wfMessage( 'emailccme' )->text(), 'wpCCMe', 'wpCCMe', $ccme ) . '
' . $this->getCaptcha() . ' ' . Xml::submitButton( wfMessage( 'emailsend' )->text(), array( 'name' => 'wpSend', 'accesskey' => 's' ) ) . ' ' . Html::hidden( 'wpEditToken', $token ) . Html::hidden( 'formtype', $this->formType ) . Xml::closeElement( 'table' ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); $wgOut->addHTML( $form ); } function useCaptcha() { global $wgCaptchaClass, $wgCaptchaTriggers, $wgUser; if ( !$wgCaptchaClass ) { return false; // no captcha installed } if ( !@$wgCaptchaTriggers['contactpage'] ) { return false; // don't trigger on contact form } if( $wgUser->isAllowed( 'skipcaptcha' ) ) { wfDebug( "EmailContactForm::useCaptcha: user group allows skipping captcha\n" ); return false; } return true; } function getCaptcha() { global $wgCaptcha; if ( !$this->useCaptcha() ) { return ''; } wfSetupSession(); #NOTE: make sure we have a session. May be required for captchas to work. return '
' . $wgCaptcha->getForm() . wfMessage( 'contactpage-captcha' )->parse() . "
\n"; } function passCaptcha() { global $wgCaptcha; if ( !$this->useCaptcha() ) { return true; } return $wgCaptcha->passCaptcha(); } function doSubmit() { global $wgOut, $wgUser, $wgRequest; global $wgUserEmailUseReplyTo, $wgPasswordSender; global $wgContactSender, $wgContactSenderName, $wgContactIncludeIP; $csender = $wgContactSender ? $wgContactSender : $wgPasswordSender; $cname = $wgContactSenderName; $senderIP = $wgRequest->getIP(); wfDebug( __METHOD__ . ": start\n" ); $targetAddress = new MailAddress( $this->target ); $replyto = null; $contactSender = new MailAddress( $csender, $cname ); if ( !$this->fromaddress ) { $submitterAddress = $contactSender; } else { $submitterAddress = new MailAddress( $this->fromaddress, $this->fromname ); if ( $wgUserEmailUseReplyTo ) { $replyto = $submitterAddress; } } $subject = trim( $this->subject ); if ( $subject === '' ) { $subject = wfMessage( 'contactpage-defsubject' )->inContentLanguage()->text(); } $includeIP = $wgContactIncludeIP && ( $this->includeIP || $wgUser->isAnon() ); if ( $this->fromname !== '' ) { if ( $includeIP ) { $subject = wfMessage( 'contactpage-subject-and-sender-withip', $subject, $this->fromname, $senderIP )->inContentLanguage()->text(); } else { $subject = wfMessage( 'contactpage-subject-and-sender', $subject, $this->fromname )->inContentLanguage()->text(); } } elseif ( $this->fromaddress !== '' ) { if ( $includeIP ) { $subject = wfMessage( 'contactpage-subject-and-sender-withip', $subject, $this->fromaddress, $senderIP )->inContentLanguage()->text(); } else { $subject = wfMessage( 'contactpage-subject-and-sender', $subject, $this->fromaddress )->inContentLanguage()->text(); } } elseif ( $includeIP ) { $subject = wfMessage( 'contactpage-subject-and-sender', $subject, $senderIP )->inContentLanguage()->text(); } if( !wfRunHooks( 'ContactForm', array( &$targetAddress, &$replyto, &$subject, &$this->text, $this->formType ) ) ) { wfDebug( __METHOD__ . ": aborted by hook\n" ); return; } wfDebug( __METHOD__ . ": sending mail from " . $submitterAddress->toString() . " to " . $targetAddress->toString(). " replyto " . ( $replyto == null ? '-/-' : $replyto->toString() ) . "\n" ); $mailResult = UserMailer::send( $targetAddress, $submitterAddress, $subject, $this->text, $replyto ); if( !$mailResult->isOK() ) { $wgOut->addWikiMsg( 'usermailererror' ) . $mailResult->getMessage(); wfDebug( __METHOD__ . ": got error from UserMailer: " . $mailResult->getMessage() . "\n" ); return; } // 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( $this->cc_me && $this->fromaddress ) { $cc_subject = wfMessage( 'emailccsubject', $this->target->getName(), $subject )->text(); if( wfRunHooks( 'ContactForm', array( &$submitterAddress, &$contactSender, &$cc_subject, &$this->text, $this->formType ) ) ) { wfDebug( __METHOD__ . ": sending cc mail from " . $contactSender->toString() . " to " . $submitterAddress->toString() . "\n" ); $ccResult = UserMailer::send( $submitterAddress, $contactSender, $cc_subject, $this->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. $wgOut->addWikiText( wfMessage( 'usermailererror' )->text() . $ccResult ); return; } } } wfDebug( __METHOD__ . ": success\n" ); $titleObj = SpecialPage::getTitleFor( 'Contact' ); $wgOut->redirect( $titleObj->getFullURL( 'action=success' ) ); wfRunHooks( 'ContactFromComplete', array( $targetAddress, $replyto, $subject, $this->text ) ); wfDebug( __METHOD__ . ": end\n" ); } function showSuccess() { global $wgOut; $wgOut->setPageTitle( wfMessage( 'emailsent' ) ); $wgOut->addWikiMsg( 'emailsenttext' ); $wgOut->returnToMain( false ); } }