18use Wikimedia\Timestamp\ConvertibleTimestamp;
54 public function header( $string, $replace =
true, $http_response_code =
null ) {
56 wfDebugLog(
'header',
'ignored post-send header {header}',
'all', [
58 'replace' => $replace,
59 'http_response_code' => $http_response_code,
60 'exception' =>
new RuntimeException(
'Ignored post-send header' ),
65 \MediaWiki\Request\HeaderCallback::warnIfHeadersSent();
66 if ( $http_response_code ) {
67 header( $string, $replace, $http_response_code );
69 header( $string, $replace );
79 return http_response_code();
89 foreach ( headers_list() as $header ) {
90 [ $name, $val ] = explode(
':', $header, 2 );
91 if ( !strcasecmp( $name, $key ) ) {
105 wfDebugLog(
'header',
'ignored post-send status header {code}',
'all', [
107 'exception' =>
new RuntimeException(
'Ignored post-send status header' ),
112 HttpStatus::header( $code );
121 return headers_sent();
144 public function setCookie( $name, $value, $expire = 0, $options = [] ) {
146 $mainConfig = $services->getMainConfig();
153 $options = array_filter( $options,
static fn ( $a ) => $a !==
null ) + [
154 'prefix' => $cookiePrefix,
155 'domain' => $cookieDomain,
156 'path' => $cookiePath,
157 'secure' => $cookieSecure,
158 'httpOnly' => $cookieHttpOnly,
163 if ( $expire ===
null ) {
165 } elseif ( $expire == 0 && $cookieExpiration != 0 ) {
166 $expire = ConvertibleTimestamp::time() + $cookieExpiration;
170 $prefixedName = $options[
'prefix'] . $name;
171 wfDebugLog(
'cookie',
'ignored post-send cookie {cookie}',
'all', [
172 'cookie' => $prefixedName,
174 'name' => $prefixedName,
175 'value' => (
string)$value,
176 'expire' => (
int)$expire,
177 'path' => (
string)$options[
'path'],
178 'domain' => (
string)$options[
'domain'],
179 'secure' => (
bool)$options[
'secure'],
180 'httpOnly' => (
bool)$options[
'httpOnly'],
181 'sameSite' => (
string)$options[
'sameSite']
183 'exception' =>
new RuntimeException(
'Ignored post-send cookie' ),
188 $hookRunner =
new HookRunner( $services->getHookContainer() );
189 if ( !$hookRunner->onWebResponseSetCookie( $name, $value, $expire, $options ) ) {
195 $prefixedName = $options[
'prefix'] . $name;
196 $value = (string)$value;
197 $func = $options[
'raw'] ?
'setrawcookie' :
'setcookie';
199 'expires' => (int)$expire,
200 'path' => (
string)$options[
'path'],
201 'domain' => (string)$options[
'domain'],
202 'secure' => (
bool)$options[
'secure'],
203 'httponly' => (bool)$options[
'httpOnly'],
204 'samesite' => (
string)$options[
'sameSite'],
208 $key =
"{$prefixedName}\n{$setOptions['domain']}\n{$setOptions['path']}";
212 if ( isset( $_COOKIE[$prefixedName] ) && !array_key_exists( $key, self::$setCookies ) ) {
213 self::$setCookies[$key] = [];
217 $deleting = ( $value ===
''
218 || ( $setOptions[
'expires'] > 0
219 && $setOptions[
'expires'] <= ConvertibleTimestamp::time()
223 $logDesc =
"$func: \"$prefixedName\", \"$value\", \"" .
224 implode(
'", "', array_map(
'strval', $setOptions ) ) .
'"';
225 $optionsForDeduplication = [ $func, $prefixedName, $value, $setOptions ];
227 if ( $deleting && !isset( self::$setCookies[$key] ) ) {
228 wfDebugLog(
'cookie',
"already deleted $logDesc" );
230 } elseif ( !$deleting && isset( self::$setCookies[$key] ) &&
231 self::$setCookies[$key] === $optionsForDeduplication
233 wfDebugLog(
'cookie',
"already set $logDesc" );
239 self::$setCookies[$key] = $deleting ? null : $optionsForDeduplication;
252 $this->
setCookie( $name,
'', ConvertibleTimestamp::time() - ExpirationAwareness::TTL_YEAR, $options );
265 protected function actuallySetCookie(
string $func,
string $prefixedName,
string $value, array $setOptions ): void {
266 if ( $func ===
'setrawcookie' ) {
267 setrawcookie( $prefixedName, $value, $setOptions );
269 setcookie( $prefixedName, $value, $setOptions );
277 if ( !defined(
'MW_PHPUNIT_TEST' ) ) {
278 throw new LogicException( __METHOD__ .
' should not be called outside tests' );
280 self::$setCookies = [];
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
if(!defined('MW_SETUP_CALLBACK'))
A class containing constants representing the names of configuration variables.
const CookieExpiration
Name constant for the CookieExpiration setting, for use with Config::get()
const CookieDomain
Name constant for the CookieDomain setting, for use with Config::get()
const CookiePath
Name constant for the CookiePath setting, for use with Config::get()
const CookieSecure
Name constant for the CookieSecure setting, for use with Config::get()
const CookiePrefix
Name constant for the CookiePrefix setting, for use with Config::get()
const CookieHttpOnly
Name constant for the CookieHttpOnly setting, for use with Config::get()