Exemplo n.º 1
0
def download(fid, secret, dest, password=None, url=None):
    metadata, nonce = get_metadata(fid, secret, password, url)

    encryptKey = deriveFileKey(secret)
    authKey = deriveAuthKey(secret, password, url)

    sig = hmac.new(authKey, nonce, sha256).digest()
    url = "https://send.firefox.com/api/download/" + fid
    resp = requests.get(url,
                        headers={'Authorization': 'send-v1 ' + b64encode(sig)},
                        stream=True)
    resp.raise_for_status()

    flen = int(resp.headers.get('Content-Length'))
    filename = metadata['metadata']['name']

    if os.path.isdir(dest):
        filename = os.path.join(dest, filename)
    else:
        filename = dest

    iv = b64decode(metadata['metadata']['iv'])
    cipher = AES.new(encryptKey, AES.MODE_GCM, iv, mac_len=16)

    ho = sha256()

    print("Downloading to %s..." % filename)

    try:
        with open(filename + '.tmp', 'wb') as outf:
            bar = ProgressBar(expected_size=flen, filled_char='=')

            dl = 0
            tag = b''
            taglen = 16
            for data in resp.iter_content(chunk_size=8192):
                dl += len(data)
                bar.show(dl)

                if dl > flen - taglen:
                    dend = max(len(data) - (dl - (flen - taglen)), 0)
                    tag += data[dend:]
                    data = data[:dend]

                chunk = cipher.decrypt(data)
                ho.update(chunk)
                outf.write(chunk)
                if len(tag) == taglen:
                    break

            print()
            cipher.verify(tag)
    except Exception as e:
        print("File download failed:", e)
        os.unlink(filename + '.tmp')
    else:
        os.rename(filename + '.tmp', filename)
        print("Done, file verified!")
Exemplo n.º 2
0
 def __init__(self, stream=None, expected_size=None, chunk_size=512):
     """
 :param stream:
   Streaming API response object returned by the 'requests' library
   :type: requests.Response
 :param int expected_size:
   Total size of file being downloaded (in bytes)
 :param int chunk_size:
   Chunk size to use when iterating over streamed response content
 """
     self.stream = stream
     self.prog_bar = ProgressBar(expected_size=expected_size,
                                 filled_char='=')
     self.progress = 0
     self.chunk_size = chunk_size
Exemplo n.º 3
0
 def __call__(self, size_rd, total):
     if self.bar is None:
         self.bar = ProgressBar(expected_size=total,
                                filled_char='=')
     self.bar.show(size_rd)