copyparty 1.15.9__py3-none-any.whl → 1.16.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copyparty/__init__.py +1 -0
- copyparty/__main__.py +16 -1
- copyparty/__version__.py +3 -3
- copyparty/authsrv.py +15 -10
- copyparty/broker_mp.py +40 -5
- copyparty/broker_mpw.py +20 -19
- copyparty/broker_thr.py +2 -2
- copyparty/cfg.py +4 -0
- copyparty/ftpd.py +1 -0
- copyparty/httpcli.py +285 -79
- copyparty/httpsrv.py +39 -0
- copyparty/metrics.py +3 -0
- copyparty/svchub.py +47 -33
- copyparty/szip.py +1 -1
- copyparty/tcpsrv.py +2 -2
- copyparty/tftpd.py +1 -0
- copyparty/th_srv.py +10 -3
- copyparty/up2k.py +339 -69
- copyparty/util.py +79 -11
- copyparty/web/a/partyfuse.py +3 -2
- copyparty/web/a/u2c.py +20 -5
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/shares.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +24 -3
- copyparty/web/splash.js.gz +0 -0
- copyparty/web/ui.css.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.16.0.dist-info}/METADATA +12 -4
- {copyparty-1.15.9.dist-info → copyparty-1.16.0.dist-info}/RECORD +35 -35
- {copyparty-1.15.9.dist-info → copyparty-1.16.0.dist-info}/WHEEL +1 -1
- {copyparty-1.15.9.dist-info → copyparty-1.16.0.dist-info}/LICENSE +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.16.0.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.16.0.dist-info}/top_level.txt +0 -0
copyparty/util.py
CHANGED
@@ -415,6 +415,27 @@ UNHUMANIZE_UNITS = {
|
|
415
415
|
VF_CAREFUL = {"mv_re_t": 5, "rm_re_t": 5, "mv_re_r": 0.1, "rm_re_r": 0.1}
|
416
416
|
|
417
417
|
|
418
|
+
def read_ram() :
|
419
|
+
a = b = 0
|
420
|
+
try:
|
421
|
+
with open("/proc/meminfo", "rb", 0x10000) as f:
|
422
|
+
zsl = f.read(0x10000).decode("ascii", "replace").split("\n")
|
423
|
+
|
424
|
+
p = re.compile("^MemTotal:.* kB")
|
425
|
+
zs = next((x for x in zsl if p.match(x)))
|
426
|
+
a = int((int(zs.split()[1]) / 0x100000) * 100) / 100
|
427
|
+
|
428
|
+
p = re.compile("^MemAvailable:.* kB")
|
429
|
+
zs = next((x for x in zsl if p.match(x)))
|
430
|
+
b = int((int(zs.split()[1]) / 0x100000) * 100) / 100
|
431
|
+
except:
|
432
|
+
pass
|
433
|
+
return a, b
|
434
|
+
|
435
|
+
|
436
|
+
RAM_TOTAL, RAM_AVAIL = read_ram()
|
437
|
+
|
438
|
+
|
418
439
|
pybin = sys.executable or ""
|
419
440
|
if EXE:
|
420
441
|
pybin = ""
|
@@ -647,13 +668,20 @@ class HLog(logging.Handler):
|
|
647
668
|
|
648
669
|
class NetMap(object):
|
649
670
|
def __init__(
|
650
|
-
self,
|
671
|
+
self,
|
672
|
+
ips ,
|
673
|
+
cidrs ,
|
674
|
+
keep_lo=False,
|
675
|
+
strict_cidr=False,
|
676
|
+
defer_mutex=False,
|
651
677
|
) :
|
652
678
|
"""
|
653
679
|
ips: list of plain ipv4/ipv6 IPs, not cidr
|
654
680
|
cidrs: list of cidr-notation IPs (ip/prefix)
|
655
681
|
"""
|
656
|
-
|
682
|
+
|
683
|
+
# fails multiprocessing; defer assignment
|
684
|
+
self.mutex = None if defer_mutex else threading.Lock()
|
657
685
|
|
658
686
|
if "::" in ips:
|
659
687
|
ips = [x for x in ips if x != "::"] + list(
|
@@ -692,6 +720,8 @@ class NetMap(object):
|
|
692
720
|
try:
|
693
721
|
return self.cache[ip]
|
694
722
|
except:
|
723
|
+
# intentionally crash the calling thread if unset:
|
724
|
+
|
695
725
|
with self.mutex:
|
696
726
|
return self._map(ip)
|
697
727
|
|
@@ -940,6 +970,7 @@ class MTHash(object):
|
|
940
970
|
self.sz = 0
|
941
971
|
self.csz = 0
|
942
972
|
self.stop = False
|
973
|
+
self.readsz = 1024 * 1024 * (2 if (RAM_AVAIL or 2) < 1 else 12)
|
943
974
|
self.omutex = threading.Lock()
|
944
975
|
self.imutex = threading.Lock()
|
945
976
|
self.work_q = Queue()
|
@@ -1014,7 +1045,7 @@ class MTHash(object):
|
|
1014
1045
|
while chunk_rem > 0:
|
1015
1046
|
with self.imutex:
|
1016
1047
|
f.seek(ofs)
|
1017
|
-
buf = f.read(min(chunk_rem,
|
1048
|
+
buf = f.read(min(chunk_rem, self.readsz))
|
1018
1049
|
|
1019
1050
|
if not buf:
|
1020
1051
|
raise Exception("EOF at " + str(ofs))
|
@@ -2109,6 +2140,23 @@ def unquotep(txt ) :
|
|
2109
2140
|
return w8dec(unq2)
|
2110
2141
|
|
2111
2142
|
|
2143
|
+
def vroots(vp1 , vp2 ) :
|
2144
|
+
"""
|
2145
|
+
input("q/w/e/r","a/s/d/e/r") output("/q/w/","/a/s/d/")
|
2146
|
+
"""
|
2147
|
+
while vp1 and vp2:
|
2148
|
+
zt1 = vp1.rsplit("/", 1) if "/" in vp1 else ("", vp1)
|
2149
|
+
zt2 = vp2.rsplit("/", 1) if "/" in vp2 else ("", vp2)
|
2150
|
+
if zt1[1] != zt2[1]:
|
2151
|
+
break
|
2152
|
+
vp1 = zt1[0]
|
2153
|
+
vp2 = zt2[0]
|
2154
|
+
return (
|
2155
|
+
"/%s/" % (vp1,) if vp1 else "/",
|
2156
|
+
"/%s/" % (vp2,) if vp2 else "/",
|
2157
|
+
)
|
2158
|
+
|
2159
|
+
|
2112
2160
|
def vsplit(vpath ) :
|
2113
2161
|
if "/" not in vpath:
|
2114
2162
|
return "", vpath
|
@@ -2568,7 +2616,7 @@ def list_ips() :
|
|
2568
2616
|
return list(ret)
|
2569
2617
|
|
2570
2618
|
|
2571
|
-
def build_netmap(csv ):
|
2619
|
+
def build_netmap(csv , defer_mutex = False):
|
2572
2620
|
csv = csv.lower().strip()
|
2573
2621
|
|
2574
2622
|
if csv in ("any", "all", "no", ",", ""):
|
@@ -2603,10 +2651,12 @@ def build_netmap(csv ):
|
|
2603
2651
|
cidrs.append(zs)
|
2604
2652
|
|
2605
2653
|
ips = [x.split("/")[0] for x in cidrs]
|
2606
|
-
return NetMap(ips, cidrs, True)
|
2654
|
+
return NetMap(ips, cidrs, True, False, defer_mutex)
|
2607
2655
|
|
2608
2656
|
|
2609
|
-
def load_ipu(
|
2657
|
+
def load_ipu(
|
2658
|
+
log , ipus , defer_mutex = False
|
2659
|
+
) :
|
2610
2660
|
ip_u = {"": "*"}
|
2611
2661
|
cidr_u = {}
|
2612
2662
|
for ipu in ipus:
|
@@ -2623,7 +2673,7 @@ def load_ipu(log , ipus ) :
|
|
2623
2673
|
cidr_u[cidr] = uname
|
2624
2674
|
ip_u[cip] = uname
|
2625
2675
|
try:
|
2626
|
-
nm = NetMap(["::"], list(cidr_u.keys()), True, True)
|
2676
|
+
nm = NetMap(["::"], list(cidr_u.keys()), True, True, defer_mutex)
|
2627
2677
|
except Exception as ex:
|
2628
2678
|
t = "failed to translate --ipu into netmap, probably due to invalid config: %r"
|
2629
2679
|
log("root", t % (ex,), 1)
|
@@ -2676,7 +2726,10 @@ def sendfile_py(
|
|
2676
2726
|
bufsz ,
|
2677
2727
|
slp ,
|
2678
2728
|
use_poll ,
|
2729
|
+
dls ,
|
2730
|
+
dl_id ,
|
2679
2731
|
) :
|
2732
|
+
sent = 0
|
2680
2733
|
remains = upper - lower
|
2681
2734
|
f.seek(lower)
|
2682
2735
|
while remains > 0:
|
@@ -2693,6 +2746,10 @@ def sendfile_py(
|
|
2693
2746
|
except:
|
2694
2747
|
return remains
|
2695
2748
|
|
2749
|
+
if dl_id:
|
2750
|
+
sent += len(buf)
|
2751
|
+
dls[dl_id] = (time.time(), sent)
|
2752
|
+
|
2696
2753
|
return 0
|
2697
2754
|
|
2698
2755
|
|
@@ -2705,6 +2762,8 @@ def sendfile_kern(
|
|
2705
2762
|
bufsz ,
|
2706
2763
|
slp ,
|
2707
2764
|
use_poll ,
|
2765
|
+
dls ,
|
2766
|
+
dl_id ,
|
2708
2767
|
) :
|
2709
2768
|
out_fd = s.fileno()
|
2710
2769
|
in_fd = f.fileno()
|
@@ -2717,7 +2776,7 @@ def sendfile_kern(
|
|
2717
2776
|
while ofs < upper:
|
2718
2777
|
stuck = stuck or time.time()
|
2719
2778
|
try:
|
2720
|
-
req = min(
|
2779
|
+
req = min(0x2000000, upper - ofs) # 32 MiB
|
2721
2780
|
if use_poll:
|
2722
2781
|
poll.poll(10000)
|
2723
2782
|
else:
|
@@ -2741,13 +2800,16 @@ def sendfile_kern(
|
|
2741
2800
|
return upper - ofs
|
2742
2801
|
|
2743
2802
|
ofs += n
|
2803
|
+
if dl_id:
|
2804
|
+
dls[dl_id] = (time.time(), ofs - lower)
|
2805
|
+
|
2744
2806
|
# print("sendfile: ok, sent {} now, {} total, {} remains".format(n, ofs - lower, upper - ofs))
|
2745
2807
|
|
2746
2808
|
return 0
|
2747
2809
|
|
2748
2810
|
|
2749
2811
|
def statdir(
|
2750
|
-
logger , scandir , lstat , top
|
2812
|
+
logger , scandir , lstat , top , throw
|
2751
2813
|
) :
|
2752
2814
|
if lstat and ANYWIN:
|
2753
2815
|
lstat = False
|
@@ -2783,6 +2845,12 @@ def statdir(
|
|
2783
2845
|
logger(src, "[s] {} @ {}".format(repr(ex), fsdec(abspath)), 6)
|
2784
2846
|
|
2785
2847
|
except Exception as ex:
|
2848
|
+
if throw:
|
2849
|
+
zi = getattr(ex, "errno", 0)
|
2850
|
+
if zi == errno.ENOENT:
|
2851
|
+
raise Pebkac(404, str(ex))
|
2852
|
+
raise
|
2853
|
+
|
2786
2854
|
t = "{} @ {}".format(repr(ex), top)
|
2787
2855
|
if logger:
|
2788
2856
|
logger(src, t, 1)
|
@@ -2791,7 +2859,7 @@ def statdir(
|
|
2791
2859
|
|
2792
2860
|
|
2793
2861
|
def dir_is_empty(logger , scandir , top ):
|
2794
|
-
for _ in statdir(logger, scandir, False, top):
|
2862
|
+
for _ in statdir(logger, scandir, False, top, False):
|
2795
2863
|
return False
|
2796
2864
|
return True
|
2797
2865
|
|
@@ -2804,7 +2872,7 @@ def rmdirs(
|
|
2804
2872
|
top = os.path.dirname(top)
|
2805
2873
|
depth -= 1
|
2806
2874
|
|
2807
|
-
stats = statdir(logger, scandir, lstat, top)
|
2875
|
+
stats = statdir(logger, scandir, lstat, top, False)
|
2808
2876
|
dirs = [x[0] for x in stats if stat.S_ISDIR(x[1].st_mode)]
|
2809
2877
|
dirs = [os.path.join(top, x) for x in dirs]
|
2810
2878
|
ok = []
|
copyparty/web/a/partyfuse.py
CHANGED
@@ -358,7 +358,8 @@ class Gateway(object):
|
|
358
358
|
if r.status != 200:
|
359
359
|
self.closeconn()
|
360
360
|
info("http error %s reading dir %r", r.status, web_path)
|
361
|
-
|
361
|
+
err = errno.ENOENT if r.status == 404 else errno.EIO
|
362
|
+
raise FuseOSError(err)
|
362
363
|
|
363
364
|
ctype = r.getheader("Content-Type", "")
|
364
365
|
if ctype == "application/json":
|
@@ -844,7 +845,7 @@ def main():
|
|
844
845
|
|
845
846
|
# dircache is always a boost,
|
846
847
|
# only want to disable it for tests etc,
|
847
|
-
cdn =
|
848
|
+
cdn = 24 # max num dirs; keep larger than max dir depth; 0=disable
|
848
849
|
cds = 1 # numsec until an entry goes stale
|
849
850
|
|
850
851
|
where = "local directory"
|
copyparty/web/a/u2c.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
from __future__ import print_function, unicode_literals
|
3
3
|
|
4
|
-
S_VERSION = "2.
|
5
|
-
S_BUILD_DT = "2024-10
|
4
|
+
S_VERSION = "2.6"
|
5
|
+
S_BUILD_DT = "2024-11-10"
|
6
6
|
|
7
7
|
"""
|
8
8
|
u2c.py: upload to copyparty
|
@@ -189,6 +189,8 @@ class HCli(object):
|
|
189
189
|
return C(self.addr, self.port, timeout=timeout, **args)
|
190
190
|
|
191
191
|
def req(self, meth, vpath, hdrs, body=None, ctype=None):
|
192
|
+
now = time.time()
|
193
|
+
|
192
194
|
hdrs.update(self.base_hdrs)
|
193
195
|
if self.ar.a:
|
194
196
|
hdrs["PW"] = self.ar.a
|
@@ -201,7 +203,9 @@ class HCli(object):
|
|
201
203
|
|
202
204
|
# large timeout for handshakes (safededup)
|
203
205
|
conns = self.hconns if ctype == MJ else self.conns
|
204
|
-
|
206
|
+
while conns and self.ar.cxp < now - conns[0][0]:
|
207
|
+
conns.pop(0)[1].close()
|
208
|
+
c = conns.pop()[1] if conns else self._connect(999 if ctype == MJ else 128)
|
205
209
|
try:
|
206
210
|
c.request(meth, vpath, body, hdrs)
|
207
211
|
if PY27:
|
@@ -210,8 +214,15 @@ class HCli(object):
|
|
210
214
|
rsp = c.getresponse()
|
211
215
|
|
212
216
|
data = rsp.read()
|
213
|
-
conns.append(c)
|
217
|
+
conns.append((time.time(), c))
|
214
218
|
return rsp.status, data.decode("utf-8")
|
219
|
+
except http_client.BadStatusLine:
|
220
|
+
if self.ar.cxp > 4:
|
221
|
+
t = "\nWARNING: --cxp probably too high; reducing from %d to 4"
|
222
|
+
print(t % (self.ar.cxp,))
|
223
|
+
self.ar.cxp = 4
|
224
|
+
c.close()
|
225
|
+
raise
|
215
226
|
except:
|
216
227
|
c.close()
|
217
228
|
raise
|
@@ -1140,7 +1151,10 @@ class Ctl(object):
|
|
1140
1151
|
|
1141
1152
|
if self.ar.drd:
|
1142
1153
|
dp = os.path.join(top, rd)
|
1143
|
-
|
1154
|
+
try:
|
1155
|
+
lnodes = set(os.listdir(dp))
|
1156
|
+
except:
|
1157
|
+
lnodes = list(ls) # fs eio; don't delete
|
1144
1158
|
if ptn:
|
1145
1159
|
zs = dp.replace(sep, b"/").rstrip(b"/") + b"/"
|
1146
1160
|
zls = [zs + x for x in lnodes]
|
@@ -1498,6 +1512,7 @@ source file/folder selection uses rsync syntax, meaning that:
|
|
1498
1512
|
ap.add_argument("--szm", type=int, metavar="MiB", default=96, help="max size of each POST (default is cloudflare max)")
|
1499
1513
|
ap.add_argument("-nh", action="store_true", help="disable hashing while uploading")
|
1500
1514
|
ap.add_argument("-ns", action="store_true", help="no status panel (for slow consoles and macos)")
|
1515
|
+
ap.add_argument("--cxp", type=float, metavar="SEC", default=57, help="assume http connections expired after SEConds")
|
1501
1516
|
ap.add_argument("--cd", type=float, metavar="SEC", default=5, help="delay before reattempting a failed handshake/upload")
|
1502
1517
|
ap.add_argument("--safe", action="store_true", help="use simple fallback approach")
|
1503
1518
|
ap.add_argument("-z", action="store_true", help="ZOOMIN' (skip uploading files if they exist at the destination with the ~same last-modified timestamp, so same as yolo / turbo with date-chk but even faster)")
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.js.gz
CHANGED
Binary file
|
copyparty/web/shares.js.gz
CHANGED
Binary file
|
copyparty/web/splash.css.gz
CHANGED
Binary file
|
copyparty/web/splash.html
CHANGED
@@ -44,6 +44,18 @@
|
|
44
44
|
</table>
|
45
45
|
{%- endif %}
|
46
46
|
|
47
|
+
{%- if dls %}
|
48
|
+
<h1 id="ae">active downloads:</h1>
|
49
|
+
<table class="vols">
|
50
|
+
<thead><tr><th>%</th><th>sent</th><th>speed</th><th>eta</th><th>idle</th><th></th><th>dir</th><th>file</th></tr></thead>
|
51
|
+
<tbody>
|
52
|
+
{% for u in dls %}
|
53
|
+
<tr><td>{{ u[0] }}</td><td>{{ u[1] }}</td><td>{{ u[2] }}</td><td>{{ u[3] }}</td><td>{{ u[4] }}</td><td>{{ u[5] }}</td><td><a href="{{ u[6] }}">{{ u[7]|e }}</a></td><td>{{ u[8] }}</td></tr>
|
54
|
+
{% endfor %}
|
55
|
+
</tbody>
|
56
|
+
</table>
|
57
|
+
{%- endif %}
|
58
|
+
|
47
59
|
{%- if avol %}
|
48
60
|
<h1>admin panel:</h1>
|
49
61
|
<table><tr><td> <!-- hehehe -->
|
@@ -129,11 +141,20 @@
|
|
129
141
|
|
130
142
|
{% if k304 or k304vis %}
|
131
143
|
{% if k304 %}
|
132
|
-
<li><a id="h" href="{{ r }}/?k304=n">disable k304</a> (currently enabled)
|
144
|
+
<li><a id="h" href="{{ r }}/?cc&setck=k304=n">disable k304</a> (currently enabled)
|
145
|
+
{%- else %}
|
146
|
+
<li><a id="i" href="{{ r }}/?cc&setck=k304=y" class="r">enable k304</a> (currently disabled)
|
147
|
+
{% endif %}
|
148
|
+
<blockquote id="j">enabling k304 will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), <em>but</em> it will also make things slower in general</blockquote></li>
|
149
|
+
{% endif %}
|
150
|
+
|
151
|
+
{% if no304 or no304vis %}
|
152
|
+
{% if no304 %}
|
153
|
+
<li><a id="ab" href="{{ r }}/?cc&setck=no304=n">disable no304</a> (currently enabled)
|
133
154
|
{%- else %}
|
134
|
-
<li><a id="
|
155
|
+
<li><a id="ac" href="{{ r }}/?cc&setck=no304=y" class="r">enable no304</a> (currently disabled)
|
135
156
|
{% endif %}
|
136
|
-
<blockquote id="
|
157
|
+
<blockquote id="ad">enabling no304 will disable all caching; try this if k304 wasn't enough. This will waste a huge amount of network traffic!</blockquote></li>
|
137
158
|
{% endif %}
|
138
159
|
|
139
160
|
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>
|
copyparty/web/splash.js.gz
CHANGED
Binary file
|
copyparty/web/ui.css.gz
CHANGED
Binary file
|
copyparty/web/util.js.gz
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.16.0
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
6
6
|
License: MIT
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: Jython
|
26
27
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
@@ -482,7 +483,7 @@ configuring accounts/volumes with arguments:
|
|
482
483
|
|
483
484
|
permissions:
|
484
485
|
* `r` (read): browse folder contents, download files, download as zip/tar, see filekeys/dirkeys
|
485
|
-
* `w` (write): upload files, move files *into* this folder
|
486
|
+
* `w` (write): upload files, move/copy files *into* this folder
|
486
487
|
* `m` (move): move files/folders *from* this folder
|
487
488
|
* `d` (delete): delete files/folders
|
488
489
|
* `.` (dots): user can ask to show dotfiles in directory listings
|
@@ -562,7 +563,8 @@ the browser has the following hotkeys (always qwerty)
|
|
562
563
|
* `ESC` close various things
|
563
564
|
* `ctrl-K` delete selected files/folders
|
564
565
|
* `ctrl-X` cut selected files/folders
|
565
|
-
* `ctrl-
|
566
|
+
* `ctrl-C` copy selected files/folders to clipboard
|
567
|
+
* `ctrl-V` paste (move/copy)
|
566
568
|
* `Y` download selected files
|
567
569
|
* `F2` [rename](#batch-rename) selected file/folder
|
568
570
|
* when a file/folder is selected (in not-grid-view):
|
@@ -631,6 +633,7 @@ click the `🌲` or pressing the `B` hotkey to toggle between breadcrumbs path (
|
|
631
633
|
|
632
634
|
press `g` or `田` to toggle grid-view instead of the file listing and `t` toggles icons / thumbnails
|
633
635
|
* can be made default globally with `--grid` or per-volume with volflag `grid`
|
636
|
+
* enable by adding `?imgs` to a link, or disable with `?imgs=0`
|
634
637
|
|
635
638
|

|
636
639
|
|
@@ -810,10 +813,11 @@ file selection: click somewhere on the line (not the link itself), then:
|
|
810
813
|
* shift-click another line for range-select
|
811
814
|
|
812
815
|
* cut: select some files and `ctrl-x`
|
816
|
+
* copy: select some files and `ctrl-c`
|
813
817
|
* paste: `ctrl-v` in another folder
|
814
818
|
* rename: `F2`
|
815
819
|
|
816
|
-
you can move files across browser tabs (cut in one tab, paste in another)
|
820
|
+
you can copy/move files across browser tabs (cut/copy in one tab, paste in another)
|
817
821
|
|
818
822
|
|
819
823
|
## shares
|
@@ -1738,6 +1742,7 @@ scrape_configs:
|
|
1738
1742
|
currently the following metrics are available,
|
1739
1743
|
* `cpp_uptime_seconds` time since last copyparty restart
|
1740
1744
|
* `cpp_boot_unixtime_seconds` same but as an absolute timestamp
|
1745
|
+
* `cpp_active_dl` number of active downloads
|
1741
1746
|
* `cpp_http_conns` number of open http(s) connections
|
1742
1747
|
* `cpp_http_reqs` number of http(s) requests handled
|
1743
1748
|
* `cpp_sus_reqs` number of 403/422/malicious requests
|
@@ -1987,6 +1992,9 @@ quick summary of more eccentric web-browsers trying to view a directory index:
|
|
1987
1992
|
| **ie4** and **netscape** 4.0 | can browse, upload with `?b=u`, auth with `&pw=wark` |
|
1988
1993
|
| **ncsa mosaic** 2.7 | does not get a pass, [pic1](https://user-images.githubusercontent.com/241032/174189227-ae816026-cf6f-4be5-a26e-1b3b072c1b2f.png) - [pic2](https://user-images.githubusercontent.com/241032/174189225-5651c059-5152-46e9-ac26-7e98e497901b.png) |
|
1989
1994
|
| **SerenityOS** (7e98457) | hits a page fault, works with `?b=u`, file upload not-impl |
|
1995
|
+
| **nintendo 3ds** | can browse, upload, view thumbnails (thx bnjmn) |
|
1996
|
+
|
1997
|
+
<p align="center"><img src="https://github.com/user-attachments/assets/88deab3d-6cad-4017-8841-2f041472b853" /></p>
|
1990
1998
|
|
1991
1999
|
|
1992
2000
|
# client examples
|
@@ -1,22 +1,22 @@
|
|
1
|
-
copyparty/__init__.py,sha256=
|
2
|
-
copyparty/__main__.py,sha256=
|
3
|
-
copyparty/__version__.py,sha256=
|
4
|
-
copyparty/authsrv.py,sha256=
|
5
|
-
copyparty/broker_mp.py,sha256=
|
6
|
-
copyparty/broker_mpw.py,sha256=
|
7
|
-
copyparty/broker_thr.py,sha256=
|
1
|
+
copyparty/__init__.py,sha256=iRCNvMPg6k9WG_O2uCtlkD4vWogH8EgP9elp9XwSIJs,2610
|
2
|
+
copyparty/__main__.py,sha256=NpKXKPp6rAuWYw-fMWs-iS0dAjyOMl9WBtwBTYsH9zY,112286
|
3
|
+
copyparty/__version__.py,sha256=snuFV6IoeKYLPgiZHLcMTRengBZI8NN2la43bff1e3E,252
|
4
|
+
copyparty/authsrv.py,sha256=7ypOOehMN-NiC10y46lO-sDU8uGGnXrJz2rt9njKEZg,99237
|
5
|
+
copyparty/broker_mp.py,sha256=QdOXXvV2Xn6J0CysEqyY3GZbqxQMyWnTpnba-a5lMc0,4987
|
6
|
+
copyparty/broker_mpw.py,sha256=PpSS4SK3pItlpfD8OwVr3QmJEPKlUgaf2nuMOozixgU,3347
|
7
|
+
copyparty/broker_thr.py,sha256=fjoYtpSscUA7-nMl4r1n2R7UK3J9lrvLS3rUZ-iJzKQ,1721
|
8
8
|
copyparty/broker_util.py,sha256=76mfnFOpX1gUUvtjm8UQI7jpTIaVINX10QonM-B7ggc,1680
|
9
9
|
copyparty/cert.py,sha256=0ZAPeXeMR164vWn9GQU3JDKooYXEq_NOQkDeg543ivg,8009
|
10
|
-
copyparty/cfg.py,sha256=
|
10
|
+
copyparty/cfg.py,sha256=4-Tk1Yb3eGcA8pO3jNRzd9HfCci6vRu3BNWarry0ia8,10263
|
11
11
|
copyparty/dxml.py,sha256=lZpg-kn-kQsXRtNY1n6fRaS-b7uXzMCyv8ovKnhZcZc,1548
|
12
12
|
copyparty/fsutil.py,sha256=5CshJWO7CflfaRRNOb3JxghUH7W5rmS_HWNmKfx42MM,4538
|
13
|
-
copyparty/ftpd.py,sha256=
|
14
|
-
copyparty/httpcli.py,sha256=
|
13
|
+
copyparty/ftpd.py,sha256=T97SFS7JFtvRLbJX8C4fJSYwe13vhN3-E6emtlVmqLA,17608
|
14
|
+
copyparty/httpcli.py,sha256=tu5abG7JpDZYTDlPNv9p5SYGd0ZgAdoWf8HNYAr45V4,206103
|
15
15
|
copyparty/httpconn.py,sha256=mQSgljh0Q-jyWjF4tQLrHbRKRe9WKl19kGqsGMsJpWo,6880
|
16
|
-
copyparty/httpsrv.py,sha256=
|
16
|
+
copyparty/httpsrv.py,sha256=WMQ-0sk6wk4Gbg7FB1ZYvnb74EsZQ5b7WJT0zAwZXjA,18226
|
17
17
|
copyparty/ico.py,sha256=eWSxEae4wOCfheHl-m-wchYvFRAR_97kJDb4NGaB-Z8,3561
|
18
18
|
copyparty/mdns.py,sha256=vC078llnL1v0pvL3mnwacuStFHPJUQuxo9Opj-IbHL4,18155
|
19
|
-
copyparty/metrics.py,sha256
|
19
|
+
copyparty/metrics.py,sha256=EOIiPOItEQmdK9YgNb75l0kCzanWb6RtJGwMI7ufifY,8966
|
20
20
|
copyparty/mtag.py,sha256=8WGjEn0T0Ri9ww1yBpLUnFHZiTQMye1BMXL6SkK3MRo,18893
|
21
21
|
copyparty/multicast.py,sha256=Ha27l2oATEa-Qo2WOzkeRgjAm6G_YDCfbVJWR-ao2UE,12319
|
22
22
|
copyparty/pwhash.py,sha256=AdLMLyIi2IDhGtbKIQOswKUxWvO7ARYYRF_ThsryOoc,4124
|
@@ -24,15 +24,15 @@ copyparty/smbd.py,sha256=Or7RF13cl1r3ncnpVh8BqyAGqH2Oa04O9iPZWCoB0Bo,14609
|
|
24
24
|
copyparty/ssdp.py,sha256=R1Z61GZOxBMF2Sk4RTxKWMOemogmcjEWG-CvLihd45k,7023
|
25
25
|
copyparty/star.py,sha256=tV5BbX6AiQ7N4UU8DYtSTckNYeoeey4DBqq4LjfymbY,3818
|
26
26
|
copyparty/sutil.py,sha256=JTMrQwcWH85hXB_cKG206eDZ967WZDGaP00AWvl_gB0,3214
|
27
|
-
copyparty/svchub.py,sha256=
|
28
|
-
copyparty/szip.py,sha256=
|
29
|
-
copyparty/tcpsrv.py,sha256=
|
30
|
-
copyparty/tftpd.py,sha256=
|
27
|
+
copyparty/svchub.py,sha256=op6BtcsSa0OLmnJ_dslPswaNTOZaqScM8tRZnQrMkDs,40864
|
28
|
+
copyparty/szip.py,sha256=HFtnwOiBgx0HMLUf-h_T84zSlRijPxmhRo5PM613kRA,8602
|
29
|
+
copyparty/tcpsrv.py,sha256=VuW_aVDcyXIhIMZ8I-wpIouX8MI9TGp7KKSRohrMTtk,19897
|
30
|
+
copyparty/tftpd.py,sha256=FRCALO3PigoBlwUrqxoKHM_xk7wT2O0GPG1TvNRtjOY,13606
|
31
31
|
copyparty/th_cli.py,sha256=o6FMkerYvAXS455z3DUossVztu_nzFlYSQhs6qN6Jt8,4636
|
32
|
-
copyparty/th_srv.py,sha256=
|
32
|
+
copyparty/th_srv.py,sha256=LBcB4LpsF-H7L52Z0Dhn9LogRjJVPp1GKa8MeIMIBnw,29596
|
33
33
|
copyparty/u2idx.py,sha256=HLO49L1zmpJtBcJiXgD12a6pAlQdnf2pFelHMA7habw,13462
|
34
|
-
copyparty/up2k.py,sha256=
|
35
|
-
copyparty/util.py,sha256=
|
34
|
+
copyparty/up2k.py,sha256=m7sWNWmRR1-VoFzlXlAOYxwhOlbeOyFBO5a8Rcl6mnE,173608
|
35
|
+
copyparty/util.py,sha256=jk4Z32KuIvqPQK8aveYhUfGZT9k0LR8viGGfcX4iab4,94422
|
36
36
|
copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
copyparty/bos/bos.py,sha256=Wb7eWsXJgR5AFlBR9ZOyKrLTwy-Kct9RrGiOu4Jo37Y,1622
|
38
38
|
copyparty/bos/path.py,sha256=yEjCq2ki9CvxA5sCT8pS0keEXwugs0ZeUyUhdBziOCI,777
|
@@ -55,9 +55,9 @@ copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUu
|
|
55
55
|
copyparty/stolen/ifaddr/_shared.py,sha256=uNC4SdEIgdSLKvuUzsf1aM-H1Xrc_9mpLoOT43YukGs,6206
|
56
56
|
copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
|
57
57
|
copyparty/web/baguettebox.js.gz,sha256=YIaxFDsubJfGIdzzxA-cL6GwJVmpWZyaPhW9hHcOIIw,7964
|
58
|
-
copyparty/web/browser.css.gz,sha256=
|
58
|
+
copyparty/web/browser.css.gz,sha256=N5T5U-iWzls21E2SYkQvDUaaZf11gjj3KwUP0lm1mMA,11672
|
59
59
|
copyparty/web/browser.html,sha256=ISpfvWEawufJCYZIqvuXiyUgiXgjmOTtScz4zrEaypI,4870
|
60
|
-
copyparty/web/browser.js.gz,sha256=
|
60
|
+
copyparty/web/browser.js.gz,sha256=uGALYaMsyyXuCSKbvdMZpB-YrIvCIV3JWo611xRlHd8,88488
|
61
61
|
copyparty/web/browser2.html,sha256=NRUZ08GH-e2YcGXcoz0UjYg6JIVF42u4IMX4HHwWTmg,1587
|
62
62
|
copyparty/web/cf.html,sha256=lJThtNFNAQT1ClCHHlivAkDGE0LutedwopXD62Z8Nys,589
|
63
63
|
copyparty/web/dbg-audio.js.gz,sha256=Ma-KZtK8LnmiwNvNKFKXMPYl_Nn_3U7GsJ6-DRWC2HE,688
|
@@ -73,19 +73,19 @@ copyparty/web/msg.css.gz,sha256=u90fXYAVrMD-jqwf5XFVC1ptSpSHZUe8Mez6PX101P8,300
|
|
73
73
|
copyparty/web/msg.html,sha256=w9CM3hkLLGJX9fWEaG4gSbTOPe2GcPqW8BpSCDiFzOI,977
|
74
74
|
copyparty/web/shares.css.gz,sha256=T2fSezuluDVIiNIERAuUREByhHFlIwwNyx7EBOAVVyQ,499
|
75
75
|
copyparty/web/shares.html,sha256=ZNHtLBM-Y4BX2qa9AGTrZzZp_IP5PLM3QvFMYKolFfM,2494
|
76
|
-
copyparty/web/shares.js.gz,sha256=
|
77
|
-
copyparty/web/splash.css.gz,sha256=
|
78
|
-
copyparty/web/splash.html,sha256=
|
79
|
-
copyparty/web/splash.js.gz,sha256=
|
76
|
+
copyparty/web/shares.js.gz,sha256=_8_1MkmERDcrPeLFpNGzJA4vticRzNRehGKeDV24fNs,926
|
77
|
+
copyparty/web/splash.css.gz,sha256=zgF2kvrp7z8LlhkaXNvFkP3RLlA4dHFZCkwQpG5RcYI,1081
|
78
|
+
copyparty/web/splash.html,sha256=wc8El8_5BR3EMuVik8WYAkkEQ4S6-VepR1B1F8qAYgI,6190
|
79
|
+
copyparty/web/splash.js.gz,sha256=EEfsi9YGtPTYRB6MPX8Dfg4YyfqncI9ldJS7_MGVOhs,2710
|
80
80
|
copyparty/web/svcs.html,sha256=P5YZimYLeQMT0uz6u3clQSNZRc5Zs0Ok-ffcbcGSYuc,11762
|
81
81
|
copyparty/web/svcs.js.gz,sha256=k81ZvZ3I-f4fMHKrNGGOgOlvXnCBz0mVjD-8mieoWCA,520
|
82
|
-
copyparty/web/ui.css.gz,sha256=
|
82
|
+
copyparty/web/ui.css.gz,sha256=DCWgsJLb4exJ3_tUPHRcI0PuLLNlJJ1krF3WiSN9I7w,2785
|
83
83
|
copyparty/web/up2k.js.gz,sha256=lGR1Xb0RkIZ1eHmncsSwWRuFc6FC2rZalvjo3oNTV1s,23291
|
84
|
-
copyparty/web/util.js.gz,sha256=
|
84
|
+
copyparty/web/util.js.gz,sha256=AMr49EVNOJiJjgSJyYyXKf_tHFLk3ODkCPQu26zbMZI,14815
|
85
85
|
copyparty/web/w.hash.js.gz,sha256=l3GpSJD6mcU-1CRWkIj7PybgbjlfSr8oeO3vortIrQk,1105
|
86
86
|
copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
87
|
-
copyparty/web/a/partyfuse.py,sha256=
|
88
|
-
copyparty/web/a/u2c.py,sha256=
|
87
|
+
copyparty/web/a/partyfuse.py,sha256=9p5Hpg_IBiSimv7j9kmPhCGpy-FLXSRUOYnLjJ5JifU,28049
|
88
|
+
copyparty/web/a/u2c.py,sha256=4_YvRoWEAYrUVQHRts-1rPdWLBd6axfzG0fF5mc2Uj8,50196
|
89
89
|
copyparty/web/a/webdav-cfg.bat,sha256=Y4NoGZlksAIg4cBMb7KdJrpKC6Nx97onaTl6yMjaimk,1449
|
90
90
|
copyparty/web/dd/2.png,sha256=gJ14XFPzaw95L6z92fSq9eMPikSQyu-03P1lgiGe0_I,258
|
91
91
|
copyparty/web/dd/3.png,sha256=4lho8Koz5tV7jJ4ODo6GMTScZfkqsT05yp48EDFIlyg,252
|
@@ -106,9 +106,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
|
|
106
106
|
copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
|
107
107
|
copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
|
108
108
|
copyparty/web/deps/sha512.hw.js.gz,sha256=vqoXeracj-99Z5MfY3jK2N4WiSzYQdfjy0RnUlQDhSU,8110
|
109
|
-
copyparty-1.
|
110
|
-
copyparty-1.
|
111
|
-
copyparty-1.
|
112
|
-
copyparty-1.
|
113
|
-
copyparty-1.
|
114
|
-
copyparty-1.
|
109
|
+
copyparty-1.16.0.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
|
110
|
+
copyparty-1.16.0.dist-info/METADATA,sha256=tLqMYoMnPCLqhLEvCe8twQHQoRnXfIGwu8neJ1MucdQ,140282
|
111
|
+
copyparty-1.16.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
112
|
+
copyparty-1.16.0.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
|
113
|
+
copyparty-1.16.0.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
|
114
|
+
copyparty-1.16.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|