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 );
147 public function setCookie( $name, $value, $expire = 0, $options = [] ) {
156 $options = array_filter( $options,
static function ( $a ) {
159 'prefix' => $cookiePrefix,
160 'domain' => $cookieDomain,
161 'path' => $cookiePath,
162 'secure' => $cookieSecure,
163 'httpOnly' => $cookieHttpOnly,
166 'sameSiteLegacy' => $useSameSiteLegacyCookies
169 if ( strcasecmp( $options[
'sameSite'],
'none' ) === 0
170 && !empty( $options[
'sameSiteLegacy'] )
172 $legacyOptions = $options;
173 $legacyOptions[
'sameSiteLegacy'] =
false;
174 $legacyOptions[
'sameSite'] =
'';
175 $this->
setCookie(
"ss0-$name", $value, $expire, $legacyOptions );
178 if ( $expire ===
null ) {
180 } elseif ( $expire == 0 && $cookieExpiration != 0 ) {
181 $expire = time() + $cookieExpiration;
184 if ( self::$disableForPostSend ) {
185 $prefixedName = $options[
'prefix'] . $name;
186 wfDebugLog(
'cookie',
'ignored post-send cookie {cookie}',
'all', [
187 'cookie' => $prefixedName,
189 'name' => $prefixedName,
190 'value' => (
string)$value,
191 'expire' => (
int)$expire,
192 'path' => (
string)$options[
'path'],
193 'domain' => (
string)$options[
'domain'],
194 'secure' => (
bool)$options[
'secure'],
195 'httpOnly' => (
bool)$options[
'httpOnly'],
196 'sameSite' => (
string)$options[
'sameSite']
198 'exception' =>
new RuntimeException(
'Ignored post-send cookie' ),
203 if ( !Hooks::runner()->onWebResponseSetCookie( $name, $value, $expire, $options ) ) {
209 $prefixedName = $options[
'prefix'] . $name;
210 $value = (string)$value;
211 $func = $options[
'raw'] ?
'setrawcookie' :
'setcookie';
213 'expires' => (int)$expire,
214 'path' => (
string)$options[
'path'],
215 'domain' => (string)$options[
'domain'],
216 'secure' => (
bool)$options[
'secure'],
217 'httponly' => (bool)$options[
'httpOnly'],
218 'samesite' => (
string)$options[
'sameSite'],
222 $key =
"{$prefixedName}\n{$setOptions['domain']}\n{$setOptions['path']}";
226 if ( isset( $_COOKIE[$prefixedName] ) && !array_key_exists( $key, self::$setCookies ) ) {
227 self::$setCookies[$key] = [];
231 $deleting = ( $value ===
'' || $setOptions[
'expires'] > 0 && $setOptions[
'expires'] <= time() );
233 $logDesc =
"$func: \"$prefixedName\", \"$value\", \"" .
234 implode(
'", "', array_map(
'strval', $setOptions ) ) .
'"';
235 $optionsForDeduplication = [ $func, $prefixedName, $value, $setOptions ];
237 if ( $deleting && !isset( self::$setCookies[$key] ) ) {
238 wfDebugLog(
'cookie',
"already deleted $logDesc" );
240 } elseif ( !$deleting && isset( self::$setCookies[$key] ) &&
241 self::$setCookies[$key] === $optionsForDeduplication
243 wfDebugLog(
'cookie',
"already set $logDesc" );
248 if ( $func ===
'setrawcookie' ) {
249 setrawcookie( $prefixedName, $value, $setOptions );
251 setcookie( $prefixedName, $value, $setOptions );
253 self::$setCookies[$key] = $deleting ? null : $optionsForDeduplication;