#!/bin/sh
# Command line upload to quickshare + tinyURL support
# by Minas Dasygenis, http://arch.ece.uowm.gr
#
# Check the latest update of this tool at 
# http://arch.ece.uowm.gr/mdasyg/misc/quickshare.sh
#
# Plug and Play install with:
# wget -q http://arch.ece.uowm.gr/mdasyg/misc/quickshare.sh -O /usr/local/bin/quickshare.sh && chmod 755 /usr/local/bin/quickshare.sh
#
# ONLY FOR UOWM Network
#
#ln -s /scripts/system/quickshare.sh /usr/local/bin/sharelsi4
#ln -s /scripts/system/quickshare.sh /usr/local/bin/sharelsi4silent
#ln  -s /scripts/system/quickshare.sh /usr/local/bin/sharesilent
#ln -s /scripts/system/quickshare.sh /usr/local/bin/share
#ln -s /scripts/system/quickshare.sh /usr/local/bin/sharedirect
#ln -s /scripts/system/quickshare.sh /usr/local/bin/shareNOlsi
#
version=26

# Enable the nanyfying of the URL using lsi.gr . If set to 0 then no minimization will happen.
# Note that minimizing the URL involves storing the URL on an external database, other than share.uowm.gr
# which maybe a security issue if you do not want your file to be logged on a third party database.
# If you do not like minimizing the URL then set the following value to 0.
shorturl=1

# Select either to display the directURL (directURLshow=1) or the landing page url of http://share.uowm.gr (directURLshow=2)
if [ x"$directURLshow" != "x" ] ; then
    directURLshow=$directURLshow
    echo "Setting override for directURLshow to [$directURLshow]"
else
    directURLshow=0
fi


UPLOAD_URL="${UPLOAD_URL:-https://share.uowm.gr/upload}"
CONNECT_TIMEOUT="${CONNECT_TIMEOUT:-15}"
MAX_TIME="${MAX_TIME:-1800}"           # 30'
EXPECT100_TIMEOUT="${EXPECT100_TIMEOUT:-10}"




#το connect timeout ήταν 5 αλλά είχα πολλά rc=7 λάθη.
curlretry="-4 --connect-timeout 10 --max-time 10 --retry 3 --retry-connrefused --retry-max-time 30"

# Apple Indicate String:
# Darwin XXXX-Pro-2.local 22.6.0 Darwin Kernel Version 22.6.0: Wed Jul  5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 arm64
theuname=`uname -a`
echo $theuname | grep -q -i Darwin > /dev/null 2>&1
if [ $? -eq 0 ] ; then
    macos=1
else
    macos=0
fi


# Priority is gtimeout
#
which gtimeout > /dev/null 2>&1
if [ $? -eq 0 ] ; then
    tmexec=gtimeout
    tmexecparam=10
fi

# Lets locate the timeout
which timeout > /dev/null 2>&1
if [ -z "$tmexec" -a $? -eq 0 ] ; then
    tmexec=timeout
    tmexecparam=10
fi



if [ -z "$tmexec" ] ; then
    tmexec=""
    tmexecparam=""
fi


#Set enviromental variable LANG to en or el with: 
# setenv QUICKSHARE_LANG en ;export  QUICKSHARE_LANG=en
if [ x"$QUICKSHARE_LANG" = x"en" -o x"$QUICKSHARE_LANG" = x"EN" ] ; then
    lang="en"
else
    lang=`locale | grep CTYPE | cut -d= -f2 | tr -d '"'  |  cut -d_ -f1`
fi

# Lets figure out if the name has the lsi4 which means we will use a minized 4 numbers name
echo $0 | grep -q lsi4
if [ $? -eq 0 ] ; then
    hashsize=4
    charset=1
else
    if [ $directURLshow -eq 0 ] ; then
        hashsize=8
        charset=0
    else
        hashsize=4
        charset=1
    fi
fi
    
echo $0 | grep -q direct
if [ $? -eq 0 ] ; then
    directURLshow=1
    shorturl=0
fi

echo $0 | grep -q silent
if [ $? -eq 0 ] ; then
    silent=1
else
    silent=0
fi

myecho()
{
    if [ $silent -eq 0 ] ; then
        echo "$@"
    fi
}


if [ $directURLshow -eq 1 ] ; then
    myecho "====> WARNING: DirectURL is enabled (possible spam detection at mail filter) <====="
fi

echo $0 | grep -q NOlsi
if [ $? -eq 0 ] ; then
    lsiUSE=0
else
    lsiUSE=1
fi



if [ "$lang" = "el" ] ; then
file="Το αρχείο"
size="με μέγεθος"
available="θα είναι διαθέσιμο έως"
url="στην παρακάτω διεύθυνση URL:"
direct="Απευθείας δεσμός μεταφόρτωσης αρχείου:"
motd="Πρόγραμμα μεταφόρτωσης φλοιού στο share.uowm.gr έκδοσης $version"
uploading="Μεταφόρτωση του"
wsize="με μέγεθος"
printing="Εκτυπώνονται '*' κάθε"
packets="πακέτα"
form=" για "
slots="θέσεις"
slot1="θέση"
done="Ολοκληρώθηκε η μεταφόρτωση"
seconds="δευτερόλεπτα"
speedmsg="ταχύτητα"
or="ή στο συντομευμένο ισοδύναμο:"
missing="Δε βρέθηκε το προαπαιτούμενο πρόγραμμα"
else
file="The file"
size="with size"
available="will be available until"
url="at the following URL:"
direct="Direct URL File Download:"
motd="share.uowm.gr version $version command line upload script"
uploading="Uploading file"
wsize="with size"
printing="Printing '*' every"
packets="packets"
form=" for "
slots="slots"
slot1="slot"
done="Done Uploading"
seconds="seconds"
speedmsg="speed"
or="or the tinyfied alias:"
missing="I could not find the required program"
fi


human_readable_size() {
    if [ -z "$1" ]; then
        echo "Usage: human_readable_size <number of bytes>"
        return
    fi

    bytes=$1
    if [ "$bytes" -lt 0 ]; then
        echo "Error: Input must be a positive number."
        return
    fi

    unit_index=0

    while [ "$bytes" -ge 1000 ]; do
        bytes=$(echo "scale=1; $bytes / 1024" | bc)
        unit_index=$((unit_index + 1))
    done

    case $unit_index in
        0) unit="B";;
        1) unit="KB";;
        2) unit="MB";;
        3) unit="GB";;
        4) unit="TB";;
    esac

    printf "%.1f %s\n" "$bytes" "$unit" ;
}

# Function to check if the short url service is online
check_short_url()
{
ok=1

if [ $lsiUSE -ne 1 ] ; then
    shorturl=0
    export shorturl
    ok=0
fi


# Check if the nanyfying web site is reachable from us
# If it is not reachable just skip it
$tmexec $tmexecparam curl $curlretry -s http://lsi.gr -o /dev/null
if [ $? -ne 0 -a $shorturl -eq 1 ] ; then
    msg="[share] lsi.gr seems inaccessible (curl returned $?)"
    logger $msg
    ok=0
fi

# if the previous version activated and disabled the shorturl
# lets perform one more check
if [ $ok -eq 0 -a $shorturl -eq 1 ] ;then
    $tmexec $tmexecparam curl $curlretry -s http://arch.ece.uowm.gr -o /dev/null
    if [ $? -ne 0 ] ; then
        msg="[share] arch.ece.uowm.gr seems inaccessible (curl returned $?)"
        shorturl=0
        export shorturl
    else
        msg="[share] arch.ece.uowm.gr is online"
        shorturl=1
        export shorturl
    fi
fi

echo $shorturl
return $shorturl
}




short_url()
{
myurl=$1



if [ $shorturl -eq 1 ]; then
# If we have perl and curl we can sorten the url a bit
which perl > /dev/null 2>&1
r1=$?
if [ $r1 -ne 0 ] ; then
    echo $missing " perl "
    shorturl=0
    rc=99
    if [ `uname -s` = "FreeBSD" ] ; then
        pkg install -f -y net/p5-URI
    fi
which perl > /dev/null 2>&1
r1=$?
fi

which curl > /dev/null 2>&1
r2=$?
if [ $r1 -eq 0 -a $r2 -eq 0  ] ; then
    urlNEW=$1
    perl -MURI::Escape -e 'help' > /dev/null 2>&1
    if [ $? -ne 0 ] ; then
        echo $missing " URI/Escape Perl module "
        shorturl=0
        rc=99
        if [ `uname -s` = "FreeBSD" ] ; then
            pkg install -y -f net/p5-URI
        fi
    fi

    if [ $shorturl -ne 0 ] ; then
        directURL="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$urlNEW")" > /dev/null 2>&1
        urlNEW=$directURL
        directURL=`$tmexec $tmexecparam curl $curlretry -s http://lsi.gr/create.php\?hashsize=${hashsize}\&charset=${charset}\&key=76111\&url=$urlNEW || $tmexec $tmexecparam curl $curlretry -s http://arch.ece.uowm.gr/lsi/create.php\?hashsize=${hashsize}\&charset=${charset}\&key=76111\&url=$urlNEW`
        rc=$?
    fi

    if [ -z "$directURL" -o $rc -ne 0 ] ; then
        #curl failed, resort to normal url
        directURL=$myurl
    fi
fi
else
    #User has not specified for minimization, so just return whatever he gave us
    directURL=$myurl
fi

echo $directURL;
}



#entry point main()

#Set enviromental variable silent with: setenv QUICKSHARE_SILENT YES;export  QUICKSHARE_SILENT=YES
if [ $silent -ne 1 ] ;then
    if [ x"$QUICKSHARE_SILENT" = x"YES" ] ; then
        silent=1
    else
        silent=0
    fi
fi

logfile=$HOME/.quickshare.log
logging=0
if [ -w "$logfile" ] ; then
    #change this option if you do not want any logging
    logging=1
fi

if [ $silent -eq 0 ] ; then
myecho "----------------------------------------------------"
myecho $motd
myecho "by Dr Minas Dasygenis"
myecho "http://arch.ece.uowm.gr , 2016-2020"
if [ $logging -eq 1 ] ; then 
    myecho Logging Enabled because I discovered $logfile; else
    myecho If you create $logfile, URLs will be logged there; fi
fi
myecho "----------------------------------------------------"
myecho " "

which python > /dev/null 2>&1
if  [ $? -ne 0 ] ; then
    which python3
    if  [ $? -ne 0 ] ; then
        echo $missing " python "
        shorturl=0
        if [ `uname -s` = "FreeBSD" ] ; then
            pkg install -y -f lang/python
        fi
        exit 4
    else
    executable=python3
    fi
else
    executable=python
fi


blocksize=2048
#number of packets to be transfered per batch it was 1000  (Browser: 1000000 so 2048 * 488)
countpackets=488
packetbytes=`expr $blocksize \* $countpackets`

if [ "$#" -eq 0 ] ; then
    echo 'Quickshare one or more files'
    echo Usage: $0 file0 file1 ....
    echo 'If you set the enviromental variable SILENT, only basic messages will appear:'
    echo 'setenv QUICKSHARE_SILENT YES;export  QUICKSHARE_SILENT=YES'
    echo 'Set the language to en or el with:'
    echo 'setenv QUICKSHARE_LANG en ;export  QUICKSHARE_LANG=en'
    exit 45
fi





which curl > /dev/null 2>&1
if [ $? -ne 0 ] ; then
    echo Requisite program curl not found
    exit 4
fi

# recursion over files with spaces may be problematic here
#
if [ $# -gt 1 ]; then
    massmode=1
else
    massmode=0
fi


for ifile in "$@"
do
    if [ ! -s "$ifile" ] ; then
        echo "File $ifile with 0 Bytes content....Skipping it."
        continue
    fi

    if [ -d "$ifile" ] ; then
        echo "Recursive is not possible into directory $ifile , skipping it."
        continue
    fi

    if [ ! -f "$ifile" ] ; then
        #this file is absent, just skip it
        echo "File $ifile does not seem to exist..."
        exit 7
        continue    
    fi

#lets find out the size
myfilesize=`ls -lHa "$ifile" | awk '{print $5}'`
#myfilesizeh=`human_readable_size $myfilesize`
myfilesizeh=`ls -lHha "$ifile" | awk '{print $5}'`

# If we are sharing multiple files, do not print headers
if [ $massmode -eq 0 ] ; then
if [ $silent -eq 0 ] ; then
    myecho -n "$uploading [$ifile] $wsize [$myfilesizeh] Bytes."
    if [ "$logging" -eq 1 ] ; then
        myecho -n "|LOG| "
    fi
fi
fi
myecho " "


#original starting time
START=$(date +%s)

#lets compute how many POSTS we need
numberposts=`expr $myfilesize / $packetbytes`

#fix for very small
if [ $numberposts -eq 0 ] ; then
    numberposts=1
fi

countersize=`expr $myfilesize / $numberposts`


windowcols=`tput col 2>/dev/null || tput cols`
#lets see if this is a number
expr $windowcols - 3 >/dev/null 2>&1
if [ $? -eq 0 ] ; then
    usable_window_width=`expr $windowcols - 3`
    if [ $usable_window_width -ge 55 ]; then
        usable_window_width=55
    fi
else
    #just a failsafe value
    usable_window_width=30
fi


#if we have too many packets, do limit the max
if [ "$numberposts" -gt "$usable_window_width" ] ; then
    numberposts=$usable_window_width
    countersize=`expr $myfilesize / $numberposts`
fi



mycounter=`myecho $countersize  | $executable -c 'from __future__ import print_function;import sys;import re; print(re.sub(r"(?<=.)(?=(?:...)+$)", ",",sys.stdin.read()));' | head -1`


# If we are sharing multiple files, do not print headers
if [ $massmode -eq 0 ] ; then
if [ $silent -eq 0 ] ; then
    if [ $numberposts -eq 1 ] ; then
        theslot=$slot1
    else
        theslot=$slots
    fi
    myecho "$printing $mycounter $packets $form $numberposts $theslot."
fi
fi



if [ "$numberposts" -lt 1 ]  ; then numberposts=0 ; fi
counter=0

# If we are sharing multiple files, do not print headers
if [ $massmode -eq 0 ] ; then
        if [ $silent -eq 0 ] ; then
            myecho -n "["
        fi
fi

while [ "$counter" -lt "$numberposts" ] ;do
if [ $massmode -eq 0 ] ; then
  if [ $silent -eq 0 ] ; then
    myecho -n .
  fi
fi
counter=`expr $counter + 1`
done

if [ $massmode -eq 0 ] ; then
  if [ $silent -eq 0 ] ; then
    myecho -n "]"
  fi
fi

counter=`expr $counter + 1`
counter=`expr $counter + 1`



if [ "$silent" -eq 0 ] ; then
    #return the cursor back
    printf "\033[${counter}D" 
    #lets reprint the missing char
    if [ $massmode -eq 0 ] ; then
        myecho -n "["
    fi
fi



#Generate our key, its simpler to just give our random key, than wait for the server to give us a random key
ourkey=`od -vAn -N4 -tu4  /dev/urandom|tr -d " "`

#upload the file in parts

#initialy we do not skip anything
skip=0
temp_transfered=0
transfered=0
uploading=1
mypackets=0

respfile=$(mktemp /tmp/quickshare.XXXXXXX)
rcfile=$(mktemp /tmp/quickshare.XXXXXXXX)


while [ $uploading = 1 ] ; do
#2025.04 Timeout may cause a slowdown in speed, lets try to avoid it 
tmexec=""
tmexecparam=""

$tmexec $tmexecparam dd if="$ifile" bs=$blocksize count=$countpackets skip=$skip 2> /dev/null  | { 
response=""
attempt=1
max_attempts=1 # Currently we do not allow re-retry because the server may get a duplicate of the data and added to the upload thus resulting in a bigger file. We should develop a protocol that has a sequence numbering and thus give the sequence and acknowledge the sequence every time



while [ "$attempt" -le "$max_attempts" ]; do
    sleep 0.1
    response="`curl  --retry 5 --retry-connrefused --retry-max-time 30  -s -X POST  --data-binary @- http://share.uowm.gr/bigUpload.php\?action=upload\&key=$ourkey`"
    rc=$?

    echo "$rc" > "$rcfile"
    echo "$response" > "$respfile"

    if [ $rc -eq 0 ]; then
		break  # Success, get out of retry loop
	elif [ $rc -eq 28 ]; then  # 28 is curl's timeout error code
		msg="Timeout occurred on attempt $attempt. Retrying..."
	else
		msg="Attempt $attempt failed with rc=$rc. Retrying..."
	fi
	myecho -n "R"
	attempt=$((attempt + 1))
done


note="Check if the return code of the previous command is not zero"
if [ "$rc" -ne 0 ] ; then
    myecho " ";
	echo "UPLOAD FAILED after [$max_attempts] attempts. Last rc=[$rc]. Response: [$response]"
    if [ $rc -eq 124 ] ; then
        echo "UPLOAD Error. Timeout has occured connecting to share.uowm.gr."
    else
        echo "UPLOAD Error rc=[$rc]. share.uowm.gr replied:[$response]" ;
    fi

    sleep 1 
    printf "\033[0m"
    exit 4 
fi 

echo "$response" | grep -q "ERROR"
if [ $? -eq 0 ] ; then
    echo " "
    echo "UPLOAD Error123. The response is: [$response]";
    printf "\033[0m"
    exit 6;
fi
}

rc=$(cat "$rcfile")
response=$(cat "$respfile")
rm $rcfile
rm $respfile


if [ $rc -ne 0 ] ; then
    uploading=0
    sleep 1
    exit
fi

skip=`expr $skip + $countpackets`
transfered=`expr $transfered + $packetbytes`

# If we are sharing multiple files, do not print headers
if [ $massmode -eq 0 ] ; then
	if [ $silent -eq 0 ] ;then
		printf "\033[31m" 
	fi
fi


# We print a start when we have completed the countersize...
temp_transfered=`expr  $packetbytes +  $temp_transfered`
should_we_print=`expr $temp_transfered / $countersize`
if [ "$should_we_print" -ge 1 ] ; then
    
    # If we are sharing multiple files, do not print headers
    if [ $massmode -eq 0 ] ; then
    if [ $silent -eq 0 ] ; then
        myecho -n "*" 
    fi
    fi
    mypackets=`expr $mypackets + 1`
    extra_packets=`expr $countersize \* $should_we_print`
    temp_transfered=`expr $temp_transfered - $extra_packets`
fi



if [ "$transfered" -ge "$myfilesize" ] ; then
    END=$(date +%s);
    duration=`echo $((END-START))`
    if [ $duration -eq 0 ] ; then duration=1 ; fi
    speed=`expr $myfilesize / $duration`
    myspeed=`echo $speed |  $executable -c 'from __future__ import print_function;import sys;import re; print(re.sub(r"(?<=.)(?=(?:...)+$)", ",",sys.stdin.read()));' | head -1`
    if [ $massmode -eq 0 ] ; then
     if [ $silent -eq 0 ] ; then
        #reset the cursor color
        printf "\033[0m\n" 
        #myecho '] '
        printf "\033[32m"
        myecho "$done [$packets: $mypackets][$seconds: $duration][$speedmsg: $myspeed B/second]"
        printf "\033[0m\n" 
     fi
    fi
    uploading=0
fi

done
#ok upload finished.

#OK, lets close the upload, and fix the filename without spaces
#Remove strange characters, normalize filename
bbname=`basename "$ifile" `
#If the file is .php then /usr/local/bin/quickshare.sh
echo $bbname | grep -qE '(.php)|(.sh)$'
if [ $? -eq 0 ] ; then
    bbname=$bbname."txt"
fi


# Remove characters sets not supported
bname=` echo "$bbname" | sed 's/[^0-9A-Za-zΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΆΈΉΊΌΎΏαβγδεζηθικλμνξοπρσςτυφχψωάέίύήώόϊ.-]/_/g'`


bbname=$bname
#Replace not supported characters- unknown Chars [Note, some transformations with tr alter dramatically the name, like ΰ •, and thus we use sed there
bname=`echo "$bbname" | tr '#' "_" |  tr "@" "_" | sed 's/ΰ/υ/g' | tr -d "]" | tr "ΐ" "ι" |  tr -d "[" |  tr " ," - | tr -d "'" | tr -d "&" |tr -d '(' | tr -d ')' | sed 's/•//g' | tr -s "-" | tr  '=' '.' | tr -s "_" | sed 's/--/-/g'  `

#lets grab the URL
response=`$tmexec $tmexecparam curl -s $curlretry -d name="$bname" -dkey="$ourkey" http://share.uowm.gr/bigUpload.php\?action=finish`

if [ $? -ne 0 ] ; then
    echo 'Server did not gave us a URL. Please retry.'
    exit 88
fi



errorstatus=`echo $response  | grep -E -o '"errorStatus":[^"},]*' | cut -f2 -d: | tr -d '"' 2>/dev/null `
errorText=`echo $response  | grep -E -o '"errorText":"[^"},]*' | cut -f2- -d: | tr -d '"' | tr -d '\\' 2>/dev/null `

#NOTE: despite it's name errorText carries the link
#NOTE: https://share.uowm.gr/download/25447b....html


if [ -z "$errorstatus" -o -z "$errorText" ] ; then
    echo "UPLOAD Error. Site replied: [$response]"
    exit 4
fi
#DEBUG: echo $errorText
directURL="https://share.uowm.gr/files/`echo $errorText | sed 's@https://share.uowm.gr/download/@@' | sed  's/.html$//'`/$bname"

shorturl=`check_short_url`
# No need to lsi.gr the big http://share.... URL
# errorTextmini=`short_url "$errorText"`

if [ $directURLshow -eq 1 ] ; then
    directURL=`short_url "$directURL"`
else
    directURL=`short_url "$errorText"`
fi

export directURL

#echo $myurl
if [ "$errorstatus" -ne 0 ] ; then
    echo Server replied with wrong errorstatus: $errorstatus / $errorText
    exit 51
fi
expirydate=`date -v +30d 2>/dev/null || date  -d "+30 days" 2>/dev/null`


myecho -n "$file ["

if [ $silent -eq 0 ] ; then
    printf "\033[33m"
fi
myecho -n "$bname"
if [ $silent -eq 0 ] ; then
    printf "\033[0m"
fi




#echo -n "]"
myecho "]"
myecho -n "$size ["
if [ $silent -eq 0 ] ; then
    printf "\033[34m"
fi
myecho -n "$myfilesizeh"
if [ $silent -eq 0 ] ; then
    printf "\033[0m"
fi
myecho "] Bytes"







myecho -n "$available ["
if [ $silent -eq 0 ] ; then
    printf "\033[32m"
fi
myecho -n $expirydate
if [ $silent -eq 0 ] ; then
    printf "\033[0m"
fi
myecho "]:"





#if [ $shorturl -eq 0 ]; then
#   echo $errorText
#fi


#if [ $shorturl -eq 1 ]; then
#   echo "$or"
#   echo $errorTextmini
#fi

if [ $silent -eq 0 ] ; then
    #echo "-----------------------------------------------------------------------------------"
    #echo "$direct"
    myecho "---------------------------"
    echo "$directURL"
    myecho "---------------------------"

    if [ $massmode -eq 0 ] ; then
        myecho " "
        myecho " "
    fi
else
    echo "$directURL"
fi

if [ "$logging" -eq 1 ] ; then
    echo "Original Name: $bbname" >> $logfile
    echo "Link Created: `/bin/date`" >> $logfile
    echo "Link Expires: $expirydate" >> $logfile 
    echo "$directURL" >> $logfile 
    echo " " >> $logfile 
fi

export SHAREDIRECTURL=$errorText

done

exit

