Wanna see this logo while booting your 2.6 kernel? Click here!

17.06.2005 09:07

CGI Post method handling in bash scripts

I just wanted to post my way of handling CGI POST method Request Strings using bash here because I didn't find anything useful in the web straightaway. The following code reads all Data from stdin (which is POST's way to send you the data) and parses it according to the CGI protocol rules.
The main problem is, that all special charactes such as exclamation marks, white spaces, german umlauts, etc. are being encoded as %xx, where xx is the hexadecimal code of this ascii character. So one has to transform these occurences to their representatives in the ascii-table.
Please keep in mind, that this example is written for use with busybox so I had to include some tricks that might not be necessary on normal installations (e.g. busybox's sed is not able to display ascii characters with the notation \xnn (where nn is any hexadecimal number)).

Update 2006-04-21:
There was an error in this script that caused it to behave incorrectly if a percent sign (%25) was found in $POST_STRING. Here's the updated version:
if [ "$REQUEST_METHOD" = "POST" ]; then

  while true; do
    HEX="$(echo "$POST_STRING" | sed 's/^.*[^%]%\([0-9a-fA-F][0-9a-fA-F]\).*/\1/')"
    if [ "$HEX" = "$POST_STRING" ]; then
    REP=$(echo -e \\x$HEX)
    # to avoid mishandling of %25 (== '%') replace all occurences of the
    # percent sign itself with a double percent sign (kind of escaping)
    [ "$REP" = "%" ] && REP="%%"

    POST_STRING="$(echo "$POST_STRING" | sed 's/^\(.*[^%]\)%\([0-9a-fA-F][0-9a-fA-F]\)/\1'$REP'/')"

  # replace all escaped percent signs with a single percent sign
  POST_STRING=$(echo $POST_STRING | sed 's/%%/%/g')

  # replace all ampersands with spaces for easier handling later
  POST_STRING=$(echo $POST_STRING | sed 's/&/ /g')

POST_STRING then contains the decoded Parameter-List which could be fed into a bash-array (of course, that's also not possible with the busybox builtin, because there's no declare plugin (not at the moment, at least)).
In my application I did also use the following line afterwards to replace all ampersands by spaces because I used " for token in $POST_STRING" afterwards (you may also set the IFS environment variable to "&" if you like).
  # replace all ampersands with spaces for easier handling later
  POST_STRING=$(echo $POST_STRING | sed 's/&/ /g')
If you have any idea of how this could be done better, don't hesitate to contact me.