Produce a download file from CGI in Lua - lua

I am writing a simple CGI program in lua. What I want to achieve is produce a response from CGI which enables a file to be downloaded from the browser. But I just can't print the data. I have no idea what's going on here. Here is the code below:
print("Content-Type: text/html; charset=UTF-8")
print("Content-Length:" .. sys.getenv("CONTENT_LENGTH"))
print("Content-Disposition:",'attachment;filename="backup.tar.gz"\n')
print("Content-Type:application/x-tar-gz\n\n")
file=io.popen("some command")
output = file:read('*a')
print(output)
--file:close()
The problem is I just can't print the output whose content is binary. I can see the type of output is string.
What is the problem? Please give some hints about it. Thank you.
ADD : I have no idea about this and Where is the issue. Let me put more info about the command I want run. But I don't think that matters.
Actually, I work in openwrt, the web server uhttpd. (No LuCI here)
The command is:sysupgrade -b - 2>/dev/null. This command is used to backup the config file. I want to write a CGI to download the backup file from the web.
But I can not print the output to the server. Even in the terminal(in lua IDE) I cannot print out the output except one or two messy code. But I can write the output to a file in terminal. Maybe it has some relationship with the content of out.
When I print the content line by line, it prints some, but not all of it. After I download the file. I can't open it.

print("Content-Disposition:",'attachment;filename="backup.tar.gz"\n')
print("Content-Type:application/x-tar-gz\n\n")
I think you have way too many new lines. First of all, you can newline in Content-Disposition and this is in addition to the newline that print adds, which ends the headers and makes Content-Type a part of the payload (which breaks the content). You also have two newlines in Content-Type where you only need one (as one is added by the print command).
I think something like this should work:
local file = io.popen("some command")
local output = file:read('*a')
file:close()
print("Content-Type: text/html; charset=UTF-8")
print("Content-Length: " .. #output)
print("Content-Disposition: " .. 'attachment;filename="backup.tar.gz"')
print("Content-Type: application/x-tar-gz\r\n")
print(output)

Related

How do I send output from the terminal to a text file in Visual Studio Code with the proper encoding?

I'm having issues sending output containing Unicode box-drawing characters to a text file.
The string ┌───top───┐ prints to the terminal fine using the print command. It also renders properly if I open and write directly to a file in my code.
However, if I pipe the terminal output into a text file using
<run command> > out.txt, I get the result
ΓöîΓöÇΓöÇΓöÇtopΓöÇΓöÇΓöÇΓöÉ
Everything else prints fine, but why doesn't it handle certain Unicode characters?
Is there a quick fix for this?

Lua io.write() not working

I am using a luvit Lua environment to run my lua code through my control panel. I am looking to write to a .txt file, but with the simple code that i am running, its not working.
The reason I wish to write to a .txt file is to log notices from my Discord Bot I am working on in the Discordia library.
I have a folder called MezzaBOT. In this file i have a write.lua file and also a log.txt file. I have this simple code in my write.lua file:
io.output('log.txt')
io.write('hello\n')
io.close()
I then run in my command promt with Luvit environment:
>luvit Desktop\mezzabot\write.lua
I don't get any errors but the log.txt file continues to stay empty. Am I missing a line in my code, or do i need to access log.txt differently?
edit: my new code is the following
file = io.open('log.txt')
file:write('hello', '\n')
file:close()
and it is not making a new line for each time with \n
edit B:
Ok, i found my problem, its creating a log.txt in my C:\Users\PC.
One other problem is when writing, its not making a new line with the \n. Can someone please help me?
Lua, by default, opens files in read mode. You need to explicitly open a file in write mode if you want to write to it (see manual)
file = io.open('log.txt', 'w')
file:write('hello', '\n')
file:close()
Should work :)

How to print response headers to console and save content to file?

How can I print the response headers to console and save the response content to a file?
I tried
http GET http://download.sysinternals.com/files/SysinternalsSuite.zip --output sis.zip
But this printed both the headers and content to the file, making it nonsense.
It is possible in an updated version, the --output option will print the output into a file, and the --download option will make sure that the headers are print to the console, and only the content to the output file.
Here is an example:
http GET "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=Stack%20Overflow" --download --output bla.txt
This is what HTTPie does by default:
When the output is not redirected, the whole message is printed to the terminal (headers & body). However, binary data is not printed to the terminal.
When the output is redirected to a file, then only the body is printed (headers & body). It doesn't matter whether the body is binary or not.
So, the output depends on where it is being printed to. You can overwrite the default context-sensitive behaviour with one of the output options. For example, the following saves the headers as well as the body to a file:
http --output sis.zip --print=hb download.sysinternals.com/files/SysinternalsSuite.zip
HTTPie currently doesn't allow outputing binary data to the terminal.
It's not possible. Reported issue https://github.com/jkbr/httpie/issues/97
Update 2013: Fixed. Try
http -h --download http://download.sysinternals.com/files/SysinternalsSuite.zip

Offending Command error while Printing EPS

I am printing an EPS File generated with following credentials.
%-12345X#PJL JOB
#PJL ENTER LANGUAGE = POSTSCRIPT
%!PS-Adobe-3.0
%%Title: InvoiceDetail_combine
%%Creator: PScript5.dll Version 5.2.2
%%CreationDate: 10/7/2011 4:46:59
%%For: Administrator
%%BoundingBox: (atend)
%%Pages: (atend)
%%Orientation: Portrait
%%PageOrder: Special
%%DocumentNeededResources: (atend)
%%DocumentSuppliedResources: (atend)
%%DocumentData: Clean7Bit
%%TargetDevice: (HP Color LaserJet 4500) (2014.200) 0
%%LanguageLevel: 2
%%EndComments
While doing Selection Printing on Ricoh Afficio 2090 or any other drivers/printers get the following error printed on the sheets
ERROR: undefined
OFFENDING COMMAND: F4S47
Stack:
.
Kindly Review and suggest a turn around for the same as i am already stuck in this hell. I have tried to convert/extract in PS but all in vain. I am using gsview to Print and view these files.
This is the problem:
%%PageOrder: Special
A ps document with "Special" page order can NOT be re-ordered. You cannot do a selection or range with this file because it is broken for this use. You must reprocess the file using Distiller or ghostscript (ps2ps or ps2pdf) in order to print selected or re-ordered pages from the document.
You can avoid this by generating your postscript files with a real Postscript™ driver (one not created by Microsoft).
The GSView Documentation has more about this.
Previously:
This line ...
%%TargetDevice: (HP Color LaserJet 4500) (2014.200) 0
... tells us that the file was generated with HP printers as a target. So this really is not an EPS file. Because it's not Encapsulatable. To generate output on a printer the file has to execute the showpage operator, which is a no-no for EPS files.
So uncheck the EPS box (it's a big fat lie, anyway), and select (install) a Generic Postscript driver. If you need to send it to multiple makes of printer, the file needs to make as few assumptions about the printer as possible.
The first thing is that this is not a valid EPS file, as it has PJL attached at the front. Many PostScript printers will strip this off, but by no means all.
This probably is not the source of the problem.
There is no way to 'review' the problem as you have not supplied the complete PostScript program. Without that there is no way to tell what is actually wrong, the error message tells you that the interpreter encountered 'F4547' while trying to parse a token, and that this has not been defined as a routine.
Most likely the file is corrupt, either damaged in some way, or possibly it is a biinary file and has been transmitted by some process which does has done some kind of conversion (CR/LF is common). The offending command looks like its ASCIIHex encoded, so that may be a red herring.
If you want additional help, you are going to have to make the whole program available somewhere.

How do I make sure that a directory name is quoted in OMake?

I have a relatively complicated suite of OMake files designed for cross-compiling on a specific platform. My source is in C++.
I'm building from Windows and I need to pass to the compiler include directories which have spaces in their names. The way that the includes string which is inserted in the command line to compile files is created is by the line:
public.PREFIXED_INCLUDES = $`(addprefix $(INCLUDES_OPT), $(set $(absname $(INCLUDES))))
At some other point in the OMake files I have a line like:
INCLUDES += $(dir "$(LIBRARY_LOCATION)/Path with spaces/include")
In the middle of the command line this expands to:
-IC:\Library location with spaces\Path with spaces\include
I want it to expand to:
-I"C:\Library location with spaces\Path with spaces\include"
I don't want to change anything but the "INCLUDES += ..." line if possible, although modifying something else in that file is also fine. I don't want to have to do something like change the definition of PREFIXED_INCLUDES, as that's in a suite of OMake files which are part of an SDK which may change beneath me. Is this possible? If so, how can I do it? If not, in what ways can I make sure that includes with spaces in them are quoted by modifying little makefile code (hopefully one line)?
The standard library function quote adds escaped quotes around its argument, so it should do the job:
INCLUDES += $(quote $(dir "$(LIBRARY_LOCATION)/Path with spaces/include"))
If needed, see quote in Omake manual.
In case someone else is having the same problem, I thought I'd share the solution I eventually went with, having never figured out how to surround with quotes. Instead of putting quotes around a name with spaces in it I ended up converting the path to the short (8.3) version. I did this via a a simple JScript file called shorten.js and a one line OMake function.
The script:
// Get Access to the file system.
var FileSystemObject = WScript.CreateObject("Scripting.FileSystemObject");
// Get the short path.
var shortPath = FileSystemObject.GetFolder(WScript.Arguments(0)).ShortPath;
// Output short path.
WScript.StdOut.Write(shortPath);
The function:
ShortDirectoryPath(longPath) =
return $(dir $(shell cscript /Nologo $(dir ./tools/shorten.js) "$(absname $(longPath))"))
So now I just use a line like the following for includes:
INCLUDES += $(ShortDirectoryPath $(dir "$(LIBRARY_LOCATION)/Path with spaces/include"))

Resources