Mercurial > libervia-web
view libervia/web/pages/_browser/file_uploader.py @ 1598:86c7a3a625d5
server: always start a new session on connection:
The session was kept when a user was connecting from service profile (but not from other
profiles), this was leading to session fixation vulnerability (an attacker on the same
machine could get service profile session cookie, and use it when a victim would log-in).
This patch fixes it by always starting a new session on connection.
fix 443
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 23 Feb 2024 13:35:24 +0100 |
parents | 106945841fbc |
children |
line wrap: on
line source
import json from bridge import Bridge from browser import console as log, window import dialog from template import Template bridge = Bridge() log.warning = log.warn class FileUploader: """Class handling HTTP upload and progress display""" def __init__(self, files_service, template_file, files_path=None, on_delete_cb=None): self.files_service = files_service self.files_path = files_path self.item_tpl = Template(template_file) self.on_delete_cb = on_delete_cb self.uploaded = {} def on_progress(self, ev, item_elt): if ev.lengthComputable: percent = int(ev.loaded/ev.total*100) self.update_progress(item_elt, percent) def on_load(self, file_, item_elt): self.update_progress(item_elt, 100) item_elt.classList.add("progress_finished") item_elt.classList.remove("progress_started") if self.on_delete_cb is not None: delete_btn = item_elt.select_one('.action_delete') if delete_btn is not None: delete_btn.bind("click", self.on_delete_cb) log.info(f"file {file_.name} uploaded correctly") def on_error(self, failure, file_, item_elt): dialog.notification.show( f"can't upload {file_.name}: {failure}", level="error" ) def update_progress(self, item_elt, new_value): progress_elt = item_elt.select_one("progress") if progress_elt is not None: progress_elt.value = new_value progress_elt.text = f"{new_value}%" def on_slot_cb(self, file_, upload_slot, item_elt): put_url, get_url, headers = upload_slot xhr = window.XMLHttpRequest.new() xhr.open("PUT", put_url, True) xhr.upload.bind('progress', lambda ev: self.on_progress(ev, item_elt)) xhr.upload.bind('load', lambda ev: self.on_load(file_, item_elt)) xhr.upload.bind('error', lambda ev: self.on_error(xhr.response, file_, item_elt)) if self.files_path is not None: xhr.setRequestHeader( 'Xmpp-File-Path', window.encodeURIComponent(self.files_path) ) xhr.setRequestHeader('Xmpp-File-No-Http', "true") xhr.send(file_) # we update file data with the get URL file_data = json.loads(item_elt.getAttribute("data-file")) file_data["url"] = get_url item_elt.setAttribute("data-file", json.dumps(file_data)) def on_slot_eb(self, file_, failure, item_elt): dialog.notification.show( f"Can't get upload slot: {failure['message']}", level="error" ) item_elt.remove() def upload_files(self, files, container_elt): """Start file upload, and add item_tpl to container_elt""" log.info(f"uploading {len(files)} files") for file_ in files: url = window.URL.createObjectURL(file_) file_data = { "name": file_.name, "mime_type": file_.type, } template_file_data = file_data.copy() # we don't want to open the file on click, it's not yet the # uploaded URL template_file_data["url"] = url # we have no thumb yet, so we use the whole image # TODO: reduce image for preview template_file_data["thumb_url"] = url item_elt = self.item_tpl.get_elt({ "file": template_file_data, "uploading": True, }) item_elt.setAttribute("data-file", json.dumps(file_data)) item_elt.classList.add("progress_started") container_elt <= item_elt bridge.file_http_upload_get_slot( file_.name, file_.size, file_.type or '', self.files_service, callback=lambda upload_slot, file_=file_, item_elt=item_elt: self.on_slot_cb(file_, upload_slot, item_elt), errback=lambda failure, file_=file_, item_elt=item_elt: self.on_slot_eb(file_, failure, item_elt), )