") then
					a_block.set_title (Void)
				else
					a_block.set_title (l_title)
				end
			end
		end
	block_conditions (a_block_id: READABLE_STRING_8): detachable ARRAYED_LIST [CMS_BLOCK_EXPRESSION_CONDITION]
			-- Condition associated with `a_block_id' in configuration, if any.
		do
			if attached setup.text_item ("blocks." + a_block_id + ".condition") as s then
				create Result.make (1)
				Result.force (create {CMS_BLOCK_EXPRESSION_CONDITION}.make (s))
			end
			if attached setup.text_list_item ("blocks." + a_block_id + ".conditions") as lst then
				if Result = Void then
					create Result.make (lst.count)
				end
				across
					lst as ic
				loop
					Result.force (create {CMS_BLOCK_EXPRESSION_CONDITION}.make (ic.item))
				end
			end
		end
	block_options (a_block_id: READABLE_STRING_8): detachable STRING_TABLE [READABLE_STRING_32]
			-- Options associated with `a_block_id' in configuration, if any.
		do
			if attached setup.text_table_item ("blocks." + a_block_id + ".options") as tb then
				Result := tb
			end
		end
	is_block_included (a_block_id: READABLE_STRING_8; dft: BOOLEAN): BOOLEAN
			-- Is block `a_block_id' included in current response?
			-- If no preference, return `dft'.
		do
			if attached block_conditions (a_block_id) as l_conditions then
				Result := across l_conditions as ic some ic.item.satisfied_for_response (Current) end
			else
				Result := dft
			end
		end
	block_cache (a_block_id: READABLE_STRING_8): detachable TUPLE [cache_block: CMS_CACHE_BLOCK; region: READABLE_STRING_8; expired: BOOLEAN]
			-- Cached version of block `a_block_id'.
		local
			l_cache: CMS_FILE_STRING_8_CACHE
		do
			if
				attached setup.text_item ("blocks." + a_block_id + ".expiration") as nb_secs and then
				nb_secs.is_integer
			then
				if attached block_region_preference (a_block_id, "none") as l_region and then not l_region.same_string_general ("none") then
					create l_cache.make (api.cache_location.extended ("_blocks").extended (a_block_id).appended_with_extension ("html"))
					if
						l_cache.exists and then
						not l_cache.expired (Void, nb_secs.to_integer)
					then
						Result := [create {CMS_CACHE_BLOCK} .make (a_block_id, l_cache), l_region, False]
					else
						Result := [create {CMS_CACHE_BLOCK} .make (a_block_id, l_cache), l_region, True]
					end
				end
			end
		end
	clear_block_caches (a_block_id_list: detachable ITERABLE [READABLE_STRING_GENERAL])
			-- Clear cache for block `a_block_id_list' if set,
			-- otherwise clear all block caches if `a_block_id_list' is Void.
		local
			p,pb: PATH
			dir: DIRECTORY
			l_cache: CMS_FILE_STRING_8_CACHE
		do
			p := api.cache_location.extended ("_blocks")
			if a_block_id_list /= Void then
				across
					a_block_id_list as ic
				loop
						-- FIXME: find a smarter way to avoid conflict between block id, and other cache id.
						-- however, this is only about "Cache" so not that critical if deleted by mistake.
					pb := p.extended (ic.item).appended_with_extension ("html")
					create l_cache.make (pb)
					if l_cache.exists then
						l_cache.delete
					end
				end
			else
					-- Clear all block caches.
				create dir.make_with_path (p)
				dir.recursive_delete
			end
			add_notice_message ("Blocks cache cleared.")
		end
feature {CMS_HOOK_CORE_MANAGER} -- Block management: internal
	internal_block_alias_table: like block_alias_table
			-- Internal memory cache for `block_alias_table'.
	block_alias_table: detachable STRING_TABLE [LIST [READABLE_STRING_8]]
			-- Table of included block aliases, if any.
			-- note: { block_id => [ alias-names ..] }
		local
			k,v: READABLE_STRING_GENERAL
			l_block_id, l_alias_id: READABLE_STRING_8
			lst: detachable LIST [READABLE_STRING_8]
		do
			Result := internal_block_alias_table
			if
				Result = Void and then
				attached setup.text_table_item ("blocks.&aliases") as tb
			then
				create Result.make (tb.count)
				across
					tb as ic
				loop
					k := ic.key
					v := ic.item
					if v.is_valid_as_string_8 then
						l_block_id := v.to_string_8
						if k.is_valid_as_string_8 then
							l_alias_id := k.to_string_8
							if is_block_included (l_alias_id, False) then
								lst := Result.item (l_block_id)
								if lst = Void then
									create {ARRAYED_LIST [READABLE_STRING_8]} lst.make (1)
								end
								lst.force (l_alias_id)
								Result.force (lst, l_block_id)
							end
						else
							check valid_alias_id: False end
						end
					else
						check valid_block_id: False end
					end
				end
			end
		end
feature -- Blocks regions
	regions: STRING_TABLE [CMS_BLOCK_REGION]
			-- Layout regions, that contains blocks.
	blocks: STRING_TABLE [CMS_BLOCK]
			-- Blocks indexed by their block id.
	block_region_settings: STRING_TABLE [READABLE_STRING_8]
	block_region (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8): CMS_BLOCK_REGION
			-- Region associated with block `b', or else `a_default_region' if provided.
		local
			l_region_name: detachable READABLE_STRING_8
		do
			l_region_name := block_region_settings.item (b.name)
			if l_region_name = Void then
				if attached setup.text_item ("blocks." + b.name + ".region") as l_setup_name then
					l_region_name := utf_8_encoded (l_setup_name) -- FIXME: is utf-8 ok here?
						-- Remember for later.
					block_region_settings.force (l_region_name, b.name)
				elseif a_default_region /= Void then
					l_region_name := a_default_region
				else
						-- Default .. put it in same named region
						-- Maybe a bad idea
					l_region_name := b.name.as_lower
				end
			end
			if attached regions.item (l_region_name) as res then
				Result := res
			else
				create Result.make (l_region_name)
				regions.force (Result, l_region_name)
			end
		end
feature {NONE} -- Blocks
	put_core_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8; is_block_included_by_default: BOOLEAN; a_alias_table: like block_alias_table)
			-- Add block `b' to associated region or `a_default_region' if provided
			-- and check optional associated condition.
			-- If no condition then use `is_block_included_by_default' to
			-- decide if block is included or not.
		local
			l_region: detachable like block_region
		do
			if is_block_included (b.name, is_block_included_by_default) then
				l_region := block_region (b, a_default_region)
				l_region.extend (b)
				blocks.force (b, b.name)
			end
				-- Included alias block ids.
			if
				a_alias_table /= Void and then
				attached a_alias_table.item (b.name) as l_aliases
			then
				across
					l_aliases as ic
				loop
					add_block (create {CMS_ALIAS_BLOCK}.make_with_block (ic.item, b), a_default_region)
				end
			end
		end
feature -- Blocks
	put_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8; is_block_included_by_default: BOOLEAN)
			-- Add block `b' to associated region or `a_default_region' if provided
			-- and check optional associated condition.
			-- If no condition then use `is_block_included_by_default' to
			-- decide if block is included or not.
		do
			if is_block_included (b.name, is_block_included_by_default) then
				add_block (b, a_default_region)
			end
		end
	add_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8)
			-- Add block `b' to associated region or `a_default_region' if provided.
			-- WARNING: ignore any block condition! USE WITH CARE!
		local
			l_region: detachable like block_region
		do
			l_region := block_region (b, a_default_region)
			l_region.extend (b)
			blocks.force (b, b.name)
		end
	remove_block (b: CMS_BLOCK)
			-- Remove block `b' from associated region.
		local
			l_region: detachable like block_region
			l_found: BOOLEAN
		do
			across
				regions as reg_ic
			until
				l_found
			loop
				l_region := reg_ic.item
				l_found := l_region.blocks.has (b)
				if l_found then
					l_region.remove (b)
				end
			end
			blocks.remove (b.name)
		end
	get_blocks
			-- Get block from CMS core, and from modules.
		local
			l_region: CMS_BLOCK_REGION
			b: CMS_BLOCK
		do
			get_core_blocks
			get_module_blocks
			across
				regions as reg_ic
			loop
				l_region := reg_ic.item
				across
					l_region.blocks as ic
				loop
					update_block (ic.item)
				end
				l_region.sort
			end
			debug ("cms")
				create {CMS_CONTENT_BLOCK} b.make ("made_with", Void, "Made with EWF", Void)
				b.set_weight (99)
				put_block (b, "footer", True)
			end
		end
	get_core_blocks
			-- Get blocks provided by the CMS core.
		local
			l_alias_table: like block_alias_table
		do
				-- Get included aliased blocks.
			l_alias_table := block_alias_table
			put_core_block (top_header_block, "top", True, l_alias_table)
			put_core_block (header_block, "header", True, l_alias_table)
			if attached message_block as m then
				put_core_block (m, "content", True, l_alias_table)
			end
			if attached primary_tabs_block as m then
				put_core_block (m, "content", True, l_alias_table)
			end
			add_block (content_block, "content") -- Can not be disabled!
			if attached management_menu_block as l_block then
				put_core_block (l_block, "sidebar_first", True, l_alias_table)
			end
			if attached navigation_menu_block as l_block then
				put_core_block (l_block, "sidebar_first", True, l_alias_table)
			end
			if attached user_menu_block as l_block then
				put_core_block (l_block, "sidebar_second", True, l_alias_table)
			end
		end
	get_module_blocks
			-- Get blocks provided by modules.
		do
				-- Get block from modules, and related alias.
			api.hooks.invoke_block (Current)
		end
	primary_menu_block: detachable CMS_MENU_BLOCK
		do
			if attached primary_menu as m and then not m.is_empty then
				create Result.make (m)
			end
		end
	management_menu_block: detachable CMS_MENU_BLOCK
		do
			if attached management_menu as m and then not m.is_empty then
				create Result.make (m)
			end
		end
	navigation_menu_block: detachable CMS_MENU_BLOCK
		do
			if attached navigation_menu as m and then not m.is_empty then
				create Result.make (m)
			end
		end
	user_menu_block: detachable CMS_MENU_BLOCK
		do
			if attached user_menu as m and then not m.is_empty then
				create Result.make (m)
			end
		end
	top_header_block: CMS_CONTENT_BLOCK
		local
			s: STRING
		do
			create s.make_empty
			create Result.make ("page_top", Void, s, Void)
			Result.set_weight (-5)
			Result.set_is_raw (True)
		end
	header_block: CMS_CONTENT_BLOCK
		local
			s: STRING
			l_hb: STRING
		do
			create s.make_from_string (theme.menu_html (primary_menu, True, Void))
			create l_hb.make_empty
			create Result.make ("header", Void, l_hb, Void)
			Result.set_weight (-4)
			Result.set_is_raw (True)
		end
	horizontal_primary_menu_html: STRING
		do
			create Result.make_empty
			Result.append ("")
		end
	horizontal_primary_tabs_html: STRING
		do
			create Result.make_empty
			Result.append ("")
			Result.append (theme.menu_html (primary_tabs, True, Void))
			Result.append ("
")
		end
	message_html: detachable STRING
		do
			if attached message as m and then not m.is_empty then
				Result := "" + m + "
"
			end
		end
	message_block: detachable CMS_CONTENT_BLOCK
		do
			if attached message as m and then not m.is_empty then
				create Result.make ("message", Void, "" + m + "
", Void)
				Result.set_is_raw (True)
				Result.set_weight (-3)
			end
		end
	primary_tabs_block: detachable CMS_MENU_BLOCK
		do
			if attached primary_tabs as m and then not m.is_empty then
				create Result.make (m)
				Result.is_horizontal := True
				Result.set_is_raw (True)
				Result.set_weight (-2)
				Result.add_css_class ("tabs")
			end
		end
	content_block: CMS_CONTENT_BLOCK
		local
			s: STRING
		do
			if attached main_content as l_content then
				s := l_content
			else
				s := ""
				debug
					s := "No Content"
				end
			end
			create Result.make ("content", Void, s, Void)
			Result.set_weight (-1)
			Result.set_is_raw (True)
		end
feature -- Menu: change
	add_to_main_menu (lnk: CMS_LINK)
		obsolete
			"use add_to_primary_menu [2017-05-31]"
		do
			add_to_primary_menu (lnk)
		end
	add_to_primary_menu (lnk: CMS_LINK)
		do
			add_to_menu (lnk, primary_menu)
		end
	add_to_primary_tabs (lnk: CMS_LINK)
		do
			add_to_menu (lnk, primary_tabs)
		end
	add_to_menu (lnk: CMS_LINK; m: CMS_MENU)
		do
			m.extend (lnk)
		end
feature -- Message
	add_message (a_msg: READABLE_STRING_8; a_category: detachable READABLE_STRING_8)
		local
			m: like message
		do
			m := message
			if m = Void then
				create m.make (a_msg.count + 9)
				message := m
			end
			if a_category /= Void then
				m.append ("")
			else
				m.append ("")
			end
			m.append (a_msg + "")
		end
	add_debug_message (a_msg: READABLE_STRING_8)
		do
			if api.is_debug then
				add_message (a_msg, "debug")
			end
		end
	add_notice_message (a_msg: READABLE_STRING_8)
		do
			add_message (a_msg, "notice")
		end
	add_warning_message (a_msg: READABLE_STRING_8)
		do
			add_message (a_msg, "warning")
		end
	add_error_message (a_msg: READABLE_STRING_8)
		do
			add_message (a_msg, "error")
		end
	add_success_message (a_msg: READABLE_STRING_8)
		do
			add_message (a_msg, "success")
		end
	report_form_errors (fd: WSF_FORM_DATA)
		require
			has_error: not fd.is_valid
		do
			if attached fd.errors as errs then
				across
					errs as err
				loop
					if attached err.item as e then
						if attached e.field as l_field then
							if attached e.message as e_msg then
								add_error_message (e_msg) --"Field [" + l_field.name + "] is invalid. " + e_msg)
							else
								add_error_message ("Field [" + l_field.name + "] is invalid.")
							end
						elseif attached e.message as e_msg then
							add_error_message (e_msg)
						end
					end
				end
			end
		end
	message: detachable STRING_8
feature -- Theme
	theme: CMS_THEME
			-- Current theme
	get_theme
		local
			l_info: CMS_THEME_INFORMATION
		do
			if attached setup.theme_information_location as fn then
				create l_info.make (fn)
			else
				create l_info.make_default
			end
			if l_info.engine.is_case_insensitive_equal_general ("smarty") then
				create {SMARTY_CMS_THEME} theme.make (api, l_info, site_url)
			else
				create {MISSING_CMS_THEME} theme.make (api, l_info, site_url)
				status_code := {HTTP_STATUS_CODE}.service_unavailable
				to_implement ("Check how to add the Retry-after, http://tools.ietf.org/html/rfc7231#section-6.6.4 and http://tools.ietf.org/html/rfc7231#section-7.1.3")
			end
		end
feature -- Theme helpers
	wsf_theme: WSF_THEME
			-- WSF Theme from CMS `theme' for Current response.
		local
			t: like internal_wsf_theme
		do
			t := internal_wsf_theme
			if t = Void then
				create {CMS_TO_WSF_THEME} t.make (Current, theme)
				internal_wsf_theme := t
			end
			Result := t
		end
feature {NONE} -- Theme helpers		
	internal_wsf_theme: detachable WSF_THEME
			-- Once per object for `wsf_theme'.
feature -- Cache managment
	clear_cache (a_cache_id_list: detachable ITERABLE [READABLE_STRING_GENERAL])
			-- Clear caches identified by `a_cache_id_list',
			-- or clear all caches if `a_cache_id_list' is Void.	
		do
			if has_permissions (<<"clear blocks cache", "admin core caches">>) then
				clear_block_caches (a_cache_id_list)
			end
		end
feature -- Response builtin variables
	builtin_variables: STRING_TABLE [detachable ANY]
			-- builtin variables value indexed by name.
		do
			Result := api.builtin_variables
			Result ["site_url"] := site_url
			Result ["host"] := site_url -- FIXME: check and remove if unused.
			Result ["is_https"] := request.is_https
		end
feature -- Generation
	prepare (page: CMS_HTML_PAGE)
		local
			lnk: CMS_LINK
			l_region: CMS_BLOCK_REGION
			l_menu_list_prepared: ARRAYED_LIST [CMS_LINK_COMPOSITE]
			l_empty_blocks: detachable ARRAYED_LIST [CMS_BLOCK]
			l_block_html: STRING
		do
			if api.enabled_modules.count <= 1 then
					-- It is the required CMS_CORE_MODULE!
				if api.has_storage_error then
					add_error_message ("Issue with the storage initialization!")
				else
					lnk := api.administration_link ("Install", "install")
					if lnk.location.same_string (location) then
							-- We are on the Install page!
					else
						add_to_primary_menu (lnk)
					end
				end
			end
				-- Cms response
			api.hooks.invoke_response_alter (Current)
				-- Sort items
			menu_system.sort
				-- Values
			common_prepare (page)
			custom_prepare (page)
				-- Cms values
			api.hooks.invoke_value_table_alter (values, Current)
				-- Predefined values
			page.register_variable (page, "page") -- DO NOT REMOVE
				-- Sort items
			menu_system.sort
				-- Blocks
			create l_menu_list_prepared.make (0)
			get_blocks
			across
				regions as reg_ic
			loop
				l_region := reg_ic.item
				across
					l_region.blocks as ic
				loop
					if attached {CMS_MENU_BLOCK} ic.item as l_menu_block then
						l_menu_list_prepared.force (l_menu_block.menu)
						prepare_links (l_menu_block.menu)
						if l_menu_block.menu.is_empty then
							if l_empty_blocks = Void then
								create l_empty_blocks.make (1)
							end
							l_empty_blocks.force (l_menu_block)
						end
					end
				end
				if l_empty_blocks /= Void then
					across
						l_empty_blocks as ic
					loop
						l_region.remove (ic.item)
					end
					l_empty_blocks := Void
				end
			end
				-- Prepare menu not in a block.
			across
				menu_system as ic
			loop
				if not l_menu_list_prepared.has (ic.item) then
					l_menu_list_prepared.force (ic.item)
					prepare_links (ic.item)
				end
			end
			l_menu_list_prepared.wipe_out -- Clear for memory purpose.
				-- Values Associated with current Execution object.
			across
				values as ic
			loop
				page.register_variable (ic.item, ic.key)
			end
				-- Block rendering
			across
				regions as reg_ic
			loop
				l_region := reg_ic.item
					-- region blocks Already sorted.
				across
					l_region.blocks as ic
				loop
					if attached {CMS_SMARTY_TEMPLATE_BLOCK} ic.item as l_tpl_block then
							-- Apply page variables to smarty block.
							-- FIXME: maybe add notion of values at the CMS_BLOCK level
							--        or consider a CMS_BLOCK_WITH_VALUES ...
						across
							page.variables as var_ic
						loop
							if not l_tpl_block.values.has (var_ic.key) then
									-- Do not overwrite if has key.
								l_tpl_block.set_value (var_ic.item, var_ic.key)
							end
						end
					end
					l_block_html := theme.block_html (ic.item)
					if attached {CMS_CACHE_BLOCK} ic.item then
							-- Already block from cache
						do_nothing
					elseif attached block_cache (ic.item.name) as l_block_cache_info then
							-- Cache-able block, then update/create the related cache.
						l_block_cache_info.cache_block.set_cache_content (l_block_html)
					end
					page.add_to_region (l_block_html, reg_ic.item.name)
				end
			end
				-- Additional lines in 
			if attached additional_page_head_lines as l_head_lines then
				across
					l_head_lines as hl
				loop
					page.head_lines.force (hl.item)
				end
			end
		end
	common_prepare (page: CMS_HTML_PAGE)
			-- Common preparation for page `page'.
		do
			debug ("refactor_fixme")
				fixme ("Fix generation common")
			end
				-- Information
			page.set_title (title)
			debug ("cms")
				if title = Void then
					page.set_title ({STRING_32} "CMS::" + request.path_info) --| FIXME: probably, should be removed and handled by theme.
				end
			end
				-- Fill with CMS builtin variables.
			across
				builtin_variables as ic
			loop
				page.register_variable (ic.item, ic.key)
			end
				-- Variables
			page.register_variable (absolute_url ("", Void), "site_url")
			page.register_variable (base_path, "base_path")
			page.register_variable (absolute_url ("", Void), "host") -- Same as `site_url'.
			page.register_variable (request.is_https, "is_https")
			if attached title as l_title then
				page.register_variable (l_title, "head_title")
				page.register_variable (l_title, "site_title")
			else
				page.register_variable (site_name, "head_title")
				page.register_variable (site_name, "site_title")
			end
			page.set_is_front (is_front)
			page.set_is_https (request.is_https)
				-- Variables/Misc
			page.register_variable (is_administration_mode, "is_administration_mode")
			page.register_variable (api.theme_path, "theme_path")
-- FIXME: logo .. could be a settings of theme, managed by admin front-end/database.
--			if attached logo_location as l_logo then
--				page.register_variable (l_logo, "logo")
--			end
				-- Menu...
			page.register_variable (horizontal_primary_menu_html, "primary_nav")
			page.register_variable (horizontal_primary_tabs_html, "primary_tabs")
				-- Page related
			if attached page_class_css as l_page_css then
				page.register_variable (l_page_css, "page_class_css")
			end
			if attached page_title as l_page_title then
				page.register_variable (l_page_title, "page_title")
			end
		end
	custom_prepare (page: CMS_HTML_PAGE)
			-- Common preparation for page `page' that can be redefined by descendants.
		do
		end
	prepare_links (a_comp: CMS_LINK_COMPOSITE)
			-- Update the active status recursively on `a_comp'.
		local
			to_remove: ARRAYED_LIST [CMS_LINK]
			ln: CMS_LINK
			l_comp_link: detachable CMS_LOCAL_LINK
		do
			if attached {CMS_LOCAL_LINK} a_comp as lnk then
				l_comp_link := lnk
				get_local_link_active_status (lnk)
			end
			if attached a_comp.items as l_items then
				create to_remove.make (0)
				across
					l_items as ic
				loop
					ln := ic.item
					if attached {CMS_LOCAL_LINK} ln as l_local then
						get_local_link_active_status (l_local)
					end
					if ln.is_forbidden then
						to_remove.force (ln)
					else
						if
							(ln.is_expanded or ln.is_collapsed) and then
							attached {CMS_LINK_COMPOSITE} ln as l_comp
						then
							prepare_links (l_comp)
						end
						if l_comp_link /= Void then
							if ln.is_expanded or (not ln.is_expandable and ln.is_active) then
								l_comp_link.set_expanded (True)
							end
						end
					end
				end
				across
					to_remove as ic
				loop
					a_comp.remove (ic.item)
				end
			end
			if l_comp_link /= Void and then l_comp_link.is_active then
				l_comp_link.set_expanded (True)
			end
		end
	get_local_link_active_status (a_lnk: CMS_LOCAL_LINK)
			-- Get `a_lnk.is_active' value according to `request' data.
		local
			qs: STRING
			l_is_active: BOOLEAN
		do
			create qs.make_from_string (request.percent_encoded_path_info)
			if qs.starts_with ("/") then
				qs.remove_head (1)
			end
			l_is_active := qs.same_string (a_lnk.location)
			if not l_is_active then
				if attached request.query_string as l_query_string and then not l_query_string.is_empty then
					qs.append_character ('?')
					qs.append (l_query_string)
				end
				l_is_active := qs.same_string (a_lnk.location)
			end
			a_lnk.set_is_active (l_is_active)
			a_lnk.set_is_forbidden (not has_permission_on_link (a_lnk))
		end
feature -- Helpers: html links
	user_html_link (u: CMS_USER): STRING
		require
			u_with_name: not u.name.is_whitespace
		do
			Result := api.user_html_link (u)
		end
	destination_location: detachable READABLE_STRING_8
			-- Destination location
			-- used across the CMS to track a location to come to later.
		do
			Result := api.destination_location (request)
		end
feature -- Execution
	execute
		do
			begin
			process
			terminate
		end
feature {NONE} -- Execution		
	begin
		local
			lnk: CMS_LINK
		do
				-- Menu
			create {CMS_LOCAL_LINK} lnk.make ("Home", "")
			lnk.set_weight (-10)
			add_to_primary_menu (lnk)
			api.hooks.invoke_menu_system_alter (menu_system, Current)
		end
	process
		deferred
		end
	frozen terminate
		local
			cms_page: CMS_HTML_PAGE
			page: CMS_HTML_PAGE_RESPONSE
			h: HTTP_HEADER
			l_new_location: detachable READABLE_STRING_8
			l_redirection_delay: like redirection_delay
		do
			if attached redirection as l_location then
					-- FIXME: find out if this is safe or not.
				if l_location.has_substring ("://") then
					l_new_location := l_location
				else
					l_new_location := location_absolute_url (l_location, Void)
				end
				l_redirection_delay := redirection_delay
				if l_redirection_delay > 0 then
					add_additional_head_line ("