Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0265455cd1 | ||
|
|
afafc886a4 | ||
|
|
8a959f6ac4 | ||
|
|
1c3aa0d2c5 |
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -37,7 +37,7 @@
|
|||||||
"python.linting.banditEnabled": true,
|
"python.linting.banditEnabled": true,
|
||||||
"python.linting.flake8Args": [
|
"python.linting.flake8Args": [
|
||||||
"--max-line-length=120",
|
"--max-line-length=120",
|
||||||
"--ignore=E722,F405,E203,W503,W293",
|
"--ignore=E722,F405,E203,W503,W293,E402",
|
||||||
],
|
],
|
||||||
"python.linting.banditArgs": [
|
"python.linting.banditArgs": [
|
||||||
"--ignore=B104"
|
"--ignore=B104"
|
||||||
@@ -55,6 +55,6 @@
|
|||||||
//
|
//
|
||||||
// things you may wanna edit:
|
// things you may wanna edit:
|
||||||
//
|
//
|
||||||
"python.pythonPath": ".venv/bin/python",
|
"python.pythonPath": "/usr/bin/python3",
|
||||||
//"python.linting.enabled": true,
|
//"python.linting.enabled": true,
|
||||||
}
|
}
|
||||||
@@ -137,6 +137,8 @@ def main():
|
|||||||
ap.add_argument("-q", action="store_true", help="quiet")
|
ap.add_argument("-q", action="store_true", help="quiet")
|
||||||
ap.add_argument("-ed", action="store_true", help="enable ?dots")
|
ap.add_argument("-ed", action="store_true", help="enable ?dots")
|
||||||
ap.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
ap.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
||||||
|
ap.add_argument("-nih", action="store_true", help="no info hostname")
|
||||||
|
ap.add_argument("-nid", action="store_true", help="no info disk-usage")
|
||||||
al = ap.parse_args()
|
al = ap.parse_args()
|
||||||
|
|
||||||
SvcHub(al).run()
|
SvcHub(al).run()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (0, 5, 0)
|
VERSION = (0, 5, 1)
|
||||||
CODENAME = "fuse jelly"
|
CODENAME = "fuse jelly"
|
||||||
BUILD_DT = (2020, 8, 17)
|
BUILD_DT = (2020, 8, 17)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import stat
|
|||||||
import gzip
|
import gzip
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
import socket
|
||||||
|
import ctypes
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import calendar
|
import calendar
|
||||||
|
|
||||||
@@ -864,6 +866,9 @@ class HttpCli(object):
|
|||||||
#
|
#
|
||||||
# send reply
|
# send reply
|
||||||
|
|
||||||
|
if not is_compressed:
|
||||||
|
self.out_headers["Cache-Control"] = "no-cache"
|
||||||
|
|
||||||
self.out_headers["Accept-Ranges"] = "bytes"
|
self.out_headers["Accept-Ranges"] = "bytes"
|
||||||
self.send_headers(
|
self.send_headers(
|
||||||
length=upper - lower,
|
length=upper - lower,
|
||||||
@@ -1073,6 +1078,34 @@ class HttpCli(object):
|
|||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
srv_info = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not self.args.nih:
|
||||||
|
srv_info.append(str(socket.gethostname()).split(".")[0])
|
||||||
|
except:
|
||||||
|
self.log("#wow #whoa")
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
# some fuses misbehave
|
||||||
|
if not self.args.nid:
|
||||||
|
if WINDOWS:
|
||||||
|
bfree = ctypes.c_ulonglong(0)
|
||||||
|
ctypes.windll.kernel32.GetDiskFreeSpaceExW(
|
||||||
|
ctypes.c_wchar_p(abspath), None, None, ctypes.pointer(bfree)
|
||||||
|
)
|
||||||
|
srv_info.append(humansize(bfree.value) + " free")
|
||||||
|
else:
|
||||||
|
sv = os.statvfs(abspath)
|
||||||
|
free = humansize(sv.f_frsize * sv.f_bfree, True)
|
||||||
|
total = humansize(sv.f_frsize * sv.f_blocks, True)
|
||||||
|
|
||||||
|
srv_info.append(free + " free")
|
||||||
|
srv_info.append(total)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
ts = ""
|
ts = ""
|
||||||
# ts = "?{}".format(time.time())
|
# ts = "?{}".format(time.time())
|
||||||
|
|
||||||
@@ -1087,6 +1120,7 @@ class HttpCli(object):
|
|||||||
prologue=logues[0],
|
prologue=logues[0],
|
||||||
epilogue=logues[1],
|
epilogue=logues[1],
|
||||||
title=html_escape(self.vpath, quote=False),
|
title=html_escape(self.vpath, quote=False),
|
||||||
|
srv_info="</span> /// <span>".join(srv_info),
|
||||||
)
|
)
|
||||||
self.reply(html.encode("utf-8", "replace"))
|
self.reply(html.encode("utf-8", "replace"))
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -334,6 +334,21 @@ def read_header(sr):
|
|||||||
return ret[:ofs].decode("utf-8", "surrogateescape").split("\r\n")
|
return ret[:ofs].decode("utf-8", "surrogateescape").split("\r\n")
|
||||||
|
|
||||||
|
|
||||||
|
def humansize(sz, terse=False):
|
||||||
|
for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
|
||||||
|
if sz < 1024:
|
||||||
|
break
|
||||||
|
|
||||||
|
sz /= 1024
|
||||||
|
|
||||||
|
ret = ' '.join([str(sz)[:4].rstrip('.'), unit])
|
||||||
|
|
||||||
|
if not terse:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
return ret.replace('iB', '').replace(' ', '')
|
||||||
|
|
||||||
|
|
||||||
def undot(path):
|
def undot(path):
|
||||||
ret = []
|
ret = []
|
||||||
for node in path.split("/"):
|
for node in path.split("/"):
|
||||||
|
|||||||
@@ -131,6 +131,17 @@ a {
|
|||||||
.logue {
|
.logue {
|
||||||
padding: .2em 1.5em;
|
padding: .2em 1.5em;
|
||||||
}
|
}
|
||||||
|
#srv_info {
|
||||||
|
opacity: .5;
|
||||||
|
font-size: .8em;
|
||||||
|
color: #fc5;
|
||||||
|
position: absolute;
|
||||||
|
top: .5em;
|
||||||
|
left: 2em;
|
||||||
|
}
|
||||||
|
#srv_info span {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
a.play {
|
a.play {
|
||||||
color: #e70;
|
color: #e70;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,10 @@
|
|||||||
|
|
||||||
<h2><a href="?h">control-panel</a></h2>
|
<h2><a href="?h">control-panel</a></h2>
|
||||||
|
|
||||||
|
{%- if srv_info %}
|
||||||
|
<div id="srv_info"><span>{{ srv_info }}</span></div>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
<div id="widget">
|
<div id="widget">
|
||||||
<div id="wtoggle">♫</div>
|
<div id="wtoggle">♫</div>
|
||||||
<div id="widgeti">
|
<div id="widgeti">
|
||||||
|
|||||||
@@ -289,19 +289,24 @@ function save_cb() {
|
|||||||
this.btn.classList.remove('force-save');
|
this.btn.classList.remove('force-save');
|
||||||
//alert('save OK -- wrote ' + r.size + ' bytes.\n\nsha512: ' + r.sha512);
|
//alert('save OK -- wrote ' + r.size + ' bytes.\n\nsha512: ' + r.sha512);
|
||||||
|
|
||||||
|
run_savechk(r.lastmod, this.txt, this.btn, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_savechk(lastmod, txt, btn, ntry) {
|
||||||
// download the saved doc from the server and compare
|
// download the saved doc from the server and compare
|
||||||
var url = (document.location + '').split('?')[0] + '?raw';
|
var url = (document.location + '').split('?')[0] + '?raw&_=' + new Date().getTime();
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', url, true);
|
xhr.open('GET', url, true);
|
||||||
xhr.responseType = 'text';
|
xhr.responseType = 'text';
|
||||||
xhr.onreadystatechange = save_chk;
|
xhr.onreadystatechange = savechk_cb;
|
||||||
xhr.btn = this.save_btn;
|
xhr.lastmod = lastmod;
|
||||||
xhr.txt = this.txt;
|
xhr.txt = txt;
|
||||||
xhr.lastmod = r.lastmod;
|
xhr.btn = btn;
|
||||||
|
xhr.ntry = ntry;
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
function save_chk() {
|
function savechk_cb() {
|
||||||
if (this.readyState != XMLHttpRequest.DONE)
|
if (this.readyState != XMLHttpRequest.DONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -313,6 +318,14 @@ function save_chk() {
|
|||||||
var doc1 = this.txt.replace(/\r\n/g, "\n");
|
var doc1 = this.txt.replace(/\r\n/g, "\n");
|
||||||
var doc2 = this.responseText.replace(/\r\n/g, "\n");
|
var doc2 = this.responseText.replace(/\r\n/g, "\n");
|
||||||
if (doc1 != doc2) {
|
if (doc1 != doc2) {
|
||||||
|
var that = this;
|
||||||
|
if (that.ntry < 10) {
|
||||||
|
// qnap funny, try a few more times
|
||||||
|
setTimeout(function () {
|
||||||
|
run_savechk(that.lastmod, that.txt, that.btn, that.ntry + 1)
|
||||||
|
}, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
alert(
|
alert(
|
||||||
'Error! The document on the server does not appear to have saved correctly (your editor contents and the server copy is not identical). Place the document on your clipboard for now and check the server logs for hints\n\n' +
|
'Error! The document on the server does not appear to have saved correctly (your editor contents and the server copy is not identical). Place the document on your clipboard for now and check the server logs for hints\n\n' +
|
||||||
'Length: yours=' + doc1.length + ', server=' + doc2.length
|
'Length: yours=' + doc1.length + ', server=' + doc2.length
|
||||||
@@ -325,7 +338,8 @@ function save_chk() {
|
|||||||
last_modified = this.lastmod;
|
last_modified = this.lastmod;
|
||||||
server_md = this.txt;
|
server_md = this.txt;
|
||||||
draw_md();
|
draw_md();
|
||||||
toast('font-size:6em;font-family:serif;color:#cf6;width:4em;', 'OK✔️');
|
toast('font-size:6em;font-family:serif;color:#cf6;width:4em;',
|
||||||
|
'OK✔️<span style="font-size:.2em;color:#999">' + this.ntry + '</span>');
|
||||||
}
|
}
|
||||||
|
|
||||||
function toast(style, msg) {
|
function toast(style, msg) {
|
||||||
|
|||||||
35
docs/pretend-youre-qnap.patch
Normal file
35
docs/pretend-youre-qnap.patch
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py
|
||||||
|
index 2d3c1ad..e1e85a0 100644
|
||||||
|
--- a/copyparty/httpcli.py
|
||||||
|
+++ b/copyparty/httpcli.py
|
||||||
|
@@ -864,6 +864,30 @@ class HttpCli(object):
|
||||||
|
#
|
||||||
|
# send reply
|
||||||
|
|
||||||
|
+ try:
|
||||||
|
+ fakefn = self.conn.hsrv.fakefn
|
||||||
|
+ fakectr = self.conn.hsrv.fakectr
|
||||||
|
+ fakedata = self.conn.hsrv.fakedata
|
||||||
|
+ except:
|
||||||
|
+ fakefn = b''
|
||||||
|
+ fakectr = 0
|
||||||
|
+ fakedata = b''
|
||||||
|
+
|
||||||
|
+ self.log('\n{} {}\n{}'.format(fakefn, fakectr, open_args[0]))
|
||||||
|
+ if fakefn == open_args[0] and fakectr > 0:
|
||||||
|
+ self.reply(fakedata, mime=guess_mime(req_path)[0])
|
||||||
|
+ self.conn.hsrv.fakectr = fakectr - 1
|
||||||
|
+ else:
|
||||||
|
+ with open_func(*open_args) as f:
|
||||||
|
+ fakedata = f.read()
|
||||||
|
+
|
||||||
|
+ self.conn.hsrv.fakefn = open_args[0]
|
||||||
|
+ self.conn.hsrv.fakedata = fakedata
|
||||||
|
+ self.conn.hsrv.fakectr = 15
|
||||||
|
+ self.reply(fakedata, mime=guess_mime(req_path)[0])
|
||||||
|
+
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
self.out_headers["Accept-Ranges"] = "bytes"
|
||||||
|
self.send_headers(
|
||||||
|
length=upper - lower,
|
||||||
Reference in New Issue
Block a user