First integration of the new GW_ design more centralized on connector, and does not require specific feature on GW_APPLICATION depending on the connector.

So this is really more flexible this way, and much easier to write application supporting CGI, FCGI, Nino and so on .. as demonstrated in hello_world

This is a first version, more will come later, mainly migrating from Eiffel Web Reloaded to this Eiffel Web Framework project.
This commit is contained in:
Jocelyn Fiat
2011-07-12 11:53:00 +02:00
parent 4fb42df5fb
commit f74ac66569
101 changed files with 7651 additions and 107 deletions

Submodule ext/server/nino updated: c772fc5194...de77802546

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="error" uuid="C2DFF741-7091-43C7-B8B1-B075E7FF914F" library_target="error">
<target name="error">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>

16
library/error/error.ecf Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="error" uuid="C2DFF741-7091-43C7-B8B1-B075E7FF914F" library_target="error">
<target name="error">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1 @@
reference:forum2

80
library/error/src/error.e Normal file
View File

@@ -0,0 +1,80 @@
note
description : "Objects that represent an error"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class
ERROR
feature -- Access
code: INTEGER
deferred
ensure
result_not_zero: Result /= 0
end
name: STRING
deferred
ensure
result_attached: Result /= Void
end
message: detachable STRING_32
-- Potential error message
deferred
end
parent: detachable ERROR
-- Eventual error prior to Current
feature -- String representation
string_representation: STRING_32
-- String representation for Current
do
create Result.make_from_string (name.as_string_32)
Result.append_character (' ')
Result.append_character ('(')
Result.append_integer (code)
Result.append_character (')')
if attached message as m then
Result.append_character (':')
Result.append_character (' ')
Result.append_string (m)
end
end
feature -- Change
set_parent (a_parent: like parent)
-- Set `parent' to `a_parent'
do
parent := a_parent
end
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
require
a_visitor_not_void: a_visitor /= Void
deferred
end
invariant
name_attached: name /= Void
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,57 @@
note
description : "Objects that represent a custom error"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_CUSTOM
inherit
ERROR
create
make
feature {NONE} -- Initialization
make (a_code: INTEGER; a_name: STRING; a_message: detachable like message)
-- Initialize `Current'.
do
code := a_code
name := a_name
if attached a_message then
message := a_message
else
message := "Error: " + a_name + " (code=" + a_code.out + ")"
end
end
feature -- Access
code: INTEGER
name: STRING
message: STRING_32
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
do
a_visitor.process_custom (Current)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,75 @@
note
description : "Objects that represent a group of errors"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_GROUP
inherit
ERROR
create
make
feature {NONE} -- Initialization
make (a_errors: LIST [ERROR])
-- Initialize `Current'.
do
name := a_errors.count.out + " errors"
create {ARRAYED_LIST [ERROR]} sub_errors.make (a_errors.count)
sub_errors.fill (a_errors)
end
feature -- Access
code: INTEGER = -1
name: STRING
message: detachable STRING_32
do
create Result.make_from_string (name)
from
sub_errors.start
until
sub_errors.after
loop
if
attached sub_errors.item as e and then
attached e.message as m
then
Result.append_character ('%N')
Result.append_string (m)
end
sub_errors.forth
end
end
sub_errors: LIST [ERROR]
-- Error contained by Current
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
do
a_visitor.process_group (Current)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,92 @@
note
description : "Objects that handle error..."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_HANDLER
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
do
create {ARRAYED_LIST [ERROR]} errors.make (3)
end
feature -- Status
has_error: BOOLEAN
-- Has error?
do
Result := count > 0
end
count: INTEGER
do
Result := errors.count
end
errors: LIST [ERROR]
-- Errors container
feature -- Basic operation
add_error (a_error: ERROR)
-- Add `a_error' to the stack of error
do
errors.force (a_error)
end
add_error_details, add_custom_error (a_code: INTEGER; a_name: STRING; a_message: detachable STRING_32)
-- Add custom error to the stack of error
local
e: ERROR_CUSTOM
do
create e.make (a_code, a_name, a_message)
add_error (e)
end
feature -- Access
as_single_error: detachable ERROR
do
if count > 1 then
create {ERROR_GROUP} Result.make (errors)
elseif count > 0 then
Result := errors.first
end
end
feature -- Element changes
concatenate
-- Concatenate into a single error if any
do
if count > 1 and then attached as_single_error as e then
wipe_out
add_error (e)
end
end
reset, wipe_out
do
errors.wipe_out
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,49 @@
note
description : "Error list iterator"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_ITERATOR
inherit
ERROR_VISITOR
feature -- Access
process_error (e: ERROR)
do
end
process_custom (e: ERROR_CUSTOM)
do
process_error (e)
end
process_group (g: ERROR_GROUP)
do
if attached g.sub_errors as err then
from
err.start
until
err.after
loop
process_error (err.item)
err.forth
end
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,38 @@
note
description : "Null error visitor"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_NULL_VISITOR
inherit
ERROR_VISITOR
feature -- Access
process_error (e: ERROR)
do
end
process_custom (e: ERROR_CUSTOM)
do
end
process_group (g: ERROR_GROUP)
do
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,35 @@
note
description : "Objects to visit an ERROR"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class
ERROR_VISITOR
feature -- Access
process_error (e: ERROR)
deferred
end
process_custom (e: ERROR_CUSTOM)
deferred
end
process_group (g: ERROR_GROUP)
deferred
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,53 @@
note
description: "File error output visitor"
date: "$Date$"
revision: "$Revision$"
class
FILE_OUTPUT_ERROR_VISITOR
inherit
OUTPUT_ERROR_VISITOR
redefine
output_integer,
output_new_line
end
create
make
feature -- Initialization
make (f: like file)
require
f_open_write: f /= Void and then f.is_open_write
do
file := f
end
feature -- Access
file: FILE
feature -- Output
output_string (a_str: detachable STRING_GENERAL)
-- Output Unicode string
do
if a_str /= Void then
to_implement ("Convert into UTF-8 or console encoding before output")
file.put_string (a_str.as_string_8)
end
end
output_integer (i: INTEGER)
do
file.put_integer (i)
end
output_new_line
do
file.put_new_line
end
end

View File

@@ -0,0 +1,93 @@
note
description: "General error output visitor"
date: "$Date$"
revision: "$Revision$"
deferred class
OUTPUT_ERROR_VISITOR
inherit
ERROR_VISITOR
REFACTORING_HELPER
feature -- Output
output_string (a_str: detachable STRING_GENERAL)
-- Output Unicode string
deferred
end
output_any (obj: detachable ANY)
-- Output Unicode string
do
if attached {STRING_GENERAL} obj as l_str then
to_implement ("Convert into UTF-8 or console encoding before output")
output_string (l_str)
elseif obj /= Void then
output_string (obj.out)
end
end
output_integer (i: INTEGER)
do
output_string (i.out)
end
output_new_line
do
output_string ("%N")
end
feature -- Process
process_error (e: ERROR)
do
output_string ({STRING_32}"Error Name: ")
output_string (e.name)
output_string ({STRING_32}"Code: ")
output_integer (e.code)
output_new_line
output_string ({STRING_32}"%TMessage: ")
output_string (e.message)
output_new_line
end
process_custom (e: ERROR_CUSTOM)
do
output_string ({STRING_32}"Error Name: ")
output_string (e.name)
output_string ({STRING_32}"Code: ")
output_integer (e.code)
output_new_line
output_string ({STRING_32}"%TMessage: ")
output_string (e.message)
output_new_line
end
process_group (g: ERROR_GROUP)
local
l_errors: LIST [ERROR]
do
from
l_errors := g.sub_errors
l_errors.start
until
l_errors.after
loop
l_errors.item.process (Current)
l_errors.forth
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,53 @@
note
description: "Text error output visitor"
date: "$Date$"
revision: "$Revision$"
class
TEXT_OUTPUT_ERROR_VISITOR
inherit
OUTPUT_ERROR_VISITOR
redefine
output_integer,
output_new_line
end
create
make
feature -- Initialization
make (buf: like buffer)
require
buf_attached: buf /= Void
do
buffer := buf
end
feature -- Access
buffer: STRING
feature -- Output
output_string (a_str: detachable STRING_GENERAL)
-- Output Unicode string
do
if a_str /= Void then
to_implement ("Convert into UTF-8 or console encoding before output")
buffer.append_string_general (a_str)
end
end
output_integer (i: INTEGER)
do
buffer.append_integer (i)
end
output_new_line
do
buffer.append_character ('%N')
end
end

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http" uuid="F8BE3C55-88E8-4103-A936-B1E5CB1D330E" library_target="http">
<target name="http">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http" uuid="F8BE3C55-88E8-4103-A936-B1E5CB1D330E" library_target="http">
<target name="http">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,97 @@
note
description: "Summary description for {HTTP_CONSTANTS}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_CONSTANTS
feature -- Ports
default_http_port: INTEGER = 80
default_https_port: INTEGER = 443
feature -- Method
method_get: STRING = "GET"
method_post: STRING = "POST"
method_put: STRING = "PUT"
method_delete: STRING = "DELETE"
method_head: STRING = "HEAD"
method_download: STRING = "DOWNLOAD"
feature -- Content type
octet_stream: STRING = "application/octet-stream"
-- Octet stream content-type header
multipart_form: STRING = "multipart/form-data"
-- Starting chars of multipart form data content-type header
form_encoded: STRING = "application/x-www-form-urlencoded"
-- Starting chars of form url-encoded data content-type header
xml_text: STRING = "text/xml"
-- XML text content-type header
html_text: STRING = "text/html"
-- HTML text content-type header
json_text: STRING = "text/json"
-- JSON text content-type header
json_app: STRING = "application/json"
-- JSON application content-type header
js_text: STRING = "text/javascript"
-- Javascript text content-type header
js_app: STRING = "application/javascript"
-- JavaScript application content-type header
plain_text: STRING = "text/plain"
-- Plain text content-type header
feature -- Server
http_version_1_0: STRING = "HTTP/1.0"
http_host_header: STRING = "Host"
http_authorization_header: STRING = "Authorization: "
http_end_of_header_line: STRING = "%R%N"
http_end_of_command: STRING = "%R%N%R%N"
http_content_length: STRING = "Content-Length: "
http_content_type: STRING = "Content-Type: "
http_content_location: STRING = "Content-Location: "
http_content_disposition: STRING = "Content-Disposition: "
http_path_translated: STRING = "Path-Translated: "
http_agent: STRING = "User-agent: "
http_from: STRING = "From: "
feature -- Server: header
header_host: STRING = "Host"
header_authorization: STRING = "Authorization"
header_content_length: STRING = "Content-Length"
header_content_type: STRING = "Content-Type"
header_content_location: STRING = "Content-Location"
header_content_disposition: STRING = "Content-Disposition"
header_cache_control: STRING = "Cache-Control"
header_path_translated: STRING = "Path-Translated"
header_agent: STRING = "User-Agent"
header_referer: STRING = "Referer" -- Officially mispelled in std
header_location: STRING = "Location"
header_from: STRING = "From"
header_status: STRING = "Status"
header_multipart_tag_value_separator: CHARACTER = ';'
feature -- Misc
http_status_ok: STRING = "200 OK"
default_bufsize: INTEGER = 16384 --| 16K
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,71 @@
note
description: "Summary description for {HTTP_DATE_TIME_UTILITIES}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_DATE_TIME_UTILITIES
feature -- Access
now_utc: DATE_TIME
do
create Result.make_now_utc
end
epoch: DATE_TIME
once ("THREAD")
create Result.make_from_epoch (0)
end
feature -- Unix time stamp
unix_time_stamp (dt: detachable DATE_TIME): INTEGER_64
-- Unix time stamp from `dt' if attached or from epoch is detached
local
l_date_time: DATE_TIME
do
if dt /= Void then
l_date_time := dt
else
l_date_time := now_utc
end
Result := l_date_time.definite_duration (epoch).seconds_count
end
fine_unix_time_stamp (dt: detachable DATE_TIME): DOUBLE
-- Fine unix time stamp from `dt' if attached or from epoch is detached
local
l_date_time: DATE_TIME
do
if dt /= Void then
l_date_time := dt
else
l_date_time := now_utc
end
Result := l_date_time.definite_duration (epoch).fine_seconds_count
end
feature -- Unix time stamp conversion
unix_time_stamp_to_date_time (i64: INTEGER_64): DATE_TIME
-- Date time related to `i64'
do
create Result.make_from_epoch (i64.as_integer_32)
ensure
same_unix_time_stamp: unix_time_stamp (Result) = i64
end
;note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,106 @@
note
description: "[
Status code constants pertaining to the HTTP protocol
See http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_STATUS_CODE
feature -- 1xx : Informational
continue: INTEGER = 100
switching_protocols: INTEGER = 101
processing: INTEGER = 102 -- WebDAV RFC 2518
ie7_request_uri_too_long: INTEGER = 122 -- non standard, IE7 only
feature -- 2xx : Success
ok: INTEGER = 200
created: INTEGER = 201
accepted: INTEGER = 202
nonauthoritative_info: INTEGER = 203
no_content: INTEGER = 204
reset_content: INTEGER = 205
partial_content: INTEGER = 206
multistatus: INTEGER = 207 -- WebDAV RFC 4918
im_used: INTEGER = 226 -- RFC 4918
feature -- 3xx : Redirection
multiple_choices: INTEGER = 300
moved_permanently: INTEGER = 301
found: INTEGER = 302
see_other: INTEGER = 303
not_modified: INTEGER = 304
use_proxy: INTEGER = 305
switch_proxy: INTEGER = 306
temp_redirect: INTEGER = 307
feature -- 4xx : Client Error
bad_request: INTEGER = 400
unauthorized: INTEGER = 401
payment_required: INTEGER = 402
forbidden: INTEGER = 403
not_found: INTEGER = 404
method_not_allowed: INTEGER = 405
not_acceptable: INTEGER = 406
proxy_auth_required: INTEGER = 407
request_timeout: INTEGER = 408
conflict: INTEGER = 409
gone: INTEGER = 410
length_required: INTEGER = 411
precondition_failed: INTEGER = 412
request_entity_too_large: INTEGER = 413
request_uri_too_long: INTEGER = 414
unsupported_media_type: INTEGER = 415
request_range_not_satisfiable: INTEGER = 416
expectation_failed: INTEGER = 417
teapot: INTEGER = 418
feature -- 4xx : Client Error : WebDAV errors
too_many_connections: INTEGER = 421
unprocessable_entity: INTEGER = 422
locked: INTEGER = 423
failed_dependency: INTEGER = 424
unordered_collection: INTEGER = 425
upgrade_required: INTEGER = 426
no_response: INTEGER = 444
retry_with: INTEGER = 449
blocked_parental: INTEGER = 450
client_closed_request: INTEGER = 499
feature -- 5xx : Server Error
internal_server_error: INTEGER = 500
not_implemented: INTEGER = 501
bad_gateway: INTEGER = 502
service_unavailable: INTEGER = 503
gateway_timeout: INTEGER = 504
http_version_not_supported: INTEGER = 505
variant_also_negotiates: INTEGER = 506
insufficient_storage: INTEGER = 507 -- WebDAV RFC 4918
bandwidth_limit_exceeded: INTEGER = 509
not_extended: INTEGER = 510
user_access_denied: INTEGER = 530
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,160 @@
note
description: "[
Status code constants pertaining to the HTTP protocol
See http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_STATUS_CODE_MESSAGES
inherit
HTTP_STATUS_CODE
feature -- Status report
is_valid_http_status_code (v: INTEGER): BOOLEAN
-- Is the given value a valid http status code?
do
Result := v >= continue and v <= user_access_denied
end
feature -- Status messages
http_status_code_message (a_code: INTEGER): detachable STRING
-- Header message related to HTTP status code `a_code'
do
inspect a_code
when continue then
Result := "Continue"
when switching_protocols then
Result := "Switching Protocols"
when processing then
Result := "Processing"
when ok then
Result := "OK"
when created then
Result := "Created"
when accepted then
Result := "Accepted"
when nonauthoritative_info then
Result := "Non-Authoritative Information"
when no_content then
Result := "No Content"
when reset_content then
Result := "Reset Content"
when partial_content then
Result := "Partial Content"
when multistatus then
Result := "Multi-Status"
when multiple_choices then
Result := "Multiple Choices"
when moved_permanently then
Result := "Moved Permanently"
when found then
Result := "Found"
when see_other then
Result := "See Other"
when not_modified then
Result := "Not Modified"
when use_proxy then
Result := "Use Proxy"
when switch_proxy then
Result := "Switch Proxy"
when temp_redirect then
Result := "Temporary Redirect"
when bad_request then
Result := "Bad Request"
when unauthorized then
Result := "Unauthorized"
when payment_required then
Result := "Payment Required"
when forbidden then
Result := "Forbidden"
when not_found then
Result := "Not Found"
when method_not_allowed then
Result := "Method Not Allowed"
when not_acceptable then
Result := "Not Acceptable"
when proxy_auth_required then
Result := "Proxy Authentication Required"
when request_timeout then
Result := "Request Timeout"
when conflict then
Result := "Conflict"
when gone then
Result := "Gone"
when length_required then
Result := "Length Required"
when precondition_failed then
Result := "Precondition Failed"
when request_entity_too_large then
Result := "Request Entity Too Large"
when request_uri_too_long then
Result := "Request-URI Too Long"
when unsupported_media_type then
Result := "Unsupported Media Type"
when request_range_not_satisfiable then
Result := "Requested Range Not Satisfiable"
when expectation_failed then
Result := "Expectation Failed"
when teapot then
Result := "I'm a teapot"
when too_many_connections then
Result := "There are too many connections from your internet address"
when unprocessable_entity then
Result := "Unprocessable Entity"
when locked then
Result := "Locked"
when failed_dependency then
Result := "Failed Dependency"
when unordered_collection then
Result := "Unordered Collection"
when upgrade_required then
Result := "Upgrade Required"
when retry_with then
Result := "Retry With"
when blocked_parental then
Result := "Blocked by Windows Parental Controls"
when internal_server_error then
Result := "Internal Server Error"
when not_implemented then
Result := "Not Implemented"
when bad_gateway then
Result := "Bad Gateway"
when service_unavailable then
Result := "Service Unavailable"
when gateway_timeout then
Result := "Gateway Timeout"
when http_version_not_supported then
Result := "HTTP Version Not Supported"
when variant_also_negotiates then
Result := "Variant Also Negotiates"
when insufficient_storage then
Result := "Insufficient Storage"
when bandwidth_limit_exceeded then
Result := "Bandwidth Limit Exceeded"
when not_extended then
Result := "Not Extended"
when user_access_denied then
Result := "User access denied"
else
Result := Void
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_cgi" uuid="3BCBC1C5-9D99-45BB-B15D-B03D2C069CED" library_target="connector_cgi">
<target name="connector_cgi">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_cgi" uuid="3BCBC1C5-9D99-45BB-B15D-B03D2C069CED" library_target="connector_cgi">
<target name="connector_cgi">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="ewsgi" location="..\ewsgi.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1 @@
reference:forum2

View File

@@ -0,0 +1,36 @@
note
description: "Summary description for {GW_CGI_CONNECTOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
GW_CGI_CONNECTOR
inherit
GW_CONNECTOR
create
make
feature -- Execution
launch
local
env: GW_ENVIRONMENT_VARIABLES
do
create env.make_with_variables ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables)
application.process (env, create {GW_CGI_INPUT_STREAM}.make, create {GW_CGI_OUTPUT_STREAM}.make)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,39 @@
note
description: "Summary description for GW_CGI_INPUT_STREAM."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_CGI_INPUT_STREAM
inherit
GW_INPUT_STREAM
CONSOLE
rename
make as console_make
end
create
make
feature {NONE} -- Initialization
make
do
make_open_stdin ("stdin")
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,39 @@
note
description: "Summary description for GW_CGI_OUTPUT_STREAM."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_CGI_OUTPUT_STREAM
inherit
GW_OUTPUT_STREAM
CONSOLE
rename
make as console_make
end
create
make
feature {NONE} -- Initialization
make
do
make_open_stdout ("stdout")
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_libfcgi" uuid="59C57E56-3EE6-4EF7-873F-7ED084B0EB22" library_target="connector_libfcgi">
<target name="connector_libfcgi">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<library name="libfcgi" location="..\..\..\libfcgi\libfcgi-safe.ecf" />
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_libfcgi" uuid="59C57E56-3EE6-4EF7-873F-7ED084B0EB22" library_target="connector_libfcgi">
<target name="connector_libfcgi">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="ewsgi" location="..\..\ewsgi.ecf" readonly="false"/>
<library name="libfcgi" location="..\..\libfcgi\libfcgi.ecf" />
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1 @@
reference:forum2

View File

@@ -0,0 +1,81 @@
note
description: "Summary description for {GW_LIBFCGI_CONNECTOR}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_LIBFCGI_CONNECTOR
inherit
GW_CONNECTOR
redefine
initialize
end
create
make
feature {NONE} -- Initialization
initialize
do
create fcgi.make
create {GW_LIBFCGI_INPUT_STREAM} input.make (fcgi)
create {GW_LIBFCGI_OUTPUT_STREAM} output.make (fcgi)
end
feature -- Server
launch
local
res: INTEGER
do
from
res := fcgi.fcgi_listen
until
res < 0
loop
process_fcgi_request (fcgi.updated_environ_variables, input, output)
res := fcgi.fcgi_listen
end
end
feature -- Execution
process_fcgi_request (vars: HASH_TABLE [STRING, STRING]; a_input: like input; a_output: like output)
local
gw_env: GW_ENVIRONMENT_VARIABLES
do
create gw_env.make_with_variables (vars)
application.process (gw_env, a_input, a_output)
end
feature -- Input/Output
input: GW_INPUT_STREAM
-- Input from client (from httpd server via FCGI)
output: GW_OUTPUT_STREAM
-- Output to client (via httpd server/fcgi)
feature {NONE} -- Implementation
fcgi: FCGI
invariant
fcgi_attached: fcgi /= Void
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,66 @@
note
description: "Summary description for GW_LIBFCGI_INPUT_STREAM."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_LIBFCGI_INPUT_STREAM
inherit
GW_INPUT_STREAM
STRING_HANDLER
create
make
feature {NONE} -- Initialization
make (a_fcgi: like fcgi)
require
valid_fcgi: a_fcgi /= Void
do
fcgi := a_fcgi
initialize
end
initialize
-- Initialize Current
do
create last_string.make_empty
end
feature -- Basic operation
read_stream (nb_char: INTEGER)
-- Read a string of at most `nb_char' bound characters
-- or until end of file.
-- Make result available in `last_string'.
do
fcgi.fill_string_from_stdin (last_string, nb_char)
end
feature -- Access
last_string: STRING
-- Last string read
feature {NONE} -- Implementation
fcgi: FCGI;
-- Bridge to FCGI world
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,57 @@
note
description: "Summary description for {GW_LIBFCGI_OUTPUT_STREAM}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_LIBFCGI_OUTPUT_STREAM
inherit
GW_OUTPUT_STREAM
create
make
feature {NONE} -- Initialization
make (a_fcgi: like fcgi)
require
valid_fcgi: a_fcgi /= Void
do
fcgi := a_fcgi
end
feature -- Basic operation
put_string (s: STRING)
-- Send `s' to http client
do
fcgi.put_string (s)
end
flush
do
end
feature {NONE} -- Implementation
fcgi: FCGI
-- Bridge to FCGI world
invariant
fcgi_attached: fcgi /= Void
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1 @@
reference:forum2

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_nino" uuid="F91861FB-4FEA-455F-9570-828D7903DC64" library_target="connector_nino">
<target name="connector_nino">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<library name="nino" location="..\..\..\..\..\ext\server\nino\nino-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_nino" uuid="F91861FB-4FEA-455F-9570-828D7903DC64" library_target="connector_nino">
<target name="connector_nino">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="ewsgi" location="..\ewsgi.ecf" readonly="false"/>
<library name="nino" location="..\..\..\..\..\ext\server\nino\nino.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,93 @@
note
description: "Summary description for {GW_NINO_CONNECTOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
GW_NINO_CONNECTOR
inherit
GW_CONNECTOR
redefine
initialize
end
create
make,
make_with_base
feature {NONE} -- Initialization
make_with_base (a_app: like application; a_base: like base)
do
make (a_app)
base := a_base
end
feature {NONE} -- Initialization
initialize
local
cfg: HTTP_SERVER_CONFIGURATION
do
create cfg.make
create server.make (cfg)
end
feature -- Access
server: HTTP_SERVER
configuration: HTTP_SERVER_CONFIGURATION
do
Result := server.configuration
end
feature -- Access
base: detachable STRING
-- Root url base
feature -- Element change
set_base (b: like base)
do
base := b
end
feature -- Server
launch
local
l_http_handler : HTTP_HANDLER
do
create {GW_NINO_HANDLER} l_http_handler.make_with_callback (server, "GW_NINO_HANDLER", Current)
debug ("nino")
if attached base as l_base then
print ("Base=" + l_base + "%N")
end
end
server.setup (l_http_handler)
end
process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
local
gw_env: GW_ENVIRONMENT_VARIABLES
do
create gw_env.make_with_variables (env)
gw_env.set_variable ("RAW_HEADER_DATA", a_headers_text)
application.process (gw_env, create {GW_NINO_INPUT_STREAM}.make (a_input), create {GW_NINO_OUTPUT_STREAM}.make (a_output))
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,156 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
GW_NINO_HANDLER
inherit
HTTP_CONNECTION_HANDLER
create
make_with_callback
feature {NONE} -- Initialization
make_with_callback (a_main_server: like main_server; a_name: STRING; a_callback: like callback)
-- Initialize `Current'.
do
make (a_main_server, a_name)
callback := a_callback
end
callback: GW_NINO_CONNECTOR
feature -- Access
base: detachable STRING
-- Root url base
feature -- Element change
set_base (a_uri: like base)
-- Set `base' to `a_uri'
do
base := a_uri
end
feature -- Request processing
process_request (a_handler: HTTP_CONNECTION_HANDLER; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
-- Process request ...
local
env, vars: HASH_TABLE [STRING, STRING]
p: INTEGER
l_request_uri, l_script_name, l_query_string, l_path_info: STRING
l_server_name, l_server_port: detachable STRING
a_headers_map: HASH_TABLE [STRING, STRING]
vn: STRING
e: EXECUTION_ENVIRONMENT
do
l_request_uri := a_handler.uri
a_headers_map := a_handler.request_header_map
create e
vars := e.starting_environment_variables
env := vars.twin
--| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `env'
from
a_headers_map.start
until
a_headers_map.after
loop
vn := a_headers_map.key_for_iteration.as_upper
vn.replace_substring_all ("-", "_")
add_environment_variable (a_headers_map.item_for_iteration, vn, env)
a_headers_map.forth
end
--| Specific cases
p := l_request_uri.index_of ('?', 1)
if p > 0 then
l_script_name := l_request_uri.substring (1, p - 1)
l_query_string := l_request_uri.substring (p + 1, l_request_uri.count)
else
l_script_name := l_request_uri.string
l_query_string := ""
end
if attached a_headers_map.item ("Host") as l_host then
add_environment_variable (l_host, "HTTP_HOST", env)
p := l_host.index_of (':', 1)
if p > 0 then
l_server_name := l_host.substring (1, p - 1)
l_server_port := l_host.substring (p+1, l_host.count)
else
l_server_name := l_host
l_server_port := "80" -- Default
end
end
if attached a_headers_map.item ("Authorization") as l_authorization then
add_environment_variable (l_authorization, "HTTP_AUTHORIZATION", env)
p := l_authorization.index_of (' ', 1)
if p > 0 then
add_environment_variable (l_authorization.substring (1, p - 1), "AUTH_TYPE", env)
end
end
add_environment_variable ("CGI/1.1", "GATEWAY_INTERFACE", env)
add_environment_variable (l_query_string, "QUERY_STRING", env)
if attached a_handler.remote_info as l_remote_info then
add_environment_variable (l_remote_info.addr, "REMOTE_ADDR", env)
add_environment_variable (l_remote_info.hostname, "REMOTE_HOST", env)
add_environment_variable (l_remote_info.port.out, "REMOTE_PORT", env)
-- add_environment_variable (Void, "REMOTE_IDENT", env)
-- add_environment_variable (Void, "REMOTE_USER", env)
end
add_environment_variable (l_request_uri, "REQUEST_URI", env)
add_environment_variable (a_handler.method, "REQUEST_METHOD", env)
add_environment_variable (l_script_name, "SCRIPT_NAME", env)
add_environment_variable (l_server_name, "SERVER_NAME", env)
add_environment_variable (l_server_port, "SERVER_PORT", env)
add_environment_variable (a_handler.version, "SERVER_PROTOCOL", env)
add_environment_variable ({HTTP_SERVER_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", env)
--| Apply `base' value
if attached base as l_base and then l_request_uri /= Void then
if l_request_uri.starts_with (l_base) then
l_path_info := l_request_uri.substring (l_base.count + 1, l_request_uri.count)
p := l_path_info.index_of ('?', 1)
if p > 0 then
l_path_info.keep_head (p - 1)
end
env.force (l_path_info, "PATH_INFO")
env.force (l_base, "SCRIPT_NAME")
end
end
callback.process_request (env, a_handler.request_header, a_input, a_output)
end
add_environment_variable (a_value: detachable STRING; a_var_name: STRING; env: HASH_TABLE [STRING, STRING])
-- Add variable `a_var_name => a_value' to `env'
do
if a_value /= Void then
env.force (a_value, a_var_name)
end
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,61 @@
note
description: "Summary description for {GW_NINO_INPUT_STREAM}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_NINO_INPUT_STREAM
inherit
GW_INPUT_STREAM
create
make
feature {NONE} -- Initialization
make (a_nino_input: like nino_input)
do
create last_string.make_empty
set_nino_input (a_nino_input)
end
feature {GW_NINO_APPLICATION} -- Nino
set_nino_input (i: like nino_input)
do
nino_input := i
end
nino_input: HTTP_INPUT_STREAM
feature -- Basic operation
read_stream (nb_char: INTEGER)
-- Read a string of at most `nb_char' bound characters
-- or until end of file.
-- Make result available in `last_string'.
do
nino_input.read_stream (nb_char)
last_string := nino_input.last_string
end
feature -- Access
last_string: STRING
-- Last string read
;note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,60 @@
note
description: "Summary description for {GW_NINO_OUTPUT_STREAM}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_NINO_OUTPUT_STREAM
inherit
GW_OUTPUT_STREAM
create
make
feature {NONE} -- Initialization
make (a_nino_output: like nino_output)
do
set_nino_output (a_nino_output)
end
feature {GW_NINO_APPLICATION} -- Nino
set_nino_output (o: like nino_output)
do
nino_output := o
end
nino_output: HTTP_OUTPUT_STREAM
feature -- Basic operation
put_string (s: STRING_8)
-- Send `s' to http client
do
debug ("nino")
print (s)
end
nino_output.put_string (s)
end
flush
-- Flush the output stream
do
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -11,10 +11,8 @@
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="interface" location="src\" recursive="true">
<file_rule>
<exclude>GW_REQUEST_CONTEXT_IMP</exclude>
</file_rule>
</cluster>
<library name="error" location="..\..\error\error-safe.ecf"/>
<library name="http" location="..\..\protocol\http\http-safe.ecf"/>
<cluster name="interface" location="src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="ewsgi" uuid="D924DBE1-1231-434A-80EF-234BA09D1E30" library_target="ewsgi">
<target name="ewsgi">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="false" void_safety="none" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="error" location="..\..\error\error-safe.ecf"/>
<library name="http" location="..\..\protocol\http\http.ecf"/>
<cluster name="interface" location="src\" recursive="true" />
</target>
</system>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="hello_world" uuid="734385F1-0D17-4B5F-9138-24DC8D4F06C6">
<target name="hello_world">
<root class="HELLO_WORLD" feature="make"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<library name="connector_cgi" location="..\..\connectors\cgi\cgi-safe.ecf" readonly="false"/>
<library name="connector_nino" location="..\..\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="connector_libfcgi" location="..\..\connectors\libfcgi\libfcgi-safe.ecf" readonly="false"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,58 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
HELLO_WORLD
inherit
GW_APPLICATION_IMP
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
local
conn: detachable GW_CONNECTOR
nino_conn: GW_NINO_CONNECTOR
do
if is_nino then
create nino_conn.make_with_base (Current, "/hello_world")
if attached nino_conn.server.server_configuration as cfg then
cfg.http_server_port := 8080
cfg.force_single_threaded := True
end
conn := nino_conn
elseif is_cgi then
create {GW_CGI_CONNECTOR} conn.make (Current)
elseif is_libfcgi then
create {GW_LIBFCGI_CONNECTOR} conn.make (Current)
else
io.error.put_string ("Unsupported connector")
end
if conn /= Void then
conn.launch
end
end
is_nino: BOOLEAN = True
is_cgi: BOOLEAN = False
is_libfcgi: BOOLEAN = False
feature -- Execution
execute (ctx: GW_REQUEST_CONTEXT)
-- Execute the request
do
ctx.output.put_string ("Hello World!%N")
if attached ctx.execution_variable ("REQUEST_COUNT") as rq_count then
ctx.output.put_string ("Request #" + rq_count + "%N")
end
end
end

View File

@@ -258,7 +258,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996
deferred
end
path_info: STRING
path_info: STRING assign update_path_info
-- The PATH_INFO metavariable specifies a path to be interpreted
-- by the CGI script. It identifies the resource or sub-resource
-- to be returned by the CGI script, and it is derived from the
@@ -581,6 +581,31 @@ feature -- Extra
deferred
end
feature {GW_REQUEST_CONTEXT} -- Element change
set_orig_path_info (s: STRING)
-- Set ORIG_PATH_INFO to `s'
require
s_attached: s /= Void
deferred
ensure
same_orig_path_info: orig_path_info ~ variable ({GW_ENVIRONMENT_NAMES}.orig_path_info)
end
unset_orig_path_info
-- Unset ORIG_PATH_INFO
deferred
ensure
unset: not has_variable ({GW_ENVIRONMENT_NAMES}.orig_path_info)
end
update_path_info (a_path_info: like path_info)
-- Updated PATH_INFO
deferred
ensure
same_path_info: path_info ~ variable ({GW_ENVIRONMENT_NAMES}.path_info)
end
invariant
server_name_not_empty: not server_name.is_empty
server_port_set: server_port /= 0
@@ -589,6 +614,8 @@ invariant
query_string_attached: query_string /= Void
remote_addr_attached: remote_addr /= Void
path_info_identical: path_info ~ variable ({GW_ENVIRONMENT_NAMES}.path_info)
;note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -0,0 +1,292 @@
note
description: "Summary description for {GW_ENVIRONMENT_VARIABLES}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_ENVIRONMENT_VARIABLES
inherit
GW_ENVIRONMENT
redefine
update_path_info
end
create
make_with_variables
feature {NONE} -- Initialization
make_with_variables (a_vars: HASH_TABLE [STRING, STRING])
-- Fill with variable from `a_vars'
local
s: detachable STRING
do
create empty_string.make_empty
create table.make (a_vars.count)
from
a_vars.start
until
a_vars.after
loop
table.force (a_vars.item_for_iteration, a_vars.key_for_iteration)
a_vars.forth
end
--| QUERY_STRING
query_string := variable_or_default ({GW_ENVIRONMENT_NAMES}.query_string, empty_string, False)
--| REQUEST_METHOD
request_method := variable_or_default ({GW_ENVIRONMENT_NAMES}.request_method, empty_string, False)
--| CONTENT_TYPE
s := variable ({GW_ENVIRONMENT_NAMES}.content_type)
if s /= Void and then not s.is_empty then
content_type := s
else
content_type := Void
end
--| CONTENT_LENGTH
s := variable ({GW_ENVIRONMENT_NAMES}.content_length)
content_length := s
if s /= Void and then s.is_integer then
content_length_value := s.to_integer
else
--| content_length := 0
end
--| PATH_INFO
path_info := variable_or_default ({GW_ENVIRONMENT_NAMES}.path_info, empty_string, False)
--| SERVER_NAME
server_name := variable_or_default ({GW_ENVIRONMENT_NAMES}.server_name, empty_string, False)
--| SERVER_PORT
s := variable ({GW_ENVIRONMENT_NAMES}.server_port)
if s /= Void and then s.is_integer then
server_port := s.to_integer
else
server_port := 80
end
--| SCRIPT_NAME
script_name := variable_or_default ({GW_ENVIRONMENT_NAMES}.script_name, empty_string, False)
--| REMOTE_ADDR
remote_addr := variable_or_default ({GW_ENVIRONMENT_NAMES}.remote_addr, empty_string, False)
--| REMOTE_HOST
remote_host := variable_or_default ({GW_ENVIRONMENT_NAMES}.remote_host, empty_string, False)
--| REQUEST_URI
request_uri := variable_or_default ({GW_ENVIRONMENT_NAMES}.request_uri, empty_string, False)
end
feature -- Access
table: HASH_TABLE [STRING, STRING]
feature -- Access
variable (a_name: STRING): detachable STRING
do
Result := table.item (a_name)
end
has_variable (a_name: STRING): BOOLEAN
do
Result := table.has_key (a_name)
end
feature {GW_REQUEST_CONTEXT, GW_APPLICATION, GW_CONNECTOR} -- Element change
set_variable (a_name: STRING; a_value: STRING)
do
table.force (a_value, a_name)
end
unset_variable (a_name: STRING)
do
table.remove (a_name)
end
feature -- Common Gateway Interface - 1.1 8 January 1996
auth_type: detachable STRING
content_length: detachable STRING
content_length_value: INTEGER
content_type: detachable STRING
gateway_interface: STRING
do
Result := variable_or_default ({GW_ENVIRONMENT_NAMES}.gateway_interface, "", False)
end
path_info: STRING
-- <Precursor/>
--
--| For instance, if the current script was accessed via the URL
--| http://www.example.com/eiffel/path_info.exe/some/stuff?foo=bar, then $_SERVER['PATH_INFO'] would contain /some/stuff.
--|
--| Note that is the PATH_INFO variable does not exists, the `path_info' value will be empty
path_translated: detachable STRING
do
Result := variable ({GW_ENVIRONMENT_NAMES}.path_translated)
end
query_string: STRING
remote_addr: STRING
remote_host: STRING
remote_ident: detachable STRING
do
Result := variable ({GW_ENVIRONMENT_NAMES}.remote_ident)
end
remote_user: detachable STRING
do
Result := variable ({GW_ENVIRONMENT_NAMES}.remote_user)
end
request_method: STRING
script_name: STRING
server_name: STRING
server_port: INTEGER
server_protocol: STRING
do
Result := variable_or_default ({GW_ENVIRONMENT_NAMES}.server_protocol, "HTTP/1.0", True)
end
server_software: STRING
do
Result := variable_or_default ({GW_ENVIRONMENT_NAMES}.server_software, "Unknown Server", True)
end
feature -- HTTP_*
http_accept: detachable STRING
-- Contents of the Accept: header from the current request, if there is one.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_accept)
end
http_accept_charset: detachable STRING
-- Contents of the Accept-Charset: header from the current request, if there is one.
-- Example: 'iso-8859-1,*,utf-8'.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_accept_charset)
end
http_accept_encoding: detachable STRING
-- Contents of the Accept-Encoding: header from the current request, if there is one.
-- Example: 'gzip'.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_accept_encoding)
end
http_accept_language: detachable STRING
-- Contents of the Accept-Language: header from the current request, if there is one.
-- Example: 'en'.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_accept_language)
end
http_connection: detachable STRING
-- Contents of the Connection: header from the current request, if there is one.
-- Example: 'Keep-Alive'.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_connection)
end
http_host: detachable STRING
-- Contents of the Host: header from the current request, if there is one.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_host)
end
http_referer: detachable STRING
-- The address of the page (if any) which referred the user agent to the current page.
-- This is set by the user agent.
-- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature.
-- In short, it cannot really be trusted.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_referer)
end
http_user_agent: detachable STRING
-- Contents of the User-Agent: header from the current request, if there is one.
-- This is a string denoting the user agent being which is accessing the page.
-- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586).
-- Among other things, you can use this value to tailor your page's
-- output to the capabilities of the user agent.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_user_agent)
end
http_authorization: detachable STRING
-- Contents of the Authorization: header from the current request, if there is one.
do
Result := table.item ({GW_ENVIRONMENT_NAMES}.http_authorization)
end
feature -- Extra
request_uri: STRING
-- The URI which was given in order to access this page; for instance, '/index.html'.
orig_path_info: detachable STRING
-- Original version of `path_info' before processed by Current environment
feature {GW_REQUEST_CONTEXT} -- Update
set_orig_path_info (s: STRING)
do
orig_path_info := s
set_variable ({GW_ENVIRONMENT_NAMES}.orig_path_info, s)
end
unset_orig_path_info
do
orig_path_info := Void
unset_variable ({GW_ENVIRONMENT_NAMES}.orig_path_info)
end
update_path_info (a_path_info: like path_info)
do
path_info := a_path_info
set_variable ({GW_ENVIRONMENT_NAMES}.path_info, a_path_info)
end
feature {NONE} -- Implementation
empty_string: STRING
-- Reusable empty string
invariant
empty_string_unchanged: empty_string.is_empty
;note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -31,29 +31,16 @@ feature -- Status report
Result := has (a_name)
end
feature -- Element change
feature {GW_REQUEST_CONTEXT, GW_APPLICATION, GW_CONNECTOR} -- Element change
replace_variable (v: STRING; k: STRING)
-- Replace variable `k'
set_variable (a_name: STRING; a_value: STRING_32)
do
force (v, k)
force (a_value, a_name)
end
add_variable (v: STRING; k: STRING)
-- Add variable `k' with value `v'
require
k_attached: k /= Void
v_attached: k /= Void
unset_variable (a_name: STRING)
do
force (v, k)
end
delete_variable (k: STRING)
-- Remove variable `k'
require
k_attached: k /= Void
do
remove (k)
remove (a_name)
end
note

View File

@@ -17,13 +17,13 @@ deferred class
feature -- Access: Input/Output
output: GW_OUTPUT_STREAM
-- Server output channel
input: GW_INPUT_STREAM
-- Server input channel
deferred
end
input: GW_INPUT_STREAM
-- Server input channel
output: GW_OUTPUT_STREAM
-- Server output channel
deferred
end
@@ -31,8 +31,8 @@ feature -- Access: global variable
variables: HASH_TABLE [STRING_32, STRING_32]
-- Table containing all the various variables
-- Warning: this is computed each time, if you change this content of other container
-- this won't update this Result's content.
-- Warning: this is computed each time, if you change the content of other containers
-- this won't update this Result's content, unless you query it again
local
vars: HASH_TABLE [STRING_GENERAL, STRING_GENERAL]
do
@@ -100,11 +100,11 @@ feature -- Access: global variable
if s = Void then
s := environment_variable (n8)
if s = Void then
s := parameters.variable (n8)
s := parameter (n8)
if s = Void then
s := form_fields.variable (n8)
s := form_field (n8)
if s = Void then
s := cookies_variables.item (n8)
s := cookies_variable (n8)
end
end
end
@@ -114,6 +114,13 @@ feature -- Access: global variable
end
end
feature -- Access: environment extra values
request_time: detachable DATE_TIME
-- Request time (UTC)
deferred
end
feature -- Access: environment variables
environment: GW_ENVIRONMENT
@@ -144,13 +151,27 @@ feature -- Access: execution variables
Result := execution_variables.variable (a_name)
end
feature -- Queries
feature -- URL Parameters
parameter (n: STRING): detachable STRING_32
-- Parameter for name `n'.
do
Result := parameters.variable (n)
end
parameters: GW_REQUEST_VARIABLES
-- Variables extracted from QUERY_STRING
deferred
end
feature -- Form fields and related
form_field (n: STRING): detachable STRING_32
-- Field for name `n'.
do
Result := form_fields.variable (n)
end
form_fields: GW_REQUEST_VARIABLES
-- Variables sent by POST request
deferred
@@ -164,6 +185,16 @@ feature -- Queries
--| tmp_base_name: basename of `tmp_name'
--| error: if /= 0 , there was an error : TODO ...
--| size: size of the file given by the http request
deferred
end
feature -- Cookies
cookies_variable (n: STRING): detachable STRING
-- Field for name `n'.
do
Result := cookies_variables.item (n)
end
cookies_variables: HASH_TABLE [STRING, STRING]
-- Expanded cookies variable

View File

@@ -16,8 +16,8 @@ inherit
ITERABLE [STRING_32]
create
make--,
-- make_from_urlencoded
make,
make_from_urlencoded
feature -- Initialization
@@ -27,11 +27,11 @@ feature -- Initialization
table.compare_objects
end
-- make_from_urlencoded (a_content: STRING; decoding: BOOLEAN)
-- do
-- make (a_content.occurrences ('&') + 1)
-- import_urlencoded (a_content, decoding)
-- end
make_from_urlencoded (a_content: STRING; decoding: BOOLEAN)
do
make (a_content.occurrences ('&') + 1)
import_urlencoded (a_content, decoding)
end
feature -- Status report
@@ -51,15 +51,28 @@ feature -- Status report
Result := table.has (a_name)
end
feature {GW_REQUEST_CONTEXT, GW_APPLICATION, GW_CONNECTOR} -- Element change
set_variable (a_name: STRING; a_value: STRING_32)
do
table.force (a_value, a_name)
end
unset_variable (a_name: STRING)
do
table.remove (a_name)
end
feature -- Import urlencoded
-- import_urlencoded (a_content: STRING; decoding: BOOLEAN)
-- -- Import `a_content'
-- local
import_urlencoded (a_content: STRING; decoding: BOOLEAN)
-- Import `a_content'
local
-- n, p, i, j: INTEGER
-- s: STRING
-- l_name,l_value: STRING_32
-- do
do
-- FIXME
-- n := a_content.count
-- if n > 0 then
-- from
@@ -89,7 +102,7 @@ feature -- Import urlencoded
-- end
-- end
-- end
-- end
end
feature -- Access: table

View File

@@ -46,6 +46,24 @@ feature -- Access
end
end
feature {GW_REQUEST_CONTEXT, GW_APPLICATION, GW_CONNECTOR} -- Element change
set_variable (a_name: STRING; a_value: G)
require
a_name_not_empty: a_name /= Void and then not a_name.is_empty
deferred
ensure
variable_set: has_variable (a_name) and then variable (a_name) ~ a_value
end
unset_variable (a_name: STRING)
require
a_name_not_empty: a_name /= Void and then not a_name.is_empty
deferred
ensure
variable_unset: not has_variable (a_name)
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -11,6 +11,7 @@ deferred class
feature -- Execution
process (env: GW_ENVIRONMENT; a_input: GW_INPUT_STREAM; a_output: GW_OUTPUT_STREAM)
-- Process request with environment `env', and i/o streams `a_input' and `a_output'
do
execute (new_request_context (env, a_input, a_output))
end

View File

@@ -0,0 +1,44 @@
note
description: "Summary description for {GW_CONNECTOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
GW_CONNECTOR
feature {NONE} -- Initialization
make (a_app: like application)
do
application := a_app
initialize
end
initialize
-- Initialize connector
do
end
feature {NONE} -- Access
application: GW_APPLICATION
-- Gateway Application
feature -- Server
launch
deferred
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,66 @@
note
description: "Summary description for {GW_ERROR}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_ERROR
inherit
ERROR
HTTP_STATUS_CODE_MESSAGES
create
make
feature {NONE} -- Initialization
make (a_code: INTEGER)
do
code := a_code
name := "HTTP Error"
if attached http_status_code_message (a_code) as m then
name := m
end
end
feature -- Access
code: INTEGER
name: STRING
message: detachable STRING_32
feature -- Element change
set_message (m: like message)
-- Set `message' to `m'
require
m_attached: m /= Void
do
message := m
end
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
do
a_visitor.process_error (Current)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,50 @@
note
description: "Summary description for {GW_APPLICATION_IMP} "
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class
GW_APPLICATION_IMP
inherit
GW_APPLICATION
redefine
process
end
feature -- Access
request_count: INTEGER
-- Request count
feature -- Execution
process (env: GW_ENVIRONMENT; a_input: GW_INPUT_STREAM; a_output: GW_OUTPUT_STREAM)
-- Process request with environment `env', and i/o streams `a_input' and `a_output'
do
request_count := request_count + 1
Precursor (env, a_input, a_output)
end
feature -- Factory
new_request_context (env: GW_ENVIRONMENT; a_input: GW_INPUT_STREAM; a_output: GW_OUTPUT_STREAM): GW_REQUEST_CONTEXT
do
create {GW_REQUEST_CONTEXT_IMP} Result.make (env, a_input, a_output)
Result.execution_variables.set_variable (request_count.out, "REQUEST_COUNT")
end
;note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,818 @@
note
description: "[
Server request context of the httpd request
You can create your own descendant of this class to
add/remove specific value or processing
This object is created by {GW_APPLICATION}.new_request_context
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
GW_REQUEST_CONTEXT_IMP
inherit
GW_REQUEST_CONTEXT
create
make
feature {NONE} -- Initialization
make (env: GW_ENVIRONMENT; a_input: like input; a_output: like output)
require
env_attached: env /= Void
do
create error_handler.make
input := a_input
output := a_output
environment := env
content_length := env.content_length_value
create execution_variables.make (10)
create uploaded_files.make (0)
raw_post_data_recorded := True
initialize
analyze
end
initialize
-- Specific initialization
local
p: INTEGER
dt: DATE_TIME
env: like environment
do
env := environment
--| Here one can set its own environment entries if needed
--| do not use `force', to avoid overwriting existing variable
if attached env.request_uri as rq_uri then
p := rq_uri.index_of ('?', 1)
if p > 0 then
env.set_variable (rq_uri.substring (1, p-1), {GW_ENVIRONMENT_NAMES}.self)
else
env.set_variable (rq_uri, {GW_ENVIRONMENT_NAMES}.self)
end
end
if env.variable ({GW_ENVIRONMENT_NAMES}.request_time) = Void then
env.set_variable (date_time_utilities.unix_time_stamp (Void).out, {GW_ENVIRONMENT_NAMES}.request_time)
end
end
analyze
-- Analyze context, set various attributes and validate values
do
extract_variables
end
feature -- Access: Input/Output
output: GW_OUTPUT_STREAM
-- Server output channel
input: GW_INPUT_STREAM
-- Server input channel
feature -- Status
raw_post_data_recorded: BOOLEAN assign set_raw_post_data_recorded
-- Record RAW POST DATA in environment variables
-- otherwise just forget about it
-- Default: true
--| warning: you might keep in memory big amount of memory ...
feature -- Error handling
has_error: BOOLEAN
do
Result := error_handler.has_error
end
error_handler: ERROR_HANDLER
-- Error handler
-- By default initialized to new handler
feature -- Access: environment variables
environment: GW_ENVIRONMENT
-- Environment variables
content_length: INTEGER
-- Extracted Content-Length value
feature -- Access: execution variables
execution_variables: GW_EXECUTION_VARIABLES
-- Execution variables set by the application
feature -- URL parameters
parameters: GW_REQUEST_VARIABLES
local
vars: like internal_parameters
p,e: INTEGER
rq_uri: like environment.request_uri
s: detachable STRING
do
vars := internal_parameters
if vars = Void then
s := environment.query_string
if s = Void then
rq_uri := environment.request_uri
p := rq_uri.index_of ('?', 1)
if p > 0 then
e := rq_uri.index_of ('#', p + 1)
if e = 0 then
e := rq_uri.count
else
e := e - 1
end
s := rq_uri.substring (p+1, e)
end
end
if s /= Void and then not s.is_empty then
create vars.make_from_urlencoded (s, True)
else
create vars.make (0)
end
internal_parameters := vars
end
Result := vars
end
feature -- Form fields and related
form_fields: GW_REQUEST_VARIABLES
local
vars: like internal_form_fields
s: STRING
n: INTEGER
l_type: detachable STRING
do
vars := internal_form_fields
if vars = Void then
n := content_length
if n > 0 then
l_type := environment.content_type
if
l_type /= Void and then
l_type.starts_with ({HTTP_CONSTANTS}.multipart_form)
then
create vars.make (5)
--| FIXME: optimization ... fetch the input data progressively, otherwise we might run out of memory ...
s := form_input_data (n)
analyze_multipart_form (l_type, s, vars)
else
s := form_input_data (n)
create vars.make_from_urlencoded (s, True)
end
if raw_post_data_recorded then
vars.add_variable (s, "RAW_POST_DATA")
end
else
create vars.make (0)
end
internal_form_fields := vars
end
Result := vars
end
uploaded_files: HASH_TABLE [TUPLE [name: STRING; type: STRING; tmp_name: STRING; tmp_basename: STRING; error: INTEGER; size: INTEGER], STRING]
-- Table of uploaded files information
--| name: original path from the user
--| type: content type
--| tmp_name: path to temp file that resides on server
--| tmp_base_name: basename of `tmp_name'
--| error: if /= 0 , there was an error : TODO ...
--| size: size of the file given by the http request
feature -- Cookies
cookies_variables: HASH_TABLE [STRING, STRING]
-- Expanded cookies variable
local
l_cookies: like cookies
do
l_cookies := cookies
create Result.make (l_cookies.count)
from
l_cookies.start
until
l_cookies.after
loop
if attached l_cookies.item_for_iteration.variables as vars then
from
vars.start
until
vars.after
loop
Result.force (vars.item_for_iteration, vars.key_for_iteration)
vars.forth
end
else
check same_name: l_cookies.key_for_iteration.same_string (l_cookies.item_for_iteration.name) end
Result.force (l_cookies.item_for_iteration.value, l_cookies.key_for_iteration)
end
l_cookies.forth
end
end
cookies: HASH_TABLE [GW_COOKIE, STRING]
-- Cookies Information
local
i,j,p,n: INTEGER
l_cookies: like internal_cookies
k,v: STRING
do
l_cookies := internal_cookies
if l_cookies = Void then
if attached environment_variable ({GW_ENVIRONMENT_NAMES}.http_cookie) as s then
create l_cookies.make (5)
from
n := s.count
p := 1
i := 1
until
p < 1
loop
i := s.index_of ('=', p)
if i > 0 then
j := s.index_of (';', i)
if j = 0 then
j := n + 1
k := s.substring (p, i - 1)
v := s.substring (i + 1, n)
p := 0 -- force termination
else
k := s.substring (p, i - 1)
v := s.substring (i + 1, j - 1)
p := j + 1
end
l_cookies.put (create {GW_COOKIE}.make (k,v), k)
end
end
else
create l_cookies.make (0)
end
internal_cookies := l_cookies
end
Result := l_cookies
end
feature -- Query
-- script_absolute_url (a_path: STRING): STRING
-- -- Absolute Url for the script if any, extended by `a_path'
-- do
-- Result := script_url (a_path)
-- if attached http_host as h then
-- Result.prepend (h)
-- else
-- --| Issue ??
-- end
-- end
-- script_url (a_path: STRING): STRING
-- -- Url relative to script name if any, extended by `a_path'
-- require
-- a_path_attached: a_path /= Void
-- local
-- l_base_url: like script_url_base
-- i,m,n: INTEGER
-- l_rq_uri: like request_uri
-- do
-- l_base_url := script_url_base
-- if l_base_url = Void then
-- if attached environment.script_name as l_script_name then
-- l_rq_uri := request_uri
-- if l_rq_uri.starts_with (l_script_name) then
-- l_base_url := l_script_name
-- else
-- --| Handle Rewrite url engine, to have clean path
-- from
-- i := 1
-- m := l_rq_uri.count
-- n := l_script_name.count
-- until
-- i > m or i > n or l_rq_uri[i] /= l_script_name[i]
-- loop
-- i := i + 1
-- end
-- if i > 1 then
-- if l_rq_uri[i-1] = '/' then
-- i := i -1
-- end
-- l_base_url := l_rq_uri.substring (1, i - 1)
-- end
-- end
-- end
-- if l_base_url = Void then
-- create l_base_url.make_empty
-- end
-- script_url_base := l_base_url
-- end
-- Result := l_base_url + a_path
-- end
-- script_url_base: detachable STRING
-- -- URL base of potential script
feature -- Access environment information
request_time: detachable DATE_TIME
-- Request time (UTC)
do
if
attached environment.variable ({GW_ENVIRONMENT_NAMES}.request_time) as t and then
t.is_integer_64
then
Result := date_time_utilities.unix_time_stamp_to_date_time (t.to_integer_64)
end
end
feature -- Element change
set_raw_post_data_recorded (b: BOOLEAN)
-- Set `raw_post_data_recorded' to `b'
do
raw_post_data_recorded := b
end
set_error_handler (ehdl: like error_handler)
-- Set `error_handler' to `ehdl'
do
error_handler := ehdl
end
update_path_info (env: GW_ENVIRONMENT)
-- Fix and update PATH_INFO value if needed
local
l_path_info: STRING
do
l_path_info := env.path_info
--| Warning
--| on IIS: we might have PATH_INFO = /sample.exe/foo/bar
--| on apache: PATH_INFO = /foo/bar
--| So, we might need to check with SCRIPT_NAME and remove it on IIS
--| store original PATH_INFO in ORIG_PATH_INFO
if l_path_info.is_empty then
env.unset_orig_path_info
else
env.set_orig_path_info (l_path_info)
if attached env.script_name as l_script_name then
if l_path_info.starts_with (l_script_name) then
env.path_info := l_path_info.substring (l_script_name.count + 1 , l_path_info.count)
end
end
end
end
feature -- Uploaded File Handling
move_uploaded_file (a_filename: STRING; a_destination: STRING): BOOLEAN
-- Move uploaded file `a_filename' to `a_destination'
--| if this is not an uploaded file, do not move it.
local
f: RAW_FILE
do
if is_uploaded_file (a_filename) then
create f.make (a_filename)
if f.exists then
f.change_name (a_destination)
Result := True
end
end
end
is_uploaded_file (a_filename: STRING): BOOLEAN
-- Is `a_filename' a file uploaded via HTTP Form
local
l_files: like uploaded_files
do
l_files := uploaded_files
if not l_files.is_empty then
from
l_files.start
until
l_files.after or Result
loop
if l_files.item_for_iteration.tmp_name.same_string (a_filename) then
Result := True
end
l_files.forth
end
end
end
feature {NONE} -- Temporary File handling
delete_uploaded_file (a_filename: STRING)
-- Delete file `a_filename'
local
f: RAW_FILE
do
if is_uploaded_file (a_filename) then
create f.make (a_filename)
if f.exists and then f.is_writable then
f.delete
else
error_handler.add_custom_error (0, "Can not delete file", "Can not delete file %""+ a_filename +"%"")
end
else
error_handler.add_custom_error (0, "Not uploaded file", "This file %""+ a_filename +"%" is not an uploaded file.")
end
end
save_uploaded_file (a_content: STRING; a_filename: STRING): detachable TUPLE [name: STRING; basename: STRING]
-- Save uploaded file content to `a_filename'
local
bn: STRING
l_safe_name: STRING
f: RAW_FILE
dn: STRING
fn: FILE_NAME
d: DIRECTORY
n: INTEGER
rescued: BOOLEAN
do
if not rescued then
dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory
create d.make (dn)
if d.exists and then d.is_writable then
l_safe_name := safe_filename (a_filename)
from
create fn.make_from_string (dn)
bn := "tmp-" + l_safe_name
fn.set_file_name (bn)
create f.make (fn.string)
n := 0
until
not f.exists
or else n > 1_000
loop
n := n + 1
fn.make_from_string (dn)
bn := "tmp-" + n.out + "-" + l_safe_name
fn.set_file_name (bn)
f.make (fn.string)
end
if not f.exists or else f.is_writable then
f.open_write
f.put_string (a_content)
f.close
Result := [f.name, bn]
else
Result := Void
end
else
error_handler.add_custom_error (0, "Directory not writable", "Can not create file in directory %""+ dn +"%"")
end
else
Result := Void
end
rescue
rescued := True
retry
end
safe_filename (fn: STRING): STRING
local
c: CHARACTER
i, n, p: INTEGER
l_accentued, l_non_accentued: STRING
do
l_accentued := "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
l_non_accentued := "AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy"
--| Compute safe filename, to avoid creating impossible filename, or dangerous one
from
i := 1
n := fn.count
create Result.make (n)
until
i > n
loop
c := fn[i]
inspect c
when '.', '-', '_' then
Result.extend (c)
when 'A' .. 'Z', 'a' .. 'z', '0' .. '9' then
Result.extend (c)
else
p := l_accentued.index_of (c, 1)
if p > 0 then
Result.extend (l_non_accentued[p])
else
Result.extend ('-')
end
end
i := i + 1
end
end
feature {NONE} -- Implementation: Form analyzer
analyze_multipart_form (t: STRING; s: STRING; vars: like form_fields)
-- Analyze multipart form content
--| FIXME[2011-06-21]: integrate eMIME parser library
require
t_attached: t /= Void
s_attached: s /= Void
vars_attached: vars /= Void
local
p,i,next_b: INTEGER
l_boundary_prefix: STRING
l_boundary: STRING
l_boundary_len: INTEGER
m: STRING
is_crlf: BOOLEAN
do
p := t.substring_index ("boundary=", 1)
if p > 0 then
l_boundary := t.substring (p + 9, t.count)
p := s.substring_index (l_boundary, 1)
if p > 1 then
l_boundary_prefix := s.substring (1, p - 1)
l_boundary := l_boundary_prefix + l_boundary
else
create l_boundary_prefix.make_empty
end
l_boundary_len := l_boundary.count
--| Let's support either %R%N and %N ...
--| Since both cases might occurs (for instance, our implementation of CGI does not have %R%N)
--| then let's be as flexible as possible on this.
is_crlf := s[l_boundary_len + 1] = '%R'
from
i := 1 + l_boundary_len + 1
if is_crlf then
i := i + 1 --| +1 = CR = %R
end
next_b := i
until
i = 0
loop
next_b := s.substring_index (l_boundary, i)
if next_b > 0 then
if is_crlf then
m := s.substring (i, next_b - 1 - 2) --| 2 = CR LF = %R %N
else
m := s.substring (i, next_b - 1 - 1) --| 1 = LF = %N
end
analyze_multipart_form_input (m, vars)
i := next_b + l_boundary_len + 1
if is_crlf then
i := i + 1 --| +1 = CR = %R
end
else
if is_crlf then
i := i + 1
end
m := s.substring (i - 1, s.count)
m.right_adjust
if not l_boundary_prefix.same_string (m) then
error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input")
end
i := next_b
end
end
end
end
analyze_multipart_form_input (s: STRING; vars_post: like form_fields)
-- Analyze multipart entry
require
s_not_empty: s /= Void and then not s.is_empty
local
n, i,p, b,e: INTEGER
l_name, l_filename, l_content_type: detachable STRING
l_header: detachable STRING
l_content: detachable STRING
l_line: detachable STRING
do
from
p := 1
n := s.count
until
p > n or l_header /= Void
loop
inspect s[p]
when '%R' then -- CR
if
n >= p + 3 and then
s[p+1] = '%N' and then -- LF
s[p+2] = '%R' and then -- CR
s[p+3] = '%N' -- LF
then
l_header := s.substring (1, p + 1)
l_content := s.substring (p + 4, n)
end
when '%N' then
if
n >= p + 1 and then
s[p+1] = '%N'
then
l_header := s.substring (1, p)
l_content := s.substring (p + 2, n)
end
else
end
p := p + 1
end
if l_header /= Void and l_content /= Void then
from
i := 1
n := l_header.count
until
i = 0 or i > n
loop
l_line := Void
b := i
p := l_header.index_of ('%N', b)
if p > 0 then
if l_header[p - 1] = '%R' then
p := p - 1
i := p + 2
else
i := p + 1
end
end
if p > 0 then
l_line := l_header.substring (b, p - 1)
if l_line.starts_with ("Content-Disposition: form-data") then
p := l_line.substring_index ("name=", 1)
if p > 0 then
p := p + 4 --| 4 = ("name=").count - 1
if l_line.valid_index (p+1) and then l_line[p+1] = '%"' then
p := p + 1
e := l_line.index_of ('"', p + 1)
else
e := l_line.index_of (';', p + 1)
if e = 0 then
e := l_line.count
end
end
l_name := l_header.substring (p + 1, e - 1)
end
p := l_line.substring_index ("filename=", 1)
if p > 0 then
p := p + 8 --| 8 = ("filename=").count - 1
if l_line.valid_index (p+1) and then l_line[p+1] = '%"' then
p := p + 1
e := l_line.index_of ('"', p + 1)
else
e := l_line.index_of (';', p + 1)
if e = 0 then
e := l_line.count
end
end
l_filename := l_header.substring (p + 1, e - 1)
end
elseif l_line.starts_with ("Content-Type: ") then
l_content_type := l_line.substring (15, l_line.count)
end
else
i := 0
end
end
if l_name /= Void then
if l_filename /= Void then
if l_content_type = Void then
l_content_type := default_content_type
end
if attached save_uploaded_file (l_content, l_filename) as l_saved_fn_info then
uploaded_files.force ([l_filename, l_content_type, l_saved_fn_info.name, l_saved_fn_info.basename, 0, l_content.count], l_name)
else
uploaded_files.force ([l_filename, l_content_type, "", "", -1, l_content.count], l_name)
end
else
vars_post.add_variable (l_content, l_name)
end
else
error_handler.add_custom_error (0, "unamed multipart entry", Void)
end
else
error_handler.add_custom_error (0, "missformed multipart entry", Void)
end
end
feature {NONE} -- Internal value
default_content_type: STRING = "text/plain"
-- Default content type
form_input_data (nb: INTEGER): STRING
-- data from input form
local
n: INTEGER
t: STRING
do
from
n := nb
create Result.make (n)
if n > 1_024 then
n := 1_024
end
until
n <= 0
loop
read_input (n)
t := last_input_string
Result.append_string (t)
if t.count < n then
n := 0
end
n := nb - t.count
end
end
internal_parameters: detachable like parameters
-- cached value for `parameters'
internal_form_fields: detachable like form_fields
-- cached value for `form_fields'
internal_cookies: detachable like cookies
-- cached value for `cookies'
feature {NONE} -- I/O: implementation
read_input (nb: INTEGER)
-- Read `nb' bytes from `input'
do
input.read_stream (nb)
end
last_input_string: STRING
-- Last string read from `input'
do
Result := input.last_string
end
feature {NONE} -- Implementation
report_bad_request_error (a_message: detachable STRING)
-- Report error
local
e: GW_ERROR
do
create e.make ({HTTP_STATUS_CODE}.bad_request)
if a_message /= Void then
e.set_message (a_message)
end
error_handler.add_error (e)
end
extract_variables
-- Extract relevant environment variables
local
s: detachable STRING
do
s := environment.request_uri
if s.is_empty then
report_bad_request_error ("Missing URI")
end
if not has_error then
s := environment.request_method
if s.is_empty then
report_bad_request_error ("Missing request method")
end
end
if not has_error then
s := environment.http_host
if s = Void or else s.is_empty then
report_bad_request_error ("Missing host header")
end
end
if not has_error then
update_path_info (environment)
end
end
feature {NONE} -- Implementation: utilities
date_time_utilities: HTTP_DATE_TIME_UTILITIES
-- Utilities classes related to date and time.
once
create Result
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,7 @@
To compile your own binaries .lib and .dll on Windows
please get the source from
https://github.com/EiffelSoftware/libfcgi
git repository:
git clone https://github.com/EiffelSoftware/libfcgi.git

View File

@@ -0,0 +1,50 @@
= How to configure FCGI =
== Apache2/Windows ==
* in apache2/conf/httpd.conf add
LoadModule fcgid_module modules/mod_fcgid.so
* and for instance, you can put the following code to test the tests/eiffelweb example
<IfModule mod_fcgid.c>
FcgidIdleTimeout 60
FcgidBusyScanInterval 120
FcgidProcessLifeTime 1600
#7200
FcgidMaxProcesses 5
FcgidMaxProcessesPerClass 100
FcgidMinProcessesPerClass 100
FcgidConnectTimeout 8
FcgidIOTimeout 3000
FcgidBusyTimeout 3200
FcgidPassHeader Authorization
alias /eiffelweb/ "c:/_dev/EiffelWebReloaded/library/fcgi/tests/EIFGENs/eiffelweb/W_code/"
<Location /eiffelweb/>
AddHandler fcgid-script .exe
Options Indexes FollowSymLinks ExecCGI
Order allow,deny
Allow from all
</Location>
</IfModule>
== IIS/Windows ==
* When you install IIS on Windows 7, you just need to enable to CGI module which also include the FastCGI module
* otherwise, have a look at http://www.iis.net/download/FastCGI and also http://learn.iis.net/page.aspx/375/set-up-fastcgi-for-php/
* Then open the IIS Manager
Modules: to check you really have FastCGIModule
Handler Mappings and then "Add Module Mapping"
Request path: *.exe
Module: FastCgiModule
Executable (optional): c:\_dev\EiffelWebReloaded\library\fcgi\tests\EIFGENs\eiffelweb\W_code\eiffelweb.exe
Name: Eiffel Web Solution using FastCGI on IIS
= Notes =
* The notes in this readme are very basic, mainly to test your executable.
* You will need to configure more precisely your httpd server to fulfill your needs
== for execution ==
* On Windows, be sure to have the libfcgi.dll in your path (or in same folder as executable)

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-6-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-6-0 http://www.eiffel.com/developers/xml/configuration-1-6-0.xsd" name="fcgi" uuid="3F4BCF74-3503-4533-9D74-5A65EC4CA3C4" library_target="fcgi">
<target name="fcgi">
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" >
</option>
<external_include location="$ECF_CONFIG_PATH/spec/include/libfcgi">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_include>
<external_include location="$ECF_CONFIG_PATH\spec\include\libfcgi">
<condition>
<platform value="windows"/>
</condition>
</external_include>
<external_library location="$ECF_CONFIG_PATH\spec\lib\$ISE_PLATFORM\$ISE_C_COMPILER\libfcgi.lib">
<condition>
<platform value="windows"/>
</condition>
</external_library>
<external_library location="/usr/local/lib/libfcgi.so">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_library>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="interface" location="interface" recursive="true"/>
<cluster name="implementation" location="implementation" recursive="true">
<file_rule>
<exclude>/linux$</exclude>
<exclude>/fake$</exclude>
<condition>
<platform value="windows"/>
</condition>
</file_rule>
<file_rule>
<exclude>/windows$</exclude>
<exclude>/fake$</exclude>
<condition>
<platform excluded_value="windows"/>
</condition>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,104 @@
note
description: "Implementation for the FCGI_I interface"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class FCGI_IMP
inherit
FCGI_I
feature -- Access
environ: POINTER
-- Get the (char**) environ variable from the DLL.
external
"C inline use %"fcgi_stdio.h%""
alias
"return (char**) environ;"
end
feature -- FCGI connection
fcgi_listen: INTEGER
-- Listen to the FCGI input stream
-- Return 0 for successful calls, -1 otherwise.
do
-- Set state on first call to prevent looping indefinitely
if fcgi_has_run then
Result := -1
else --if not is_interactive then
fcgi_has_run := True
end
end
fcgi_has_run: BOOLEAN
-- For emulation only; Has fcgi_listen been called?
fcgi_finish
-- Finish current request from HTTP server started from
-- the most recent call to `fcgi_accept'.
do
end
set_fcgi_exit_status (v: INTEGER)
do
end
feature -- FCGI output
put_string (a_str: STRING)
-- Put `a_str' on the FastCGI stdout.
do
io.put_string (a_str)
end
-- fcgi_printf (fmt: STRING; args: FINITE[ANY])
-- -- Put args, formatted per 'fmt' on the FastCGI stdout.
-- do
-- apf.printf (fmt, args)
-- end
feature -- FCGI Input
read_from_stdin (n: INTEGER)
-- Read up to n bytes from stdin and store in input buffer
do
end
copy_from_stdin (n: INTEGER; tf: FILE)
-- Read up to n bytes from stdin and write to given file
do
end
feature -- Status
buffer_contents: STRING
do
if attached private_input_buffer as buf then
Result := buf
else
Result := ""
end
end
buffer_capacity: INTEGER
do
if attached private_input_buffer as bug then
Result := buf.capacity
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,97 @@
note
description: "Wrappers around FastCGI C API."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
FCGI_C_API
feature -- Connection
accept: INTEGER
-- Accept a Fast CGI connection.
-- Return 0 for successful calls, -1 otherwise.
external
"C inline use %"fcgi_stdio.h%""
alias
"return FCGI_Accept();"
end
environ: POINTER
-- Get the (char**) environ variable from the DLL.
external
"C inline use %"fcgi_stdio.h%""
alias
"return (char**) environ;"
end
finish
-- Finished current request from HTTP server started from
-- the most recent call to `fcgi_accept'.
external
"C inline use %"fcgi_stdio.h%""
alias
"FCGI_Finish();"
end
set_exit_status (v: INTEGER)
-- Set the exit status for the most recent request
external
"C inline use %"fcgi_stdio.h%""
alias
"FCGI_SetExitStatus($v);"
end
feature -- Input
read_content_into (a_buffer: POINTER; a_length: INTEGER): INTEGER
-- Read content stream into `a_buffer' but no more than `a_length' character.
external
"C inline use %"fcgi_stdio.h%""
alias
"[
{
size_t n;
if (! FCGI_feof(FCGI_stdin)) {
n = FCGI_fread($a_buffer, 1, $a_length, FCGI_stdin);
} else {
n = 0;
}
return n;
}
]"
end
gets (s: POINTER): POINTER
-- gets() reads a line from stdin into the buffer pointed to
-- by s until either a terminating newline or EOF, which it
-- replaces with '\0'
-- No check for buffer overrun is performed
external
"C inline use %"fcgi_stdio.h%""
alias
"return FCGI_gets($s);"
end
feature -- Output
put_string (v: POINTER; n: INTEGER)
external
"C inline use %"fcgi_stdio.h%""
alias
"FCGI_fwrite($v, 1, $n, FCGI_stdout);"
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,183 @@
note
description: "Implementation for the FCGI_I interface"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class FCGI_IMP
inherit
FCGI_I
STRING_HANDLER
feature {NONE} -- Initialization
make
-- Initialize FCGI interface
do
create fcgi
end
fcgi: FCGI_C_API
-- FastCGI C API primitives
feature -- Access
fcgi_environ: POINTER
do
Result := fcgi.environ
end
feature -- FCGI Connection
fcgi_listen: INTEGER
-- Listen to the FCGI input stream
-- Return 0 for successful calls, -1 otherwise.
do
Result := {FCGI_C_API}.accept
end
update_eif_environ
external
"C inline use <string.h>"
alias
"[
eif_environ = (char**) environ;
]"
end
fcgi_finish
-- Finish current request from HTTP server started from
-- the most recent call to `fcgi_accept'.
do
{FCGI_C_API}.finish
end
set_fcgi_exit_status (v: INTEGER)
do
{FCGI_C_API}.set_exit_status (-2)
end
feature -- FCGI output
put_string (a_str: STRING)
-- Put `a_str' on the FastCGI stdout.
local
l_c_str: C_STRING
do
l_c_str := c_buffer
l_c_str.set_string (a_str)
{FCGI_C_API}.put_string (l_c_str.item, l_c_str.count)
end
-- fcgi_printf (fmt: STRING; args: FINITE[ANY])
-- -- Put args, formatted per 'fmt' on the FastCGI stdout.
-- local
-- l_c_str: C_STRING
-- do
-- create l_c_str.make (apf.aprintf (fmt, args))
-- {FCGI_C_API}.put_string (l_c_str.item, l_c_str.count)
-- end
feature -- FCGI Input
copy_from_stdin (n: INTEGER; tf: FILE)
-- Read up to n bytes from stdin and write to given file
local
l_c_str: C_STRING
num, readsize, writecount: INTEGER
done: BOOLEAN
do
--put_trace ("copy_from_stdin, n=" +n.out)
readsize := n.min (K_input_bufsize)
--put_trace ("copy_from_stdin, readsize=" +readsize.out)
l_c_str := c_buffer
from
until done or writecount >= n
loop
num := {FCGI_C_API}.read_content_into (l_c_str.item, readsize)
--put_trace ("copy_from_stdin, num=" +num.out)
if num = 0 then
-- EOF
done := True
else
tf.put_managed_pointer (c_buffer.managed_data, 0, num)
writecount := writecount + num
end
end
end
feature {NONE} -- Implementation: FCGI Input
fill_pointer_from_stdin (p: POINTER; n: INTEGER): INTEGER
-- Read up to `n' bytes from stdin and store in pointer `p'
-- and return number of bytes read.
do
Result := {FCGI_C_API}.read_content_into (p, n)
end
feature -- I/O Routines
--RFO read_stdin_into (a_str: STRING)
--RFO -- Read a string from the `stdin' into `a_str'.
--RFO require
--RFO a_str_not_void: a_str /= Void
--RFO local
--RFO l_c_str: C_STRING
--RFO n: INTEGER
--RFO do
--RFO l_c_str := c_buffer
--RFO n := {FCGI_C_API}.read_content_into (l_c_str.item, l_c_str.capacity)
--RFO a_str.set_count (n)
--RFO l_c_str.read_substring_into (a_str, 1, n)
--RFO end
--RFO read_string_into (a_str: STRING)
--RFO require
--RFO exists: a_str /= Void
--RFO local
--RFO l_c_str: C_STRING
--RFO p: POINTER
--RFO do
--RFO create l_c_str.make_empty (1024)
--RFO p := {FCGI_C_API}.gets (l_c_str.item)
--RFO-- if p /= default_pointer and p = l_c_str.item then
--RFO a_str.resize (l_c_str.count)
--RFO l_c_str.read_string_into (a_str)
--RFO-- else
--RFO-- put_error_line ("Bad pointer from gets")
--RFO-- end
--RFO end
--RFO read_line
--RFO -- Read up to the next end of line, or end of input
--RFO -- Leave result in last_string
--RFO -- Newline character is absent from result
--RFO do
--RFO if last_string = Void then
--RFO create Result.make (K_input_bufsize)
--RFO else
--RFO last_string.wipe_out
--RFO end
--RFO-- if input_filename /= Void then
--RFO-- io.read_line
--RFO-- last_string.append (io.last_string)
--RFO-- else
--RFO read_string_into (last_string)
--RFO-- end
--RFO end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,136 @@
note
description: "Wrappers around FastCGI C API."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
FCGI_C_API
feature -- Connections
accept: INTEGER
-- Accept a Fast CGI connection.
-- Return 0 for successful calls, -1 otherwise.
external
"dll libfcgi.dll signature (): EIF_INTEGER use fcgi_stdio.h "
alias
"FCGI_Accept"
end
environ: POINTER
-- Get the (char**) environ variable from the DLL.
external
"dll libfcgi.dll signature (): EIF_POINTER use fcgi_stdio.h "
alias
"FCGI_Environ"
end
finish
-- Finished current request from HTTP server started from
-- the most recent call to `accept'.
external
"dll libfcgi.dll signature () use fcgi_stdio.h "
alias
"FCGI_Finish"
end
set_exit_status (v: INTEGER)
-- Set the exit status for the most recent request
external
"dll libfcgi.dll signature (EIF_INTEGER) use fcgi_stdio.h "
alias
"FCGI_SetExitStatus"
end
feature -- Input
fread (v: POINTER; a_size: INTEGER; n: INTEGER; fp: POINTER): INTEGER
-- FCGI_fread() read from input `fp' and put into `v'
external
"dll libfcgi.dll signature (EIF_POINTER, EIF_INTEGER, EIF_INTEGER, EIF_POINTER): EIF_INTEGER use fcgi_stdio.h "
alias
"FCGI_fread"
end
feof (v: POINTER): INTEGER
-- FCGI_feof()
external
"dll libfcgi.dll signature (EIF_POINTER): EIF_INTEGER use fcgi_stdio.h "
alias
"FCGI_feof"
end
read_content_into (a_buffer: POINTER; a_length: INTEGER): INTEGER
-- Read content stream into `a_buffer' but no more than `a_length' character.
local
i: INTEGER
l_stdin: POINTER
do
l_stdin := stdin
i := feof (l_stdin)
if i /= 0 then
Result := 0
else
Result := fread(a_buffer, 1, a_length, l_stdin)
end
end
gets (s: POINTER): POINTER
-- gets() reads a line from stdin into the buffer pointed to
-- by `s' until either a terminating newline or EOF, which it
-- replaces with '\0'
-- No check for buffer overrun is performed
external
"dll libfcgi.dll signature (EIF_POINTER): EIF_POINTER use fcgi_stdio.h "
alias
"FCGI_gets"
end
feature -- Output
put_string (v: POINTER; n: INTEGER)
local
i: INTEGER
do
i := fwrite (v, 1, n, stdout)
end
fwrite (v: POINTER; a_size: INTEGER; n: INTEGER; fp: POINTER): INTEGER
-- FCGI_fwrite() ouput `v' to `fp'
external
"dll libfcgi.dll signature (EIF_POINTER, EIF_INTEGER, EIF_INTEGER, EIF_POINTER): EIF_INTEGER use fcgi_stdio.h "
alias
"FCGI_fwrite"
end
feature -- Access
stdout: POINTER
-- FCGI_stdout() return pointer on output FCGI_FILE
external
"C inline use %"fcgi_stdio.h%""
alias
"FCGI_stdout"
end
stdin: POINTER
-- FCGI_stdin() return pointer on input FCGI_FILE
external
"C inline use %"fcgi_stdio.h%""
alias
"FCGI_stdin"
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,267 @@
note
description: "Implementation for the FCGI_I interface"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class FCGI_IMP
inherit
FCGI_I
feature {NONE} -- Initialization
make
-- Initialize FCGI interface
do
create fcgi
end
fcgi: FCGI_C_API
-- FastCGI C API primitives
feature -- Access
fcgi_environ: POINTER
do
Result := fcgi.environ
end
-- updated_environ_variables: HASH_TABLE [STRING, STRING]
-- local
---- n, l_size,
-- i: INTEGER
-- p, v, null: POINTER
-- do
---- update_eif_environ
---- Result := starting_environment_variables
--
---- p := environ_strings_pointer ($n)
---- from
---- i := 1
---- l_size := 0
---- create Result.make (n)
---- until
---- i > n
---- loop
---- create s.make_from_c (p.plus (l_size))
---- l_size := l_size + s.count + 1
---- if attached separated_variables (s) as t then
---- Result.force (t.value, t.key)
---- end
---- i := i + 1
---- end
--
-- p := fcgi.environ
-- create Result.make (50)
-- if p /= null then
-- from
-- i := 0
-- v := fcgi_i_th_environ (i,p)
-- until
-- v = null
-- loop
-- if attached separated_variables (create {STRING}.make_from_c (v)) as t then
-- Result.force (t.value, t.key)
-- end
-- i := i + 1
-- v := fcgi_i_th_environ (i,p)
-- end
-- end
-- end
--
-- fcgi_i_th_environ (i: INTEGER; p: POINTER): POINTER
-- -- Environment variable at `i'-th position of `p'.
-- require
-- i_valid: i >=0
-- external
-- "C inline use <string.h>"
-- alias
-- "[
-- return ((char **)$p)[$i];
-- ]"
-- end
feature -- FCGI connection
fcgi_listen: INTEGER
-- Listen to the FCGI input stream
-- Return 0 for successful calls, -1 otherwise.
do
Result := fcgi.accept
end
-- update_eif_environ
-- external
-- "C inline use <string.h>"
-- alias
-- "[
-- #ifdef EIF_WINDOWS
-- #ifndef GetEnvironmentStringsA
-- extern LPVOID WINAPI GetEnvironmentStringsA(void);
-- #endif
--
-- eif_environ = (char**) GetEnvironmentStringsA();
-- #endif
-- ]"
-- end
fcgi_finish
-- Finish current request from HTTP server started from
-- the most recent call to `fcgi_accept'.
do
fcgi.finish
end
set_fcgi_exit_status (v: INTEGER)
do
fcgi.set_exit_status (-2)
end
feature -- FCGI output
put_string (a_str: STRING)
-- Put `a_str' on the FastCGI stdout.
local
l_c_str: C_STRING
do
l_c_str := c_buffer
l_c_str.set_string (a_str)
fcgi.put_string (l_c_str.item, l_c_str.count)
end
feature -- FCGI input
copy_from_stdin (n: INTEGER; f: FILE)
-- Read up to n bytes from stdin and write to given file
local
l_c_str: C_STRING
num, readsize, writecount: INTEGER
done: BOOLEAN
l_fcgi: like fcgi
do
--put_trace ("copy_from_stdin, n=" +n.out)
readsize := n.min (K_input_bufsize)
--put_trace ("copy_from_stdin, readsize=" +readsize.out)
l_c_str := c_buffer
from
l_fcgi := fcgi
until done or writecount >= n
loop
num := l_fcgi.read_content_into (l_c_str.item, readsize)
--put_trace ("copy_from_stdin, num=" +num.out)
if num = 0 then
-- EOF
done := True
else
f.put_managed_pointer (c_buffer.managed_data, 0, num)
writecount := writecount + num
end
end
end
feature {NONE} -- Implementation: FCGI Input
fill_pointer_from_stdin (p: POINTER; n: INTEGER): INTEGER
-- Read up to `n' bytes from stdin and store in pointer `p'
-- and return number of bytes read.
do
Result := fcgi.read_content_into (p, n)
end
feature -- I/O Routines
--RFO read_stdin_into (a_str: STRING)
--RFO -- Read a string from the `stdin' into `a_str'.
--RFO require
--RFO a_str_not_void: a_str /= Void
--RFO local
--RFO l_c_str: C_STRING
--RFO n: INTEGER
--RFO do
--RFO l_c_str := c_buffer
--RFO n := fcgi.read_content_into (l_c_str.item, l_c_str.capacity)
--RFO a_str.set_count (n)
--RFO l_c_str.read_substring_into (a_str, 1, n)
--RFO end
--RFO read_string_into (a_str: STRING)
--RFO require
--RFO exists: a_str /= Void
--RFO local
--RFO l_c_str: C_STRING
--RFO p: POINTER
--RFO do
--RFO create l_c_str.make_empty (1024)
--RFO p := fcgi.gets (l_c_str.item)
--RFO-- if p /= default_pointer and p = l_c_str.item then
--RFO a_str.resize (l_c_str.count)
--RFO l_c_str.read_string_into (a_str)
--RFO-- else
--RFO-- put_error_line ("Bad pointer from gets")
--RFO-- end
--RFO end
--RFO read_line
--RFO -- Read up to the next end of line, or end of input
--RFO -- Leave result in last_string
--RFO -- Newline character is absent from result
--RFO do
--RFO if last_string = Void then
--RFO create Result.make (K_input_bufsize)
--RFO else
--RFO last_string.wipe_out
--RFO end
--RFO-- if input_filename /= Void then
--RFO-- io.read_line
--RFO-- last_string.append (io.last_string)
--RFO-- else
--RFO read_string_into (last_string)
--RFO-- end
--RFO end
feature {NONE} -- Implementation: environment
-- environ_strings_pointer (p_nb: TYPED_POINTER [INTEGER]): POINTER
-- -- Environment variable strings returned by `GetEnvironmentStringsA'
-- -- `p_nb' return the count of environment variables.
-- external
-- "C inline use <string.h>"
-- alias
-- "[
-- #ifdef EIF_WINDOWS
-- #ifndef GetEnvironmentStringsA
-- extern LPVOID WINAPI GetEnvironmentStringsA(void);
-- #endif
--
-- int cnt = 0;
-- LPSTR vars = GetEnvironmentStringsA();
-- char** p = (char**) vars;
--
-- for (; *vars; vars++) {
-- while (*vars) { vars++; }
-- cnt++;
-- }
--
-- *$p_nb = cnt;
-- return (EIF_POINTER) p;
-- #endif
-- ]"
-- end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,26 @@
note
description: "Interface to FCGI C library"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class FCGI
inherit
FCGI_IMP
create
make
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,236 @@
note
description: "Abstract interface to FCGI C library"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class FCGI_I
inherit
STRING_HANDLER
feature {NONE} -- Initialization
make
-- Initialize FCGI interface
deferred
end
feature -- Access
updated_environ_variables: HASH_TABLE [STRING, STRING]
local
i: INTEGER
p, v, null: POINTER
do
p := fcgi_environ
create Result.make (50)
if p /= null then
from
i := 0
v := fcgi_i_th_environ (i,p)
until
v = null
loop
if attached separated_variables (create {STRING}.make_from_c (v)) as t then
Result.force (t.value, t.key)
end
i := i + 1
v := fcgi_i_th_environ (i,p)
end
end
end
feature -- FCGI interface
fcgi_listen: INTEGER
-- Listen to the FCGI input stream
-- Return 0 for successful calls, -1 otherwise.
deferred
end
fcgi_environ: POINTER
-- Get the (char**) environ variable from the DLL.
deferred
end
fcgi_finish
-- Finish current request from HTTP server started from
-- the most recent call to `fcgi_accept'.
deferred
end
set_fcgi_exit_status (v: INTEGER)
deferred
end
feature -- Status
is_interactive: BOOLEAN
-- Is execution interactive? (for debugging)
do
end
feature -- Input
fill_string_from_stdin (s: STRING; n: INTEGER)
-- Read up to `n' bytes from stdin and store in string `s'
local
new_count: INTEGER
str_area: ANY
do
s.grow (n)
str_area := s.area
new_count := fill_pointer_from_stdin ($str_area, n)
s.set_count (new_count)
end
read_from_stdin (n: INTEGER)
-- Read up to n bytes from stdin and store in input buffer
require
small_enough: n <= buffer_capacity
local
l_c_str: C_STRING
l_count: INTEGER
do
last_read_is_empty_ref.set_item (False)
l_c_str := c_buffer
l_count := fill_pointer_from_stdin (l_c_str.item, n)
last_read_count_ref.set_item (l_count)
if l_count <= 0 then
last_read_is_empty_ref.set_item (True)
end
end
fill_pointer_from_stdin (p: POINTER; n: INTEGER): INTEGER
-- Read up to `n' bytes from stdin and store in pointer `p'
-- and return number of bytes read.
deferred
end
copy_from_stdin (n: INTEGER; f: FILE)
-- Read up to n bytes from stdin and write to given file
require
-- small_enough: n <= buffer_capacity
file_exists: f /= Void
file_open: f.is_open_write or f.is_open_append
deferred
end
feature -- Output
put_string (a_str: STRING)
-- Put `a_str' on the FastCGI stdout.
require
a_str_not_void: a_str /= Void
deferred
end
feature -- Implementation
buffer_contents: STRING
local
n: like last_read_count
do
n := last_read_count
create Result.make (n)
Result.set_count (n)
c_buffer.read_substring_into (Result, 1, n)
end
buffer_capacity: INTEGER
do
Result := c_buffer.capacity
end
--RFO last_string: STRING
--RFO once
--RFO create Result.make (K_input_bufsize)
--RFO end
last_read_count: INTEGER
do
Result := last_read_count_ref.item
end
last_read_is_empty: BOOLEAN
do
Result := last_read_is_empty_ref.item
end
feature {NONE} -- Shared buffer
c_buffer: C_STRING
-- Buffer for Eiffel to C and C to Eiffel string conversions.
once
create Result.make_empty (K_input_bufsize)
ensure
c_buffer_not_void: Result /= Void
end
feature {NONE} -- Constants
last_read_count_ref: INTEGER_REF
once
create Result
end
last_read_is_empty_ref: BOOLEAN_REF
once
create Result
end
K_input_bufsize: INTEGER = 1024_000
feature {NONE} -- Implementation: Environment
fcgi_i_th_environ (i: INTEGER; p: POINTER): POINTER
-- Environment variable at `i'-th position of `p'.
require
i_valid: i >=0
external
"C inline use <string.h>"
alias
"return ((char **)$p)[$i];"
end
separated_variables (a_var: STRING): detachable TUPLE [value: STRING; key: STRING]
-- 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.
require
a_var_attached: a_var /= Void
local
i, j: INTEGER
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
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-6-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-6-0 http://www.eiffel.com/developers/xml/configuration-1-6-0.xsd" name="libfcgi" uuid="3F4BCF74-3503-4533-9D74-5A65EC4CA3C4" library_target="libfcgi">
<target name="libfcgi">
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" >
</option>
<external_include location="$ECF_CONFIG_PATH/spec/include/libfcgi">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_include>
<external_include location="$ECF_CONFIG_PATH\spec\include\libfcgi">
<condition>
<platform value="windows"/>
</condition>
</external_include>
<external_library location="$ECF_CONFIG_PATH\spec\lib\$ISE_PLATFORM\$ISE_C_COMPILER\libfcgi.lib">
<condition>
<platform value="windows"/>
</condition>
</external_library>
<external_library location="/usr/local/lib/libfcgi.so">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_library>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="interface" location="interface" recursive="true"/>
<cluster name="implementation" location="implementation" recursive="true">
<file_rule>
<exclude>/linux$</exclude>
<exclude>/fake$</exclude>
<condition>
<platform value="windows"/>
</condition>
</file_rule>
<file_rule>
<exclude>/windows$</exclude>
<exclude>/fake$</exclude>
<condition>
<platform excluded_value="windows"/>
</condition>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-6-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-6-0 http://www.eiffel.com/developers/xml/configuration-1-6-0.xsd" name="libfcgi" uuid="3F4BCF74-3503-4533-9D74-5A65EC4CA3C4" library_target="libfcgi">
<target name="libfcgi">
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
</option>
<external_include location="$ECF_CONFIG_PATH/spec/include/libfcgi">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_include>
<external_include location="$ECF_CONFIG_PATH\spec\include\libfcgi">
<condition>
<platform value="windows"/>
</condition>
</external_include>
<external_library location="$ECF_CONFIG_PATH\spec\lib\$ISE_PLATFORM\$ISE_C_COMPILER\libfcgi.lib">
<condition>
<platform value="windows"/>
</condition>
</external_library>
<external_library location="/usr/local/lib/libfcgi.so">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_library>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<cluster name="interface" location="interface" recursive="true"/>
<cluster name="implementation" location="implementation" recursive="true">
<file_rule>
<exclude>/linux$</exclude>
<exclude>/fake$</exclude>
<condition>
<platform value="windows"/>
</condition>
</file_rule>
<file_rule>
<exclude>/windows$</exclude>
<exclude>/fake$</exclude>
<condition>
<platform excluded_value="windows"/>
</condition>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1 @@
reference:forum2

View File

@@ -0,0 +1,136 @@
/*
* fastcgi.h --
*
* Defines for the FastCGI protocol.
*
*
* Copyright (c) 1995-1996 Open Market, Inc.
*
* See the file "LICENSE.TERMS" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* $Id: fastcgi.h,v 1.1.1.1 1997/09/16 15:36:32 stanleyg Exp $
*/
#ifndef _FASTCGI_H
#define _FASTCGI_H
/*
* Listening socket file number
*/
#define FCGI_LISTENSOCK_FILENO 0
typedef struct {
unsigned char version;
unsigned char type;
unsigned char requestIdB1;
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
} FCGI_Header;
#define FCGI_MAX_LENGTH 0xffff
/*
* Number of bytes in a FCGI_Header. Future versions of the protocol
* will not reduce this number.
*/
#define FCGI_HEADER_LEN 8
/*
* Value for version component of FCGI_Header
*/
#define FCGI_VERSION_1 1
/*
* Values for type component of FCGI_Header
*/
#define FCGI_BEGIN_REQUEST 1
#define FCGI_ABORT_REQUEST 2
#define FCGI_END_REQUEST 3
#define FCGI_PARAMS 4
#define FCGI_STDIN 5
#define FCGI_STDOUT 6
#define FCGI_STDERR 7
#define FCGI_DATA 8
#define FCGI_GET_VALUES 9
#define FCGI_GET_VALUES_RESULT 10
#define FCGI_UNKNOWN_TYPE 11
#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
/*
* Value for requestId component of FCGI_Header
*/
#define FCGI_NULL_REQUEST_ID 0
typedef struct {
unsigned char roleB1;
unsigned char roleB0;
unsigned char flags;
unsigned char reserved[5];
} FCGI_BeginRequestBody;
typedef struct {
FCGI_Header header;
FCGI_BeginRequestBody body;
} FCGI_BeginRequestRecord;
/*
* Mask for flags component of FCGI_BeginRequestBody
*/
#define FCGI_KEEP_CONN 1
/*
* Values for role component of FCGI_BeginRequestBody
*/
#define FCGI_RESPONDER 1
#define FCGI_AUTHORIZER 2
#define FCGI_FILTER 3
typedef struct {
unsigned char appStatusB3;
unsigned char appStatusB2;
unsigned char appStatusB1;
unsigned char appStatusB0;
unsigned char protocolStatus;
unsigned char reserved[3];
} FCGI_EndRequestBody;
typedef struct {
FCGI_Header header;
FCGI_EndRequestBody body;
} FCGI_EndRequestRecord;
/*
* Values for protocolStatus component of FCGI_EndRequestBody
*/
#define FCGI_REQUEST_COMPLETE 0
#define FCGI_CANT_MPX_CONN 1
#define FCGI_OVERLOADED 2
#define FCGI_UNKNOWN_ROLE 3
/*
* Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT records
*/
#define FCGI_MAX_CONNS "FCGI_MAX_CONNS"
#define FCGI_MAX_REQS "FCGI_MAX_REQS"
#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
typedef struct {
unsigned char type;
unsigned char reserved[7];
} FCGI_UnknownTypeBody;
typedef struct {
FCGI_Header header;
FCGI_UnknownTypeBody body;
} FCGI_UnknownTypeRecord;
#endif /* _FASTCGI_H */

View File

@@ -0,0 +1,39 @@
/*
* Copied to fcgi_config.h when building on WinNT without cygwin,
* i.e. configure is not run. See fcgi_config.h.in for details.
*/
#define HAVE_FPOS 1
#define HAVE_LIMITS_H 1
#define HAVE_STREAMBUF_CHAR_TYPE 1
#define HAVE_STRERROR 1
#undef HAVE_ARPA_INET_H
#undef HAVE_DLFCN_H
#undef HAVE_FILENO_PROTO
#undef HAVE_INTTYPES_H
#undef HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
#undef HAVE_LIBNSL
#undef HAVE_LIBSOCKET
#undef HAVE_MEMORY_H
#undef HAVE_NETDB_H
#undef HAVE_NETINET_IN_H
#undef HAVE_PTHREAD
#undef HAVE_SOCKADDR_UN_SUN_LEN
#undef HAVE_SOCKLEN
#undef HAVE_STDINT_H
#undef HAVE_STDLIB_H
#undef HAVE_STRING_H
#undef HAVE_STRINGS_H
#undef HAVE_SYS_PARAM_H
#undef HAVE_SYS_SOCKET_H
#undef HAVE_SYS_STAT_H
#undef HAVE_SYS_TIME_H
#undef HAVE_SYS_TYPES_H
#undef HAVE_UNISTD_H
#undef HAVE_VA_ARG_LONG_DOUBLE_BUG
#undef PTHREAD_CREATE_JOINABLE
#undef STDC_HEADERS
#undef USE_LOCKING
#undef const
#undef inline
#undef ssize_t

View File

@@ -0,0 +1,39 @@
/*
* Copied to fcgi_config.h when building on WinNT without cygwin,
* i.e. configure is not run. See fcgi_config.h.in for details.
*/
#define HAVE_FPOS 1
#define HAVE_LIMITS_H 1
#define HAVE_STREAMBUF_CHAR_TYPE 1
#define HAVE_STRERROR 1
#undef HAVE_ARPA_INET_H
#undef HAVE_DLFCN_H
#undef HAVE_FILENO_PROTO
#undef HAVE_INTTYPES_H
#undef HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
#undef HAVE_LIBNSL
#undef HAVE_LIBSOCKET
#undef HAVE_MEMORY_H
#undef HAVE_NETDB_H
#undef HAVE_NETINET_IN_H
#undef HAVE_PTHREAD
#undef HAVE_SOCKADDR_UN_SUN_LEN
#undef HAVE_SOCKLEN
#undef HAVE_STDINT_H
#undef HAVE_STDLIB_H
#undef HAVE_STRING_H
#undef HAVE_STRINGS_H
#undef HAVE_SYS_PARAM_H
#undef HAVE_SYS_SOCKET_H
#undef HAVE_SYS_STAT_H
#undef HAVE_SYS_TIME_H
#undef HAVE_SYS_TYPES_H
#undef HAVE_UNISTD_H
#undef HAVE_VA_ARG_LONG_DOUBLE_BUG
#undef PTHREAD_CREATE_JOINABLE
#undef STDC_HEADERS
#undef USE_LOCKING
#undef const
#undef inline
#undef ssize_t

View File

@@ -0,0 +1,246 @@
/*
* fcgi_stdio.h --
*
* FastCGI-stdio compatibility package
*
*
* Copyright (c) 1996 Open Market, Inc.
*
* See the file "LICENSE.TERMS" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* $Id: fcgi_stdio.h,v 1.5 2001/06/22 13:21:15 robs Exp $
*/
#ifndef _FCGI_STDIO
#define _FCGI_STDIO 1
#include <stdio.h>
#include <sys/types.h>
#include "fcgiapp.h"
#if defined (c_plusplus) || defined (__cplusplus)
extern "C" {
#endif
#ifndef DLLAPI
#ifdef _WIN32
#define DLLAPI __declspec(dllimport)
#else
#define DLLAPI
#endif
#endif
/*
* Wrapper type for FILE
*/
typedef struct {
FILE *stdio_stream;
FCGX_Stream *fcgx_stream;
} FCGI_FILE;
/*
* The four new functions and two new macros
*/
DLLAPI int FCGI_Accept(void);
DLLAPI char** FCGI_Environ(void);
DLLAPI void FCGI_Finish(void);
DLLAPI int FCGI_StartFilterData(void);
DLLAPI void FCGI_SetExitStatus(int status);
#define FCGI_ToFILE(fcgi_file) (fcgi_file->stdio_stream)
#define FCGI_ToFcgiStream(fcgi_file) (fcgi_file->fcgx_stream)
/*
* Wrapper stdin, stdout, and stderr variables, set up by FCGI_Accept()
*/
DLLAPI extern FCGI_FILE _fcgi_sF[];
#define FCGI_stdin (&_fcgi_sF[0])
#define FCGI_stdout (&_fcgi_sF[1])
#define FCGI_stderr (&_fcgi_sF[2])
/*
* Wrapper function prototypes, grouped according to sections
* of Harbison & Steele, "C: A Reference Manual," fourth edition,
* Prentice-Hall, 1995.
*/
DLLAPI void FCGI_perror(const char *str);
DLLAPI FCGI_FILE *FCGI_fopen(const char *path, const char *mode);
DLLAPI int FCGI_fclose(FCGI_FILE *fp);
DLLAPI int FCGI_fflush(FCGI_FILE *fp);
DLLAPI FCGI_FILE *FCGI_freopen(const char *path, const char *mode, FCGI_FILE *fp);
DLLAPI int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size);
DLLAPI void FCGI_setbuf(FCGI_FILE *fp, char *buf);
DLLAPI int FCGI_fseek(FCGI_FILE *fp, long offset, int whence);
DLLAPI int FCGI_ftell(FCGI_FILE *fp);
DLLAPI void FCGI_rewind(FCGI_FILE *fp);
#ifdef HAVE_FPOS
DLLAPI int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos);
DLLAPI int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos);
#endif
DLLAPI int FCGI_fgetc(FCGI_FILE *fp);
DLLAPI int FCGI_getchar(void);
DLLAPI int FCGI_ungetc(int c, FCGI_FILE *fp);
DLLAPI char *FCGI_fgets(char *str, int size, FCGI_FILE *fp);
DLLAPI char *FCGI_gets(char *str);
/*
* Not yet implemented
*
* int FCGI_fscanf(FCGI_FILE *fp, const char *format, ...);
* int FCGI_scanf(const char *format, ...);
*
*/
DLLAPI int FCGI_fputc(int c, FCGI_FILE *fp);
DLLAPI int FCGI_putchar(int c);
DLLAPI int FCGI_fputs(const char *str, FCGI_FILE *fp);
DLLAPI int FCGI_puts(const char *str);
DLLAPI int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...);
DLLAPI int FCGI_printf(const char *format, ...);
DLLAPI int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap);
DLLAPI int FCGI_vprintf(const char *format, va_list ap);
DLLAPI size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp);
DLLAPI size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp);
DLLAPI int FCGI_feof(FCGI_FILE *fp);
DLLAPI int FCGI_ferror(FCGI_FILE *fp);
DLLAPI void FCGI_clearerr(FCGI_FILE *fp);
DLLAPI FCGI_FILE *FCGI_tmpfile(void);
DLLAPI int FCGI_fileno(FCGI_FILE *fp);
DLLAPI FCGI_FILE *FCGI_fdopen(int fd, const char *mode);
DLLAPI FCGI_FILE *FCGI_popen(const char *cmd, const char *type);
DLLAPI int FCGI_pclose(FCGI_FILE *);
/*
* The remaining definitions are for application programs,
* not for fcgi_stdio.c
*/
#ifndef NO_FCGI_DEFINES
/*
* Replace standard types, variables, and functions with FastCGI wrappers.
* Use undef in case a macro is already defined.
*/
#undef FILE
#define FILE FCGI_FILE
#undef stdin
#define stdin FCGI_stdin
#undef stdout
#define stdout FCGI_stdout
#undef stderr
#define stderr FCGI_stderr
#undef perror
#define perror FCGI_perror
#undef fopen
#define fopen FCGI_fopen
#undef fclose
#define fclose FCGI_fclose
#undef fflush
#define fflush FCGI_fflush
#undef freopen
#define freopen FCGI_freopen
#undef setvbuf
#define setvbuf FCGI_setvbuf
#undef setbuf
#define setbuf FCGI_setbuf
#undef fseek
#define fseek FCGI_fseek
#undef ftell
#define ftell FCGI_ftell
#undef rewind
#define rewind FCGI_rewind
#undef fgetpos
#define fgetpos FCGI_fgetpos
#undef fsetpos
#define fsetpos FCGI_fsetpos
#undef fgetc
#define fgetc FCGI_fgetc
#undef getc
#define getc FCGI_fgetc
#undef getchar
#define getchar FCGI_getchar
#undef ungetc
#define ungetc FCGI_ungetc
#undef fgets
#define fgets FCGI_fgets
#undef gets
#define gets FCGI_gets
#undef fputc
#define fputc FCGI_fputc
#undef putc
#define putc FCGI_fputc
#undef putchar
#define putchar FCGI_putchar
#undef fputs
#define fputs FCGI_fputs
#undef puts
#define puts FCGI_puts
#undef fprintf
#define fprintf FCGI_fprintf
#undef printf
#define printf FCGI_printf
#undef vfprintf
#define vfprintf FCGI_vfprintf
#undef vprintf
#define vprintf FCGI_vprintf
#undef fread
#define fread FCGI_fread
#undef fwrite
#define fwrite FCGI_fwrite
#undef feof
#define feof FCGI_feof
#undef ferror
#define ferror FCGI_ferror
#undef clearerr
#define clearerr FCGI_clearerr
#undef tmpfile
#define tmpfile FCGI_tmpfile
#undef fileno
#define fileno FCGI_fileno
#undef fdopen
#define fdopen FCGI_fdopen
#undef popen
#define popen FCGI_popen
#undef pclose
#define pclose FCGI_pclose
#endif /* NO_FCGI_DEFINES */
#if defined (__cplusplus) || defined (c_plusplus)
} /* terminate extern "C" { */
#endif
#endif /* _FCGI_STDIO */

View File

@@ -0,0 +1,622 @@
/*
* fcgiapp.h --
*
* Definitions for FastCGI application server programs
*
*
* Copyright (c) 1996 Open Market, Inc.
*
* See the file "LICENSE.TERMS" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* $Id: fcgiapp.h,v 1.12 2001/11/21 21:10:11 robs Exp $
*/
#ifndef _FCGIAPP_H
#define _FCGIAPP_H
/* Hack to see if we are building TCL - TCL needs varargs not stdarg */
#ifndef TCL_LIBRARY
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifndef DLLAPI
#ifdef _WIN32
#define DLLAPI __declspec(dllimport)
#else
#define DLLAPI
#endif
#endif
#if defined (c_plusplus) || defined (__cplusplus)
extern "C" {
#endif
/*
* Error codes. Assigned to avoid conflict with EOF and errno(2).
*/
#define FCGX_UNSUPPORTED_VERSION -2
#define FCGX_PROTOCOL_ERROR -3
#define FCGX_PARAMS_ERROR -4
#define FCGX_CALL_SEQ_ERROR -5
/*
* This structure defines the state of a FastCGI stream.
* Streams are modeled after the FILE type defined in stdio.h.
* (We wouldn't need our own if platform vendors provided a
* standard way to subclass theirs.)
* The state of a stream is private and should only be accessed
* by the procedures defined below.
*/
typedef struct FCGX_Stream {
unsigned char *rdNext; /* reader: first valid byte
* writer: equals stop */
unsigned char *wrNext; /* writer: first free byte
* reader: equals stop */
unsigned char *stop; /* reader: last valid byte + 1
* writer: last free byte + 1 */
unsigned char *stopUnget; /* reader: first byte of current buffer
* fragment, for ungetc
* writer: undefined */
int isReader;
int isClosed;
int wasFCloseCalled;
int FCGI_errno; /* error status */
void (*fillBuffProc) (struct FCGX_Stream *stream);
void (*emptyBuffProc) (struct FCGX_Stream *stream, int doClose);
void *data;
} FCGX_Stream;
/*
* An environment (as defined by environ(7)): A NULL-terminated array
* of strings, each string having the form name=value.
*/
typedef char **FCGX_ParamArray;
/*
* FCGX_Request Flags
*
* Setting FCGI_FAIL_ACCEPT_ON_INTR prevents FCGX_Accept() from
* restarting upon being interrupted.
*/
#define FCGI_FAIL_ACCEPT_ON_INTR 1
/*
* FCGX_Request -- State associated with a request.
*
* Its exposed for API simplicity, I expect parts of it to change!
*/
typedef struct FCGX_Request {
int requestId; /* valid if isBeginProcessed */
int role;
FCGX_Stream *in;
FCGX_Stream *out;
FCGX_Stream *err;
char **envp;
/* Don't use anything below here */
struct Params *paramsPtr;
int ipcFd; /* < 0 means no connection */
int isBeginProcessed; /* FCGI_BEGIN_REQUEST seen */
int keepConnection; /* don't close ipcFd at end of request */
int appStatus;
int nWriters; /* number of open writers (0..2) */
int flags;
int listen_sock;
} FCGX_Request;
/*
*======================================================================
* Control
*======================================================================
*/
/*
*----------------------------------------------------------------------
*
* FCGX_IsCGI --
*
* Returns TRUE iff this process appears to be a CGI process
* rather than a FastCGI process.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_IsCGI(void);
/*
*----------------------------------------------------------------------
*
* FCGX_Init --
*
* Initialize the FCGX library. Call in multi-threaded apps
* before calling FCGX_Accept_r().
*
* Returns 0 upon success.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_Init(void);
/*
*----------------------------------------------------------------------
*
* FCGX_OpenSocket --
*
* Create a FastCGI listen socket.
*
* path is the Unix domain socket (named pipe for WinNT), or a colon
* followed by a port number. e.g. "/tmp/fastcgi/mysocket", ":5000"
*
* backlog is the listen queue depth used in the listen() call.
*
* Returns the socket's file descriptor or -1 on error.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_OpenSocket(const char *path, int backlog);
/*
*----------------------------------------------------------------------
*
* FCGX_InitRequest --
*
* Initialize a FCGX_Request for use with FCGX_Accept_r().
*
* sock is a file descriptor returned by FCGX_OpenSocket() or 0 (default).
* The only supported flag at this time is FCGI_FAIL_ON_INTR.
*
* Returns 0 upon success.
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_InitRequest(FCGX_Request *request, int sock, int flags);
/*
*----------------------------------------------------------------------
*
* FCGX_Accept_r --
*
* Accept a new request (multi-thread safe). Be sure to call
* FCGX_Init() first.
*
* Results:
* 0 for successful call, -1 for error.
*
* Side effects:
*
* Finishes the request accepted by (and frees any
* storage allocated by) the previous call to FCGX_Accept.
* Creates input, output, and error streams and
* assigns them to *in, *out, and *err respectively.
* Creates a parameters data structure to be accessed
* via getenv(3) (if assigned to environ) or by FCGX_GetParam
* and assigns it to *envp.
*
* DO NOT retain pointers to the envp array or any strings
* contained in it (e.g. to the result of calling FCGX_GetParam),
* since these will be freed by the next call to FCGX_Finish
* or FCGX_Accept.
*
* DON'T use the FCGX_Request, its structure WILL change.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_Accept_r(FCGX_Request *request);
/*
*----------------------------------------------------------------------
*
* FCGX_Finish_r --
*
* Finish the request (multi-thread safe).
*
* Side effects:
*
* Finishes the request accepted by (and frees any
* storage allocated by) the previous call to FCGX_Accept.
*
* DO NOT retain pointers to the envp array or any strings
* contained in it (e.g. to the result of calling FCGX_GetParam),
* since these will be freed by the next call to FCGX_Finish
* or FCGX_Accept.
*
*----------------------------------------------------------------------
*/
DLLAPI void FCGX_Finish_r(FCGX_Request *request);
/*
*----------------------------------------------------------------------
*
* FCGX_Free --
*
* Free the memory and, if close is true,
* IPC FD associated with the request (multi-thread safe).
*
*----------------------------------------------------------------------
*/
DLLAPI void FCGX_Free(FCGX_Request * request, int close);
/*
*----------------------------------------------------------------------
*
* FCGX_Accept --
*
* Accept a new request (NOT multi-thread safe).
*
* Results:
* 0 for successful call, -1 for error.
*
* Side effects:
*
* Finishes the request accepted by (and frees any
* storage allocated by) the previous call to FCGX_Accept.
* Creates input, output, and error streams and
* assigns them to *in, *out, and *err respectively.
* Creates a parameters data structure to be accessed
* via getenv(3) (if assigned to environ) or by FCGX_GetParam
* and assigns it to *envp.
*
* DO NOT retain pointers to the envp array or any strings
* contained in it (e.g. to the result of calling FCGX_GetParam),
* since these will be freed by the next call to FCGX_Finish
* or FCGX_Accept.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_Accept(
FCGX_Stream **in,
FCGX_Stream **out,
FCGX_Stream **err,
FCGX_ParamArray *envp);
/*
*----------------------------------------------------------------------
*
* FCGX_Finish --
*
* Finish the current request (NOT multi-thread safe).
*
* Side effects:
*
* Finishes the request accepted by (and frees any
* storage allocated by) the previous call to FCGX_Accept.
*
* DO NOT retain pointers to the envp array or any strings
* contained in it (e.g. to the result of calling FCGX_GetParam),
* since these will be freed by the next call to FCGX_Finish
* or FCGX_Accept.
*
*----------------------------------------------------------------------
*/
DLLAPI void FCGX_Finish(void);
/*
*----------------------------------------------------------------------
*
* FCGX_StartFilterData --
*
* stream is an input stream for a FCGI_FILTER request.
* stream is positioned at EOF on FCGI_STDIN.
* Repositions stream to the start of FCGI_DATA.
* If the preconditions are not met (e.g. FCGI_STDIN has not
* been read to EOF) sets the stream error code to
* FCGX_CALL_SEQ_ERROR.
*
* Results:
* 0 for a normal return, < 0 for error
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_StartFilterData(FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_SetExitStatus --
*
* Sets the exit status for stream's request. The exit status
* is the status code the request would have exited with, had
* the request been run as a CGI program. You can call
* SetExitStatus several times during a request; the last call
* before the request ends determines the value.
*
*----------------------------------------------------------------------
*/
DLLAPI void FCGX_SetExitStatus(int status, FCGX_Stream *stream);
/*
*======================================================================
* Parameters
*======================================================================
*/
/*
*----------------------------------------------------------------------
*
* FCGX_GetParam -- obtain value of FCGI parameter in environment
*
*
* Results:
* Value bound to name, NULL if name not present in the
* environment envp. Caller must not mutate the result
* or retain it past the end of this request.
*
*----------------------------------------------------------------------
*/
DLLAPI char *FCGX_GetParam(const char *name, FCGX_ParamArray envp);
/*
*======================================================================
* Readers
*======================================================================
*/
/*
*----------------------------------------------------------------------
*
* FCGX_GetChar --
*
* Reads a byte from the input stream and returns it.
*
* Results:
* The byte, or EOF (-1) if the end of input has been reached.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_GetChar(FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_UnGetChar --
*
* Pushes back the character c onto the input stream. One
* character of pushback is guaranteed once a character
* has been read. No pushback is possible for EOF.
*
* Results:
* Returns c if the pushback succeeded, EOF if not.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_UnGetChar(int c, FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_GetStr --
*
* Reads up to n consecutive bytes from the input stream
* into the character array str. Performs no interpretation
* of the input bytes.
*
* Results:
* Number of bytes read. If result is smaller than n,
* the end of input has been reached.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_GetStr(char *str, int n, FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_GetLine --
*
* Reads up to n-1 consecutive bytes from the input stream
* into the character array str. Stops before n-1 bytes
* have been read if '\n' or EOF is read. The terminating '\n'
* is copied to str. After copying the last byte into str,
* stores a '\0' terminator.
*
* Results:
* NULL if EOF is the first thing read from the input stream,
* str otherwise.
*
*----------------------------------------------------------------------
*/
DLLAPI char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_HasSeenEOF --
*
* Returns EOF if end-of-file has been detected while reading
* from stream; otherwise returns 0.
*
* Note that FCGX_HasSeenEOF(s) may return 0, yet an immediately
* following FCGX_GetChar(s) may return EOF. This function, like
* the standard C stdio function feof, does not provide the
* ability to peek ahead.
*
* Results:
* EOF if end-of-file has been detected, 0 if not.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_HasSeenEOF(FCGX_Stream *stream);
/*
*======================================================================
* Writers
*======================================================================
*/
/*
*----------------------------------------------------------------------
*
* FCGX_PutChar --
*
* Writes a byte to the output stream.
*
* Results:
* The byte, or EOF (-1) if an error occurred.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_PutChar(int c, FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_PutStr --
*
* Writes n consecutive bytes from the character array str
* into the output stream. Performs no interpretation
* of the output bytes.
*
* Results:
* Number of bytes written (n) for normal return,
* EOF (-1) if an error occurred.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_PutS --
*
* Writes a null-terminated character string to the output stream.
*
* Results:
* number of bytes written for normal return,
* EOF (-1) if an error occurred.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_PutS(const char *str, FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_FPrintF, FCGX_VFPrintF --
*
* Performs printf-style output formatting and writes the results
* to the output stream.
*
* Results:
* number of bytes written for normal return,
* EOF (-1) if an error occurred.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...);
DLLAPI int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg);
/*
*----------------------------------------------------------------------
*
* FCGX_FFlush --
*
* Flushes any buffered output.
*
* Server-push is a legitimate application of FCGX_FFlush.
* Otherwise, FCGX_FFlush is not very useful, since FCGX_Accept
* does it implicitly. Calling FCGX_FFlush in non-push applications
* results in extra writes and therefore reduces performance.
*
* Results:
* EOF (-1) if an error occurred.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_FFlush(FCGX_Stream *stream);
/*
*======================================================================
* Both Readers and Writers
*======================================================================
*/
/*
*----------------------------------------------------------------------
*
* FCGX_FClose --
*
* Closes the stream. For writers, flushes any buffered
* output.
*
* Close is not a very useful operation since FCGX_Accept
* does it implicitly. Closing the out stream before the
* err stream results in an extra write if there's nothing
* in the err stream, and therefore reduces performance.
*
* Results:
* EOF (-1) if an error occurred.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_FClose(FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_GetError --
*
* Return the stream error code. 0 means no error, > 0
* is an errno(2) error, < 0 is an FastCGI error.
*
*----------------------------------------------------------------------
*/
DLLAPI int FCGX_GetError(FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_ClearError --
*
* Clear the stream error code and end-of-file indication.
*
*----------------------------------------------------------------------
*/
DLLAPI void FCGX_ClearError(FCGX_Stream *stream);
/*
*----------------------------------------------------------------------
*
* FCGX_CreateWriter --
*
* Create a FCGX_Stream (used by cgi-fcgi). This shouldn't
* be needed by a FastCGI applictaion.
*
*----------------------------------------------------------------------
*/
DLLAPI FCGX_Stream *FCGX_CreateWriter(
int socket,
int requestId,
int bufflen,
int streamType);
/*
*----------------------------------------------------------------------
*
* FCGX_FreeStream --
*
* Free a FCGX_Stream (used by cgi-fcgi). This shouldn't
* be needed by a FastCGI applictaion.
*
*----------------------------------------------------------------------
*/
DLLAPI void FCGX_FreeStream(FCGX_Stream **stream);
/* ----------------------------------------------------------------------
*
* Prevent the lib from accepting any new requests. Signal handler safe.
*
* ----------------------------------------------------------------------
*/
DLLAPI void FCGX_ShutdownPending(void);
#if defined (__cplusplus) || defined (c_plusplus)
} /* terminate extern "C" { */
#endif
#endif /* _FCGIAPP_H */

View File

@@ -0,0 +1,38 @@
/*
* fcgimisc.h --
*
* Miscellaneous definitions
*
*
* Copyright (c) 1996 Open Market, Inc.
*
* See the file "LICENSE.TERMS" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* $Id: fcgimisc.h,v 1.3 2001/06/18 14:25:47 robs Exp $
*/
#ifndef _FCGIMISC_H
#define _FCGIMISC_H
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef ASSERT
#define ASSERT(assertion) assert(assertion)
#endif
#endif /* _FCGIMISC_H */

View File

@@ -0,0 +1,151 @@
//
// Provides support for FastCGI via C++ iostreams.
//
// $Id: fcgio.h,v 1.15 2002/02/25 13:16:11 robs Exp $
//
// This work is based on routines written by George Feinberg. They
// have been mostly re-written and extensively changed by
// Michael Richards.
//
// Rewritten again with bug fixes and numerous enhancements by
// Michael Shell.
//
// And rewritten again by Rob Saccoccio.
//
// Special Thanks to Dietmar Kuehl for his help and the numerous custom
// streambuf examples on his web site.
//
// Copyright (c) 2000 Tux the Linux Penguin
// Copyright (c) 2001 Rob Saccoccio and Chelsea Networks
//
// You are free to use this software without charge or royalty
// as long as this notice is not removed or altered, and recognition
// is given to the author(s)
//
// This code is offered as-is without any warranty either expressed or
// implied; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. If it breaks, you get to keep
// both halves.
#ifndef FCGIO_H
#define FCGIO_H
#include <iostream>
#include "fcgiapp.h"
#ifndef DLLAPI
#ifdef _WIN32
#define DLLAPI __declspec(dllimport)
#else
#define DLLAPI
#endif
#endif
#if ! HAVE_STREAMBUF_CHAR_TYPE
typedef char char_type;
#endif
/*
* fcgi_streambuf
*/
class DLLAPI fcgi_streambuf : public std::streambuf
{
public:
// Note that if no buf is assigned (the default), iostream methods
// such as peek(), unget() and putback() will fail. If a buf is
// assigned, I/O is a bit less effecient and output streams will
// have to be flushed (or the streambuf destroyed) before the next
// call to "accept".
fcgi_streambuf(FCGX_Stream * fcgx, char * buf, int len);
fcgi_streambuf(char_type * buf, std::streamsize len);
fcgi_streambuf(FCGX_Stream * fcgx = 0);
~fcgi_streambuf(void);
int attach(FCGX_Stream * fcgx);
protected:
// Consume the put area (if buffered) and c (if c is not EOF).
virtual int overflow(int);
// Flush the put area (if buffered) and the FCGX buffer to the client.
virtual int sync();
// Remove and return the current character.
virtual int uflow();
// Fill the get area (if buffered) and return the current character.
virtual int underflow();
// Use a buffer. The only reasons that a buffer would be useful is
// to support the use of the unget()/putback() or seek() methods. Using
// a buffer will result in less efficient I/O. Note: the underlying
// FastCGI library (FCGX) maintains its own input and output buffers.
virtual std::streambuf * setbuf(char_type * buf, std::streamsize len);
virtual std::streamsize xsgetn(char_type * s, std::streamsize n);
virtual std::streamsize xsputn(const char_type * s, std::streamsize n);
private:
FCGX_Stream * fcgx;
// buf is just handy to have around
char_type * buf;
// this isn't kept by the base class
std::streamsize bufsize;
void init(FCGX_Stream * fcgx, char_type * buf, std::streamsize bufsize);
void reset(void);
};
/*
* fcgi_istream - deprecated
*/
class DLLAPI fcgi_istream : public std::istream
{
public:
// deprecated
fcgi_istream(FCGX_Stream * fcgx = 0);
// deprecated
~fcgi_istream(void) {}
// deprecated
virtual void attach(FCGX_Stream * fcgx);
private:
fcgi_streambuf fcgi_strmbuf;
};
/*
* fcgi_ostream - deprecated
*/
class DLLAPI fcgi_ostream : public std::ostream
{
public:
// deprecated
fcgi_ostream(FCGX_Stream * fcgx = 0);
// deprecated
~fcgi_ostream(void) {}
// deprecated
virtual void attach(FCGX_Stream *fcgx);
private:
fcgi_streambuf fcgi_strmbuf;
};
#endif /* FCGIO_H */

View File

@@ -0,0 +1,130 @@
/*
* fcgios.h --
*
* Description of file.
*
*
* Copyright (c) 1996 Open Market, Inc.
* All rights reserved.
*
* This file contains proprietary and confidential information and
* remains the unpublished property of Open Market, Inc. Use,
* disclosure, or reproduction is prohibited except as permitted by
* express written license agreement with Open Market, Inc.
*
* Bill Snapper
* snapper@openmarket.com
*/
#ifndef _FCGIOS_H
#define _FCGIOS_H
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#endif
#include "fcgi_config.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if defined (c_plusplus) || defined (__cplusplus)
extern "C" {
#endif
#ifdef _WIN32
#define OS_Errno GetLastError()
#define OS_SetErrno(err) SetLastError(err)
#ifndef O_NONBLOCK
#define O_NONBLOCK 0x0004 /* no delay */
#endif
#else /* !_WIN32 */
#define OS_Errno errno
#define OS_SetErrno(err) errno = (err)
#endif /* !_WIN32 */
#ifndef DLLAPI
#ifdef _WIN32
#define DLLAPI __declspec(dllimport)
#else
#define DLLAPI
#endif
#endif
/* This is the initializer for a "struct timeval" used in a select() call
* right after a new request is accept()ed to determine readablity. Its
* a drop-dead timer. Its only used for AF_UNIX sockets (not TCP sockets).
* Its a workaround for a kernel bug in Linux 2.0.x and SCO Unixware.
* Making this as small as possible, yet remain reliable would be best.
* 2 seconds is very conservative. 0,0 is not reliable. The shorter the
* timeout, the faster request processing will recover. The longer the
* timeout, the more likely this application being "busy" will cause other
* requests to abort and cause more dead sockets that need this timeout. */
#define READABLE_UNIX_FD_DROP_DEAD_TIMEVAL 2,0
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#ifndef X_OK
#define X_OK 0x01
#endif
#ifndef _CLIENTDATA
# if defined(__STDC__) || defined(__cplusplus)
typedef void *ClientData;
# else
typedef int *ClientData;
# endif /* __STDC__ */
#define _CLIENTDATA
#endif
typedef void (*OS_AsyncProc) (ClientData clientData, int len);
DLLAPI int OS_LibInit(int stdioFds[3]);
DLLAPI void OS_LibShutdown(void);
DLLAPI int OS_CreateLocalIpcFd(const char *bindPath, int backlog);
DLLAPI int OS_FcgiConnect(char *bindPath);
DLLAPI int OS_Read(int fd, char * buf, size_t len);
DLLAPI int OS_Write(int fd, char * buf, size_t len);
DLLAPI int OS_SpawnChild(char *execPath, int listenFd);
DLLAPI int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr,
ClientData clientData);
DLLAPI int OS_AsyncRead(int fd, int offset, void *buf, int len,
OS_AsyncProc procPtr, ClientData clientData);
DLLAPI int OS_AsyncWrite(int fd, int offset, void *buf, int len,
OS_AsyncProc procPtr, ClientData clientData);
DLLAPI int OS_Close(int fd);
DLLAPI int OS_CloseRead(int fd);
DLLAPI int OS_DoIo(struct timeval *tmo);
DLLAPI int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs);
DLLAPI int OS_IpcClose(int ipcFd);
DLLAPI int OS_IsFcgi(int sock);
DLLAPI void OS_SetFlags(int fd, int flags);
DLLAPI void OS_ShutdownPending(void);
#if defined (__cplusplus) || defined (c_plusplus)
} /* terminate extern "C" { */
#endif
#endif /* _FCGIOS_H */

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,64 @@
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>
<IfModule mod_fcgid.c>
# FcgidIdleTimeout 600
# FcgidBusyScanInterval 120
# FcgidProcessLifeTime 0
# #7200
# FcgidMaxProcesses 1000
# FcgidMaxProcessesPerClass 100
# FcgidMinProcessesPerClass 100
# FcgidConnectTimeout 8
# FcgidIOTimeout 60
# FcgidBusyTimeout 1200
alias /eiffelweb/ "/home/jfiat/_dev/EiffelWebReloaded/library/fcgi/tests/EIFGENs/eiffelweb/W_code/"
<Location /eiffelweb/>
AddHandler fcgid-script .ews
Options Indexes FollowSymLinks ExecCGI
# Customize the next two directives for your requirements.
Order allow,deny
Allow from all
</Location>
</IfModule>
</VirtualHost>

View File

@@ -0,0 +1,80 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
APPLICATION_ROOT
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
local
res: INTEGER
nb: INTEGER
do
initialize
from
res := fcgi.fcgi_listen
until
res < 0
loop
nb := nb + 1
fcgi.put_string (header ("FCGI Eiffel Application"))
fcgi.put_string ("<h1>Hello FCGI Eiffel Application</h1>%N")
fcgi.put_string ("Request number " + nb.out + "<br/>%N")
fcgi.put_string ("<ul>Environment variables%N")
print_environment_variables (fcgi.updated_environ_variables)
fcgi.put_string ("</ul>")
fcgi.put_string (footer)
res := fcgi.fcgi_listen
end
end
feature -- Access
header (a_title: STRING): STRING
do
Result := "Content-type: text/html%R%N"
Result.append ("%R%N")
Result.append ("<html>%N")
Result.append ("<head><title>" + a_title + "</title></head>")
Result.append ("<body>%N")
end
footer: STRING
do
Result := "</body>%N</html>%N"
end
print_environment_variables (vars: HASH_TABLE [STRING, STRING])
local
do
from
vars.start
until
vars.after
loop
fcgi.put_string ("<li><strong>" + vars.key_for_iteration + "</strong> = " + vars.item_for_iteration + "</li>%N")
vars.forth
end
end
feature {NONE} -- Implementation
initialize
do
create fcgi.make
end
fcgi: FCGI
end

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="eiffelweb" uuid="6A03BC65-BD03-4B68-B51E-2543F9471D42">
<target name="eiffelweb">
<root cluster="application" class="APPLICATION_ROOT" feature="make"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<setting name="console_application" value="true"/>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="fcgi" location="..\fcgi.ecf" readonly="false"/>
<cluster name="application" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="encoder" uuid="EE80E648-C64D-4802-8868-C57AAFEACC55" library_target="encoder">
<target name="encoder">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="src" location="src\" recursive="true">
<file_rule>
<exclude>/tests$</exclude>
</file_rule>
</cluster>
</target>
<target name="tests" extends="encoder" >
<root class="ANY" feature="default_create"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<assertions precondition="true"/>
</option>
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
<tests name="tests" location="./tests"/>
</target>
</system>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="encoder" uuid="EE80E648-C64D-4802-8868-C57AAFEACC55" library_target="encoder">
<target name="encoder">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<cluster name="src" location="src\" recursive="true">
<file_rule>
<exclude>/tests$</exclude>
</file_rule>
</cluster>
</target>
<target name="tests" extends="encoder" >
<root class="ANY" feature="default_create"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
<assertions precondition="true"/>
</option>
<library name="testing" location="$ISE_LIBRARY\library\testing\testing.ecf"/>
<tests name="tests" location="./tests"/>
</target>
</system>

View File

@@ -0,0 +1 @@
reference:forum2

View File

@@ -0,0 +1,218 @@
note
description: "Summary description for {BASE64}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
BASE64
inherit
ENCODER [STRING_8, STRING_8]
redefine
valid_encoded_string
end
feature -- Access
name: STRING = "base64"
feature -- Status report
has_error: BOOLEAN
valid_encoded_string (v: STRING): BOOLEAN
do
Result := Precursor (v) and then
(v.is_empty or v.count >= 4)
end
feature -- base64 encoder
encoded_string (s: STRING): STRING_8
-- base64 encoded value of `s'.
local
i,n: INTEGER
c: INTEGER
f: SPECIAL [BOOLEAN]
base64chars: STRING_8
do
has_error := False
base64chars := character_map
from
n := s.count
i := (8 * n) \\ 6
if i > 0 then
create f.make_filled (False, 8 * n + (6 - i))
else
create f.make_filled (False, 8 * n)
end
i := 0
until
i > n - 1
loop
c := s.item (i + 1).code
f[8 * i + 0] := c.bit_test(7)
f[8 * i + 1] := c.bit_test(6)
f[8 * i + 2] := c.bit_test(5)
f[8 * i + 3] := c.bit_test(4)
f[8 * i + 4] := c.bit_test(3)
f[8 * i + 5] := c.bit_test(2)
f[8 * i + 6] := c.bit_test(1)
f[8 * i + 7] := c.bit_test(0)
i := i + 1
end
from
i := 0
n := f.count
create Result.make (n // 6)
until
i > n - 1
loop
c := 0
if f[i + 0] then c := c + 0x20 end
if f[i + 1] then c := c + 0x10 end
if f[i + 2] then c := c + 0x8 end
if f[i + 3] then c := c + 0x4 end
if f[i + 4] then c := c + 0x2 end
if f[i + 5] then c := c + 0x1 end
Result.extend (base64chars.item (c + 1))
i := i + 6
end
i := s.count \\ 3
if i > 0 then
from until i > 2 loop
Result.extend ('=')
i := i + 1
end
end
end
feature -- Decoder
decoded_string (v: STRING): STRING
-- base64 decoded value of `s'.
local
byte_count: INTEGER
pos, n: INTEGER
byte1, byte2, byte3, byte4, tmp1, tmp2: INTEGER
done: BOOLEAN
base64chars: STRING_8
c: CHARACTER
do
has_error := False
base64chars := character_map
n := v.count
create Result.make (n)
from
pos := 0
invariant
n = v.count
until
(pos >= n) or done
loop
byte_count := 0
pos := next_encoded_character_position (v, pos)
if pos <= n then
byte1 := base64chars.index_of (v[pos], 1) - 1
byte_count := byte_count + 1
pos := next_encoded_character_position (v, pos)
if pos <= n then
byte2 := base64chars.index_of (v[pos], 1) - 1
byte_count := byte_count + 1
pos := next_encoded_character_position (v, pos)
if pos <= n then
c := v[pos]
if c /= '=' then
byte3 := base64chars.index_of (c, 1) - 1
byte_count := byte_count + 1
end
pos := next_encoded_character_position (v, pos)
if pos <= n then
c := v[pos]
if c /= '=' then
byte4 := base64chars.index_of (c, 1) - 1
byte_count := byte_count + 1
end
end
end
end
end
-- pos := pos + byte_count
done := byte_count < 4
if byte_count > 1 then
tmp1 := byte1.bit_shift_left (2) & 0xff
tmp2 := byte2.bit_shift_right (4) & 0x03
Result.extend ((tmp1 | tmp2).to_character_8)
if byte_count > 2 then
tmp1 := byte2.bit_shift_left (4) & 0xff
tmp2 := byte3.bit_shift_right (2) & 0x0f
Result.extend ((tmp1 | tmp2).to_character_8)
if byte_count > 3 then
Result.extend(
((byte4 | byte3.bit_shift_left(6))& 0xff).to_character_8)
end
end
end
end
end
next_encoded_character_position (v: STRING; from_pos: INTEGER): INTEGER
-- Next encoded character position from `v' starting after `from_pos' index.
-- Result over `v.count' denodes no remaining decodable position
--| Mainly to handle base64 encoded text on multiple line
--| thus we just skip %N, %R and eventually all blanks
require
v_attached: v /= Void
valid_from_pos: v.valid_index (from_pos + 1)
local
n: INTEGER
l_map: like character_map
do
l_map := character_map
from
Result := from_pos + 1
n := v.count
until
in_character_map (v[Result]) or Result > n
loop
Result := Result + 1
end
ensure
result_after_from_pos: Result > from_pos
end
in_character_map (c: CHARACTER): BOOLEAN
-- Is a character map element?
do
inspect c
when 'A' .. 'Z', 'a' .. 'z', '0'..'9', '+', '/', '=' then
Result := True
else
end
end
feature {NONE} -- Constants
character_map: STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,73 @@
note
description: "Summary description for {ENCODER}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class
ENCODER [U -> STRING_GENERAL, E -> STRING_GENERAL] --| U:unencoded type, E:encoded type
feature -- Access
name: STRING
-- Encoding name.
deferred
end
feature -- Status report
has_error: BOOLEAN
-- Error occurred
deferred
end
feature -- Assertion helpers
valid_unencoded_string (s: U): BOOLEAN
-- Is `s' a valid unencoded string ?
do
Result := s /= Void
end
valid_encoded_string (v: E): BOOLEAN
-- Is `v' a valid encoded string ?
do
Result := v /= Void
end
feature -- Encoder
encoded_string (s: U): E
-- Encoded value of `s'.
require
valid_unencoded_string: valid_unencoded_string (s)
deferred
ensure
unchanged: s ~ (old s)
valid_encoded_string: valid_encoded_string (Result)
end
feature -- Decoder
decoded_string (v: E): U
-- Decoded value of `v'.
require
valid_encoded_string: valid_encoded_string (v)
deferred
ensure
unchanged: v ~ (old v)
valid_unencoded_string: valid_unencoded_string (Result)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,267 @@
note
description: "[
Summary description for {HTML_ENCODER}.
see: http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTML_ENCODER
inherit
ENCODER [STRING_32, STRING_8]
PLATFORM
export
{NONE} all
end
feature -- Access
name: STRING = "HTML-encoded"
feature -- Status report
has_error: BOOLEAN
feature -- Encoder
encoded_string (s: STRING_32): STRING_8
-- HTML-encoded value of `s'.
local
i, n: INTEGER
uc: CHARACTER_32
c: CHARACTER_8
do
has_error := False
create Result.make (s.count + s.count // 10)
n := s.count
from i := 1 until i > n loop
uc := s.item (i)
if uc.is_character_8 then
c := uc.to_character_8
inspect c
when '%"' then Result.append_string ("&quot;")
when '&' then Result.append_string ("&amp;")
when '%'' then Result.append_string ("&apos;")
when '<' then Result.append_string ("&lt;")
when '>' then Result.append_string ("&gt;")
else
Result.extend (c)
end
else
Result.append ("&#")
Result.append (uc.code.out)
Result.extend (';')
end
i := i + 1
end
end
feature -- Decoder
decoded_string (v: STRING_8): STRING_32
-- The HTML-encoded equivalent of the given string
local
i, n: INTEGER
c: CHARACTER
cl_i: CELL [INTEGER]
do
n := v.count
create Result.make (n)
create cl_i.put (0)
from i := 1 until i > n loop
c := v.item (i)
if c = '&' then
cl_i.replace (i)
Result.append_string (next_entity (v, cl_i))
i := cl_i.item
else
Result.append_character (c.to_character_32)
i := i + 1
end
end
end
feature {NONE} -- Implementation: decoder
next_entity (v: STRING_8; cl_i: CELL [INTEGER]): STRING_32
-- Return next entity value
-- move index
local
i: INTEGER
c: CHARACTER
is_char: BOOLEAN
is_hexa: BOOLEAN
s: STRING_32
do
i := cl_i.item
create s.make_empty
i := i + 1
c := v[i]
if c = '#' then
is_char := True
i := i + 1
c := v[i]
if c = 'x' then
is_hexa := True
i := i + 1
c := v[i]
end
end
if is_char then
if is_hexa then
from
until
not c.is_hexa_digit or c = ';'
loop
s.append_character (c)
i := i + 1
c := v[i]
end
else
from
until
not c.is_digit or c = ';'
loop
s.append_character (c)
i := i + 1
c := v[i]
end
end
else
from
until
not valid_entity_character (c) or c = ';'
loop
s.append_character (c)
i := i + 1
c := v[i]
end
end
if c = ';' then
if is_char then
if is_hexa then
-- not yet implemented
s.prepend_character ('x')
s.prepend_character ('#')
s.prepend_character ('&')
s.append_character (';')
Result := s
elseif s.is_integer then
create Result.make (1)
Result.append_code (s.to_natural_32)
else
s.prepend_character ('&')
s.append_character (';')
Result := s
end
else
resolve_entity (s)
Result := s
end
cl_i.replace (i + 1)
else
cl_i.replace (cl_i.item + 1)
s.prepend_character ('&')
has_error := True -- ("Invalid entity syntax " + s)
Result := s
end
end
resolve_entity (s: STRING_32)
-- Resolve `s' as an entity
--| Hardcoding the xml entities &quot; &amp; &apos; &lt; and &gt;
require
s_attached: s /= Void
local
l_resolved: BOOLEAN
do
inspect s[1].as_lower
when 'a' then
if
s.count = 3 and then
s[2].as_lower = 'm' and then
s[3].as_lower = 'p'
then -- &amp;
l_resolved := True
s.wipe_out
s.append_character ('&')
elseif -- &apos;
s.count = 4 and then
s[2].as_lower = 'p' and then
s[3].as_lower = 'o' and then
s[4].as_lower = 's'
then
l_resolved := True
s.wipe_out
s.append_character ('%'')
end
when 'q' then
if
s.count = 4 and then
s[2].as_lower = 'u' and then
s[3].as_lower = 'o' and then
s[4].as_lower = 't'
then -- &quot;
l_resolved := True
s.wipe_out
s.append_character ('%"')
end
when 'l' then
if
s.count = 2 and then
s[2].as_lower = 't'
then -- &quot;
l_resolved := True
s.wipe_out
s.append_character ('<')
end
when 'g' then
if
s.count = 2 and then
s[2].as_lower = 't'
then -- &quot;
l_resolved := True
s.wipe_out
s.append_character ('>')
end
else
end
if not l_resolved then
s.prepend_character ('&')
s.append_character (';')
end
end
valid_entity_character (c: CHARACTER): BOOLEAN
-- Is `c' a valid character in html entity value?
--| such as &amp;
do
inspect
c
when 'a'..'z' then
Result := True
when 'A'..'Z' then
Result := True
when '0'..'9' then
Result := True
else
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,321 @@
note
description: "Summary description for {URL_ENCODER}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
URL_ENCODER
inherit
ENCODER [STRING_32, STRING_8]
PLATFORM
export
{NONE} all
end
feature -- Access
name: STRING = "URL-encoded"
feature -- Status report
has_error: BOOLEAN
feature -- Encoder
encoded_string (s: STRING_32): STRING_8
-- URL-encoded value of `s'.
local
i, n: INTEGER
uc: CHARACTER_32
c: CHARACTER_8
do
has_error := False
create Result.make (s.count + s.count // 10)
n := s.count
from i := 1 until i > n loop
uc := s.item (i)
if uc.is_character_8 then
c := uc.to_character_8
inspect c
when
'A' .. 'Z',
'a' .. 'z', '0' .. '9',
'.', '-', '~', '_'
then
Result.extend (c)
when ' ' then
Result.extend ('+')
else
Result.append (url_encoded_char (uc))
end
else
Result.append (url_encoded_char (uc))
end
i := i + 1
end
end
feature {NONE} -- encoder character
url_encoded_char (uc: CHARACTER_32): STRING_8
do
create Result.make (3)
if uc.is_character_8 then
Result.extend ('%%')
Result.append (uc.code.to_hex_string)
from
until
Result.count < 2 or else Result[2] /= '0'
loop
Result.remove (2)
end
else
has_error := True --| Non-ascii escape not currently supported
end
ensure
exists: Result /= Void
end
feature -- Decoder
decoded_string (v: STRING_8): STRING_32
-- The URL-encoded equivalent of the given string
local
i, n: INTEGER
c: CHARACTER
pr: CELL [INTEGER]
do
n := v.count
create Result.make (n)
from i := 1
until i > n
loop
c := v.item (i)
inspect c
when '+' then
Result.append_character ({CHARACTER_32}' ')
when '%%' then
-- An escaped character ?
if i = n then
Result.append_character (c.to_character_32)
else
create pr.put (i)
Result.append (url_decoded_char (v, pr))
i := pr.item
end
else
Result.append_character (c.to_character_32)
end
i := i + 1
end
end
feature {NONE} -- decoded character
url_decoded_char (buf: STRING_8; posr: CELL [INTEGER]): STRING_32
-- Character(s) resulting from decoding the URL-encoded string
require
stream_exists: buf /= Void
posr_exists: posr /= Void
valid_start: posr.item <= buf.count
local
c: CHARACTER
i, n, nb: INTEGER
not_a_digit: BOOLEAN
ascii_pos, ival: INTEGER
pos: INTEGER
do
--| pos is index in stream of escape character ('%')
pos := posr.item
create Result.make (4)
if buf.item (pos + 1) = 'u' then
-- An escaped Unicode (ucs2) value, from ECMA scripts
-- Has the form: %u<n> where <n> is the UCS value
-- of the character (two byte integer, one to 4 chars
-- after escape sequence).
-- UTF-8 result can be 1 to 4 characters
n := buf.count
from i := pos + 2
until (i > n) or not_a_digit
loop
c := buf.item (i)
if c.is_hexa_digit then
ival := ival * 16
if c.is_digit then
ival := ival + (c |-| '0')
else
ival := ival + (c.upper |-| 'A') + 10
end
i := i + 1
else
not_a_digit := True
end
end
posr.replace (i)
-- ival is now UCS2 value; needs conversion to UTF8
Result.append_code (ival.as_natural_32)
nb := utf8_bytes_in_sequence (buf, pos)
else
-- ASCII char?
ascii_pos := hex_to_integer_32 (buf.substring (pos+1, pos+2))
if ascii_pos >= 0x80 and ascii_pos <= 0xff then
-- Might be improperly escaped
Result.append_code (ascii_pos.as_natural_32)
posr.replace (pos + 2)
else
Result.append_code (ascii_pos.as_natural_32)
posr.replace (pos + 2)
end
end
ensure
exists: Result /= Void
end
feature {NONE} -- UTF8
utf8_bytes_in_sequence (s: STRING_8; spos: INTEGER): INTEGER
-- If the given character is a legal first byte element in a
-- utf8 byte sequence (aka character), then return the number
-- of bytes in that sequence
-- Result of zero means it's not a utf8 first byte
require
exists: s /= Void
long_enough: s.count >= spos
do
Result := bytes_in_utf8_char (s.item (spos))
end
bytes_in_utf8_char (v: CHARACTER_8): INTEGER
-- If the given byte a legal first byte element in a utf8 sequence,
-- then the number of bytes in that character
-- Zero denotes an error, i.e. not a legal UTF8 char
--
-- The first byte of a UTF8 encodes the length
local
c: NATURAL_8
do
c := v.code.to_natural_8
Result := 1 -- 7 bit ASCII
if (c & 0x80) /= 0 then
-- Hi bit means not ASCII
Result := 0
if (c & 0xe0) = 0xc0 then
-- If we see a first byte as b110xxxxx
-- then we expect a two-byte character
Result := 2
elseif (c & 0xf0) = 0xe0 then
-- If we see a first byte as b1110xxxx
-- then we expect a three-byte character
Result := 3
elseif (c & 0xf8) = 0xf0 then
-- If we see a first byte as b11110xxx
-- then we expect a four-byte character
Result := 4
elseif (c & 0xfc) = 0xf8 then
-- If we see a first byte as b111110xx
-- then we expect a five-byte character
Result := 5
elseif (c & 0xfe) = 0xfc then
-- If we see a first byte as b1111110x
-- then we expect a six-byte character
Result := 6
end
end
end
feature {NONE} -- Hexadecimal and strings
hex_to_integer_32 (s: STRING): INTEGER_32
-- Hexadecimal string `s' converted to INTEGER_32 value
require
s_not_void: s /= Void
local
i, nb: INTEGER;
char: CHARACTER
do
nb := s.count
if nb >= 2 and then s.item (2) = 'x' then
i := 3
else
i := 1
end
from
until
i > nb
loop
Result := Result * 16
char := s.item (i)
if char >= '0' and then char <= '9' then
Result := Result + (char |-| '0')
else
Result := Result + (char.lower |-| 'a' + 10)
end
i := i + 1
end
end
hex_to_integer_64 (s: STRING): INTEGER_64
-- Hexadecimal string `s' converted to INTEGER_64 value
require
s_not_void: s /= Void
local
i, nb: INTEGER;
char: CHARACTER
do
nb := s.count
if nb >= 2 and then s.item (2) = 'x' then
i := 3
else
i := 1
end
from
until
i > nb
loop
Result := Result * 16
char := s.item (i)
if char >= '0' and then char <= '9' then
Result := Result + (char |-| '0')
else
Result := Result + (char.lower |-| 'a' + 10)
end
i := i + 1
end
end
hex_to_pointer (s: STRING): POINTER
-- Hexadecimal string `s' converted to POINTER value
require
s_not_void: s /= Void
local
val_32: INTEGER_32
val_64: INTEGER_64
do
if Pointer_bytes = Integer_64_bytes then
val_64 := hex_to_integer_64 (s)
($Result).memory_copy ($val_64, Pointer_bytes)
else
val_32 := hex_to_integer_32 (s)
($Result).memory_copy ($val_32, Pointer_bytes)
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,267 @@
note
description: "[
Summary description for {XML_ENCODER}.
see: http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
XML_ENCODER
inherit
ENCODER [STRING_32, STRING_8]
PLATFORM
export
{NONE} all
end
feature -- Access
name: STRING = "XML-encoded"
feature -- Status report
has_error: BOOLEAN
feature -- Encoder
encoded_string (s: STRING_32): STRING_8
-- XML-encoded value of `s'.
local
i, n: INTEGER
uc: CHARACTER_32
c: CHARACTER_8
do
has_error := False
create Result.make (s.count + s.count // 10)
n := s.count
from i := 1 until i > n loop
uc := s.item (i)
if uc.is_character_8 then
c := uc.to_character_8
inspect c
when '%"' then Result.append_string ("&quot;")
when '&' then Result.append_string ("&amp;")
when '%'' then Result.append_string ("&apos;")
when '<' then Result.append_string ("&lt;")
when '>' then Result.append_string ("&gt;")
else
Result.extend (c)
end
else
Result.append ("&#")
Result.append (uc.code.out)
Result.extend (';')
end
i := i + 1
end
end
feature -- Decoder
decoded_string (v: STRING_8): STRING_32
-- The XML-encoded equivalent of the given string
local
i, n: INTEGER
c: CHARACTER
cl_i: CELL [INTEGER]
do
n := v.count
create Result.make (n)
create cl_i.put (0)
from i := 1 until i > n loop
c := v.item (i)
if c = '&' then
cl_i.replace (i)
Result.append_string (next_entity (v, cl_i))
i := cl_i.item
else
Result.append_character (c.to_character_32)
i := i + 1
end
end
end
feature {NONE} -- Implementation: decoder
next_entity (v: STRING_8; cl_i: CELL [INTEGER]): STRING_32
-- Return next entity value
-- move index
local
i: INTEGER
c: CHARACTER
is_char: BOOLEAN
is_hexa: BOOLEAN
s: STRING_32
do
i := cl_i.item
create s.make_empty
i := i + 1
c := v[i]
if c = '#' then
is_char := True
i := i + 1
c := v[i]
if c = 'x' then
is_hexa := True
i := i + 1
c := v[i]
end
end
if is_char then
if is_hexa then
from
until
not c.is_hexa_digit or c = ';'
loop
s.append_character (c)
i := i + 1
c := v[i]
end
else
from
until
not c.is_digit or c = ';'
loop
s.append_character (c)
i := i + 1
c := v[i]
end
end
else
from
until
not valid_entity_character (c) or c = ';'
loop
s.append_character (c)
i := i + 1
c := v[i]
end
end
if c = ';' then
if is_char then
if is_hexa then
-- not yet implemented
s.prepend_character ('x')
s.prepend_character ('#')
s.prepend_character ('&')
s.append_character (';')
Result := s
elseif s.is_integer then
create Result.make (1)
Result.append_code (s.to_natural_32)
else
s.prepend_character ('&')
s.append_character (';')
Result := s
end
else
resolve_entity (s)
Result := s
end
cl_i.replace (i + 1)
else
cl_i.replace (cl_i.item + 1)
s.prepend_character ('&')
has_error := True -- ("Invalid entity syntax " + s)
Result := s
end
end
resolve_entity (s: STRING_32)
-- Resolve `s' as an entity
--| Hardcoding the xml entities &quot; &amp; &apos; &lt; and &gt;
require
s_attached: s /= Void
local
l_resolved: BOOLEAN
do
inspect s[1].as_lower
when 'a' then
if
s.count = 3 and then
s[2].as_lower = 'm' and then
s[3].as_lower = 'p'
then -- &amp;
l_resolved := True
s.wipe_out
s.append_character ('&')
elseif -- &apos;
s.count = 4 and then
s[2].as_lower = 'p' and then
s[3].as_lower = 'o' and then
s[4].as_lower = 's'
then
l_resolved := True
s.wipe_out
s.append_character ('%'')
end
when 'q' then
if
s.count = 4 and then
s[2].as_lower = 'u' and then
s[3].as_lower = 'o' and then
s[4].as_lower = 't'
then -- &quot;
l_resolved := True
s.wipe_out
s.append_character ('%"')
end
when 'l' then
if
s.count = 2 and then
s[2].as_lower = 't'
then -- &quot;
l_resolved := True
s.wipe_out
s.append_character ('<')
end
when 'g' then
if
s.count = 2 and then
s[2].as_lower = 't'
then -- &quot;
l_resolved := True
s.wipe_out
s.append_character ('>')
end
else
end
if not l_resolved then
s.prepend_character ('&')
s.append_character (';')
end
end
valid_entity_character (c: CHARACTER): BOOLEAN
-- Is `c' a valid character in html entity value?
--| such as &amp;
do
inspect
c
when 'a'..'z' then
Result := True
when 'A'..'Z' then
Result := True
when '0'..'9' then
Result := True
else
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,49 @@
note
description: "[
Eiffel tests that can be executed by testing tool.
]"
author: "EiffelStudio test wizard"
date: "$Date$"
revision: "$Revision$"
testing: "type/manual"
class
TEST_BASE64
inherit
EQA_TEST_SET
feature -- Test routines
test_base64_encoder
note
testing: "base64"
do
test_base64_encoding ("Il <20>tait une fois !")
end
test_base64_encoding (s: STRING_8)
local
u: STRING_8
e: STRING_8
b: BASE64
do
create b
e := b.encoded_string (s)
u := b.decoded_string (e)
assert ("decoded encoded string is same", u ~ s)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,49 @@
note
description: "[
Eiffel tests that can be executed by testing tool.
]"
author: "EiffelStudio test wizard"
date: "$Date$"
revision: "$Revision$"
testing: "type/manual"
class
TEST_URL_ENCODER
inherit
EQA_TEST_SET
feature -- Test routines
test_url_encoded_encoder
note
testing: "url-encoded"
do
test_url_encoded_encoding ("http://domain.tld/foo/bar/script.php?test='toto'&foo=bar&title=il <20>tait une fois")
end
test_url_encoded_encoding (s: STRING_32)
local
u: STRING_32
e: STRING_8
b: URL_ENCODER
do
create b
e := b.encoded_string (s)
u := b.decoded_string (e)
assert ("decoded encoded string is same", u ~ s)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

Some files were not shown because too many files have changed in this diff Show More