56 self::$disableForPostSend =
true;
65 public function header( $string, $replace =
true, $http_response_code =
null ) {
66 if ( self::$disableForPostSend ) {
67 wfDebugLog(
'header',
'ignored post-send header {header}',
'all', [
69 'replace' => $replace,
70 'http_response_code' => $http_response_code,
71 'exception' =>
new RuntimeException(
'Ignored post-send header' ),
76 \MediaWiki\Request\HeaderCallback::warnIfHeadersSent();
77 if ( $http_response_code ) {
78 header( $string, $replace, $http_response_code );
80 header( $string, $replace );
91 foreach ( headers_list() as
$header ) {
92 [ $name, $val ] = explode(
':',
$header, 2 );
93 if ( !strcasecmp( $name, $key ) ) {
106 if ( self::$disableForPostSend ) {
107 wfDebugLog(
'header',
'ignored post-send status header {code}',
'all', [
109 'exception' =>
new RuntimeException(
'Ignored post-send status header' ),
123 return headers_sent();
147 public function setCookie( $name, $value, $expire = 0, $options = [] ) {
149 $mainConfig = $services->getMainConfig();
157 $options = array_filter( $options,
static function ( $a ) {
160 'prefix' => $cookiePrefix,
161 'domain' => $cookieDomain,
162 'path' => $cookiePath,
163 'secure' => $cookieSecure,
164 'httpOnly' => $cookieHttpOnly,
167 'sameSiteLegacy' => $useSameSiteLegacyCookies
170 if ( strcasecmp( $options[
'sameSite'],
'none' ) === 0
171 && !empty( $options[
'sameSiteLegacy'] )
173 $legacyOptions = $options;
174 $legacyOptions[
'sameSiteLegacy'] =
false;
175 $legacyOptions[
'sameSite'] =
'';
176 $this->
setCookie(
"ss0-$name", $value, $expire, $legacyOptions );
179 if ( $expire ===
null ) {
181 } elseif ( $expire == 0 && $cookieExpiration != 0 ) {
182 $expire = time() + $cookieExpiration;
185 if ( self::$disableForPostSend ) {
186 $prefixedName = $options[
'prefix'] . $name;
187 wfDebugLog(
'cookie',
'ignored post-send cookie {cookie}',
'all', [
188 'cookie' => $prefixedName,
190 'name' => $prefixedName,
191 'value' => (
string)$value,
192 'expire' => (
int)$expire,
193 'path' => (
string)$options[
'path'],
194 'domain' => (
string)$options[
'domain'],
195 'secure' => (
bool)$options[
'secure'],
196 'httpOnly' => (
bool)$options[
'httpOnly'],
197 'sameSite' => (
string)$options[
'sameSite']
199 'exception' =>
new RuntimeException(
'Ignored post-send cookie' ),
204 $hookRunner =
new HookRunner( $services->getHookContainer() );
205 if ( !$hookRunner->onWebResponseSetCookie( $name, $value, $expire, $options ) ) {
211 $prefixedName = $options[
'prefix'] . $name;
212 $value = (string)$value;
213 $func = $options[
'raw'] ?
'setrawcookie' :
'setcookie';
215 'expires' => (int)$expire,
216 'path' => (
string)$options[
'path'],
217 'domain' => (string)$options[
'domain'],
218 'secure' => (
bool)$options[
'secure'],
219 'httponly' => (bool)$options[
'httpOnly'],
220 'samesite' => (
string)$options[
'sameSite'],
224 $key =
"{$prefixedName}\n{$setOptions['domain']}\n{$setOptions['path']}";
228 if ( isset( $_COOKIE[$prefixedName] ) && !array_key_exists( $key, self::$setCookies ) ) {
229 self::$setCookies[$key] = [];
233 $deleting = ( $value ===
'' || $setOptions[
'expires'] > 0 && $setOptions[
'expires'] <= time() );
235 $logDesc =
"$func: \"$prefixedName\", \"$value\", \"" .
236 implode(
'", "', array_map(
'strval', $setOptions ) ) .
'"';
237 $optionsForDeduplication = [ $func, $prefixedName, $value, $setOptions ];
239 if ( $deleting && !isset( self::$setCookies[$key] ) ) {
240 wfDebugLog(
'cookie',
"already deleted $logDesc" );
242 } elseif ( !$deleting && isset( self::$setCookies[$key] ) &&
243 self::$setCookies[$key] === $optionsForDeduplication
245 wfDebugLog(
'cookie',
"already set $logDesc" );
250 if ( $func ===
'setrawcookie' ) {
251 setrawcookie( $prefixedName, $value, $setOptions );
253 setcookie( $prefixedName, $value, $setOptions );
255 self::$setCookies[$key] = $deleting ? null : $optionsForDeduplication;
268 $this->
setCookie( $name,
'', time() - 31536000 , $options );
285 class_alias( WebResponse::class,
'WebResponse' );
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
static header( $code)
Output an HTTP status code header.
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 UseSameSiteLegacyCookies
Name constant for the UseSameSiteLegacyCookies 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()