mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
fix some issues with shares mentioned in #84;
* crash when root volume is unmapped * rephrase login-page for shares * add chrome support (lol) * fix confusing helptext * improve ux * placeholders in share creator * button to disable expiration in share creator * human-readable timestamps in share listing
This commit is contained in:
parent
fca70b3508
commit
7ff46966da
|
@ -757,7 +757,7 @@ this feature was made with [identity providers](#identity-providers) in mind --
|
||||||
when creating a share, the creator can choose any of the following options:
|
when creating a share, the creator can choose any of the following options:
|
||||||
|
|
||||||
* password-protection
|
* password-protection
|
||||||
* expire after a certain time
|
* expire after a certain time; `0` or blank means infinite
|
||||||
* allow visitors to upload (if the user who creates the share has write-access)
|
* allow visitors to upload (if the user who creates the share has write-access)
|
||||||
|
|
||||||
semi-intentional limitations:
|
semi-intentional limitations:
|
||||||
|
@ -768,7 +768,10 @@ semi-intentional limitations:
|
||||||
* when linking something to discord (for example) it'll get accessed by their scraper and that would count as a hit
|
* when linking something to discord (for example) it'll get accessed by their scraper and that would count as a hit
|
||||||
* browsers wouldn't be able to resume a broken download unless the requester's IP gets allowlisted for X minutes (ref. tricky)
|
* browsers wouldn't be able to resume a broken download unless the requester's IP gets allowlisted for X minutes (ref. tricky)
|
||||||
|
|
||||||
the links are created inside a specific toplevel folder which must be specified with server-config `--shr`, for example `--shr /share/` (this also enables the feature)
|
specify `--shr /foobar` to enable this feature; a toplevel virtual folder named `foobar` is then created, and that's where all the shares will be served from
|
||||||
|
|
||||||
|
* you can name it whatever, `foobar` is just an example
|
||||||
|
* if you're using config files, put `shr: /foobar` inside the `[global]` section instead
|
||||||
|
|
||||||
users can delete their own shares in the controlpanel, and a list of privileged users (`--shr-adm`) are allowed to see and/or delet any share on the server
|
users can delete their own shares in the controlpanel, and a list of privileged users (`--shr-adm`) are allowed to see and/or delet any share on the server
|
||||||
|
|
||||||
|
|
|
@ -975,8 +975,8 @@ def add_fs(ap):
|
||||||
def add_share(ap):
|
def add_share(ap):
|
||||||
db_path = os.path.join(E.cfg, "shares.db")
|
db_path = os.path.join(E.cfg, "shares.db")
|
||||||
ap2 = ap.add_argument_group('share-url options')
|
ap2 = ap.add_argument_group('share-url options')
|
||||||
ap2.add_argument("--shr", metavar="URL", default="", help="base url for shared files, for example [\033[32m/share\033[0m] (must be a toplevel subfolder)")
|
ap2.add_argument("--shr", metavar="DIR", default="", help="toplevel virtual folder for shared files/folders, for example [\033[32m/share\033[0m]")
|
||||||
ap2.add_argument("--shr-db", metavar="PATH", default=db_path, help="database to store shares in")
|
ap2.add_argument("--shr-db", metavar="FILE", default=db_path, help="database to store shares in")
|
||||||
ap2.add_argument("--shr-adm", metavar="U,U", default="", help="comma-separated list of users allowed to view/delete any share")
|
ap2.add_argument("--shr-adm", metavar="U,U", default="", help="comma-separated list of users allowed to view/delete any share")
|
||||||
ap2.add_argument("--shr-v", action="store_true", help="debug")
|
ap2.add_argument("--shr-v", action="store_true", help="debug")
|
||||||
|
|
||||||
|
|
|
@ -1508,7 +1508,6 @@ class AuthSrv(object):
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
shv = VFS(self.log_func, "", shr, AXS(), {"d2d": True})
|
shv = VFS(self.log_func, "", shr, AXS(), {"d2d": True})
|
||||||
par = vfs.all_vols[""]
|
|
||||||
|
|
||||||
db_path = self.args.shr_db
|
db_path = self.args.shr_db
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
|
@ -1539,7 +1538,7 @@ class AuthSrv(object):
|
||||||
# don't know the abspath yet + wanna ensure the user
|
# don't know the abspath yet + wanna ensure the user
|
||||||
# still has the privs they granted, so nullmap it
|
# still has the privs they granted, so nullmap it
|
||||||
shv.nodes[s_k] = VFS(
|
shv.nodes[s_k] = VFS(
|
||||||
self.log_func, "", "%s/%s" % (shr, s_k), s_axs, par.flags.copy()
|
self.log_func, "", "%s/%s" % (shr, s_k), s_axs, shv.flags.copy()
|
||||||
)
|
)
|
||||||
|
|
||||||
vfs.nodes[shr] = vfs.all_vols[shr] = shv
|
vfs.nodes[shr] = vfs.all_vols[shr] = shv
|
||||||
|
|
|
@ -3958,6 +3958,7 @@ class HttpCli(object):
|
||||||
rvol=rvol,
|
rvol=rvol,
|
||||||
wvol=wvol,
|
wvol=wvol,
|
||||||
avol=avol,
|
avol=avol,
|
||||||
|
in_shr=self.args.shr and self.vpath.startswith(self.args.shr[1:]),
|
||||||
vstate=vstate,
|
vstate=vstate,
|
||||||
scanning=vs["scanning"],
|
scanning=vs["scanning"],
|
||||||
hashq=vs["hashq"],
|
hashq=vs["hashq"],
|
||||||
|
@ -4006,10 +4007,10 @@ class HttpCli(object):
|
||||||
def tx_404(self, is_403: bool = False) -> bool:
|
def tx_404(self, is_403: bool = False) -> bool:
|
||||||
rc = 404
|
rc = 404
|
||||||
if self.args.vague_403:
|
if self.args.vague_403:
|
||||||
t = '<h1 id="n">404 not found ┐( ´ -`)┌</h1><p id="o">or maybe you don\'t have access -- try logging in or <a href="{}/?h">go home</a></p>'
|
t = '<h1 id="n">404 not found ┐( ´ -`)┌</h1><p id="o">or maybe you don\'t have access -- try a password or <a href="{}/?h">go home</a></p>'
|
||||||
pt = "404 not found ┐( ´ -`)┌ (or maybe you don't have access -- try logging in)"
|
pt = "404 not found ┐( ´ -`)┌ (or maybe you don't have access -- try a password)"
|
||||||
elif is_403:
|
elif is_403:
|
||||||
t = '<h1 id="p">403 forbiddena ~┻━┻</h1><p id="q">you\'ll have to log in or <a href="{}/?h">go home</a></p>'
|
t = '<h1 id="p">403 forbiddena ~┻━┻</h1><p id="q">use a password or <a href="{}/?h">go home</a></p>'
|
||||||
pt = "403 forbiddena ~┻━┻ (you'll have to log in)"
|
pt = "403 forbiddena ~┻━┻ (you'll have to log in)"
|
||||||
rc = 403
|
rc = 403
|
||||||
else:
|
else:
|
||||||
|
@ -4026,7 +4027,8 @@ class HttpCli(object):
|
||||||
|
|
||||||
t = t.format(self.args.SR)
|
t = t.format(self.args.SR)
|
||||||
qv = quotep(self.vpaths) + self.ourlq()
|
qv = quotep(self.vpaths) + self.ourlq()
|
||||||
html = self.j2s("splash", this=self, qvpath=qv, msg=t)
|
in_shr = self.args.shr and self.vpath.startswith(self.args.shr[1:])
|
||||||
|
html = self.j2s("splash", this=self, qvpath=qv, in_shr=in_shr, msg=t)
|
||||||
self.reply(html.encode("utf-8"), status=rc)
|
self.reply(html.encode("utf-8"), status=rc)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -4382,7 +4384,8 @@ class HttpCli(object):
|
||||||
pw = req.get("pw") or ""
|
pw = req.get("pw") or ""
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
sexp = req["exp"]
|
sexp = req["exp"]
|
||||||
exp = now + int(sexp) * 60 if sexp else 0
|
exp = int(sexp) if sexp else 0
|
||||||
|
exp = now + exp * 60 if exp else 0
|
||||||
pr = "".join(zc for zc, zb in zip("rwmd", (s_rd, s_wr, s_mv, s_del)) if zb)
|
pr = "".join(zc for zc, zb in zip("rwmd", (s_rd, s_wr, s_mv, s_del)) if zb)
|
||||||
|
|
||||||
q = "insert into sh values (?,?,?,?,?,?,?,?)"
|
q = "insert into sh values (?,?,?,?,?,?,?,?)"
|
||||||
|
|
|
@ -376,7 +376,13 @@ class SvcHub(object):
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
al.shr = "/%s/" % (al.shr.strip("/"))
|
al.shr = al.shr.strip("/")
|
||||||
|
if "/" in al.shr:
|
||||||
|
t = "config error: --shr must be the name of a virtual toplevel directory to put shares inside"
|
||||||
|
self.log("root", t, 1)
|
||||||
|
raise Exception(t)
|
||||||
|
|
||||||
|
al.shr = "/%s/" % (al.shr,)
|
||||||
|
|
||||||
create = True
|
create = True
|
||||||
db_path = self.args.shr_db
|
db_path = self.args.shr_db
|
||||||
|
|
|
@ -3820,13 +3820,14 @@ var fileman = (function () {
|
||||||
'<button id="sh_rand">🎲 random</button>',
|
'<button id="sh_rand">🎲 random</button>',
|
||||||
'<button id="sh_apply">✅ create share</button>',
|
'<button id="sh_apply">✅ create share</button>',
|
||||||
'</td></tr>',
|
'</td></tr>',
|
||||||
'<tr><td>name</td><td><input type="text" id="sh_k" ' + NOAC + ' tt="name your link" /></td></tr>',
|
'<tr><td>name</td><td><input type="text" id="sh_k" ' + NOAC + ' placeholder="optional link name; will be random if blank" /></td></tr>',
|
||||||
'<tr><td>source</td><td><input type="text" id="sh_vp" ' + NOAC + ' readonly tt="the file or folder to share" /></td></tr>',
|
'<tr><td>source</td><td><input type="text" id="sh_vp" ' + NOAC + ' readonly tt="the file or folder to share" /></td></tr>',
|
||||||
'<tr><td>passwd</td><td><input type="text" id="sh_pw" ' + NOAC + ' tt="optional password" /></td></tr>',
|
'<tr><td>passwd</td><td><input type="text" id="sh_pw" ' + NOAC + ' placeholder="optional password" /></td></tr>',
|
||||||
'<tr><td>expiry</td><td class="exs">',
|
'<tr><td>expiry</td><td class="exs">',
|
||||||
'<input type="text" id="sh_exm" ' + NOAC + ' /> min / ',
|
'<input type="text" id="sh_exm" ' + NOAC + ' /> min / ',
|
||||||
'<input type="text" id="sh_exh" ' + NOAC + ' /> hours / ',
|
'<input type="text" id="sh_exh" ' + NOAC + ' /> hours / ',
|
||||||
'<input type="text" id="sh_exd" ' + NOAC + ' /> days',
|
'<input type="text" id="sh_exd" ' + NOAC + ' /> days / ',
|
||||||
|
'<button id="sh_noex">never</button>',
|
||||||
'</td></tr>',
|
'</td></tr>',
|
||||||
'<tr><td>perms</td><td class="sh_axs">',
|
'<tr><td>perms</td><td class="sh_axs">',
|
||||||
];
|
];
|
||||||
|
@ -3840,11 +3841,12 @@ var fileman = (function () {
|
||||||
var sh_rand = ebi('sh_rand'),
|
var sh_rand = ebi('sh_rand'),
|
||||||
sh_abrt = ebi('sh_abrt'),
|
sh_abrt = ebi('sh_abrt'),
|
||||||
sh_apply = ebi('sh_apply'),
|
sh_apply = ebi('sh_apply'),
|
||||||
|
sh_noex = ebi('sh_noex'),
|
||||||
exm = ebi('sh_exm'),
|
exm = ebi('sh_exm'),
|
||||||
exh = ebi('sh_exh'),
|
exh = ebi('sh_exh'),
|
||||||
exd = ebi('sh_exd'),
|
exd = ebi('sh_exd'),
|
||||||
sh_k = ebi('sh_k'),
|
sh_k = ebi('sh_k'),
|
||||||
sh_vp = ebi('sh_vp');
|
sh_vp = ebi('sh_vp'),
|
||||||
sh_pw = ebi('sh_pw');
|
sh_pw = ebi('sh_pw');
|
||||||
|
|
||||||
function setexp(a, b) {
|
function setexp(a, b) {
|
||||||
|
@ -3870,6 +3872,9 @@ var fileman = (function () {
|
||||||
exm.onfocus = exh.onfocus = exd.onfocus = function () {
|
exm.onfocus = exh.onfocus = exd.onfocus = function () {
|
||||||
this.value = '';
|
this.value = '';
|
||||||
};
|
};
|
||||||
|
sh_noex.onclick = function () {
|
||||||
|
setexp(0, 1);
|
||||||
|
};
|
||||||
exm.onblur = exh.onblur = exd.onblur = setdef;
|
exm.onblur = exh.onblur = exd.onblur = setdef;
|
||||||
|
|
||||||
exm.onkeydown = exh.onkeydown = exd.onkeydown =
|
exm.onkeydown = exh.onkeydown = exd.onkeydown =
|
||||||
|
@ -3910,6 +3915,7 @@ var fileman = (function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
function shr_cb() {
|
function shr_cb() {
|
||||||
|
toast.hide();
|
||||||
if (this.status !== 201) {
|
if (this.status !== 201) {
|
||||||
shui.style.display = 'block';
|
shui.style.display = 'block';
|
||||||
var msg = unpre(this.responseText);
|
var msg = unpre(this.responseText);
|
||||||
|
@ -3919,7 +3925,7 @@ var fileman = (function () {
|
||||||
var surl = this.responseText;
|
var surl = this.responseText;
|
||||||
modal.confirm(L.fs_ok + esc(surl), function() {
|
modal.confirm(L.fs_ok + esc(surl), function() {
|
||||||
cliptxt(surl, function () {
|
cliptxt(surl, function () {
|
||||||
toast.ok(1, 'copied to clipboard');
|
toast.ok(2, 'copied to clipboard');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3934,6 +3940,8 @@ var fileman = (function () {
|
||||||
plist.push(pbtns[a].textContent);
|
plist.push(pbtns[a].textContent);
|
||||||
|
|
||||||
shui.style.display = 'none';
|
shui.style.display = 'none';
|
||||||
|
toast.inf(30, "creating share...");
|
||||||
|
|
||||||
var body = {
|
var body = {
|
||||||
"k": sh_k.value,
|
"k": sh_k.value,
|
||||||
"vp": sh_vp.value,
|
"vp": sh_vp.value,
|
||||||
|
|
|
@ -58,6 +58,9 @@ td, th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
td+td+td+td+td+td+td+td {
|
||||||
|
font-family: var(--font-mono), monospace, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="wrap">
|
<div id="wrap">
|
||||||
<a id="a" href="{{ r }}/?shares" class="af">refresh</a>
|
<a id="a" href="{{ r }}/?shares" class="af">refresh</a>
|
||||||
<a id="a" href="{{ r }}/?h" class="af">controlpanel</a>
|
<a id="a" href="{{ r }}/?h" class="af">control-panel</a>
|
||||||
|
|
||||||
<span>axs = perms (read,write,move,delet)</span>
|
<span>axs = perms (read,write,move,delet)</span>
|
||||||
<span>st 1=file 2=dir</span>
|
<span>st 1=file 2=dir</span>
|
||||||
<span>min/hrs = time left</span>
|
<span>min/hrs = time left</span>
|
||||||
|
|
||||||
<table><tr>
|
<table id="tab"><thead><tr>
|
||||||
<th>delete</th>
|
<th>delete</th>
|
||||||
<th>sharekey</th>
|
<th>sharekey</th>
|
||||||
<th>pw</th>
|
<th>pw</th>
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
<th>expires</th>
|
<th>expires</th>
|
||||||
<th>min</th>
|
<th>min</th>
|
||||||
<th>hrs</th>
|
<th>hrs</th>
|
||||||
</tr>
|
</tr></thead><tbody>
|
||||||
{% for k, pw, vp, pr, st, un, t0, t1 in rows %}
|
{% for k, pw, vp, pr, st, un, t0, t1 in rows %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#" k="{{ k }}">delete</a></td>
|
<td><a href="#" k="{{ k }}">delete</a></td>
|
||||||
|
@ -45,11 +45,11 @@
|
||||||
<td>{{ un|e }}</td>
|
<td>{{ un|e }}</td>
|
||||||
<td>{{ t0 }}</td>
|
<td>{{ t0 }}</td>
|
||||||
<td>{{ t1 }}</td>
|
<td>{{ t1 }}</td>
|
||||||
<td>{{ (t1 - now) // 60 if t1 else "never" }}</td>
|
<td>{{ ((t1 - now) / 60) | round(1) if t1 else "inf" }}</td>
|
||||||
<td>{{ (t1 - now) // 3600 if t1 else "never" }}</td>
|
<td>{{ ((t1 - now) / 3600) | round(1) if t1 else "inf" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</tbody></table>
|
||||||
{% if not rows %}
|
{% if not rows %}
|
||||||
(you don't have any active shares btw)
|
(you don't have any active shares btw)
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -17,3 +17,21 @@ function cb() {
|
||||||
|
|
||||||
document.location = '?shares';
|
document.location = '?shares';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var tab = ebi('tab').tBodies[0],
|
||||||
|
tr = Array.prototype.slice.call(tab.rows, 0);
|
||||||
|
|
||||||
|
var buf = [];
|
||||||
|
for (var a = 0; a < tr.length; a++)
|
||||||
|
for (var b = 7; b < 9; b++)
|
||||||
|
buf.push(parseInt(tr[a].cells[b].innerHTML));
|
||||||
|
|
||||||
|
var ibuf = 0;
|
||||||
|
for (var a = 0; a < tr.length; a++)
|
||||||
|
for (var b = 7; b < 9; b++) {
|
||||||
|
var v = buf[ibuf++];
|
||||||
|
tr[a].cells[b].innerHTML =
|
||||||
|
v ? unix2iso(v).replace(' ', ', ') : 'never';
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="wrap">
|
<div id="wrap">
|
||||||
|
{%- if not in_shr %}
|
||||||
<a id="a" href="{{ r }}/?h" class="af">refresh</a>
|
<a id="a" href="{{ r }}/?h" class="af">refresh</a>
|
||||||
<a id="v" href="{{ r }}/?hc" class="af">connect</a>
|
<a id="v" href="{{ r }}/?hc" class="af">connect</a>
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
<a id="c" href="{{ r }}/?pw=x" class="logout">logout</a>
|
<a id="c" href="{{ r }}/?pw=x" class="logout">logout</a>
|
||||||
<p><span id="m">welcome back,</span> <strong>{{ this.uname|e }}</strong></p>
|
<p><span id="m">welcome back,</span> <strong>{{ this.uname|e }}</strong></p>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
{%- if msg %}
|
{%- if msg %}
|
||||||
<div id="msg">
|
<div id="msg">
|
||||||
|
@ -76,6 +78,37 @@
|
||||||
</ul>
|
</ul>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
{%- if in_shr %}
|
||||||
|
<h1 id="z">unlock this share:</h1>
|
||||||
|
<div>
|
||||||
|
<form id="lf" method="post" enctype="multipart/form-data" action="{{ r }}/{{ qvpath }}">
|
||||||
|
<input type="hidden" id="la" name="act" value="login" />
|
||||||
|
<input type="password" id="lp" name="cppwd" placeholder=" password" />
|
||||||
|
<input type="hidden" name="uhash" id="uhash" value="x" />
|
||||||
|
<input type="submit" id="ls" value="Unlock" />
|
||||||
|
{% if ahttps %}
|
||||||
|
<a id="w" href="{{ ahttps }}">switch to https</a>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{%- else %}
|
||||||
|
<h1 id="l">login for more:</h1>
|
||||||
|
<div>
|
||||||
|
<form id="lf" method="post" enctype="multipart/form-data" action="{{ r }}/{{ qvpath }}">
|
||||||
|
<input type="hidden" id="la" name="act" value="login" />
|
||||||
|
<input type="password" id="lp" name="cppwd" placeholder=" password" />
|
||||||
|
<input type="hidden" name="uhash" id="uhash" value="x" />
|
||||||
|
<input type="submit" id="ls" value="Login" />
|
||||||
|
{% if chpw %}
|
||||||
|
<a id="x" href="#">change password</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if ahttps %}
|
||||||
|
<a id="w" href="{{ ahttps }}">switch to https</a>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
<h1 id="cc">other stuff:</h1>
|
<h1 id="cc">other stuff:</h1>
|
||||||
<ul>
|
<ul>
|
||||||
{%- if this.uname != '*' and this.args.shr %}
|
{%- if this.uname != '*' and this.args.shr %}
|
||||||
|
@ -94,21 +127,6 @@
|
||||||
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>
|
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h1 id="l">login for more:</h1>
|
|
||||||
<div>
|
|
||||||
<form id="lf" method="post" enctype="multipart/form-data" action="{{ r }}/{{ qvpath }}">
|
|
||||||
<input type="hidden" id="la" name="act" value="login" />
|
|
||||||
<input type="password" id="lp" name="cppwd" placeholder=" password" />
|
|
||||||
<input type="hidden" name="uhash" id="uhash" value="x" />
|
|
||||||
<input type="submit" id="ls" value="Login" />
|
|
||||||
{% if chpw %}
|
|
||||||
<a id="x" href="#">change password</a>
|
|
||||||
{% endif %}
|
|
||||||
{% if ahttps %}
|
|
||||||
<a id="w" href="{{ ahttps }}">switch to https</a>
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<a href="#" id="repl">π</a>
|
<a href="#" id="repl">π</a>
|
||||||
{%- if not this.args.nb %}
|
{%- if not this.args.nb %}
|
||||||
|
|
|
@ -17,9 +17,9 @@ var Ls = {
|
||||||
"l1": "logg inn:",
|
"l1": "logg inn:",
|
||||||
"m1": "velkommen tilbake,",
|
"m1": "velkommen tilbake,",
|
||||||
"n1": "404: filen finnes ikke ┐( ´ -`)┌",
|
"n1": "404: filen finnes ikke ┐( ´ -`)┌",
|
||||||
"o1": 'eller kanskje du ikke har tilgang? prøv å logge inn eller <a href="' + SR + '/?h">gå hjem</a>',
|
"o1": 'eller kanskje du ikke har tilgang? prøv et passord eller <a href="' + SR + '/?h">gå hjem</a>',
|
||||||
"p1": "403: tilgang nektet ~┻━┻",
|
"p1": "403: tilgang nektet ~┻━┻",
|
||||||
"q1": 'du må logge inn eller <a href="' + SR + '/?h">gå hjem</a>',
|
"q1": 'prøv et passord eller <a href="' + SR + '/?h">gå hjem</a>',
|
||||||
"r1": "gå hjem",
|
"r1": "gå hjem",
|
||||||
".s1": "kartlegg",
|
".s1": "kartlegg",
|
||||||
"t1": "handling",
|
"t1": "handling",
|
||||||
|
@ -29,6 +29,7 @@ var Ls = {
|
||||||
"w1": "bytt til https",
|
"w1": "bytt til https",
|
||||||
"x1": "bytt passord",
|
"x1": "bytt passord",
|
||||||
"y1": "dine delinger",
|
"y1": "dine delinger",
|
||||||
|
"z1": "lås opp område",
|
||||||
"ta1": "du må skrive et nytt passord først",
|
"ta1": "du må skrive et nytt passord først",
|
||||||
"ta2": "gjenta for å bekrefte nytt passord:",
|
"ta2": "gjenta for å bekrefte nytt passord:",
|
||||||
"ta3": "fant en skrivefeil; vennligst prøv igjen",
|
"ta3": "fant en skrivefeil; vennligst prøv igjen",
|
||||||
|
|
Loading…
Reference in a new issue