Values keyed by header name. */ public static function parse( string $raw ): array { $headers = array(); foreach ( preg_split( '/[\r\n]+/', $raw ) ?: array() as $line ) { $line = trim( (string) $line ); if ( '' === $line || ! str_contains( $line, ':' ) ) { continue; } list( $name, $value ) = explode( ':', $line, 2 ); $name = self::clean_name( $name ); $value = self::clean_value( $value ); if ( '' === $name || '' === $value ) { continue; } $headers[ $name ] = $value; if ( count( $headers ) >= self::LIMIT ) { break; } } return $headers; } /** * Renders a header map back into the text the editor shows. * * @param array $headers Values keyed by header name. */ public static function format( array $headers ): string { $lines = array(); foreach ( $headers as $name => $value ) { $lines[] = $name . ': ' . $value; } return implode( "\n", $lines ); } /** * Cleans a header name. * * @param string $name Raw name. * * @return string The name, or an empty string when it is not usable. */ private static function clean_name( string $name ): string { $name = trim( $name ); // RFC 9110 token characters. Anything else is not a header name. return 1 === preg_match( '/^[A-Za-z0-9!#$%&\'*+.^_`|~-]+$/', $name ) ? $name : ''; } /** * Cleans a header value. * * @param string $value Raw value. */ private static function clean_value( string $value ): string { return trim( str_replace( array( "\r", "\n", "\0" ), '', $value ) ); } }