#!/usr/bin/env python
"""
 <transfersh - unofficial command line client for https://github.com/dutchcoders/transfer.sh>
    Copyright (C) 2017  Lukas N. <Alpix> contact[at]alpix.eu - https://github.com/AlpixTM/transfersh

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.
    If not, see <http://www.gnu.org/licenses/>.

"""
import argparse
import glob
import os
import sys
import tarfile
import tempfile

try:
    import requests
except ImportError:
    print("In order to use transfersh, you need to install requests mudule (sudo pip install requests)")
    exit(0)


parser = argparse.ArgumentParser()
parser.add_argument("file", help="Path to the file or directory to upload")
parser.add_argument("-v", "--verbosity", help="Increase output verbosity", action="store_true")
parser.add_argument("-p", "--progress", help="Display progress bar", action="store_true")
parser.add_argument("-n", "--name", help="Change name of the file on Transfer.sh")
parser.add_argument("-r", "--recursive", help="Upload all files in a directory recursively", action="store_true")
parser.add_argument("-tg", "--targz", help="Upload as gzip compressed tar archive", action="store_true")
parser.add_argument("-t", "--tar", help="Upload as uncompressed tar archive", action="store_true")
parser.add_argument("-vt", "--virustotal", help="Check file with virustotal", action="store_true")
parser.add_argument("-sn", "--servername", help="Use your server.name instead of transfer.sh e.g. -sn up.de for https://up.de/")
parser.add_argument("-d", "--dryrun", help="Print the commands that would be executed, but do not execute them.", action="store_true")
# parser.add_argument("-t", "--tor", help="upload files via tor network",action="store_true")

args = parser.parse_args()


def upload(file, recursive=False):
    # Upload procedure
    params = ""
    message = "File saved at: "

    if args.virustotal:
        params = params + "/virustotal"
        message = "Virustotal Report is available here: "

    if args.name:
        filename = args.name
    else:
        filename = file.split("/")
        filename = str(filename[-1])

    if not args.dryrun:
        with open(file, 'rb', 0) as fh:
            if progressbar:
                # Dirty MultipartEncoder object(required byMultipartEncoderMonitor) simulation hack
                fh.len = os.path.getsize(file)
                data = MultipartEncoderMonitor(fh, callback)
            else:
                data = fh

            response = requests.put('https://' + upload_servername + '/' + filename + params, data)

        if recursive:
            print('\r File ' + file + ' saved at: ' + response.text)
        else:
            print('\r' + message + response.text)
    else:
        print('File {0} mock saved.'.format(file))
    return


last_progress = 0


def callback(monitor):
    # Progress bar callback
    global last_progress
    progress = monitor.bytes_read/monitor.len

    if progress == last_progress:
        if last_progress == 1:
            progress = -1
        else:
            progress = 0
    else:
        last_progress = progress

    update_progress(progress)


# Progress bar
def update_progress(progress):
    bar_len = [int(n) for n in os.popen('stty size', 'r').read().split()][1] - 24
    #print(bar_len)
    status = ""

    if progress == -1:
        return
    elif progress >= 1:
        progress = 1
        status = "Done\r\n Waiting for response"

    block = int(round(bar_len*progress))
    text = "\r Upload: [{0}] {1}% {2}".format("#"*block + "-"*(bar_len-block), "{0:.2f}".format(progress*100), status)
    sys.stdout.write(text)
    sys.stdout.flush()


progressbar = False
if args.progress:
    # Load progressbar dependencies
    progressbar = True
    try:
        from requests_toolbelt import(MultipartEncoder, MultipartEncoderMonitor)
    except ImportError:
        print("In order to use the progress bar, you need to install requests_toolbelt (sudo pip install requests_toolbelt)")
        progressbar = False


if args.verbosity:
    print (
    " ====== Transfersh ===== \nUnofficial command-line client for https://transfer.sh/ based on python "
    "\nby Alpix (https://alpix.eu)"
    "\ncontribute: https://github.com/AlpixTM/transfersh"
    )
    if args.recursive:
        print ('Selected path to upload: ' + args.file)
    else:
        print ('Selected file to upload: ' + args.file)


# Define upload url
if args.servername:
    upload_servername = args.servername
else:
    # default server transfer.sh
    upload_servername = "transfer.sh"


"""
    if args.tor:
    Tor Support needs new concept -> Public tor socks proxy? Public tor http proxy without daily changing cookie!?

"""

if args.tar:
    temp_dir = tempfile.gettempdir()
    tar = tarfile.open(temp_dir + "/transfersh-upload.tar", mode="w")
    tarfilename = temp_dir + "/transfersh-upload.tar"

if args.targz:
    temp_dir = tempfile.gettempdir()
    tar = tarfile.open(temp_dir + "/transfersh-upload.tar", mode="w:gz")
    tarfilename = temp_dir + "/transfersh-upload.tar.gz"

if args.recursive:
    isfile = os.path.isfile(args.file)
    if isfile:
        exit("Not a dir -> do not use -r // --recursive")
    for filename in glob.iglob(args.file + "**", recursive=True):
        check = os.path.isfile(filename)
        if check is not False:
            if args.tar is True or args.targz is True:
                tar.add(filename)
            else:
                upload(filename, True)
    if args.tar is True or args.targz is True:
        tar.close()
        upload(tarfilename, False)
        os.remove(tarfilename)
else:
    if args.tar is True or args.targz is True:
        tar.add(args.file)
        tar.close()
        upload(tarfilename, False)
        os.remove(tarfilename)
    else:
        upload(args.file, False)
