# Buggy code
def __init__(self, common, is_gui, mode="share"):
    self.common = common
    self.common.log("Web", "__init__", "is_gui={}, mode={}".format(is_gui, mode))

    # The flask app
    self.app = Flask(
        __name__,
        static_folder=self.common.get_resource_path("static"),
        template_folder=self.common.get_resource_path("templates"),
    )
    self.app.secret_key = self.common.random_string(8)

    # Debug mode?
    if self.common.debug:
        self.debug_mode()

    # Are we running in GUI mode?
    self.is_gui = is_gui

    # Are we using receive mode?
    self.mode = mode
    if self.mode == "receive":
        # Use custom WSGI middleware, to modify environ
        self.app.wsgi_app = ReceiveModeWSGIMiddleware(self.app.wsgi_app, self)
        # Use a custom Request class to track upload progess
        self.app.request_class = ReceiveModeRequest

    # Starting in Flask 0.11, render_template_string autoescapes template variables
    # by default. To prevent content injection through template variables in
    # earlier versions of Flask, we force autoescaping in the Jinja2 template
    # engine if we detect a Flask version with insecure default behavior.
    if Version(flask_version) < Version("0.11"):
        # Monkey-patch in the fix from https://github.com/pallets/flask/commit/99c99c4c16b1327288fd76c44bc8635a1de452bc
        Flask.select_jinja_autoescape = self._safe_select_jinja_autoescape

    self.security_headers = [
        (
            "Content-Security-Policy",
            "default-src 'self'; style-src 'self'; script-src 'self'; img-src 'self' data:;",
        ),
        ("X-Frame-Options", "DENY"),
        ("X-Xss-Protection", "1; mode=block"),
        ("X-Content-Type-Options", "nosniff"),
        ("Referrer-Policy", "no-referrer"),
        ("Server", "OnionShare"),
    ]

    self.q = queue.Queue()
    self.slug = None
    self.error404_count = 0

    self.done = False

    # shutting down the server only works within the context of flask, so the easiest way to do it is over http
    self.shutdown_slug = self.common.random_string(16)

    # Keep track if the server is running
    self.running = False

    # Define the web app routes
    self.define_common_routes()

    # Create the mode web object, which defines its own routes
    self.share_mode = None
    self.receive_mode = None
    if self.mode == "receive":
        self.receive_mode = ReceiveModeWeb(self.common, self)
    elif self.mode == "share":
        self.share_mode = ShareModeWeb(self.common, self)


# Traceback (KeyError)
[Jan 07 2019 20:58:37] Onion.cleanup: trying to remove onion 5yym6w3kg4tof56umfy6a632nvtoc5dkkpkhj4zd2slqzp5wuiwml7yd
=> 2.4 MiB         video 1.mov[Jan 07 2019 20:58:37] ReceiveMode.update_primary_action
Traceback (most recent call last):
File "onionshare_gui/onionshare_gui.py", line 382, in timer_callback
mode.handle_request_progress(event)
File "onionshare_gui/mode/receive_mode/__init__.py", line 159, in handle_request_progress
'progress': event["data"]["progress"]
File "onionshare_gui/mode/history.py", line 451, in update
self.item_list.update(id, data)
File "onionshare_gui/mode/history.py", line 347, in update
self.items[id].update(data)
KeyError: 0
=> 2.4 MiB         video 1.movAbort trap: 6

# Fixed code
def __init__(self, common, is_gui, mode="share"):
    self.common = common
    self.common.log("Web", "__init__", "is_gui={}, mode={}".format(is_gui, mode))

    # The flask app
    self.app = Flask(
        __name__,
        static_folder=self.common.get_resource_path("static"),
        template_folder=self.common.get_resource_path("templates"),
    )
    self.app.secret_key = self.common.random_string(8)

    # Debug mode?
    if self.common.debug:
        self.debug_mode()

    # Are we running in GUI mode?
    self.is_gui = is_gui

    # If the user stops the server while a transfer is in progress, it should
    # immediately stop the transfer. In order to make it thread-safe, stop_q
    # is a queue. If anything is in it, then the user stopped the server
    self.stop_q = queue.Queue()

    # Are we using receive mode?
    self.mode = mode
    if self.mode == "receive":
        # Use custom WSGI middleware, to modify environ
        self.app.wsgi_app = ReceiveModeWSGIMiddleware(self.app.wsgi_app, self)
        # Use a custom Request class to track upload progess
        self.app.request_class = ReceiveModeRequest

    # Starting in Flask 0.11, render_template_string autoescapes template variables
    # by default. To prevent content injection through template variables in
    # earlier versions of Flask, we force autoescaping in the Jinja2 template
    # engine if we detect a Flask version with insecure default behavior.
    if Version(flask_version) < Version("0.11"):
        # Monkey-patch in the fix from https://github.com/pallets/flask/commit/99c99c4c16b1327288fd76c44bc8635a1de452bc
        Flask.select_jinja_autoescape = self._safe_select_jinja_autoescape

    self.security_headers = [
        (
            "Content-Security-Policy",
            "default-src 'self'; style-src 'self'; script-src 'self'; img-src 'self' data:;",
        ),
        ("X-Frame-Options", "DENY"),
        ("X-Xss-Protection", "1; mode=block"),
        ("X-Content-Type-Options", "nosniff"),
        ("Referrer-Policy", "no-referrer"),
        ("Server", "OnionShare"),
    ]

    self.q = queue.Queue()
    self.slug = None
    self.error404_count = 0

    self.done = False

    # shutting down the server only works within the context of flask, so the easiest way to do it is over http
    self.shutdown_slug = self.common.random_string(16)

    # Keep track if the server is running
    self.running = False

    # Define the web app routes
    self.define_common_routes()

    # Create the mode web object, which defines its own routes
    self.share_mode = None
    self.receive_mode = None
    if self.mode == "receive":
        self.receive_mode = ReceiveModeWeb(self.common, self)
    elif self.mode == "share":
        self.share_mode = ShareModeWeb(self.common, self)