Automatic generation produced by ISE Eiffel
indexing
description: "System's entry class derived from CGI_INTERFACE, takes care of requests and sends back responses"
author: "Peizhu Li <lip@student.ethz.ch>"
date: "12.12.2007"
revision: "0.2"
deferred class
REQUEST_DISPATCHER
feature {NONE} -- Initialization
default_create
-- Process instances of classes with no creation clause.
-- (Default: do nothing.)
-- (from ANY)
do
end
feature {CGI_FORMS} -- Access
form_data: HASH_TABLE [LINKED_LIST [STRING_8], STRING_8]
-- User provided data.
-- (from CGI_INTERFACE)
hexa_to_ascii (s: STRING_8)
-- Replace %xy by the corresponding ASCII character.
-- (from CGI_INTERFACE)
local
char: CHARACTER_8
new: STRING_8
i: INTEGER_32
do
create new.make (s.count)
from
i := 1
until
i > s.count
loop
if s.item (i) = '%%' then
if s.valid_index (i + 1) and s.valid_index (i + 2) then
char := charconv (16 * hexa_value (s.item (i + 1)) + hexa_value (s.item (i + 2)))
new.append_character (char)
i := i + 2
else
new.append_character (s.item (i))
end
else
new.append_character (s.item (i))
end
i := i + 1
end
s.make_from_string (new)
end
hexa_value (c: CHARACTER_8): INTEGER_32
-- Hexadecimal value of a character from the hexa alphabet.
-- (from CGI_INTERFACE)
require -- from CGI_INTERFACE
valid_hexa_character: (c >= '0' and c <= '9') or (c >= 'A' and c <= 'F')
do
inspect c
when '0'..'9' then
Result := c.code - ('0').code
when 'A'..'F' then
Result := c.code - ('A').code + 10
end
end
input_data: STRING_8
-- Data sent by the server.
-- (from CGI_INTERFACE)
once
if request_method.is_equal ("POST") then
if content_length.is_integer then
stdin.read_stream (content_length.to_integer)
Result := stdin.last_string
else
raise_error ("Incorrect value for CONTENT_LENGTH")
end
else
Result := query_string
end
if Result = Void then
Result := ""
end
ensure -- from CGI_INTERFACE
input_data_exists: Result /= Void
end
insert_pair (name, val: STRING_8)
-- Insert pair (name,value) into form_data; take care of collisions.
-- (from CGI_INTERFACE)
local
vl: LINKED_LIST [STRING_8]
do
hexa_to_ascii (name)
hexa_to_ascii (val)
if form_data.has (name) then
form_data.item (name).extend (val)
form_data.item (name).start
else
create vl.make
vl.extend (val)
vl.start
form_data.put (vl, name)
end
end
parse_arguments (args: ARRAY [STRING_8])
-- Parse arguments array and set environment variables.
-- (from CGI_INTERFACE)
local
i, sep_index: INTEGER_32
lh, rh, item: STRING_8
do
from
i := args.lower
until
i > args.upper
loop
item := args.item (i)
sep_index := item.index_of ('=', 1)
if sep_index > 1 then
lh := item.substring (1, sep_index - 1)
if sep_index < item.count then
rh := item.substring (sep_index + 1, item.count)
else
rh := ""
end
set_environment_variable (lh, rh)
end
i := i + 1
end
end
parse_input
-- Split input string and build (name,value) pairs.
-- (from CGI_INTERFACE)
local
data, pair, key, val: STRING_8
nb_pairs, c, sep_index, field_sep_index: INTEGER_32
done: BOOLEAN
do
data := input_data.twin
if not data.is_empty then
data.replace_substring_all ("+", " ")
nb_pairs := data.occurrences (pair_separator) + 1
create form_data.make (nb_pairs)
from
c := 1
until
done or else c > data.count
loop
sep_index := data.index_of (pair_separator, c)
if sep_index = 1 then
c := 2
else
if sep_index = 0 then
pair := data.substring (c, data.count)
done := True
else
pair := data.substring (c, sep_index - 1)
end
field_sep_index := pair.index_of (value_separator, 1)
key := pair.substring (1, field_sep_index - 1)
if pair.count >= field_sep_index + 1 then
val := pair.substring (field_sep_index + 1, pair.count)
else
val := ""
end
insert_pair (key, val)
c := sep_index + 1
end
end
else
create form_data.make (0)
end
end
feature -- Access
button_value (field_name: STRING_8; overriding_value: STRING_8): BOOLEAN
-- Is Button relative to 'field_name' selected ?
-- (from CGI_FORMS)
require -- from CGI_FORMS
field_not_void: field_name /= Void
field_exists: field_defined (field_name)
local
s: STRING_8
do
s := form_data.item (field_name).first
s.to_lower
if s.is_equal ("on") then
Result := True
elseif overriding_value /= Void then
overriding_value.to_lower
Result := overriding_value.is_equal (s)
end
end
generating_type: STRING_8
-- Name of current object's generating type
-- (type of which it is a direct instance)
-- (from ANY)
external
"built_in"
ensure -- from ANY
generating_type_not_void: Result /= Void
generating_type_not_empty: not Result.is_empty
end
generator: STRING_8
-- Name of current object's generating class
-- (base class of the type of which it is a direct instance)
-- (from ANY)
external
"built_in"
ensure -- from ANY
generator_not_void: Result /= Void
generator_not_empty: not Result.is_empty
end
menu_values (field_name: STRING_8): LINKED_LIST [STRING_8]
-- Selected values for a list, whose name
-- is 'field_name'.
-- (from CGI_FORMS)
require -- from CGI_FORMS
field_not_void: field_name /= Void
field_exists: field_defined (field_name)
do
Result := form_data.item (field_name)
ensure -- from CGI_FORMS
value_exists: Result /= Void
end
output: STDOUT
-- Shared standard output.
-- (from CGI_IN_AND_OUT)
once
create Result.make
end
response_header: CGI_RESPONSE_HEADER
-- (from CGI_IN_AND_OUT)
once
create Result
end
stdin: STDIN
-- Shared standard input
-- (from CGI_IN_AND_OUT)
once
create Result.make
end
text_field_value (field_name: STRING_8): STRING_8
-- First (unique?) value for a text field.
-- Applies for a password and a text area too.
-- (from CGI_FORMS)
require -- from CGI_FORMS
field_not_void: field_name /= Void
field_exists: field_defined (field_name)
do
Result := form_data.item (field_name).first
ensure -- from CGI_FORMS
value_exists: Result /= Void
end
feature {NONE} -- Access
check_instruction: INTEGER_32 is 7
-- Exception code for violated check
-- (from EXCEP_CONST)
class_invariant: INTEGER_32 is 6
-- Exception code for violated class invariant
-- (from EXCEP_CONST)
com_exception: INTEGER_32 is 28
-- Exception code for a COM error.
-- (from EXCEP_CONST)
command_line: ARGUMENTS
-- Command line that was used to start current execution
-- (from EXECUTION_ENVIRONMENT)
once
create Result
end
create_on_deferred: INTEGER_32 is 17
-- Create on deferred
-- (from EXCEP_CONST)
current_working_directory: STRING_8
-- Directory of current execution
-- (from EXECUTION_ENVIRONMENT)
external
"C use %"eif_dir.h%""
alias
"dir_current"
ensure -- from EXECUTION_ENVIRONMENT
result_not_void: Result /= Void
end
default_shell: STRING_8
-- Default shell
-- (from EXECUTION_ENVIRONMENT)
once
Result := get ("SHELL")
if Result = Void then
Result := ""
end
end
developer_exception: INTEGER_32 is 24
-- Exception code for developer exception
-- (from EXCEP_CONST)
dollar_applied_to_melted_feature: INTEGER_32 is 26
-- $ applied to melted feature
-- (from EXCEP_CONST)
eiffel_runtime_fatal_error: INTEGER_32 is 25
-- Eiffel run-time fatal error
-- (from EXCEP_CONST)
eiffel_runtime_panic: INTEGER_32 is 13
-- Eiffel run-time panic
-- (from EXCEP_CONST)
exception_in_signal_handler: INTEGER_32 is 20
-- Exception in signal handler
-- (from EXCEP_CONST)
external_exception: INTEGER_32 is 18
-- Exception code for operating system error
-- which does not set the `errno' variable
-- (Unix-specific)
-- (from EXCEP_CONST)
floating_point_exception: INTEGER_32 is 5
-- Exception code for floating point exception
-- (from EXCEP_CONST)
get (s: STRING_8): STRING_8
-- Value of `s' if it is an environment variable and has been set;
-- void otherwise.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
s_exists: s /= Void
not_has_null_character: not s.has ('%U')
local
ext: ANY
c_string: POINTER
void_pointer: POINTER
do
ext := s.to_c
c_string := eif_getenv ($ext)
if c_string /= void_pointer then
create Result.make_from_c (c_string)
end
end
home_directory_name: STRING_8
-- Directory name corresponding to the home directory.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
home_directory_supported: operating_environment.home_directory_supported
do
Result := eif_home_directory_name
end
incorrect_inspect_value: INTEGER_32 is 9
-- Exception code for inspect value which is not one
-- of the inspect constants, if there is no Else_part
-- (from EXCEP_CONST)
io_exception: INTEGER_32 is 21
-- Exception code for I/O error
-- (from EXCEP_CONST)
loop_invariant: INTEGER_32 is 11
-- Exception code for violated loop invariant
-- (from EXCEP_CONST)
loop_variant: INTEGER_32 is 10
-- Exception code for non-decreased loop variant
-- (from EXCEP_CONST)
no_more_memory: INTEGER_32 is 2
-- Exception code for failed memory allocation
-- (from EXCEP_CONST)
number_of_codes: INTEGER_32 is 29
-- How many codes are there to represent exceptions?
-- (from EXCEP_CONST)
operating_system_exception: INTEGER_32 is 22
-- Exception code for operating system error
-- which sets the `errno' variable
-- (Unix-specific)
-- (from EXCEP_CONST)
out_of_memory: INTEGER_32 is 15
-- Out of memory (cannot be ignored)
-- (from EXCEP_CONST)
postcondition: INTEGER_32 is 4
-- Exception code for violated postcondition
-- (from EXCEP_CONST)
precondition: INTEGER_32 is 3
-- Exception code for violated precondition
-- (from EXCEP_CONST)
rescue_exception: INTEGER_32 is 14
-- Exception code for exception in rescue clause
-- (from EXCEP_CONST)
resumption_failed: INTEGER_32 is 16
-- Resumption failed (retry did not succeed)
-- (from EXCEP_CONST)
retrieve_exception: INTEGER_32 is 23
-- Exception code for retrieval error
-- may be raised by `retrieved' in `IO_MEDIUM'.
-- (from EXCEP_CONST)
root_directory_name: STRING_8
-- Directory name corresponding to the root directory.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
root_directory_supported: operating_environment.root_directory_supported
do
Result := eif_root_directory_name
ensure -- from EXECUTION_ENVIRONMENT
result_not_void: Result /= Void
end
routine_failure: INTEGER_32 is 8
-- Exception code for failed routine
-- (from EXCEP_CONST)
runtime_check_exception: INTEGER_32 is 29
-- Exception code for runtime check being violated.
-- (from EXCEP_CONST)
runtime_io_exception: INTEGER_32 is 27
-- Exception code for I/O error raised by runtime functions
-- such as store/retrieve, file access...
-- (from EXCEP_CONST)
signal_exception: INTEGER_32 is 12
-- Exception code for operating system signal
-- (from EXCEP_CONST)
starting_environment_variables: HASH_TABLE [STRING_8, STRING_8]
-- Table of environment variables when current process starts,
-- indexed by variable name
-- (from EXECUTION_ENVIRONMENT)
local
l_ptr: POINTER
i: INTEGER_32
l_curr_var: TUPLE [value: STRING_8; key: STRING_8]
do
create Result.make (40)
from
i := 0
l_ptr := i_th_environ (i)
until
l_ptr = default_pointer
loop
l_curr_var := separated_variables (create {STRING_8}.make_from_c (l_ptr))
if l_curr_var /= Void then
Result.force (l_curr_var.value, l_curr_var.key)
end
i := i + 1
l_ptr := i_th_environ (i)
end
ensure -- from EXECUTION_ENVIRONMENT
result_attached: Result /= Void
end
valid_code (c: INTEGER_32): BOOLEAN
-- Is `c' a valid code to represent some kind of exceptions?
-- (from EXCEP_CONST)
do
Result := c >= 1 and c <= number_of_codes
end
void_assigned_to_expanded: INTEGER_32 is 19
-- Exception code for assignment of void value
-- to expanded entity
-- (from EXCEP_CONST)
void_call_target: INTEGER_32 is 1
-- Exception code for feature applied to void reference
-- (from EXCEP_CONST)
feature {CGI_ERROR_HANDLING} -- Access
raised_error: STRING_8
-- Error explicitely raised by developer code.
-- (from CGI_ERROR_HANDLING)
feature -- Comparison
frozen deep_equal (some: ANY; other: like arg #1): BOOLEAN
-- Are `some' and `other' either both void
-- or attached to isomorphic object structures?
-- (from ANY)
do
if some = Void then
Result := other = Void
else
Result := other /= Void and then some.is_deep_equal (other)
end
ensure -- from ANY
shallow_implies_deep: standard_equal (some, other) implies Result
both_or_none_void: (some = Void) implies (Result = (other = Void))
same_type: (Result and (some /= Void)) implies some.same_type (other)
symmetric: Result implies deep_equal (other, some)
end
frozen equal (some: ANY; other: like arg #1): BOOLEAN
-- Are `some' and `other' either both void or attached
-- to objects considered equal?
-- (from ANY)
do
if some = Void then
Result := other = Void
else
Result := other /= Void and then some.is_equal (other)
end
ensure -- from ANY
definition: Result = (some = Void and other = Void) or else ((some /= Void and other /= Void) and then some.is_equal (other))
end
frozen is_deep_equal (other: like Current): BOOLEAN
-- Are `Current' and `other' attached to isomorphic object structures?
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
external
"built_in"
ensure -- from ANY
shallow_implies_deep: standard_is_equal (other) implies Result
same_type: Result implies same_type (other)
symmetric: Result implies other.is_deep_equal (Current)
end
is_equal (other: like Current): BOOLEAN
-- Is `other' attached to an object considered
-- equal to current object?
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
do
Result := standard_is_equal (other)
ensure -- from ANY
symmetric: Result implies other.is_equal (Current)
consistent: standard_is_equal (other) implies Result
end
frozen standard_equal (some: ANY; other: like arg #1): BOOLEAN
-- Are `some' and `other' either both void or attached to
-- field-by-field identical objects of the same type?
-- Always uses default object comparison criterion.
-- (from ANY)
do
if some = Void then
Result := other = Void
else
Result := other /= Void and then some.standard_is_equal (other)
end
ensure -- from ANY
definition: Result = (some = Void and other = Void) or else ((some /= Void and other /= Void) and then some.standard_is_equal (other))
end
frozen standard_is_equal (other: like Current): BOOLEAN
-- Is `other' attached to an object of the same type
-- as current object, and field-by-field identical to it?
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
external
"built_in"
ensure -- from ANY
same_type: Result implies same_type (other)
symmetric: Result implies other.standard_is_equal (Current)
end
feature -- Status report
conforms_to (other: ANY): BOOLEAN
-- Does type of current object conform to type
-- of `other' (as per Eiffel: The Language, chapter 13)?
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
external
"built_in"
end
same_type (other: ANY): BOOLEAN
-- Is type of current object identical to type of `other'?
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
external
"built_in"
ensure -- from ANY
definition: Result = (conforms_to (other) and other.conforms_to (Current))
end
feature {NONE} -- Status report
assertion_violation: BOOLEAN
-- Is last exception originally due to a violated
-- assertion or non-decreasing variant?
-- (from EXCEPTIONS)
do
Result := (original_exception = check_instruction) or else (original_exception = class_invariant) or else (original_exception = loop_invariant) or else (original_exception = loop_variant) or else (original_exception = postcondition) or else (original_exception = precondition)
end
class_name: STRING_8
-- Name of the class that includes the recipient
-- of original form of last exception
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eelclass"
end
developer_exception_name: STRING_8
-- Name of last developer-raised exception
-- (from EXCEPTIONS)
require -- from EXCEPTIONS
applicable: is_developer_exception
do
Result := original_tag_name
end
exception: INTEGER_32
-- Code of last exception that occurred
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eelcode"
end
exception_trace: STRING_8
-- String representation of the exception trace
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"stack_trace_string"
end
is_developer_exception: BOOLEAN
-- Is the last exception originally due to
-- a developer exception?
-- (from EXCEPTIONS)
do
Result := (original_exception = developer_exception)
end
is_developer_exception_of_name (name: STRING_8): BOOLEAN
-- Is the last exception originally due to a developer
-- exception of name `name'?
-- (from EXCEPTIONS)
do
Result := is_developer_exception and then equal (name, developer_exception_name)
end
is_signal: BOOLEAN
-- Is last exception originally due to an external
-- event (operating system signal)?
-- (from EXCEPTIONS)
do
Result := (original_exception = signal_exception)
end
is_system_exception: BOOLEAN
-- Is last exception originally due to an
-- external event (operating system error)?
-- (from EXCEPTIONS)
do
Result := (original_exception = external_exception) or else (original_exception = operating_system_exception)
end
meaning (except: INTEGER_32): STRING_8
-- A message in English describing what `except' is
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eename"
end
original_class_name: STRING_8
-- Name of the class that includes the recipient
-- of original form of last exception
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eeoclass"
end
original_exception: INTEGER_32
-- Original code of last exception that triggered
-- current exception
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eeocode"
end
original_recipient_name: STRING_8
-- Name of the routine whose execution was
-- interrupted by original form of last exception
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eeorout"
end
original_tag_name: STRING_8
-- Assertion tag for original form of last
-- assertion violation.
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eeotag"
end
recipient_name: STRING_8
-- Name of the routine whose execution was
-- interrupted by last exception
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eelrout"
end
tag_name: STRING_8
-- Tag of last violated assertion clause
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eeltag"
end
feature {NONE} -- Status setting
catch (code: INTEGER_32)
-- Make sure that any exception of code `code' will be
-- caught. This is the default.
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eecatch"
end
change_working_directory (path: STRING_8)
-- Set the current directory to `path'
-- (from EXECUTION_ENVIRONMENT)
local
ext: ANY
do
ext := path.to_c
return_code := eif_chdir ($ext)
end
die (code: INTEGER_32)
-- Terminate execution with exit status `code',
-- without triggering an exception.
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"esdie"
end
ignore (code: INTEGER_32)
-- Make sure that any exception of code `code' will be
-- ignored. This is not the default.
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eeignore"
end
launch (s: STRING_8)
-- Pass to the operating system an asynchronous request to
-- execute `s'.
-- If `s' is empty, use the default shell as command.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
s_not_void: s /= Void
local
ext: ANY
do
if s.is_empty then
ext := default_shell.to_c
else
ext := s.to_c
end
asynchronous_system_call ($ext)
end
message_on_failure
-- Print an exception history table
-- in case of failure.
-- This is the default.
-- (from EXCEPTIONS)
do
c_trace_exception (True)
end
new_die (code: INTEGER_32)
obsolete "Use ``die''"
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"esdie"
end
no_message_on_failure
-- Do not print an exception history table
-- in case of failure.
-- (from EXCEPTIONS)
do
c_trace_exception (False)
end
put (value, key: STRING_8)
-- Set the environment variable `key' to `value'.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
key_exists: key /= Void
key_meaningful: not key.is_empty
not_key_has_null_character: not key.has ('%U')
value_exists: value /= Void
not_value_has_null_character: not value.has ('%U')
local
l_env: STRING_8
l_c_env: C_STRING
do
create l_env.make (value.count + key.count + 1)
l_env.append (key)
l_env.append_character ('=')
l_env.append (value)
create l_c_env.make (l_env)
environ.force (l_c_env, key)
return_code := eif_putenv (l_c_env.item)
ensure -- from EXECUTION_ENVIRONMENT
variable_set: (return_code = 0) implies (equal (value, get (key)) or else (value.is_empty and then (get (key) = Void)))
end
raise (name: STRING_8)
-- Raise a developer exception of name `name'.
-- (from EXCEPTIONS)
local
str: ANY
do
if name /= Void then
str := name.to_c
end
eraise ($str, developer_exception)
end
raise_retrieval_exception (name: STRING_8)
-- Raise a retrieval exception of name `name'.
-- (from EXCEPTIONS)
local
str: ANY
do
if name /= Void then
str := name.to_c
end
eraise ($str, retrieve_exception)
end
system (s: STRING_8)
-- Pass to the operating system a request to execute `s'.
-- If `s' is empty, use the default shell as command.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
s_exists: s /= Void
local
ext: ANY
do
if s.is_empty then
ext := default_shell.to_c
else
ext := s.to_c
end
return_code := system_call ($ext)
end
feature {NONE} -- Conversion
charconv (i: INTEGER_32): CHARACTER_8
-- Character associated with integer value `i'
-- (from BASIC_ROUTINES)
do
Result := (i & 255).to_character_8
end
feature -- Duplication
frozen clone (other: ANY): like other
obsolete "Use `twin' instead."
-- Void if `other' is void; otherwise new object
-- equal to `other'
--
-- For non-void `other', clone calls copy;
-- to change copying/cloning semantics, redefine copy.
-- (from ANY)
do
if other /= Void then
Result := other.twin
end
ensure -- from ANY
equal: equal (Result, other)
end
copy (other: like Current)
-- Update current object using fields of object attached
-- to `other', so as to yield equal objects.
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
type_identity: same_type (other)
external
"built_in"
ensure -- from ANY
is_equal: is_equal (other)
end
frozen deep_clone (other: ANY): like other
obsolete "Use `deep_twin' instead."
-- Void if `other' is void: otherwise, new object structure
-- recursively duplicated from the one attached to `other'
-- (from ANY)
do
if other /= Void then
Result := other.deep_twin
end
ensure -- from ANY
deep_equal: deep_equal (other, Result)
end
frozen deep_copy (other: like Current)
-- Effect equivalent to that of:
-- copy (`other' . deep_twin)
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
do
copy (other.deep_twin)
ensure -- from ANY
deep_equal: deep_equal (Current, other)
end
frozen deep_twin: like Current
-- New object structure recursively duplicated from Current.
-- (from ANY)
external
"built_in"
ensure -- from ANY
deep_twin_not_void: Result /= Void
deep_equal: deep_equal (Current, Result)
end
frozen standard_clone (other: ANY): like other
obsolete "Use `standard_twin' instead."
-- Void if `other' is void; otherwise new object
-- field-by-field identical to `other'.
-- Always uses default copying semantics.
-- (from ANY)
do
if other /= Void then
Result := other.standard_twin
end
ensure -- from ANY
equal: standard_equal (Result, other)
end
frozen standard_copy (other: like Current)
-- Copy every field of `other' onto corresponding field
-- of current object.
-- (from ANY)
require -- from ANY
other_not_void: other /= Void
type_identity: same_type (other)
external
"built_in"
ensure -- from ANY
is_standard_equal: standard_is_equal (other)
end
frozen standard_twin: like Current
-- New object field-by-field identical to `other'.
-- Always uses default copying semantics.
-- (from ANY)
local
l_temp: BOOLEAN
do
l_temp := {ISE_RUNTIME}.check_assert (False)
Result ?= {ISE_RUNTIME}.c_standard_clone ($Current)
Result.standard_copy (Current)
l_temp := {ISE_RUNTIME}.check_assert (l_temp)
ensure -- from ANY
standard_twin_not_void: Result /= Void
equal: standard_equal (Result, Current)
end
frozen twin: like Current
-- New object equal to `Current'
-- twin calls copy; to change copying/twining semantics, redefine copy.
-- (from ANY)
local
l_temp: BOOLEAN
do
l_temp := {ISE_RUNTIME}.check_assert (False)
Result ?= {ISE_RUNTIME}.c_standard_clone ($Current)
Result.copy (Current)
l_temp := {ISE_RUNTIME}.check_assert (l_temp)
ensure -- from ANY
twin_not_void: Result /= Void
is_equal: Result.is_equal (Current)
end
feature -- Basic operations
frozen default: like Current
-- Default value of object's type
-- (from ANY)
do
end
frozen default_pointer: POINTER
-- Default value of type `POINTER'
-- (Avoid the need to write `p'.default for
-- some `p' of type `POINTER'.)
-- (from ANY)
do
end
default_rescue
-- Process exception for routines with no Rescue clause.
-- (Default: do nothing.)
-- (from ANY)
do
end
frozen do_nothing
-- Execute a null action.
-- (from ANY)
do
end
feature {NONE} -- Basic operations
abs (n: INTEGER_32): INTEGER_32
-- Absolute value of `n'
-- (from BASIC_ROUTINES)
do
if n < 0 then
Result := - n
else
Result := n
end
ensure -- from BASIC_ROUTINES
non_negative_result: Result >= 0
end
bottom_int_div (n1, n2: INTEGER_32): INTEGER_32
-- Greatest lower bound of the integer division of `n1' by `n2'
-- (from BASIC_ROUTINES)
do
Result := n1 // n2
if n1 >= 0 xor n2 > 0 then
if (n1 \\ n2) /= 0 then
Result := Result - 1
end
end
end
rsign (r: REAL_32): INTEGER_32
-- Sign of `r':
-- -1 if `r' < 0
-- 0 if `r' = 0
-- +1 if `r' > 0
-- (from BASIC_ROUTINES)
do
if r < 0 then
Result := -1
elseif r > 0 then
Result := 1
end
ensure -- from BASIC_ROUTINES
correct_negative: (r < 0) = (Result = -1)
correct_zero: (r = 0) = (Result = 0)
correct_positive: (r > 0) = (Result = 1)
end
sign (n: INTEGER_32): INTEGER_32
-- Sign of `n':
-- -1 if `n' < 0
-- 0 if `n' = 0
-- +1 if `n' > 0
-- (from BASIC_ROUTINES)
do
if n < 0 then
Result := -1
elseif n > 0 then
Result := 1
end
ensure -- from BASIC_ROUTINES
correct_negative: (n < 0) = (Result = -1)
correct_zero: (n = 0) = (Result = 0)
correct_positive: (n > 0) = (Result = 1)
end
up_int_div (n1, n2: INTEGER_32): INTEGER_32
-- Least upper bound of the integer division
-- of `n1' by `n2'
-- (from BASIC_ROUTINES)
do
Result := n1 // n2
if not (n1 >= 0 xor n2 > 0) then
if (n1 \\ n2) /= 0 then
Result := Result + 1
end
end
end
feature {NONE} -- Implementation
c_trace_exception (b: BOOLEAN)
-- (from EXCEPTIONS)
external
"C use %"eif_except.h%""
alias
"eetrace"
end
environ: HASH_TABLE [C_STRING, STRING_8]
-- Environment variable memory set by current execution,
-- indexed by environment variable name. Needed otherwise
-- we would corrupt memory after freeing memory used by
-- C_STRING instance since not referenced anywhere else.
-- (from EXECUTION_ENVIRONMENT)
once
create Result.make (10)
end
eraise (str: POINTER; code: INTEGER_32)
-- Raise an exception
-- (from EXCEPTIONS)
external
"C signature (char *, long) use %"eif_except.h%""
end
get_env_variable (v: STRING_8): STRING_8
-- Get value of environment variable `v'.
-- (from CGI_ENVIRONMENT)
do
Result := get (v)
if Result = Void then
Result := ""
end
end
i_th_environ (i: INTEGER_32): POINTER
-- Environment variable at `i'-th position of `eif_environ'.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
i_valid: i >= 0
external
"C inline use <string.h>"
alias
"[
if (eif_environ) {
#ifdef EIF_WINDOWS
LPSTR vars = (LPSTR) eif_environ;
int cnt = 0;
for (; *vars; vars++) {
if ($i==cnt) return vars;
while (*vars) { vars++; }
cnt++;
}
return NULL;
#else
return ((char **)eif_environ)[$i];
#endif
} else {
return NULL;
}
]"
end
separated_variables (a_var: STRING_8): TUPLE [value: STRING_8; key: STRING_8]
-- Given an environment variable `a_var' in form of "key=value",
-- return separated key and value.
-- Return Void if `a_var' is in incorrect format.
-- (from EXECUTION_ENVIRONMENT)
require -- from EXECUTION_ENVIRONMENT
a_var_attached: a_var /= Void
local
i, j: INTEGER_32
done: BOOLEAN
do
j := a_var.count
from
i := 1
until
i > j or done
loop
if a_var.item (i) = '=' then
done := True
else
i := i + 1
end
end
if i > 1 and then i < j then
Result := [a_var.substring (i + 1, j), a_var.substring (1, i - 1)]
end
end
feature {REQUEST_DISPATCHER} -- initialization
init_configuration
-- read configuration file
local
istart, iend: INTEGER_32
do
istart := script_name.last_index_of ('/', script_name.count) + 1
iend := script_name.last_index_of ('.', script_name.count) - 1
if iend = -1 or iend <= istart then
iend := script_name.count
end
create config.make ("./" + script_name.substring (istart, iend) + ".conf")
end
instantiate_handler
-- based on initialized handler mapping table, lookup and initialize a handler for current request
require
config_is_set: config /= Void
local
handler_type: STRING_8
handler: INTERNAL
type: INTEGER_32
do
if not config.handler.is_empty then
create handler_type.make_from_string (config.handler)
elseif not config.notfound_request.is_empty then
create handler_type.make_from_string (config.notfound_request)
handler_id_string := config.notfound_request
command_string := config.notfound_command
else
create handler_type.make_empty
end
if not handler_type.is_empty then
create handler
type := handler.dynamic_type_from_string (handler_type)
actual_handler ?= handler.new_instance_of (type)
if actual_handler /= Void then
actual_handler.initialize (Current)
end
end
rescue
io.error.putstring ("crash in `lookup_and_instantiate_handler' %N")
end
parse_handler_command_string
-- identify request and command strings ((http://localhost/cgi-bin/zen.cgi?zengarden&action=register -> zengarden, register)
do
create handler_id_string.make_empty
if not input_data.is_empty then
if input_data.has ('&') then
if not input_data.split ('&').i_th (1).has ('=') then
handler_id_string.append ((input_data.split ('&')).i_th (1))
end
else
handler_id_string.append (input_data)
end
if handler_id_string.is_empty and field_defined ("handler_id") then
handler_id_string.append (text_field_value ("handler_id"))
end
end
if field_defined ("cmd") then
create command_string.make_from_string (text_field_value ("cmd"))
else
create command_string.make_empty
end
end
process_undefined_request
-- generate result page in case unkown request
do
create {ERROR_PAGE_VIEW} return_page.build_default_not_found_page
end
set_session_enabled (a_enabled: BOOLEAN)
-- set whether session should be enabled
do
session_enabled := a_enabled
end
feature -- Advanced Access
fields: ARRAY [STRING_8]
-- Names of fields in the form.
-- (from CGI_FORMS)
once
Result := form_data.current_keys
Result.compare_objects
end
value_count (field_name: STRING_8): INTEGER_32
-- Number of values for a field.
-- (from CGI_FORMS)
require -- from CGI_FORMS
field_not_void: field_name /= Void
field_exists: field_defined (field_name)
do
Result := form_data.item (field_name).count
ensure -- from CGI_FORMS
valid_count: Result >= 0
end
value_list (field_name: STRING_8): LINKED_LIST [STRING_8]
-- List of values for a field.
-- (from CGI_FORMS)
require -- from CGI_FORMS
field_not_void: field_name /= Void
field_exists: field_defined (field_name)
do
Result := form_data.item (field_name)
ensure -- from CGI_FORMS
valid_count: Result.count = value_count (field_name)
end
feature -- Attributes
command_string: STRING_8
-- command string that handler need to process
config: CONFIG_READER
-- website configuration (handler, default stylesheet, actual session class)
cookie_enabled: BOOLEAN
-- whether cookie is enabled by browser
handler_id_string: STRING_8
-- string identifies which handler should be instantiated for actual request
session: SESSION
-- actual session object
session_enabled: BOOLEAN
-- whether session support should be enabled
feature {REQUEST_DISPATCHER} -- Attributes
actual_handler: REQUEST_HANDLER
-- handler that will process actual request
debug_mode: BOOLEAN is True
-- Should exception trace be displayed in case a crash occurs?
processing_finished: BOOLEAN
-- finished processing, return result
return_page: HTML_PAGE
-- result HTML_PAGE to be sent back to the browser
session_manager: SESSION_MANAGER
-- object that responsable to retrieve/store session
feature -- Basic Operations
handle_exception
-- General exception hanlding.
-- (from CGI_ERROR_HANDLING)
local
msg: STRING_8
do
if raised_error /= Void then
msg := raised_error
else
msg := ""
end
response_header.send_trace (msg + exception_trace)
end
raise_error (msg: STRING_8)
-- Raise an error.
-- (from CGI_ERROR_HANDLING)
require -- from CGI_ERROR_HANDLING
message_exists: msg /= Void
do
raised_error := msg
handle_exception
ensure -- from CGI_ERROR_HANDLING
exists: raised_error /= Void
end
feature -- Cookies
cookies: HASH_TABLE [STRING_8, STRING_8]
-- Cookie Information relative to data.
-- (from CGI_ENVIRONMENT)
local
i, j: INTEGER_32
s: STRING_8
once
create Result.make (20)
s := get_env_variable ("HTTP_COOKIE")
s.append_character (';')
from
i := 1
until
i < 1
loop
i := s.index_of ('=', 1)
if i > 0 then
j := s.index_of (';', i)
if j > i then
Result.put (s.substring (i + 1, j - 1), s.substring (1, i - 1))
if j < s.count - 1 then
s.remove_head (j + 1)
else
i := 0
end
else
i := 0
end
end
end
end
feature -- Environment variable setting
set_environment_variable (variable, val: STRING_8)
-- Set environment variable `variable' to `val'.
-- (from CGI_ENVIRONMENT)
require -- from CGI_ENVIRONMENT
valid_variable: variable /= Void and then variable.count > 0
valid_value: val /= Void
do
variable.to_upper
put (val, variable)
end
feature {NONE} -- External
asynchronous_system_call (s: POINTER)
-- Pass to the operating system an asynchronous request to execute `s'.
-- (from EXECUTION_ENVIRONMENT)
external
"C blocking use %"eif_misc.h%""
alias
"eif_system_asynchronous"
end
eif_chdir (path: POINTER): INTEGER_32
-- Set the current directory to `path'
-- (from EXECUTION_ENVIRONMENT)
external
"C use %"eif_dir.h%""
end
eif_getenv (s: POINTER): POINTER
-- Value of environment variable `s'
-- (from EXECUTION_ENVIRONMENT)
external
"C use <stdlib.h>"
alias
"getenv"
end
eif_home_directory_name: STRING_8
-- Directory name corresponding to the home directory
-- (from EXECUTION_ENVIRONMENT)
external
"C use %"eif_path_name.h%""
end
eif_putenv (v: POINTER): INTEGER_32
-- Set `v' in environment.
-- (from EXECUTION_ENVIRONMENT)
external
"C use <stdlib.h>"
alias
"putenv"
end
eif_root_directory_name: STRING_8
-- Directory name corresponding to the root directory
-- (from EXECUTION_ENVIRONMENT)
external
"C use %"eif_path_name.h%""
end
system_call (s: POINTER): INTEGER_32
-- Pass to the operating system a request to execute `s'.
-- (from EXECUTION_ENVIRONMENT)
external
"C blocking use %"eif_misc.h%""
alias
"eif_system"
end
feature -- Headerline based environment variables
http_accept: STRING_8
-- MIME types which the client will accept.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("HTTP_ACCEPT")
end
http_user_agent: STRING_8
-- Browser the client is using to send the request.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("HTTP_USER_AGENT")
end
feature {NONE} -- Implementation constants
pair_separator: CHARACTER_8 is '&'
-- Name / value pairs separator.
-- (from CGI_INTERFACE)
value_separator: CHARACTER_8 is '='
-- Name / value separator.
-- (from CGI_INTERFACE)
feature -- Miscellanous
set_environment
-- Set environment variable to user value.
-- (from CGI_INTERFACE)
do
end
feature -- Not request-specific environment variables
gateway_interface: STRING_8
-- Revision of the CGI specification to which this server complies.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("GATEWAY_INTERFACE")
end
server_name: STRING_8
-- Server's hostname, DNS alias, or IP address.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("SERVER_NAME")
end
server_software: STRING_8
-- Name and version of information server answering the request.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("SERVER_SOFTWARE")
end
feature -- Output
io: STD_FILES
-- Handle to standard file setup
-- (from ANY)
once
create Result
Result.set_output_default
ensure -- from ANY
io_not_void: Result /= Void
end
out: STRING_8
-- New string containing terse printable representation
-- of current object
-- (from ANY)
do
Result := tagged_out
ensure -- from ANY
out_not_void: Result /= Void
end
print (some: ANY)
-- Write terse external representation of `some'
-- on standard output.
-- (from ANY)
do
if some /= Void then
io.put_string (some.out)
end
end
frozen tagged_out: STRING_8
-- New string containing terse printable representation
-- of current object
-- (from ANY)
external
"built_in"
ensure -- from ANY
tagged_out_not_void: Result /= Void
end
feature -- Platform
operating_environment: OPERATING_ENVIRONMENT
-- Objects available from the operating system
-- (from ANY)
once
create Result
ensure -- from ANY
operating_environment_not_void: Result /= Void
end
feature -- Report
field_defined (field_name: STRING_8): BOOLEAN
-- Is field `field_name' defined?
-- (from CGI_FORMS)
require -- from CGI_FORMS
filed_name_not_void: field_name /= Void
do
Result := fields.has (field_name)
end
feature -- Request specific environment variables
auth_type: STRING_8
-- Protocol-specific authentication method used to validate user.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("AUTH_TYPE")
end
content_length: STRING_8
-- Length of the said content as given by the client.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("CONTENT_LENGTH")
end
content_type: STRING_8
-- Content type of data.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("CONTENT_TYPE")
end
path_info: STRING_8
-- Extra path information, as given by the client.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("PATH_INFO")
end
path_translated: STRING_8
-- Translated version of PATH_INFO provided by server.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("PATH_TRANSLATED")
end
query_string: STRING_8
-- Information which follows ? in URL referencing CGI program.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("QUERY_STRING")
end
remote_addr: STRING_8
-- IP address of the remote host making the request.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("REMOTE_ADDR")
end
remote_host: STRING_8
-- Hostname making the request.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("REMOTE_HOST")
end
remote_ident: STRING_8
-- User name retrieved from server if RFC 931 supported.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("REMOTE_IDENT")
end
remote_user: STRING_8
-- Username, if applicable.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("REMOTE_USER")
end
request_method: STRING_8
-- Method with which the request was made.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("REQUEST_METHOD")
end
script_name: STRING_8
-- Virtual path to the script being executed.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("SCRIPT_NAME")
end
server_port: STRING_8
-- Port number to which request was sent.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("SERVER_PORT")
end
server_protocol: STRING_8
-- Name and revision of information protocol of this request.
-- (from CGI_ENVIRONMENT)
once
Result := get_env_variable ("SERVER_PROTOCOL")
end
feature {NONE} -- Retrieval
frozen internal_correct_mismatch
-- Called from runtime to perform a proper dynamic dispatch on `correct_mismatch'
-- from MISMATCH_CORRECTOR.
-- (from ANY)
local
l_corrector: MISMATCH_CORRECTOR
l_msg: STRING_8
l_exc: EXCEPTIONS
do
l_corrector ?= Current
if l_corrector /= Void then
l_corrector.correct_mismatch
else
create l_msg.make_from_string ("Mismatch: ")
create l_exc
l_msg.append (generating_type)
l_exc.raise_retrieval_exception (l_msg)
end
end
feature {NONE} -- Status
return_code: INTEGER_32
-- Status code set by last call to system or put
-- (from EXECUTION_ENVIRONMENT)
feature -- creation
make
-- Initiate input data parsing and process information.
local
retried: BOOLEAN
do
session_enabled := True
if not retried then
parse_input
execute
else
if debug_mode then
handle_exception
end
end
rescue
retried := True
retry
end
feature -- dispatching
execute
-- process actual request, send back result html page to the browser.
do
parse_handler_command_string
init_configuration
config.read_configuration (handler_id_string, command_string)
if handler_id_string.is_empty then
handler_id_string := config.default_request
end
if command_string.is_empty then
command_string := config.default_command
end
if session_enabled then
init_session_manager
init_session
end
pre_execute
if not processing_finished then
instantiate_handler
if actual_handler = Void then
process_undefined_request
processing_finished := True
else
return_page := actual_handler.process_request
end
if not processing_finished then
post_execute
end
end
if not response_header.is_complete_header then
response_header.generate_text_header
end
if session_enabled then
save_session
setup_sid_cookie
end
response_header.send_to_browser
response_header.output.put_string (return_page.out)
rescue
io.error.putstring ("crash in `request_dispatcher.execute()' %N")
end
feature {REQUEST_DISPATCHER} -- pre/post execution
post_execute
-- common tasks to be executed after request processed
do
end
pre_execute
-- common tasks to be executed before starting process user request
-- if necessary, set 'processing_finished' tag and return_page to premature processing
do
end
feature {REQUEST_DISPATCHER} -- session/cookie
init_session
-- retrieve the saved session or create a new session object
local
sid: STRING_8
do
create sid.make_empty
if cookies /= Void and then cookies.has ("sid") then
create sid.make_from_string (cookies.item ("sid"))
session := session_manager.get_session (sid)
if session /= Void and then not session.expired then
cookie_enabled := True
check
cookie_enabled_and_sid_ok: not sid.is_empty
end
else
create sid.make_empty
end
end
if sid.is_empty then
if field_defined ("sid") and not text_field_value ("sid").is_empty then
create sid.make_from_string (Current.text_field_value ("sid"))
else
check
cookie_disabled_and_sid_empty: sid.is_empty
end
create sid.make_from_string (session_manager.generate_session_id)
end
end
check
sid_not_empty: not sid.is_empty
end
session := session_manager.get_session (sid)
if session = Void or (session /= Void and then session.expired) then
create session.make
session.set_session_id (sid)
session.set_expiration_after_seconds (config.session_expiration)
end
ensure
app_session_object_initialized: session /= Void and not session.session_id.is_empty
end
init_session_manager
-- init session_manager object
do
create {SESSION_MANAGER_FILE_IMPL} session_manager.make (config.session_files_folder, config.session_expiration, config.session_id_length)
end
save_session
-- save actual session to session manager
do
session_manager.save_session (session.session_id, session)
end
setup_sid_cookie
-- update cookie in the client
require
session.session_id /= Void and then not session.session_id.is_empty
local
expire: STRING_8
do
expire := session.expiration_time.formatted_out ("ddd, [0]dd-[0]mm-yyyy [0]hh:[0]mi:[0]ss") + " GMT"
response_header.set_cookie ("sid", session.session_id.out, expire, config.application_path, Void, Void)
end
invariant
invariant_clause: True
-- from ANY
reflexive_equality: standard_is_equal (Current)
reflexive_conformance: conforms_to (Current)
end -- class REQUEST_DISPATCHER
-- Generated by ISE Eiffel --
For more details: www.eiffel.com