private static function validateOption($name, &$value) { $listSchema = (include __DIR__ . '/CollaborationListContentSchema.php'); // Special handling for DISPLAYMODE if ($name == 'DISPLAYMODE') { if ($value == 'members' || $value == 'normal' || $value == 'error') { return true; } return false; } // Force intrepretation as boolean for certain options if ($name == "includedesc") { $value = (bool) $value; } // Set up a dummy CollaborationListContent array featuring the options being validated $toValidate = ['displaymode' => 'normal', 'description' => '', 'columns' => [], 'options' => [$name => $value]]; return EventLogging::schemaValidate($toValidate, $listSchema); }
/** * Decode and validate the contents * @return bool Whether the contents are valid */ public function isValid() { $hubSchema = (include __DIR__ . '/CollaborationHubContentSchema.php'); $jsonParse = $this->getData(); if ($jsonParse->isGood()) { // TODO: The schema should be checking for required fields but for some reason that doesn't work if (!isset($jsonParse->value->content)) { return false; } // Forcing the object to become an array $jsonAsArray = json_decode(json_encode($jsonParse->getValue()), true); try { EventLogging::schemaValidate($jsonAsArray, $hubSchema); return true; } catch (JsonSchemaException $e) { return false; } return false; } return false; }
/** * Uses EventLogging when available to record an event on server side * * @param string $schema The name of the schema * @param int $revision The revision of the schema * @param array $data The data to be recorded against the schema */ public static function eventLog($schema, $revision, $data) { if (is_callable('EventLogging::logEvent')) { EventLogging::logEvent($schema, $revision, $data); } }
/** * Log stuff to EventLogging's Schema:Edit - see https://meta.wikimedia.org/wiki/Schema:Edit * If you don't have EventLogging installed, does nothing. * * @param string $action * @param Article $article Which article (with full context, page, title, etc.) * @param array $data Data to log for this action * @return bool Whether the event was logged or not. */ public static function doEventLogging($action, $article, $data = array()) { global $wgVersion; if (!class_exists('EventLogging')) { return false; } // Sample 6.25% (via hex digit) if ($data['editingSessionId'][0] > '0') { return false; } $user = $article->getContext()->getUser(); $page = $article->getPage(); $title = $article->getTitle(); $data = array('action' => $action, 'version' => 1, 'editor' => 'wikitext', 'platform' => 'desktop', 'integration' => 'page', 'page.id' => $page->getId(), 'page.title' => $title->getPrefixedText(), 'page.ns' => $title->getNamespace(), 'page.revid' => $page->getRevision() ? $page->getRevision()->getId() : 0, 'user.id' => $user->getId(), 'user.editCount' => $user->getEditCount() ?: 0, 'mediawiki.version' => $wgVersion) + $data; if ($user->isAnon()) { $data['user.class'] = 'IP'; } return EventLogging::logEvent('Edit', 13457736, $data); }
public function quickContextFilters($pString) { if (empty($pString)) { return 0; } $myCounter = 0; $myList = preg_split('/\\s+/', $pString, -1, PREG_SPLIT_NO_EMPTY); foreach ($myList as $myItem) { if (preg_match('/^([^()]+)\\(([^()]+)\\)$/', $myItem, $myMatches)) { $myContext = $myMatches[1]; $myOverride = $myMatches[2]; $filter = array(); if (strpos($myContext, '::') !== false) { // class $tmp = explode('::', $myContext, 2); $filter['class'] = trim($tmp[0]); if (preg_match('/\\S/', $tmp[1])) { $filter['function'] = trim($tmp[1]); } $filter['effectiveLevel'] = trim($myOverride); } elseif (strpos($myContext, '~') !== false) { // message match $tmp = explode('~', $myContext, 2); $filter['matchlevel'] = trim($tmp[0]); $filter['matchpattern'] = trim($tmp[1]); $filter['effectiveLevel'] = trim($myOverride); } elseif (strpos($myContext, '/') !== false) { // file $filter['file'] = trim($myContext); $filter['effectiveLevel'] = trim($myOverride); } else { // function $filter['function'] = trim($myContext); $filter['effectiveLevel'] = trim($myOverride); } if (EventObject::stClassifyErrorType($myOverride)) { EventLogging::stAddContextFilter($filter); $myCounter++; } } } return $myCounter; }
/** * @param &$out OutputPage * @param &$skin Skin * @return bool * @todo Add 1x1 images somewhere besides page content */ static function onBeforePageDisplay(&$out, &$skin) { global $wgCentralAuthLoginWiki, $wgCentralAuthUseEventLogging; if ($out->getUser()->isAnon()) { if ($wgCentralAuthLoginWiki && wfWikiID() !== $wgCentralAuthLoginWiki) { $out->addModules('ext.centralauth.centralautologin'); // For non-JS clients. Use WikiMap to avoid localization of the // 'Special' namespace, see bug 54195. $wiki = WikiMap::getWiki(wfWikiID()); $params = array('type' => '1x1'); if (self::isMobileDomain()) { $params['mobile'] = 1; } $url = wfAppendQuery($wiki->getFullUrl('Special:CentralAutoLogin/start'), $params); $out->addHTML('<noscript>' . Xml::element('img', array('src' => $url, 'alt' => '', 'title' => '', 'width' => 1, 'height' => 1, 'style' => 'border: none; position: absolute;')) . '</noscript>'); } } else { $centralUser = CentralAuthUser::getInstance($out->getUser()); if ($centralUser->exists() && $centralUser->isAttached()) { $out->addModules('ext.centralauth.centralautologin.clearcookie'); } if ($out->getRequest()->getSessionData('CentralAuthDoEdgeLogin')) { $out->getRequest()->setSessionData('CentralAuthDoEdgeLogin', null); $out->addHTML(self::getEdgeLoginHTML()); if ($wgCentralAuthUseEventLogging) { // Need to correlate user_id across wikis EventLogging::logEvent('CentralAuth', 5690875, array('version' => 1, 'userId' => $centralUser->getId(), 'action' => 'sul2-autologin-login')); } } } return true; }
} // Get information about user $myCurrentUser = User::getCurrentUser(); if (empty($myCurrentUser)) { $myUserName = '******'; } else { $myUserName = $myCurrentUser->getUsername(); } $string = "{$dt} " . EventObject::PrettyErrorType($event->getLayoutType()) . " >{$myNetworkName} >{$myUserName}@{$myNodeName} [" . $_SERVER['REQUEST_URI'] . "]" . ": " . $event->getMessage() . (!empty($myFilename) ? " in {$myFilename}" . (!empty($myLinenum) ? " on line {$myLinenum}" : "") : "") . "\n"; if ($event->classifyErrorType() == 'error') { $string .= " Stack Backtrace\n" . self::FormatBacktrace($event->getContext()) . "\n"; } return $string; } } $myLogfile = !defined('WIFIDOG_LOGFILE') ? "tmp/wifidog.log" : constant('WIFIDOG_LOGFILE'); if (!empty($myLogfile)) { if (substr($myLogfile, 0, 1) != '/') { $myLogfile = WIFIDOG_ABS_FILE_PATH . $myLogfile; } EventLogging::stAddChannel(new FileChannel($myLogfile, new WifidogSyslogFormatter(), 'warning,notice'), 'logfile'); } // trigger_error("here i am", E_USER_NOTICE); } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * c-hanging-comment-ender-p: nil * End: */
function execute($par) { global $wgMemc, $wgCentralAuthLoginWiki; $request = $this->getRequest(); $this->loginWiki = $wgCentralAuthLoginWiki; if (!$this->loginWiki) { // Ugh, no central wiki. If we're coming from an edge login, make // the logged-into wiki the de-facto central wiki for this request // so auto-login still works. $fromwiki = $request->getVal('from', $request->getVal('notifywiki')); if ($fromwiki !== null && WikiMap::getWiki($fromwiki)) { $this->loginWiki = $fromwiki; } } elseif ($request->getVal('from') === wfWikiId() && $wgCentralAuthLoginWiki !== wfWikiId()) { // Remote wiki must not have wgCentralAuthLoginWiki set, but we do. Redirect them. $this->do302Redirect($wgCentralAuthLoginWiki, $par, $request->getValues()); return; } $params = $request->getValues('type', 'from', 'return', 'returnto', 'returntoquery', 'proto', 'mobile'); switch (strval($par)) { case 'P3P': // Explain the bogus P3P header $this->setHeaders(); $this->getOutput()->addWikiMsg('centralauth-centralautologin-p3p-explanation'); return; case 'toolslist': // Do not cache this, we want updated Echo numbers and such. $this->getOutput()->enableClientCache(false); $user = $this->getUser(); if (!$user->isAnon()) { if (!CentralAuthHooks::isUIReloadRecommended($user)) { $html = $this->getSkin()->getPersonalToolsList(); $json = FormatJSON::encode(array('toolslist' => $html)); } else { $gender = $this->getUser()->getOption('gender'); if (strval($gender) === '') { $gender = 'unknown'; } $json = FormatJSON::encode(array('notify' => array('username' => $user->getName(), 'gender' => $gender))); } $this->doFinalOutput(true, 'OK', $json, 'json'); } else { $this->doFinalOutput(false, 'Not logged in', '', 'json'); } return; case 'refreshCookies': // Refresh central cookies (e.g. in case 'remember me' was set) // Do not cache this, we need to reset the cookies every time. $this->getOutput()->enableClientCache(false); if (!$wgCentralAuthLoginWiki || !$this->checkIsCentralWiki($wikiid)) { return; } CentralAuthUser::setP3P(); $centralUser = CentralAuthUser::getInstance($this->getUser()); if ($centralUser && $centralUser->getId()) { $centralSession = $this->getCentralSession($centralUser, $this->getUser()); // Refresh 'remember me' preference $remember = (bool) $centralSession['remember']; if ($remember != $this->getUser()->getBoolOption('rememberpassword')) { $this->getUser()->setOption('rememberpassword', $remember ? 1 : 0); $this->getUser()->saveSettings(); } $secureCookie = $centralSession['secureCookies']; $centralUser->setGlobalCookies($remember, false, $secureCookie, $centralSession); $this->doFinalOutput(true, 'success'); } else { $this->doFinalOutput(false, 'Not logged in'); } return; case 'deleteCookies': // Delete central cookies // Do not cache this, we need to reset the cookies every time. $this->getOutput()->enableClientCache(false); if ($this->getUser()->isLoggedIn()) { $this->doFinalOutput(false, 'Cannot delete cookies while still logged in'); return; } CentralAuthUser::setP3P(); CentralAuthUser::deleteGlobalCookies(); $this->doFinalOutput(true, 'success'); return; case 'start': // Main entry point // Note this is safe to cache, because the cache already varies on // the session cookies. $this->getOutput()->setSquidMaxage(1200); if (!$this->checkIsLocalWiki()) { return; } CentralAuthUser::setP3P(); $this->do302Redirect($this->loginWiki, 'checkLoggedIn', array('wikiid' => wfWikiID(), 'proto' => $request->detectProtocol()) + $params); return; case 'checkLoggedIn': // Check if we're logged in centrally // Note this is safe to cache, because the cache already varies on // the session cookies. $this->getOutput()->setSquidMaxage(1200); if (!$this->checkIsCentralWiki($wikiid)) { return; } CentralAuthUser::setP3P(); if ($this->getUser()->isLoggedIn()) { $centralUser = CentralAuthUser::getInstance($this->getUser()); } else { $this->doFinalOutput(false, 'Not centrally logged in', self::getInlineScript('anon-set.js')); return; } // We're pretty sure this user is logged in, so pass back // headers to prevent caching, just in case $this->getOutput()->enableClientCache(false); $memcData = array('gu_id' => $centralUser->getId()); $token = MWCryptRand::generateHex(32); $key = CentralAuthUser::memcKey('centralautologin-token', $token); $wgMemc->set($key, $memcData, 60); $this->do302Redirect($wikiid, 'createSession', array('token' => $token) + $params); return; case 'createSession': // Create the local session and shared memcache token if (!$this->checkIsLocalWiki()) { return; } CentralAuthUser::setP3P(); $token = $request->getVal('token', ''); $gid = $request->getVal('gu_id', ''); if ($token !== '') { // Load memc data $key = CentralAuthUser::memcKey('centralautologin-token', $token); $memcData = $wgMemc->get($key); $wgMemc->delete($key); if (!$memcData || !isset($memcData['gu_id'])) { $this->doFinalOutput(false, 'Invalid parameters'); return; } $gu_id = intval($memcData['gu_id']); } elseif ($gid !== '') { // Cached, or was logging in as we switched from gu_id to token $gu_id = intval($gid); } else { $this->doFinalOutput(false, 'Invalid parameters'); return; } if ($gu_id <= 0) { $this->doFinalOutput(false, 'Not centrally logged in', self::getInlineScript('anon-set.js')); return; } // At this point we can't cache anymore because we need to set // cookies and memc each time. $this->getOutput()->enableClientCache(false); // Ensure that a session exists if (session_id() == '') { wfSetupSession(); } // Create memc token $wikiid = wfWikiID(); $memcData = array('gu_id' => $gu_id, 'wikiid' => $wikiid); $token = MWCryptRand::generateHex(32); $key = CentralAuthUser::memcKey('centralautologin-token', $token, $wikiid); $wgMemc->set($key, $memcData, 60); // Save memc token for the 'setCookies' step $request->setSessionData('centralautologin-token', $token); $this->do302Redirect($this->loginWiki, 'validateSession', array('token' => $token, 'wikiid' => $wikiid) + $params); return; case 'validateSession': // Validate the shared memcached token // Do not cache this, we need to reset the cookies and memc every time. $this->getOutput()->enableClientCache(false); if (!$this->checkIsCentralWiki($wikiid)) { return; } if (!$this->getUser()->isLoggedIn()) { $this->doFinalOutput(false, 'Not logged in'); return; } CentralAuthUser::setP3P(); // Validate params $token = $request->getVal('token', ''); if ($token === '') { $this->doFinalOutput(false, 'Invalid parameters'); return; } // Load memc data $key = CentralAuthUser::memcKey('centralautologin-token', $token, $wikiid); $memcData = $wgMemc->get($key); $wgMemc->delete($key); // Check memc data $centralUser = CentralAuthUser::getInstance($this->getUser()); if (!$memcData || $memcData['wikiid'] !== $wikiid || !$centralUser || !$centralUser->getId() || $memcData['gu_id'] != $centralUser->getId()) { $this->doFinalOutput(false, 'Invalid parameters'); return; } // Write info for session creation into memc $centralSession = $this->getCentralSession($centralUser, $this->getUser()); $memcData += array('userName' => $centralUser->getName(), 'token' => $centralUser->getAuthToken(), 'finalProto' => $centralSession['finalProto'], 'secureCookies' => $centralSession['secureCookies'], 'remember' => $centralSession['remember'], 'sessionId' => $centralSession['sessionId']); $wgMemc->set($key, $memcData, 60); $this->do302Redirect($wikiid, 'setCookies', $params); return; case 'setCookies': // Check that memcached is validated, and set cookies // Do not cache this, we need to reset the cookies and memc every time. $this->getOutput()->enableClientCache(false); if (!$this->checkIsLocalWiki()) { return; } CentralAuthUser::setP3P(); // Check saved memc token $token = $this->getRequest()->getSessionData('centralautologin-token'); if ($token === null) { $this->doFinalOutput(false, 'Lost session'); return; } // Load memc data $wikiid = wfWikiID(); $key = CentralAuthUser::memcKey('centralautologin-token', $token, $wikiid); $memcData = $wgMemc->get($key); $wgMemc->delete($key); // Check memc data if (!$memcData || $memcData['wikiid'] !== $wikiid || !isset($memcData['userName']) || !isset($memcData['token'])) { $this->doFinalOutput(false, 'Lost session'); return; } // Load and check CentralAuthUser. But don't check if it's // attached, because then if the user is missing en.site they // won't be auto logged in to any of the non-en versions either. $centralUser = new CentralAuthUser($memcData['userName']); if (!$centralUser->getId() || $centralUser->getId() != $memcData['gu_id']) { $msg = "Wrong user: expected {$memcData['gu_id']}, got {$centralUser->getId()}"; wfDebug(__METHOD__ . ": {$msg}\n"); $this->doFinalOutput(false, 'Lost session'); return; } $loginResult = $centralUser->authenticateWithToken($memcData['token']); if ($loginResult != 'ok') { $msg = "Bad token: {$loginResult}"; wfDebug(__METHOD__ . ": {$msg}\n"); $this->doFinalOutput(false, 'Lost session'); return; } // Set a new session cookie, Just In Case™ wfResetSessionID(); // Set central cookies too, with a refreshed sessionid. Also, check if we // need to override the default cookie security policy $secureCookie = $memcData['secureCookies']; $centralUser->setGlobalCookies($memcData['remember'], $memcData['sessionId'], $secureCookie, array('finalProto' => $memcData['finalProto'], 'secureCookies' => $memcData['secureCookies'], 'remember' => $memcData['remember'])); // Now, figure out how to report this back to the user. // First, set to redo the edge login on the next pageview $request->setSessionData('CentralAuthDoEdgeLogin', true); // If it's not a script callback, just go for it. if ($request->getVal('type') !== 'script') { $this->doFinalOutput(true, 'success'); return; } // If it is a script callback, then we do want to create the user // if it doesn't already exist locally (and fail if that can't be // done). if (!User::idFromName($centralUser->getName())) { $user = new User(); $user->setName($centralUser->getName()); if (CentralAuthHooks::attemptAddUser($user)) { $centralUser->invalidateCache(); } } if (!$centralUser->isAttached()) { $this->doFinalOutput(false, 'Local user is not attached', self::getInlineScript('anon-set.js')); return; } $script = self::getInlineScript('anon-remove.js'); // If we're returning to returnto, do that if ($request->getCheck('return')) { global $wgRedirectOnLogin; if ($wgRedirectOnLogin !== null) { $returnTo = $wgRedirectOnLogin; $returnToQuery = array(); } else { $returnTo = $request->getVal('returnto', ''); $returnToQuery = wfCgiToArray($request->getVal('returntoquery', '')); } $returnToTitle = Title::newFromText($returnTo); if (!$returnToTitle) { $returnToTitle = Title::newMainPage(); $returnToQuery = array(); } $redirectUrl = $returnToTitle->getFullURL($returnToQuery); $script .= "\n" . 'location.href = ' . Xml::encodeJsVar($redirectUrl) . ';'; $this->doFinalOutput(true, 'success', $script); return; } // Otherwise, we need to rewrite p-personal and maybe notify the user too global $wgCentralAuthUseEventLogging; if ($wgCentralAuthUseEventLogging) { EventLogging::logEvent('CentralAuth', 5690875, array('version' => 1, 'userId' => $centralUser->getId(), 'action' => 'sul2-autologin-fallbacklogin')); } // Add a script to the page that will pull in the user's toolslist // via ajax, and update the UI. Don't write out the tools here (bug 57081). $code = $this->getUser()->getOption('language'); $code = RequestContext::sanitizeLangCode($code); Hooks::run('UserGetLanguageObject', array($this->getUser(), &$code, $this->getContext())); $script .= "\n" . Xml::encodeJsCall('mediaWiki.messages.set', array(array('centralauth-centralautologin-logged-in' => wfMessage('centralauth-centralautologin-logged-in')->inLanguage($code)->plain(), 'centralauth-centralautologin-logged-in-nouser' => wfMessage('centralauth-centralautologin-logged-in-nouser')->inLanguage($code)->plain(), 'centralautologin' => wfMessage('centralautologin')->inLanguage($code)->plain()))); $script .= "\n" . self::getInlineScript('autologin.js'); // And for good measure, add the edge login HTML images to the page. $script .= "\n" . Xml::encodeJsCall("jQuery( 'body' ).append", array(CentralAuthHooks::getEdgeLoginHTML())); $this->doFinalOutput(true, 'success', $script); return; default: $this->setHeaders(); $this->getOutput()->addWikiMsg('centralauth-centralautologin-desc'); return; } }