'LZMA Returns Input Format not supported

It seems that when I try to decode some bytes that where decoded from base 64 it gives an Input Format not Supported. I cannot isolate the issue, as when I bring the decoded logic alone into a new file, the error will not happen, making me think that this is something to do with the way flask passes arguments to the functions.

Code:

from flask import Flask
import base64
import lzma
from urllib.parse import quote, unquote
app = Flask('app')

@app.route('/')
def hello_world():
  return 'Hello, World!<br><button onclick = "var base = \'https://Text-Viewer-from-Bsace-64-URL.inyourface3445.repl.co/encode\';location.href = `${base}/${prompt(\'What do you want to send?\')}`" >Use</button>'

newline = '/n'

@app.route('/view/<path:b64>')
def viewer(b64):
    print(type(b64))
    s1 = base64.b64decode(b64.encode() + b'==')
    s2 = lzma.decompress(s1).decode()
    s3 = unquote(s2).replace(newline, '<br>')
    
    return f'<div style="overflow-x: auto;">{s3}</div>'


@app.route('/encode/<path:txt>')
def encode(txt):
    quote_text = quote(txt, safe = "")
    compressed_text = lzma.compress(quote_text.encode())
    base_64_txt = base64.b64encode(compressed_text).decode()
    
    return f'<a href = "https://Text-Viewer-from-Bsace-64-URL.inyourface3445.repl.co/view/{base_64_txt}">text link </a>'


app.run(host='0.0.0.0', port=8080, debug=True)

Can someone explain what I am doing wrong?



Solution 1:[1]

You are passing a base64-encoded string as a part of the URL, and that string may contain characters that gets mangled in the process.

For example, visiting /encode/hello will give the following URL:

https://text-viewer-from-bsace-64-url.inyourface3445.repl.co/view//Td6WFoAAATm1rRGAgAhARYAAAB0L+WjAQAEaGVsbG8AAAAAsTe52+XaHpsAAR0FuC2Arx+2830BAAAAAARZWg==

Several characters could go wrong:

  • The first character is /, and as a result Flask will redirect from view//TD6... to view/TD6...: in other words the first character gets deleted
  • Depending on how URL-encoding is performed by the browser and URL-decoding is performed by Flask, the + character may be decoded into a space

To avoid these issues, I would suggest using base64.urlsafe_b64encode / base64.urlsafe_b64decode which are versions of the base64 encoding where the output can be used in URLs without being mangled.

The following changes on your code seems to do the trick:

  1. s1 = base64.urlsafe_b64decode(b64.encode()) in viewer
  2. base_64_txt = base64.urlsafe_b64encode(compressed_text).decode() in encode

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rogdham