コード例 #1
0
 public function testExecute_email()
 {
     $config = new HashConfig(['PasswordResetRoutes' => ['username' => true, 'email' => true], 'EnableEmail' => true]);
     $authManager = $this->getMockBuilder(AuthManager::class)->disableOriginalConstructor()->getMock();
     $authManager->expects($this->any())->method('allowsAuthenticationDataChange')->willReturn(Status::newGood());
     $authManager->expects($this->exactly(2))->method('changeAuthenticationData');
     $request = new FauxRequest();
     $request->setIP('1.2.3.4');
     $performingUser = $this->getMock(User::class);
     $performingUser->expects($this->any())->method('getRequest')->willReturn($request);
     $performingUser->expects($this->any())->method('isAllowed')->willReturn(true);
     $targetUser1 = $this->getMock(User::class);
     $targetUser2 = $this->getMock(User::class);
     $targetUser1->expects($this->any())->method('getName')->willReturn('User1');
     $targetUser2->expects($this->any())->method('getName')->willReturn('User2');
     $targetUser1->expects($this->any())->method('getId')->willReturn(1);
     $targetUser2->expects($this->any())->method('getId')->willReturn(2);
     $targetUser1->expects($this->any())->method('getEmail')->willReturn('*****@*****.**');
     $targetUser2->expects($this->any())->method('getEmail')->willReturn('*****@*****.**');
     $passwordReset = $this->getMockBuilder(PasswordReset::class)->setMethods(['getUsersByEmail'])->setConstructorArgs([$config, $authManager])->getMock();
     $passwordReset->expects($this->any())->method('getUsersByEmail')->with('*****@*****.**')->willReturn([$targetUser1, $targetUser2]);
     $status = $passwordReset->isAllowed($performingUser);
     $this->assertTrue($status->isGood());
     $status = $passwordReset->execute($performingUser, null, '*****@*****.**');
     $this->assertTrue($status->isGood());
 }
コード例 #2
0
 /**
  * @covers FauxRequest::setHeader
  * @covers FauxRequest::getHeader
  */
 public function testGetSetHeader()
 {
     $value = 'test/test';
     $request = new FauxRequest();
     $request->setHeader('Content-Type', $value);
     $this->assertEquals($request->getHeader('Content-Type'), $value);
     $this->assertEquals($request->getHeader('CONTENT-TYPE'), $value);
     $this->assertEquals($request->getHeader('content-type'), $value);
 }
コード例 #3
0
ファイル: ApiTestCase.php プロジェクト: eFFemeer/seizamcore
 protected function doApiRequest($params, $session = null, $appendModule = false)
 {
     if (is_null($session)) {
         $session = array();
     }
     $request = new FauxRequest($params, true, $session);
     $module = new ApiMain($request, true);
     $module->execute();
     $results = array($module->getResultData(), $request, $request->getSessionArray());
     if ($appendModule) {
         $results[] = $module;
     }
     return $results;
 }
コード例 #4
0
 /**
  * @dataProvider provideTryNormaliseRedirect
  * @covers MediaWiki::tryNormaliseRedirect
  */
 public function testTryNormaliseRedirect($url, $query, $title, $expectedRedirect = false)
 {
     // Set SERVER because interpolateTitle() doesn't use getRequestURL(),
     // whereas tryNormaliseRedirect does().
     $_SERVER['REQUEST_URI'] = $url;
     $req = new FauxRequest($query);
     $req->setRequestURL($url);
     // This adds a virtual 'title' query parameter. Normally called from Setup.php
     $req->interpolateTitle();
     $titleObj = Title::newFromText($title);
     // Set global context since some involved code paths don't yet have context
     $context = RequestContext::getMain();
     $context->setRequest($req);
     $context->setTitle($titleObj);
     $mw = new MediaWiki($context);
     $method = new ReflectionMethod($mw, 'tryNormaliseRedirect');
     $method->setAccessible(true);
     $ret = $method->invoke($mw, $titleObj);
     $this->assertEquals($expectedRedirect !== false, $ret, 'Return true only when redirecting');
     $this->assertEquals($expectedRedirect ?: '', $context->getOutput()->getRedirect());
 }
コード例 #5
0
ファイル: FauxRequestTest.php プロジェクト: D66Ha/mediawiki
 /**
  * @covers FauxRequest::setHeader
  * @covers FauxRequest::getHeader
  */
 public function testGetSetHeader()
 {
     $value = 'text/plain, text/html';
     $request = new FauxRequest();
     $request->setHeader('Accept', $value);
     $this->assertEquals($request->getHeader('Nonexistent'), false);
     $this->assertEquals($request->getHeader('Accept'), $value);
     $this->assertEquals($request->getHeader('ACCEPT'), $value);
     $this->assertEquals($request->getHeader('accept'), $value);
     $this->assertEquals($request->getHeader('Accept', WebRequest::GETHEADER_LIST), array('text/plain', 'text/html'));
 }
コード例 #6
0
 public function testGetSessionIdFromCookie()
 {
     $this->setMwGlobals('wgCookiePrefix', 'wgCookiePrefix');
     $request = new \FauxRequest();
     $request->setCookies(array('' => 'empty---------------------------', 'Foo' => 'foo-----------------------------', 'wgCookiePrefixFoo' => 'wgfoo---------------------------', 'BarFoo' => 'foobar--------------------------', 'bad' => 'bad'), '');
     $provider = \TestingAccessWrapper::newFromObject($this->getProvider(null));
     try {
         $provider->getSessionIdFromCookie($request);
         $this->fail('Expected exception not thrown');
     } catch (\BadMethodCallException $ex) {
         $this->assertSame('MediaWiki\\Session\\ImmutableSessionProviderWithCookie::getSessionIdFromCookie ' . 'may not be called when $this->sessionCookieName === null', $ex->getMessage());
     }
     $provider = \TestingAccessWrapper::newFromObject($this->getProvider('Foo'));
     $this->assertSame('wgfoo---------------------------', $provider->getSessionIdFromCookie($request));
     $provider = \TestingAccessWrapper::newFromObject($this->getProvider('Foo', 'Bar'));
     $this->assertSame('foobar--------------------------', $provider->getSessionIdFromCookie($request));
     $provider = \TestingAccessWrapper::newFromObject($this->getProvider('Foo', ''));
     $this->assertSame('foo-----------------------------', $provider->getSessionIdFromCookie($request));
     $provider = \TestingAccessWrapper::newFromObject($this->getProvider('bad', ''));
     $this->assertSame(null, $provider->getSessionIdFromCookie($request));
     $provider = \TestingAccessWrapper::newFromObject($this->getProvider('none', ''));
     $this->assertSame(null, $provider->getSessionIdFromCookie($request));
 }
コード例 #7
0
 /**
  * Execute the requested Api actions.
  * @todo: Write some unit tests for API results
  */
 public function execute()
 {
     // Logged-in users' parser options depend on preferences
     $this->getMain()->setCacheMode('anon-public-user-private');
     // Enough '*' keys in JSON!!!
     $isXml = $this->getMain()->isInternalMode() || $this->getMain()->getPrinter()->getFormat() == 'XML';
     $textElement = $isXml ? '*' : 'text';
     $params = $this->extractRequestParams();
     $prop = array_flip($params['prop']);
     $sectionProp = array_flip($params['sectionprop']);
     $this->variant = $params['variant'];
     $this->followRedirects = $params['redirect'] == 'yes';
     $this->noHeadings = $params['noheadings'];
     $this->noTransform = $params['notransform'];
     $onlyRequestedSections = $params['onlyrequestedsections'];
     $this->offset = $params['offset'];
     $this->maxlen = $params['maxlen'];
     if ($this->offset === 0 && $this->maxlen === 0) {
         $this->offset = -1;
         // Disable text splitting
     } elseif ($this->maxlen === 0) {
         $this->maxlen = PHP_INT_MAX;
     }
     $title = $this->makeTitle($params['page']);
     // See whether the actual page (or if enabled, the redirect target) is the main page
     $this->mainPage = $this->isMainPage($title);
     if ($this->mainPage && $this->noHeadings) {
         $this->noHeadings = false;
         $this->setWarning("``noheadings'' makes no sense on the main page, ignoring");
     }
     if (isset($prop['normalizedtitle']) && $title->getPrefixedText() != $params['page']) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('normalizedtitle' => $title->getPageLanguage()->convert($title->getPrefixedText())));
     }
     $data = $this->getData($title, $params['noimages']);
     // Bug 73109: #getData will return an empty array if the title redirects to
     // a page in a virtual namespace (NS_SPECIAL, NS_MEDIA), so make sure that
     // the requested data exists too.
     if (isset($prop['lastmodified']) && isset($data['lastmodified'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('lastmodified' => $data['lastmodified']));
     }
     if (isset($prop['lastmodifiedby']) && isset($data['lastmodifiedby'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('lastmodifiedby' => $data['lastmodifiedby']));
     }
     if (isset($prop['revision']) && isset($data['revision'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('revision' => $data['revision']));
     }
     if (isset($prop['id']) && isset($data['id'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('id' => $data['id']));
     }
     if (isset($prop['languagecount']) && isset($data['languagecount'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('languagecount' => $data['languagecount']));
     }
     if (isset($prop['hasvariants']) && isset($data['hasvariants'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('hasvariants' => $data['hasvariants']));
     }
     if (isset($prop['displaytitle']) && isset($data['displaytitle'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('displaytitle' => $data['displaytitle']));
     }
     if (isset($prop['pageprops'])) {
         $propNames = $params['pageprops'];
         if ($propNames == '*' && isset($data['pageprops'])) {
             $pageProps = $data['pageprops'];
         } else {
             $propNames = explode('|', $propNames);
             $pageProps = array_intersect_key($data['pageprops'], array_flip($propNames));
         }
         $this->getResult()->addValue(null, $this->getModuleName(), array('pageprops' => $pageProps));
     }
     if (isset($prop['description']) && isset($data['pageprops']['wikibase_item'])) {
         $desc = ExtMobileFrontend::getWikibaseDescription($data['pageprops']['wikibase_item']);
         if ($desc) {
             $this->getResult()->addValue(null, $this->getModuleName(), array('description' => $desc));
         }
     }
     if ($this->usePageImages) {
         $this->addPageImage($data, $params, $prop);
     }
     $result = array();
     $missingSections = array();
     if ($this->mainPage) {
         if ($onlyRequestedSections) {
             $requestedSections = self::parseSections($params['sections'], $data, $missingSections);
         } else {
             $requestedSections = array(0);
         }
         $this->getResult()->addValue(null, $this->getModuleName(), array('mainpage' => ''));
     } elseif (isset($params['sections'])) {
         $requestedSections = self::parseSections($params['sections'], $data, $missingSections);
     } else {
         $requestedSections = array();
     }
     if (isset($data['sections'])) {
         if (isset($prop['sections'])) {
             $sectionCount = count($data['sections']);
             for ($i = 0; $i <= $sectionCount; $i++) {
                 if (!isset($requestedSections[$i]) && $onlyRequestedSections) {
                     continue;
                 }
                 $section = array();
                 if ($i > 0) {
                     $section = array_intersect_key($data['sections'][$i - 1], $sectionProp);
                 }
                 $section['id'] = $i;
                 if (isset($prop['text']) && isset($requestedSections[$i]) && isset($data['text'][$i])) {
                     $section[$textElement] = $this->stringSplitter($this->prepareSection($data['text'][$i]));
                     unset($requestedSections[$i]);
                 }
                 if (isset($data['refsections'][$i])) {
                     $section['references'] = '';
                 }
                 $result[] = $section;
             }
             $missingSections = array_keys($requestedSections);
         } else {
             foreach (array_keys($requestedSections) as $index) {
                 $section = array('id' => $index);
                 if (isset($data['text'][$index])) {
                     $section[$textElement] = $this->stringSplitter($this->prepareSection($data['text'][$index]));
                 } else {
                     $missingSections[] = $index;
                 }
                 $result[] = $section;
             }
         }
         $this->getResult()->setIndexedTagName($result, 'section');
         $this->getResult()->addValue(null, $this->getModuleName(), array('sections' => $result));
     }
     if (isset($prop['protection'])) {
         $this->addProtection($title);
     }
     if (isset($prop['editable'])) {
         $user = $this->getUser();
         if ($user->isAnon()) {
             // HACK: Anons receive cached information, so don't check blocked status for them
             // to avoid them receiving false positives. Currently there is no way to check
             // all permissions except blocked status from the Title class.
             $req = new FauxRequest();
             $req->setIP('127.0.0.1');
             $user = User::newFromSession($req);
         }
         $editable = $title->quickUserCan('edit', $user);
         if ($isXml) {
             $editable = intval($editable);
         }
         $this->getResult()->addValue(null, $this->getModuleName(), array('editable' => $editable));
     }
     // https://bugzilla.wikimedia.org/show_bug.cgi?id=51586
     // Inform ppl if the page is infested with LiquidThreads but that's the
     // only thing we support about it.
     if (class_exists('LqtDispatch') && LqtDispatch::isLqtPage($title)) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('liquidthreads' => ''));
     }
     if (count($missingSections) && isset($prop['text'])) {
         $this->setWarning('Section(s) ' . implode(', ', $missingSections) . ' not found');
     }
     if ($this->maxlen < 0) {
         // There is more data available
         $this->getResult()->addValue(null, $this->getModuleName(), array('continue-offset' => $params['offset'] + $params['maxlen']));
     }
 }
コード例 #8
0
 /**
  * Test conditional headers output
  * @dataProvider provideConditionalRequestHeadersOutput
  * @param array $conditions Return data for ApiBase::getConditionalRequestData
  * @param array $headers Expected output headers
  * @param bool $isError $isError flag
  * @param bool $post Request is a POST
  */
 public function testConditionalRequestHeadersOutput($conditions, $headers, $isError = false, $post = false)
 {
     $request = new FauxRequest(array('action' => 'query', 'meta' => 'siteinfo'), $post);
     $response = $request->response();
     $api = new ApiMain($request);
     $priv = TestingAccessWrapper::newFromObject($api);
     $priv->mInternalMode = false;
     $module = $this->getMockBuilder('ApiBase')->setConstructorArgs(array($api, 'mock'))->setMethods(array('getConditionalRequestData'))->getMockForAbstractClass();
     $module->expects($this->any())->method('getConditionalRequestData')->will($this->returnCallback(function ($condition) use($conditions) {
         return isset($conditions[$condition]) ? $conditions[$condition] : null;
     }));
     $priv->mModule = $module;
     $priv->sendCacheHeaders($isError);
     foreach (array('Last-Modified', 'ETag') as $header) {
         $this->assertEquals(isset($headers[$header]) ? $headers[$header] : null, $response->getHeader($header), $header);
     }
 }
コード例 #9
0
 /**
  * @covers FauxRequest::getHeader
  */
 public function testGetHeader()
 {
     $_SERVER['HTTP_TEST'] = 'Example';
     $request = new FauxRequest();
     $this->assertEquals(false, $request->getHeader('test'));
 }
コード例 #10
0
 /**
  * @covers ApiMain::lacksSameOriginSecurity
  */
 public function testLacksSameOriginSecurity()
 {
     // Basic test
     $main = new ApiMain(new FauxRequest(array('action' => 'query', 'meta' => 'siteinfo')));
     $this->assertFalse($main->lacksSameOriginSecurity(), 'Basic test, should have security');
     // JSONp
     $main = new ApiMain(new FauxRequest(array('action' => 'query', 'format' => 'xml', 'callback' => 'foo')));
     $this->assertTrue($main->lacksSameOriginSecurity(), 'JSONp, should lack security');
     // Header
     $request = new FauxRequest(array('action' => 'query', 'meta' => 'siteinfo'));
     $request->setHeader('TrEaT-As-UnTrUsTeD', '');
     // With falsey value!
     $main = new ApiMain($request);
     $this->assertTrue($main->lacksSameOriginSecurity(), 'Header supplied, should lack security');
     // Hook
     $this->mergeMwGlobalArrayValue('wgHooks', array('RequestHasSameOriginSecurity' => array(function () {
         return false;
     })));
     $main = new ApiMain(new FauxRequest(array('action' => 'query', 'meta' => 'siteinfo')));
     $this->assertTrue($main->lacksSameOriginSecurity(), 'Hook, should lack security');
 }
コード例 #11
0
 public function __construct($url, array $cookies = array())
 {
     $this->url = $url;
     $query = array();
     if ($url) {
         $params = wfParseUrl(wfExpandUrl($url));
         if (isset($params['query'])) {
             $query = wfCgiToArray($params['query']);
         }
     }
     parent::__construct($query);
     $this->cookies = $cookies;
     $this->response = new FauxResponse();
 }
コード例 #12
0
 /**
  * Depending on the requested action this method will try to store/preview
  * the data in mOptions or retrieve the edit form.
  *
  * The form and target page will be available in mOptions after execution of
  * the method.
  *
  * Errors and warnings are logged in the API result under the 'errors' key.
  * The general request status is maintained in mStatus.
  *
  * @global $wgRequest
  * @global $wgOut
  * @global SFFormPrinter $sfgFormPrinter
  * @throws MWException
  */
 public function doAction()
 {
     global $wgOut, $wgParser, $wgRequest, $sfgFormPrinter;
     // if the wiki is read-only, do not save
     if (wfReadOnly()) {
         if ($this->mAction === self::ACTION_SAVE) {
             throw new MWException(wfMessage('sf_autoedit_readonly', wfReadOnlyReason())->parse());
         }
         // even if not saving notify client anyway. Might want to dislay a notice
         $this->logMessage(wfMessage('sf_autoedit_readonly', wfReadOnlyReason())->parse(), self::NOTICE);
     }
     // find the title of the form to be used
     $formTitle = $this->getFormTitle();
     // get the form content
     $formContent = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $this->getTextForPage($formTitle));
     // signals that the form was submitted
     // always true, else we would not be here
     $isFormSubmitted = $this->mAction === self::ACTION_SAVE || $this->mAction === self::ACTION_PREVIEW || $this->mAction === self::ACTION_DIFF;
     // the article id of the form to be used
     $formArticleId = $formTitle->getArticleID();
     // the name of the target page; might be empty when using the one-step-process
     $targetName = $this->mOptions['target'];
     // if the target page was not specified, try finding the page name formula
     // (Why is this not done in SFFormPrinter::formHTML?)
     if ($targetName === '') {
         // Parse the form to see if it has a 'page name' value set.
         if (preg_match('/{{{\\s*info.*page name\\s*=\\s*(.*)}}}/msU', $formContent, $matches)) {
             $pageNameElements = SFUtils::getFormTagComponents(trim($matches[1]));
             $targetNameFormula = $pageNameElements[0];
         } else {
             throw new MWException(wfMessage('sf_autoedit_notargetspecified')->parse());
         }
         $targetTitle = null;
     } else {
         $targetNameFormula = null;
         $targetTitle = Title::newFromText($targetName);
     }
     $preloadContent = '';
     // save $wgRequest for later restoration
     $oldRequest = $wgRequest;
     $pageExists = false;
     // preload data if not explicitly excluded and if the preload page exists
     if (!isset($this->mOptions['preload']) || $this->mOptions['preload'] !== false) {
         if (isset($this->mOptions['preload']) && is_string($this->mOptions['preload'])) {
             $preloadTitle = Title::newFromText($this->mOptions['preload']);
         } else {
             $preloadTitle = Title::newFromText($targetName);
         }
         if ($preloadTitle !== null && $preloadTitle->exists()) {
             // the content of the page that was specified to be used for preloading
             $preloadContent = $this->getTextForPage($preloadTitle);
             $pageExists = true;
         } else {
             if (isset($this->mOptions['preload'])) {
                 $this->logMessage(wfMessage('sf_autoedit_invalidpreloadspecified', $this->mOptions['preload'])->parse(), self::WARNING);
             }
         }
     }
     // Allow extensions to set/change the preload text, for new
     // pages.
     if (!$pageExists) {
         Hooks::run('sfEditFormPreloadText', array(&$preloadContent, $targetTitle, $formTitle));
     }
     // Flag to keep track of formHTML() runs.
     $formHtmlHasRun = false;
     if ($preloadContent !== '') {
         // @HACK - we need to set this for the preload to take
         // effect in the form.
         $pageExists = true;
         // Spoof $wgRequest for SFFormPrinter::formHTML().
         if (isset($_SESSION)) {
             $wgRequest = new FauxRequest($this->mOptions, true, $_SESSION);
         } else {
             $wgRequest = new FauxRequest($this->mOptions, true);
         }
         // Call SFFormPrinter::formHTML() to get at the form
         // HTML of the existing page.
         list($formHTML, $formJS, $targetContent, $form_page_title, $generatedTargetNameFormula) = $sfgFormPrinter->formHTML($formContent, $isFormSubmitted, $pageExists, $formArticleId, $preloadContent, $targetName, $targetNameFormula);
         // Parse the data to be preloaded from the form HTML of
         // the existing page.
         $data = $this->parseDataFromHTMLFrag($formHTML);
         // ...and merge/overwrite it with the new data.
         $this->mOptions = SFUtils::array_merge_recursive_distinct($data, $this->mOptions);
     }
     // We already preloaded stuff for saving/previewing -
     // do not do this again.
     if ($isFormSubmitted && !$wgRequest->getCheck('partial')) {
         $preloadContent = '';
         $pageExists = false;
     } else {
         // Source of the data is a page.
         $pageExists = is_a($targetTitle, 'Title') && $targetTitle->exists();
     }
     // Spoof $wgRequest for SFFormPrinter::formHTML().
     if (isset($_SESSION)) {
         $wgRequest = new FauxRequest($this->mOptions, true, $_SESSION);
     } else {
         $wgRequest = new FauxRequest($this->mOptions, true);
     }
     // get wikitext for submitted data and form
     list($formHTML, $formJS, $targetContent, $generatedFormName, $generatedTargetNameFormula) = $sfgFormPrinter->formHTML($formContent, $isFormSubmitted, $pageExists, $formArticleId, $preloadContent, $targetName, $targetNameFormula);
     // Restore original request.
     $wgRequest = $oldRequest;
     if ($generatedFormName !== '') {
         $formTitle = Title::newFromText($generatedFormName);
         $this->mOptions['formtitle'] = $formTitle->getText();
     }
     $this->mOptions['formHTML'] = $formHTML;
     $this->mOptions['formJS'] = $formJS;
     if ($isFormSubmitted) {
         // If the target page was not specified, see if
         // something was generated from the target name formula.
         if ($this->mOptions['target'] === '') {
             // If no name was generated, we cannot save => give up
             if ($generatedTargetNameFormula === '') {
                 throw new MWException(wfMessage('sf_autoedit_notargetspecified')->parse());
             }
             $this->mOptions['target'] = $this->generateTargetName($generatedTargetNameFormula);
         }
         // Lets other code process additional form-definition syntax
         Hooks::run('sfWritePageData', array($this->mOptions['form'], Title::newFromText($this->mOptions['target']), &$targetContent));
         $editor = $this->setupEditPage($targetContent);
         // Perform the requested action.
         if ($this->mAction === self::ACTION_PREVIEW) {
             $this->doPreview($editor);
         } else {
             if ($this->mAction === self::ACTION_DIFF) {
                 $this->doDiff($editor);
             } else {
                 $this->doStore($editor);
             }
         }
     } else {
         if ($this->mAction === self::ACTION_FORMEDIT) {
             $parserOutput = $wgParser->getOutput();
             if (method_exists($wgOut, 'addParserOutputMetadata')) {
                 $wgOut->addParserOutputMetadata($parserOutput);
             } else {
                 $wgOut->addParserOutputNoText($parserOutput);
             }
             $this->doFormEdit($formHTML, $formJS);
         }
     }
 }
コード例 #13
0
 private static function makeContext(ResourceLoaderContext $mainContext, $group, $type, array $extraQuery = [])
 {
     // Create new ResourceLoaderContext so that $extraQuery may trigger isRaw().
     $req = new FauxRequest(array_merge($mainContext->getRequest()->getValues(), $extraQuery));
     // Set 'only' if not combined
     $req->setVal('only', $type === ResourceLoaderModule::TYPE_COMBINED ? null : $type);
     // Remove user parameter in most cases
     if ($group !== 'user' && $group !== 'private') {
         $req->setVal('user', null);
     }
     $context = new ResourceLoaderContext($mainContext->getResourceLoader(), $req);
     // Allow caller to setVersion() and setModules()
     return new DerivativeResourceLoaderContext($context);
 }
コード例 #14
0
 public function testBug71329()
 {
     SpecialPageFactory::resetList();
     RequestContext::resetMain();
     $req = new FauxRequest(array('title' => 'Special:Search', 'mobileaction' => 'toggle_view_mobile'));
     $req->setRequestURL('/w/index.php?title=Special:Search&mobileaction=toggle_view_mobile');
     RequestContext::getMain()->setRequest($req);
     MobileContext::setInstance(null);
     $this->setMwGlobals('wgTitle', null);
     SpecialPage::getTitleFor('Search');
     $this->assertTrue(true, 'In case of failure this test just crashes');
 }
コード例 #15
0
 /**
  * @dataProvider provideCheckIpLimits
  */
 public function testCheckIpLimits($ip, $sessionData, $userData, $logLevel1, $logLevel2)
 {
     $this->setMwGlobals(array('wgSuspiciousIpPerSessionLimit' => 5, 'wgSuspiciousIpPerUserLimit' => 10, 'wgSuspiciousIpExpiry' => 600, 'wgSquidServers' => array('11.22.33.44')));
     $manager = new SessionManager();
     $logger = $this->getMock('\\Psr\\Log\\LoggerInterface');
     $this->setLogger('session-ip', $logger);
     $request = new \FauxRequest();
     $request->setIP($ip);
     $session = $manager->getSessionForRequest($request);
     /** @var SessionBackend $backend */
     $backend = \TestingAccessWrapper::newFromObject($session)->backend;
     $data =& $backend->getData();
     $data = array('SessionManager-ip' => $sessionData);
     $backend->setUser(User::newFromName('UTSysop'));
     $manager = \TestingAccessWrapper::newFromObject($manager);
     $manager->store->set('SessionManager-ip:' . md5('UTSysop'), $userData);
     $logger->expects($this->exactly(isset($logLevel1) + isset($logLevel2)))->method('log');
     if ($logLevel1) {
         $logger->expects($this->at(0))->method('log')->with($logLevel1, 'Same session used from {count} IPs', $this->isType('array'));
     }
     if ($logLevel2) {
         $logger->expects($this->at(isset($logLevel1)))->method('log')->with($logLevel2, 'Same user had sessions from {count} IPs', $this->isType('array'));
     }
     $manager->checkIpLimits($session);
 }
コード例 #16
0
 public function testGetCookie()
 {
     $provider = new CookieSessionProvider(['priority' => 1, 'sessionName' => 'MySessionName', 'cookieOptions' => ['prefix' => 'x']]);
     $provider->setLogger(new \Psr\Log\NullLogger());
     $provider->setConfig($this->getConfig());
     $provider->setManager(SessionManager::singleton());
     $provider = \TestingAccessWrapper::newFromObject($provider);
     $request = new \FauxRequest();
     $request->setCookies(['xFoo' => 'foo!', 'xBar' => 'deleted'], '');
     $this->assertSame('foo!', $provider->getCookie($request, 'Foo', 'x'));
     $this->assertNull($provider->getCookie($request, 'Bar', 'x'));
     $this->assertNull($provider->getCookie($request, 'Baz', 'x'));
 }
コード例 #17
0
 /**
  * Import the resolved user IP, HTTP headers, user ID, and session ID.
  * This sets the current session and sets $wgUser and $wgRequest.
  * Once the return value falls out of scope, the old context is restored.
  * This function can only be called within CLI mode scripts.
  *
  * This will setup the session from the given ID. This is useful when
  * background scripts inherit context when acting on behalf of a user.
  *
  * $param array $params Result of RequestContext::exportSession()
  * @return ScopedCallback
  * @throws MWException
  * @since 1.21
  */
 public static function importScopedSession(array $params)
 {
     if (PHP_SAPI !== 'cli') {
         // Don't send random private cookies or turn $wgRequest into FauxRequest
         throw new MWException("Sessions can only be imported in cli mode.");
     } elseif (!strlen($params['sessionId'])) {
         throw new MWException("No session ID was specified.");
     }
     if ($params['userId']) {
         // logged-in user
         $user = User::newFromId($params['userId']);
         if (!$user) {
             throw new MWException("No user with ID '{$params['userId']}'.");
         }
     } elseif (!IP::isValid($params['ip'])) {
         throw new MWException("Could not load user '{$params['ip']}'.");
     } else {
         // anon user
         $user = User::newFromName($params['ip'], false);
     }
     $importSessionFunction = function (User $user, array $params) {
         global $wgRequest, $wgUser;
         $context = RequestContext::getMain();
         // Commit and close any current session
         session_write_close();
         // persist
         session_id('');
         // detach
         $_SESSION = array();
         // clear in-memory array
         // Remove any user IP or agent information
         $context->setRequest(new FauxRequest());
         $wgRequest = $context->getRequest();
         // b/c
         // Now that all private information is detached from the user, it should
         // be safe to load the new user. If errors occur or an exception is thrown
         // and caught (leaving the main context in a mixed state), there is no risk
         // of the User object being attached to the wrong IP, headers, or session.
         $context->setUser($user);
         $wgUser = $context->getUser();
         // b/c
         if (strlen($params['sessionId'])) {
             // don't make a new random ID
             wfSetupSession($params['sessionId']);
             // sets $_SESSION
         }
         $request = new FauxRequest(array(), false, $_SESSION);
         $request->setIP($params['ip']);
         foreach ($params['headers'] as $name => $value) {
             $request->setHeader($name, $value);
         }
         // Set the current context to use the new WebRequest
         $context->setRequest($request);
         $wgRequest = $context->getRequest();
         // b/c
     };
     // Stash the old session and load in the new one
     $oUser = self::getMain()->getUser();
     $oParams = self::getMain()->exportSession();
     $importSessionFunction($user, $params);
     // Set callback to save and close the new session and reload the old one
     return new ScopedCallback(function () use($importSessionFunction, $oUser, $oParams) {
         $importSessionFunction($oUser, $oParams);
     });
 }
コード例 #18
0
 public function testSetLoggedOutCookie()
 {
     $provider = \TestingAccessWrapper::newFromObject(new CookieSessionProvider(array('priority' => 1, 'sessionName' => 'MySessionName', 'cookieOptions' => array('prefix' => 'x'))));
     $provider->setLogger(new \Psr\Log\NullLogger());
     $provider->setConfig($this->getConfig());
     $provider->setManager(SessionManager::singleton());
     $t1 = time();
     $t2 = time() - 86400 * 2;
     // Set it
     $request = new \FauxRequest();
     $provider->setLoggedOutCookie($t1, $request);
     $this->assertSame((string) $t1, $request->response()->getCookie('xLoggedOut'));
     // Too old
     $request = new \FauxRequest();
     $provider->setLoggedOutCookie($t2, $request);
     $this->assertSame(null, $request->response()->getCookie('xLoggedOut'));
     // Don't reset if it's already set
     $request = new \FauxRequest();
     $request->setCookies(array('xLoggedOut' => $t1), '');
     $provider->setLoggedOutCookie($t1, $request);
     $this->assertSame(null, $request->response()->getCookie('xLoggedOut'));
 }
コード例 #19
0
 public function testLogin()
 {
     // Test failure when bot passwords aren't enabled
     $this->setMwGlobals('wgEnableBotPasswords', false);
     $status = BotPassword::login("{$this->testUserName}@BotPassword", 'foobaz', new FauxRequest());
     $this->assertEquals(Status::newFatal('botpasswords-disabled'), $status);
     $this->setMwGlobals('wgEnableBotPasswords', true);
     // Test failure when BotPasswordSessionProvider isn't configured
     $manager = new SessionManager(['logger' => new Psr\Log\NullLogger(), 'store' => new EmptyBagOStuff()]);
     $reset = MediaWiki\Session\TestUtils::setSessionManagerSingleton($manager);
     $this->assertNull($manager->getProvider(MediaWiki\Session\BotPasswordSessionProvider::class), 'sanity check');
     $status = BotPassword::login("{$this->testUserName}@BotPassword", 'foobaz', new FauxRequest());
     $this->assertEquals(Status::newFatal('botpasswords-no-provider'), $status);
     ScopedCallback::consume($reset);
     // Now configure BotPasswordSessionProvider for further tests...
     $mainConfig = RequestContext::getMain()->getConfig();
     $config = new HashConfig(['SessionProviders' => $mainConfig->get('SessionProviders') + [MediaWiki\Session\BotPasswordSessionProvider::class => ['class' => MediaWiki\Session\BotPasswordSessionProvider::class, 'args' => [['priority' => 40]]]]]);
     $manager = new SessionManager(['config' => new MultiConfig([$config, RequestContext::getMain()->getConfig()]), 'logger' => new Psr\Log\NullLogger(), 'store' => new EmptyBagOStuff()]);
     $reset = MediaWiki\Session\TestUtils::setSessionManagerSingleton($manager);
     // No "@"-thing in the username
     $status = BotPassword::login($this->testUserName, 'foobaz', new FauxRequest());
     $this->assertEquals(Status::newFatal('botpasswords-invalid-name', '@'), $status);
     // No base user
     $status = BotPassword::login('UTDummy@BotPassword', 'foobaz', new FauxRequest());
     $this->assertEquals(Status::newFatal('nosuchuser', 'UTDummy'), $status);
     // No bot password
     $status = BotPassword::login("{$this->testUserName}@DoesNotExist", 'foobaz', new FauxRequest());
     $this->assertEquals(Status::newFatal('botpasswords-not-exist', $this->testUserName, 'DoesNotExist'), $status);
     // Failed restriction
     $request = $this->getMock('FauxRequest', ['getIP']);
     $request->expects($this->any())->method('getIP')->will($this->returnValue('10.0.0.1'));
     $status = BotPassword::login("{$this->testUserName}@BotPassword", 'foobaz', $request);
     $this->assertEquals(Status::newFatal('botpasswords-restriction-failed'), $status);
     // Wrong password
     $status = BotPassword::login("{$this->testUserName}@BotPassword", $this->testUser->password, new FauxRequest());
     $this->assertEquals(Status::newFatal('wrongpassword'), $status);
     // Success!
     $request = new FauxRequest();
     $this->assertNotInstanceOf(MediaWiki\Session\BotPasswordSessionProvider::class, $request->getSession()->getProvider(), 'sanity check');
     $status = BotPassword::login("{$this->testUserName}@BotPassword", 'foobaz', $request);
     $this->assertInstanceOf('Status', $status);
     $this->assertTrue($status->isGood());
     $session = $status->getValue();
     $this->assertInstanceOf(MediaWiki\Session\Session::class, $session);
     $this->assertInstanceOf(MediaWiki\Session\BotPasswordSessionProvider::class, $session->getProvider());
     $this->assertSame($session->getId(), $request->getSession()->getId());
     ScopedCallback::consume($reset);
 }
 public function testContinueLinkAttempt()
 {
     $user = \User::newFromName('UTSysop');
     $obj = new \stdClass();
     $reqs = $this->getLinkRequests();
     $done = [false, false, false];
     // First, test the pass-through for not containing the ConfirmLinkAuthenticationRequest
     $mock = $this->getMockBuilder(ConfirmLinkSecondaryAuthenticationProvider::class)->setMethods(['beginLinkAttempt'])->getMock();
     $mock->expects($this->once())->method('beginLinkAttempt')->with($this->identicalTo($user), $this->identicalTo('state'))->will($this->returnValue($obj));
     $this->assertSame($obj, \TestingAccessWrapper::newFromObject($mock)->continueLinkAttempt($user, 'state', $reqs));
     // Now test the actual functioning
     $provider = $this->getMockBuilder(ConfirmLinkSecondaryAuthenticationProvider::class)->setMethods(['beginLinkAttempt', 'providerAllowsAuthenticationDataChange', 'providerChangeAuthenticationData'])->getMock();
     $provider->expects($this->never())->method('beginLinkAttempt');
     $provider->expects($this->any())->method('providerAllowsAuthenticationDataChange')->will($this->returnCallback(function ($req) use($reqs) {
         return $req->getUniqueId() === 'Request3' ? \StatusValue::newFatal('foo') : \StatusValue::newGood();
     }));
     $provider->expects($this->any())->method('providerChangeAuthenticationData')->will($this->returnCallback(function ($req) use(&$done) {
         $done[$req->id] = true;
     }));
     $config = new \HashConfig(['AuthManagerConfig' => ['preauth' => [], 'primaryauth' => [], 'secondaryauth' => [['factory' => function () use($provider) {
         return $provider;
     }]]]]);
     $request = new \FauxRequest();
     $manager = new AuthManager($request, $config);
     $provider->setManager($manager);
     $provider = \TestingAccessWrapper::newFromObject($provider);
     $req = new ConfirmLinkAuthenticationRequest($reqs);
     $this->assertEquals(AuthenticationResponse::newAbstain(), $provider->continueLinkAttempt($user, 'state', [$req]));
     $request->getSession()->setSecret('state', ['maybeLink' => []]);
     $this->assertEquals(AuthenticationResponse::newAbstain(), $provider->continueLinkAttempt($user, 'state', [$req]));
     $request->getSession()->setSecret('state', ['maybeLink' => $reqs]);
     $this->assertEquals(AuthenticationResponse::newPass(), $res = $provider->continueLinkAttempt($user, 'state', [$req]));
     $this->assertSame([false, false, false], $done);
     $request->getSession()->setSecret('state', ['maybeLink' => [$reqs['Request2']]]);
     $req->confirmedLinkIDs = ['Request1', 'Request2'];
     $res = $provider->continueLinkAttempt($user, 'state', [$req]);
     $this->assertEquals(AuthenticationResponse::newPass(), $res);
     $this->assertSame([false, true, false], $done);
     $done = [false, false, false];
     $request->getSession()->setSecret('state', ['maybeLink' => $reqs]);
     $req->confirmedLinkIDs = ['Request1', 'Request2'];
     $res = $provider->continueLinkAttempt($user, 'state', [$req]);
     $this->assertEquals(AuthenticationResponse::newPass(), $res);
     $this->assertSame([true, true, false], $done);
     $done = [false, false, false];
     $request->getSession()->setSecret('state', ['maybeLink' => $reqs]);
     $req->confirmedLinkIDs = ['Request1', 'Request3'];
     $res = $provider->continueLinkAttempt($user, 'state', [$req]);
     $this->assertEquals(AuthenticationResponse::UI, $res->status);
     $this->assertCount(1, $res->neededRequests);
     $this->assertInstanceOf(ButtonAuthenticationRequest::class, $res->neededRequests[0]);
     $this->assertSame([true, false, false], $done);
     $done = [false, false, false];
     $res = $provider->continueLinkAttempt($user, 'state', [$res->neededRequests[0]]);
     $this->assertEquals(AuthenticationResponse::newPass(), $res);
     $this->assertSame([false, false, false], $done);
 }
コード例 #21
0
 /**
  * Import an client IP address, HTTP headers, user ID, and session ID
  *
  * This sets the current session, $wgUser, and $wgRequest from $params.
  * Once the return value falls out of scope, the old context is restored.
  * This method should only be called in contexts where there is no session
  * ID or end user receiving the response (CLI or HTTP job runners). This
  * is partly enforced, and is done so to avoid leaking cookies if certain
  * error conditions arise.
  *
  * This is useful when background scripts inherit context when acting on
  * behalf of a user. In general the 'sessionId' parameter should be set
  * to an empty string unless session importing is *truly* needed. This
  * feature is somewhat deprecated.
  *
  * @note suhosin.session.encrypt may interfere with this method.
  *
  * @param array $params Result of RequestContext::exportSession()
  * @return ScopedCallback
  * @throws MWException
  * @since 1.21
  */
 public static function importScopedSession(array $params)
 {
     if (strlen($params['sessionId']) && MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent()) {
         // Sanity check to avoid sending random cookies for the wrong users.
         // This method should only called by CLI scripts or by HTTP job runners.
         throw new MWException("Sessions can only be imported when none is active.");
     } elseif (!IP::isValid($params['ip'])) {
         throw new MWException("Invalid client IP address '{$params['ip']}'.");
     }
     if ($params['userId']) {
         // logged-in user
         $user = User::newFromId($params['userId']);
         $user->load();
         if (!$user->getId()) {
             throw new MWException("No user with ID '{$params['userId']}'.");
         }
     } else {
         // anon user
         $user = User::newFromName($params['ip'], false);
     }
     $importSessionFunc = function (User $user, array $params) {
         global $wgRequest, $wgUser;
         $context = RequestContext::getMain();
         // Commit and close any current session
         if (MediaWiki\Session\PHPSessionHandler::isEnabled()) {
             session_write_close();
             // persist
             session_id('');
             // detach
             $_SESSION = [];
             // clear in-memory array
         }
         // Get new session, if applicable
         $session = null;
         if (strlen($params['sessionId'])) {
             // don't make a new random ID
             $manager = MediaWiki\Session\SessionManager::singleton();
             $session = $manager->getSessionById($params['sessionId'], true) ?: $manager->getEmptySession();
         }
         // Remove any user IP or agent information, and attach the request
         // with the new session.
         $context->setRequest(new FauxRequest([], false, $session));
         $wgRequest = $context->getRequest();
         // b/c
         // Now that all private information is detached from the user, it should
         // be safe to load the new user. If errors occur or an exception is thrown
         // and caught (leaving the main context in a mixed state), there is no risk
         // of the User object being attached to the wrong IP, headers, or session.
         $context->setUser($user);
         $wgUser = $context->getUser();
         // b/c
         if ($session && MediaWiki\Session\PHPSessionHandler::isEnabled()) {
             session_id($session->getId());
             MediaWiki\quietCall('session_start');
         }
         $request = new FauxRequest([], false, $session);
         $request->setIP($params['ip']);
         foreach ($params['headers'] as $name => $value) {
             $request->setHeader($name, $value);
         }
         // Set the current context to use the new WebRequest
         $context->setRequest($request);
         $wgRequest = $context->getRequest();
         // b/c
     };
     // Stash the old session and load in the new one
     $oUser = self::getMain()->getUser();
     $oParams = self::getMain()->exportSession();
     $oRequest = self::getMain()->getRequest();
     $importSessionFunc($user, $params);
     // Set callback to save and close the new session and reload the old one
     return new ScopedCallback(function () use($importSessionFunc, $oUser, $oParams, $oRequest) {
         global $wgRequest;
         $importSessionFunc($oUser, $oParams);
         // Restore the exact previous Request object (instead of leaving FauxRequest)
         RequestContext::getMain()->setRequest($oRequest);
         $wgRequest = RequestContext::getMain()->getRequest();
         // b/c
     });
 }
コード例 #22
0
 public function testProvideSessionInfo()
 {
     $provider = $this->getProvider();
     $request = new \FauxRequest();
     $request->setCookie('_BPsession', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'wgCookiePrefix');
     if (!defined('MW_API')) {
         $this->assertNull($provider->provideSessionInfo($request));
         define('MW_API', 1);
     }
     $info = $provider->provideSessionInfo($request);
     $this->assertInstanceOf('MediaWiki\\Session\\SessionInfo', $info);
     $this->assertSame('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $info->getId());
     $this->config->set('EnableBotPasswords', false);
     $this->assertNull($provider->provideSessionInfo($request));
     $this->config->set('EnableBotPasswords', true);
     $this->assertNull($provider->provideSessionInfo(new \FauxRequest()));
 }
コード例 #23
0
ファイル: WebRequest.php プロジェクト: mangowi/mediawiki
 public function __construct(WebRequest $base, $data, $wasPosted = false)
 {
     $this->base = $base;
     parent::__construct($data, $wasPosted);
 }
コード例 #24
0
ファイル: FauxRequestTest.php プロジェクト: paladox/mediawiki
 /**
  * @covers FauxRequest::getRawQueryString
  * @covers FauxRequest::getRawPostString
  * @covers FauxRequest::getRawInput
  */
 public function testDummies()
 {
     $req = new FauxRequest();
     $this->assertEquals('', $req->getRawQueryString());
     $this->assertEquals('', $req->getRawPostString());
     $this->assertEquals('', $req->getRawInput());
 }