Moved mime handler classes under wsf/src/mime/

This commit is contained in:
Jocelyn Fiat
2012-03-20 08:38:38 +01:00
parent 3f0b745ecc
commit 71d5dc4795
3 changed files with 0 additions and 0 deletions
@@ -0,0 +1,74 @@
note
description: "Summary description for {WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER
inherit
WSF_MIME_HANDLER
WSF_MIME_HANDLER_HELPER
feature -- Status report
valid_content_type (a_content_type: READABLE_STRING_8): BOOLEAN
do
Result := a_content_type.same_string ({HTTP_MIME_TYPES}.application_x_www_form_encoded)
end
feature -- Execution
handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST;
a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8])
local
l_content: READABLE_STRING_8
n, p, i, j: INTEGER
s: READABLE_STRING_8
l_name, l_value: READABLE_STRING_8
do
l_content := full_input_data (req)
if a_raw_data /= Void then
a_raw_data.replace (l_content)
end
check content_count_same_as_content_length_if_not_chunked: (not req.is_chunked_input) implies (l_content.count = req.content_length_value.to_integer_32) end --| FIXME: truncated value
n := l_content.count
if n > 0 then
from
p := 1
until
p = 0
loop
i := l_content.index_of ('&', p)
if i = 0 then
s := l_content.substring (p, n)
p := 0
else
s := l_content.substring (p, i - 1)
p := i + 1
end
if not s.is_empty then
j := s.index_of ('=', 1)
if j > 0 then
l_name := s.substring (1, j - 1)
l_value := s.substring (j + 1, s.count)
add_string_value_to_table (l_name, l_value, a_vars)
end
end
end
end
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
@@ -0,0 +1,37 @@
note
description: "Summary description for {WSF_MIME_HANDLER}."
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_MIME_HANDLER
feature -- Status report
valid_content_type (a_content_type: READABLE_STRING_8): BOOLEAN
deferred
end
feature -- Execution
handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST;
a_vars: TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8])
-- Handle MIME content from request `req', eventually fill the `a_vars' (not yet available from `req')
-- and if `a_raw_data' is attached, store any read data inside `a_raw_data'
require
valid_content_type: valid_content_type (a_content_type)
deferred
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
@@ -0,0 +1,259 @@
note
description: "Summary description for {WSF_MULTIPART_FORM_DATA_HANDLER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_MULTIPART_FORM_DATA_HANDLER
inherit
WSF_MIME_HANDLER
WSF_MIME_HANDLER_HELPER
create
make
feature {NONE} -- Initialization
make (a_err_handler: like error_handler)
-- Instantiate Current
do
error_handler := a_err_handler
end
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 -- Status report
valid_content_type (a_content_type: READABLE_STRING_8): BOOLEAN
do
Result := a_content_type.starts_with ({HTTP_MIME_TYPES}.multipart_form_data)
end
feature -- Execution
handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST;
a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8])
local
s: like full_input_data
do
s := full_input_data (req)
if a_raw_data /= Void then
a_raw_data.replace (s)
end
--| FIXME: optimization ... fetch the input data progressively, otherwise we might run out of memory ...
analyze_multipart_form (req, a_content_type, s, a_vars)
end
feature {NONE} -- Implementation: Form analyzer
analyze_multipart_form (req: WSF_REQUEST; t: READABLE_STRING_8; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32])
-- 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 (req, 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 (req: WSF_REQUEST; s: STRING; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32])
-- 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_8
l_header: detachable STRING_8
l_content: detachable STRING_8
l_line: detachable STRING_8
l_up_file: WSF_UPLOADED_FILE
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 and then not l_filename.is_empty then
if l_content_type = Void then
l_content_type := default_content_type
end
create l_up_file.make (l_name, l_filename, l_content_type, l_content.count)
add_value_to_table (l_name, l_up_file, vars)
--| `l_up_file' might have a new name
req.save_uploaded_file (l_up_file, l_content)
else
add_string_value_to_table (l_name, l_content, vars)
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
default_content_type: STRING = "text/plain"
-- Default content type
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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