/**
  * Hook function for EditFilterMergedContent
  *
  * @param IContextSource $context
  * @param Content        $content
  * @param Status         $status
  * @param string         $summary
  * @param User           $user
  * @param bool           $minoredit
  *
  * @return bool
  */
 static function filterMergedContent(IContextSource $context, Content $content, Status $status, $summary, User $user, $minoredit)
 {
     $title = $context->getTitle();
     if (isset($title->spamBlackListFiltered) && $title->spamBlackListFiltered) {
         // already filtered
         return true;
     }
     // get the link from the not-yet-saved page content.
     $editInfo = $context->getWikiPage()->prepareContentForEdit($content);
     $pout = $editInfo->output;
     $links = array_keys($pout->getExternalLinks());
     // HACK: treat the edit summary as a link
     if ($summary !== '') {
         $links[] = $summary;
     }
     $spamObj = BaseBlacklist::getInstance('spam');
     $matches = $spamObj->filter($links, $title);
     if ($matches !== false) {
         $status->fatal('spamprotectiontext');
         foreach ($matches as $match) {
             $status->fatal('spamprotectionmatch', $match);
         }
     }
     // Always return true, EditPage will look at $status->isOk().
     return true;
 }
示例#2
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__);
 }
示例#3
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__);
 }
示例#4
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();
 }
示例#5
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__);
 }
示例#6
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
  */
 public static final 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());
     if ($action instanceof Action) {
         return $action->getName();
     }
     return 'nosuchaction';
 }
 /**
  * Common implementation for the APIEditBeforeSave, EditFilterMerged
  * and EditFilterMergedContent hooks.
  *
  * @param IContextSource $context the context of the edit
  * @param Content|null $content the new Content generated by the edit
  * @param string $text new page content (subject of filtering)
  * @param Status $status  Error message to return
  * @param string $summary Edit summary for page
  * @param bool $minoredit whether this is a minor edit according to the user.
  *
  * @return bool
  */
 public static function filterEdit(IContextSource $context, $content, $text, Status $status, $summary, $minoredit)
 {
     // Load vars
     $vars = new AbuseFilterVariableHolder();
     $title = $context->getTitle();
     // Some edits are running through multiple hooks, but we only want to filter them once
     if (isset($title->editAlreadyFiltered)) {
         return true;
     } elseif ($title) {
         $title->editAlreadyFiltered = true;
     }
     self::$successful_action_vars = false;
     self::$last_edit_page = false;
     $user = $context->getUser();
     // Check for null edits.
     $oldtext = '';
     $oldcontent = null;
     if ($title instanceof Title && $title->canExist() && $title->exists()) {
         // Make sure we load the latest text saved in database (bug 31656)
         $page = $context->getWikiPage();
         $revision = $page->getRevision();
         if (!$revision) {
             return true;
         }
         if (defined('MW_SUPPORTS_CONTENTHANDLER')) {
             $oldcontent = $revision->getContent(Revision::RAW);
             $oldtext = AbuseFilter::contentToString($oldcontent);
         } else {
             $oldtext = AbuseFilter::revisionToString($revision, Revision::RAW);
         }
         // Cache article object so we can share a parse operation
         $articleCacheKey = $title->getNamespace() . ':' . $title->getText();
         AFComputedVariable::$articleCache[$articleCacheKey] = $page;
     } else {
         $page = null;
     }
     // Don't trigger for null edits.
     if ($content && $oldcontent && $oldcontent->equals($content)) {
         // Compare Content objects if available
         return true;
     } else {
         if (strcmp($oldtext, $text) == 0) {
             // Otherwise, compare strings
             return true;
         }
     }
     $vars->addHolders(AbuseFilter::generateUserVars($user), AbuseFilter::generateTitleVars($title, 'ARTICLE'));
     $vars->setVar('action', 'edit');
     $vars->setVar('summary', $summary);
     $vars->setVar('minor_edit', $minoredit);
     $vars->setVar('old_wikitext', $oldtext);
     $vars->setVar('new_wikitext', $text);
     // TODO: set old_content and new_content vars, use them
     $vars->addHolders(AbuseFilter::getEditVars($title, $page));
     $filter_result = AbuseFilter::filterAction($vars, $title);
     if (!$filter_result->isOK()) {
         $status->merge($filter_result);
         return true;
         // re-show edit form
     }
     self::$successful_action_vars = $vars;
     self::$last_edit_page = $page;
     return true;
 }
 private function main()
 {
     global $wgTitle;
     $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;
     $trxProfiler = Profiler::instance()->getTransactionProfiler();
     $trxProfiler->setLogger(LoggerFactory::getInstance('DBPerformance'));
     // Aside from rollback, master queries should not happen on GET requests.
     // Periodic or "in passing" updates on GET should use the job queue.
     if (!$request->wasPosted() && in_array($action, array('view', 'edit', 'history'))) {
         $trxProfiler->setExpectation('masterConns', 0, __METHOD__);
         $trxProfiler->setExpectation('writes', 0, __METHOD__);
     } else {
         $trxProfiler->setExpectation('maxAffected', 500, __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' && ($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', array($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);
             $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();
             return;
         }
     }
     if ($this->config->get('UseFileCache') && $title->getNamespace() >= 0) {
         if (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 (!$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();
                 return;
             }
         }
     }
     // 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();
 }