Add --port
This commit is contained in:
+11
-13
@@ -32,27 +32,25 @@
|
||||
errorBox.hidden = !msg;
|
||||
}
|
||||
|
||||
// --- token memory -------------------------------------------------------
|
||||
// Kept in localStorage only so the field survives a reload; it is never sent
|
||||
// anywhere but this origin's upload endpoint.
|
||||
try {
|
||||
var saved = localStorage.getItem('send.token');
|
||||
if (saved && tokenInput) tokenInput.value = saved;
|
||||
} catch (e) { /* private mode; not important */ }
|
||||
|
||||
// --- credentials --------------------------------------------------------
|
||||
// A token is remembered in an HttpOnly cookie the server sets, not here:
|
||||
// this script cannot read it back, so an injected script cannot steal it
|
||||
// either. The page is told who it is by the server when it renders, and the
|
||||
// limits panel is refreshed from /api/limits, which reads the same cookie.
|
||||
function refreshLimits() {
|
||||
var token = tokenInput ? tokenInput.value.trim() : '';
|
||||
try {
|
||||
if (token) localStorage.setItem('send.token', token);
|
||||
else localStorage.removeItem('send.token');
|
||||
} catch (e) { /* ignore */ }
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', base + 'api/limits');
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
// Sent only when the field holds something; otherwise the cookie answers.
|
||||
if (token) xhr.setRequestHeader('Authorization', 'Bearer ' + token);
|
||||
xhr.onload = function () {
|
||||
if (xhr.status !== 200) return;
|
||||
if (xhr.status !== 200) {
|
||||
if (xhr.status === 401 && token) showError('That token is not recognised.');
|
||||
return;
|
||||
}
|
||||
showError('');
|
||||
var l;
|
||||
try { l = JSON.parse(xhr.responseText); } catch (e) { return; }
|
||||
limits = l;
|
||||
|
||||
@@ -142,3 +142,27 @@ pre {
|
||||
.warn p { margin: .25rem 0 .75rem; font-size: .875rem; }
|
||||
|
||||
.result .field { margin-top: 1rem; }
|
||||
|
||||
.check { display: flex; align-items: center; gap: .5rem; margin-bottom: 1rem; font-size: .875rem; }
|
||||
.check input { margin: 0; }
|
||||
|
||||
.notice {
|
||||
margin: 0 0 1rem;
|
||||
padding: .625rem .875rem;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--line);
|
||||
border-left: 3px solid var(--accent);
|
||||
border-radius: 6px;
|
||||
font-size: .875rem;
|
||||
}
|
||||
.notice .forget-form, .notice form { display: inline; }
|
||||
|
||||
button.link {
|
||||
padding: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
color: var(--accent);
|
||||
font: inherit;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
{{define "content"}}
|
||||
{{if .Stale}}
|
||||
<p class="notice">The token remembered on this device no longer exists. It has been forgotten.</p>
|
||||
{{end}}
|
||||
|
||||
{{if .TokenName}}
|
||||
<div class="notice" id="identity">
|
||||
Uploading as <strong>{{.TokenName}}</strong>.
|
||||
<form method="post" action="{{.Base}}api/forget"><button type="submit" class="link">Forget</button></form>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<form id="upload" class="card" method="post" action="{{.Base}}api/upload" enctype="multipart/form-data">
|
||||
<!-- Field order is load-bearing: the server streams this body and must know
|
||||
the credentials and options before the file part arrives. -->
|
||||
<label class="field">
|
||||
<span>Token <em>optional</em></span>
|
||||
<input type="password" name="token" id="token" autocomplete="off" placeholder="anonymous">
|
||||
<input type="password" name="token" id="token" autocomplete="off"
|
||||
placeholder="{{if .TokenName}}remembered — type to replace{{else}}anonymous{{end}}">
|
||||
</label>
|
||||
|
||||
<label class="check">
|
||||
<input type="checkbox" name="remember" id="remember" value="1" checked>
|
||||
<span>Remember this token on this device</span>
|
||||
</label>
|
||||
|
||||
<div class="row">
|
||||
@@ -15,7 +32,7 @@
|
||||
<label class="field" id="vanity-field">
|
||||
<span>Vanity name <em>token only</em></span>
|
||||
<input type="text" name="vanity" id="vanity" placeholder="auto" autocomplete="off"
|
||||
pattern="[A-Za-z0-9][A-Za-z0-9._-]{1,63}">
|
||||
pattern="[A-Za-z0-9][A-Za-z0-9._-]{1,63}"{{if not .AllowVanity}} disabled{{end}}>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +56,7 @@
|
||||
<dt>Maximum size</dt><dd id="limit-size">{{.MaxSize}}</dd>
|
||||
<dt>Longest lifetime</dt><dd id="limit-expiry">{{.MaxExpiry}}</dd>
|
||||
<dt>Default lifetime</dt><dd id="limit-default">{{.DefaultExpiry}}</dd>
|
||||
<dt>Vanity names</dt><dd id="limit-vanity">requires a token</dd>
|
||||
<dt>Vanity names</dt><dd id="limit-vanity">{{if .AllowVanity}}allowed{{else}}requires a token{{end}}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user