@@ -30,7 +30,7 @@ BOTCOMMANDS="-h help init start stop status suspendback resumeback killb
3030# 8 - curl/wget missing
3131# 10 - not bash!
3232#
33- # ### $$VERSION$$ v1.40-0-gf9dab50
33+ # ### $$VERSION$$ v1.45-dev-26-g82a57a7
3434# #################################################################
3535
3636# are we running in a terminal?
@@ -99,11 +99,15 @@ getConfigKey() {
9999 [[ " $1 " =~ ^[-${azAZo9} ,._]+$ ]] || return 3
100100 [ -r " ${BOTCONFIG} .jssh" ] && sed -n ' s/\["' " $1 " ' "\]\t*"\(.*\)"/\1/p' " ${BOTCONFIG} .jssh" | tail -n 1
101101}
102- # escape / remove text characters for json strings, eg. " -> \"
103- # $1 string
104- # output escaped string
102+ # escape characters in json strings for telegram
103+ # $1 string, output escaped string
105104JsonEscape (){
106- sed ' s/\([-"`´,§$%&/(){}#@!?*.\t]\)/\\\1/g' <<< " $1"
105+ sed -E -e ' s/\r//g' -e ' s/([-"`´,§$%&/(){}#@!?*.\t])/\\\1/g' <<< " ${1//$'\n'/\\n}"
106+ }
107+ # clean \ from escaped json string
108+ # $1 string, output cleaned string
109+ cleanEscaped (){ # remove " all \ but \n\u \n or \r
110+ sed -E -e ' s/\\"/+/g' -e ' s/\\([^nu])/\1/g' -e ' s/(\r|\n)//g' <<< " $1"
107111}
108112# check if $1 seems a valid token
109113# return true if token seems to be valid
@@ -157,7 +161,7 @@ debug_checks(){ {
157161 [ -z " $( getConfigKey " botadmin" ) " ] && printf " %(%c)T: %s\n" -1 " Bot admin is missing! =========="
158162 # call user defined debug_checks if exists
159163 _exec_if_function my_debug_checks " $( _date) " " ${where} " " $* "
160- } >> " ${DEBUGLOG} "
164+ } 2> /dev/null >> " ${DEBUGLOG} "
161165}
162166
163167# some Linux distributions (e.g. Manjaro) doesn't seem to have C locale activated by default
@@ -174,10 +178,10 @@ RUNDIR="$(dirname "$0")"
174178MODULEDIR=" ${SCRIPTDIR} /modules"
175179
176180# adjust stuff for source, use return from source without source
177- alias exit_source= ' exit'
181+ exit_source () { exit " $1 " ; }
178182if [[ " ${SCRIPT} " != " ${REALME} " || " $1 " == " source" ]]; then
179183 SOURCE=" yes"
180- [ -z " $1 " ] && alias exit_source= ' printf "Exit from source ...\n";return'
184+ [ -z " $1 " ] && exit_source () { printf " Exit from source ...\n" ; return " $1 " ; }
181185fi
182186
183187# emmbeded system may claim bash but it is not
@@ -271,6 +275,7 @@ if [ -z "${BOTTOKEN}" ]; then
271275 [ -z " ${admin} " ] && admin=' ?'
272276 printf ' ["botadmin"]\t"%s"\n' " ${admin} " >> " ${BOTCONFIG} .jssh"
273277 fi
278+
274279 # setup botacl file
275280 if [ ! -f " ${BOTACL} " ]; then
276281 printf " ${GREY} Create initial ${BOTACL} file.${NN} "
@@ -279,15 +284,14 @@ if [ -z "${BOTTOKEN}" ]; then
279284 # check data dir file
280285 if [ ! -w " ${DATADIR} " ]; then
281286 printf " ${RED} ERROR: ${DATADIR} does not exist or is not writeable!.${NN} "
282- exit_source 2
287+ [ " $1 " != " init " ] && exit_source 2 # skip on init
283288 fi
284289 # setup count file
285290 if [ ! -f " ${COUNTFILE} .jssh" ]; then
286291 printf ' ["counted_user_chat_id"]\t"num_messages_seen"\n' >> " ${COUNTFILE} .jssh"
287292 elif [ ! -w " ${COUNTFILE} .jssh" ]; then
288- printf " ${RED} ERROR : Can't write to ${COUNTFILE} !.${NN} "
293+ printf " ${RED} WARNING : Can't write to ${COUNTFILE} !.${NN} "
289294 ls -l " ${COUNTFILE} .jssh"
290- exit_source 2
291295 fi
292296 # setup blocked file
293297 if [ ! -f " ${BLOCKEDFILE} .jssh" ]; then
342346BASHBOT_RETRY=" " # retry by default
343347
344348URL=" ${BASHBOT_URL:- https:// api.telegram.org/ bot}${BOTTOKEN} "
349+ FILEURL=" ${URL%%/ bot* } /file/bot${BOTTOKEN} "
345350ME_URL=${URL} ' /getMe'
346351
347352# ################
@@ -388,16 +393,6 @@ if ! _is_function jssh_newDB; then
388393 exit_source 6
389394fi
390395
391- # $1 URL, $2 filename in DATADIR
392- # outputs final filename
393- download () {
394- local empty=" no.file" file=" ${2:- ${empty} } "
395- if [[ " ${file} " = * " /" * ]] || [[ " ${file} " = " ." * ]]; then file=" ${empty} " ; fi
396- while [ -f " ${DATADIR:- .} /${file} " ] ; do file=" ${RANDOM} -${file} " ; done
397- getJson " $1 " > " ${DATADIR:- .} /${file} " || return
398- printf ' %s\n' " ${DATADIR:- .} /${file} "
399- }
400-
401396# $1 postfix, e.g. chatid
402397# $2 prefix, back- or startbot-
403398procname (){
@@ -425,19 +420,56 @@ killallproc() {
425420 debug_checks " end killallproc" " $1 "
426421}
427422
428-
429- # $ chat $2 msg_id $3 nolog
430- declare -xr DELETE_URL=${URL} ' /deleteMessage'
431- delete_message () {
432- [ -z " $3 " ] && log_update " Delete Message CHAT=$1 MSG_ID=$2 "
433- sendJson " $1 " ' "message_id": ' " $2 " ' ' " ${DELETE_URL} "
434- }
435-
436- # get download url for file id, $1 file_id
423+ # URL path for file id, $1 file_id
424+ # use download_file "path" to download file
437425get_file () {
438426 [ -z " $1 " ] && return
439427 sendJson " " ' "file_id": "' " $1 " ' "' " ${URL} /getFile"
440- printf " %s\n" " ${URL} /${UPD["result,file_path"]} "
428+ printf " %s\n" " ${UPD["result,file_path"]} "
429+ }
430+ # download file to DATADIR
431+ # $1 URL path, $2 proposed filename (may modified/ignored)
432+ # outputs final filename
433+ # keep old function name for backward compatibility
434+ alias download=" download_file"
435+ download_file () {
436+ local url=" $1 " file=" ${2:- $1 } "
437+ # old mode if full URL is given
438+ if [[ " ${1} " =~ ^https* :// ]]; then
439+ # random filename if not given for http
440+ if [ -z " $2 " ]; then
441+ : " $( mktemp -u -p . " XXXXXXXXXX" 2> /dev/null) "
442+ file=" download-${_# ./ } "
443+ fi
444+ else
445+ # prefix https://api.telegram...
446+ url=" ${FILEURL} /${url} "
447+ fi
448+ # filename: replace "/" with "-", use mktemp if exist
449+ file=" ${DATADIR:- .} /${file// \/ / -} "
450+ [ -f " ${file} " ] && file=" $( mktemp -p " ${DATADIR:- .} " " XXXXX-${file##*/ } " ) "
451+ getJson " ${url} " > " ${file} " || return
452+ # output absolute file path
453+ printf " %s\n" " $( cd " ${file%/* } " > /dev/null 2>&1 && pwd) /${file##*/ } "
454+ }
455+ # notify mycommands about errors while sending
456+ # $1 calling function $2 error $3 chat $4 user $5 error message $6 ... remaining args to calling function
457+ # calls function based on error: bashbotError{function} basbotError{error}
458+ # if no specific function exist try to call bashbotProcessError
459+ processError (){
460+ local func=" $1 " err=" $2 "
461+ [[ " ${err} " != " 4" * ]] && return 1
462+ # check for bashbotError${func} provided in mycommands
463+ # shellcheck disable=SC2082
464+ if _is_function " bashbotError_${func} " ; then
465+ " bashbotError_${func} " " $@ "
466+ # check for bashbotError${err} provided in mycommands
467+ elif _is_function " bashbotError_${err} " ; then
468+ " bashbotError_${err} " " $@ "
469+ # noting found, try bashbotProcessError
470+ else
471+ _exec_if_function bashbotProcessError " $@ "
472+ fi
441473}
442474
443475# iconv used to filter out broken utf characters, if not installed fake it
@@ -461,7 +493,7 @@ sendJson(){
461493 if [ -n " ${BASHBOTDEBUG} " ] ; then
462494 log_update " sendJson (${DETECTED_CURL} ) CHAT=${chat#*: } JSON=${2: 0: 100} URL=${3##*/ } "
463495 # mask " and \ , remove newline from json
464- log_message " DEBUG sendJson ==========\n$( " ${JSONSHFILE} " -b -n <<< " $(sed -E -e 's/\\ " /+/g ' -e ' s/ \\ / \\\\ /g ' -e ' s/( \r | \n )//g ' <<< "${json}")" 2>&1)"
496+ log_message " DEBUG sendJson ==========\n$( " ${JSONSHFILE} " -b -n <<< " $(cleanEscaped " ${json} " )" 2>&1 ) "
465497 fi
466498 # chat id not a number
467499 if [[ " ${chat} " == * " NAN\" ," ]]; then
@@ -477,6 +509,36 @@ sendJson(){
477509 [ -n " ${BASHBOT_EVENT_SEND[*]} " ] && event_send " send" " ${@ } " &
478510}
479511
512+ UPLOADDIR=" ${BASHBOT_UPLOAD:- ${DATADIR} / upload} "
513+
514+ # $1 chat $2 file, $3 calling function
515+ # return final file name or empty string on error
516+ checkUploadFile () {
517+ local err file=" $2 "
518+ [[ " ${file} " = * ' ..' * || " ${file} " = ' .' * ]] && err=1 # no directory traversal
519+ if [[ " ${file} " = ' /' * ]] ; then
520+ [[ ! " ${file} " =~ ${FILE_REGEX} ]] && err=2 # absolute must match REGEX
521+ else
522+ file=" ${UPLOADDIR:- NOUPLOADDIR} /${file} " # others must be in UPLOADDIR
523+ fi
524+ [ ! -r " ${file} " ] && err=3 # and file must exits of course
525+ # file path error, generate error response
526+ if [ -n " ${err} " ]; then
527+ BOTSENT=(); BOTSENT[OK]=" false"
528+ case " ${err} " in
529+ 1) BOTSENT[ERROR]=" Path to file $2 contains to much '../' or starts with '.'" ;;
530+ 2) BOTSENT[ERROR]=" Path to file $2 does not match regex: ${FILE_REGEX} " ;;
531+ 3) if [[ " $2 " == " /" * ]]; then
532+ BOTSENT[ERROR]=" File not found: $2 "
533+ else
534+ BOTSENT[ERROR]=" File not found: ${UPLOADDIR} /$2 "
535+ fi ;;
536+ esac
537+ [ -n " ${BASHBOTDEBUG} " ] && log_debug " $3 : CHAT=$1 FILE=$2 MSG=${BOTSENT[DESCRIPTION]} "
538+ return 1
539+ fi
540+ }
541+
480542
481543#
482544# curl / wget specific functions
0 commit comments