#---------------------------------------------------------------------------- # /www/srv/admin/cgi-helper # # Creation: 2005-08-12 hh # Last Update: $Id$ #---------------------------------------------------------------------------- #---------------------------------------------------------------------------- # do some useful things #---------------------------------------------------------------------------- # set_debug=yes # parse variables cgi_helper="yes" eval "`proccgi $*`" : ${set_debug:=$FORM_debug} # Write debug info to debug.log case $set_debug in yes) exec 2>/srv/www/admin/debug.log set -x ;; *) exec 2>/dev/null ;; esac . /var/run/mini_httpd.conf myname=`basename $0` : ${cginame:=`basename $0 .cgi`} : ${lang:="$HTTPD_GUI_LANG"} : ${showmenu:=$FORM_showmenu} # get language files if [ -f /srv/www/lang/main.$lang ] then . /srv/www/lang/main.$lang else . /srv/www/lang/main.en fi if [ -f /srv/www/lang/$cginame.$lang ] then . /srv/www/lang/$cginame.$lang else [ -f /srv/www/lang/$cginame.en ] && . /srv/www/lang/$cginame.en fi #---------------------------------------------------------------------------- # Security function #---------------------------------------------------------------------------- user_has_rights () { # returns true if the user has access [ -z "$1" ] && return 0 if grep ^$REMOTE_USER= /etc/httpd/rights | cut -d= -f2 | \ grep -vq -e "^all$" \ -e "\( \|^\)$1:all\( \|$\)" \ -e "\( \|^\)$1[^ ]*[:,]$2\( \|,\|$\)" then return 1 else return 0 fi } check_rights () { : ${SEC_REALM:=$1} : ${SEC_ACTION:=$2} if [ -z "$SEC_REALM" -o -z "$SEC_ACTION" ] then show_html_header "$_MN_accdenied" show_error "$_MN_seclib" "$_MN_nopar" show_html_footer # Exit the CGI-Script exit 1 fi case $REMOTE_USER in "") ;; *) if ! user_has_rights $SEC_REALM $SEC_ACTION then show_html_header "$_MN_accdenied" show_error "$_MN_accdenied" "$_MN_noright
\ $_MN_user: \"$REMOTE_USER\"
\ $_MN_realm: \"$SEC_REALM\"
\ $_MN_secaction: \"$SEC_ACTION\"" show_html_footer # Exit the CGI-Script exit 1 fi ;; esac } #---------------------------------------------------------------------------- # some useful functions #---------------------------------------------------------------------------- reload () { # Reload site echo "Location: $myname" echo } # # Output HTTP Header # # Echoes additional HTTP headers. Should at least contain Content-Type. # # According to RFC 2616 each header line must be terminated with CR LF, # which is \r\n. Shell adds \n but not \r so we must do this for each # header line! # # $1 output type (case) # $2 additional option string to be evaluated # http_header () { # need quoted string expansion, \r is not interpreted as is in heredoc local CR=$'\r' case "$1" in ""|html) cat <<-EOF Content-Type: text/html; charset=utf-8$CR Cache-Control: max-age=1, s-maxage=1, no-cache, must-revalidate, no-store$CR Pragma: no-cache$CR Expires: $(date -Ru)$CR EOF ;; htmlstatic) cat <<-EOF Content-Type: text/html; charset=utf-8$CR Cache-control: max-age=3600$CR EOF ;; download) eval $2 : ${ctype:=application/download} : ${filename:=file.txt} cat <<-EOF Content-Type: ${ctype}$CR Content-Disposition: attachment; filename=${filename}$CR EOF ;; esac # headers are finished with an empty line ending with CR LF echo "$CR" } create_menu () { # read the menu file and create a menu menucache="/tmp/menu_${REMOTE_USER}`echo $menufile | sed 's#/#_#g'`" if ! [ -f "$menucache" ] then sec_close= cursec_print= { while read type prio link desc right do # Include the cgi-specific Language-File if available cginame=`echo "$link" | sed 's/.*\///;s/\.cgi$//'` if [ "$cginame" != '-' ]; then if [ -f /srv/www/lang/$cginame.$lang ] then . /srv/www/lang/$cginame.$lang else [ -f /srv/www/lang/$cginame.en ] && . /srv/www/lang/$cginame.en fi fi eval desc=\"$desc\" case "$type" in t) case "$desc" in Opt) cursec=$_MT_opt ;; *) cursec=$desc ;; esac cursec_print=yes ;; e) if user_has_rights "$right" "view" then if [ -n "$cursec_print" ] then echo "$sec_close"'
  • '"$cursec"'
  • " fi echo "
  • $desc
  • " fi ;; esac done < $menufile echo '' } > $menucache fi cat $menucache } show_html_header () { # usage: show_html_header "[title]" "refresh=$time;url=$url;cssfile=$file;showmenu=no;menufile=$file;marker=foo bar" # get additional options case $2 in "") ;; *) eval $2 ;; esac case $menufile in "") menufile=/etc/httpd/menu ;; *) [ -f $menufile ] || menufile=/etc/httpd/menu ;; esac # get name of opt case x$FORM_link in x) optname=$cginame ;; *) optname="$(echo "$FORM_link" | cut -d? -f1)" ;; esac eval optname=\"$(grep "$optname" "$menufile" | cut -d" " -f4)\" # set title case $1 in "") title=$optname ;; *) title=$1; shift ;; esac case $refresh in "") ;; *[^0-9]*) ;; *[0-9]*) : ${url:=$myname} meta="" ;; esac # if no css-file is specified, try to get file similar to cgi-filename case $cssfile in "") [ -f /srv/www/css/$cginame.css ] && css='' ;; *) css="" ;; esac case $showmenu in no) comment_start='';; *) case $subtitle in "") case $REMOTE_USER in "") user="" ;; *) case $HTTPD_USER_N in 1) user="${REMOTE_USER}@" ;; *) user=''$REMOTE_USER'@' ;; esac ;; esac subtitle="${user}${HOSTNAME}.${DOMAIN_NAME}" ;; esac menu=`create_menu` date=`date` version=$HTTPD_VERSION flihost="${HOSTNAME}.${DOMAIN_NAME}" fli_arch=`uname -m` topnav='
  •  
  • ' ;; esac # save stdout to filedescriptor 3 exec 3>&1 # redirect stdout to a file (everything after the header is supposed to be content) exec 1>/tmp/content_$$.html } show_html_footer () { case $set_debug in yes) echo "
    "
                cat /srv/www/admin/debug.log | htmlspecialchars
                echo "
    " ;; esac # restore stdout exec 1>&3 # do the output http_header # with the redirection we are able to do a little cleaning cat /srv/www/include/header.inc /tmp/content_$$.html /srv/www/include/footer.inc | substitute_markers meta css title topnav subtitle date version menu comment_start comment_end flihost fli_arch $marker | xhtml_cleaning rm -f /tmp/content_$$.html } substitute_markers () { sedstring= for _marker in $* do # we have to escape double quotes, ampersand, dollar substitute=`eval echo '$'${_marker} | sed 's/"/\\\\\"/g; s/&/\\\&/g; s/\\\$/\\\\\$/g'` if [ $_marker = "menu" ] then substitute2=${substitute} else substitute2=${substitute//%/\\%} fi sedstring="${sedstring}s%###${_marker//%/\\%}###%${substitute2}%g; " done eval sed \"$sedstring\" } translate_label () { local label=`echo "${1}" | sed -e 's/ /\ /g'` if [ -z "${label}" ] then label="missing translation" fi echo "${label}" } xhtml_cleaning () { # do a very basic xhtm cleaning, remove unused markers # todo strtolower of tags #img,br,hr,meta,link,base,area,input,param,col # HTTPD_GUI_XHTML_CLEANING is set on boottime by rc430.httpd eval sed $HTTPD_GUI_XHTML_CLEANING -e 's/\(###\)\([^#]*\)\(###\)//g' } # Cleans up standard input such that it can be safely used in eval'd context. # Only letters, digits, dots and underscores are kept. # Input: # = input that shall be cleaned up # Output: # = input free of problematic characters # cleanup_for_eval() { sed 's/[^-.a-zA-Z0-9_]//g' } show_tab_header () { echo '
      ' case $1 in "") echo '' ;; esac # add table cells if no title is given to prevent html error FORM_action="$(echo "$FORM_action" | cleanup_for_eval)" eval selected='"$_'"$mod_prefx$FORM_action"'"' selected="$(echo "$selected" | cleanup_for_eval)" cols=0 while [ "x$1" != "x" ] do local cleantabcaption="$(echo "$1" | cleanup_for_eval)" if [ "$cleantabcaption" = "$selected" -o "$2" = "no" ] then echo '
    • '$1'
    • ' else echo '
    • '$1'
    • ' fi shift 2 cols=`expr $cols + 3` done echo '
    ' echo '
    ' } show_tab_footer () { echo '
    ' } show_backlink () { echo "<< $_MN_bck" } show_box () { # Error: err, Info: info echo "
    " show_tab_header "$2" no if [ "$3" ]; then echo "$3" else while read line; do echo "$line" done fi show_tab_footer echo '
    ' } show_error () { show_box "err" "$1" "$2" } show_warn () { show_box "warn" "$1" "$2" } show_info () { show_box "info" "$1" "$2" } # miscellaneous helpful functions do_tail () { tail -n $1 } get_dns_name () { res= set -- `nslookup $1 | sed -n -e '/^Server:/,/^Address/d;s/^Address[^:]*://p'` [ "$2" ] && res=$2 } have_imond () { [ -f /var/run/imond.port ] && return 0 || return 255 } htmlspecialchars () { # escape html entities # if the first parameter is set to "quot" or "apos", # also espace double/single quotes case $1 in quot) sed 's/\&/\&/g; s//\>/g; s/\"/\"/g;' ;; apos) sed 's/\&/\&/g; s//\>/g; s/'"'"'/\'/g;' ;; *) sed 's/\&/\&/g; s//\>/g;' ;; esac } url_encode () { echo "$*" | sed 's/%/%25/g s/ /%20/g s/ /%09/g s/!/%21/g s/"/%22/g s/#/%23/g s/\$/%24/g s/\&/%26/g s/'\''/%27/g s/(/%28/g s/)/%29/g s/\*/%2a/g s/+/%2b/g s/,/%2c/g s/-/%2d/g s/\./%2e/g s/\//%2f/g s/:/%3a/g s/;/%3b/g s//%3e/g s/?/%3f/g s/@/%40/g s/\[/%5b/g s/\\/%5c/g s/\]/%5d/g s/\^/%5e/g s/_/%5f/g s/`/%60/g s/{/%7b/g s/|/%7c/g s/}/%7d/g s/~/%7e/g s/�/%f6/g s/�/%fc/g s/�/%e4/g s/�/%d6/g s/�/%dc/g s/�/%c4/g :a $!{N ba } s/\n/%0d/' || return 1 # the last five lines are the reason why sed is uncool - just # replacing the newlines by %0d } cgi_log() { if [ -f /var/run/syslogd.pid ]; then logger -t "$0[$$]" "$1" else if cgi_script; then echo "
    $0[$$]: $1
    " else echo "$0[$$]: $1" fi fi } cgi_log_errors() { if [ -s "$2" ]; then cgi_log "Errors while rendering '$1'" while read line; do cgi_log "$line" done < $2 fi }