This is micro-optimization of closure code to avoid binding the closure
to $this where it is not needed.
Created by I25a17fb22b6b669e817317a0f45051ae9c608208
Change-Id: I0ffc6200f6c6693d78a3151cb8cea7dce7c21653
This is sent at the end of the LBFactory::shutdown wrapper, so will
still happen at the same logical point in time.
Use LBFactory->replLogger since that it is also the logger used
by ChronologyProtector.
Bug: T254634
Change-Id: Ic4a9573e6cd3ea00f77b2f44c03453c5b96fa486
When there are pending updates, MediaWiki disables
compression by setting a header 'Content-Encoding: none'
but this is not a valid value for this field. Change
to 'Content-Encoding: identity'
https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding
Bug: T258877
Change-Id: Ie769ca7862a02e5010e0ff8a4ff3be57fe5cdb86
Add $wgForceHTTPS. When set to true:
* It makes the HTTP to HTTPS redirect unconditional and suppresses the
forceHTTPS cookie.
* It makes session cookies be secure.
* In the Action API, it triggers the existing deprecation warning and
avoids more expensive user/session checks.
* In login and signup, it suppresses the old hidden form fields for
protocol switching.
* It hides the prefershttps user preference.
Other changes:
* Factor out the HTTPS redirect in MediaWiki::main() into
maybeDoHttpsRedirect() and shouldDoHttpRedirect(). Improve
documentation.
* User::requiresHTTPS() reflects $wgForceHTTPS whereas the Session
concept of "force HTTPS" does not. The documentation of
User::requiresHTTPS() says that it includes configuration, and
retaining this definition was beneficial for some callers. Whereas
Session::shouldForceHTTPS() was used fairly narrowly as the value
of the forceHTTPS cookie, and injecting configuration into it is not
so easy or beneficial, so I left it as it was, except for clarifying
the documentation.
* Deprecate the following hooks: BeforeHttpsRedirect, UserRequiresHTTPS,
CanIPUseHTTPS. No known extension uses them, and they're not compatible
with the long-term goal of ending support for mixed-protocol wikis.
BeforeHttpsRedirect was documented as unstable from its inception.
CanIPUseHTTPS was a WMF config hack now superseded by GFOC's SNI
sniffing.
* For tests which failed with $wgForceHTTPS=true, I mostly split the
tests, testing each configuration value separately.
* Add ArrayUtils::cartesianProduct() as a helper for generating
combinations of boolean options in the session tests.
Bug: T256095
Change-Id: Iefb5ba55af35350dfc7c050f9fb8f4e8a79751cb
'wgInternalRedirectTargetUrl' should be set using getLinkURL()
(which doesn't contain the domain) instead of getFullURL().
This is already the case for normal article redirects (see how
'wgInternalRedirectTargetUrl' is set in Article.php).
Bug: T255620
Change-Id: I77473bedd52bc51c8ef53d6bc695b6bf2ebd0bfd
A terminating line break has not been required in wfDebug() since 2014,
however no migration was done. Some of these line breaks found their way
into LoggerInterface::debug() calls, where they mess up the formatting
of the debug log.
So, remove terminating line breaks from wfDebug() and
LoggerInterface::debug() calls.
Also:
* Fix the stripping of leading line breaks from the log header emitted
by Setup.php. This feature, accidentally broken in 2014, allows
requests to be distinguished in the log file.
* Avoid using the global variable $self.
* Move the logging of the client IP back to Setup.php. It was moved to
WebRequest in the hopes that it would not always be needed, however
$wgRequest->getIP() is now called unconditionally a few lines up in
Setup.php. This means that it is put in its proper place after the
"start request" message.
* Wrap the log header code in a closure so that variables like $name do
not leak into global scope.
* In Linker.php, remove a few instances of an unnecessary second
parameter to wfDebug().
Change-Id: I96651d3044a95b9d210b51cb8368edc76bebbb9e
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
Make sure that CAUGHT_BY_HANDLER is only for errors caught by the
handler from MWExceptionHandler::installHandler().
Add CAUGHT_BY_ENTRYPOINT constant for entrypoint try/catch logic,
e.g. MediaWiki::run()/ApiMain::executeActionWithErrorHandling().
Use Throwable to catch more types of errors given that PHP 7.2
is already required.
Change-Id: Ib496e26572c98d771a772972676c02c05b872e31
MediaWiki::schedulePostSendJobs() creates a DeferredUpdate to run jobs
opportunistically post-send when $wgJobRunRate > 0. The MWCallableUpdate
created by addCallableUpdate() creates a "transaction round", which
makes JobRunner fail because it wants to be called with no active
transaction round.
Instead, use a TransactionRoundDefiningUpdate which doesn't create a
round.
Bug: T248021
Change-Id: I59dba84cd26344e0e72522e3dfbaacf024a9a74c
Added:
- ContentHandlerFactory
Tests:
- PHPUnit
Changed
- Calls of changed and deprecated
- DI for some service/api
Deprecated:
- ContentHandler::* then similar to ContentHandlerFactory
- ContentHandler::getForTitle
- ContentHandler::$handlers
Bug: T235165
Change-Id: I59246938c7ad7b3e70e46c9e698708ef9bc672c6
This will allow us to remove the phan stubs. The MWDebug part was copied
from Ia92b881a7eeab4b8b53531136fb0dbafb6ec30ba.
Change-Id: Id8a5e267b2eb2d8beda3b1b2c1041000a0a1b17c
This was previously hardcoded from three places: 1) Upon viewing EditPage,
2) Upon viewing SpecialCreateAccount, 3) For any url if the user is
logged-in (User::loadFromSession/isLoggedIn).
== User::loadFromSession
Performing cookie blocks from here created a circular dependency because
Block may need the user language for localisation, which is determined by
asking the User object. This was previously worked around by using a
DeferredUpdate (T180050, T226777). Moving this logic explicitly to the
end of the pre-send cycle in MediaWiki::preOutputCommit breaks the cycle.
This is also where other request-specific handling resides already.
== Limited effect on unregistered users
When an unregistered user performs an edit, and gets blocked,
the cookie block is not applied until they open built-in editor
or CreateAccount page. This makes it more likely for a user's
IP to change meanwhile. Either intentionally, or simply due to
IPs varying naturally (e.g. between mobile locations, or when
going on/off WiFi). By applying it throughout sessioned page
views for unregistered users, it is more likely to get set.
Similar to what was already done for logged-in users.
This commit also makes the intent of not caching EditPage and
SpecialCreateAccount explicit. This was previously implicit
through nothing having called setCdnMaxage() and/or due to
Session::persist being checked for by OutputPage::sendCacheControl.
Bug: T233594
Change-Id: Icf5a00f9b41d31bb6d4742c049feca0039d0c9d9
Set appropriate headers and flush the output as needed to avoid blocking
the client on post-send updates for the stock apache2 server scenario.
Several cases have bits of header logic to avoid delay:
a) basic GET/POST requests that succeed (e.g. HTTP 2XX)
b) requests that fail with errors (e.g. HTTP 500)
c) If-Modified-Since requests (e.g. HTTP 304)
d) HEAD requests
This last two still block on deferred updates, so schedulePostSendJobs()
does not trigger on them as a form of mitigation. Slow deferred updates
should only trigger on POST anyway (inline and redirect responses are
OK), so this should not be much of a problem.
Deprecate triggerJobs() and implement post-send job runs as a deferred.
This makes it easy to check for the existence of post-send updates by
calling DeferredUpdates::pendingUpdatesCount() after the pre-send stage.
Also, avoid running jobs on requests that had exceptions. Relatedly,
remove $mode option from restInPeace() and doPostOutputShutdown()
Only one caller was using the non-default options.
Bug: T206283
Change-Id: I2dd2b71f1ced0f4ef8b16ff41ffb23bb5b4c7028
The same way it does already for non-error output. This makes
it so that doPreOutputCommit() consistently happens between
the staging of output and the actual sending of output.
It is still allowed for code to bypass this, such as for fatal
errors and for handlers that disable OutputPage (like Special:Export).
But for cases where we do want to perform doPreOutputCommit(), it
should be run consistently between staging and sending so that it
can make appropiate decisions based on the current state of
OutputPage.
Previously, the state of OutputPage seen by doPreOutputCommit()
would be the broken/incomplete output of a seemingly succesful
(possibly cacheable) user action, which would then, after
doPreOutputCommit() runs, be completely replaced by $e->report()/
$out->showErrorPage().
This is a prerequisite for being able to reliably send cookie-block
cookies on error pages (next patch).
Bug: T233594
Change-Id: Iaeaf5e55a5868e6be534ddda73f3b56b9d6ef8f0
This re-applies commit 41106688ab
(thereby reverting commit 6c57748aeee6e4f2a197d64785102306fbd4a297)
and fixes it for local interwiki redirects by adding and using a
forcing parameter in Special:GoToInterwiki to treat local redirects
like external ones.
Bug: T227700
Change-Id: I4bc2ed998430fc2bac71baf850b8988fdb24c1ac
This reverts commit 41106688ab.
The original case is changed by this commit from a MediaWiki fatal
exception with HTTP 500, to a blank 200 response due to silent
failure. Use of GoToInterwiki appears to be invalid at this point in
the code. Reverting to keep prod the same as last week, so as
to unblock the train.
Bug: T227700
Change-Id: Ieece956d2e2e4c21b5ed7a75890b9f11eaf07e66
Previously, WikiPage::performRequest() would assume that Titles returned
by RedirectSpecialPage::getRedirect() are local pages, and would set
$wgTitle to whatever was returned. That would lead to a confused state
where the skin would try to render for an interwiki Title.
Instead, WikiPage::performRequest() should wrap the interwiki redirect
in a call to Special:GoToInterwiki/xyz, just like
Title::getFullUrlForRedirect() does, but still avoid the HTTP redirect,
to avoid leaking private information via view counters (T109724).
There are two things to test:
1) call Special:MyLanguage with an interwiki prefix,
e.g. Special:MyLanguage/wikipedia:XYZ.
2) create a page that contains an interwiki redirect,
e.g. #REDIRECT [[wikipedia:XYZ]], then call Special:MyLanguage
for that page.
For these tests, the user language should be the same as the content
language. That is the critical case. If the user language differs
from the content language, the problem would be obscured by another
bug which is addressed by Ib4cbeec47a877c473.
Bug: T227700
Change-Id: I2852c5a9774f0c76e49f1e3876fcfe85a305f9ce
Do not send headers if they were already flushed. Split off some
chronology protection logic into a separate private method. Use
ILBFactory over LBFactory in a few places. Also, update various
code comments.
Bug: T225655
Change-Id: Iecb574e11d8ba09147ff7b84ad57d8845069ba99
This means that enqueuable updates (LinksUpdate, LinksDeletionUpdate) will run immediately
at this point rather than be enqueued as jobs. This only affects ApiPurge since the other
callers use either POSTSEND or "false".
Change-Id: I8b6ff6c9a68730374e6d83682e774e4f4bfbf52f
This will make it easier to create redirects where $subpage is the title,
e.g. "Special:Example/Foo?x=y" to "index.php?title=Foo&x=y".
To do that conveniently, getRedirectQuery() needs access to $subpage.
The alternative is to do Title-parsing inside getRedirect(), which then
complicates this significantly as one has to deal with absence of a title
(null) and invalid titles (illegal chars etc.).
By using it plainly as query parameter (defaulting to null/omitted), this
is all deferred to index.php, which seems like a better separation of
concerns.
Motivated by SpecialMobileHistory in MobileFrontend (Ic0aea7ee340a).
Change-Id: I9fe78f479053fb55952ba78850d2fc281a039fe3
I benchmarked this again. The runtime of an unlimited explode() can be
quite high. This is not really a DoS attack vector as it would require to
post megabytes worth of input to the code, which will hit many other
limits before. I still consider it good practice to use unlimited explode()
only when it is actually allowed to return an unlimited amount of elements.
Change-Id: I30f8ca5dba7b317bb4a046b9740fd736b4eea291
This is inspired by Ib117e05.
As far as I can tell this is functionally identical. Even arrays should
behave the same, as both the getVal() and getCheck() methods do have a
special case that returns the `null` default in case the user tried to
pass multiple values instead of a single scalar.
Change-Id: Id4e4ec91f39d3c39461bd41673bdafc3bde11737
Some of the callers of setExpectations() actually need to reset the old
expectations to avoid erroneous warnings.
Change-Id: I63c01c0f6cd748bdc849f1a5264e17bd377b9d11
Use these in place of various wfWikiID() calls.
Also cleanup UserRightsProxy wiki ID variable names and removed unused
and poorly named getDBname() method.
Change-Id: Ib28889663989382d845511f8d34712b08317f60e