1. Get images or binary files from web form

Hello all!

I am trying to do an web form where the people send me some text fields and 2 or 3 photos.

How can a cgi-bin to process this? I can get successly text files, but binary files don't work. (XAMPP on Windows 7 machine).

Any hint?

This is my first experiment:

<html><head></head><body> 
 
<form method="post" action="/cgi-bin/prueba.cgi" enctype="multipart/form-data"> 
	Your text: <input name="primero" /> 
	<br>	 
	Your file: <input type="file" name="imagen" accept="image/png, .jpeg, .jpg, image/gif"> 
	<br> 
	<input type="submit" /> 
</form> 
 
</body></html> 
 

This is the prueba.cgi, based on cgitest file I have take and modified from examples on the archive:

#!eui 
-- test program for euphoria cgi 
-- comment/uncomment the following to test the EUINC variable 
 
with batch 
 
include std/io.e 
include std/pretty.e 
sequence cmd 
 
-- if val is a string, return it, otherwise "Undefined" 
function test_val(object val) 
    if atom(val) then 
        return "Undefined" 
    elsif object(val) then 
        for i = 1 to length(val) do 
            if not atom(val[i]) then 
                return "Invalid string sequence" 
            end if 
        end for 
        return val 
    else 
        return "Invalid type for string" 
    end if 
    return "foozle" -- never reached 
end function 
 
 
procedure env_dump(sequence val) 
     printf(1, "%s: %s\n", {val, test_val(getenv(val))} ) 
end procedure 
 
puts(1, "Content-Type: text/plain\n\n") 
puts(1, "Hello!\n\n") 
puts(1, "COMMAND LINE\n============\n\n") 
 
cmd = command_line() 
for i = 1 to length(cmd) do 
    printf(1, "%d: %s\n", {i, cmd[i]} ) 
end for 
 
puts(1, "\n\nREMOTE INFO\n===========\n") 
 
env_dump("REMOTE_IDENT") 
env_dump("REMOTE_USER") 
env_dump("REMOTE_HOST") 
env_dump("REMOTE_ADDR") 
 
puts(1, "\n\nSERVER INFO\n===========\n") 
env_dump("SERVER_SOFTWARE") 
env_dump("SERVER_NAME") 
env_dump("GATEWAY_INTERFACE") 
env_dump("SERVER_PROTOCOL") 
env_dump("SERVER_PORT") 
env_dump("REQUEST_METHOD") 
env_dump("PATH_INFO") 
env_dump("PATH_TRANSLATED") 
env_dump("SCRIPT_NAME") 
env_dump("QUERY_STRING") 
env_dump("AUTH_TYPE") 
env_dump("CONTENT_TYPE") 
env_dump("CONTENT_LENGTH") 
 
puts(1, "\n\nBROWSER INFO\n============\n") 
env_dump("HTTP_ACCEPT") 
env_dump("HTTP_USER_AGENT") 
 
puts(1, "\n\nSTANDAR INPUT\n=============\n") 
sequence whole_file 
whole_file = {} 
sequence chunk 
while 1 do 
	chunk = get_bytes(0, 1024) -- read 100 bytes at a time 
	whole_file &= chunk 
	-- chunk might be empty, that's ok 
	if length(chunk) < 1024 then 
		exit 
	end if 
end while 
 
print(1, whole_file) 
printf(1, "\n\nEl archivo recibido tiene %d bytes\n\n", {length(whole_file)}) 
-- should match DIR size of "temp" 
 
puts(1, whole_file) 
new topic     » topic index » view message » categorize

2. Re: Get images or binary files from web form

I have a question for the people involved on the interpreter design.

To get files in the POST method. The file is received trough the standar input.

Can the interpreter to manage if the standar input has "binary" info. Like 00 bytes? Or is the information filtered by the interpreter prior to arrive to my app?

new topic     » goto parent     » topic index » view message » categorize

3. Re: Get images or binary files from web form

After more testing, on linux hosting appear to work OK.

Appear to be a bug on the windows. Not sure if from Windows itself, or our interpreter, or the C libraries used to compile it ¿¿Who knows??

But PHP on windows without problems to get binaries, so is possible to workaround.

I upload the same image at my windows localhost and at linux remote hosting. Noted that the standar input stream breaks when Windows received a character 001A (Ctrl-Z) So the windows interpreter take it as the end of the stream.

Screeshot comparing WINDOWS and Linux output: https://www.facebook.com/photo?fbid=10228785197921746

You can test at: http://quienfabrica.co/formulario.html

The same is reported for other languages: https://stackoverflow.com/questions/61460004/why-ascii-sub-u001a-is-ignored-in-java

My current code:

#!eui 
-- test program for euphoria cgi 
-- comment/uncomment the following to test the EUINC variable 
 
with batch 
 
include std/io.e 
include std/pretty.e 
include std/get.e 
sequence cmd 
 
-- if val is a string, return it, otherwise "Undefined" 
function test_val(object val) 
    if atom(val) then 
        return "Undefined" 
    elsif object(val) then 
        for i = 1 to length(val) do 
            if not atom(val[i]) then 
                return "Invalid string sequence" 
            end if 
        end for 
        return val 
    else 
        return "Invalid type for string" 
    end if 
    return "foozle" -- never reached 
end function 
 
 
procedure env_dump(sequence val) 
     printf(1, "%s: %s\n", {val, test_val(getenv(val))} ) 
end procedure 
 
puts(1, "Content-Type: text/plain\n\n") 
puts(1, "Hello!\n\n") 
puts(1, "COMMAND LINE\n============\n\n") 
 
cmd = command_line() 
for i = 1 to length(cmd) do 
    printf(1, "%d: %s\n", {i, cmd[i]} ) 
end for 
 
puts(1, "\n\nREMOTE INFO\n===========\n") 
 
env_dump("REMOTE_IDENT") 
env_dump("REMOTE_USER") 
env_dump("REMOTE_HOST") 
env_dump("REMOTE_ADDR") 
 
puts(1, "\n\nSERVER INFO\n===========\n") 
env_dump("SERVER_SOFTWARE") 
env_dump("SERVER_NAME") 
env_dump("GATEWAY_INTERFACE") 
env_dump("SERVER_PROTOCOL") 
env_dump("SERVER_PORT") 
env_dump("REQUEST_METHOD") 
env_dump("PATH_INFO") 
env_dump("PATH_TRANSLATED") 
env_dump("SCRIPT_NAME") 
env_dump("QUERY_STRING") 
env_dump("AUTH_TYPE") 
env_dump("CONTENT_TYPE") 
env_dump("CONTENT_LENGTH") 
	 
puts(1, "\n\nBROWSER INFO\n============\n") 
env_dump("HTTP_ACCEPT") 
env_dump("HTTP_USER_AGENT") 
 
flush(1) 
 
puts(1, "\n\nSTANDAR INPUT\n=============\n") 
 
object content_size 
sequence std_input = {} 
object char 
 
content_size = getenv("CONTENT_LENGTH") 
puts(1, "Content_size: ") 
print(1, content_size) 
if atom(content_size) then  -- content length no definido 
	puts(1, "\nNo standar input\n\n") 
	abort(0) 
elsif sequence(content_size) then 
	object j = value(content_size) 
	puts(1, "\nj= ")? j 
	if j[1] = 0 then --value() => GET_SUCESS 
		puts(1, "CONTENT_LENGTH: ") 
		? j[2] 
		for i=1 to j[2] do 
			char = getc(0) 
			std_input = append(std_input, char) 
			puts(1, char) 
		end for 
		puts(1,"\n\n") 
		print(1, std_input) 
		--puts(1, "\n") 
 
	end if 
else  -- Unexpected error 
	puts(1, "There is something strange about CONTENT_LENGTH\n\n") 
	abort(0) 
end if 
 
print(1, std_input) 
--puts(1, "\n") 
 
printf(1, "\nEntrada estandar recibida tiene %d bytes", {content_size}) 
 
new topic     » goto parent     » topic index » view message » categorize

4. Re: Get images or binary files from web form

On Euphoria 3.1 for windows works!

But the Ctrl-Z character are replace with -1, but the stream continues. So you can simply search for -1 and replace with 26 on the sequence.

Anyway, this code is painfully slow.

Really someone use euphoria for cgi-bin? How use POST method?

new topic     » goto parent     » topic index » view message » categorize

5. Re: Get images or binary files from web form

Wouldn't allow_break(0) do the job (in std/console.e)?

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

6. Re: Get images or binary files from web form

Maybe also:

  sequence nBytes = getenv("CONTENT_LENGTH") 
  sequence query = get_bytes(0, to_number(nBytes)) 
new topic     » goto parent     » topic index » view message » categorize

7. Re: Get images or binary files from web form

Thanks for your reply.

I have just tested. But the output is the same. No matter the size of the archive, is trunked when received the EOF character.

new topic     » goto parent     » topic index » view message » categorize

8. Re: Get images or binary files from web form

Here is my test program that works:

-- test program for euphoria cgi 
 
include std/filesys.e 
include std/convert.e 
include std/io.e 
include std/net/url.e 
 
function test_variable(sequence variable) 
  object val = getenv(variable) 
  -- if val is a string, return it, otherwise "Undefined" 
  if atom(val) then 
    return "Undefined" 
  elsif object(val) then 
    for i = 1 to length(val) do 
      if not atom(val[i]) then 
        return "Invalid string sequence" 
      end if 
    end for 
    return val 
  else 
    return "Invalid type for string" 
  end if 
  return "foozle" -- never reached 
end function 
 
procedure print_variable(sequence val) 
  printf(1, "%s: %s\n", {val, test_variable(val)} ) 
end procedure 
 
procedure main(sequence cmd) 
  sequence dt = date() 
  sequence path = test_variable("SCRIPT_FILENAME")  -- PATH_TRANSLATED on Apache2 
  sequence webDir = dirname(path) 
  sequence script = filebase(path) 
 
  sequence query, method 
  object nBytes 
 
  puts(1, "Content-Type: text/plain\n\n") 
 
  puts(1, "COMMAND LINE\n============\n\n") 
 
  for i = 1 to length(cmd) do 
    printf(1, "%d: %s\n", {i, cmd[i]} ) 
  end for 
 
  puts(1, "\n\nREMOTE INFO\n===========\n") 
 
  print_variable("REMOTE_ADDR") 
  print_variable("REMOTE_HOST") 
  print_variable("REMOTE_HOST") 
  print_variable("REMOTE_PORT") 
  print_variable("REMOTE_IDENT") 
 
  puts(1, "\n\nSERVER INFO\n===========\n") 
  print_variable("SERVER_ADMIN") 
  print_variable("SERVER_NAME") 
  print_variable("GATEWAY_INTERFACE") 
  print_variable("SERVER_PROTOCOL") 
  print_variable("SERVER_PORT") 
  print_variable("SERVER_SOFTWARE") 
  print_variable("SERVER_SIGNATURE") 
  method = test_variable("REQUEST_METHOD") 
  printf(1, "%s: %s\n", {"REQUEST_METHOD", method} ) 
  print_variable("SESSION_PATH") 
  print_variable("PATH") 
  print_variable("PATH_INFO") 
  print_variable("REQUEST_SCHEME") 
  print_variable("REQUEST_URI") 
  print_variable("DOCUMENT_URI") 
  print_variable("PATH_TRANSLATED") 
  print_variable("SCRIPT_NAME") 
  print_variable("SCRIPT_FILENAME") 
  if equal(method, "GET") then 
    -- print_variable("QUERY_STRING") 
    query = decode(test_variable("QUERY_STRING")) 
    printf(1, "%s: %s\n", {"QUERY_STRING", query} ) 
  else 
    nBytes = getenv("CONTENT_LENGTH") 
    query = get_bytes(0, to_number(nBytes)) 
    printf(1, "%s: %s\n", {"BODY", query} ) 
  end if 
  print_variable("AUTH_TYPE") 
  print_variable("CONTENT_TYPE") 
  print_variable("CONTENT_LENGTH") 
  print_variable("DOCUMENT_ROOT") 
 
  puts(1, "\n\nBROWSER INFO\n=============\n") 
  print_variable("HTTP_ACCEPT") 
  print_variable("HTTP_USER_AGENT") 
  print_variable("HTTP_COOKIE") 
  print_variable("HTTP_HOST") 
  print_variable("HTTP_REFERER") 
  print_variable("HTTPS") 
end procedure 
 
main(command_line()) 

Here is the answer to a POST request when sending a Zip file:

COMMAND LINE 
============ 
 
1: C:\My Program Files\euphoria4.1\bin\eui.exe 
2: C:/Data/Euphoria/transfer/server/www/test.ex 
 
 
REMOTE INFO 
=========== 
REMOTE_ADDR: 127.0.0.1 
REMOTE_HOST: Undefined 
REMOTE_HOST: Undefined 
REMOTE_PORT: 55454 
REMOTE_IDENT: Undefined 
 
 
SERVER INFO 
=========== 
SERVER_ADMIN: Undefined 
SERVER_NAME: 127.0.0.1 
GATEWAY_INTERFACE: CGI/1.1 
SERVER_PROTOCOL: HTTP/1.1 
SERVER_PORT: 80 
SERVER_SOFTWARE: lighttpd/1.4.49 
SERVER_SIGNATURE: Undefined 
REQUEST_METHOD: POST 
SESSION_PATH: Undefined 
PATH: C:\My Program Files\lighttpd 
PATH_INFO: Undefined 
REQUEST_SCHEME: http 
REQUEST_URI: /test.ex 
DOCUMENT_URI: Undefined 
PATH_TRANSLATED: Undefined 
SCRIPT_NAME: /test.ex 
SCRIPT_FILENAME: C:/Data/Euphoria/transfer/server/www/test.ex 
BODY: ------WebKitFormBoundaryXeARN8nzBv8gcjaM 
Content-Disposition: form-data; name="File"; filename="vt100_v0.1.9.zip" 
Content-Type: application/x-zip-compressed 
 
PK 
AUTH_TYPE: Undefined 
CONTENT_TYPE: multipart/form-data; boundary=----WebKitFormBoundaryXeARN8nzBv8gcjaM 
CONTENT_LENGTH: 1159310 
DOCUMENT_ROOT: C:/Data/Euphoria/transfer/server/www 
 
 
BROWSER INFO 
============= 
HTTP_ACCEPT: */* 
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.134 Safari/537.36 Edg/102.0.1245.50 
HTTP_COOKIE: Undefined 
HTTP_HOST: 127.0.0.1 
HTTP_REFERER: Undefined 
HTTPS: Undefined 

I use lighttpd on Windows 10.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

9. Re: Get images or binary files from web form

Sorry, I was too quick. When displaying the real length of the received file the error appears:

    nBytes = getenv("CONTENT_LENGTH") 
    query = get_bytes(0, to_number(nBytes)) 
    printf(1, "%s: %d\n", {"%d bytes received", length(query)} ) 

%d bytes received: 482 
AUTH_TYPE: Undefined 
CONTENT_TYPE: multipart/form-data; boundary=----WebKitFormBoundary8MhqlWPqRLSpCl9f 
CONTENT_LENGTH: 1159310 

allow_break(0) doesn't change anything to the result.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

10. Re: Get images or binary files from web form

getc is not affected by the problem so here is the work-around:

    nBytes = getenv("CONTENT_LENGTH") 
    query = {} 
    for n = 1 to to_integer(nBytes) do 
      integer c = getc(0) 
      query = append(query, c) 
    end for 
    -- query = get_bytes(0, to_number(nBytes)) 
    printf(1, "%d bytes received\n", {length(query)} ) 

1159310 bytes received 
AUTH_TYPE: Undefined 
CONTENT_TYPE: multipart/form-data; boundary=----WebKitFormBoundaryba4L3niknxAhwapL 
CONTENT_LENGTH: 1159310 

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

11. Re: Get images or binary files from web form

Here is your code reviewed. It writes the received file in place. Just add a header FILE_NAME in the post request. It will bee seen by the CGI script as HTTP_FILE_NAME.

#!eui  
-- test program for euphoria cgi  
-- comment/uncomment the following to test the EUINC variable  
  
with batch  
  
include std/io.e  
include std/pretty.e  
include std/get.e  
include std/convert.e 
include std/io.e 
 
sequence cmd  
  
-- if val is a string, return it, otherwise "Undefined"  
function test_val(object val)  
    if atom(val) then  
        return "Undefined"  
    elsif object(val) then  
        for i = 1 to length(val) do  
            if not atom(val[i]) then  
                return "Invalid string sequence"  
            end if  
        end for  
        return val  
    else  
        return "Invalid type for string"  
    end if  
    return "foozle" -- never reached  
end function  
  
  
procedure env_dump(sequence val)  
     printf(1, "%s: %s\n", {val, test_val(getenv(val))} )  
end procedure  
  
puts(1, "Content-Type: text/plain\n\n")  
puts(1, "Hello!\n\n")  
puts(1, "COMMAND LINE\n============\n\n")  
  
cmd = command_line()  
for i = 1 to length(cmd) do  
    printf(1, "%d: %s\n", {i, cmd[i]} )  
end for  
  
puts(1, "\n\nREMOTE INFO\n===========\n")  
  
env_dump("REMOTE_IDENT")  
env_dump("REMOTE_USER")  
env_dump("REMOTE_HOST")  
env_dump("REMOTE_ADDR")  
  
puts(1, "\n\nSERVER INFO\n===========\n")  
env_dump("SERVER_SOFTWARE")  
env_dump("SERVER_NAME")  
env_dump("GATEWAY_INTERFACE")  
env_dump("SERVER_PROTOCOL")  
env_dump("SERVER_PORT")  
env_dump("REQUEST_METHOD")  
env_dump("PATH_INFO")  
env_dump("PATH_TRANSLATED")  
env_dump("SCRIPT_NAME")  
env_dump("QUERY_STRING")  
env_dump("AUTH_TYPE")  
env_dump("CONTENT_TYPE")  
env_dump("CONTENT_LENGTH")  
	  
puts(1, "\n\nBROWSER INFO\n============\n")  
env_dump("HTTP_ACCEPT")  
env_dump("HTTP_USER_AGENT")  
 
puts(1, "\n\nFILE NAME\n============\n")  
sequence fname = test_val(getenv("HTTP_FILE_NAME")) 
 
flush(1)  
  
puts(1, "\n\nSTANDARD INPUT\n=============\n")  
  
object content_size  
sequence std_input = {}  
object char  
  
content_size = getenv("CONTENT_LENGTH")  
puts(1, "Content_size: ")  
print(1, content_size)  
if atom(content_size) then  -- content length no definido  
	puts(1, "\nNo standard input\n\n")  
	abort(0)  
elsif sequence(content_size) then  
	std_input = {} 
	for n = 1 to to_integer(content_size) do 
		integer c = getc(0) 
		std_input = append(std_input, c) 
	end for 
else  -- Unexpected error  
	puts(1, "There is something strange about CONTENT_LENGTH\n\n")  
	abort(0)  
end if  
  
write_file(fname, std_input)  
  
printf(1, "\nStandard input received %s bytes", {content_size})  

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

12. Re: Get images or binary files from web form

I forgot to print the file name:

printf(1, "%s: %s\n", {"HTTP_FILE_NAME", fname} )  
new topic     » goto parent     » topic index » view message » categorize

13. Re: Get images or binary files from web form

What version are you using?

I tested your last code, and I have the same problem.

I am using: Euphoria Interpreter v4.1.0 development 64-bit Windows, Using System Memory Revision Date: 2015-02-02 14:18:53, Id: 6300:57179171dbed

On linux works well, but not on windows

The data received is somethink like

{45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, 45,45,45,45,51,57,57,52,48,54,52,49,55,48,49,56,51,53,57,52,49,54,57,52,50,54, 57,48,49,48,51,49,56,50,10,67,111,110,116,101,110,116,45,68,105,115,112,111, 115,105,116,105,111,110,58,32,102,111,114,109,45,100,97,116,97,59,32,110,97,109,101,61,34,112,114,105,109,101,114,111,34,10,10,102,103,104,106,102,103,104,106,10,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,51,57,57,52,48,54,52,49,55,48,49,56,51,53,57,52,49,54,57,52,50,54,57,48,49,48,51,49,56,50,10,67,111,110,116,101,110,116,45,68,105,115,112,111,115,105,116,105,111,110,58,32,102,111,114,109,45,100,97,116,97,59,32,110,97,109,101,61,34,102,105,108,101,84,111,85,112,108,111,97,100,34,59,32,102,105,108,101,110,97,109,101,61,34,116,117,120,46,106,112,103,34,10,67,111,110,116,101,110,116,45,84,121,112,101,58,32,105,109,97,103,101,47,106,112,101,103,10,10,255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,4,2,3,3,3,2,4,3,3,3,4,4,4,4,5,9,6,5,5,5,5,11,8,8,6,9,13,11,13,13,13,11,12,12,14,16,20,17,14,15,19,15,12,12,18,24,18,19,21,22,23,23,23,14,17,25,27,25,22,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, ....

When detected an EOF character (number 26), the EOF and any subsequent data is converted to -1.

new topic     » goto parent     » topic index » view message » categorize

14. Re: Get images or binary files from web form

Here s what I'm using:

Microsoft Windows [version 10.0.19042.1826] 
(c) Microsoft Corporation. Tous droits réservés. 
 
Euphoria Interpreter v4.1.0 development 
   32-bit Windows, Using System Memory 
   Revision Date: 2015-02-02 14:18:53, Id: 6300:57179171dbed 
 
lighttpd/1.4.49 (ssl) - a light and fast webserver 
This version is built by dtech(.hu), http://lighttpd.dtech.hu/ 
Binary package is compiled with GCC v6.4.0 under Cygwin environment. 

Avoid using EU4.1 64 bits when problems occur. 32 bits version is more safe.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

15. Re: Get images or binary files from web form

I have put Lighttpd and the project folder on my personal site:

Unarchive lighttpd.zip anywhere and don't change it.

Unarchive transfer.zip anywhere. Change directory to transfer\server. You will have to update:

  • lighttpd.bat to tell it where to find lighttpd. Default command is "C:\My Program Files\lighttpd\lighttpd.exe" -D
  • conf/lighttpd.conf, lines 178 and 180, to tell lighttpd where to find openeuphoria. Defaults are:
    • ".ex" => "C:/My Program Files/euphoria4.1/bin/eui",
    • ".il" => "C:/My Program Files/euphoria4.1/bin/eub",

The way it is done, you can have one lighttpd configuration per project.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

16. Re: Get images or binary files from web form

Failed! The file received has been modified at the first ESC char! This old Windows EU4 bug is still relevant as you wrote since the beginning of this thread.

new topic     » goto parent     » topic index » view message » categorize

17. Re: Get images or binary files from web form

Yes, but the problem is on windows version only.

Check it working on linux server:

http://quienfabrica.co/formulario.html

new topic     » goto parent     » topic index » view message » categorize

18. Re: Get images or binary files from web form

For a test, I sent a .png file, 4,675 bytes Can you successfully reconstruct the image from that?

new topic     » goto parent     » topic index » view message » categorize

19. Re: Get images or binary files from web form

My page don't save any file, is just a test!

But you can go down, after the binary dump, copy the sequence and paste on Eu code to save the file.

I had not tried. I'll do it and inform you.

Marco A

new topic     » goto parent     » topic index » view message » categorize

20. Re: Get images or binary files from web form

Copied the sequence, which is 35,331 bytes. How to convert that back to an image?

new topic     » goto parent     » topic index » view message » categorize

21. Re: Get images or binary files from web form

I did it by hand and worked well.

- Upload jpg file to the web.

- Wait a lot, the program is slow because use getc, I'll modify later.

- Go down, after the binary dump, appear twice the sequence dump.

- Copy the sequence.

- Search for 13,10,13,10 After The second time appears is the first byte of your file.

- Search for 13,10,45,45 near the end. This is the last separator, your file ends just before that.

 
include std/io.e 
sequence filedata={255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255, 
 
... 
 
,2,34,32,63,255,217} 
 
print (1,length(filedata)) 
write_file("file2.jpg", filedata) 
new topic     » goto parent     » topic index » view message » categorize

22. Re: Get images or binary files from web form

This is the way I do:

std_input = get_bytes(0, to_integer(content_size)) 
sequence boundary = {} 
for n = 1 to length(std_input) do 
  if (std_input[n] = '\n') and (std_input[n+1] = '\n') then 
    sequence s = std_input[1..n-1] 
    boundary = split(s, '\n') 
    std_input = remove(std_input, 1, n+1) 
    exit 
  end if 
end for 
write_file(fname, std_input)  

Within the boundary part you can extract the filename.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

23. Re: Get images or binary files from web form

Following code works with files containing no ESC char, so it should work on Linux for all files:

with batch  
  
include std/io.e  
include std/pretty.e  
include std/get.e  
include std/convert.e 
include std/sequence.e  -- split 
include std/text.e  -- dequote 
 
-- if val is a string, return it, otherwise "Undefined"  
function test_val(object val)  
    if atom(val) then  
        return "Undefined"  
    elsif object(val) then  
        for i = 1 to length(val) do  
            if not atom(val[i]) then  
                return "Invalid string sequence"  
            end if  
        end for  
        return val  
    else  
        return "Invalid type for string"  
    end if  
    return "foozle" -- never reached  
end function  
  
puts(1, "Content-Type: text/plain\n\n")  
sequence fname = "" 
sequence content_size = test_val(getenv("CONTENT_LENGTH")) 
sequence std_input = get_bytes(0, to_integer(content_size)) 
sequence boundary = {} 
for n = 1 to length(std_input) do 
  if (std_input[n] = '\n') and (std_input[n+1] = '\n') then 
    sequence s = std_input[1..n-1] 
    boundary = split(s, '\n') 
    std_input = remove(std_input, 1, n+1) 
    s = split(boundary[2], "filename=") 
    fname = dequote(s[2]) 
    exit 
  end if 
end for 
write_file(fname, std_input)  
printf(1, "Received %s bytes\n", {content_size})  
printf(1, "Written %s (%d bytes)", {fname, length(std_input)})  

Received 29044 bytes 
Written bloatbox.zip (64 bytes) 

Unfortunately, there is no solution for Windows when the file contains ESC chars.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

24. Re: Get images or binary files from web form

Thanks for share. I'll use that.

By now I'll be forced to use PHP sad

I hope this problem may become solved. I put a ticket.

I am not sure if the problem is in the interpreter or in the standar library.

new topic     » goto parent     » topic index » view message » categorize

25. Re: Get images or binary files from web form

It looks like STDIN is allways in text mode and cannot be put in binary mode. In OE 4 Windows, STDIN seems to be closely tied to the keyboard.

I tried to force binary mode with a wrapper on _setmode (msvcrt.dll), but this cannot work with CGI because of browser restrictions. Maybe this could work witn a self made server.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

26. Re: Get images or binary files from web form

I wonder if it fails the same way translated?

new topic     » goto parent     » topic index » view message » categorize

27. Re: Get images or binary files from web form

If you mean by using James Cook's translated eui, the answer is yes. STDIN is still in text mode.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

28. Re: Get images or binary files from web form

Tried with EU 3.11. CTRL-Z (and not ESC as written before) is still replaced by -1 but following chars remain as is: it's better but still wrong. Some chars as #0D are even left out.

So prefer Linux if you need to upload files via CGI.

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

29. Re: Get images or binary files from web form

Using _setmode() seems to work for me, running xampp-portable-windows-x64-7.4.29-0-VC15 on Windows 10 64-bit with Euphoria 4.1 64-bit. Here's the code I used to test. (Including an override for getenv() that returns a default value and converts strings to atoms.)

#!"C:\Euphoria\bin\eui.exe" 
 
include std/io.e 
include std/convert.e 
include std/dll.e 
 
without warning += { override } 
with batch 
 
constant msvcrt = open_dll( "msvcrt.dll" ) 
constant _setmode = define_c_func( msvcrt, "_setmode", {C_INT,C_INT}, C_INT ) 
 
constant O_BINARY = 0x008000 
 
function set_mode( integer fn, integer mode ) 
    return c_func( _setmode, {fn,mode} ) 
end function 
 
override function getenv( sequence name, object default="" ) 
    object value = eu:getenv( name ) 
    if equal( value, -1 ) then 
        return default 
    end if 
    if atom( default ) then 
        value = to_number( value ) 
    end if 
    return value 
end function 
 
printf( STDOUT, "Content-type: text/html\n\n" ) 
printf( STDOUT, "<html><head></head><body>\n" ) 
printf( STDOUT, "<form method=\"post\" action=\"/cgi-bin/upload.esp\" enctype=\"multipart/form-data\">\n" ) 
printf( STDOUT, "Your text: <input name=\"text\" /><br>\n" ) 
printf( STDOUT, "Your file: <input type=\"file\" name=\"file\" accept=\"image/png, .jpeg, .jpg, image/gif\"><br>\n" ) 
printf( STDOUT, "<input type=\"submit\" /></form>\n" ) 
 
sequence request_method = getenv( "REQUEST_METHOD" ) 
 
if equal( request_method, "POST" ) then 
 
    sequence content_type = getenv( "CONTENT_TYPE" ) 
    integer content_length = getenv( "CONTENT_LENGTH", 0 ) 
 
    printf( STDOUT, "<pre><code>\n" ) 
    printf( STDOUT, "CONTENT_TYPE = \"%s\"\n", {content_type} ) 
    printf( STDOUT, "CONTENT_LENGTH = %d\n", {content_length} ) 
    printf( STDOUT, "REQUEST_METHOD = \"%s\"\n", {request_method} ) 
    printf( STDOUT, "</code></pre>\n" ) 
 
    set_mode( STDIN, O_BINARY ) 
    sequence bytes = get_bytes( STDIN, content_length ) 
 
    printf( STDOUT, "<p>Received %d bytes!</p>\n", {length(bytes)} ) 
 
end if 
 
printf( 1, "</body></html>\n" ) 

I still need to include multipart form handling in Euphoria MVC, but if I recall, last time I looked at it I was stuck on this problem and I believe this corrects it. I will also look at what it takes to do this in the back end.

-Greg

new topic     » goto parent     » topic index » view message » categorize

30. Re: Get images or binary files from web form

Thanks Greg,

I have not been able to get it work. However, following code works on Linux:

with batch 
 
include std/io.e 
include std/pretty.e 
include std/get.e 
include std/convert.e 
include std/sequence.e  -- split 
include std/text.e  -- dequote 
 
-- if val is a string, return it, otherwise "Undefined" 
function test_val(object val) 
    if atom(val) then 
        return "Undefined" 
    elsif object(val) then 
        for i = 1 to length(val) do 
            if not atom(val[i]) then 
                return "Invalid string sequence" 
            end if 
        end for 
        return val 
    else 
        return "Invalid type for string" 
    end if 
    return "foozle" -- never reached 
end function 
 
puts(1, "Content-Type: text/plain\n\n") 
sequence fname = "" 
sequence content_size = test_val(getenv("CONTENT_LENGTH")) 
sequence std_input = get_bytes(0, to_integer(content_size)) 
 
sequence boundary = {} 
for n = 1 to length(std_input) do 
  if equal(std_input[n..n+3], "\r\n\r\n") then 
    sequence s = std_input[1..n-1] 
    boundary = split(s, "\r\n") 
    std_input = remove(std_input, 1, n+3) 
    s = split(boundary[2], "filename=") 
    fname = dequote(s[2]) 
    exit 
  end if 
end for 
integer p = match("\r\n" & boundary[1], std_input) 
write_file("/tmp/" & fname, std_input[1..p-1]) 
 
printf(1, "Received %s bytes\n", {content_size}) 
printf(1, "Written %s (%d bytes)", {fname, length(std_input[1..p-1])}) 

POST response is:

Received 29044 bytes 
Written bloatbox.zip (28840 bytes) 

File is correctly written in /tmp:

root@cpe-tests-tool-JM:/var/www/html# ls -l /tmp/bloatbox.zip 
-rw-r--r-- 1 www-data www-data 28840 Aug 16 11:14 /tmp/bloatbox.zip 
root@cpe-tests-tool-JM:/var/www/html# unzip -l /tmp/bloatbox.zip 
Archive:  /tmp/bloatbox.zip 
  Length      Date    Time    Name 
---------  ---------- -----   ---- 
   159744  2021-05-24 11:50   Bloatbox.exe 
        0  2021-05-24 11:50   de/ 
     8192  2021-05-24 11:50   de/Bloatbox.resources.dll 
---------                     ------- 
   167936                     3 files 

Jean-Marc

new topic     » goto parent     » topic index » view message » categorize

31. Re: Get images or binary files from web form

Just this week I come back with this

Your code works well to me (Windows 7) Just needed to add platform(), so don't try to run windows specific code on linux machines.

I am also learning about how to parse form response.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

Would be nice to have on standar lib a clever function may scan the binary input, from any web form, separate chunks using boundary, read the Content-Disposition on each section to define how to scan it. Usual form inputs are simply plain text, and files are binary blobs. Then return one simple sequence, something like.

{ 
{FORMTEXT, "FormName", "Bill Gates"}, 
{FORMTEXT, "FormCompany", "Microsoft"} 
{FORMFILE, "FormPhoto", {"myphoto.jpg", "Long Binary sequence here......"} } 
} 

Marco Achury

new topic     » goto parent     » topic index » view message » categorize

32. Re: Get images or binary files from web form

achury said...

Just needed to add platform(), so don't try to run windows specific code on linux machines.

You should be using ifdef instead of platform(). Here's an updated example that uses ifdef to only provide set_mode() on Windows.

#!"C:\Euphoria\bin\eui.exe" 
 
include std/io.e 
include std/convert.e 
include std/dll.e 
 
without warning += { override } 
with batch 
 
ifdef WINDOWS then 
 
    constant msvcrt = open_dll( "msvcrt.dll" ) 
    constant _setmode = define_c_func( msvcrt, "_setmode", {C_INT,C_INT}, C_INT ) 
 
    constant O_BINARY = 0x008000 
 
    function set_mode( integer fn, integer mode ) 
        return c_func( _setmode, {fn,mode} ) 
    end function 
 
end ifdef 
 
override function getenv( sequence name, object default="" ) 
    object value = eu:getenv( name ) 
    if equal( value, -1 ) then 
        return default 
    end if 
    if atom( default ) then 
        value = to_number( value ) 
    end if 
    return value 
end function 
 
printf( STDOUT, "Content-type: text/html\n\n" ) 
printf( STDOUT, "<html><head></head><body>\n" ) 
printf( STDOUT, "<form method=\"post\" action=\"/cgi-bin/upload.esp\" enctype=\"multipart/form-data\">\n" ) 
printf( STDOUT, "Your text: <input name=\"text\" /><br>\n" ) 
printf( STDOUT, "Your file: <input type=\"file\" name=\"file\" accept=\"image/png, .jpeg, .jpg, image/gif\"><br>\n" ) 
printf( STDOUT, "<input type=\"submit\" /></form>\n" ) 
 
sequence request_method = getenv( "REQUEST_METHOD" ) 
 
if equal( request_method, "POST" ) then 
 
    sequence content_type = getenv( "CONTENT_TYPE" ) 
    integer content_length = getenv( "CONTENT_LENGTH", 0 ) 
 
    printf( STDOUT, "<pre><code>\n" ) 
    printf( STDOUT, "CONTENT_TYPE = \"%s\"\n", {content_type} ) 
    printf( STDOUT, "CONTENT_LENGTH = %d\n", {content_length} ) 
    printf( STDOUT, "REQUEST_METHOD = \"%s\"\n", {request_method} ) 
    printf( STDOUT, "</code></pre>\n" ) 
 
ifdef WINDOWS then 
    set_mode( STDIN, O_BINARY ) 
end ifdef 
 
    sequence bytes = get_bytes( STDIN, content_length ) 
 
    printf( STDOUT, "<p>Received %d bytes!</p>\n", {length(bytes)} ) 
 
end if 
 
printf( 1, "</body></html>\n" ) 
achury said...

I am also learning about how to parse form response.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

Would be nice to have on standar lib a clever function may scan the binary input, from any web form, separate chunks using boundary, read the Content-Disposition on each section to define how to scan it.

I do plan to add this to Euphoria MVC, although in time I may end up ingesting that entire project into Euphoria standard library.

-Greg

new topic     » goto parent     » topic index » view message » categorize

33. Re: Get images or binary files from web form

I want to have a very simple library for CGI bin. Please check this and guide me how to follow. May be later you can include some from this on your MVC

Note, the 3 example forms point to the same CGI script.

https://github.com/marcoachury/cgiform

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu