Fixed error in previous commits.

This commit is contained in:
2020-10-02 15:35:00 +02:00
parent 37644e66bb
commit 14e85932a9
2 changed files with 46 additions and 236 deletions

View File

@@ -1,262 +1,70 @@
note
description: "Summary description for {WSF_MULTIPART_FORM_DATA_HANDLER}."
description: "Summary description for {WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER}."
date: "$Date$"
revision: "$Revision$"
class
WSF_MULTIPART_FORM_DATA_HANDLER
WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER
inherit
WSF_MIME_HANDLER
WSF_MIME_HANDLER_HELPER
create
make
feature {NONE} -- Initialization
make
-- Instantiate Current
do
WSF_VALUE_UTILITIES
export
{NONE} all
end
feature -- Status report
valid_content_type (a_content_type: HTTP_CONTENT_TYPE): BOOLEAN
do
Result := a_content_type.same_simple_type ({HTTP_MIME_TYPES}.multipart_form_data)
Result := a_content_type.same_simple_type ({HTTP_MIME_TYPES}.application_x_www_form_encoded)
end
feature -- Execution
handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST;
a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]; a_raw_data: detachable CELL [detachable READABLE_STRING_8])
a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]; a_raw_data: detachable CELL [detachable READABLE_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
s := full_input_data (req)
l_content := full_input_data (req)
if a_raw_data /= Void then
a_raw_data.replace (s)
a_raw_data.replace (l_content)
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; a_content_type: HTTP_CONTENT_TYPE; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
-- Analyze multipart form content
--| FIXME[2011-06-21]: integrate eMIME parser library
require
a_content_type_valid: a_content_type /= Void and not a_content_type.has_error
s_attached: s /= Void
same_content_length: req.content_length_value > 0 implies req.content_length_value.as_integer_32 <= s.count
vars_attached: vars /= Void
local
p,i,next_b: INTEGER
l_boundary_prefix: READABLE_STRING_8
l_boundary_len: INTEGER
l_boundary: detachable READABLE_STRING_8
m: READABLE_STRING_8
tmp: STRING_8
is_crlf: BOOLEAN
do
l_boundary := a_content_type.parameter ("boundary")
if l_boundary /= Void and then not l_boundary.is_empty then
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
l_boundary_prefix := ""
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'
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
i := 1 + l_boundary_len + 1
if is_crlf then
i := i + 1 --| +1 = CR = %R
end
next_b := i
p := 1
until
i = 0
p = 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)
if s.valid_index (next_b + l_boundary_len + 1) then
if is_crlf then
if s[next_b + l_boundary_len] = '%R' and s[next_b + l_boundary_len + 1] = '%N' then
-- continue
else
i := 0 -- reached the end
end
else
if s[next_b + l_boundary_len + 1] = '%N' then
-- continue
else
i := 0 -- reached the end
end
end
else
i := 0 -- missing end ?
req.error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input")
end
if i > 0 then
i := next_b + l_boundary_len + 1
if is_crlf then
i := i + 1 --| +1 = CR = %R
end
end
i := l_content.index_of ('&', p)
if i = 0 then
s := l_content.substring (p, n)
p := 0
else
if is_crlf then
i := i + 1
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_percent_encoded_string_value_to_table (l_name, l_value, a_vars)
end
tmp := s.substring (i - 1, s.count).to_string_8
tmp.right_adjust
-- TODO: check if next condition should not use tmp instead of s
if i >= s.count and not l_boundary_prefix.same_string (tmp) then
req.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: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
-- 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 READABLE_STRING_8
l_unicode_name: READABLE_STRING_32
l_header: detachable READABLE_STRING_8
l_content: detachable READABLE_STRING_8
l_line: detachable READABLE_STRING_8
l_up_file: WSF_UPLOADED_FILE
utf: UTF_CONVERTER
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
l_unicode_name := utf.utf_8_string_8_to_string_32 (l_name)
create l_up_file.make (l_unicode_name, utf.utf_8_string_8_to_escaped_string_32 (l_filename), l_content_type, l_content.count)
add_value_to_table (l_unicode_name, l_up_file, vars)
--| `l_up_file' might have a new name
req.save_uploaded_file (l_up_file, l_content)
else
add_utf_8_string_value_to_table (l_name, l_content, vars)
end
else
req.error_handler.add_custom_error (0, "unamed multipart entry", Void)
end
else
req.error_handler.add_custom_error (0, "missformed multipart entry", Void)
end
end
default_content_type: STRING = "text/plain"
-- Default content type
note
copyright: "2011-2020, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -55,10 +55,11 @@ feature {NONE} -- Implementation: Form analyzer
vars_attached: vars /= Void
local
p,i,next_b: INTEGER
l_boundary_prefix: STRING
l_boundary_prefix: READABLE_STRING_8
l_boundary_len: INTEGER
l_boundary: detachable READABLE_STRING_8
m: STRING
m: READABLE_STRING_8
tmp: STRING_8
is_crlf: BOOLEAN
do
l_boundary := a_content_type.parameter ("boundary")
@@ -68,13 +69,13 @@ feature {NONE} -- Implementation: Form analyzer
l_boundary_prefix := s.substring (1, p - 1)
l_boundary := l_boundary_prefix + l_boundary
else
create l_boundary_prefix.make_empty
l_boundary_prefix := ""
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'
is_crlf := s [l_boundary_len + 1] = '%R'
from
i := 1 + l_boundary_len + 1
if is_crlf then
@@ -120,9 +121,10 @@ feature {NONE} -- Implementation: Form analyzer
if is_crlf then
i := i + 1
end
m := s.substring (i - 1, s.count)
m.right_adjust
if i >= s.count and not l_boundary_prefix.same_string (m) then
tmp := s.substring (i - 1, s.count).to_string_8
tmp.right_adjust
-- TODO: check if next condition should not use tmp instead of s
if i >= s.count and not l_boundary_prefix.same_string (tmp) then
req.error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input")
end
i := next_b
@@ -131,17 +133,17 @@ feature {NONE} -- Implementation: Form analyzer
end
end
analyze_multipart_form_input (req: WSF_REQUEST; s: STRING; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
analyze_multipart_form_input (req: WSF_REQUEST; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
-- 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_name, l_filename, l_content_type: detachable READABLE_STRING_8
l_unicode_name: READABLE_STRING_32
l_header: detachable STRING_8
l_content: detachable STRING_8
l_line: detachable STRING_8
l_header: detachable READABLE_STRING_8
l_content: detachable READABLE_STRING_8
l_line: detachable READABLE_STRING_8
l_up_file: WSF_UPLOADED_FILE
utf: UTF_CONVERTER
do
@@ -256,7 +258,7 @@ feature {NONE} -- Implementation: Form analyzer
-- Default content type
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software