MediaWiki  1.23.14
SpecialUserlogin.php
Go to the documentation of this file.
1 <?php
29 class LoginForm extends SpecialPage {
30  const SUCCESS = 0;
31  const NO_NAME = 1;
32  const ILLEGAL = 2;
33  const WRONG_PLUGIN_PASS = 3;
34  const NOT_EXISTS = 4;
35  const WRONG_PASS = 5;
36  const EMPTY_PASS = 6;
37  const RESET_PASS = 7;
38  const ABORTED = 8;
39  const CREATE_BLOCKED = 9;
40  const THROTTLED = 10;
41  const USER_BLOCKED = 11;
42  const NEED_TOKEN = 12;
43  const WRONG_TOKEN = 13;
44 
45  public $mAbortLoginErrorMsg = null;
46 
47  protected $mUsername;
48  protected $mPassword;
49  protected $mRetype;
50  protected $mReturnTo;
51  protected $mCookieCheck;
52  protected $mPosted;
53  protected $mAction;
54  protected $mCreateaccount;
56  protected $mLoginattempt;
57  protected $mRemember;
58  protected $mEmail;
59  protected $mDomain;
60  protected $mLanguage;
61  protected $mSkipCookieCheck;
62  protected $mReturnToQuery;
63  protected $mToken;
64  protected $mStickHTTPS;
65  protected $mType;
66  protected $mReason;
67  protected $mRealName;
68 
70  private $mLoaded = false;
72 
74  private $mOverrideRequest = null;
75 
77  private $mRequest = null;
78 
82  public function __construct( $request = null ) {
83  parent::__construct( 'Userlogin' );
84 
85  $this->mOverrideRequest = $request;
86  }
87 
91  function load() {
92  global $wgAuth, $wgHiddenPrefs, $wgEnableEmail;
93 
94  if ( $this->mLoaded ) {
95  return;
96  }
97  $this->mLoaded = true;
98 
99  if ( $this->mOverrideRequest === null ) {
100  $request = $this->getRequest();
101  } else {
103  }
104  $this->mRequest = $request;
105 
106  $this->mType = $request->getText( 'type' );
107  $this->mUsername = $request->getText( 'wpName' );
108  $this->mPassword = $request->getText( 'wpPassword' );
109  $this->mRetype = $request->getText( 'wpRetype' );
110  $this->mDomain = $request->getText( 'wpDomain' );
111  $this->mReason = $request->getText( 'wpReason' );
112  $this->mCookieCheck = $request->getVal( 'wpCookieCheck' );
113  $this->mPosted = $request->wasPosted();
114  $this->mCreateaccountMail = $request->getCheck( 'wpCreateaccountMail' )
115  && $wgEnableEmail;
116  $this->mCreateaccount = $request->getCheck( 'wpCreateaccount' ) && !$this->mCreateaccountMail;
117  $this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
118  $this->mAction = $request->getVal( 'action' );
119  $this->mRemember = $request->getCheck( 'wpRemember' );
120  $this->mFromHTTP = $request->getBool( 'fromhttp', false );
121  $this->mStickHTTPS = ( !$this->mFromHTTP && $request->getProtocol() === 'https' )
122  || $request->getBool( 'wpForceHttps', false );
123  $this->mLanguage = $request->getText( 'uselang' );
124  $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' );
125  $this->mToken = $this->mType == 'signup'
126  ? $request->getVal( 'wpCreateaccountToken' )
127  : $request->getVal( 'wpLoginToken' );
128  $this->mReturnTo = $request->getVal( 'returnto', '' );
129  $this->mReturnToQuery = $request->getVal( 'returntoquery', '' );
130 
131  if ( $wgEnableEmail ) {
132  $this->mEmail = $request->getText( 'wpEmail' );
133  } else {
134  $this->mEmail = '';
135  }
136  if ( !in_array( 'realname', $wgHiddenPrefs ) ) {
137  $this->mRealName = $request->getText( 'wpRealName' );
138  } else {
139  $this->mRealName = '';
140  }
141 
142  if ( !$wgAuth->validDomain( $this->mDomain ) ) {
143  $this->mDomain = $wgAuth->getDomain();
144  }
145  $wgAuth->setDomain( $this->mDomain );
146 
147  # 1. When switching accounts, it sucks to get automatically logged out
148  # 2. Do not return to PasswordReset after a successful password change
149  # but goto Wiki start page (Main_Page) instead ( bug 33997 )
150  $returnToTitle = Title::newFromText( $this->mReturnTo );
151  if ( is_object( $returnToTitle )
152  && ( $returnToTitle->isSpecial( 'Userlogout' )
153  || $returnToTitle->isSpecial( 'PasswordReset' ) )
154  ) {
155  $this->mReturnTo = '';
156  $this->mReturnToQuery = '';
157  }
158  }
159 
160  function getDescription() {
161  if ( $this->mType === 'signup' ) {
162  return $this->msg( 'createaccount' )->text();
163  } else {
164  return $this->msg( 'login' )->text();
165  }
166  }
167 
168  /*
169  * @param $subPage string|null
170  */
171  public function execute( $subPage ) {
172  if ( session_id() == '' ) {
173  wfSetupSession();
174  }
175 
176  $this->load();
177 
178  // Check for [[Special:Userlogin/signup]]. This affects form display and
179  // page title.
180  if ( $subPage == 'signup' ) {
181  $this->mType = 'signup';
182  }
183  $this->setHeaders();
184 
185  // If logging in and not on HTTPS, either redirect to it or offer a link.
186  global $wgSecureLogin;
187  if ( $this->mRequest->getProtocol() !== 'https' ) {
188  $title = $this->getFullTitle();
189  $query = array(
190  'returnto' => $this->mReturnTo !== '' ? $this->mReturnTo : null,
191  'returntoquery' => $this->mReturnToQuery !== '' ?
192  $this->mReturnToQuery : null,
193  'title' => null,
194  ) + $this->mRequest->getQueryValues();
195  $url = $title->getFullURL( $query, false, PROTO_HTTPS );
196  if ( $wgSecureLogin && wfCanIPUseHTTPS( $this->getRequest()->getIP() ) ) {
197  $url = wfAppendQuery( $url, 'fromhttp=1' );
198  $this->getOutput()->redirect( $url );
199  // Since we only do this redir to change proto, always vary
200  $this->getOutput()->addVaryHeader( 'X-Forwarded-Proto' );
201 
202  return;
203  } else {
204  // A wiki without HTTPS login support should set $wgServer to
205  // http://somehost, in which case the secure URL generated
206  // above won't actually start with https://
207  if ( substr( $url, 0, 8 ) === 'https://' ) {
208  $this->mSecureLoginUrl = $url;
209  }
210  }
211  }
212 
213  if ( !is_null( $this->mCookieCheck ) ) {
214  $this->onCookieRedirectCheck( $this->mCookieCheck );
215 
216  return;
217  } elseif ( $this->mPosted ) {
218  if ( $this->mCreateaccount ) {
219  $this->addNewAccount();
220 
221  return;
222  } elseif ( $this->mCreateaccountMail ) {
223  $this->addNewAccountMailPassword();
224 
225  return;
226  } elseif ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
227  $this->processLogin();
228 
229  return;
230  }
231  }
232  $this->mainLoginForm( '' );
233  }
234 
238  function addNewAccountMailPassword() {
239  if ( $this->mEmail == '' ) {
240  $this->mainLoginForm( $this->msg( 'noemailcreate' )->escaped() );
241 
242  return;
243  }
244 
245  $status = $this->addNewAccountInternal();
246  if ( !$status->isGood() ) {
247  $error = $status->getMessage();
248  $this->mainLoginForm( $error->toString() );
249 
250  return;
251  }
252 
253  $u = $status->getValue();
254 
255  // Wipe the initial password and mail a temporary one
256  $u->setPassword( null );
257  $u->saveSettings();
258  $result = $this->mailPasswordInternal( $u, false, 'createaccount-title', 'createaccount-text' );
259 
260  wfRunHooks( 'AddNewAccount', array( $u, true ) );
261  $u->addNewUserLogEntry( 'byemail', $this->mReason );
262 
263  $out = $this->getOutput();
264  $out->setPageTitle( $this->msg( 'accmailtitle' ) );
265 
266  if ( !$result->isGood() ) {
267  $this->mainLoginForm( $this->msg( 'mailerror', $result->getWikiText() )->text() );
268  } else {
269  $out->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() );
270  $this->executeReturnTo( 'success' );
271  }
272  }
273 
278  function addNewAccount() {
279  global $wgContLang, $wgUser, $wgEmailAuthentication, $wgLoginLanguageSelector;
280 
281  # Create the account and abort if there's a problem doing so
282  $status = $this->addNewAccountInternal();
283  if ( !$status->isGood() ) {
284  $error = $status->getMessage();
285  $this->mainLoginForm( $error->toString() );
286 
287  return false;
288  }
289 
290  $u = $status->getValue();
291 
292  # Only save preferences if the user is not creating an account for someone else.
293  if ( $this->getUser()->isAnon() ) {
294  # If we showed up language selection links, and one was in use, be
295  # smart (and sensible) and save that language as the user's preference
296  if ( $wgLoginLanguageSelector && $this->mLanguage ) {
297  $u->setOption( 'language', $this->mLanguage );
298  } else {
299 
300  # Otherwise the user's language preference defaults to $wgContLang,
301  # but it may be better to set it to their preferred $wgContLang variant,
302  # based on browser preferences or URL parameters.
303  $u->setOption( 'language', $wgContLang->getPreferredVariant() );
304  }
305  if ( $wgContLang->hasVariants() ) {
306  $u->setOption( 'variant', $wgContLang->getPreferredVariant() );
307  }
308  }
309 
310  $out = $this->getOutput();
311 
312  # Send out an email authentication message if needed
313  if ( $wgEmailAuthentication && Sanitizer::validateEmail( $u->getEmail() ) ) {
314  $status = $u->sendConfirmationMail();
315  if ( $status->isGood() ) {
316  $out->addWikiMsg( 'confirmemail_oncreate' );
317  } else {
318  $out->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) );
319  }
320  }
321 
322  # Save settings (including confirmation token)
323  $u->saveSettings();
324 
325  # If not logged in, assume the new account as the current one and set
326  # session cookies then show a "welcome" message or a "need cookies"
327  # message as needed
328  if ( $this->getUser()->isAnon() ) {
329  $u->setCookies();
330  $wgUser = $u;
331  // This should set it for OutputPage and the Skin
332  // which is needed or the personal links will be
333  // wrong.
334  $this->getContext()->setUser( $u );
335  wfRunHooks( 'AddNewAccount', array( $u, false ) );
336  $u->addNewUserLogEntry( 'create' );
337  if ( $this->hasSessionCookie() ) {
338  $this->successfulCreation();
339  } else {
340  $this->cookieRedirectCheck( 'new' );
341  }
342  } else {
343  # Confirm that the account was created
344  $out->setPageTitle( $this->msg( 'accountcreated' ) );
345  $out->addWikiMsg( 'accountcreatedtext', $u->getName() );
346  $out->addReturnTo( $this->getPageTitle() );
347  wfRunHooks( 'AddNewAccount', array( $u, false ) );
348  $u->addNewUserLogEntry( 'create2', $this->mReason );
349  }
350 
351  return true;
352  }
353 
360  public function addNewAccountInternal() {
361  global $wgAuth, $wgMemc, $wgAccountCreationThrottle,
362  $wgMinimalPasswordLength, $wgEmailConfirmToEdit;
363 
364  // If the user passes an invalid domain, something is fishy
365  if ( !$wgAuth->validDomain( $this->mDomain ) ) {
366  return Status::newFatal( 'wrongpassword' );
367  }
368 
369  // If we are not allowing users to login locally, we should be checking
370  // to see if the user is actually able to authenticate to the authenti-
371  // cation server before they create an account (otherwise, they can
372  // create a local account and login as any domain user). We only need
373  // to check this for domains that aren't local.
374  if ( 'local' != $this->mDomain && $this->mDomain != '' ) {
375  if (
376  !$wgAuth->canCreateAccounts() &&
377  (
378  !$wgAuth->userExists( $this->mUsername ) ||
379  !$wgAuth->authenticate( $this->mUsername, $this->mPassword )
380  )
381  ) {
382  return Status::newFatal( 'wrongpassword' );
383  }
384  }
385 
386  if ( wfReadOnly() ) {
387  throw new ReadOnlyError;
388  }
389 
390  # Request forgery checks.
391  if ( !self::getCreateaccountToken() ) {
393 
394  return Status::newFatal( 'nocookiesfornew' );
395  }
396 
397  # The user didn't pass a createaccount token
398  if ( !$this->mToken ) {
399  return Status::newFatal( 'sessionfailure' );
400  }
401 
402  # Validate the createaccount token
403  if ( $this->mToken !== self::getCreateaccountToken() ) {
404  return Status::newFatal( 'sessionfailure' );
405  }
406 
407  # Check permissions
408  $currentUser = $this->getUser();
409  $creationBlock = $currentUser->isBlockedFromCreateAccount();
410  if ( !$currentUser->isAllowed( 'createaccount' ) ) {
411  throw new PermissionsError( 'createaccount' );
412  } elseif ( $creationBlock instanceof Block ) {
413  // Throws an ErrorPageError.
414  $this->userBlockedMessage( $creationBlock );
415 
416  // This should never be reached.
417  return false;
418  }
419 
420  # Include checks that will include GlobalBlocking (Bug 38333)
421  $permErrors = $this->getPageTitle()->getUserPermissionsErrors(
422  'createaccount',
423  $currentUser,
424  true
425  );
426 
427  if ( count( $permErrors ) ) {
428  throw new PermissionsError( 'createaccount', $permErrors );
429  }
430 
431  $ip = $this->getRequest()->getIP();
432  if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) {
433  return Status::newFatal( 'sorbs_create_account_reason' );
434  }
435 
436  // Normalize the name so that silly things don't cause "invalid username"
437  // errors. User::newFromName does some rather strict checking, rejecting
438  // e.g. leading/trailing/multiple spaces.
439  $title = Title::makeTitleSafe( NS_USER, $this->mUsername );
440  if ( !is_object( $title ) ) {
441  return Status::newFatal( 'noname' );
442  }
443 
444  # Now create a dummy user ($u) and check if it is valid
445  $u = User::newFromName( $title->getText(), 'creatable' );
446  if ( !is_object( $u ) ) {
447  return Status::newFatal( 'noname' );
448  } elseif ( 0 != $u->idForName() ) {
449  return Status::newFatal( 'userexists' );
450  }
451 
452  if ( $this->mCreateaccountMail ) {
453  # do not force a password for account creation by email
454  # set invalid password, it will be replaced later by a random generated password
455  $this->mPassword = null;
456  } else {
457  if ( $this->mPassword !== $this->mRetype ) {
458  return Status::newFatal( 'badretype' );
459  }
460 
461  # check for minimal password length
462  $valid = $u->getPasswordValidity( $this->mPassword );
463  if ( $valid !== true ) {
464  if ( !is_array( $valid ) ) {
465  $valid = array( $valid, $wgMinimalPasswordLength );
466  }
467 
468  return call_user_func_array( 'Status::newFatal', $valid );
469  }
470  }
471 
472  # if you need a confirmed email address to edit, then obviously you
473  # need an email address.
474  if ( $wgEmailConfirmToEdit && strval( $this->mEmail ) === '' ) {
475  return Status::newFatal( 'noemailtitle' );
476  }
477 
478  if ( strval( $this->mEmail ) !== '' && !Sanitizer::validateEmail( $this->mEmail ) ) {
479  return Status::newFatal( 'invalidemailaddress' );
480  }
481 
482  # Set some additional data so the AbortNewAccount hook can be used for
483  # more than just username validation
484  $u->setEmail( $this->mEmail );
485  $u->setRealName( $this->mRealName );
486 
487  $abortError = '';
488  $abortStatus = null;
489  if ( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError, &$abortStatus ) ) ) {
490  // Hook point to add extra creation throttles and blocks
491  wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
492  if ( $abortStatus === null ) {
493  // Report back the old string as a raw message status.
494  // This will report the error back as 'createaccount-hook-aborted'
495  // with the given string as the message.
496  // To return a different error code, return a Status object.
497  $abortError = new Message( 'createaccount-hook-aborted', array( $abortError ) );
498  $abortError->text();
499 
500  return Status::newFatal( $abortError );
501  } else {
502  // For MediaWiki 1.23+ and updated hooks, return the Status object
503  // returned from the hook.
504  return $abortStatus;
505  }
506  }
507 
508  // Hook point to check for exempt from account creation throttle
509  if ( !wfRunHooks( 'ExemptFromAccountCreationThrottle', array( $ip ) ) ) {
510  wfDebug( "LoginForm::exemptFromAccountCreationThrottle: a hook " .
511  "allowed account creation w/o throttle\n" );
512  } else {
513  if ( ( $wgAccountCreationThrottle && $currentUser->isPingLimitable() ) ) {
514  $key = 'global:acctcreate:ip:' . $ip;
515  $value = $wgMemc->get( $key );
516  if ( !$value ) {
517  $wgMemc->set( $key, 0, 86400 );
518  }
519  if ( $value >= $wgAccountCreationThrottle ) {
520  return Status::newFatal( 'acct_creation_throttle_hit', $wgAccountCreationThrottle );
521  }
522  $wgMemc->incr( $key );
523  }
524  }
525 
526  if ( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) {
527  return Status::newFatal( 'externaldberror' );
528  }
529 
531 
532  return $this->initUser( $u, false );
533  }
534 
544  function initUser( $u, $autocreate ) {
545  global $wgAuth;
546 
547  $status = $u->addToDatabase();
548  if ( !$status->isOK() ) {
549  return $status;
550  }
551 
552  if ( $wgAuth->allowPasswordChange() ) {
553  $u->setPassword( $this->mPassword );
554  }
555 
556  $u->setEmail( $this->mEmail );
557  $u->setRealName( $this->mRealName );
558  $u->setToken();
559 
560  $wgAuth->initUser( $u, $autocreate );
561 
562  $u->saveSettings();
563 
564  // Update user count
565  DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
566 
567  // Watch user's userpage and talk page
568  $u->addWatch( $u->getUserPage(), WatchedItem::IGNORE_USER_RIGHTS );
569 
570  return Status::newGood( $u );
571  }
572 
581  public function authenticateUserData() {
582  global $wgUser, $wgAuth;
583 
584  $this->load();
585 
586  if ( $this->mUsername == '' ) {
587  return self::NO_NAME;
588  }
589 
590  // We require a login token to prevent login CSRF
591  // Handle part of this before incrementing the throttle so
592  // token-less login attempts don't count towards the throttle
593  // but wrong-token attempts do.
594 
595  // If the user doesn't have a login token yet, set one.
596  if ( !self::getLoginToken() ) {
598 
599  return self::NEED_TOKEN;
600  }
601  // If the user didn't pass a login token, tell them we need one
602  if ( !$this->mToken ) {
603  return self::NEED_TOKEN;
604  }
605 
606  $throttleCount = self::incLoginThrottle( $this->mUsername );
607  if ( $throttleCount === true ) {
608  return self::THROTTLED;
609  }
610 
611  // Validate the login token
612  if ( $this->mToken !== self::getLoginToken() ) {
613  return self::WRONG_TOKEN;
614  }
615 
616  // Load the current user now, and check to see if we're logging in as
617  // the same name. This is necessary because loading the current user
618  // (say by calling getName()) calls the UserLoadFromSession hook, which
619  // potentially creates the user in the database. Until we load $wgUser,
620  // checking for user existence using User::newFromName($name)->getId() below
621  // will effectively be using stale data.
622  if ( $this->getUser()->getName() === $this->mUsername ) {
623  wfDebug( __METHOD__ . ": already logged in as {$this->mUsername}\n" );
624 
625  return self::SUCCESS;
626  }
627 
628  $u = User::newFromName( $this->mUsername );
629  if ( !( $u instanceof User ) || !User::isUsableName( $u->getName() ) ) {
630  return self::ILLEGAL;
631  }
632 
633  $isAutoCreated = false;
634  if ( $u->getID() == 0 ) {
635  $status = $this->attemptAutoCreate( $u );
636  if ( $status !== self::SUCCESS ) {
637  return $status;
638  } else {
639  $isAutoCreated = true;
640  }
641  } else {
642  $u->load();
643  }
644 
645  // Give general extensions, such as a captcha, a chance to abort logins
646  $abort = self::ABORTED;
647  $msg = null;
648  if ( !wfRunHooks( 'AbortLogin', array( $u, $this->mPassword, &$abort, &$msg ) ) ) {
649  $this->mAbortLoginErrorMsg = $msg;
650 
651  return $abort;
652  }
653 
654  global $wgBlockDisablesLogin;
655  if ( !$u->checkPassword( $this->mPassword ) ) {
656  if ( $u->checkTemporaryPassword( $this->mPassword ) ) {
657  // The e-mailed temporary password should not be used for actu-
658  // al logins; that's a very sloppy habit, and insecure if an
659  // attacker has a few seconds to click "search" on someone's o-
660  // pen mail reader.
661  //
662  // Allow it to be used only to reset the password a single time
663  // to a new value, which won't be in the user's e-mail ar-
664  // chives.
665  //
666  // For backwards compatibility, we'll still recognize it at the
667  // login form to minimize surprises for people who have been
668  // logging in with a temporary password for some time.
669  //
670  // As a side-effect, we can authenticate the user's e-mail ad-
671  // dress if it's not already done, since the temporary password
672  // was sent via e-mail.
673  if ( !$u->isEmailConfirmed() ) {
674  $u->confirmEmail();
675  $u->saveSettings();
676  }
677 
678  // At this point we just return an appropriate code/ indicating
679  // that the UI should show a password reset form; bot inter-
680  // faces etc will probably just fail cleanly here.
681  $this->mAbortLoginErrorMsg = 'resetpass-temp-emailed';
682  $this->mTempPasswordUsed = true;
684  } else {
685  $retval = ( $this->mPassword == '' ) ? self::EMPTY_PASS : self::WRONG_PASS;
686  }
687  } elseif ( $wgBlockDisablesLogin && $u->isBlocked() ) {
688  // If we've enabled it, make it so that a blocked user cannot login
690  } elseif ( $u->getPasswordExpired() == 'hard' ) {
691  // Force reset now, without logging in
693  $this->mAbortLoginErrorMsg = 'resetpass-expired';
694  } else {
695  $wgAuth->updateUser( $u );
696  $wgUser = $u;
697  // This should set it for OutputPage and the Skin
698  // which is needed or the personal links will be
699  // wrong.
700  $this->getContext()->setUser( $u );
701 
702  // Please reset throttle for successful logins, thanks!
703  if ( $throttleCount ) {
704  self::clearLoginThrottle( $this->mUsername );
705  }
706 
707  if ( $isAutoCreated ) {
708  // Must be run after $wgUser is set, for correct new user log
709  wfRunHooks( 'AuthPluginAutoCreate', array( $u ) );
710  }
711 
713  }
714  wfRunHooks( 'LoginAuthenticateAudit', array( $u, $this->mPassword, $retval ) );
715 
716  return $retval;
717  }
718 
725  public static function incLoginThrottle( $username ) {
726  global $wgPasswordAttemptThrottle, $wgMemc, $wgRequest;
727  $canUsername = User::getCanonicalName( $username, 'usable' );
728  $username = $canUsername !== false ? $canUsername : $username;
729 
730  $throttleCount = 0;
731  if ( is_array( $wgPasswordAttemptThrottle ) ) {
732  $throttleKey = 'global:password-throttle:' . $wgRequest->getIP() . ':' . md5( $username );
733  $count = $wgPasswordAttemptThrottle['count'];
734  $period = $wgPasswordAttemptThrottle['seconds'];
735 
736  $throttleCount = $wgMemc->get( $throttleKey );
737  if ( !$throttleCount ) {
738  $wgMemc->add( $throttleKey, 1, $period ); // start counter
739  } elseif ( $throttleCount < $count ) {
740  $wgMemc->incr( $throttleKey );
741  } elseif ( $throttleCount >= $count ) {
742  return true;
743  }
744  }
745 
746  return $throttleCount;
747  }
748 
754  public static function clearLoginThrottle( $username ) {
755  global $wgMemc, $wgRequest;
756  $canUsername = User::getCanonicalName( $username, 'usable' );
757  $username = $canUsername !== false ? $canUsername : $username;
758 
759  $throttleKey = 'global:password-throttle:' . $wgRequest->getIP() . ':' . md5( $username );
760  $wgMemc->delete( $throttleKey );
761  }
762 
771  function attemptAutoCreate( $user ) {
772  global $wgAuth;
773 
774  if ( $this->getUser()->isBlockedFromCreateAccount() ) {
775  wfDebug( __METHOD__ . ": user is blocked from account creation\n" );
776 
777  return self::CREATE_BLOCKED;
778  }
779 
780  if ( !$wgAuth->autoCreate() ) {
781  return self::NOT_EXISTS;
782  }
783 
784  if ( !$wgAuth->userExists( $user->getName() ) ) {
785  wfDebug( __METHOD__ . ": user does not exist\n" );
786 
787  return self::NOT_EXISTS;
788  }
789 
790  if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) {
791  wfDebug( __METHOD__ . ": \$wgAuth->authenticate() returned false, aborting\n" );
792 
794  }
795 
796  $abortError = '';
797  if ( !wfRunHooks( 'AbortAutoAccount', array( $user, &$abortError ) ) ) {
798  // Hook point to add extra creation throttles and blocks
799  wfDebug( "LoginForm::attemptAutoCreate: a hook blocked creation: $abortError\n" );
800  $this->mAbortLoginErrorMsg = $abortError;
801 
802  return self::ABORTED;
803  }
804 
805  wfDebug( __METHOD__ . ": creating account\n" );
806  $status = $this->initUser( $user, true );
807 
808  if ( !$status->isOK() ) {
809  $errors = $status->getErrorsByType( 'error' );
810  $this->mAbortLoginErrorMsg = $errors[0]['message'];
811 
812  return self::ABORTED;
813  }
814 
815  return self::SUCCESS;
816  }
817 
818  function processLogin() {
819  global $wgMemc, $wgLang, $wgSecureLogin, $wgPasswordAttemptThrottle,
820  $wgInvalidPasswordReset;
821 
822  switch ( $this->authenticateUserData() ) {
823  case self::SUCCESS:
824  # We've verified now, update the real record
825  $user = $this->getUser();
826  $user->invalidateCache();
827 
828  if ( $user->requiresHTTPS() ) {
829  $this->mStickHTTPS = true;
830  }
831 
832  if ( $wgSecureLogin && !$this->mStickHTTPS ) {
833  $user->setCookies( $this->mRequest, false, $this->mRemember );
834  } else {
835  $user->setCookies( $this->mRequest, null, $this->mRemember );
836  }
838 
839  // Reset the throttle
840  $request = $this->getRequest();
841  $key = wfMemcKey( 'password-throttle', $request->getIP(), md5( $this->mUsername ) );
842  $wgMemc->delete( $key );
843 
844  if ( $this->hasSessionCookie() || $this->mSkipCookieCheck ) {
845  /* Replace the language object to provide user interface in
846  * correct language immediately on this first page load.
847  */
848  $code = $request->getVal( 'uselang', $user->getOption( 'language' ) );
849  $userLang = Language::factory( $code );
850  $wgLang = $userLang;
851  $this->getContext()->setLanguage( $userLang );
852  // Reset SessionID on Successful login (bug 40995)
853  $this->renewSessionId();
854  if ( $this->getUser()->getPasswordExpired() == 'soft' ) {
855  $this->resetLoginForm( $this->msg( 'resetpass-expired-soft' ) );
856  } elseif ( $wgInvalidPasswordReset
857  && !$user->isValidPassword( $this->mPassword )
858  ) {
859  $status = $user->checkPasswordValidity( $this->mPassword );
860  $this->resetLoginForm(
861  $status->getMessage( 'resetpass-validity-soft' )
862  );
863  } else {
864  $this->successfulLogin();
865  }
866  } else {
867  $this->cookieRedirectCheck( 'login' );
868  }
869  break;
870 
871  case self::NEED_TOKEN:
872  $error = $this->mAbortLoginErrorMsg ?: 'nocookiesforlogin';
873  $this->mainLoginForm( $this->msg( $error )->parse() );
874  break;
875  case self::WRONG_TOKEN:
876  $error = $this->mAbortLoginErrorMsg ?: 'sessionfailure';
877  $this->mainLoginForm( $this->msg( $error )->text() );
878  break;
879  case self::NO_NAME:
880  case self::ILLEGAL:
881  $error = $this->mAbortLoginErrorMsg ?: 'noname';
882  $this->mainLoginForm( $this->msg( $error )->text() );
883  break;
885  $error = $this->mAbortLoginErrorMsg ?: 'wrongpassword';
886  $this->mainLoginForm( $this->msg( $error )->text() );
887  break;
888  case self::NOT_EXISTS:
889  if ( $this->getUser()->isAllowed( 'createaccount' ) ) {
890  $error = $this->mAbortLoginErrorMsg ?: 'nosuchuser';
891  $this->mainLoginForm( $this->msg( $error,
892  wfEscapeWikiText( $this->mUsername ) )->parse() );
893  } else {
894  $error = $this->mAbortLoginErrorMsg ?: 'nosuchusershort';
895  $this->mainLoginForm( $this->msg( $error,
896  wfEscapeWikiText( $this->mUsername ) )->text() );
897  }
898  break;
899  case self::WRONG_PASS:
900  $error = $this->mAbortLoginErrorMsg ?: 'wrongpassword';
901  $this->mainLoginForm( $this->msg( $error )->text() );
902  break;
903  case self::EMPTY_PASS:
904  $error = $this->mAbortLoginErrorMsg ?: 'wrongpasswordempty';
905  $this->mainLoginForm( $this->msg( $error )->text() );
906  break;
907  case self::RESET_PASS:
908  $error = $this->mAbortLoginErrorMsg ?: 'resetpass_announce';
909  $this->resetLoginForm( $this->msg( $error ) );
910  break;
912  $this->userBlockedMessage( $this->getUser()->isBlockedFromCreateAccount() );
913  break;
914  case self::THROTTLED:
915  $error = $this->mAbortLoginErrorMsg ?: 'login-throttled';
916  $this->mainLoginForm( $this->msg( $error )
917  ->params( $this->getLanguage()->formatDuration( $wgPasswordAttemptThrottle['seconds'] ) )
918  ->text()
919  );
920  break;
921  case self::USER_BLOCKED:
922  $error = $this->mAbortLoginErrorMsg ?: 'login-userblocked';
923  $this->mainLoginForm( $this->msg( $error, $this->mUsername )->escaped() );
924  break;
925  case self::ABORTED:
926  $error = $this->mAbortLoginErrorMsg ?: 'login-abort-generic';
927  $this->mainLoginForm( $this->msg( $error )->text() );
928  break;
929  default:
930  throw new MWException( 'Unhandled case value' );
931  }
932  }
933 
938  protected function resetLoginForm( Message $msg ) {
939  // Allow hooks to explain this password reset in more detail
940  wfRunHooks( 'LoginPasswordResetMessage', array( &$msg, $this->mUsername ) );
941  $reset = new SpecialChangePassword();
942  $derivative = new DerivativeContext( $this->getContext() );
943  $derivative->setTitle( $reset->getPageTitle() );
944  $reset->setContext( $derivative );
945  if ( !$this->mTempPasswordUsed ) {
946  $reset->setOldPasswordMessage( 'oldpassword' );
947  }
948  $reset->setChangeMessage( $msg );
949  $reset->execute( null );
950  }
951 
959  function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle',
960  $emailText = 'passwordremindertext'
961  ) {
962  global $wgNewPasswordExpiry;
963 
964  if ( $u->getEmail() == '' ) {
965  return Status::newFatal( 'noemail', $u->getName() );
966  }
967  $ip = $this->getRequest()->getIP();
968  if ( !$ip ) {
969  return Status::newFatal( 'badipaddress' );
970  }
971 
972  $currentUser = $this->getUser();
973  wfRunHooks( 'User::mailPasswordInternal', array( &$currentUser, &$ip, &$u ) );
974 
975  $np = $u->randomPassword();
976  $u->setNewpassword( $np, $throttle );
977  $u->saveSettings();
978  $userLanguage = $u->getOption( 'language' );
979 
980  $mainPage = Title::newMainPage();
981  $mainPageUrl = $mainPage->getCanonicalURL();
982 
983  $m = $this->msg( $emailText, $ip, $u->getName(), $np, '<' . $mainPageUrl . '>',
984  round( $wgNewPasswordExpiry / 86400 ) )->inLanguage( $userLanguage )->text();
985  $result = $u->sendMail( $this->msg( $emailTitle )->inLanguage( $userLanguage )->text(), $m );
986 
987  return $result;
988  }
989 
1000  function successfulLogin() {
1001  # Run any hooks; display injected HTML if any, else redirect
1002  $currentUser = $this->getUser();
1003  $injected_html = '';
1004  wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) );
1005 
1006  if ( $injected_html !== '' ) {
1007  $this->displaySuccessfulAction( $this->msg( 'loginsuccesstitle' ),
1008  'loginsuccess', $injected_html );
1009  } else {
1010  $this->executeReturnTo( 'successredirect' );
1011  }
1012  }
1013 
1020  function successfulCreation() {
1021  # Run any hooks; display injected HTML
1022  $currentUser = $this->getUser();
1023  $injected_html = '';
1024  $welcome_creation_msg = 'welcomecreation-msg';
1025 
1026  wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) );
1027 
1033  wfRunHooks( 'BeforeWelcomeCreation', array( &$welcome_creation_msg, &$injected_html ) );
1034 
1035  $this->displaySuccessfulAction( $this->msg( 'welcomeuser', $this->getUser()->getName() ),
1036  $welcome_creation_msg, $injected_html );
1037  }
1038 
1046  private function displaySuccessfulAction( $title, $msgname, $injected_html ) {
1047  $out = $this->getOutput();
1048  $out->setPageTitle( $title );
1049  if ( $msgname ) {
1050  $out->addWikiMsg( $msgname, wfEscapeWikiText( $this->getUser()->getName() ) );
1051  }
1052 
1053  $out->addHTML( $injected_html );
1054 
1055  $this->executeReturnTo( 'success' );
1056  }
1057 
1066  function userBlockedMessage( Block $block ) {
1067  # Let's be nice about this, it's likely that this feature will be used
1068  # for blocking large numbers of innocent people, e.g. range blocks on
1069  # schools. Don't blame it on the user. There's a small chance that it
1070  # really is the user's fault, i.e. the username is blocked and they
1071  # haven't bothered to log out before trying to create an account to
1072  # evade it, but we'll leave that to their guilty conscience to figure
1073  # out.
1074  $errorParams = array(
1075  $block->getTarget(),
1076  $block->mReason ? $block->mReason : $this->msg( 'blockednoreason' )->text(),
1077  $block->getByName()
1078  );
1079 
1080  if ( $block->getType() === Block::TYPE_RANGE ) {
1081  $errorMessage = 'cantcreateaccount-range-text';
1082  $errorParams[] = $this->getRequest()->getIP();
1083  } else {
1084  $errorMessage = 'cantcreateaccount-text';
1085  }
1086 
1087  throw new ErrorPageError(
1088  'cantcreateaccounttitle',
1089  $errorMessage,
1090  $errorParams
1091  );
1092  }
1093 
1108  public function showReturnToPage(
1109  $type, $returnTo = '', $returnToQuery = '', $stickHTTPs = false
1110  ) {
1111  $this->mReturnTo = $returnTo;
1112  $this->mReturnToQuery = $returnToQuery;
1113  $this->mStickHTTPS = $stickHTTPs;
1114  $this->executeReturnTo( $type );
1115  }
1116 
1125  private function executeReturnTo( $type ) {
1126  global $wgRedirectOnLogin, $wgSecureLogin;
1127 
1128  if ( $type != 'error' && $wgRedirectOnLogin !== null ) {
1129  $returnTo = $wgRedirectOnLogin;
1130  $returnToQuery = array();
1131  } else {
1132  $returnTo = $this->mReturnTo;
1133  $returnToQuery = wfCgiToArray( $this->mReturnToQuery );
1134  }
1135 
1136  $returnToTitle = Title::newFromText( $returnTo );
1137  if ( !$returnToTitle ) {
1138  $returnToTitle = Title::newMainPage();
1139  }
1140 
1141  if ( $wgSecureLogin && !$this->mStickHTTPS ) {
1142  $options = array( 'http' );
1143  $proto = PROTO_HTTP;
1144  } elseif ( $wgSecureLogin ) {
1145  $options = array( 'https' );
1146  $proto = PROTO_HTTPS;
1147  } else {
1148  $options = array();
1149  $proto = PROTO_RELATIVE;
1150  }
1151 
1152  if ( $type == 'successredirect' ) {
1153  $redirectUrl = $returnToTitle->getFullURL( $returnToQuery, false, $proto );
1154  $this->getOutput()->redirect( $redirectUrl );
1155  } else {
1156  $this->getOutput()->addReturnTo( $returnToTitle, $returnToQuery, null, $options );
1157  }
1158  }
1159 
1163  function mainLoginForm( $msg, $msgtype = 'error' ) {
1164  global $wgEnableEmail, $wgEnableUserEmail;
1165  global $wgHiddenPrefs, $wgLoginLanguageSelector;
1166  global $wgAuth, $wgEmailConfirmToEdit, $wgCookieExpiration;
1167  global $wgSecureLogin, $wgPasswordResetRoutes;
1168 
1169  $titleObj = $this->getPageTitle();
1170  $user = $this->getUser();
1171  $out = $this->getOutput();
1172 
1173  if ( $this->mType == 'signup' ) {
1174  // Block signup here if in readonly. Keeps user from
1175  // going through the process (filling out data, etc)
1176  // and being informed later.
1177  $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $user, true );
1178  if ( count( $permErrors ) ) {
1179  throw new PermissionsError( 'createaccount', $permErrors );
1180  } elseif ( $user->isBlockedFromCreateAccount() ) {
1181  $this->userBlockedMessage( $user->isBlockedFromCreateAccount() );
1182 
1183  return;
1184  } elseif ( wfReadOnly() ) {
1185  throw new ReadOnlyError;
1186  }
1187  }
1188 
1189  // Pre-fill username (if not creating an account, bug 44775).
1190  if ( $this->mUsername == '' && $this->mType != 'signup' ) {
1191  if ( $user->isLoggedIn() ) {
1192  $this->mUsername = $user->getName();
1193  } else {
1194  $this->mUsername = $this->getRequest()->getCookie( 'UserName' );
1195  }
1196  }
1197 
1198  // Generic styles and scripts for both login and signup form
1199  $out->addModuleStyles( array(
1200  'mediawiki.ui',
1201  'mediawiki.ui.button',
1202  'mediawiki.special.userlogin.common.styles'
1203  ) );
1204  $out->addModules( array(
1205  'mediawiki.special.userlogin.common.js'
1206  ) );
1207 
1208  if ( $this->mType == 'signup' ) {
1209  // XXX hack pending RL or JS parse() support for complex content messages
1210  // https://bugzilla.wikimedia.org/show_bug.cgi?id=25349
1211  $out->addJsConfigVars( 'wgCreateacctImgcaptchaHelp',
1212  $this->msg( 'createacct-imgcaptcha-help' )->parse() );
1213 
1214  // Additional styles and scripts for signup form
1215  $out->addModules( array(
1216  'mediawiki.special.userlogin.signup.js'
1217  ) );
1218  $out->addModuleStyles( array(
1219  'mediawiki.special.userlogin.signup.styles'
1220  ) );
1221 
1222  $template = new UsercreateTemplate();
1223 
1224  // Must match number of benefits defined in messages
1225  $template->set( 'benefitCount', 3 );
1226 
1227  $q = 'action=submitlogin&type=signup';
1228  $linkq = 'type=login';
1229  } else {
1230  // Additional styles for login form
1231  $out->addModuleStyles( array(
1232  'mediawiki.special.userlogin.login.styles'
1233  ) );
1234 
1235  $template = new UserloginTemplate();
1236 
1237  $q = 'action=submitlogin&type=login';
1238  $linkq = 'type=signup';
1239  }
1240 
1241  if ( $this->mReturnTo !== '' ) {
1242  $returnto = '&returnto=' . wfUrlencode( $this->mReturnTo );
1243  if ( $this->mReturnToQuery !== '' ) {
1244  $returnto .= '&returntoquery=' .
1245  wfUrlencode( $this->mReturnToQuery );
1246  }
1247  $q .= $returnto;
1248  $linkq .= $returnto;
1249  }
1250 
1251  # Don't show a "create account" link if the user can't.
1252  if ( $this->showCreateOrLoginLink( $user ) ) {
1253  # Pass any language selection on to the mode switch link
1254  if ( $wgLoginLanguageSelector && $this->mLanguage ) {
1255  $linkq .= '&uselang=' . $this->mLanguage;
1256  }
1257  // Supply URL, login template creates the button.
1258  $template->set( 'createOrLoginHref', $titleObj->getLocalURL( $linkq ) );
1259  } else {
1260  $template->set( 'link', '' );
1261  }
1262 
1263  $resetLink = $this->mType == 'signup'
1264  ? null
1265  : is_array( $wgPasswordResetRoutes ) && in_array( true, array_values( $wgPasswordResetRoutes ) );
1266 
1267  $template->set( 'header', '' );
1268  $template->set( 'skin', $this->getSkin() );
1269  $template->set( 'name', $this->mUsername );
1270  $template->set( 'password', $this->mPassword );
1271  $template->set( 'retype', $this->mRetype );
1272  $template->set( 'createemailset', $this->mCreateaccountMail );
1273  $template->set( 'email', $this->mEmail );
1274  $template->set( 'realname', $this->mRealName );
1275  $template->set( 'domain', $this->mDomain );
1276  $template->set( 'reason', $this->mReason );
1277 
1278  $template->set( 'action', $titleObj->getLocalURL( $q ) );
1279  $template->set( 'message', $msg );
1280  $template->set( 'messagetype', $msgtype );
1281  $template->set( 'createemail', $wgEnableEmail && $user->isLoggedIn() );
1282  $template->set( 'userealname', !in_array( 'realname', $wgHiddenPrefs ) );
1283  $template->set( 'useemail', $wgEnableEmail );
1284  $template->set( 'emailrequired', $wgEmailConfirmToEdit );
1285  $template->set( 'emailothers', $wgEnableUserEmail );
1286  $template->set( 'canreset', $wgAuth->allowPasswordChange() );
1287  $template->set( 'resetlink', $resetLink );
1288  $template->set( 'canremember', ( $wgCookieExpiration > 0 ) );
1289  $template->set( 'usereason', $user->isLoggedIn() );
1290  $template->set( 'remember', $this->mRemember );
1291  $template->set( 'cansecurelogin', ( $wgSecureLogin === true ) );
1292  $template->set( 'stickhttps', (int)$this->mStickHTTPS );
1293  $template->set( 'loggedin', $user->isLoggedIn() );
1294  $template->set( 'loggedinuser', $user->getName() );
1295 
1296  if ( $this->mType == 'signup' ) {
1297  if ( !self::getCreateaccountToken() ) {
1299  }
1300  $template->set( 'token', self::getCreateaccountToken() );
1301  } else {
1302  if ( !self::getLoginToken() ) {
1304  }
1305  $template->set( 'token', self::getLoginToken() );
1306  }
1307 
1308  # Prepare language selection links as needed
1309  if ( $wgLoginLanguageSelector ) {
1310  $template->set( 'languages', $this->makeLanguageSelector() );
1311  if ( $this->mLanguage ) {
1312  $template->set( 'uselang', $this->mLanguage );
1313  }
1314  }
1315 
1316  $template->set( 'secureLoginUrl', $this->mSecureLoginUrl );
1317  // Use loginend-https for HTTPS requests if it's not blank, loginend otherwise
1318  // Ditto for signupend. New forms use neither.
1319  $usingHTTPS = $this->mRequest->getProtocol() == 'https';
1320  $loginendHTTPS = $this->msg( 'loginend-https' );
1321  $signupendHTTPS = $this->msg( 'signupend-https' );
1322  if ( $usingHTTPS && !$loginendHTTPS->isBlank() ) {
1323  $template->set( 'loginend', $loginendHTTPS->parse() );
1324  } else {
1325  $template->set( 'loginend', $this->msg( 'loginend' )->parse() );
1326  }
1327  if ( $usingHTTPS && !$signupendHTTPS->isBlank() ) {
1328  $template->set( 'signupend', $signupendHTTPS->parse() );
1329  } else {
1330  $template->set( 'signupend', $this->msg( 'signupend' )->parse() );
1331  }
1332 
1333  // Give authentication and captcha plugins a chance to modify the form
1334  $wgAuth->modifyUITemplate( $template, $this->mType );
1335  if ( $this->mType == 'signup' ) {
1336  wfRunHooks( 'UserCreateForm', array( &$template ) );
1337  } else {
1338  wfRunHooks( 'UserLoginForm', array( &$template ) );
1339  }
1340 
1341  $out->disallowUserJs(); // just in case...
1342  $out->addTemplate( $template );
1343  }
1344 
1352  private function showCreateOrLoginLink( &$user ) {
1353  if ( $this->mType == 'signup' ) {
1354  return true;
1355  } elseif ( $user->isAllowed( 'createaccount' ) ) {
1356  return true;
1357  } else {
1358  return false;
1359  }
1360  }
1361 
1372  function hasSessionCookie() {
1373  global $wgDisableCookieCheck;
1374 
1375  return $wgDisableCookieCheck ? true : $this->getRequest()->checkSessionCookie();
1376  }
1377 
1382  public static function getLoginToken() {
1383  global $wgRequest;
1384 
1385  return $wgRequest->getSessionData( 'wsLoginToken' );
1386  }
1387 
1391  public static function setLoginToken() {
1392  global $wgRequest;
1393  // Generate a token directly instead of using $user->getEditToken()
1394  // because the latter reuses $_SESSION['wsEditToken']
1395  $wgRequest->setSessionData( 'wsLoginToken', MWCryptRand::generateHex( 32 ) );
1396  }
1397 
1401  public static function clearLoginToken() {
1402  global $wgRequest;
1403  $wgRequest->setSessionData( 'wsLoginToken', null );
1404  }
1405 
1410  public static function getCreateaccountToken() {
1411  global $wgRequest;
1412 
1413  return $wgRequest->getSessionData( 'wsCreateaccountToken' );
1414  }
1415 
1419  public static function setCreateaccountToken() {
1420  global $wgRequest;
1421  $wgRequest->setSessionData( 'wsCreateaccountToken', MWCryptRand::generateHex( 32 ) );
1422  }
1423 
1427  public static function clearCreateaccountToken() {
1428  global $wgRequest;
1429  $wgRequest->setSessionData( 'wsCreateaccountToken', null );
1430  }
1431 
1435  private function renewSessionId() {
1436  global $wgSecureLogin, $wgCookieSecure;
1437  if ( $wgSecureLogin && !$this->mStickHTTPS ) {
1438  $wgCookieSecure = false;
1439  }
1440  // Always make sure edit token is regenerated. (T114419)
1441  $this->getRequest()->setSessionData( 'wsEditToken', null );
1442  wfResetSessionID();
1443  }
1444 
1448  function cookieRedirectCheck( $type ) {
1449  $titleObj = SpecialPage::getTitleFor( 'Userlogin' );
1450  $query = array( 'wpCookieCheck' => $type );
1451  if ( $this->mReturnTo !== '' ) {
1452  $query['returnto'] = $this->mReturnTo;
1453  $query['returntoquery'] = $this->mReturnToQuery;
1454  }
1455  $check = $titleObj->getFullURL( $query );
1456 
1457  $this->getOutput()->redirect( $check );
1458  }
1459 
1463  function onCookieRedirectCheck( $type ) {
1464  if ( !$this->hasSessionCookie() ) {
1465  if ( $type == 'new' ) {
1466  $this->mainLoginForm( $this->msg( 'nocookiesnew' )->parse() );
1467  } elseif ( $type == 'login' ) {
1468  $this->mainLoginForm( $this->msg( 'nocookieslogin' )->parse() );
1469  } else {
1470  # shouldn't happen
1471  $this->mainLoginForm( $this->msg( 'error' )->text() );
1472  }
1473  } else {
1474  $this->successfulLogin();
1475  }
1476  }
1477 
1484  function makeLanguageSelector() {
1485  $msg = $this->msg( 'loginlanguagelinks' )->inContentLanguage();
1486  if ( !$msg->isBlank() ) {
1487  $langs = explode( "\n", $msg->text() );
1488  $links = array();
1489  foreach ( $langs as $lang ) {
1490  $lang = trim( $lang, '* ' );
1491  $parts = explode( '|', $lang );
1492  if ( count( $parts ) >= 2 ) {
1493  $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
1494  }
1495  }
1496 
1497  return count( $links ) > 0 ? $this->msg( 'loginlanguagelabel' )->rawParams(
1498  $this->getLanguage()->pipeList( $links ) )->escaped() : '';
1499  } else {
1500  return '';
1501  }
1502  }
1503 
1512  function makeLanguageSelectorLink( $text, $lang ) {
1513  if ( $this->getLanguage()->getCode() == $lang ) {
1514  // no link for currently used language
1515  return htmlspecialchars( $text );
1516  }
1517  $query = array( 'uselang' => $lang );
1518  if ( $this->mType == 'signup' ) {
1519  $query['type'] = 'signup';
1520  }
1521  if ( $this->mReturnTo !== '' ) {
1522  $query['returnto'] = $this->mReturnTo;
1523  $query['returntoquery'] = $this->mReturnToQuery;
1524  }
1525 
1526  $attr = array();
1527  $targetLanguage = Language::factory( $lang );
1528  $attr['lang'] = $attr['hreflang'] = $targetLanguage->getHtmlCode();
1529 
1530  return Linker::linkKnown(
1531  $this->getPageTitle(),
1532  htmlspecialchars( $text ),
1533  $attr,
1534  $query
1535  );
1536  }
1537 
1538  protected function getGroupName() {
1539  return 'login';
1540  }
1541 }
ReadOnlyError
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Definition: ReadOnlyError.php:28
LoginForm\onCookieRedirectCheck
onCookieRedirectCheck( $type)
Definition: SpecialUserlogin.php:1461
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:488
LoginForm\showReturnToPage
showReturnToPage( $type, $returnTo='', $returnToQuery='', $stickHTTPs=false)
Add a "return to" link or redirect to it.
Definition: SpecialUserlogin.php:1106
LoginForm\$mToken
$mToken
Definition: SpecialUserlogin.php:63
LoginForm\$mCreateaccountMail
$mCreateaccountMail
Definition: SpecialUserlogin.php:55
$wgUser
$wgUser
Definition: Setup.php:572
LoginForm\$mLoginattempt
$mLoginattempt
Definition: SpecialUserlogin.php:56
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. $reader:XMLReader object $logInfo:Array of information Return false to stop further processing of the tag 'ImportHandlePageXMLTag':When parsing a XML tag in a page. $reader:XMLReader object $pageInfo:Array of information Return false to stop further processing of the tag 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information Return false to stop further processing of the tag 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. $reader:XMLReader object Return false to stop further processing of the tag 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. $reader:XMLReader object $revisionInfo:Array of information Return false to stop further processing of the tag 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. $title:Title object for the current page $request:WebRequest $ignoreRedirect:boolean to skip redirect check $target:Title/string of redirect target $article:Article object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) $article:article(object) being checked 'IsTrustedProxy':Override the result of wfIsTrustedProxy() $ip:IP being check $result:Change this value to override the result of wfIsTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of User::isValidEmailAddr(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetMagic':DEPRECATED, use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetSpecialPageAliases':DEPRECATED, use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Associative array mapping language codes to prefixed links of the form "language:title". & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LinkBegin':Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1528
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:189
$request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled also a ContextSource error or success you ll probably need to make sure the header is varied on WebRequest $request
Definition: hooks.txt:1961
Block\getType
getType()
Get the type of target for this particular block.
Definition: Block.php:1250
wfCanIPUseHTTPS
wfCanIPUseHTTPS( $ip)
Determine whether the client at a given source IP is likely to be able to access the wiki via HTTPS.
Definition: GlobalFunctions.php:4194
LoginForm\USER_BLOCKED
const USER_BLOCKED
Definition: SpecialUserlogin.php:41
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
LoginForm\hasSessionCookie
hasSessionCookie()
Check if a session cookie is present.
Definition: SpecialUserlogin.php:1370
LoginForm\WRONG_PASS
const WRONG_PASS
Definition: SpecialUserlogin.php:35
LoginForm\CREATE_BLOCKED
const CREATE_BLOCKED
Definition: SpecialUserlogin.php:39
wfSetupSession
wfSetupSession( $sessionId=false)
Initialise php session.
Definition: GlobalFunctions.php:3587
LoginForm\$mRetype
$mRetype
Definition: SpecialUserlogin.php:49
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:535
LoginForm\$mSkipCookieCheck
$mSkipCookieCheck
Definition: SpecialUserlogin.php:61
LoginForm\mainLoginForm
mainLoginForm( $msg, $msgtype='error')
Definition: SpecialUserlogin.php:1161
LoginForm\ILLEGAL
const ILLEGAL
Definition: SpecialUserlogin.php:32
LoginForm\$mSecureLoginUrl
$mSecureLoginUrl
Definition: SpecialUserlogin.php:71
$wgMemc
globals will be eliminated from MediaWiki replaced by an application object which would be passed to constructors Whether that would be an convenient solution remains to be but certainly PHP makes such object oriented programming models easier than they were in previous versions For the time being MediaWiki programmers will have to work in an environment with some global context At the time of globals were initialised on startup by MediaWiki of these were configuration which are documented in DefaultSettings php There is no comprehensive documentation for the remaining however some of the most important ones are listed below They are typically initialised either in index php or in Setup php For a description of the see design txt $wgTitle Title object created from the request URL $wgOut OutputPage object for HTTP response $wgUser User object for the user associated with the current request $wgLang Language object selected by user preferences $wgContLang Language object associated with the wiki being viewed $wgParser Parser object Parser extensions register their hooks here $wgRequest WebRequest to get request data $wgMemc
Definition: globals.txt:25
Block\TYPE_RANGE
const TYPE_RANGE
Definition: Block.php:49
LoginForm\SUCCESS
const SUCCESS
Definition: SpecialUserlogin.php:30
text
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition: design.txt:12
LoginForm\$mLoaded
$mLoaded
Definition: SpecialUserlogin.php:70
Title\newMainPage
static newMainPage()
Create a new Title for the Main Page.
Definition: Title.php:441
LoginForm\incLoginThrottle
static incLoginThrottle( $username)
Increment the login attempt throttle hit count for the (username,current IP) tuple unless the throttl...
Definition: SpecialUserlogin.php:723
LoginForm\execute
execute( $subPage)
Default execute method Checks user permissions, calls the function given in mFunction.
Definition: SpecialUserlogin.php:169
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:377
LoginForm\successfulCreation
successfulCreation()
Run any hooks registered for logins, then display a message welcoming the user.
Definition: SpecialUserlogin.php:1018
Status\newGood
static newGood( $value=null)
Factory function for good results.
Definition: Status.php:77
UsercreateTemplate
Definition: Usercreate.php:24
LoginForm\$mOverrideRequest
WebRequest $mOverrideRequest
Definition: SpecialUserlogin.php:73
Sanitizer\validateEmail
static validateEmail( $addr)
Does a string look like an e-mail address?
Definition: Sanitizer.php:1847
LoginForm\$mRealName
$mRealName
Definition: SpecialUserlogin.php:67
LoginForm\RESET_PASS
const RESET_PASS
Definition: SpecialUserlogin.php:37
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1360
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:389
LoginForm\getCreateaccountToken
static getCreateaccountToken()
Get the createaccount token from the current session.
Definition: SpecialUserlogin.php:1408
LoginForm\$mAbortLoginErrorMsg
$mAbortLoginErrorMsg
Definition: SpecialUserlogin.php:45
LoginForm\clearLoginThrottle
static clearLoginThrottle( $username)
Clear the login attempt throttle hit count for the (username,current IP) tuple.
Definition: SpecialUserlogin.php:752
LoginForm\$mPosted
$mPosted
Definition: SpecialUserlogin.php:52
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name.
Definition: SpecialPage.php:74
LoginForm\THROTTLED
const THROTTLED
Definition: SpecialUserlogin.php:40
SpecialPage\getSkin
getSkin()
Shortcut to get the skin being used for this instance.
Definition: SpecialPage.php:555
MWCryptRand\generateHex
static generateHex( $chars, $forceStrong=false)
Generate a run of (ideally) cryptographically random data and return it in hexadecimal string format.
Definition: MWCryptRand.php:514
PermissionsError
Show an error when a user tries to do something they do not have the necessary permissions for.
Definition: PermissionsError.php:28
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
LoginForm\$mReturnToQuery
$mReturnToQuery
Definition: SpecialUserlogin.php:62
LoginForm\$mCreateaccount
$mCreateaccount
Definition: SpecialUserlogin.php:54
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:578
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:139
Linker\linkKnown
static linkKnown( $target, $html=null, $customAttribs=array(), $query=array(), $options=array( 'known', 'noclasses'))
Identical to link(), except $options defaults to 'known'.
Definition: Linker.php:264
true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:1530
LoginForm\authenticateUserData
authenticateUserData()
Internally authenticate the login request.
Definition: SpecialUserlogin.php:579
LoginForm\setLoginToken
static setLoginToken()
Randomly generate a new login token and attach it to the current session.
Definition: SpecialUserlogin.php:1389
LoginForm\clearCreateaccountToken
static clearCreateaccountToken()
Remove any createaccount token attached to the current session.
Definition: SpecialUserlogin.php:1425
LoginForm\EMPTY_PASS
const EMPTY_PASS
Definition: SpecialUserlogin.php:36
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:506
LoginForm\load
load()
Loader.
Definition: SpecialUserlogin.php:89
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:32
LoginForm\ABORTED
const ABORTED
Definition: SpecialUserlogin.php:38
MWException
MediaWiki exception.
Definition: MWException.php:26
LoginForm\$mType
$mType
Definition: SpecialUserlogin.php:65
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3635
$out
$out
Definition: UtfNormalGenerate.php:167
LoginForm\renewSessionId
renewSessionId()
Renew the user's session id, using strong entropy.
Definition: SpecialUserlogin.php:1433
LoginForm\resetLoginForm
resetLoginForm(Message $msg)
Show the Special:ChangePassword form, with custom message.
Definition: SpecialUserlogin.php:936
LoginForm\$mCookieCheck
$mCookieCheck
Definition: SpecialUserlogin.php:51
LoginForm\addNewAccountInternal
addNewAccountInternal()
Make a new user account using the loaded data.
Definition: SpecialUserlogin.php:358
WatchedItem\IGNORE_USER_RIGHTS
const IGNORE_USER_RIGHTS
Constant to specify that user rights 'editmywatchlist' and 'viewmywatchlist' should not be checked.
Definition: WatchedItem.php:35
SpecialPage\getFullTitle
getFullTitle()
Return the full title, including $par.
Definition: SpecialPage.php:588
DeferredUpdates\addUpdate
static addUpdate(DeferrableUpdate $update)
Add an update to the deferred list.
Definition: DeferredUpdates.php:51
LoginForm\NOT_EXISTS
const NOT_EXISTS
Definition: SpecialUserlogin.php:34
wfRunHooks
wfRunHooks( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in $wgHooks.
Definition: GlobalFunctions.php:4066
LoginForm\cookieRedirectCheck
cookieRedirectCheck( $type)
Definition: SpecialUserlogin.php:1446
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:459
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
LoginForm\makeLanguageSelector
makeLanguageSelector()
Produce a bar of links which allow the user to select another language during login/registration but ...
Definition: SpecialUserlogin.php:1482
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:352
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:545
LoginForm\showCreateOrLoginLink
showCreateOrLoginLink(&$user)
Whether the login/create account form should display a link to the other form (in addition to whateve...
Definition: SpecialUserlogin.php:1350
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
LoginForm
Implements Special:UserLogin.
Definition: SpecialUserlogin.php:29
SiteStatsUpdate
Class for handling updates to the site_stats table.
Definition: SiteStatsUpdate.php:24
LoginForm\__construct
__construct( $request=null)
Definition: SpecialUserlogin.php:80
LoginForm\$mReturnTo
$mReturnTo
Definition: SpecialUserlogin.php:50
PROTO_HTTPS
const PROTO_HTTPS
Definition: Defines.php:268
LoginForm\setCreateaccountToken
static setCreateaccountToken()
Randomly generate a new createaccount token and attach it to the current session.
Definition: SpecialUserlogin.php:1417
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:508
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:1530
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:422
LoginForm\mailPasswordInternal
mailPasswordInternal( $u, $throttle=true, $emailTitle='passwordremindertitle', $emailText='passwordremindertext')
Definition: SpecialUserlogin.php:957
LoginForm\userBlockedMessage
userBlockedMessage(Block $block)
Output a message that informs the user that they cannot create an account because there is a block on...
Definition: SpecialUserlogin.php:1064
LoginForm\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialUserlogin.php:1536
$title
presenting them properly to the user as errors is done by the caller $title
Definition: hooks.txt:1324
SpecialChangePassword
Let users recover their password.
Definition: SpecialChangePassword.php:29
$value
$value
Definition: styleTest.css.php:45
LoginForm\WRONG_TOKEN
const WRONG_TOKEN
Definition: SpecialUserlogin.php:43
SpecialPage\msg
msg()
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:609
LoginForm\processLogin
processLogin()
Definition: SpecialUserlogin.php:816
SpecialPage
Parent class for all special pages.
Definition: SpecialPage.php:33
LoginForm\makeLanguageSelectorLink
makeLanguageSelectorLink( $text, $lang)
Create a language selector link for a particular language Links back to this page preserving type and...
Definition: SpecialUserlogin.php:1510
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:525
PROTO_HTTP
const PROTO_HTTP
Definition: Defines.php:267
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:2124
LoginForm\$mRequest
WebRequest $mRequest
Effective request; set at the beginning of load *.
Definition: SpecialUserlogin.php:75
PROTO_RELATIVE
const PROTO_RELATIVE
Definition: Defines.php:269
LoginForm\$mEmail
$mEmail
Definition: SpecialUserlogin.php:58
Block\getTarget
getTarget()
Get the target for this particular Block.
Definition: Block.php:1273
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:237
LoginForm\$mRemember
$mRemember
Definition: SpecialUserlogin.php:57
LoginForm\$mUsername
$mUsername
Definition: SpecialUserlogin.php:47
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
Definition: WebRequest.php:38
$count
$count
Definition: UtfNormalTest2.php:96
LoginForm\getDescription
getDescription()
Returns the name that goes in the <h1> in the special page itself, and also the name that will be lis...
Definition: SpecialUserlogin.php:158
LoginForm\$mTempPasswordUsed
$mTempPasswordUsed
Definition: SpecialUserlogin.php:69
LoginForm\displaySuccessfulAction
displaySuccessfulAction( $title, $msgname, $injected_html)
Display an "successful action" page.
Definition: SpecialUserlogin.php:1044
LoginForm\addNewAccount
addNewAccount()
Definition: SpecialUserlogin.php:276
$wgLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as $wgLang
Definition: design.txt:56
UserloginTemplate
Definition: Userlogin.php:24
LoginForm\$mReason
$mReason
Definition: SpecialUserlogin.php:66
LoginForm\$mStickHTTPS
$mStickHTTPS
Definition: SpecialUserlogin.php:64
LoginForm\$mPassword
$mPassword
Definition: SpecialUserlogin.php:48
User\getCanonicalName
static getCanonicalName( $name, $validate='valid')
Given unvalidated user input, return a canonical username, or false if the username is invalid.
Definition: User.php:884
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
Block
Definition: Block.php:22
LoginForm\NEED_TOKEN
const NEED_TOKEN
Definition: SpecialUserlogin.php:42
WRONG_PASS
this hook is for auditing only WRONG_PASS
Definition: hooks.txt:1644
NS_USER
const NS_USER
Definition: Defines.php:81
LoginForm\initUser
initUser( $u, $autocreate)
Actually add a user to the database.
Definition: SpecialUserlogin.php:542
LoginForm\$mAction
$mAction
Definition: SpecialUserlogin.php:53
LoginForm\successfulLogin
successfulLogin()
Run any hooks registered for logins, then HTTP redirect to $this->mReturnTo (or Main Page if that's u...
Definition: SpecialUserlogin.php:998
LoginForm\NO_NAME
const NO_NAME
Definition: SpecialUserlogin.php:31
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:184
Block\getByName
getByName()
Get the username of the blocking sysop.
Definition: Block.php:831
LoginForm\$mLanguage
$mLanguage
Definition: SpecialUserlogin.php:60
LoginForm\getLoginToken
static getLoginToken()
Get the login token from the current session.
Definition: SpecialUserlogin.php:1380
$error
usually copyright or history_copyright This message must be in HTML not wikitext $subpages will be ignored and the rest of subPageSubtitle() will run. 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink' whether MediaWiki currently thinks this is a CSS JS page Hooks may change this value to override the return value of Title::isCssOrJsPage(). 'TitleIsAlwaysKnown' whether MediaWiki currently thinks this page is known isMovable() always returns false. $title whether MediaWiki currently thinks this page is movable Hooks may change this value to override the return value of Title::isMovable(). 'TitleIsWikitextPage' whether MediaWiki currently thinks this is a wikitext page Hooks may change this value to override the return value of Title::isWikitextPage() 'TitleMove' use UploadVerification and UploadVerifyFile instead where the first element is the message key and the remaining elements are used as parameters to the message based on mime etc Preferred in most cases over UploadVerification object with all info about the upload string as detected by MediaWiki Handlers will typically only apply for specific mime types object & $error
Definition: hooks.txt:2584
User\isUsableName
static isUsableName( $name)
Usernames which fail to pass this function will be blocked from user login and new account registrati...
Definition: User.php:624
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:27
$query
return true to allow those checks to and false if checking is done use this to change the tables headers temp or archived zone change it to an object instance and return false override the list derivative used the name of the old file when set the default code will be skipped add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1105
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:59
LoginForm\attemptAutoCreate
attemptAutoCreate( $user)
Attempt to automatically create a user on login.
Definition: SpecialUserlogin.php:769
wfResetSessionID
wfResetSessionID()
Reset the session_id.
Definition: GlobalFunctions.php:3566
LoginForm\executeReturnTo
executeReturnTo( $type)
Add a "return to" link or redirect to it.
Definition: SpecialUserlogin.php:1123
$retval
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account incomplete not yet checked for validity & $retval
Definition: hooks.txt:237
LoginForm\addNewAccountMailPassword
addNewAccountMailPassword()
Definition: SpecialUserlogin.php:236
LoginForm\clearLoginToken
static clearLoginToken()
Remove any login token attached to the current session.
Definition: SpecialUserlogin.php:1399
Status\newFatal
static newFatal( $message)
Factory function for fatal errors.
Definition: Status.php:63
LoginForm\WRONG_PLUGIN_PASS
const WRONG_PLUGIN_PASS
Definition: SpecialUserlogin.php:33
$type
$type
Definition: testCompression.php:46
LoginForm\$mDomain
$mDomain
Definition: SpecialUserlogin.php:59