From 55274429cee12e7a0c66f87fffcc98560a8da0e1 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Tue, 18 Dec 2018 19:42:30 +0300 Subject: [PATCH 1/9] Dynamically get path to bash bash is not /bin/bash on some systems, especially BSD OSes --- bashlib.in | 2 +- configure.in | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bashlib.in b/bashlib.in index bcdae1c..74df6d7 100644 --- a/bashlib.in +++ b/bashlib.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!@BASH@ # Author: darren chamberlain # Co-Author: Paul Bournival diff --git a/configure.in b/configure.in index a0ce2f1..4b74b94 100644 --- a/configure.in +++ b/configure.in @@ -28,6 +28,7 @@ bashlib_version=0.5 AC_INIT(bashlib.in) +AC_PATH_PROG(BASH, bash, "") AC_PATH_PROG(AWK, awk, "") AC_PATH_PROG(CAT, cat, "") AC_PATH_PROG(CUT, cut, "") From fdf18135cfcee3de31f289423fff406712899d35 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Wed, 19 Dec 2018 17:22:17 +0300 Subject: [PATCH 2/9] Fix function definitions (did not work with Bash 4) --- bashlib.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bashlib.in b/bashlib.in index 74df6d7..6e2c250 100644 --- a/bashlib.in +++ b/bashlib.in @@ -153,11 +153,11 @@ fi # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # Shameless plug, advertises verion. -version { +version() { echo "bashlib, version ${VERSION}" } -version_html { +version_html() { echo -n "bashlib," echo "version ${VERSION}" } From 16ddf20f20df131e12046a443bdea7051ea559b1 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Mon, 29 Apr 2019 00:38:35 +0300 Subject: [PATCH 3/9] Add examples --- examples/bashlib.sourceforge.net_backup.html | 111 +++++++++++++++++++ examples/promo-codes.sh | 52 +++++++++ 2 files changed, 163 insertions(+) create mode 100644 examples/bashlib.sourceforge.net_backup.html create mode 100644 examples/promo-codes.sh diff --git a/examples/bashlib.sourceforge.net_backup.html b/examples/bashlib.sourceforge.net_backup.html new file mode 100644 index 0000000..8642fd7 --- /dev/null +++ b/examples/bashlib.sourceforge.net_backup.html @@ -0,0 +1,111 @@ + + + bashlib - CGI programming with the bash shell + + +
+

bashlib - CGI programming with the bash shell

+ + [ Project Page + | Why? + | bashlib news + | How it came about + | Using bashlib ]
+ + [ CVs eXtender + | Something you don't like? + | Getting bashlib + | Other Resources + | Comments? ] +
+
+

Why?

+

bashlib is a shell script that makes CGI programming in the bash shell easier, or at least more tolerable. It contains a few functions that get called automatically and place form elements (from POSTs and GETs) and cookies in your environment. It also contains complete documentation on how to use these variables and how to set cookies manually.

+

Recent bashlib News

+

The most recent version of bashlib will always be available from http://bashlib.sourceforge.net/src/bashlib-current.tar.gz and will + be browsable at http://bashlib.sourceforge.net/src/bashlib-current/.

+

Version 0.4 (download or browse) of bashlib, released March 12, 2002, is fully autoconfiscated. To install it, run ./configure as usual. If you check out the CVS version, you'll need autoconf installed to create the configure script from configure.in.

+

I released version 0.3 (download or browse)of bashlib on February 21, 2001. The only difference between 0.3 and 0.2 is that the tarball works. I've been testing it for a while, and it definitely seems stable enough for real use. The interface has changed a little; the sample below reflects these changes.

+

How this came about, and what it is useful for

+

Things such as this are born of necessity. My ISP, while being incredibly useful in most ways, doesn't have a recent version of Perl available for their casual users (e.g., dial-up accounts, with web pages in http://www.isp.net/~mylogin/) -- Perl is a "value-added" service. This was a great source of frustration for me, since I am a Perl programmer by day. So, I began rooting (not literally) around for other methods of writing CGI scripts, and realized that the shell, which I spent most of my time using, was not only a great generaly purpose scripting environment, but also a good one for CGI scripts. This naturally led me to forms and cookies, and here we are today.

+

No, I really don't have this much free time. The current release is the result of about a days worth of work (on and off throughout the day), with some help. Well, that's not quite true -- 9 years of using Unix went into it as well.

+

Using bashlib

+

Using bashlib is pretty straight-forward. More important, however, is knowing what to do with the variables once they come into your script and knowing how to write CGI scripts. (This script is not running here, for obvious reasons.)

+
+#!/bin/bash
+
+# this sources bashlib into your current environment
+. /usr/local/lib/bashlib
+
+echo "Content-type: text/html"
+echo ""
+
+# OK, so we've sent the header... now send some content
+echo "<html><title>Crack This Server</title><body>"
+
+# print a "hello" if the username is filled out
+username=`param username`
+if [ -n "x$username" != "x" ] ; then
+    echo "<h1>Hello, $username</h1>
+fi
+
+echo "<h2>Users on `/bin/hostname`</h2>"
+echo "<ul>"
+
+# for each user in the passwd file, print their login and full name
+# bold them if they are the current user
+for user in $(cat /etc/passwd | awk -F: '{print $1 "\t" $5}') ; do
+    echo "<li>"
+    if [ "$username" = "$user" ] ; then
+        echo "<strong>$user</strong>"
+    else
+        echo "$user"
+    fi
+    echo "</li>"
+done
+echo "</ul>"
+echo "</body></html>"
+  
+ + + +

Other Resoruces

+
    +
  • I recommend checking out bashish if you use bash often; it is dedicated to the configuration of bash. Although it isn't helpful for CGI programming in bash, it makes day to day usage of bash quite nice. To quote:
  • +
    +Bashish is a theme engine for the console.
    +It lets you customize title, prompt, background, foreground, colors, font and a lot of other things.
    +Bashish is also very configurable, you can turn on and off nearly all features.
    +
    +
  • ^txt2regex$ is a Regular Expression "wizard", all written with bash2 builtins, that converts human sentences to RegExs. with a simple interface, you just answer to questions and build your own RegEx for a large variety of programs, like awk, ed, emacs, grep, perl, php, procmail, python, sed and vim. there are more than 20 supported programs. it's bash so download and run, no compilation needed.
  • +
  • For folks who do a lot of command-line-based web work, surfaw might be useful:
  • +
    + Surfraw (Shell Users' Revolutionary Front Rage Against the Web) provides a Unix command line interface to a variety of popular Web search engines and sites, including Google, Altavista, Babelfish, Raging, DejaNews, Research Index, Yahoo!, WeatherNews, Slashdot, freshmeat, and many others. +
    +
  • The BASH Programming - Introduction HOW-TO and Advanced Bash-Scripting HOWTO: A guide to shell scripting, using Bash are very, very useful.
  • +
  • I just came across Prentice Hall's 1996 book Portable Shell Programming, and it is wonderful. All the examples are pure Bourne shell, so they are (naturally) portable, and also very informative.
  • +
  • And, finally, while it's not free, David Tansley's Linux & Unix Shell Programming is a wonderful resource (get it from fatbrain).
  • +
+ + + +

Something you don't like?

+

OK, so there's probably something in here you think should be different, could be better, etc. Well, drop me a line (email me at dlc@users.sourceforge.net) and let me know. You can write it out in words ("bashlib should uuencode GIFs on the fly"), provide a patch (via diff -u), or rewrite the whole thing (try to keep it in shell, though). All reasonable emails will be read, and probably answered as well.

+ + + +

Getting bashlib

+

bashlib is a pretty short script (as libraries go), and all versions can be browsed here. It is available for download from Sourceforge at http.

+

bashlib is also available from anonymous CVS. The CVS repository can be checked out through anonymous (pserver) CVS. When prompted for a password for anonymous, simply press the Enter key.

+
+cvs -d:pserver:anonymous@cvs.bashlib.sourceforge.net:/cvsroot/bashlib login 
+cvs -z3 -d:pserver:anonymous@cvs.bashlib.sourceforge.net:/cvsroot/bashlib co bashlib
+
+
+ SourceForge Logo +
+ diff --git a/examples/promo-codes.sh b/examples/promo-codes.sh new file mode 100644 index 0000000..781c5bd --- /dev/null +++ b/examples/promo-codes.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# CGI script +# Does not work with FastCGI (fcgi) because it requires additional communication, see https://unix.stackexchange.com/a/241694 +set -e +set -f +#set -u # BAH01215: ./bashlib: line 82: value: unbound variable + +# https://stackoverflow.com/questions/3919755/how-to-parse-query-string-from-a-bash-cgi-script + +# source bashlib https://github.com/mikhailnov/bashlib +. ./bashlib 2>/dev/null || . bashlib || ( echo "Failed to source bashlib!" ; exit 1 ) + +# get file with promo codes +for file in './promo_codes_1.txt' '/var/www/domain.tld/promo_codes_1.txt' +do + [ -f "$file" ] && file_codes="$file" && break +done + +do_redirect_back(){ +code_error_type="${code_error_type:-неверный}" +echo -n " + +
+Ошибка: вы ввели ${code_error_type} промо-код! +
+
+
" +} + +do_redirect_forward(){ +redir_URL='https://domain.tld/page2' +echo -n " + + + + + +Вы будете перенаправлены на страницу записи. Если она не открылась, перейдите по ссылке. +" +} + +write_used_code(){ + # used codes will be converted to empty lines + # TODO: check if this file is writable and redirect back in case of error + sed -e "s/${code}//g" -i "$file_codes" +} + +code="$(param code)" +if grep -q "$code" "$file_codes" + then write_used_code && do_redirect_forward # don't redirect if failed to write_used_code + else do_redirect_back +fi From 158390f6eb5355e2a978966623cfbe06c5323d09 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Sat, 27 Jun 2020 13:21:04 +0300 Subject: [PATCH 4/9] Do not confuse emails which names start with the same characters (e.g. email and emails) --- bashlib.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bashlib.in b/bashlib.in index 6e2c250..39fddc0 100644 --- a/bashlib.in +++ b/bashlib.in @@ -20,7 +20,7 @@ PATH=/bin:/usr/bin # # Set version number # -VERSION="0.05" +VERSION="0.06" # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Initialization stuff begins here. These things run immediately, and @@ -178,7 +178,7 @@ param() { if [ $# -eq 1 ]; then name=$1 name=$(echo ${name} | @SED@ -e 's/FORM_//') - value=$(@ENV@ | @GREP@ "^FORM_${name}" | @SED@ -e 's/FORM_//' | @CUT@ -d= -f2-) + value=$(@ENV@ | @GREP@ "^FORM_${name}=" | @SED@ -e 's/FORM_//' | @CUT@ -d= -f2-) elif [ $# -gt 1 ]; then name=$1 shift From 582b4171ea7865404115b08d741e0cc8d361d0e5 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Wed, 20 Jan 2021 19:35:35 +0300 Subject: [PATCH 5/9] Do not loose empty space from params --- bashlib.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bashlib.in b/bashlib.in index 39fddc0..b0c0ed0 100644 --- a/bashlib.in +++ b/bashlib.in @@ -186,7 +186,9 @@ param() { else value=$(@ENV@ | @GREP@ '^FORM_' | @SED@ -e 's/FORM_//' | @CUT@ -d= -f1) fi - echo ${value} + # "+" is URL-encoded as "%2B", web server replaces spaces with "+", replace back, + # otherwise safe_param() just removes the "+" sign and looses the space. + echo "${value}" | @SED@ -e 's/+/ /' unset name unset value } From 8a5cc81ddc6780363b3fa0c6ecae2119b8555bd2 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Mon, 21 Feb 2022 18:58:35 +0300 Subject: [PATCH 6/9] Bump version, enable integer comparison of versions if needed, some clean up --- bashlib.in | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/bashlib.in b/bashlib.in index b0c0ed0..6ee50e8 100644 --- a/bashlib.in +++ b/bashlib.in @@ -2,16 +2,9 @@ # Author: darren chamberlain # Co-Author: Paul Bournival +# Co-Author: Mikhail Novosyolov # -####### -# Updated Oct 15 2004 by Tony Clayton -# * add safe_param() function with XSS and shell-invocation prevention -# * add extra "| tr -d '$`'" sanity check to name decoding to prevent shell -# invocation of param names. -# * ported function defs to be bash/ash compatible -####### - # bashlib is used by sourcing it at the beginning of scripts that # needs its functionality (by using the . or source commands). @@ -19,8 +12,9 @@ PATH=/bin:/usr/bin # # Set version number +# Must be an integer because bash cannot compare float numbers # -VERSION="0.06" +VERSION="2" # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Initialization stuff begins here. These things run immediately, and From fc8ef054d417dece50242dbbb6acd8fca0ffa4f4 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Tue, 16 Apr 2024 16:00:25 +0300 Subject: [PATCH 7/9] upd copyright --- configure.in | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.in b/configure.in index 4b74b94..68c2783 100644 --- a/configure.in +++ b/configure.in @@ -4,6 +4,7 @@ dnl $Id$ dnl ---------------------------------------------------------------------- dnl bashlib dnl Copyright (C) 2002-2005 darren chamberlain +dnl Copyright (C) 2018-2024 Mikhail Novosyolov dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by From 9f7c0932d1f5a727003a9876be219c155692ab07 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Tue, 16 Apr 2024 16:00:52 +0300 Subject: [PATCH 8/9] use bash built-in printf and echo to speed up things, no need in external binaries --- bashlib.in | 22 +++++++++++----------- configure.in | 2 -- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/bashlib.in b/bashlib.in index 6ee50e8..3caff41 100644 --- a/bashlib.in +++ b/bashlib.in @@ -36,7 +36,7 @@ fi if [ -n "${QUERY_STRING}" ]; then # name=value params, separated by either '&' or ';' if echo ${QUERY_STRING} | grep '=' >/dev/null ; then - for Q in $(@ECHO@ ${QUERY_STRING} | @TR@ ";&" "\012") ; do + for Q in $(echo ${QUERY_STRING} | @TR@ ";&" "\012") ; do # # Clear our local variables # @@ -48,12 +48,12 @@ if [ -n "${QUERY_STRING}" ]; then # get the name of the key, and decode it # name=${Q%%=*} - name=$(@ECHO@ ${name} | \ + name=$(echo ${name} | \ @SED@ -e 's/%\(\)/\\\x/g' | \ @TR@ "+" " ") - name=$(@ECHO@ ${name} | \ + name=$(echo ${name} | \ @TR@ -d ".-") - name=$(@PRINTF@ ${name} | @TR@ -d '$`') + name=$(printf ${name} | @TR@ -d '$`') # # get the value and decode it. This is tricky... printf chokes on @@ -63,7 +63,7 @@ if [ -n "${QUERY_STRING}" ]; then # printf, and then remove it. # tmpvalue=${Q#*=} - tmpvalue=$(@ECHO@ ${tmpvalue} | \ + tmpvalue=$(echo ${tmpvalue} | \ @SED@ -e 's/%\(..\)/\\\x\1 /g') #echo "Intermediate \$value: ${tmpvalue}" 1>&2 @@ -72,7 +72,7 @@ if [ -n "${QUERY_STRING}" ]; then # value # for i in ${tmpvalue}; do - g=$(@PRINTF@ ${i}) + g=$(printf ${i}) value="${value}${g}" done #value=$(echo ${value}) @@ -110,17 +110,17 @@ if [ -n "${HTTP_COOKIE}" ]; then # get the name of the key, and decode it # name=${Q%%=*} - name=$(@ECHO@ ${name} | \ + name=$(echo ${name} | \ @SED@ -e 's/%\(\)/\\\x/g' | \ @TR@ "+" " ") - name=$(@ECHO@ ${name} | \ + name=$(echo ${name} | \ @TR@ -d ".-") - name=$(@PRINTF@ ${name}) + name=$(printf ${name}) # Decode the cookie value. See the parameter section above for # an explanation of what this is doing. tmpvalue=${Q#*=} - tmpvalue=$(@ECHO@ ${tmpvalue} | \ + tmpvalue=$(echo ${tmpvalue} | \ @SED@ -e 's/%\(..\)/\\\x\1 /g') #echo "Intermediate \$value: ${tmpvalue}" 1>&2 @@ -129,7 +129,7 @@ if [ -n "${HTTP_COOKIE}" ]; then # value # for i in ${tmpvalue}; do - g=$(@PRINTF@ ${i}) + g=$(printf ${i}) value="${value}${g}" done #value=$(echo ${value}) diff --git a/configure.in b/configure.in index 68c2783..4d2bb24 100644 --- a/configure.in +++ b/configure.in @@ -34,13 +34,11 @@ AC_PATH_PROG(AWK, awk, "") AC_PATH_PROG(CAT, cat, "") AC_PATH_PROG(CUT, cut, "") AC_PATH_PROG(CP, cp, "") -AC_PATH_PROG(ECHO, echo, "") AC_PATH_PROG(ENV, env, "") AC_PATH_PROG(GREP, grep, "") AC_PATH_PROG(GZIP, gzip, "") AC_PATH_PROG(INSTALL, install, "") AC_PATH_PROG(MKDIR, mkdir, "") -AC_PATH_PROG(PRINTF, printf, "") AC_PATH_PROG(RM, rm, "") AC_PATH_PROG(SED, sed, "") AC_PATH_PROG(TAR, tar, "") From 4b2328b1a8e2dea8756da8df5c050fb41b388760 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Tue, 16 Apr 2024 16:24:58 +0300 Subject: [PATCH 9/9] add another simple example --- examples/write-to-file.sh | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 examples/write-to-file.sh diff --git a/examples/write-to-file.sh b/examples/write-to-file.sh new file mode 100755 index 0000000..d76ebf0 --- /dev/null +++ b/examples/write-to-file.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Example request: +# http://localhost/cgi-bin/r8168.cgi?rev=0x00&probe=b0cdd5070e + +# https://github.com/mikhailnov/bashlib, https://abf.io/import/bashlib +. bashlib ||{ echo "Failed to source bashlib!" ; exit 1 ;} + +readonly file="/var/www/r8168.list" +readonly lock="/var/www/r8168.lock" +readonly rev="$(safe_param rev)" +readonly probe="$(safe_param probe)" + +# possible values: 0x15, 0x09 +if ! [[ "$rev" =~ ^0x..$ ]]; then + echo "Status: 400 Bad request" + echo "Content-Type: text/plain; charset=utf-8" + echo "" + echo "Incorrect value of rev" + exit 1 +fi + +if [ ${#probe} -gt 20 ] || ! [[ "$probe" =~ ^[a-zA-Z0-9]+$ ]]; then + echo "Status: 400 Bad request" + echo "Content-Type: text/plain; charset=utf-8" + echo "" + echo "Incorrect value of probe" + exit 1 +fi + +set -e +echo "$rev;$probe" | flock "$lock" tee -a "$file" >/dev/null +echo "Status: 200 OK" +echo "Content-Type: text/plain; charset=utf-8" +echo "" +echo "OK"