webash‎ > ‎

doc_en

Webash


Bash for Web

A "dialog" concept



Documentation

CGI technology works like a ping-pong game “a’ trois” , and the three players are:

browser <-> http server <-> CGI program

Browser asks for CGI page to http server, after that, through a click in a possible form, it sends form data to http server which passes them on via StdIn to CGI program itself; the latter processes them and re-sends the reply via StdOut to http server, which will pass it on to browser. There is not a session management system, so it’s the CGI programmer who has to have fancy.

Webash implements a system like this: "take input -> go to right point -> process -> give output and exit".

Since script exits, to keep data Webash provides two functions "set_variable_cgi" and "read_variable_cgi", besides providing, obviously, a mechanism to "remember" at which point in the processing flow the CGI program was, when it exited. These two data types, that is “variables” which have to survive the program exit, and session management data ( = variable “${form_count}” – set by “set_cookie [n]” command - ), are stored in a file whom will be removed when CGI program will use the last function: “final_message_cgi()”.

And now, enter Webash:

# char_max_number_CONTENT_LENGTH=150

# verify_CONTENT_LENGTH (void)
#
# MYSQL_user="please_set_this_variable"
# MYSQL_password="
please_set_this_variable"

#

#PRE-FORMATTED MESSAGE: pre_message__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "This is a pre-formatted message …"

#

#MESSAGE: message__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "This is a message …"

#

#ALERT MESSAGE: alert_message__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "Warning, dull boy ..."

#

#OK MESSAGE: ok_message__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "Bravo , you did the job ..."

#

#FINAL MESSAGE: final_message__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "[URL_TO_REDIRECT_THE_USER]" "Bravo , happy googling..."

#

#MENU: options=("John and Franca" "Foo" "Bar and Bubba and Big Dull" ) && menu__cgi "<progressive form number>"(opt.) "[page color]" "[text color]"

#     options=("John and Franca" "Foo" "Bar and Bubba and Big Dull" ) => ${options[${menu_choice}]}

#

#INPUT: input__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "[text|password]" "variable_1" "[variable_1's value]" "[text|password]" "variable_2" "[variable_2's value]" "[text|password]" "variable_n" "[variable_n's value]"...

#

#INTERACTIVE TABLE: table__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "[table color]" "[table text color]" "This is my interactive table …" "1 2 3

#                                                                             4 5 6"

#

#NOT INTERACTIVE TABLES: not_interactive_tables__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "[table color]" "[table text color]" "table_name_1,table_name_2,table_name_n"   "  \"table_name_1\" \"1\" \"NULL\" \"3\"

#                                                                  \"4\" \"5\" \"6\"

#                                                                 \"NULL\" \"8\" \"9\"

#                                                    \"table_name_2\" \"a\" \"b\" \"c\"

#                                                                  \"NULL\" \"e\" \"f\"

#                                                                   \"g\" \"h\" \"i\"

#                                                    \"table_name_n\" \"ga s\" \"ad sf\" \"NULL\"

#                                                                   \"sg f\" \"werg\" \"rr rg\"

#                                                                   \"aaa\" \"c bv\" \"ar h\"  "

#

#UPLOAD FILE: file_upload__cgi "<progressive form number>"(opt.) "[page color]" "[text color]" "[file extension]" "[MAX dimension in kb]"

#     => ${uploaded_file_name}

#

#

##get_all_mysql_table_ids "[database name]" "[table name]" "<order by column>"(optional)

#

##read_mysql "[database name]" "[column_1,column_2,etc.]" "[table name]" "<order by column>"(optional)

#

##output_fields_in_tabs__quoted__and__changing_empty_fields_in_NULL "field1[tab]f.2[tab]f.3

#                                                                       f.4[tab][tab]f.6                                                                                 [tab]f.8[tab]f.9 "

#

##read_mysql_row "[database name]" "[id]" "[table name]"

#

##insert_mysql "[database name]" "[column_1,column_2,etc.]" "[table name]" "['value_1','value_2',etc.]"

#

##change_empty_values_in_NULL "variable_name_1" "variable_name_2" etc.

#

##cancel_mysql "[database name]" "[ref. column]" "[table name]" “[value if found, mysql deletes the row]”

#

##update_mysql "[database name]" "[ref. column]" "[table name]" "[ value if found, mysql updates the row]" "[column_1='value_1',column_2='value_2',etc.]"

#

##find_values_in_mysql_row "[database name]" "[column_1,column_2,etc]" "[table name]" "[value_1,value_2,etc.]"

#

##set_variable__cgi "[variable_name]" "[variable value]"

##read_variable__cgi "[variable_name]"

#

#

#

#

#still to do ... (see below)

## 1) wait_please_dear_user [n] (n = seconds)

## 2) ask_for_confirm "Continue?"

      #confirm=${?}

      #if [ "${confirm}" -eq 0 ] #"OK"

      #     then

      #     bla-bla

      #elif [ "${confirm}" -eq 1 ] #"Do’h"

      #     then

      #     bla-bla

      #fi

 

 

Tutorials

First step:
type visudo at prompt and append a row like this:
apache ALL=/bin/false,NOPASSWD:/usr/local/bin/appendi_stringa_in_file
then exit
(:wq) .
IMPORTANT: You have to download and compile urldecode.c & urlencode.c, then copy the binaries urldecode and urlencode in your /usr/local/bin directory, in order to make input() be able to parse StdIn arguments !  ( See download section. )


We’ll create 3 programs: the first only to show Webash, second and third a little bit more useful…

1) Tell_Me_How_Do_You_Feel.cgi

Rather useless: it helps just to demonstrate Webash library potential. Launch a text editor ( I use  Kwrite ) and save file as : “Tell_Me_How_Do_You_Feel.cgi”, then move it in your http server’s directory “/var/www/cgi-bin” ( I use Apache ).

#!/bin/bash

#you do know this for what‘s used for…

#

source /path/to/Webash

#“include lib”…

#

if [ ! -d "${Dir_cookies}" ]

      then

      mkdir "${Dir_cookies}"

      if [ ! -d "${Dir_cookies}" ]

            then

            alert_message__cgi "1" "red" "black" "Alert...\n \"\${Dir_cookies}\" doesn't exist..."

      fi

fi

#

input

# ”input()” is a kick ass function: it understands if an upload is starting, in that case it proceeds for getting the file then makes program exit, otherwise goes ahead , and IF browser sends anything to server (obviously this happens only if user clicks form’s button OK) then input() sets “${remote_browser_data}” variable ; after this check, and possibly the variable setting, it returns and gives back the control to “main()” …

#

[ -z "${remote_browser_data}" ] && \

 \

set_cookie "1" && \

 \

      {

      #

      message__cgi \

      "darkkhaki" "black" \

      "Hi ! \nThere are animals and flowers ...\nyou have to choose wich you feel yourself as, today ... "

      # if "${remote_browser_data}" is not set, CGI program sends to browser a form web page and exit from the program logical flow … ( this is the FIRST page sent from CGI program when the user's browser, for first time, points to CGI program URL – in that case ${remote_browser_data} variable doesn't exist yet - ) …

      }

# if, on the other hand, the prior condition is NOT verified ( = the variable is already set ) , flow goes ahead…

#

create_variables_from_form

#translates all forms' ${remote_browser_data} data, in distinct variables …

#

#react_to_error

#this is a custom function …

#

check_cookie

#afraid that user could change session data? check_cookie() securely matches session data from browser with those it expects at that point ( stored in a file ) …

#

[[ ${form_count} = 1 ]] && \

 \

set_cookie "2" && \

 \

      {

      #

      #NOT INTERACTIVE TABLES

not_interactive_tables__cgi \

"#D3D3D3" "black" "gray" "white" \

"animals,flowers" \

"  \"animals\" \"NULL\" \"animals\" \"NULL\"

                       \"1\" \"Workhorse\" \"NULL\"

                       \"2\" \"Bull\" \"NULL\"

     \"3\" \"Bengala Tiger\" \"(my prefered)\"

                       \"4\" \"Canary\" \"NULL\"

         \"flowers\" \"NULL\" \"flowers\" \"NULL\"

                     \"1\" \"Gillyflower\" \"NULL\"

   \"2\" \"Rose\" \"NULL\"

                     \"3\" \"Happiness Lotus\" \"NULL\"

                     \"4\" \"Violet\" \"NULL\"

   \"5\" \"Geranium\" \"(my prefered)\"

                     \"6\" \"Chrysanthemum\" \"NULL\"    "

      }

#

[[ ${form_count} = 2 ]] && \

 \

set_cookie "3" && \

 \

      {

      #

      #MENU

      options=("Workhorse" "Bull" "Bengala Tiger" "Canary") && menu__cgi \

      "#90EE90" "black"

      }

#

[[ ${form_count} = 3 ]] && \

 \

set_cookie "4" && \

 \

      {

      #( since program did exit after prior page output, “${options[@]}” array was lost, and we need to re-set it … )

#

      options=("Workhorse" "Bull" "Bengala Tiger" "Canary")

      #

      message__cgi \

      "#E0FFFF" "black" \

      " Hi ! ... \nElement ${menu_choice} of array \${options[@]} is: \"${options[${menu_choice}]}\" ...)"

      }

#

[[ ${form_count} = 4 ]] && \

 \

set_cookie "5" && \

 \

      {

      #

      alert_message__cgi \

      "white" "red" \

      " This is an alert message... "

      }

#

[[ ${form_count} = 5 ]] && \

 \

set_cookie "6" && \

 \

      {

      #

      ok_message__cgi \

      "white" "blue" \

      " This is an ok message... "

      }

#

[[ ${form_count} = 6 ]] && \

 \

set_cookie "7" && \

 \

      {

      #

      pre_message__cgi \

      "white" "black" \

      " This is a PRE-formatted message...

 

Nel mezzo del cammin

Di nostra vita

Mi ritrovai

In una selva oscura

 

       ….Bye,bye!

 

 

 

"

      }

#

[[ ${form_count} = 7 ]] && \

 \

set_cookie "8" && \

 \

      {

      #

      input__cgi \

      "#87CEFA" "black" \

      "text" "User_Defined_Variable_1" "NULL" \
      "password" "User_Defined_Variable_2" "NULL" \
      "text" "User_Defined_Variable_3" "NULL"

      }

#

[[ ${form_count} = 8 ]] && \

 \

set_cookie "9" && \

 \

      {

      #now let's save “${User_Defined_Variable_nth}” variables as session permanent variables…

      set_variable__cgi "User_Defined_Variable_1" "${User_Defined_Variable_1}"
      set_variable__cgi "User_Defined_Variable_2" "${User_Defined_Variable_2}"
      set_variable__cgi "User_Defined_Variable_3" "${User_Defined_Variable_3}"

      #

      message__cgi \

      "darkkhaki" "black" \

      " Please, choose wich flower you feel yourself as, today ..."

      }

#

[[ ${form_count} = 9 ]] && \

 \

set_cookie "10" && \

 \

      {

      #

      options=("Gillyflower" "Rose" "Happiness Lotus" "Violet" "Geranium" "Chrysanthemum") && menu__cgi \

      "#90EE90" "black"

      }

#

[[ ${form_count} = 10 ]] && \

 \

set_cookie "0" && \

 \

      {

      #

      options=("Gillyflower" "Rose" "Happiness Lotus" "Violet" "Geranium" "Chrysanthemum")

      #

User_Defined_Variable_1=$(read_variable__cgi "User_Defined_Variable_1")
      User_Defined_Variable_2=$(read_variable__cgi "User_Defined_Variable_2")
      User_Defined_Variable_3=$(read_variable__cgi "User_Defined_Variable_3")

      #

      #FINAL MESSAGE & SESSION FILE DELETING…

      final_message__cgi \

      "moccasin" "black" "www.google.it" \

      " OK!!\nYou feel a flower \"${options[${menu_choice}]}\" and \"User_Defined_Variable\" variables were: \"${User_Defined_Variable_1}\" \"${User_Defined_Variable_2}\" e \"${User_Defined_Variable_3}\" ...\n"

      }    

#

#

###

##

#

 

2) Working_Hours_Manager.cgi

Web program for day by day working hours management through MySQL.  Launch a text editor ( I use  Kwrite ) and save file as : “Working_Hours_Manager.cgi”, then move it in your http server’s directory “/var/www/cgi-bin” ( I use Apache ).

First, tough, you must create a mysql database ( I use PHPMyAdmin ) called “webash_test” and two tables: “table_one” (3 columns: “id”-primary-,“user”,”password”) e “table_two” (4 columns: “id”-primary-“date”,”start_hour”,”end_hour”).
( Obviously in table_one there must be at least one row... !! )

Edit Webash and set the two mysql variables ( you MUST do it ) :
MYSQL_user
MYSQL_password
.

#!/bin/bash

#

source /path/to/Webash

#

if [ ! -d "${Dir_cookies}" ]

      then

      mkdir "${Dir_cookies}"

      if [ ! -d "${Dir_cookies}" ]

            then

            alert_message__cgi "1" "red" "black" "Alert...\n \"\${Dir_cookies}\" doesn't exist..."

      fi

fi

#

input

#

[ -z "${remote_browser_data}" ] && \

 \

set_cookie "2" && \

 \

      {

      #

      input__cgi \

      "darkkhaki" "black" \

      "text"      "User"    "NULL" \

      "password"  "Password"  "NULL"

     

      }


#

create_variables_from_form

#

#react_to_error

#

check_cookie

#

[[ ${form_count} = 1 ]] && \

 \

set_cookie "2" && \

 \

      {

      #
            #here the program sends the user if he did some mistakes through command : ‘ set_cookie “1” ‘ …

      #
      #INPUT__CGI

      input__cgi \

      "darkkhaki" "black" \

      "text"      "User"    "NULL" \

      "password" "Password"  "NULL"

      }


#

[[ ${form_count} = 2 ]] && \

 \

      {

      #

      #Let's check the two variables: "User" and "Password"...

      #

      if [ $(echo -n "${User}" | tr -dc [:alnum:] | wc -c) -eq 0 -o $(echo -n "${Password}" | tr -dc [:alnum:] | wc -c) -eq 0 ]

            then

            set_cookie "1" && \

            {

            #

            alert_message__cgi \

            "white" "red" \

            " Please write both fields... "

            }

           

      fi

      #

      foo="$(find_values_in_mysql_row "webash_test" "user,password" "table_one" "${User},${Password}" )"

      if [[ "${foo}" = *YES* ]]

            then

            #

            set_cookie "3" && \

            {

            #

            ok_message__cgi \

            "lightgreen" "black" \

            " Welcome in $(basename ${0}) \ngreat \"${User}\" ... "

            }

      else

            #

            set_cookie "1" && \

            {

            #    

            #MESSAGGIO_DI_AVVISO__CGI

            alert_message__cgi \

            "white" "red" \

            " Sorry, but you are NOT authorized \n or you typed a wrong password ... "

            }

      fi

      #

      #

      }

#if User is validate, let's go ahead with “form_count” = 3 …

#

[[ ${form_count} = 3 ]] && \

 \

set_cookie "4" && \

 \

      {

      #

      table__cgi \

      "darkgray" "black" "gray" "white" \

      "This is the resume of your work activity :" \

      "$(read_mysql "webash_test" "date,start_hour,end_hour" "table_two")"

      }

# “table__cgi()” gives possibility to insert new records, modify or remove those pre-existent ; here the sintax:

#table__cgi "<progressive form number>(opt.)" "[page color]" "[text color]" "[table color]" "[table text color]" "Table introduction" "1 2 3

 #            4 5 6

 #            7 8 9"

#(table rows are splitted by new lines - \n – as those after 3 and 6 … easy, isn't?) …

#When user clicks form's OK, ${Action} variable is set, which can have values:

#Insert

#Modify_[row number]

#Remove_[row number]

#NoAction

#

[[ ${form_count} = 4 ]] && \

 \

      {

      #

      #

      if [[ "${Action}" = Insert ]]

            then

            #

            set_cookie "6" && \

            {

            #

            #INPUT__CGI

            input__cgi "lightskyblue" "black" \

            "text"      "Date"            "NULL" \

            "text"      "Start_Hour"            "NULL" \

            "text"      "End_Hour"        "NULL"

            }

      elif [[ "${Action}" = Modify_* ]]

            then

            #

            set_cookie "7" && \

            {

            #

            id_column_elements_array=( $(get_all_mysql_table_ids "webash_test" "table_two") )

            row_choice=$(echo "${Action}" | cut -d '_' -f '2')

            id_choice=${id_column_elements_array[${row_choice}]}

            #

            row_content="$(read_mysql_row "webash_test" "${id_choice}" "table_two" )"

            #

            set_variable__cgi "id" "${id_choice}"

            #

            message__cgi \

            "white" "red" \

            "You choosed to MODIFY row : \nID=${row_content} "

            }

      elif [[ "${Action}" = Remove_* ]]

            then

            #

            set_cookie "3" && \

            {

            #

            id_column_elements_array=( $( get_all_mysql_table_ids "webash_test" "table_two") )

            row_choice=$(echo "${Action}" | cut -d '_' -f '2')

            id_choice=${id_column_elements_array[${row_choice}]}

            row_content="$(read_mysql_row "webash_test" "${id_choice}" "table_two" )"

            #

            cancel_mysql "webash_test" "id" "table_two" "'${id_choice}'"

            #

            #

            message__cgi \

            "white" "red" \

            "You REMOVED row : \nID=${row_content} "

            #

            }

            #goes back to interactive table…

            #

      elif [[ "${Action}" = NoAction ]]

            then

            set_cookie "9" && \

            {

            #

      message__cgi \

            "darkgray" "black" \

            "You choosed to perform no action ... "

            }

            #goes to final message…

                        #

      fi

      #

      #

      }

#

#“Insert” section…

[[ ${form_count} = 6 ]] && \

 \

set_cookie "3" && \

 \

      {

      #

      change_empty_values_in_NULL "Date" "Start_Hour" "End_Hour"

      #

      insert_mysql "webash_test" "date,start_hour,end_hour" "table_two" "'${Date}','${Start_Hour}','${End_hour}'"

      #

      message__cgi \

      "darkgray" "black" \

      "You inserted : \"'${Date}','${Start_Hour}','${End_Hour}'\" ... "

      }

# => goes back to interactive table ..

#

#begin  “Modify” section …

[[ ${form_count} = 7 ]] && \

 \

set_cookie "8" && \

 \

      {

      #

      id=$(read_variable__cgi "id")

      row_content="$(read_mysql_row "webash_test" "${id}" "table_two" )"

      eval array_row=( ${row_content} )

      #

      input__cgi "lightskyblue" "black" \

      "text"      "Date"      "${array_row[1]}" \

      "text"      "Start_Hour"      "${array_row[2]}" \

      "text"      "End_Hour"  "${array_row[3]}"

      }

#

[[ ${form_count} = 8 ]] && \

 \

set_cookie "3" && \

 \

      {

      #

      change_empty_values_in_NULL "Date" "Start_Hour" "End_Hour"

      #

      id=$(read_variable__cgi "id")

      update_mysql "webash_test" "id" "table_two" "${id}" "date='${Date}',start_hour='${Start_Hour}',end_hour='${End_Hour}'"

      #

      message__cgi \

      "darkgray" "black" \

      "You inserted : \"date='${Date}',start_hour='${Start_Hour}',end_hour='${End_Hour}'\" ... "

      }

#

#end “Modify” section=> goes back to interactive table…

#

#

#

#End program …

[[ ${form_count} = 9 ]] && \

 \

set_cookie "0" && \

 \

      {

      #

      #

     

      final_message__cgi \

      "lightgreen" "black" "www.webash.tk" \

      "Thanks for using \"$(basename ${0})\" "

      }

#

#

###

##

#

 

3) MySQL_Tables_Structure.cgi

Web program to display a mysql database structure. Launch a text editor ( I use  Kwrite ) and save file as : “MySQL_Tables_Structure.cgi”, then move it in your http server’s directory “/var/www/cgi-bin” ( I use Apache ).

#!/bin/bash

#

source /path/to/Webash

#

if [ ! -d "${Dir_cookies}" ]

      then

      mkdir "${Dir_cookies}"

      if [ ! -d "${Dir_cookies}" ]

            then

            alert_message__cgi "1" "red" "black" "Alert...\n \"\${Dir_cookies}\" doesn't exist..."

      fi

fi

#

input

#

[ -z "${remote_browser_data}" ] && \

 \

set_cookie "1" && \

 \

      {

      #

      message__cgi \

      "lightgreen" "black" \

      " Welcome in $(basename ${0})... \n\nPlease select, in next page, a MySQL database\n to see its tables structure !!"

      }

#

create_variables_from_form

#

#react_to_error

#

check_cookie

#

[[ ${form_count} = 1 ]] && \

 \

set_cookie "2" && \

 \

      {

      DB=( $(mysql --batch --force -u ${MYSQL_user} -h localhost -p${MYSQL_password} <<<"SHOW DATABASES;") )

      unset DB[0] && db="${DB[@]}"

      #

      set_variable__cgi "All_Databases" "${db}"

      #

      #MENU

      options=( ${db} ) && menu__cgi \

      "darkkhaki" "black"

      #

      }

#

[[ ${form_count} = 2 ]] && \

 \

set_cookie "3" && \

 \

      {

      #

      All_Databases="$(read_variable__cgi "All_Databases")" && options=( ${All_Databases} )

#

      Database="${options[${menu_choice}]}" && export Database

      #

      tables_with_first_field=( $(mysql --batch --force -u ${MYSQL_user} -h localhost –p${MYSQL_password} <<<"USE ${Database}; SHOW TABLES;" ) )

      unset tables_with_first_field[0] && tables=( ${tables_with_first_field[@]} )

#

      table_names="$(echo "${tables[@]}" | tr ' ' ',' )"

      #

      not_interactive_tables__cgi \

      "darkgray" "black" "gray" "white" \

      "${table_names}" \

      "$(for table in ${tables[@]}

            do

            echo -n "\"${table}\" "

            output_fields_in_tabs__quoted__and__changing_empty_fields_in_NULL "$(mysql --batch --force -u ${MYSQL_user} -h localhost –p${MYSQL_password} <<<"USE ${Database}; DESCRIBE ${table};" )"

      done)"

      #

      }

#

[[ ${form_count} = 3 ]] && \

 \

set_cookie "0" && \

 \

      {

      #

      #FINAL MESSAGE & SESSION FILE DELETING…

      final_message__cgi \

      "lightgreen" "black" "www.webash.tk" \

      "Thanks for using \"$(basename ${0})\" "

      }

#

#

###

##

#

 


Bugs

Programming with Webash is more like BASIC ( with its line numbers and "GOTO" peculiarity ) than like structured flow languages like bash or C.
It's all too bare ( e.g.: input__cgi() doesn't have an user explanation text ).
Function "set_variable__cgi()" must be invoked AFTER "set_cookie()" ( otherwise no destination file is set ).
If you have two Webash CGI programs opened in your browser and one of those reaches final_message__cgi(), then check_cookie() will stop even the other, because it DOESN'T make difference between browser windows ( they are like in same session ). You would not using check_cookie() in order to fix this.
If web user closes the browser before final_message__cgi(), the session file will stay in "Dir_cookies" directory for ever...

 

Comments