.\" Process with groff -man -Tascii haserl.1 .TH haserl 1 "October 2010" .SH NAME haserl \- A cgi scripting program for embedded environments .SH SYNOPSIS .BI "#!/usr/bin/haserl [\-\-shell=" pathspec "] [\-\-upload\-dir=" dirspec "] [\-\-upload\-handler=" handler "] [\-\-upload\-limit=" limit "] [\-\-accept\-all] [\-\-accept\-none] [\-\-silent] [\-\-debug]" [ text ] [ <% shell script %> ] [ text ] ... .SH DESCRIPTION Haserl is a small cgi wrapper that allows "PHP" style cgi programming, but uses a UNIX bash-like shell or Lua as the programming language. It is very small, so it can be used in embedded environments, or where something like PHP is too big. It combines three features into a small cgi engine: .IP It parses POST and GET requests, placing form-elements as name=value pairs into the environment for the CGI script to use. This is somewhat like the .IR uncgi " wrapper." .IP It opens a shell, and translates all text into printable statements. All text within <% ... %> constructs are passed verbatim to the shell. This is somewhat like .RI writing " PHP " "scripts." .IP It can optionally be installed to drop its permissions to the owner of the script, giving it some of the security features of .IR suexec " or " cgiwrapper . .SH OPTIONS SUMMARY This is a summary of the command-line options. Please see the .B OPTIONS section under the long option name for a complete description. \-a \-\-accept\-all .br \-n \-\-accept\-none .br \-d \-\-debug .br \-s, \-\-shell .br \-S, \-\-silent .br \-U, \-\-upload\-dir .br \-u, \-\-upload\-limit .br \-H, \-\-upload\-handler .br .SH OPTIONS .TP .BI \-\-accept\-all The program normally accepts POST data only when the REQUEST_METHOD is POST and only accepts data on the URL data when the REQUEST_METHOD is GET. This option allows both POST and URL data to be accepted regardless of the REQUEST_METHOD. When this option is set, the REQUEST_METHOD takes precedence (e.g. if the method is POST, FORM_variables are taken from COOKIE data, GET data, and POST data, in that order. If the method is GET, FORM_variables are taken from COOKIE data, POST data, and GET data.) The default is not to accept all input methods - just the COOKIE data and the REQUEST_METHOD. .TP .BI \-\-accept\-none If given, haserl will not parse standard input as http content before processing the script. This is useful if calling a haserl script from another haserl script. .TP .BI \-\-debug Instead of executing the script, print out the script that would be executed. If the environment variable 'REQUEST_METHOD' is set, the data is sent with the plain/text content type. Otherwise, the shell script is printed verbatim. .TP .BI \-\-shell= "pathspec " Specify an alternative bash-like shell to use. Defaults to "/bin/sh" To include shell parameters do not use the \-\-shell=/bin/sh format. Instead, use the alternative format without the "=", as in \-\-shell "/bin/bash \-\-norc". Be sure to quote the option string to protect any special characters. If compiled with Lua libraries, then the string "lua" is used to use an integrated Lua vm. This string is case sensitive. Example: .BI \-\-shell= lua An alternative is "luac". This causes the haserl and lua parsers to be disabled, and the script is assumed to be a precompiled lua chunk. See .B LUAC below for more information. .TP .BI \-\-silent Haserl normally prints an informational message on error conditions. This suppresses the error message, so that the use of haserl is not advertised. .TP .BI \-\-upload\-dir= "dirspec " Defaults to "/tmp". All uploaded files are created with temporary filename in this directory .BR HASERL_xxx_path " contains the name of the temporary file. " FORM_xxx_name contains the original name of the file, as specified by the client. .TP .BI \-\-upload\-handler= "pathspec " When specified, file uploads are handled by this handler, rather than written to temporary files. The full pathspec must be given (the PATH is not searched), and the upload-handler is given one command-line parameter: The name of the FIFO on which the upload file will be sent. In addition, the handler may receive 3 environment variables: .BR CONTENT_TYPE ", " FILENAME ", and " NAME . These reflect the MIME content-disposition headers for the content. Haserl will fork the handler for each file uploaded, and will send the contents of the upload file to the specified FIFO. Haserl will then block until the handler terminates. This method is for experts only. .TP .BI \-\-upload\-limit= "limit " Allow a mime-encoded file up to .I limit KB to be uploaded. The default is .I 0KB (no uploads allowed). Note that mime-encoding adds 33% to the size of the data. .SH OVERVIEW OF OPERATION In general, the web server sets up several environment variables, and then uses .I fork or another method to run the CGI script. If the script uses the .I haserl interpreter, the following happens: .IP If .I haserl is installed suid root, then uid/gid is set to the owner of the script. The environment is scanned for .IR HTTP_COOKIE , which may have been set by the web server. If it exists, the parsed contents are placed in the local environment. The environment is scanned for .IR REQUEST_METHOD , which was set by the web server. Based on the request method, standard input is read and parsed. The parsed contents are placed in the local environment. The script is tokenized, parsing .I haserl code blocks from raw text. Raw text is converted into "echo" statements, and then all tokens are sent to the sub-shell. .I haserl forks and a sub-shell (typically .IR /bin/sh ) is started. All tokens are sent to the STDIN of the sub-shell, with a trailing .B exit command. When the sub-shell terminates, the .I haserl interpreter performs final cleanup and then terminates. .SH CLIENT SIDE INPUT The .I haserl interpreter will decode data sent via the HTTP_COOKIE environment variable, and the GET or POST method from the client, and store them as environment variables that can be accessed by haserl. The name of the variable follows the name given in the source, except that a prefix ( .IR FORM_ ) is prepended. For example, if the client sends "foo=bar", the environment variable is .BR FORM_foo = bar . For the HTTP_COOKIE method, variables are also stored with the prefix ( .IR COOKIE_ ) added. For example, if HTTP_COOKIE includes "foo=bar", the environment variable is .BR COOKIE_foo = bar . For the GET method, data sent in the form %xx is translated into the characters they represent, and variables are also stored with the prefix ( .IR GET_ ) added. For example, if QUERY_STRING includes "foo=bar", the environment variable is .BR GET_foo = bar . For the POST method, variables are also stored with the prefix ( .IR POST_ ) added. For example, if the post stream includes "foo=bar", the environment variable is .BR POST_foo = bar . Also, for the POST method, if the data is sent using .I "multipart/form\-data" encoding, the data is automatically decoded. This is typically used when files are uploaded from a web client using . .TP .B NOTE When a file is uploaded to the web server, it is stored in the .I upload-dir directory. .BR FORM_variable_name= " contains the name of the file uploaded" (as specified by the client.) .BR HASERL_variable_path= " contains the name of the file in " .I upload-dir that holds the uploaded content. To prevent malicious clients from filling up .I upload-dir on your web server, file uploads are only allowed when the .I \-\-upload\-limit option is used to specify how large a file can be uploaded. Haserl automatically deletes the temporary file when the script is finished. To keep the file, move it or rename it somewhere in the script. .TP .B " " Note that the filename is stored in .BI HASERL_ variable_path This is because the FORM_, GET_, and POST_ variables are modifiable by the client, and a malicious client can set a second variable with the name .IR variable_path=/etc/passwd . Earlier versions did not store the pathspec in .B HASERL namespace. .I To maintain backward compailibility, the name of the temporary file .I is also stored in .BI FORM_variable= " and " .BI POST_variable=. " This is considered unsafe and should not be used." .P If the client sends data .I both by POST and GET methods, then .I haserl will parse only the data that corresponds with the .I REQUEST_METHOD variable set by the web server, unless the .I accept-all option has been set. For example, a form called via POST method, but having a URI of some.cgi?foo=bar&otherdata=something will have the POST data parsed, and the .IR foo " and " otherdata variables are ignored. .P If the web server defines a .I HTTP_COOKIE environment variable, the cookie data is parsed. Cookie data is parsed .I before the GET or POST data, so in the event of two variables of the same name, the GET or POST data overwrites the cookie information. .P When multiple instances of the same variable are sent from different sources, the FORM_variable will be set according to the order in which variables are processed. HTTP_COOKIE is always processed first, followed by the REQUEST_METHOD. If the accept-all option has been set, then HTTP_COOKIE is processed first, followed by the method not specified by REQUEST_METHOD, followed by the REQUEST_METHOD. The last instance of the variable will be used to set FORM_variable. Note that the variables are also separately creates as COOKIE_variable, GET_variable and POST_variable. This allows the use of overlapping names from each source. .P When multiple instances of the same variable are sent from the same source, only the last one is saved. To keep all copies (for multi-selects, for instance), add "[]" to the end of the variable name. All results will be returned, separated by newlines. For example, host=Enoch&host=Esther&host=Joshua results in "FORM_host=Joshua". host[]=Enoch&host[]Esther&host[]=Joshua results in "FORM_host=Enoch\\nEsther\\nJoshua" .SH LANGUAGE The following language structures are recognized by .IR haserl . .TP .B "RUN" .nf <% [shell script] %> .sp .fi Anything enclosed by <% %> tags is sent to the sub-shell for execution. The text is sent verbatim. .TP .B "INCLUDE" .nf <%in pathspec %> .sp .fi Include another file verbatim in this script. The file is included when the script is initially parsed. .TP .B "EVAL" .nf <%= expression %> .sp .fi print the shell expression. Syntactic sugar for "echo expr". .TP .B "COMMENT" .nf <%# comment %> .sp .fi Comment block. Anything in a comment block is not parsed. Comments can be nested and can contain other haserl elements. .SH EXAMPLES .TP .B WARNING The examples below are simplified to show how to use .IR haserl . You should be familiar with basic web scripting security before using .I haserl (or any scripting language) in a production environment. .TP .B Simple Command .nf #!/usr/local/bin/haserl content-type: text/plain .sp <%# This is a sample "env" script %> <% env %> .fi Prints the results of the .I env command as a mime-type "text/plain" document. This is the .I haserl version of the common .I printenv cgi. .TP .B Looping with dynamic output .nf #!/usr/local/bin/haserl Content-type: text/html .sp
"><% echo \-n "$a" %> | <% done %>