def view_uploads(*, vbid: str = None, timeout: int = 60, files: int = 4, email: str = None, **kwargs):
"""
GET: Display upload interface or create a new upload box.
POST: Handle uploaded files to a specific vbid.
"""
global _gc_thread_on
if not _gc_thread_on:
threading.Thread(target=periodic_purge, daemon=True).start()
_gc_thread_on = True
admin_email = os.environ.get("ADMIN_EMAIL")
gw.info(f"Entry: vbid={vbid!r}, timeout={timeout}, files={files}, email={email!r}, method={request.method}")
# Handle file upload (POST) with a vbid (the classic file upload case)
if request.method == 'POST' and vbid:
gw.info(f"POST file upload for vbid={vbid}")
with _gc_lock:
expire = _open_boxes.get(vbid)
if not expire or expire < time.time():
gw.warning(f"vbox expired for vbid={vbid}")
return render_error("Upload Box Expired", "Please regenerate a new vbid.")
try:
short, _ = vbid.split(".", 1)
except ValueError:
gw.error(f"Invalid vbid format: {vbid}")
return render_error("Invalid vbid format", "Expected form: <code>short.long</code>.")
upload_dir = gw.resource(*VBOX_PATH, short)
os.makedirs(upload_dir, exist_ok=True)
uploaded_files = request.files.getlist("file")
results = []
for f in uploaded_files:
save_path = os.path.join(upload_dir, f.filename)
try:
f.save(save_path)
results.append(f"Uploaded {f.filename}")
gw.info(f"Uploaded {f.filename} to {short}")
except Exception as e:
results.append(f"Error uploading {f.filename}: {e}")
gw.error(f"Issue uploading {f.filename} to {short}")
gw.exception(e)
download_short_url = gw.web.app.build_url("download", vbid=short)
download_long_url = gw.web.app.build_url("download", vbid=vbid)
gw.info(f"Returning upload result UI for vbid={vbid}")
return (
"<pre>" + "\n".join(results) + "</pre>" +
f"<p><a href='?vbid={vbid}'>UPLOAD MORE files to this box</a></p>" +
f"<p><a href='{download_short_url}'>Go to PUBLIC READ-ONLY download page for this box</a></p>" +
f"<p><a href='{download_long_url}'>Go to HIDDEN WRITE download page for this box</a></p>"
)
if not vbid:
gw.info(f"No vbid present, always creating/checking box.")
remote_addr = request.remote_addr or ''
user_agent = request.headers.get('User-Agent') or ''
identity = remote_addr + user_agent
hash_digest = hashlib.sha256(identity.encode()).hexdigest()
short = hash_digest[:12]
full_id = f"{short}.{hash_digest[:40]}"
with _gc_lock:
now = time.time()
expires = _open_boxes.get(full_id)
if not expires or expires < now:
_open_boxes[full_id] = now + timeout * 60
os.makedirs(gw.resource(*VBOX_PATH, short), exist_ok=True)
url = gw.build_url("uploads", vbid=full_id)
message = f"[UPLOAD] Upload box created (expires in {timeout} min): {url}"
print(("-" * 70) + '\n' + message + '\n' + ("-" * 70))
gw.warning(message)
gw.info(f"Created new box: {full_id}")
else:
url = gw.build_url("upload", vbid=full_id)
gw.info(f"Existing box reused: {full_id}")
admin_notif = ""
sent_copy_msg = "<p>A copy of the access URL was sent to the admin.</p>"
if email:
if admin_email and email.lower() == admin_email.strip().lower():
subject = "Upload Box Link"
body = (
f"A new upload box was created.\n\n"
f"Access URL: {url}\n\n"
f"This box will expire in {timeout} minutes."
)
try:
gw.mail.send(subject, body=body, to=admin_email)
gw.info(f"Sent upload URL email to admin.")
except Exception as e:
gw.error(f"Error sending VBOX notification email: {e}")
admin_notif = sent_copy_msg
else:
admin_notif = sent_copy_msg
gw.info(f"Pretend email sent: {email!r} != {admin_email!r}")
# Show the ready box UI + the optional email form
email_form_html = (
"<form method='POST'>"
"<input type='email' name='email' required placeholder='Your email address'>"
"<button type='submit'>Request Link</button>"
"</form>"
)
form_message = (
"<p>If you are a site member, you may request a URL to be sent to your email by entering it here.</p>"
)
local_console_info = ""
if gw.web.server.is_local():
local_console_info = (
"<p>We've prepared an upload box for you. Check the console for the access URL.</p>"
"<p>To use it, go to <code>?vbid=…</code> and upload your files there.</p>"
)
return (
"<h1>Upload to Virtual Box</h1>"
f"{local_console_info}"
f"{admin_notif}"
f"{form_message if not email else ''}{email_form_html if not email else ''}"
)
# Validate and show upload UI for an existing vbid
gw.info(f"Render upload UI for vbid={vbid!r}")
with _gc_lock:
expire = _open_boxes.get(vbid)
if not expire or expire < time.time():
gw.warning(f"vbox expired for vbid={vbid}")
return render_error("Upload Box Expired or Not Found", "Please regenerate a new vbid.")
try:
short, _ = vbid.split(".", 1)
except ValueError:
gw.error(f"Invalid vbid format: {vbid}")
return render_error("Invalid vbid format", "Expected form: <code>short.long</code>.")
# Generate N file input fields
file_inputs = "\n".join(
f'<input type="file" name="file">' for _ in range(max(1, files))
)
download_url = gw.build_url("download", vbid=vbid)
gw.info(f"Displaying upload form for {short}")
return f"<h1>Upload to Box: {short}</h1>" + f"""
<form method="POST" enctype="multipart/form-data">
{file_inputs}
<br><p><button type="submit">Upload</button><p/>
</form>
<p>Files will be stored in <code>{'/'.join(VBOX_PATH)}/{short}/</code></p>
<p><a href="{download_url}">Go to download page for this box</a></p>
"""