]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/SpecialUserlogin.php
MediaWiki 1.5.8 (initial commit)
[autoinstallsdev/mediawiki.git] / includes / SpecialUserlogin.php
1 <?php
2 /**
3  *
4  * @package MediaWiki
5  * @subpackage SpecialPage
6  */
7
8 /**
9  * constructor
10  */
11 function wfSpecialUserlogin() {
12         global $wgCommandLineMode;
13         global $wgRequest;
14         if( !$wgCommandLineMode && !isset( $_COOKIE[session_name()] )  ) {
15                 User::SetupSession();
16         }
17         
18         $form = new LoginForm( $wgRequest );
19         $form->execute();
20 }
21
22 /**
23  *
24  * @package MediaWiki
25  * @subpackage SpecialPage
26  */
27 class LoginForm {
28         var $mName, $mPassword, $mRetype, $mReturnto, $mCookieCheck, $mPosted;
29         var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
30         var $mLoginattempt, $mRemember, $mEmail, $mDomain;
31         
32         /**
33          * Constructor
34          * @param webrequest $request A webrequest object passed by reference
35          */
36         function LoginForm( &$request ) {
37                 global $wgLang, $wgAllowRealName, $wgEnableEmail;
38                 global $wgAuth;
39
40                 $this->mName = $request->getText( 'wpName' );
41                 $this->mPassword = $request->getText( 'wpPassword' );
42                 $this->mRetype = $request->getText( 'wpRetype' );
43                 $this->mDomain = $request->getText( 'wpDomain' );
44                 $this->mReturnto = $request->getVal( 'returnto' );
45                 $this->mCookieCheck = $request->getVal( 'wpCookieCheck' );
46                 $this->mPosted = $request->wasPosted();
47                 $this->mCreateaccount = $request->getCheck( 'wpCreateaccount' );
48                 $this->mCreateaccountMail = $request->getCheck( 'wpCreateaccountMail' )
49                                             && $wgEnableEmail;
50                 $this->mMailmypassword = $request->getCheck( 'wpMailmypassword' )
51                                          && $wgEnableEmail;
52                 $this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
53                 $this->mAction = $request->getVal( 'action' );
54                 $this->mRemember = $request->getCheck( 'wpRemember' );
55                 
56                 if( $wgEnableEmail ) {
57                         $this->mEmail = $request->getText( 'wpEmail' );
58                 } else {
59                         $this->mEmail = '';
60                 }
61                 if( $wgAllowRealName ) {
62                     $this->mRealName = $request->getText( 'wpRealName' );
63                 } else {
64                     $this->mRealName = '';
65                 }
66                 
67                 if( !$wgAuth->validDomain( $this->mDomain ) ) {
68                         $this->mDomain = 'invaliddomain';
69                 }
70                 $wgAuth->setDomain( $this->mDomain );
71  
72                 # When switching accounts, it sucks to get automatically logged out
73                 if( $this->mReturnto == $wgLang->specialPage( 'Userlogout' ) ) {
74                         $this->mReturnto = '';
75                 }
76         }
77
78         function execute() {
79                 if ( !is_null( $this->mCookieCheck ) ) {
80                         $this->onCookieRedirectCheck( $this->mCookieCheck );
81                         return;
82                 } else if( $this->mPosted ) {
83                         if( $this->mCreateaccount ) {
84                                 return $this->addNewAccount();
85                         } else if ( $this->mCreateaccountMail ) {
86                                 return $this->addNewAccountMailPassword();
87                         } else if ( $this->mMailmypassword ) {
88                                 return $this->mailPassword();
89                         } else if ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
90                                 return $this->processLogin();
91                         }
92                 }
93                 $this->mainLoginForm( '' );
94         }
95
96         /**
97          * @access private
98          */
99         function addNewAccountMailPassword() {
100                 global $wgOut;
101                 
102                 if ('' == $this->mEmail) {
103                         $this->mainLoginForm( wfMsg( 'noemail', htmlspecialchars( $this->mName ) ) );
104                         return;
105                 }
106
107                 $u = $this->addNewaccountInternal();
108
109                 if ($u == NULL) {
110                         return;
111                 }
112
113                 $u->saveSettings();
114                 $result = $this->mailPasswordInternal($u);
115                 
116                 $wgOut->setPageTitle( wfMsg( 'accmailtitle' ) );
117                 $wgOut->setRobotpolicy( 'noindex,nofollow' );
118                 $wgOut->setArticleRelated( false );
119         
120                 if( WikiError::isError( $result ) ) {
121                         $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
122                 } else {
123                         $wgOut->addWikiText( wfMsg( 'accmailtext', $u->getName(), $u->getEmail() ) );
124                         $wgOut->returnToMain( false );
125                 }
126                 $u = 0;
127         }
128
129
130         /**
131          * @access private
132          */
133         function addNewAccount() {
134                 global $wgUser, $wgOut, $wgEmailAuthentication;
135
136                 $u = $this->addNewAccountInternal();
137
138                 if ($u == NULL) {
139                         return;
140                 }
141
142                 $wgUser = $u;
143                 $wgUser->setCookies();
144
145                 $wgUser->saveSettings();
146                 if( $wgEmailAuthentication && $wgUser->isValidEmailAddr( $wgUser->getEmail() ) ) {
147                         $wgUser->sendConfirmationMail();
148                 }
149                 
150                 wfRunHooks( 'AddNewAccount' );
151
152                 if( $this->hasSessionCookie() ) {
153                         return $this->successfulLogin( wfMsg( 'welcomecreation', $wgUser->getName() ) );
154                 } else {
155                         return $this->cookieRedirectCheck( 'new' );
156                 }
157         }
158
159         /**
160          * @access private
161          */
162         function addNewAccountInternal() {
163                 global $wgUser, $wgOut;
164                 global $wgUseLatin1, $wgEnableSorbs, $wgProxyWhitelist;
165                 global $wgMemc, $wgAccountCreationThrottle, $wgDBname, $wgIP;
166                 global $wgAuth;
167
168                 // If the user passes an invalid domain, something is fishy
169                 if( !$wgAuth->validDomain( $this->mDomain ) ) {
170                         $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
171                         return false;
172                 }
173
174                 // If we are not allowing users to login locally, we should
175                 // be checking to see if the user is actually able to
176                 // authenticate to the authentication server before they
177                 // create an account (otherwise, they can create a local account
178                 // and login as any domain user). We only need to check this for
179                 // domains that aren't local.
180                 if( 'local' != $this->mDomain && '' != $this->mDomain ) {
181                         if( !$wgAuth->canCreateAccounts() && ( !$wgAuth->userExists( $this->mName ) || !$wgAuth->authenticate( $this->mName, $this->mPassword ) ) ) {
182                                 $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
183                                 return false;
184                         }
185                 }
186
187                 if (!$wgUser->isAllowedToCreateAccount()) {
188                         $this->userNotPrivilegedMessage();
189                         return false;
190                 }
191
192                 if ( $wgEnableSorbs && !in_array( $wgIP, $wgProxyWhitelist ) && 
193                   $wgUser->inSorbsBlacklist( $wgIP ) ) 
194                 {
195                         $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $wgIP ) . ')' );
196                         return;
197                 }
198
199
200                 if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
201                         $this->mainLoginForm( wfMsg( 'badretype' ) );
202                         return false;
203                 }
204                 
205                 $name = trim( $this->mName );
206                 $u = User::newFromName( $name );
207                 if ( is_null( $u ) ) {
208                         $this->mainLoginForm( wfMsg( 'noname' ) );
209                         return false;
210                 }
211                 
212                 if ( wfReadOnly() ) {
213                         $wgOut->readOnlyPage();
214                         return false;
215                 }
216                 
217                 if ( 0 != $u->idForName() ) {
218                         $this->mainLoginForm( wfMsg( 'userexists' ) );
219                         return false;
220                 }
221
222                 if ( !$wgUser->isValidPassword( $this->mPassword ) ) {
223                         $this->mainLoginForm( wfMsg( 'passwordtooshort', $wgMinimalPasswordLength ) );
224                         return false;
225                 }
226
227                 if ( $wgAccountCreationThrottle ) {
228                         $key = $wgDBname.':acctcreate:ip:'.$wgIP;
229                         $value = $wgMemc->incr( $key );
230                         if ( !$value ) {
231                                 $wgMemc->set( $key, 1, 86400 );
232                         }
233                         if ( $value > $wgAccountCreationThrottle ) {
234                                 $this->throttleHit( $wgAccountCreationThrottle );
235                                 return false;
236                         }
237                 }
238
239                 $abortError = '';
240                 if( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError ) ) ) {
241                         wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
242                         $this->mainLoginForm( $abortError );
243                         return false;
244                 }
245
246                 if( !$wgAuth->addUser( $u, $this->mPassword ) ) {
247                         $this->mainLoginForm( wfMsg( 'externaldberror' ) );
248                         return false;
249                 }
250
251                 # Update user count
252                 $ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
253                 $ssUpdate->doUpdate();
254
255                 return $this->initUser( $u );
256         }
257         
258         /**
259          * Actually add a user to the database.
260          * Give it a User object that has been initialised with a name.
261          *
262          * @param User $u
263          * @return User
264          * @access private
265          */
266         function &initUser( &$u ) {
267                 $u->addToDatabase();
268                 $u->setPassword( $this->mPassword );
269                 $u->setEmail( $this->mEmail );
270                 $u->setRealName( $this->mRealName );
271                 $u->setToken();
272                 
273                 global $wgAuth;
274                 $wgAuth->initUser( $u );
275
276                 if ( $this->mRemember ) { $r = 1; }
277                 else { $r = 0; }
278                 $u->setOption( 'rememberpassword', $r );
279                 
280                 return $u;
281         }
282
283         /**
284          * @access private
285          */
286         function processLogin() {
287                 global $wgUser;
288                 global $wgAuth;
289
290                 if ( '' == $this->mName ) {
291                         $this->mainLoginForm( wfMsg( 'noname' ) );
292                         return;
293                 }
294                 $u = User::newFromName( $this->mName );
295                 if( is_null( $u ) ) {
296                         $this->mainLoginForm( wfMsg( 'noname' ) );
297                         return;
298                 }
299                 if ( 0 == $u->getID() ) {
300                         global $wgAuth;
301                         /**
302                          * If the external authentication plugin allows it,
303                          * automatically create a new account for users that
304                          * are externally defined but have not yet logged in.
305                          */
306                         if ( $wgAuth->autoCreate() && $wgAuth->userExists( $u->getName() ) ) {
307                                 if ( $wgAuth->authenticate( $u->getName(), $this->mPassword ) ) {
308                                         $u =& $this->initUser( $u );
309                                 } else {
310                                         $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
311                                         return;
312                                 }
313                         } else {
314                                 $this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName() ) );
315                                 return;
316                         }
317                 } else {
318                         $u->loadFromDatabase();
319                 }
320
321                 if (!$u->checkPassword( $this->mPassword )) {
322                         $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
323                         return;
324                 }
325
326                 # We've verified now, update the real record
327                 #
328                 if ( $this->mRemember ) {
329                         $r = 1;
330                 } else {
331                         $r = 0;
332                 }
333                 $u->setOption( 'rememberpassword', $r );
334
335                 $wgAuth->updateUser( $u );
336
337                 $wgUser = $u;
338                 $wgUser->setCookies();
339
340                 $wgUser->saveSettings();
341                 
342                 if( $this->hasSessionCookie() ) {
343                         return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) );
344                 } else {
345                         return $this->cookieRedirectCheck( 'login' );
346                 }
347         }
348
349         /**
350          * @access private
351          */
352         function mailPassword() {
353                 global $wgUser, $wgDeferredUpdateList, $wgOutputEncoding;
354                 global $wgCookiePath, $wgCookieDomain, $wgDBname;
355
356                 if ( '' == $this->mName ) {
357                         $this->mainLoginForm( wfMsg( 'noname' ) );
358                         return;
359                 }
360                 $u = User::newFromName( $this->mName );
361                 if( is_null( $u ) ) {
362                         $this->mainLoginForm( wfMsg( 'noname' ) );
363                         return;
364                 }
365                 if ( 0 == $u->getID() ) {
366                         $this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName() ) );
367                         return;
368                 }
369
370                 $u->loadFromDatabase();
371
372                 $result = $this->mailPasswordInternal( $u );
373                 if( WikiError::isError( $result ) ) {
374                         $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
375                 } else {
376                         $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ) );
377                 }
378         }
379
380
381         /**
382          * @return mixed true on success, WikiError on failure
383          * @access private
384          */
385         function mailPasswordInternal( $u ) {
386                 global $wgPasswordSender, $wgIP;
387                 global $wgCookiePath, $wgCookieDomain, $wgCookiePrefix;
388
389                 if ( '' == $u->getEmail() ) {
390                         return wfMsg( 'noemail', $u->getName() );
391                 }
392
393                 $np = $u->randomPassword();
394                 $u->setNewpassword( $np );
395
396                 setcookie( "{$wgCookiePrefix}Token", '', time() - 3600, $wgCookiePath, $wgCookieDomain );
397
398                 $u->saveSettings();
399
400                 $ip = $wgIP;
401                 if ( '' == $ip ) { $ip = '(Unknown)'; }
402
403                 $m = wfMsg( 'passwordremindertext', $ip, $u->getName(), $np );
404
405                 $result = $u->sendMail( wfMsg( 'passwordremindertitle' ), $m );
406                 return $result;
407         }
408
409
410         /**
411          * @param string $msg Message that will be shown on success.
412          * @access private
413          */
414         function successfulLogin( $msg ) {
415                 global $wgUser;
416                 global $wgOut;
417
418                 # Run any hooks; ignore results
419                 
420                 wfRunHooks('UserLoginComplete', array(&$wgUser));
421                 
422                 $wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) );
423                 $wgOut->setRobotpolicy( 'noindex,nofollow' );
424                 $wgOut->setArticleRelated( false );
425                 $wgOut->addWikiText( $msg );
426                 $wgOut->returnToMain();
427         }
428
429         /** */
430         function userNotPrivilegedMessage() {
431                 global $wgOut;
432                 
433                 $wgOut->setPageTitle( wfMsg( 'whitelistacctitle' ) );
434                 $wgOut->setRobotpolicy( 'noindex,nofollow' );
435                 $wgOut->setArticleRelated( false );
436
437                 $wgOut->addWikiText( wfMsg( 'whitelistacctext' ) );
438                 
439                 $wgOut->returnToMain( false );
440         }
441
442         /**
443          * @access private
444          */
445         function mainLoginForm( $err ) {
446                 global $wgUser, $wgOut, $wgLang;
447                 global $wgAllowRealName, $wgEnableEmail;
448                 global $wgCookiePrefix;
449                 global $wgAuth;
450
451                 if ( '' == $this->mName ) {
452                         if ( $wgUser->isLoggedIn() ) {
453                                 $this->mName = $wgUser->getName();
454                         } else {
455                                 $this->mName = @$_COOKIE[$wgCookiePrefix.'UserName'];
456                         }
457                 }
458
459                 $q = 'action=submitlogin';
460                 if ( !empty( $this->mReturnto ) ) {
461                         $q .= '&returnto=' . wfUrlencode( $this->mReturnto );
462                 }
463                 $titleObj = Title::makeTitle( NS_SPECIAL, 'Userlogin' );
464
465                 require_once( 'templates/Userlogin.php' );
466                 $template =& new UserloginTemplate();
467                 
468                 $template->set( 'name', $this->mName );
469                 $template->set( 'password', $this->mPassword );
470                 $template->set( 'retype', $this->mRetype );
471                 $template->set( 'email', $this->mEmail );
472                 $template->set( 'realname', $this->mRealName );
473                 $template->set( 'domain', $this->mDomain );
474
475                 $template->set( 'action', $titleObj->getLocalUrl( $q ) );
476                 $template->set( 'error', $err );
477                 $template->set( 'create', $wgUser->isAllowedToCreateAccount() );
478                 $template->set( 'createemail', $wgEnableEmail && $wgUser->isLoggedIn() );
479                 $template->set( 'userealname', $wgAllowRealName );
480                 $template->set( 'useemail', $wgEnableEmail );
481                 $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember  );
482                 $wgAuth->modifyUITemplate( $template );
483                 
484                 $wgOut->setPageTitle( wfMsg( 'userlogin' ) );
485                 $wgOut->setRobotpolicy( 'noindex,nofollow' );
486                 $wgOut->setArticleRelated( false );
487                 $wgOut->addTemplate( $template );
488         }
489
490         /**
491          * @access private
492          */
493         function hasSessionCookie() {
494                 global $wgDisableCookieCheck;
495                 return ( $wgDisableCookieCheck ) ? true : ( isset( $_COOKIE[session_name()] ) );
496         }
497           
498         /**
499          * @access private
500          */
501         function cookieRedirectCheck( $type ) {
502                 global $wgOut, $wgLang;
503
504                 $titleObj = Title::makeTitle( NS_SPECIAL, 'Userlogin' );
505                 $check = $titleObj->getFullURL( 'wpCookieCheck='.$type );
506
507                 return $wgOut->redirect( $check );
508         }
509
510         /**
511          * @access private
512          */
513         function onCookieRedirectCheck( $type ) {
514                 global $wgUser;
515
516                 if ( !$this->hasSessionCookie() ) {
517                         if ( $type == 'new' ) {
518                                 return $this->mainLoginForm( wfMsg( 'nocookiesnew' ) );
519                         } else if ( $type == 'login' ) {
520                                 return $this->mainLoginForm( wfMsg( 'nocookieslogin' ) );
521                         } else {
522                                 # shouldn't happen
523                                 return $this->mainLoginForm( wfMsg( 'error' ) );
524                         }
525                 } else {
526                         return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) );
527                 }
528         }
529
530         /**
531          * @access private
532          */
533         function throttleHit( $limit ) {
534                 global $wgOut;
535
536                 $wgOut->addWikiText( wfMsg( 'acct_creation_throttle_hit', $limit ) );
537         }
538 }
539 ?>