Index: trunk/extensions/CentralAuth/CentralAuthUser.php |
— | — | @@ -60,12 +60,12 @@ |
61 | 61 | private function loadState() { |
62 | 62 | if( !isset( $this->mGlobalId ) ) { |
63 | 63 | global $wgDBname; |
64 | | - $dbr = self::getCentralDB(); |
| 64 | + $dbr = self::getCentralSlaveDB(); |
65 | 65 | $globaluser = self::tableName( 'globaluser' ); |
66 | 66 | $localuser = self::tableName( 'localuser' ); |
67 | 67 | |
68 | 68 | $sql = |
69 | | - "SELECT gu_id, lu_dbname |
| 69 | + "SELECT gu_id, lu_dbname, gu_salt, gu_password,gu_authtoken,gu_locked,gu_hidden,gu_registration |
70 | 70 | FROM $globaluser |
71 | 71 | LEFT OUTER JOIN $localuser |
72 | 72 | ON gu_name=lu_name |
— | — | @@ -78,6 +78,12 @@ |
79 | 79 | if( $row ) { |
80 | 80 | $this->mGlobalId = intval( $row->gu_id ); |
81 | 81 | $this->mIsAttached = ($row->lu_dbname !== null); |
| 82 | + $this->mSalt = $row->gu_salt; |
| 83 | + $this->mPassword = $row->gu_password; |
| 84 | + $this->mAuthToken = $row->gu_authtoken; |
| 85 | + $this->mLocked = $row->gu_locked; |
| 86 | + $this->mHidden = $row->gu_hidden; |
| 87 | + $this->mRegistration = $row->gu_registration; |
82 | 88 | } else { |
83 | 89 | $this->mGlobalId = 0; |
84 | 90 | $this->mIsAttached = false; |
— | — | @@ -100,6 +106,27 @@ |
101 | 107 | $this->loadState(); |
102 | 108 | return $this->mIsAttached; |
103 | 109 | } |
| 110 | + |
| 111 | + /** |
| 112 | + * Return the password hash and salt. |
| 113 | + * @return array( salt, hash ) |
| 114 | + */ |
| 115 | + public function getPasswordHash() { |
| 116 | + $this->loadState(); |
| 117 | + return array( $this->mSalt, $this->mPassword ); |
| 118 | + } |
| 119 | + |
| 120 | + /** |
| 121 | + * Return the global-login token for this account. |
| 122 | + */ |
| 123 | + public function getAuthToken() { |
| 124 | + $this->loadState(); |
| 125 | + |
| 126 | + if (!$this->mAuthToken) { |
| 127 | + $this->resetAuthToken(); |
| 128 | + } |
| 129 | + return $this->mAuthToken; |
| 130 | + } |
104 | 131 | |
105 | 132 | /** |
106 | 133 | * Check whether a global user account for this name exists yet. |
— | — | @@ -116,41 +143,27 @@ |
117 | 144 | } |
118 | 145 | |
119 | 146 | /** |
120 | | - * Lazy-load misc properties that may be used at times |
121 | | - */ |
122 | | - private function loadProperties() { |
123 | | - if( !isset( $this->mProperties ) ) { |
124 | | - $dbw = self::getCentralDB(); |
125 | | - $row = $dbw->selectRow( self::tableName( 'globaluser' ), |
126 | | - array( 'gu_locked', 'gu_hidden', 'gu_registration' ), |
127 | | - array( 'gu_name' => $this->mName ), |
128 | | - __METHOD__ ); |
129 | | - $this->mProperties = $row; |
130 | | - } |
131 | | - } |
132 | | - |
133 | | - /** |
134 | 147 | * @return bool |
135 | 148 | */ |
136 | 149 | public function isLocked() { |
137 | | - $this->loadProperties(); |
138 | | - return (bool)$this->mProperties->gu_locked; |
| 150 | + $this->loadState(); |
| 151 | + return (bool)$this->mLocked; |
139 | 152 | } |
140 | 153 | |
141 | 154 | /** |
142 | | - * @return bool |
| 155 | + * @return bool |
143 | 156 | */ |
144 | 157 | public function isHidden() { |
145 | | - $this->loadProperties(); |
146 | | - return (bool)$this->mProperties->gu_hidden; |
| 158 | + $this->loadState(); |
| 159 | + return (bool)$this->mHidden; |
147 | 160 | } |
148 | 161 | |
149 | 162 | /** |
150 | 163 | * @return string timestamp |
151 | 164 | */ |
152 | 165 | public function getRegistration() { |
153 | | - $this->loadProperties(); |
154 | | - return wfTimestamp( TS_MW, $this->mProperties->gu_registration ); |
| 166 | + $this->loadState(); |
| 167 | + return wfTimestamp( TS_MW, $this->mRegistration ); |
155 | 168 | } |
156 | 169 | |
157 | 170 | private function lazyMigrate() { |
— | — | @@ -677,38 +690,46 @@ |
678 | 691 | $this->resetState(); |
679 | 692 | } |
680 | 693 | } |
681 | | - |
| 694 | + |
682 | 695 | /** |
683 | | - * Attempt to authenticate the global user account with the given password |
684 | | - * @param string $password |
685 | | - * @return string status, one of: "ok", "no user", "locked", or "bad password". |
686 | | - * @todo Currently only the "ok" result is used (i.e. either use, or return a bool). |
| 696 | + * If the user provides the correct password, would we let them log in? |
| 697 | + * This encompasses checks on missing and locked accounts, at present. |
| 698 | + * @return string status, one of: "no user", "locked" |
687 | 699 | */ |
688 | | - public function authenticate( $password ) { |
| 700 | + public function canAuthenticate() { |
689 | 701 | $this->lazyMigrate(); |
690 | 702 | |
691 | | - $dbw = self::getCentralDB(); |
692 | | - $row = $dbw->selectRow( self::tableName( 'globaluser' ), |
693 | | - array( 'gu_salt', 'gu_password', 'gu_locked' ), |
694 | | - array( 'gu_id' => $this->getId() ), |
695 | | - __METHOD__ ); |
696 | | - |
697 | | - if( !$row ) { |
| 703 | + if( !$this->getId() ) { |
698 | 704 | wfDebugLog( 'CentralAuth', |
699 | 705 | "authentication for '$this->mName' failed due to missing account" ); |
700 | 706 | return "no user"; |
701 | 707 | } |
702 | 708 | |
703 | | - $salt = $row->gu_salt; |
704 | | - $crypt = $row->gu_password; |
705 | | - $locked = $row->gu_locked; |
| 709 | + list($salt,$crypt) = $this->getPasswordHash(); |
| 710 | + $locked = $this->isLocked(); |
706 | 711 | |
707 | 712 | if( $locked ) { |
708 | 713 | wfDebugLog( 'CentralAuth', |
709 | 714 | "authentication for '$this->mName' failed due to lock" ); |
710 | 715 | return "locked"; |
711 | 716 | } |
| 717 | + |
| 718 | + return true; |
| 719 | + } |
712 | 720 | |
| 721 | + /** |
| 722 | + * Attempt to authenticate the global user account with the given password |
| 723 | + * @param string $password |
| 724 | + * @return string status, one of: "ok", "no user", "locked", or "bad password". |
| 725 | + * @todo Currently only the "ok" result is used (i.e. either use, or return a bool). |
| 726 | + */ |
| 727 | + public function authenticate( $password ) { |
| 728 | + if (($ret = $this->canAuthenticate()) !== true) { |
| 729 | + return $ret; |
| 730 | + } |
| 731 | + |
| 732 | + list( $salt, $crypt ) = $this->getPasswordHash(); |
| 733 | + |
713 | 734 | if( $this->matchHash( $password, $salt, $crypt ) ) { |
714 | 735 | wfDebugLog( 'CentralAuth', |
715 | 736 | "authentication for '$this->mName' succeeded" ); |
— | — | @@ -719,6 +740,23 @@ |
720 | 741 | return "bad password"; |
721 | 742 | } |
722 | 743 | } |
| 744 | + |
| 745 | + /** |
| 746 | + * Attempt to authenticate the global user account with the given global authtoken |
| 747 | + * @param string $token |
| 748 | + * @return string status, one of: "ok", "no user", "locked", or "bad token" |
| 749 | + */ |
| 750 | + public function authenticateWithToken( $token ) { |
| 751 | + if (($ret = $this->canAuthenticate()) !== true) { |
| 752 | + return $ret; |
| 753 | + } |
| 754 | + |
| 755 | + if ($this->validateAuthToken( $token ) ) { |
| 756 | + return "ok"; |
| 757 | + } else { |
| 758 | + return "bad token"; |
| 759 | + } |
| 760 | + } |
723 | 761 | |
724 | 762 | /** |
725 | 763 | * @param $plaintext User-provided password plaintext. |
— | — | @@ -1095,7 +1133,78 @@ |
1096 | 1134 | |
1097 | 1135 | wfDebugLog( 'CentralAuth', |
1098 | 1136 | "Set global password for '$this->mName'" ); |
| 1137 | + |
| 1138 | + // Reset the auth token. |
| 1139 | + $this->resetAuthToken(); |
| 1140 | + $this->setGlobalCookies(); |
1099 | 1141 | return true; |
1100 | 1142 | } |
1101 | 1143 | |
| 1144 | + /** |
| 1145 | + * Set a global cookie that auto-authenticates the user on other wikis |
| 1146 | + * Called on login. |
| 1147 | + */ |
| 1148 | + function setGlobalCookies($localUser) { |
| 1149 | + global $wgCentralAuthCookiePrefix,$wgCentralAuthCookieDomain,$wgCookieSecure,$wgCookieExpiration; |
| 1150 | + |
| 1151 | + $exp = time() + $wgCookieExpiration; |
| 1152 | + |
| 1153 | + $global_session = array(); |
| 1154 | + |
| 1155 | + $global_session['user'] = $this->mName; |
| 1156 | + setcookie( $wgCentralAuthCookiePrefix.'User', $this->mName, $exp, '/', $wgCentralAuthCookieDomain, $wgCookieSecure ); |
| 1157 | + $global_session['token'] = $this->getAuthToken(); |
| 1158 | + $global_session['expiry'] = time() + 86400; |
| 1159 | + |
| 1160 | + if ($localUser->getOption('rememberpassword') == 1) { |
| 1161 | + setcookie( $wgCentralAuthCookiePrefix.'Token', $this->getAuthToken(), $exp, '/', $wgCentralAuthCookieDomain, $wgCookieSecure ); |
| 1162 | + } else { |
| 1163 | + setcookie( $wgCentralAuthCookiePrefix.'Token', '', time() - 86400 ); |
| 1164 | + } |
| 1165 | + |
| 1166 | + // Make up a session id. |
| 1167 | + $session_id = md5( $exp . mt_rand( 0, 0x7fffffff ) . $this->getId() ); |
| 1168 | + // Store the session in memcached |
| 1169 | + global $wgMemc; |
| 1170 | + $wgMemc->set( 'centralauth_session_'.$session_id, serialize($global_session), 86400 ); |
| 1171 | + |
| 1172 | + setcookie( $wgCentralAuthCookiePrefix.'Session', $session_id, time() + 86400, '/', $wgCentralAuthCookieDomain, $wgCookieSecure ); |
| 1173 | + } |
| 1174 | + |
| 1175 | + /** |
| 1176 | + * Delete global cookies which auto-authenticate the user on other wikis. |
| 1177 | + * Called on logout. |
| 1178 | + */ |
| 1179 | + function deleteGlobalCookies() { |
| 1180 | + global $wgCentralAuthCookiePrefix,$wgCentralAuthCookieDomain,$wgCookieSecure; |
| 1181 | + |
| 1182 | + $exp = time() - 86400; |
| 1183 | + |
| 1184 | + setcookie( $wgCentralAuthCookiePrefix.'User', '', $exp, '/', $wgCentralAuthCookieDomain, $wgCookieSecure ); |
| 1185 | + setcookie( $wgCentralAuthCookiePrefix.'Token', '', $exp, '/', $wgCentralAuthCookieDomain, $wgCookieSecure ); |
| 1186 | + setcookie( $wgCentralAuthCookiePrefix.'Session', '', $exp, '/', $wgCentralAuthCookieDomain, $wgCookieSecure ); |
| 1187 | + |
| 1188 | + $this->resetAuthToken(); |
| 1189 | + } |
| 1190 | + |
| 1191 | + /** |
| 1192 | + * Check a global auth token against the one we know of in the database. |
| 1193 | + */ |
| 1194 | + function validateAuthToken( $token ) { |
| 1195 | + return ($token == $this->getAuthToken()); |
| 1196 | + } |
| 1197 | + |
| 1198 | + /** |
| 1199 | + * Generate a new random auth token, and store it in the database. |
| 1200 | + * Should be called as often as possible, to the extent that it will |
| 1201 | + * not randomly log users out (so on logout, as is done currently, is a good time). |
| 1202 | + */ |
| 1203 | + function resetAuthToken() { |
| 1204 | + // Generate a random token. |
| 1205 | + $this->mAuthToken = md5( mt_rand( 0, 0x7fffffff ) . $this->getId() ); |
| 1206 | + |
| 1207 | + // Save it. |
| 1208 | + $dbw = self::getCentralDB(); |
| 1209 | + $dbw->update( self::tableName( 'globaluser' ), array( 'gu_authtoken' => $this->mAuthToken ), array( 'gu_id' => $this->getId() ), __METHOD__ ); |
| 1210 | + } |
1102 | 1211 | } |
Index: trunk/extensions/CentralAuth/CentralAuth.php |
— | — | @@ -38,6 +38,27 @@ |
39 | 39 | */ |
40 | 40 | $wgCentralAuthDryRun = false; |
41 | 41 | |
| 42 | +/** |
| 43 | + * Domain to set global cookies for. |
| 44 | + */ |
| 45 | +$wgCentralAuthCookieDomains = $wgServer; |
| 46 | + |
| 47 | +/** |
| 48 | + * Prefix for CentralAuth cookies. |
| 49 | + */ |
| 50 | +$wgCentralAuthCookiePrefix = 'centralauth_'; |
| 51 | + |
| 52 | +/** |
| 53 | + * Wikis to automatically log into when this one is logged into. |
| 54 | + * Done by loading a 1x1 image from Special:AutoLogin on that wiki. |
| 55 | + */ |
| 56 | +$wgCentralAuthAutoLoginWikis = array(); |
| 57 | + |
| 58 | +/** |
| 59 | + * Prefix for CentralAuth global auto-authentication cookies |
| 60 | + */ |
| 61 | + $wgCentralAuthCookiePrefix = 'centralauth'; |
| 62 | + |
42 | 63 | $wgExtensionCredits['specialpage'][] = array( |
43 | 64 | 'name' => 'Central Auth', |
44 | 65 | 'url' => 'http://www.mediawiki.org/wiki/Extension:CentralAuth', |
— | — | @@ -57,12 +78,17 @@ |
58 | 79 | $wgAutoloadClasses['CentralAuthPlugin'] = "$caBase/CentralAuthPlugin.php"; |
59 | 80 | $wgAutoloadClasses['WikiMap'] = "$caBase/WikiMap.php"; |
60 | 81 | $wgAutoloadClasses['WikiReference'] = "$caBase/WikiMap.php"; |
| 82 | +$wgAutoloadClasses['SpecialAutoLogin'] = "$caBase/SpecialAutoLogin.php"; |
61 | 83 | $wgExtensionMessagesFiles['SpecialCentralAuth'] = "$caBase/CentralAuth.i18n.php"; |
62 | 84 | |
63 | 85 | $wgHooks['AuthPluginSetup'][] = 'wfSetupCentralAuthPlugin'; |
64 | 86 | $wgHooks['AddNewAccount'][] = 'wfCentralAuthAddNewAccount'; |
65 | 87 | $wgHooks['PreferencesUserInformationPanel'][] = 'wfCentralAuthInformationPanel'; |
66 | 88 | $wgHooks['AbortNewAccount'][] = 'wfCentralAuthAbortNewAccount'; |
| 89 | +$wgHooks['UserLoginComplete'][] = 'wfCentralAuthUserLoginComplete'; |
| 90 | +$wgHooks['AutoAuthenticate'][] = 'wfCentralAuthAutoAuthenticate'; |
| 91 | +$wgHooks['UserLogout'][] = 'wfCentralAuthLogout'; |
| 92 | +$wgHooks['UserLogoutComplete'][] = 'wfCentralAuthLogoutComplete'; |
67 | 93 | |
68 | 94 | // For interaction with the Special:Renameuser extension |
69 | 95 | $wgHooks['RenameUserAbort'][] = 'wfCentralAuthRenameUserAbort'; |
— | — | @@ -72,6 +98,7 @@ |
73 | 99 | $wgGroupPermissions['*']['centralauth-merge'] = true; |
74 | 100 | |
75 | 101 | $wgSpecialPages['CentralAuth'] = 'SpecialCentralAuth'; |
| 102 | +$wgSpecialPages['AutoLogin'] = 'SpecialAutoLogin'; |
76 | 103 | $wgSpecialPages['MergeAccount'] = 'SpecialMergeAccount'; |
77 | 104 | |
78 | 105 | function wfSetupCentralAuthPlugin( &$auth ) { |
— | — | @@ -199,3 +226,107 @@ |
200 | 227 | return true; |
201 | 228 | } |
202 | 229 | |
| 230 | +function wfCentralAuthUserLoginComplete( &$user, &$inject_html ) { |
| 231 | + $centralUser = new CentralAuthUser( $user->getName() ); |
| 232 | + |
| 233 | + if ($centralUser->exists()) { |
| 234 | + $centralUser->setGlobalCookies($user); |
| 235 | + } else { |
| 236 | + return; |
| 237 | + } |
| 238 | + |
| 239 | + // On other wikis |
| 240 | + global $wgCentralAuthAutoLoginWikis; |
| 241 | + |
| 242 | + $inject_html .= Xml::openElement( 'p' ); |
| 243 | + |
| 244 | + foreach( $wgCentralAuthAutoLoginWikis as $dbname ) { |
| 245 | + $wiki = WikiMap::byDatabase( $dbname ); |
| 246 | + $url = $wiki->getUrl( 'Special:AutoLogin' ); |
| 247 | + |
| 248 | + $querystring = 'user=' . urlencode( $user->getName() ); |
| 249 | + $querystring .= '&token=' . $centralUser->getAuthToken(); |
| 250 | + $querystring .= '&remember=' . $user->getOption( 'rememberpassword' ); |
| 251 | + |
| 252 | + if (strpos($url, '?') > 0) { |
| 253 | + $url .= "&$querystring"; |
| 254 | + } else { |
| 255 | + $url .= "?$querystring"; |
| 256 | + } |
| 257 | + |
| 258 | + $inject_html .= Xml::element( 'img', array( 'src' => $url ) ); |
| 259 | + } |
| 260 | + |
| 261 | + $inject_html .= Xml::closeElement( 'p' ); |
| 262 | + |
| 263 | + return true; |
| 264 | +} |
| 265 | + |
| 266 | +function wfCentralAuthAutoAuthenticate( &$user ) { |
| 267 | + global $wgCentralAuthCookiePrefix; |
| 268 | + $prefix = $wgCentralAuthCookiePrefix; |
| 269 | + |
| 270 | + if (isset($_COOKIE["{$prefix}User"]) && isset($_COOKIE["{$prefix}Token"])) { |
| 271 | + list ($username, $token) = array( $_COOKIE["{$prefix}User"], $_COOKIE["{$prefix}Token"] ); |
| 272 | + $centralUser = new CentralAuthUser( $username ); |
| 273 | + |
| 274 | + if ($centralUser->authenticateWithToken( $token ) == 'ok' && $centralUser->isAttached()) { |
| 275 | + // Auth OK. |
| 276 | + $user = User::newFromName( $username ); |
| 277 | + } |
| 278 | + } elseif (isset($_COOKIE["{$prefix}Session"])) { |
| 279 | + $session_id = $_COOKIE["{$prefix}Session"]; |
| 280 | + |
| 281 | + global $wgMemc; |
| 282 | + $global_session = unserialize($wgMemc->get( "centralauth_session_$session_id" )); |
| 283 | + |
| 284 | + $token = $global_session['token']; |
| 285 | + $username = $global_session['user']; |
| 286 | + |
| 287 | + if ($global_session['expiry'] < time()) { |
| 288 | + return true; // Session has expired. Don't let it be logged-in with. |
| 289 | + } |
| 290 | + |
| 291 | + $centralUser = new CentralAuthUser( $username ); |
| 292 | + |
| 293 | + if ($centralUser->authenticateWithToken( $token ) == 'ok' && $centralUser->isAttached()) { |
| 294 | + // Auth OK. |
| 295 | + $user = User::newFromName( $username ); |
| 296 | + } |
| 297 | + } |
| 298 | + |
| 299 | + return true; |
| 300 | +} |
| 301 | + |
| 302 | +function wfCentralAuthLogout( &$user ) { |
| 303 | + $centralUser = new CentralAuthUser( $user->getName() ); |
| 304 | + |
| 305 | + if ($centralUser->exists()) { |
| 306 | + $centralUser->deleteGlobalCookies(); |
| 307 | + } |
| 308 | + |
| 309 | + return true; |
| 310 | +} |
| 311 | + |
| 312 | +function wfCentralAuthLogoutComplete( &$user, &$inject_html ) { |
| 313 | + // Generate the images |
| 314 | + global $wgCentralAuthAutoLoginWikis; |
| 315 | + |
| 316 | + $inject_html .= Xml::openElement( 'p' ); |
| 317 | + |
| 318 | + foreach( $wgCentralAuthAutoLoginWikis as $dbname ) { |
| 319 | + $wiki = WikiMap::byDatabase( $dbname ); |
| 320 | + $url = $wiki->getUrl( 'Special:AutoLogin' ); |
| 321 | + |
| 322 | + if (strpos($url, '?') > 0) { |
| 323 | + $url .= '&logout=1'; |
| 324 | + } else { |
| 325 | + $url .= '?logout=1'; |
| 326 | + } |
| 327 | + |
| 328 | + $inject_html .= Xml::element( 'img', array( 'src' => $url, alt => '' ) ); |
| 329 | + } |
| 330 | + |
| 331 | + $inject_html .= Xml::closeElement( 'p' ); |
| 332 | + return true; |
| 333 | +} |
\ No newline at end of file |
Index: trunk/extensions/CentralAuth/central-auth.sql |
— | — | @@ -80,6 +80,9 @@ |
81 | 81 | -- Random key for password resets |
82 | 82 | gu_password_reset_key tinyblob, |
83 | 83 | gu_password_reset_expiration varchar(14) binary, |
| 84 | + |
| 85 | + -- Random key for crosswiki authentication tokens |
| 86 | + gu_auth_token varchar(32) binary, |
84 | 87 | |
85 | 88 | primary key (gu_id), |
86 | 89 | unique key (gu_name), |
Index: trunk/extensions/CentralAuth/SpecialAutoLogin.php |
— | — | @@ -0,0 +1,59 @@ |
| 2 | +<? |
| 3 | +if (!defined('MEDIAWIKI')) { |
| 4 | + die('CentralAuth'); |
| 5 | +} |
| 6 | + |
| 7 | +/** |
| 8 | + * Unlisted Special page to set requisite cookies for being logged into this wiki. |
| 9 | + * |
| 10 | + * @addtogroup Extensions |
| 11 | + */ |
| 12 | + |
| 13 | + global $IP; |
| 14 | + |
| 15 | +require_once( "$IP/includes/StreamFile.php" ); |
| 16 | + |
| 17 | +class SpecialAutoLogin extends UnlistedSpecialPage |
| 18 | +{ |
| 19 | + function SpecialAutoLogin() { |
| 20 | + SpecialPage::SpecialPage('AutoLogin'); |
| 21 | + } |
| 22 | + |
| 23 | + function execute() { |
| 24 | + global $wgRequest,$wgOut,$wgUser; |
| 25 | + |
| 26 | + $username = $wgRequest->getVal( 'user' ); |
| 27 | + $token = $wgRequest->getVal('token'); |
| 28 | + $remember = $wgRequest->getBool( 'remember' ); |
| 29 | + $logout = $wgRequest->getBool( 'logout' ); |
| 30 | + |
| 31 | + if ((strlen($username) == 0 || strlen($token) == 0) && !$logout) { |
| 32 | + $wgOut->addWikitext( 'AutoLogin' ); |
| 33 | + return; |
| 34 | + } |
| 35 | + |
| 36 | + if ($logout == true) { |
| 37 | + $centralUser = new CentralAuthUser( $wgUser->getName() ); |
| 38 | + |
| 39 | + if ($centralUser->getId) { |
| 40 | + $centralUser->deleteGlobalCookies(); |
| 41 | + } |
| 42 | + } else { |
| 43 | + $centralUser = new CentralAuthUser( $username ); |
| 44 | + |
| 45 | + $login_result = $centralUser->authenticateWithToken( $token ); |
| 46 | + |
| 47 | + if ($login_result == 'ok' && $centralUser->isAttached()) { |
| 48 | + // Auth OK. |
| 49 | + $user = User::newFromName( $username ); |
| 50 | + $user->setOption( 'rememberpassword', $remember ); |
| 51 | + |
| 52 | + $centralUser->setGlobalCookies($user); |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + wfStreamFile( dirname(__FILE__).'/1x1.png' ); |
| 57 | + |
| 58 | + $wgOut->disable(); |
| 59 | + } |
| 60 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/CentralAuth/SpecialAutoLogin.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 61 | + native |
Index: trunk/extensions/CentralAuth/1x1.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/CentralAuth/1x1.png |
___________________________________________________________________ |
Added: svn:mime-type |
2 | 62 | + image/png |