50 self::$disableForPostSend =
true;
59 public function header( $string, $replace =
true, $http_response_code =
null ) {
60 if ( self::$disableForPostSend ) {
61 wfDebugLog(
'header',
'ignored post-send header {header}',
'all', [
63 'replace' => $replace,
64 'http_response_code' => $http_response_code,
65 'exception' =>
new RuntimeException(
'Ignored post-send header' ),
71 if ( $http_response_code ) {
72 header( $string, $replace, $http_response_code );
74 header( $string, $replace );
85 foreach ( headers_list() as
$header ) {
86 list( $name, $val ) = explode(
':',
$header, 2 );
87 if ( !strcasecmp( $name, $key ) ) {
100 if ( self::$disableForPostSend ) {
101 wfDebugLog(
'header',
'ignored post-send status header {code}',
'all', [
103 'exception' =>
new RuntimeException(
'Ignored post-send status header' ),
117 return headers_sent();
141 public function setCookie( $name, $value, $expire = 0, $options = [] ) {
146 $options = array_filter( $options,
function ( $a ) {
159 if ( strcasecmp( $options[
'sameSite'],
'none' ) === 0
160 && !empty( $options[
'sameSiteLegacy'] )
162 $legacyOptions = $options;
163 $legacyOptions[
'sameSiteLegacy'] =
false;
164 $legacyOptions[
'sameSite'] =
'';
165 $this->
setCookie(
"ss0-$name", $value, $expire, $legacyOptions );
168 if ( $expire ===
null ) {
174 if ( self::$disableForPostSend ) {
175 $prefixedName = $options[
'prefix'] . $name;
176 wfDebugLog(
'cookie',
'ignored post-send cookie {cookie}',
'all', [
177 'cookie' => $prefixedName,
179 'name' => $prefixedName,
180 'value' => (
string)$value,
181 'expire' => (
int)$expire,
182 'path' => (
string)$options[
'path'],
183 'domain' => (
string)$options[
'domain'],
184 'secure' => (
bool)$options[
'secure'],
185 'httpOnly' => (
bool)$options[
'httpOnly'],
186 'sameSite' => (
string)$options[
'sameSite']
188 'exception' =>
new RuntimeException(
'Ignored post-send cookie' ),
193 if ( !
Hooks::run(
'WebResponseSetCookie', [ &$name, &$value, &$expire, &$options ] ) ) {
199 $prefixedName = $options[
'prefix'] . $name;
200 $value = (string)$value;
201 $func = $options[
'raw'] ?
'setrawcookie' :
'setcookie';
203 'expires' => (int)$expire,
204 'path' => (
string)$options[
'path'],
205 'domain' => (string)$options[
'domain'],
206 'secure' => (
bool)$options[
'secure'],
207 'httponly' => (bool)$options[
'httpOnly'],
208 'samesite' => (
string)$options[
'sameSite'],
212 $key =
"{$prefixedName}\n{$setOptions['domain']}\n{$setOptions['path']}";
216 if ( isset( $_COOKIE[$prefixedName] ) && !array_key_exists( $key, self::$setCookies ) ) {
217 self::$setCookies[$key] = [];
221 $deleting = ( $value ===
'' || $setOptions[
'expires'] > 0 && $setOptions[
'expires'] <= time() );
223 $logDesc =
"$func: \"$prefixedName\", \"$value\", \"" .
224 implode(
'", "', $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" );
238 if ( $func ===
'setrawcookie' ) {
240 SetCookieCompat::setrawcookie( $prefixedName, $value, $setOptions );
243 SetCookieCompat::setcookie( $prefixedName, $value, $setOptions );
245 self::$setCookies[$key] = $deleting ? null : $optionsForDeduplication;
258 $this->
setCookie( $name,
'', time() - 31536000 , $options );