Search code examples
bashcgi

How can I pass folder paths through CGI to script via variable?


I have a CGI bash script that is intended to call up another bash script that installs a docker container. I'm having an issue when trying to pass a folder path.

app-install.cgi:

#!/bin/sh
echo "Content-type: text/html\n"

# Collect arguments from the URL
APPNAME=`echo "$QUERY_STRING" | sed -n 's/^.*appname=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
APP_WEB_PORT=`echo "$QUERY_STRING" | sed -n 's/^.*app_web_port=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
APP_WEB_USER=`echo "$QUERY_STRING" | sed -n 's/^.*app_web_user=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
APP_WEB_PASS=`echo "$QUERY_STRING" | sed -n 's/^.*app_web_pass=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
DOWNLOAD_DIR=`echo "$QUERY_STRING" | sed -n 's/^.*download_dir=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
CONFIG_DIR=`echo "$QUERY_STRING" | sed -n 's/^.*config_dir=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
LIBRARY_DIR=`echo "$QUERY_STRING" | sed -n 's/^.*library_dir=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
DOWNLOAD__TEMP_DIR=`echo "$QUERY_STRING" | sed -n 's/^.*download_temp_dir=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
WORKING_DIR=`echo "$QUERY_STRING" | sed -n 's/^.*working_dir=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`

# Export em

export APPNAME
export APP_WEB_PORT
export APP_WEB_USER
export APP_WEB_PASS
export DOWNLOAD_DIR
export CONFIG_DIR
export LIBRARY_DIR
export DOWNLOAD__TEMP_DIR
export WORKING_DIR

# HTML header
echo "<html>"
echo "<head><title></title></head>"
echo "<body>"

# Run script
if [ $APPNAME ]
then
    echo "Installing $APPNAME..."
    echo "<pre>"
    bash -x /var/www/mysite.local/public_html/lib/$APPNAME/install-$APPNAME.sh
    echo "</pre>"
else
    echo "No app specified, check the error log"
fi

# Close HTML header
echo "</body>"
echo "</html>"

install-myapp.sh

#!/bin/sh

# Install docker container from vars
sudo docker create \
   --name=myapp \
   -v $CONFIG_DIR:/config \
   -v $DOWNLOAD_DIR:/downloads \
   -v $LIBRARY_DIR:/library \
   -e PGID=$PGID -e PUID=$PUID  \
   -e TZ=$TZ \
   -p $APP_WEB_PORT \
   docker/imagepath

I call everything up by using a URL (I left out most of the variables in this case because it seems only the vars ending in "DIR" seem to have an issue:

http://mysite.local/cgi-bin/install-app.cgi?appname=foo&config_dir="\tmp\myapp\config"

I get the following error from docker:

Error response from daemon: create %22/tmp/myapp/config%22: "%22/tmp/myapp/config%22" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed

I'm assuming that I'm not escaping something correctly, but how can I pass a folder name correctly here?


Solution

  • Your immediate problem is that the URL incorrectly contains quotes that aren't needed:

    http://mysite.local/cgi-bin/install-app.cgi?appname=foo&config_dir=\tmp\myapp\config
    

    Until you rewrite this in a language better suited to parsing URLs, I would use something like this (which is still fragile, but simpler than your current code):

    QUERY_STRING='http://mysite.local/cgi-bin/install-app.cgi?appname=foo&config_dir=\tmp\myapp\config'
    
    IFS='&' read -ra kvpairs <<< ${QUERY_STRING#*\?}
    
    for kv in "${kvpairs[@]}"; do
      IFS== read -r k v <<< $kv
      case $k in
        appname)           APPNAME=$v ;;
        app_web_port)      APP_WEB_PORT=$v ;;
        app_web_user)      APP_WEB_USER=$v ;;
        app_web_pass)      APP_WEB_PASS=$v ;;
        download_dir)      DOWNLOAD_DIR=$v ;;
        config_dir)        CONFIG_DIR=$v ;;
        library_dir)       LIBRARY_DIR=$v ;;
        download_temp_dir) DOWNLOAD_TEMP_DIR=$v ;;
        working_temp_dir)  WORKING_DIR=$v ;;
      esac
    done