示例#1
0
 function __construct(IContextSource $context, $par = null)
 {
     $this->like = $context->getRequest()->getText('like');
     $this->showbots = $context->getRequest()->getBool('showbots', 0);
     if (is_numeric($par)) {
         $this->setLimit($par);
     }
     parent::__construct($context);
 }
 /**
  * Generates a brief review form for a page
  * @param \IContextSource|\RequestContext $context
  * @param FlaggableWikiPage $article
  * @param Revision $rev
  */
 public function __construct(IContextSource $context, FlaggableWikiPage $article, Revision $rev)
 {
     $this->user = $context->getUser();
     $this->request = $context->getRequest();
     $this->article = $article;
     $this->rev = $rev;
 }
示例#3
0
 /**
  * Check if pages can be cached for this request/user
  * @param $context IContextSource
  * @return bool
  */
 public static function useFileCache(IContextSource $context)
 {
     global $wgUseFileCache, $wgShowIPinHeader, $wgDebugToolbar, $wgContLang;
     if (!$wgUseFileCache) {
         return false;
     }
     if ($wgShowIPinHeader || $wgDebugToolbar) {
         wfDebug("HTML file cache skipped. Either \$wgShowIPinHeader and/or \$wgDebugToolbar on\n");
         return false;
     }
     // Get all query values
     $queryVals = $context->getRequest()->getValues();
     foreach ($queryVals as $query => $val) {
         if ($query === 'title' || $query === 'curid') {
             continue;
             // note: curid sets title
             // Normal page view in query form can have action=view.
         } elseif ($query === 'action' && in_array($val, self::cacheablePageActions())) {
             continue;
             // Below are header setting params
         } elseif ($query === 'maxage' || $query === 'smaxage') {
             continue;
         }
         return false;
     }
     $user = $context->getUser();
     // Check for non-standard user language; this covers uselang,
     // and extensions for auto-detecting user language.
     $ulang = $context->getLanguage()->getCode();
     $clang = $wgContLang->getCode();
     // Check that there are no other sources of variation
     return !$user->getId() && !$user->getNewtalk() && $ulang == $clang;
 }
示例#4
0
 /**
  * Checks if the request should abort due to a lagged server,
  * for given maxlag parameter.
  *
  * @param boolean $abort True if this class should abort the
  * script execution. False to return the result as a boolean.
  * @return boolean True if we passed the check, false if we surpass the maxlag
  */
 private function checkMaxLag($abort)
 {
     global $wgShowHostnames;
     wfProfileIn(__METHOD__);
     $maxLag = $this->context->getRequest()->getVal('maxlag');
     if (!is_null($maxLag)) {
         $lb = wfGetLB();
         // foo()->bar() is not supported in PHP4
         list($host, $lag) = $lb->getMaxLag();
         if ($lag > $maxLag) {
             if ($abort) {
                 $resp = $this->context->getRequest()->response();
                 $resp->header('HTTP/1.1 503 Service Unavailable');
                 $resp->header('Retry-After: ' . max(intval($maxLag), 5));
                 $resp->header('X-Database-Lag: ' . intval($lag));
                 $resp->header('Content-Type: text/plain');
                 if ($wgShowHostnames) {
                     echo "Waiting for {$host}: {$lag} seconds lagged\n";
                 } else {
                     echo "Waiting for a database server: {$lag} seconds lagged\n";
                 }
             }
             wfProfileOut(__METHOD__);
             if (!$abort) {
                 return false;
             }
             exit;
         }
     }
     wfProfileOut(__METHOD__);
     return true;
 }
示例#5
0
 function __construct(IContextSource $context, $userName = null, $search = '', $including = false)
 {
     global $wgMiserMode;
     $this->mIncluding = $including;
     if ($userName) {
         $nt = Title::newFromText($userName, NS_USER);
         if (!is_null($nt)) {
             $this->mUserName = $nt->getText();
             $this->mQueryConds['img_user_text'] = $this->mUserName;
         }
     }
     if ($search != '' && !$wgMiserMode) {
         $this->mSearch = $search;
         $nt = Title::newFromURL($this->mSearch);
         if ($nt) {
             $dbr = wfGetDB(DB_SLAVE);
             $this->mQueryConds[] = 'LOWER(img_name)' . $dbr->buildLike($dbr->anyString(), strtolower($nt->getDBkey()), $dbr->anyString());
         }
     }
     if (!$including) {
         if ($context->getRequest()->getText('sort', 'img_date') == 'img_date') {
             $this->mDefaultDirection = true;
         } else {
             $this->mDefaultDirection = false;
         }
     } else {
         $this->mDefaultDirection = true;
     }
     parent::__construct($context);
 }
示例#6
0
 /**
  * Check whether external edit or diff should be used.
  *
  * @param $context IContextSource context to use
  * @param $type String can be either 'edit' or 'diff'
  * @return Bool
  */
 public static function useExternalEngine(IContextSource $context, $type)
 {
     global $wgUseExternalEditor;
     if (!$wgUseExternalEditor) {
         return false;
     }
     $pref = $type == 'diff' ? 'externaldiff' : 'externaleditor';
     $request = $context->getRequest();
     return !$request->getVal('internaledit') && ($context->getUser()->getOption($pref) || $request->getVal('externaledit'));
 }
示例#7
0
	/**
	 * Fetch an appropriate changes list class for the specified context
	 * Some users might want to use an enhanced list format, for instance
	 *
	 * @param $context IContextSource to use
	 * @return ChangesList|EnhancedChangesList|OldChangesList derivative
	 */
	public static function newFromContext( IContextSource $context ) {
		$user = $context->getUser();
		$sk = $context->getSkin();
		$list = null;
		if ( wfRunHooks( 'FetchChangesList', array( $user, &$sk, &$list ) ) ) {
			$new = $context->getRequest()->getBool( 'enhanced', $user->getOption( 'usenewrc' ) );
			return $new ? new EnhancedChangesList( $context ) : new OldChangesList( $context );
		} else {
			return $list;
		}
	}
示例#8
0
 private function main()
 {
     global $wgUseFileCache, $wgTitle, $wgUseAjax;
     wfProfileIn(__METHOD__);
     $request = $this->context->getRequest();
     // Send Ajax requests to the Ajax dispatcher.
     if ($wgUseAjax && $request->getVal('action', 'view') == 'ajax') {
         // Set a dummy title, because $wgTitle == null might break things
         $title = Title::makeTitle(NS_MAIN, 'AJAX');
         $this->context->setTitle($title);
         $wgTitle = $title;
         $dispatcher = new AjaxDispatcher();
         $dispatcher->performAction();
         wfProfileOut(__METHOD__);
         return;
     }
     // Get title from request parameters,
     // is set on the fly by parseTitle the first time.
     $title = $this->getTitle();
     $action = $this->getAction();
     $wgTitle = $title;
     if ($wgUseFileCache && $title->getNamespace() >= 0) {
         wfProfileIn('main-try-filecache');
         if (HTMLFileCache::useFileCache($this->context)) {
             // Try low-level file cache hit
             $cache = HTMLFileCache::newFromTitle($title, $action);
             if ($cache->isCacheGood()) {
                 // Check incoming headers to see if client has this cached
                 $timestamp = $cache->cacheTimestamp();
                 if (!$this->context->getOutput()->checkLastModified($timestamp)) {
                     $cache->loadFromFileCache($this->context);
                 }
                 // Do any stats increment/watchlist stuff
                 $this->context->getWikiPage()->doViewUpdates($this->context->getUser());
                 // Tell OutputPage that output is taken care of
                 $this->context->getOutput()->disable();
                 wfProfileOut('main-try-filecache');
                 wfProfileOut(__METHOD__);
                 return;
             }
         }
         wfProfileOut('main-try-filecache');
     }
     $this->performRequest();
     // Now commit any transactions, so that unreported errors after
     // output() don't roll back the whole DB transaction
     wfGetLBFactory()->commitMasterChanges();
     // Output everything!
     $this->context->getOutput()->output();
     wfProfileOut(__METHOD__);
 }
示例#9
0
 private function main()
 {
     global $wgUseFileCache, $wgTitle, $wgUseAjax;
     wfProfileIn(__METHOD__);
     $request = $this->context->getRequest();
     // Send Ajax requests to the Ajax dispatcher.
     if ($wgUseAjax && $request->getVal('action', 'view') == 'ajax') {
         // Set a dummy title, because $wgTitle == null might break things
         // Wikia change - start
         // @author macbre, wladek
         $title = Wikia::createTitleFromRequest($request);
         // Wikia change - end
         $this->context->setTitle($title);
         $wgTitle = $title;
         $dispatcher = new AjaxDispatcher();
         $dispatcher->performAction();
         wfProfileOut(__METHOD__);
         return;
     }
     // Get title from request parameters,
     // is set on the fly by parseTitle the first time.
     $title = $this->getTitle();
     $action = $this->getAction();
     $wgTitle = $title;
     if ($wgUseFileCache && $title->getNamespace() >= 0) {
         wfProfileIn('main-try-filecache');
         if (HTMLFileCache::useFileCache($this->context)) {
             // Try low-level file cache hit
             $cache = HTMLFileCache::newFromTitle($title, $action);
             if ($cache->isCacheGood()) {
                 // Check incoming headers to see if client has this cached
                 $timestamp = $cache->cacheTimestamp();
                 if (!$this->context->getOutput()->checkLastModified($timestamp)) {
                     $cache->loadFromFileCache($this->context);
                 }
                 // Do any stats increment/watchlist stuff
                 $this->context->getWikiPage()->doViewUpdates($this->context->getUser());
                 // Tell OutputPage that output is taken care of
                 $this->context->getOutput()->disable();
                 wfProfileOut('main-try-filecache');
                 wfProfileOut(__METHOD__);
                 return;
             }
         }
         wfProfileOut('main-try-filecache');
     }
     $this->performRequest();
     $this->finalCleanup();
     wfProfileOut(__METHOD__);
 }
示例#10
0
 private function main()
 {
     global $wgTitle;
     $output = $this->context->getOutput();
     $request = $this->context->getRequest();
     // Send Ajax requests to the Ajax dispatcher.
     if ($this->config->get('UseAjax') && $request->getVal('action') === 'ajax') {
         // Set a dummy title, because $wgTitle == null might break things
         $title = Title::makeTitle(NS_SPECIAL, 'Badtitle/performing an AJAX call in ' . __METHOD__);
         $this->context->setTitle($title);
         $wgTitle = $title;
         $dispatcher = new AjaxDispatcher($this->config);
         $dispatcher->performAction($this->context->getUser());
         return;
     }
     // Get title from request parameters,
     // is set on the fly by parseTitle the first time.
     $title = $this->getTitle();
     $action = $this->getAction();
     $wgTitle = $title;
     // Set DB query expectations for this HTTP request
     $trxLimits = $this->config->get('TrxProfilerLimits');
     $trxProfiler = Profiler::instance()->getTransactionProfiler();
     $trxProfiler->setLogger(LoggerFactory::getInstance('DBPerformance'));
     if ($request->hasSafeMethod()) {
         $trxProfiler->setExpectations($trxLimits['GET'], __METHOD__);
     } else {
         $trxProfiler->setExpectations($trxLimits['POST'], __METHOD__);
     }
     // If the user has forceHTTPS set to true, or if the user
     // is in a group requiring HTTPS, or if they have the HTTPS
     // preference set, redirect them to HTTPS.
     // Note: Do this after $wgTitle is setup, otherwise the hooks run from
     // isLoggedIn() will do all sorts of weird stuff.
     if ($request->getProtocol() == 'http' && preg_match('#^https://#', wfExpandUrl($request->getRequestURL(), PROTO_HTTPS)) && ($request->getSession()->shouldForceHTTPS() || $request->getCookie('forceHTTPS', '') || $request->getCookie('forceHTTPS') || $this->context->getUser()->isLoggedIn() && $this->context->getUser()->requiresHTTPS())) {
         $oldUrl = $request->getFullRequestURL();
         $redirUrl = preg_replace('#^http://#', 'https://', $oldUrl);
         // ATTENTION: This hook is likely to be removed soon due to overall design of the system.
         if (Hooks::run('BeforeHttpsRedirect', [$this->context, &$redirUrl])) {
             if ($request->wasPosted()) {
                 // This is weird and we'd hope it almost never happens. This
                 // means that a POST came in via HTTP and policy requires us
                 // redirecting to HTTPS. It's likely such a request is going
                 // to fail due to post data being lost, but let's try anyway
                 // and just log the instance.
                 // @todo FIXME: See if we could issue a 307 or 308 here, need
                 // to see how clients (automated & browser) behave when we do
                 wfDebugLog('RedirectedPosts', "Redirected from HTTP to HTTPS: {$oldUrl}");
             }
             // Setup dummy Title, otherwise OutputPage::redirect will fail
             $title = Title::newFromText('REDIR', NS_MAIN);
             $this->context->setTitle($title);
             // Since we only do this redir to change proto, always send a vary header
             $output->addVaryHeader('X-Forwarded-Proto');
             $output->redirect($redirUrl);
             $output->output();
             return;
         }
     }
     if ($title->canExist() && HTMLFileCache::useFileCache($this->context)) {
         // Try low-level file cache hit
         $cache = new HTMLFileCache($title, $action);
         if ($cache->isCacheGood()) {
             // Check incoming headers to see if client has this cached
             $timestamp = $cache->cacheTimestamp();
             if (!$output->checkLastModified($timestamp)) {
                 $cache->loadFromFileCache($this->context);
             }
             // Do any stats increment/watchlist stuff, assuming user is viewing the
             // latest revision (which should always be the case for file cache)
             $this->context->getWikiPage()->doViewUpdates($this->context->getUser());
             // Tell OutputPage that output is taken care of
             $output->disable();
             return;
         }
     }
     // Actually do the work of the request and build up any output
     $this->performRequest();
     // GUI-ify and stash the page output in MediaWiki::doPreOutputCommit() while
     // ChronologyProtector synchronizes DB positions or slaves accross all datacenters.
     $buffer = null;
     $outputWork = function () use($output, &$buffer) {
         if ($buffer === null) {
             $buffer = $output->output(true);
         }
         return $buffer;
     };
     // Now commit any transactions, so that unreported errors after
     // output() don't roll back the whole DB transaction and so that
     // we avoid having both success and error text in the response
     $this->doPreOutputCommit($outputWork);
     // Now send the actual output
     print $outputWork();
 }
示例#11
0
	/**
	 * Get the action that will be executed, not necessarily the one passed
	 * passed through the "action" request parameter. Actions disabled in
	 * $wgActions will be replaced by "nosuchaction".
	 *
	 * @since 1.19
	 * @param $context IContextSource
	 * @return string: action name
	 */
	final public static function getActionName( IContextSource $context ) {
		global $wgActions;

		$request = $context->getRequest();
		$actionName = $request->getVal( 'action', 'view' );

		// Check for disabled actions
		if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
			$actionName = 'nosuchaction';
		}

		// Workaround for bug #20966: inability of IE to provide an action dependent
		// on which submit button is clicked.
		if ( $actionName === 'historysubmit' ) {
			if ( $request->getBool( 'revisiondelete' ) ) {
				$actionName = 'revisiondelete';
			} else {
				$actionName = 'view';
			}
		} elseif ( $actionName == 'editredlink' ) {
			$actionName = 'edit';
		}

		// Trying to get a WikiPage for NS_SPECIAL etc. will result
		// in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
		// For SpecialPages et al, default to action=view.
		if ( !$context->canUseWikiPage() ) {
			return 'view';
		}

		$action = Action::factory( $actionName, $context->getWikiPage(), $context );
		if ( $action instanceof Action ) {
			return $action->getName();
		}

		return 'nosuchaction';
	}
示例#12
0
 /**
  * Returns the HTML to add to the page for the toolbar
  *
  * @param IContextSource $context
  * @return array
  */
 public static function getDebugInfo(IContextSource $context)
 {
     if (!self::$enabled) {
         return array();
     }
     global $wgVersion, $wgRequestTime;
     $request = $context->getRequest();
     // HHVM's reported memory usage from memory_get_peak_usage()
     // is not useful when passing false, but we continue passing
     // false for consistency of historical data in zend.
     // see: https://github.com/facebook/hhvm/issues/2257#issuecomment-39362246
     $realMemoryUsage = wfIsHHVM();
     return array('mwVersion' => $wgVersion, 'phpEngine' => wfIsHHVM() ? 'HHVM' : 'PHP', 'phpVersion' => wfIsHHVM() ? HHVM_VERSION : PHP_VERSION, 'gitRevision' => GitInfo::headSHA1(), 'gitBranch' => GitInfo::currentBranch(), 'gitViewUrl' => GitInfo::headViewUrl(), 'time' => microtime(true) - $wgRequestTime, 'log' => self::$log, 'debugLog' => self::$debug, 'queries' => self::$query, 'request' => array('method' => $request->getMethod(), 'url' => $request->getRequestURL(), 'headers' => $request->getAllHeaders(), 'params' => $request->getValues()), 'memory' => $context->getLanguage()->formatSize(memory_get_usage($realMemoryUsage)), 'memoryPeak' => $context->getLanguage()->formatSize(memory_get_peak_usage($realMemoryUsage)), 'includes' => self::getFilesIncluded($context));
 }
示例#13
0
 /**
  * Returns the HTML to add to the page for the toolbar
  *
  * @param $context IContextSource
  * @return array
  */
 public static function getDebugInfo(IContextSource $context)
 {
     if (!self::$enabled) {
         return array();
     }
     global $wgVersion, $wgRequestTime;
     $request = $context->getRequest();
     return array('mwVersion' => $wgVersion, 'phpVersion' => PHP_VERSION, 'gitRevision' => GitInfo::headSHA1(), 'gitBranch' => GitInfo::currentBranch(), 'gitViewUrl' => GitInfo::headViewUrl(), 'time' => microtime(true) - $wgRequestTime, 'log' => self::$log, 'debugLog' => self::$debug, 'queries' => self::$query, 'request' => array('method' => $request->getMethod(), 'url' => $request->getRequestURL(), 'headers' => $request->getAllHeaders(), 'params' => $request->getValues()), 'memory' => $context->getLanguage()->formatSize(memory_get_usage()), 'memoryPeak' => $context->getLanguage()->formatSize(memory_get_peak_usage()), 'includes' => self::getFilesIncluded($context));
 }
示例#14
0
 private function main()
 {
     global $wgUseFileCache, $wgTitle, $wgUseAjax;
     wfProfileIn(__METHOD__);
     $request = $this->context->getRequest();
     // Send Ajax requests to the Ajax dispatcher.
     if ($wgUseAjax && $request->getVal('action', 'view') == 'ajax') {
         // Set a dummy title, because $wgTitle == null might break things
         $title = Title::makeTitle(NS_MAIN, 'AJAX');
         $this->context->setTitle($title);
         $wgTitle = $title;
         $dispatcher = new AjaxDispatcher();
         $dispatcher->performAction();
         wfProfileOut(__METHOD__);
         return;
     }
     // Get title from request parameters,
     // is set on the fly by parseTitle the first time.
     $title = $this->getTitle();
     $action = $this->getAction();
     $wgTitle = $title;
     // If the user has forceHTTPS set to true, or if the user
     // is in a group requiring HTTPS, or if they have the HTTPS
     // preference set, redirect them to HTTPS.
     // Note: Do this after $wgTitle is setup, otherwise the hooks run from
     // isLoggedIn() will do all sorts of weird stuff.
     if (($request->getCookie('forceHTTPS', '') || $request->getCookie('forceHTTPS') || $this->context->getUser()->isLoggedIn() && $this->context->getUser()->requiresHTTPS()) && $request->getProtocol() == 'http') {
         $oldUrl = $request->getFullRequestURL();
         $redirUrl = str_replace('http://', 'https://', $oldUrl);
         if ($request->wasPosted()) {
             // This is weird and we'd hope it almost never happens. This
             // means that a POST came in via HTTP and policy requires us
             // redirecting to HTTPS. It's likely such a request is going
             // to fail due to post data being lost, but let's try anyway
             // and just log the instance.
             //
             // @todo @fixme See if we could issue a 307 or 308 here, need
             // to see how clients (automated & browser) behave when we do
             wfDebugLog('RedirectedPosts', "Redirected from HTTP to HTTPS: {$oldUrl}");
         }
         // Setup dummy Title, otherwise OutputPage::redirect will fail
         $title = Title::newFromText(NS_MAIN, 'REDIR');
         $this->context->setTitle($title);
         $output = $this->context->getOutput();
         // Since we only do this redir to change proto, always send a vary header
         $output->addVaryHeader('X-Forwarded-Proto');
         $output->redirect($redirUrl);
         $output->output();
         wfProfileOut(__METHOD__);
         return;
     }
     if ($wgUseFileCache && $title->getNamespace() >= 0) {
         wfProfileIn('main-try-filecache');
         if (HTMLFileCache::useFileCache($this->context)) {
             // Try low-level file cache hit
             $cache = HTMLFileCache::newFromTitle($title, $action);
             if ($cache->isCacheGood()) {
                 // Check incoming headers to see if client has this cached
                 $timestamp = $cache->cacheTimestamp();
                 if (!$this->context->getOutput()->checkLastModified($timestamp)) {
                     $cache->loadFromFileCache($this->context);
                 }
                 // Do any stats increment/watchlist stuff
                 // Assume we're viewing the latest revision (this should always be the case with file cache)
                 $this->context->getWikiPage()->doViewUpdates($this->context->getUser());
                 // Tell OutputPage that output is taken care of
                 $this->context->getOutput()->disable();
                 wfProfileOut('main-try-filecache');
                 wfProfileOut(__METHOD__);
                 return;
             }
         }
         wfProfileOut('main-try-filecache');
     }
     // Actually do the work of the request and build up any output
     $this->performRequest();
     // Either all DB and deferred updates should happen or none.
     // The later should not be cancelled due to client disconnect.
     ignore_user_abort(true);
     // Now commit any transactions, so that unreported errors after
     // output() don't roll back the whole DB transaction
     wfGetLBFactory()->commitMasterChanges();
     // Output everything!
     $this->context->getOutput()->output();
     wfProfileOut(__METHOD__);
 }
示例#15
0
 /**
  * Save submitted protection form
  *
  * @return bool Success
  */
 function save()
 {
     # Permission check!
     if ($this->disabled) {
         $this->show();
         return false;
     }
     $request = $this->mContext->getRequest();
     $user = $this->mContext->getUser();
     $out = $this->mContext->getOutput();
     $token = $request->getVal('wpEditToken');
     if (!$user->matchEditToken($token, ['protect', $this->mTitle->getPrefixedDBkey()])) {
         $this->show(['sessionfailure']);
         return false;
     }
     # Create reason string. Use list and/or custom string.
     $reasonstr = $this->mReasonSelection;
     if ($reasonstr != 'other' && $this->mReason != '') {
         // Entry from drop down menu + additional comment
         $reasonstr .= $this->mContext->msg('colon-separator')->text() . $this->mReason;
     } elseif ($reasonstr == 'other') {
         $reasonstr = $this->mReason;
     }
     $expiry = [];
     foreach ($this->mApplicableTypes as $action) {
         $expiry[$action] = $this->getExpiry($action);
         if (empty($this->mRestrictions[$action])) {
             continue;
             // unprotected
         }
         if (!$expiry[$action]) {
             $this->show(['protect_expiry_invalid']);
             return false;
         }
         if ($expiry[$action] < wfTimestampNow()) {
             $this->show(['protect_expiry_old']);
             return false;
         }
     }
     $this->mCascade = $request->getBool('mwProtect-cascade');
     $status = $this->mArticle->doUpdateRestrictions($this->mRestrictions, $expiry, $this->mCascade, $reasonstr, $user);
     if (!$status->isOK()) {
         $this->show($out->parseInline($status->getWikiText()));
         return false;
     }
     /**
      * Give extensions a change to handle added form items
      *
      * @since 1.19 you can (and you should) return false to abort saving;
      *             you can also return an array of message name and its parameters
      */
     $errorMsg = '';
     if (!Hooks::run('ProtectionForm::save', [$this->mArticle, &$errorMsg, $reasonstr])) {
         if ($errorMsg == '') {
             $errorMsg = ['hookaborted'];
         }
     }
     if ($errorMsg != '') {
         $this->show($errorMsg);
         return false;
     }
     WatchAction::doWatchOrUnwatch($request->getCheck('mwProtectWatch'), $this->mTitle, $user);
     return true;
 }
示例#16
0
 /**
  * Returns the HTML to add to the page for the toolbar
  *
  * @param $context IContextSource
  * @return string
  */
 public static function getDebugHTML(IContextSource $context)
 {
     if (!self::$enabled) {
         return '';
     }
     global $wgVersion, $wgRequestTime;
     MWDebug::log('MWDebug output complete');
     $request = $context->getRequest();
     $debugInfo = array('mwVersion' => $wgVersion, 'phpVersion' => PHP_VERSION, 'time' => microtime(true) - $wgRequestTime, 'log' => self::$log, 'debugLog' => self::$debug, 'queries' => self::$query, 'request' => array('method' => $_SERVER['REQUEST_METHOD'], 'url' => $request->getRequestURL(), 'headers' => $request->getAllHeaders(), 'params' => $request->getValues()), 'memory' => $context->getLanguage()->formatSize(memory_get_usage()), 'memoryPeak' => $context->getLanguage()->formatSize(memory_get_peak_usage()), 'includes' => self::getFilesIncluded($context));
     // Cannot use OutputPage::addJsConfigVars because those are already outputted
     // by the time this method is called.
     $html = Html::inlineScript(ResourceLoader::makeLoaderConditionalScript(ResourceLoader::makeConfigSetScript(array('debugInfo' => $debugInfo))));
     return $html;
 }
 /**
  * Returns a message that notifies the user he/she is looking at
  * a cached version of the page, including a refresh link.
  *
  * @since 1.20
  *
  * @param IContextSource $context
  * @param boolean $includePurgeLink
  *
  * @return string
  */
 public function getCachedNotice(IContextSource $context, $includePurgeLink = true)
 {
     if ($this->cacheExpiry < 86400 * 3650) {
         $message = $context->msg('cachedspecial-viewing-cached-ttl', $context->getLanguage()->formatDuration($this->cacheExpiry))->escaped();
     } else {
         $message = $context->msg('cachedspecial-viewing-cached-ts')->escaped();
     }
     if ($includePurgeLink) {
         $refreshArgs = $context->getRequest()->getQueryValues();
         unset($refreshArgs['title']);
         $refreshArgs['action'] = 'purge';
         $subPage = $context->getTitle()->getFullText();
         $subPage = explode('/', $subPage, 2);
         $subPage = count($subPage) > 1 ? $subPage[1] : false;
         $message .= ' ' . Linker::link($context->getTitle($subPage), $context->msg('cachedspecial-refresh-now')->escaped(), array(), $refreshArgs);
     }
     return $message;
 }
示例#18
0
 function __construct(IContextSource $context, $userName = null, $search = '', $including = false, $showAll = false)
 {
     $this->mIncluding = $including;
     $this->mShowAll = $showAll;
     if ($userName) {
         $nt = Title::newFromText($userName, NS_USER);
         if (!is_null($nt)) {
             $this->mUserName = $nt->getText();
         }
     }
     if ($search !== '' && !$this->getConfig()->get('MiserMode')) {
         $this->mSearch = $search;
         $nt = Title::newFromURL($this->mSearch);
         if ($nt) {
             $dbr = wfGetDB(DB_SLAVE);
             $this->mQueryConds[] = 'LOWER(img_name)' . $dbr->buildLike($dbr->anyString(), strtolower($nt->getDBkey()), $dbr->anyString());
         }
     }
     if (!$including) {
         if ($context->getRequest()->getText('sort', 'img_date') == 'img_date') {
             $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
         } else {
             $this->mDefaultDirection = IndexPager::DIR_ASCENDING;
         }
     } else {
         $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
     }
     parent::__construct($context);
 }
示例#19
0
文件: Block.php 项目: whysasse/kmwiki
 /**
  * Get the key and parameters for the corresponding error message.
  *
  * @since 1.22
  * @param IContextSource $context
  * @return array
  */
 public function getPermissionsError(IContextSource $context)
 {
     $blocker = $this->getBlocker();
     if ($blocker instanceof User) {
         // local user
         $blockerUserpage = $blocker->getUserPage();
         $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]";
     } else {
         // foreign user
         $link = $blocker;
     }
     $reason = $this->mReason;
     if ($reason == '') {
         $reason = $context->msg('blockednoreason')->text();
     }
     /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked.
      * This could be a username, an IP range, or a single IP. */
     $intended = $this->getTarget();
     $lang = $context->getLanguage();
     return array($this->mAuto ? 'autoblockedtext' : 'blockedtext', $link, $reason, $context->getRequest()->getIP(), $this->getByName(), $this->getId(), $lang->formatExpiry($this->mExpiry), (string) $intended, $lang->userTimeAndDate($this->mTimestamp, $context->getUser()));
 }
示例#20
0
 /**
  * Handler for non-standard (edit/log) entries that need IP data
  *
  * @param $context IContextSource
  * @param $data Array
  * @return bool
  */
 protected static function onLoggableUserIPData(IContextSource $context, array $data)
 {
     $user = $context->getUser();
     $request = $context->getRequest();
     // Get IP address
     $ip = $request->getIP();
     // Get XFF header
     $xff = $request->getHeader('X-Forwarded-For');
     list($xff_ip, $isSquidOnly) = IP::getClientIPfromXFF($xff);
     // Get agent
     $agent = $request->getHeader('User-Agent');
     $dbw = wfGetDB(DB_MASTER);
     $cuc_id = $dbw->nextSequenceValue('cu_changes_cu_id_seq');
     $rcRow = array('cuc_id' => $cuc_id, 'cuc_page_id' => $data['pageid'], 'cuc_namespace' => $data['namespace'], 'cuc_title' => $data['title'], 'cuc_minor' => 0, 'cuc_user' => $user->getId(), 'cuc_user_text' => $user->getName(), 'cuc_actiontext' => $data['action'], 'cuc_comment' => $data['comment'], 'cuc_this_oldid' => 0, 'cuc_last_oldid' => 0, 'cuc_type' => RC_LOG, 'cuc_timestamp' => $dbw->timestamp($data['timestamp']), 'cuc_ip' => IP::sanitizeIP($ip), 'cuc_ip_hex' => $ip ? IP::toHex($ip) : null, 'cuc_xff' => !$isSquidOnly ? $xff : '', 'cuc_xff_hex' => $xff_ip && !$isSquidOnly ? IP::toHex($xff_ip) : null, 'cuc_agent' => $agent);
     $dbw->insert('cu_changes', $rcRow, __METHOD__);
     return true;
 }
 /**
  * Edit a Collaboration Hub via the edit API
  * @param $title Title
  * @param $displayName string
  * @param $icon string
  * @param $colour string
  * @param $introduction string
  * @param $footer string
  * @param $content array
  * @param $summary string Message key for edit summary
  * @param $context IContextSource The calling context
  * @return Status
  */
 public static function edit(Title $title, $displayName, $image, $colour, $introduction, $footer, $content, $summary, IContextSource $context)
 {
     $contentBlock = ['display_name' => $displayName, 'introduction' => $introduction, 'footer' => $footer, 'image' => $image, 'colour' => $colour, 'content' => $content];
     // TODO Do content
     $jsonText = FormatJson::encode($contentBlock);
     if ($jsonText === null) {
         return Status::newFatal('collaborationkit-hub-edit-tojsonerror');
     }
     // Ensure that a valid context is provided to the API in unit tests
     $der = new DerivativeContext($context);
     $request = new DerivativeRequest($context->getRequest(), ['action' => 'edit', 'title' => $title->getFullText(), 'contentmodel' => 'CollaborationHubContent', 'text' => $jsonText, 'summary' => $summary, 'token' => $context->getUser()->getEditToken()], true);
     $der->setRequest($request);
     try {
         $api = new ApiMain($der, true);
         $api->execute();
     } catch (UsageException $e) {
         return Status::newFatal($context->msg('collaborationkit-hub-edit-apierror', $e->getCodeString()));
     }
     return Status::newGood();
 }
示例#22
0
 function __construct(IContextSource $context, $par = null)
 {
     $this->like = $context->getRequest()->getText('like');
     $this->showbots = $context->getRequest()->getBool('showbots', 0);
     parent::__construct($context);
 }
示例#23
0
 /**
  * Check if pages can be cached for this request/user
  * @param IContextSource $context
  * @param integer $mode One of the HTMLFileCache::MODE_* constants (since 1.28)
  * @return bool
  */
 public static function useFileCache(IContextSource $context, $mode = self::MODE_NORMAL)
 {
     $config = MediaWikiServices::getInstance()->getMainConfig();
     if (!$config->get('UseFileCache') && $mode !== self::MODE_REBUILD) {
         return false;
     } elseif ($config->get('DebugToolbar')) {
         wfDebug("HTML file cache skipped. \$wgDebugToolbar on\n");
         return false;
     }
     // Get all query values
     $queryVals = $context->getRequest()->getValues();
     foreach ($queryVals as $query => $val) {
         if ($query === 'title' || $query === 'curid') {
             continue;
             // note: curid sets title
             // Normal page view in query form can have action=view.
         } elseif ($query === 'action' && in_array($val, self::cacheablePageActions())) {
             continue;
             // Below are header setting params
         } elseif ($query === 'maxage' || $query === 'smaxage') {
             continue;
         }
         return false;
     }
     $user = $context->getUser();
     // Check for non-standard user language; this covers uselang,
     // and extensions for auto-detecting user language.
     $ulang = $context->getLanguage();
     // Check that there are no other sources of variation
     if ($user->getId() || $ulang->getCode() !== $config->get('LanguageCode')) {
         return false;
     }
     if ($mode === self::MODE_NORMAL) {
         if ($user->getNewtalk()) {
             return false;
         }
     }
     // Allow extensions to disable caching
     return Hooks::run('HTMLFileCache::useFileCache', [$context]);
 }
示例#24
0
 /**
  * Backend function for confirmEdit() and confirmEditAPI()
  * @param WikiPage $page
  * @param $newtext string
  * @param $section
  * @param IContextSource $context
  * @return bool false if the CAPTCHA is rejected, true otherwise
  */
 private function doConfirmEdit(WikiPage $page, $newtext, $section, IContextSource $context)
 {
     $request = $context->getRequest();
     if ($request->getVal('captchaid')) {
         $request->setVal('wpCaptchaId', $request->getVal('captchaid'));
     }
     if ($request->getVal('captchaword')) {
         $request->setVal('wpCaptchaWord', $request->getVal('captchaword'));
     }
     if ($this->shouldCheck($page, $newtext, $section, $context)) {
         return $this->passCaptchaLimited();
     } else {
         wfDebug("ConfirmEdit: no need to show captcha.\n");
         return true;
     }
 }
示例#25
0
 /**
  * Just like executePath() but will override global variables and execute
  * the page in "inclusion" mode. Returns true if the execution was
  * successful or false if there was no such special page, or a title object
  * if it was a redirect.
  *
  * Also saves the current $wgTitle, $wgOut, $wgRequest, $wgUser and $wgLang
  * variables so that the special page will get the context it'd expect on a
  * normal request, and then restores them to their previous values after.
  *
  * @param Title $title
  * @param IContextSource $context
  * @return string HTML fragment
  */
 public static function capturePath(Title $title, IContextSource $context)
 {
     global $wgTitle, $wgOut, $wgRequest, $wgUser, $wgLang;
     $main = RequestContext::getMain();
     // Save current globals and main context
     $glob = ['title' => $wgTitle, 'output' => $wgOut, 'request' => $wgRequest, 'user' => $wgUser, 'language' => $wgLang];
     $ctx = ['title' => $main->getTitle(), 'output' => $main->getOutput(), 'request' => $main->getRequest(), 'user' => $main->getUser(), 'language' => $main->getLanguage()];
     // Override
     $wgTitle = $title;
     $wgOut = $context->getOutput();
     $wgRequest = $context->getRequest();
     $wgUser = $context->getUser();
     $wgLang = $context->getLanguage();
     $main->setTitle($title);
     $main->setOutput($context->getOutput());
     $main->setRequest($context->getRequest());
     $main->setUser($context->getUser());
     $main->setLanguage($context->getLanguage());
     // The useful part
     $ret = self::executePath($title, $context, true);
     // Restore old globals and context
     $wgTitle = $glob['title'];
     $wgOut = $glob['output'];
     $wgRequest = $glob['request'];
     $wgUser = $glob['user'];
     $wgLang = $glob['language'];
     $main->setTitle($ctx['title']);
     $main->setOutput($ctx['output']);
     $main->setRequest($ctx['request']);
     $main->setUser($ctx['user']);
     $main->setLanguage($ctx['language']);
     return $ret;
 }
示例#26
0
 /**
  * Get the WebRequest being used for this instance.
  * IndexPager extends ContextSource as of 1.19.
  *
  * @since 0.1
  *
  * @return WebRequest
  */
 public function getRequest()
 {
     return $this->context->getRequest();
 }
示例#27
0
 /**
  * Just like executePath() but will override global variables and execute
  * the page in "inclusion" mode. Returns true if the execution was
  * successful or false if there was no such special page, or a title object
  * if it was a redirect.
  *
  * Also saves the current $wgTitle, $wgOut, $wgRequest, $wgUser and $wgLang
  * variables so that the special page will get the context it'd expect on a
  * normal request, and then restores them to their previous values after.
  *
  * @param $title Title
  * @param $context IContextSource
  *
  * @return String: HTML fragment
  */
 static function capturePath(Title $title, IContextSource $context)
 {
     global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang;
     // Save current globals
     $oldTitle = $wgTitle;
     $oldOut = $wgOut;
     $oldRequest = $wgRequest;
     $oldUser = $wgUser;
     $oldLang = $wgLang;
     // Set the globals to the current context
     $wgTitle = $title;
     $wgOut = $context->getOutput();
     $wgRequest = $context->getRequest();
     $wgUser = $context->getUser();
     $wgLang = $context->getLanguage();
     // The useful part
     $ret = self::executePath($title, $context, true);
     // And restore the old globals
     $wgTitle = $oldTitle;
     $wgOut = $oldOut;
     $wgRequest = $oldRequest;
     $wgUser = $oldUser;
     $wgLang = $oldLang;
     return $ret;
 }
 /**
  * Attempt to validate and submit this data to the DB
  * @param $context IContextSource
  * @return array( true or error key string, html error msg or null )
  */
 public function submit(IContextSource $context)
 {
     global $wgAuth, $wgAccountRequestThrottle, $wgMemc, $wgContLang;
     global $wgConfirmAccountRequestFormItems;
     $formConfig = $wgConfirmAccountRequestFormItems;
     // convience
     $reqUser = $this->requester;
     # Make sure that basic permissions are checked
     $block = ConfirmAccount::getAccountRequestBlock($reqUser);
     if ($block) {
         return array('accountreq_permission_denied', $context->msg('badaccess-group0')->escaped());
     } elseif (wfReadOnly()) {
         return array('accountreq_readonly', $context->msg('badaccess-group0')->escaped());
     }
     # Now create a dummy user ($u) and check if it is valid
     if ($this->userName === '') {
         return array('accountreq_no_name', $context->msg('noname')->escaped());
     }
     $u = User::newFromName($this->userName, 'creatable');
     if (!$u) {
         return array('accountreq_invalid_name', $context->msg('noname')->escaped());
     }
     # No request spamming...
     if ($wgAccountRequestThrottle && $reqUser->isPingLimitable()) {
         $key = wfMemcKey('acctrequest', 'ip', $this->ip);
         $value = (int) $wgMemc->get($key);
         if ($value > $wgAccountRequestThrottle) {
             return array('accountreq_throttled', $context->msg('acct_request_throttle_hit', $wgAccountRequestThrottle)->text());
         }
     }
     # Make sure user agrees to policy here
     if ($formConfig['TermsOfService']['enabled'] && !$this->tosAccepted) {
         return array('acct_request_skipped_tos', $context->msg('requestaccount-agree')->escaped());
     }
     # Validate email address
     if (!Sanitizer::validateEmail($this->email)) {
         return array('acct_request_invalid_email', $context->msg('invalidemailaddress')->escaped());
     }
     # Check if biography is long enough
     if ($formConfig['Biography']['enabled'] && str_word_count($this->bio) < $formConfig['Biography']['minWords']) {
         $minWords = $formConfig['Biography']['minWords'];
         return array('acct_request_short_bio', $context->msg('requestaccount-tooshort')->numParams($minWords)->text());
     }
     # Per security reasons, file dir cannot be pulled from client,
     # so ask them to resubmit it then...
     # If the extra fields are off, then uploads are off
     $allowFiles = $formConfig['CV']['enabled'];
     if ($allowFiles && $this->attachmentPrevName && !$this->attachmentSrcName) {
         # If the user is submitting forgotAttachment as true with no file,
         # then they saw the notice and choose not to re-select the file.
         # Assume that they don't want to send one anymore.
         if (!$this->attachmentDidNotForget) {
             $this->attachmentPrevName = '';
             $this->attachmentDidNotForget = 0;
             return array(false, $context->msg('requestaccount-resub')->escaped());
         }
     }
     # Check if already in use
     if (0 != $u->idForName() || $wgAuth->userExists($u->getName())) {
         return array('accountreq_username_exists', $context->msg('userexists')->escaped());
     }
     # Set email and real name
     $u->setEmail($this->email);
     $u->setRealName($this->realName);
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin();
     // ready to acquire locks
     # Check pending accounts for name use
     if (!UserAccountRequest::acquireUsername($u->getName())) {
         $dbw->rollback();
         return array('accountreq_username_pending', $context->msg('requestaccount-inuse')->escaped());
     }
     # Check if someone else has an account request with the same email
     if (!UserAccountRequest::acquireEmail($u->getEmail())) {
         $dbw->rollback();
         return array('acct_request_email_exists', $context->msg('requestaccount-emaildup')->escaped());
     }
     # Process upload...
     if ($allowFiles && $this->attachmentSrcName) {
         global $wgAccountRequestExts, $wgConfirmAccountFSRepos;
         $ext = explode('.', $this->attachmentSrcName);
         $finalExt = $ext[count($ext) - 1];
         # File must have size.
         if (trim($this->attachmentSrcName) == '' || empty($this->attachmentSize)) {
             $this->attachmentPrevName = '';
             $dbw->rollback();
             return array('acct_request_empty_file', $context->msg('emptyfile')->escaped());
         }
         # Look at the contents of the file; if we can recognize the
         # type but it's corrupt or data of the wrong type, we should
         # probably not accept it.
         if (!in_array($finalExt, $wgAccountRequestExts)) {
             $this->attachmentPrevName = '';
             $dbw->rollback();
             return array('acct_request_bad_file_ext', $context->msg('requestaccount-exts')->escaped());
         }
         $veri = ConfirmAccount::verifyAttachment($this->attachmentTempPath, $finalExt);
         if (!$veri->isGood()) {
             $this->attachmentPrevName = '';
             $dbw->rollback();
             return array('acct_request_corrupt_file', $context->msg('verification-error')->escaped());
         }
         # Start a transaction, move file from temp to account request directory.
         $repo = new FSRepo($wgConfirmAccountFSRepos['accountreqs']);
         $key = sha1_file($this->attachmentTempPath) . '.' . $finalExt;
         $pathRel = UserAccountRequest::relPathFromKey($key);
         $triplet = array($this->attachmentTempPath, 'public', $pathRel);
         $status = $repo->storeBatch(array($triplet), FSRepo::OVERWRITE_SAME);
         // save!
         if (!$status->isOk()) {
             $dbw->rollback();
             return array('acct_request_file_store_error', $context->msg('filecopyerror', $this->attachmentTempPath, $pathRel)->escaped());
         }
     }
     $expires = null;
     // passed by reference
     $token = ConfirmAccount::getConfirmationToken($u, $expires);
     # Insert into pending requests...
     $req = UserAccountRequest::newFromArray(array('name' => $u->getName(), 'email' => $u->getEmail(), 'real_name' => $u->getRealName(), 'registration' => $this->registration, 'bio' => $this->bio, 'notes' => $this->notes, 'urls' => $this->urls, 'filename' => isset($this->attachmentSrcName) ? $this->attachmentSrcName : null, 'type' => $this->type, 'areas' => $this->areas, 'storage_key' => isset($key) ? $key : null, 'comment' => '', 'email_token' => md5($token), 'email_token_expires' => $expires, 'ip' => $this->ip, 'xff' => $this->xff, 'agent' => $this->agent));
     $req->insertOn();
     # Send confirmation, required!
     $result = ConfirmAccount::sendConfirmationMail($u, $this->ip, $token, $expires);
     if (!$result->isOK()) {
         $dbw->rollback();
         // nevermind
         if (isset($repo) && isset($pathRel)) {
             // remove attachment
             $repo->cleanupBatch(array(array('public', $pathRel)));
         }
         $param = $context->getOutput()->parse($result->getWikiText());
         return array('acct_request_mail_failed', $context->msg('mailerror')->rawParams($param)->escaped());
     }
     $dbw->commit();
     # Clear cache for notice of how many account requests there are
     ConfirmAccount::clearAccountRequestCountCache();
     # No request spamming...
     if ($wgAccountRequestThrottle && $reqUser->isPingLimitable()) {
         $ip = $context->getRequest()->getIP();
         $key = wfMemcKey('acctrequest', 'ip', $ip);
         $value = $wgMemc->incr($key);
         if (!$value) {
             $wgMemc->set($key, 1, 86400);
         }
     }
     # Done!
     return array(true, null);
 }
示例#29
0
	/**
	 * @param $user User
	 * @param $context IContextSource
	 * @param $defaultPreferences
	 * @return void
	 */
	static function profilePreferences( $user, IContextSource $context, &$defaultPreferences ) {
		global $wgAuth, $wgContLang, $wgParser, $wgCookieExpiration, $wgLanguageCode,
			$wgDisableTitleConversion, $wgDisableLangConversion, $wgMaxSigChars,
			$wgEnableEmail, $wgEmailConfirmToEdit, $wgEnableUserEmail, $wgEmailAuthentication,
			$wgEnotifWatchlist, $wgEnotifUserTalk, $wgEnotifRevealEditorAddress,
			$wgSecureLogin;

		// retrieving user name for GENDER and misc.
		$userName = $user->getName();

		## User info #####################################
		// Information panel
		$defaultPreferences['username'] = array(
			'type' => 'info',
			'label-message' => array( 'username', $userName ),
			'default' => $userName,
			'section' => 'personal/info',
		);

		$defaultPreferences['userid'] = array(
			'type' => 'info',
			'label-message' => array( 'uid', $userName ),
			'default' => $user->getId(),
			'section' => 'personal/info',
		);

		# Get groups to which the user belongs
		$userEffectiveGroups = $user->getEffectiveGroups();
		$userGroups = $userMembers = array();
		foreach ( $userEffectiveGroups as $ueg ) {
			if ( $ueg == '*' ) {
				// Skip the default * group, seems useless here
				continue;
			}
			$groupName = User::getGroupName( $ueg );
			$userGroups[] = User::makeGroupLinkHTML( $ueg, $groupName );

			$memberName = User::getGroupMember( $ueg, $userName );
			$userMembers[] = User::makeGroupLinkHTML( $ueg, $memberName );
		}
		asort( $userGroups );
		asort( $userMembers );

		$lang = $context->getLanguage();

		$defaultPreferences['usergroups'] = array(
			'type' => 'info',
			'label' => $context->msg( 'prefs-memberingroups' )->numParams(
				count( $userGroups ) )->params( $userName )->parse(),
			'default' => $context->msg( 'prefs-memberingroups-type',
				$lang->commaList( $userGroups ),
				$lang->commaList( $userMembers )
			)->plain(),
			'raw' => true,
			'section' => 'personal/info',
		);

		$editCount = Linker::link( SpecialPage::getTitleFor( "Contributions", $userName ),
			$lang->formatNum( $user->getEditCount() ) );

		$defaultPreferences['editcount'] = array(
			'type' => 'info',
			'raw' => true,
			'label-message' => 'prefs-edits',
			'default' => $editCount,
			'section' => 'personal/info',
		);

		if ( $user->getRegistration() ) {
			$displayUser = $context->getUser();
			$userRegistration = $user->getRegistration();
			$defaultPreferences['registrationdate'] = array(
				'type' => 'info',
				'label-message' => 'prefs-registration',
				'default' => $context->msg(
					'prefs-registration-date-time',
					$lang->userTimeAndDate( $userRegistration, $displayUser ),
					$lang->userDate( $userRegistration, $displayUser ),
					$lang->userTime( $userRegistration, $displayUser )
				)->parse(),
				'section' => 'personal/info',
			);
		}

		$canViewPrivateInfo = $user->isAllowed( 'viewmyprivateinfo' );
		$canEditPrivateInfo = $user->isAllowed( 'editmyprivateinfo' );

		// Actually changeable stuff
		$defaultPreferences['realname'] = array(
			// (not really "private", but still shouldn't be edited without permission)
			'type' => $canEditPrivateInfo && $wgAuth->allowPropChange( 'realname' ) ? 'text' : 'info',
			'default' => $user->getRealName(),
			'section' => 'personal/info',
			'label-message' => 'yourrealname',
			'help-message' => 'prefs-help-realname',
		);

		if ( $canEditPrivateInfo && $wgAuth->allowPasswordChange() ) {
			$link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ),
				$context->msg( 'prefs-resetpass' )->escaped(), array(),
				array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) );

			$defaultPreferences['password'] = array(
				'type' => 'info',
				'raw' => true,
				'default' => $link,
				'label-message' => 'yourpassword',
				'section' => 'personal/info',
			);
		}
		if ( $wgCookieExpiration > 0 ) {
			$defaultPreferences['rememberpassword'] = array(
				'type' => 'toggle',
				'label' => $context->msg( 'tog-rememberpassword' )->numParams(
					ceil( $wgCookieExpiration / ( 3600 * 24 ) ) )->text(),
				'section' => 'personal/info',
			);
		}
		// Only show preferhttps if secure login is turned on
		if ( $wgSecureLogin && wfCanIPUseHTTPS( $context->getRequest()->getIP() ) ) {
			$defaultPreferences['prefershttps'] = array(
				'type' => 'toggle',
				'label-message' => 'tog-prefershttps',
				'help-message' => 'prefs-help-prefershttps',
				'section' => 'personal/info'
			);
		}

		// Language
		$languages = Language::fetchLanguageNames( null, 'mw' );
		if ( !array_key_exists( $wgLanguageCode, $languages ) ) {
			$languages[$wgLanguageCode] = $wgLanguageCode;
		}
		ksort( $languages );

		$options = array();
		foreach ( $languages as $code => $name ) {
			$display = wfBCP47( $code ) . ' - ' . $name;
			$options[$display] = $code;
		}
		$defaultPreferences['language'] = array(
			'type' => 'select',
			'section' => 'personal/i18n',
			'options' => $options,
			'label-message' => 'yourlanguage',
		);

		$defaultPreferences['gender'] = array(
			'type' => 'radio',
			'section' => 'personal/i18n',
			'options' => array(
				$context->msg( 'parentheses',
					$context->msg( 'gender-unknown' )->text()
				)->text() => 'unknown',
				$context->msg( 'gender-female' )->text() => 'female',
				$context->msg( 'gender-male' )->text() => 'male',
			),
			'label-message' => 'yourgender',
			'help-message' => 'prefs-help-gender',
		);

		// see if there are multiple language variants to choose from
		if ( !$wgDisableLangConversion ) {
			foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
				if ( $langCode == $wgContLang->getCode() ) {
					$variants = $wgContLang->getVariants();

					if ( count( $variants ) <= 1 ) {
						continue;
					}

					$variantArray = array();
					foreach ( $variants as $v ) {
						$v = str_replace( '_', '-', strtolower( $v ) );
						$variantArray[$v] = $lang->getVariantname( $v, false );
					}

					$options = array();
					foreach ( $variantArray as $code => $name ) {
						$display = wfBCP47( $code ) . ' - ' . $name;
						$options[$display] = $code;
					}

					$defaultPreferences['variant'] = array(
						'label-message' => 'yourvariant',
						'type' => 'select',
						'options' => $options,
						'section' => 'personal/i18n',
						'help-message' => 'prefs-help-variant',
					);

					if ( !$wgDisableTitleConversion ) {
						$defaultPreferences['noconvertlink'] = array(
							'type' => 'toggle',
							'section' => 'personal/i18n',
							'label-message' => 'tog-noconvertlink',
						);
					}
				} else {
					$defaultPreferences["variant-$langCode"] = array(
						'type' => 'api',
					);
				}
			}
		}

		// Stuff from Language::getExtraUserToggles()
		// FIXME is this dead code? $extraUserToggles doesn't seem to be defined for any language
		$toggles = $wgContLang->getExtraUserToggles();

		foreach ( $toggles as $toggle ) {
			$defaultPreferences[$toggle] = array(
				'type' => 'toggle',
				'section' => 'personal/i18n',
				'label-message' => "tog-$toggle",
			);
		}

		// show a preview of the old signature first
		$oldsigWikiText = $wgParser->preSaveTransform( "~~~", $context->getTitle(), $user, ParserOptions::newFromContext( $context ) );
		$oldsigHTML = $context->getOutput()->parseInline( $oldsigWikiText, true, true );
		$defaultPreferences['oldsig'] = array(
			'type' => 'info',
			'raw' => true,
			'label-message' => 'tog-oldsig',
			'default' => $oldsigHTML,
			'section' => 'personal/signature',
		);
		$defaultPreferences['nickname'] = array(
			'type' => $wgAuth->allowPropChange( 'nickname' ) ? 'text' : 'info',
			'maxlength' => $wgMaxSigChars,
			'label-message' => 'yournick',
			'validation-callback' => array( 'Preferences', 'validateSignature' ),
			'section' => 'personal/signature',
			'filter-callback' => array( 'Preferences', 'cleanSignature' ),
		);
		$defaultPreferences['fancysig'] = array(
			'type' => 'toggle',
			'label-message' => 'tog-fancysig',
			'help-message' => 'prefs-help-signature', // show general help about signature at the bottom of the section
			'section' => 'personal/signature'
		);

		## Email stuff

		if ( $wgEnableEmail ) {
			if ( $canViewPrivateInfo ) {
				$helpMessages[] = $wgEmailConfirmToEdit
						? 'prefs-help-email-required'
						: 'prefs-help-email';

				if ( $wgEnableUserEmail ) {
					// additional messages when users can send email to each other
					$helpMessages[] = 'prefs-help-email-others';
				}

				$emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
				if ( $canEditPrivateInfo && $wgAuth->allowPropChange( 'emailaddress' ) ) {
					$link = Linker::link(
						SpecialPage::getTitleFor( 'ChangeEmail' ),
						$context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(),
						array(),
						array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) );

					$emailAddress .= $emailAddress == '' ? $link : (
						$context->msg( 'word-separator' )->plain()
						. $context->msg( 'parentheses' )->rawParams( $link )->plain()
					);
				}

				$defaultPreferences['emailaddress'] = array(
					'type' => 'info',
					'raw' => true,
					'default' => $emailAddress,
					'label-message' => 'youremail',
					'section' => 'personal/email',
					'help-messages' => $helpMessages,
					# 'cssclass' chosen below
				);
			}

			$disableEmailPrefs = false;

			if ( $wgEmailAuthentication ) {
				$emailauthenticationclass = 'mw-email-not-authenticated';
				if ( $user->getEmail() ) {
					if ( $user->getEmailAuthenticationTimestamp() ) {
						// date and time are separate parameters to facilitate localisation.
						// $time is kept for backward compat reasons.
						// 'emailauthenticated' is also used in SpecialConfirmemail.php
						$displayUser = $context->getUser();
						$emailTimestamp = $user->getEmailAuthenticationTimestamp();
						$time = $lang->userTimeAndDate( $emailTimestamp, $displayUser );
						$d = $lang->userDate( $emailTimestamp, $displayUser );
						$t = $lang->userTime( $emailTimestamp, $displayUser );
						$emailauthenticated = $context->msg( 'emailauthenticated',
							$time, $d, $t )->parse() . '<br />';
						$disableEmailPrefs = false;
						$emailauthenticationclass = 'mw-email-authenticated';
					} else {
						$disableEmailPrefs = true;
						$emailauthenticated = $context->msg( 'emailnotauthenticated' )->parse() . '<br />' .
							Linker::linkKnown(
								SpecialPage::getTitleFor( 'Confirmemail' ),
								$context->msg( 'emailconfirmlink' )->escaped()
							) . '<br />';
						$emailauthenticationclass = "mw-email-not-authenticated";
					}
				} else {
					$disableEmailPrefs = true;
					$emailauthenticated = $context->msg( 'noemailprefs' )->escaped();
					$emailauthenticationclass = 'mw-email-none';
				}

				if ( $canViewPrivateInfo ) {
					$defaultPreferences['emailauthentication'] = array(
						'type' => 'info',
						'raw' => true,
						'section' => 'personal/email',
						'label-message' => 'prefs-emailconfirm-label',
						'default' => $emailauthenticated,
						# Apply the same CSS class used on the input to the message:
						'cssclass' => $emailauthenticationclass,
					);
					$defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass;
				}
			}

			if ( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) {
				$defaultPreferences['disablemail'] = array(
					'type' => 'toggle',
					'invert' => true,
					'section' => 'personal/email',
					'label-message' => 'allowemail',
					'disabled' => $disableEmailPrefs,
				);
				$defaultPreferences['ccmeonemails'] = array(
					'type' => 'toggle',
					'section' => 'personal/email',
					'label-message' => 'tog-ccmeonemails',
					'disabled' => $disableEmailPrefs,
				);
			}

			if ( $wgEnotifWatchlist ) {
				$defaultPreferences['enotifwatchlistpages'] = array(
					'type' => 'toggle',
					'section' => 'personal/email',
					'label-message' => 'tog-enotifwatchlistpages',
					'disabled' => $disableEmailPrefs,
				);
			}
			if ( $wgEnotifUserTalk ) {
				$defaultPreferences['enotifusertalkpages'] = array(
					'type' => 'toggle',
					'section' => 'personal/email',
					'label-message' => 'tog-enotifusertalkpages',
					'disabled' => $disableEmailPrefs,
				);
			}
			if ( $wgEnotifUserTalk || $wgEnotifWatchlist ) {
				$defaultPreferences['enotifminoredits'] = array(
					'type' => 'toggle',
					'section' => 'personal/email',
					'label-message' => 'tog-enotifminoredits',
					'disabled' => $disableEmailPrefs,
				);

				if ( $wgEnotifRevealEditorAddress ) {
					$defaultPreferences['enotifrevealaddr'] = array(
						'type' => 'toggle',
						'section' => 'personal/email',
						'label-message' => 'tog-enotifrevealaddr',
						'disabled' => $disableEmailPrefs,
					);
				}
			}
		}
	}
 /**
  * @param $title Title
  * @param $summary string
  * @param $context IContextSource
  * @todo rework this to use a generic CollaborationList editor function once it exists
  */
 public static function postMemberList(Title $title, $summary, IContextSource $context)
 {
     $username = $context->getUser()->getName();
     $collabList = self::makeMemberList($username, $context->msg('collaborationkit-hub-members-description'));
     // Ensure that a valid context is provided to the API in unit tests
     $der = new DerivativeContext($context);
     $request = new DerivativeRequest($context->getRequest(), ['action' => 'edit', 'title' => $title->getFullText(), 'contentmodel' => 'CollaborationListContent', 'contentformat' => 'application/json', 'text' => $collabList->serialize(), 'summary' => $summary, 'token' => $context->getUser()->getEditToken()], true);
     $der->setRequest($request);
     try {
         $api = new ApiMain($der, true);
         $api->execute();
     } catch (UsageException $e) {
         return Status::newFatal($context->msg('collaborationkit-hub-edit-apierror', $e->getCodeString()));
     }
     return Status::newGood();
 }