mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
show README.md in directory listings
This commit is contained in:
parent
ca16c4108d
commit
a009ff53f7
23
README.md
23
README.md
|
@ -477,6 +477,10 @@ and there are *two* editors
|
||||||
|
|
||||||
* click the bottom-left `π` to open a javascript prompt for debugging
|
* click the bottom-left `π` to open a javascript prompt for debugging
|
||||||
|
|
||||||
|
* files named `.prologue.html` / `.epilogue.html` will be rendered before/after directory listings unless `--no-logues`
|
||||||
|
|
||||||
|
* files named `README.md` / `readme.md` will be rendered after directory listings unless `--no-readme` (but `.epilogue.html` takes precedence)
|
||||||
|
|
||||||
|
|
||||||
## searching
|
## searching
|
||||||
|
|
||||||
|
@ -757,6 +761,24 @@ below are some tweaks roughly ordered by usefulness:
|
||||||
...however it adds an overhead to internal communication so it might be a net loss, see if it works 4 u
|
...however it adds an overhead to internal communication so it might be a net loss, see if it works 4 u
|
||||||
|
|
||||||
|
|
||||||
|
# security
|
||||||
|
|
||||||
|
some notes on hardening
|
||||||
|
|
||||||
|
on public copyparty instances with anonymous upload enabled:
|
||||||
|
|
||||||
|
* users can upload html/css/js which will evaluate for other visitors in a few ways,
|
||||||
|
* unless `--no-readme` is set: by uploading/modifying a file named `readme.md`
|
||||||
|
* if `move` access is granted AND none of `--no-logues`, `--no-dot-mv`, `--no-dot-ren` is set: by uploading some .html file and renaming it to `.epilogue.html` (uploading it directly is blocked)
|
||||||
|
|
||||||
|
|
||||||
|
## gotchas
|
||||||
|
|
||||||
|
behavior that might be unexpected
|
||||||
|
|
||||||
|
* users without read-access to a folder can still see the `.prologue.html` / `.epilogue.html` / `README.md` contents, for the purpose of showing a description on how to use the uploader for example
|
||||||
|
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
|
|
||||||
mandatory deps:
|
mandatory deps:
|
||||||
|
@ -887,7 +909,6 @@ in the `scripts` folder:
|
||||||
roughly sorted by priority
|
roughly sorted by priority
|
||||||
|
|
||||||
* hls framework for Someone Else to drop code into :^)
|
* hls framework for Someone Else to drop code into :^)
|
||||||
* readme.md as epilogue
|
|
||||||
|
|
||||||
|
|
||||||
## discarded ideas
|
## discarded ideas
|
||||||
|
|
|
@ -363,6 +363,7 @@ def run_argparse(argv, formatter):
|
||||||
ap2.add_argument("--no-dot-mv", action="store_true", help="disallow moving dotfiles; makes it impossible to move folders containing dotfiles")
|
ap2.add_argument("--no-dot-mv", action="store_true", help="disallow moving dotfiles; makes it impossible to move folders containing dotfiles")
|
||||||
ap2.add_argument("--no-dot-ren", action="store_true", help="disallow renaming dotfiles; makes it impossible to make something a dotfile")
|
ap2.add_argument("--no-dot-ren", action="store_true", help="disallow renaming dotfiles; makes it impossible to make something a dotfile")
|
||||||
ap2.add_argument("--no-logues", action="store_true", help="disable rendering .prologue/.epilogue.html into directory listings")
|
ap2.add_argument("--no-logues", action="store_true", help="disable rendering .prologue/.epilogue.html into directory listings")
|
||||||
|
ap2.add_argument("--no-readme", action="store_true", help="disable rendering readme.md into directory listings")
|
||||||
|
|
||||||
ap2 = ap.add_argument_group('logging options')
|
ap2 = ap.add_argument_group('logging options')
|
||||||
ap2.add_argument("-q", action="store_true", help="quiet")
|
ap2.add_argument("-q", action="store_true", help="quiet")
|
||||||
|
|
|
@ -1875,6 +1875,15 @@ class HttpCli(object):
|
||||||
with open(fsenc(fn), "rb") as f:
|
with open(fsenc(fn), "rb") as f:
|
||||||
logues[n] = f.read().decode("utf-8")
|
logues[n] = f.read().decode("utf-8")
|
||||||
|
|
||||||
|
readme = ""
|
||||||
|
if not self.args.no_readme and not logues[1]:
|
||||||
|
for fn in ["README.md", "readme.md"]:
|
||||||
|
fn = os.path.join(abspath, fn)
|
||||||
|
if bos.path.exists(fn):
|
||||||
|
with open(fsenc(fn), "rb") as f:
|
||||||
|
readme = f.read().decode("utf-8")
|
||||||
|
break
|
||||||
|
|
||||||
ls_ret = {
|
ls_ret = {
|
||||||
"dirs": [],
|
"dirs": [],
|
||||||
"files": [],
|
"files": [],
|
||||||
|
@ -1883,6 +1892,7 @@ class HttpCli(object):
|
||||||
"acct": self.uname,
|
"acct": self.uname,
|
||||||
"perms": perms,
|
"perms": perms,
|
||||||
"logues": logues,
|
"logues": logues,
|
||||||
|
"readme": readme,
|
||||||
}
|
}
|
||||||
j2a = {
|
j2a = {
|
||||||
"vdir": quotep(self.vpath),
|
"vdir": quotep(self.vpath),
|
||||||
|
@ -1901,6 +1911,7 @@ class HttpCli(object):
|
||||||
"have_b_u": (self.can_write and self.uparam.get("b") == "u"),
|
"have_b_u": (self.can_write and self.uparam.get("b") == "u"),
|
||||||
"url_suf": url_suf,
|
"url_suf": url_suf,
|
||||||
"logues": logues,
|
"logues": logues,
|
||||||
|
"readme": readme,
|
||||||
"title": html_escape(self.vpath, crlf=True),
|
"title": html_escape(self.vpath, crlf=True),
|
||||||
"srv_info": srv_info,
|
"srv_info": srv_info,
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,8 @@
|
||||||
have_mv = {{ have_mv|tojson }},
|
have_mv = {{ have_mv|tojson }},
|
||||||
have_del = {{ have_del|tojson }},
|
have_del = {{ have_del|tojson }},
|
||||||
have_unpost = {{ have_unpost|tojson }},
|
have_unpost = {{ have_unpost|tojson }},
|
||||||
have_zip = {{ have_zip|tojson }};
|
have_zip = {{ have_zip|tojson }},
|
||||||
|
readme = {{ readme|tojson }};
|
||||||
</script>
|
</script>
|
||||||
<script src="/.cpr/util.js?_={{ ts }}"></script>
|
<script src="/.cpr/util.js?_={{ ts }}"></script>
|
||||||
<script src="/.cpr/browser.js?_={{ ts }}"></script>
|
<script src="/.cpr/browser.js?_={{ ts }}"></script>
|
||||||
|
|
|
@ -140,9 +140,10 @@ ebi('op_cfg').innerHTML = (
|
||||||
' <div>\n' +
|
' <div>\n' +
|
||||||
' <a id="tooltips" class="tgl btn" href="#" tt="◔ ◡ ◔">ℹ️ tooltips</a>\n' +
|
' <a id="tooltips" class="tgl btn" href="#" tt="◔ ◡ ◔">ℹ️ tooltips</a>\n' +
|
||||||
' <a id="lightmode" class="tgl btn" href="#">☀️ lightmode</a>\n' +
|
' <a id="lightmode" class="tgl btn" href="#">☀️ lightmode</a>\n' +
|
||||||
' <a id="dotfiles" class="tgl btn" href="#" tt="show hidden files (if server permits)">dotfiles</a>\n' +
|
|
||||||
' <a id="griden" class="tgl btn" href="#" tt="toggle icons or list-view$NHotkey: G">田 the grid</a>\n' +
|
' <a id="griden" class="tgl btn" href="#" tt="toggle icons or list-view$NHotkey: G">田 the grid</a>\n' +
|
||||||
' <a id="thumbs" class="tgl btn" href="#" tt="in icon view, toggle icons or thumbnails$NHotkey: T">🖼️ thumbs</a>\n' +
|
' <a id="thumbs" class="tgl btn" href="#" tt="in icon view, toggle icons or thumbnails$NHotkey: T">🖼️ thumbs</a>\n' +
|
||||||
|
' <a id="dotfiles" class="tgl btn" href="#" tt="show hidden files (if server permits)">dotfiles</a>\n' +
|
||||||
|
' <a id="ireadme" class="tgl btn" href="#" tt="show README.md in folder listings">📜 readme</a>\n' +
|
||||||
' </div>\n' +
|
' </div>\n' +
|
||||||
'</div>\n' +
|
'</div>\n' +
|
||||||
(have_zip ? (
|
(have_zip ? (
|
||||||
|
@ -2999,7 +3000,8 @@ var treectl = (function () {
|
||||||
var treectl = {
|
var treectl = {
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"ls_cb": null,
|
"ls_cb": null,
|
||||||
"dir_cb": tree_scrollto
|
"dir_cb": tree_scrollto,
|
||||||
|
"ireadme": bcfg_get('ireadme', true)
|
||||||
},
|
},
|
||||||
entreed = false,
|
entreed = false,
|
||||||
fixedpos = false,
|
fixedpos = false,
|
||||||
|
@ -3320,6 +3322,12 @@ var treectl = (function () {
|
||||||
ebi('pro').innerHTML = res.logues ? res.logues[0] || "" : "";
|
ebi('pro').innerHTML = res.logues ? res.logues[0] || "" : "";
|
||||||
ebi('epi').innerHTML = res.logues ? res.logues[1] || "" : "";
|
ebi('epi').innerHTML = res.logues ? res.logues[1] || "" : "";
|
||||||
|
|
||||||
|
clmod(ebi('epi'), 'mdo');
|
||||||
|
if (res.readme)
|
||||||
|
setTimeout(function () {
|
||||||
|
show_readme(res.readme);
|
||||||
|
}, 10);
|
||||||
|
|
||||||
document.title = '⇆🎉 ' + uricom_dec(document.location.pathname.slice(1, -1))[0];
|
document.title = '⇆🎉 ' + uricom_dec(document.location.pathname.slice(1, -1))[0];
|
||||||
|
|
||||||
filecols.set_style();
|
filecols.set_style();
|
||||||
|
@ -3372,6 +3380,12 @@ var treectl = (function () {
|
||||||
treectl.goto(get_evpath());
|
treectl.goto(get_evpath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function treadme(e) {
|
||||||
|
ev(e);
|
||||||
|
treectl.ireadme = !treectl.ireadme;
|
||||||
|
bcfg_set('ireadme', treectl.ireadme);
|
||||||
|
}
|
||||||
|
|
||||||
function dyntree(e) {
|
function dyntree(e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
dyn = !dyn;
|
dyn = !dyn;
|
||||||
|
@ -3393,6 +3407,7 @@ var treectl = (function () {
|
||||||
ebi('detree').onclick = treectl.detree;
|
ebi('detree').onclick = treectl.detree;
|
||||||
ebi('visdir').onclick = tree_scrollto;
|
ebi('visdir').onclick = tree_scrollto;
|
||||||
ebi('dotfiles').onclick = tdots;
|
ebi('dotfiles').onclick = tdots;
|
||||||
|
ebi('ireadme').onclick = treadme;
|
||||||
ebi('dyntree').onclick = dyntree;
|
ebi('dyntree').onclick = dyntree;
|
||||||
ebi('twig').onclick = scaletree;
|
ebi('twig').onclick = scaletree;
|
||||||
ebi('twobytwo').onclick = scaletree;
|
ebi('twobytwo').onclick = scaletree;
|
||||||
|
@ -3823,6 +3838,7 @@ var light;
|
||||||
|
|
||||||
function freshen() {
|
function freshen() {
|
||||||
clmod(document.documentElement, "light", light);
|
clmod(document.documentElement, "light", light);
|
||||||
|
clmod(document.documentElement, "dark", !light);
|
||||||
pbar.drawbuf();
|
pbar.drawbuf();
|
||||||
pbar.drawpos();
|
pbar.drawpos();
|
||||||
vbar.draw();
|
vbar.draw();
|
||||||
|
@ -4036,6 +4052,51 @@ var msel = (function () {
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
function show_readme(md, url, depth) {
|
||||||
|
if (!treectl.ireadme)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var div = ebi('epi'),
|
||||||
|
errmsg = 'cannot show README.md:\n\n',
|
||||||
|
now = window.location.href.replace(/\/?[?#].*/, "");
|
||||||
|
|
||||||
|
url = url || now;
|
||||||
|
if (url != now)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!window['marked']) {
|
||||||
|
if (depth)
|
||||||
|
return toast.warn(10, errmsg + 'failed to load marked.js')
|
||||||
|
|
||||||
|
return import_js('/.cpr/deps/marked.js', function () {
|
||||||
|
show_readme(md, url, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
clmod(div, 'mdo', 1);
|
||||||
|
div.innerHTML = marked(md, {
|
||||||
|
headerPrefix: 'md-',
|
||||||
|
breaks: true,
|
||||||
|
gfm: true
|
||||||
|
});
|
||||||
|
var links = QSA('#epi a');
|
||||||
|
for (var a = 0, aa = links.length; a < aa; a++) {
|
||||||
|
var href = links[a].getAttribute('href');
|
||||||
|
if (!href.startsWith('#'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
links[a].setAttribute('href', '#md-' + href.slice(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
toast.warn(10, errmsg + ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (readme)
|
||||||
|
show_readme(readme);
|
||||||
|
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
try {
|
try {
|
||||||
var tr = ebi('files').tBodies[0].rows;
|
var tr = ebi('files').tBodies[0].rows;
|
||||||
|
|
|
@ -365,6 +365,7 @@ html.light #tt em {
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
word-wrap: break-word; /*ie*/
|
word-wrap: break-word; /*ie*/
|
||||||
}
|
}
|
||||||
|
html.light .mdo a,
|
||||||
.mdo a {
|
.mdo a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #39b;
|
background: #39b;
|
||||||
|
|
Loading…
Reference in a new issue