copyparty 1.15.5__py3-none-any.whl → 1.15.7__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/__main__.py +7 -4
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +1 -1
- copyparty/cfg.py +3 -1
- copyparty/ftpd.py +4 -0
- copyparty/httpcli.py +77 -26
- copyparty/httpconn.py +2 -0
- copyparty/httpsrv.py +6 -0
- copyparty/mtag.py +1 -1
- copyparty/ssdp.py +1 -1
- copyparty/svchub.py +6 -0
- copyparty/tcpsrv.py +1 -1
- copyparty/up2k.py +76 -35
- copyparty/util.py +35 -4
- copyparty/web/a/u2c.py +30 -12
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/METADATA +78 -23
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/RECORD +23 -23
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/LICENSE +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/WHEEL +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/top_level.txt +0 -0
copyparty/up2k.py
CHANGED
@@ -353,17 +353,18 @@ class Up2k(object):
|
|
353
353
|
return '[{"timeout":1}]'
|
354
354
|
|
355
355
|
ret = []
|
356
|
+
userset = set([(uname or "\n"), "*"])
|
356
357
|
try:
|
357
358
|
for ptop, tab2 in self.registry.items():
|
358
359
|
cfg = self.flags.get(ptop, {}).get("u2abort", 1)
|
359
360
|
if not cfg:
|
360
361
|
continue
|
361
362
|
addr = (ip or "\n") if cfg in (1, 2) else ""
|
362
|
-
user =
|
363
|
+
user = userset if cfg in (1, 3) else None
|
363
364
|
for job in tab2.values():
|
364
365
|
if (
|
365
366
|
"done" in job
|
366
|
-
or (user and
|
367
|
+
or (user and job["user"] not in user)
|
367
368
|
or (addr and addr != job["addr"])
|
368
369
|
):
|
369
370
|
continue
|
@@ -1008,6 +1009,7 @@ class Up2k(object):
|
|
1008
1009
|
vpath = k
|
1009
1010
|
|
1010
1011
|
_, flags = self._expr_idx_filter(flags)
|
1012
|
+
n4g = bool(flags.get("noforget"))
|
1011
1013
|
|
1012
1014
|
ft = "\033[0;32m{}{:.0}"
|
1013
1015
|
ff = "\033[0;35m{}{:.0}"
|
@@ -1061,20 +1063,39 @@ class Up2k(object):
|
|
1061
1063
|
except:
|
1062
1064
|
pass
|
1063
1065
|
|
1066
|
+
if reg2 and "dwrk" not in reg2[next(iter(reg2))]:
|
1067
|
+
for job in reg2.values():
|
1068
|
+
job["dwrk"] = job["wark"]
|
1069
|
+
|
1070
|
+
rm = []
|
1064
1071
|
for k, job in reg2.items():
|
1065
|
-
|
1072
|
+
job["ptop"] = ptop
|
1073
|
+
if "done" in job:
|
1074
|
+
job["need"] = job["hash"] = emptylist
|
1075
|
+
else:
|
1076
|
+
if "need" not in job:
|
1077
|
+
job["need"] = []
|
1078
|
+
if "hash" not in job:
|
1079
|
+
job["hash"] = []
|
1080
|
+
|
1081
|
+
fp = djoin(ptop, job["prel"], job["name"])
|
1066
1082
|
if bos.path.exists(fp):
|
1067
1083
|
reg[k] = job
|
1068
1084
|
if "done" in job:
|
1069
|
-
job["need"] = job["hash"] = emptylist
|
1070
1085
|
continue
|
1071
1086
|
job["poke"] = time.time()
|
1072
1087
|
job["busy"] = {}
|
1073
1088
|
else:
|
1074
1089
|
self.log("ign deleted file in snap: [{}]".format(fp))
|
1090
|
+
if not n4g:
|
1091
|
+
rm.append(k)
|
1092
|
+
continue
|
1093
|
+
|
1094
|
+
for x in rm:
|
1095
|
+
del reg2[x]
|
1075
1096
|
|
1076
1097
|
if drp is None:
|
1077
|
-
drp = [k for k, v in reg.items() if not v
|
1098
|
+
drp = [k for k, v in reg.items() if not v["need"]]
|
1078
1099
|
else:
|
1079
1100
|
drp = [x for x in drp if x in reg]
|
1080
1101
|
|
@@ -1536,7 +1557,7 @@ class Up2k(object):
|
|
1536
1557
|
at = 0
|
1537
1558
|
|
1538
1559
|
# skip upload hooks by not providing vflags
|
1539
|
-
self.db_add(db.c, {}, rd, fn, lmod, sz, "", "", wark, "", "", ip, at)
|
1560
|
+
self.db_add(db.c, {}, rd, fn, lmod, sz, "", "", wark, wark, "", "", ip, at)
|
1540
1561
|
db.n += 1
|
1541
1562
|
tfa += 1
|
1542
1563
|
td = time.time() - db.t
|
@@ -2764,9 +2785,10 @@ class Up2k(object):
|
|
2764
2785
|
|
2765
2786
|
cj["name"] = sanitize_fn(cj["name"], "")
|
2766
2787
|
cj["poke"] = now = self.db_act = self.vol_act[ptop] = time.time()
|
2767
|
-
wark = self._get_wark(cj)
|
2788
|
+
wark = dwark = self._get_wark(cj)
|
2768
2789
|
job = None
|
2769
2790
|
pdir = djoin(ptop, cj["prel"])
|
2791
|
+
inc_ap = djoin(pdir, cj["name"])
|
2770
2792
|
try:
|
2771
2793
|
dev = bos.stat(pdir).st_dev
|
2772
2794
|
except:
|
@@ -2781,6 +2803,7 @@ class Up2k(object):
|
|
2781
2803
|
reg = self.registry[ptop]
|
2782
2804
|
vfs = self.asrv.vfs.all_vols[cj["vtop"]]
|
2783
2805
|
n4g = bool(vfs.flags.get("noforget"))
|
2806
|
+
noclone = bool(vfs.flags.get("noclone"))
|
2784
2807
|
rand = vfs.flags.get("rand") or cj.get("rand")
|
2785
2808
|
lost = []
|
2786
2809
|
|
@@ -2790,6 +2813,12 @@ class Up2k(object):
|
|
2790
2813
|
vols = [(ptop, jcur)] if jcur else []
|
2791
2814
|
if vfs.flags.get("xlink"):
|
2792
2815
|
vols += [(k, v) for k, v in self.cur.items() if k != ptop]
|
2816
|
+
|
2817
|
+
if noclone:
|
2818
|
+
wark = up2k_wark_from_metadata(
|
2819
|
+
self.salt, cj["size"], cj["lmod"], cj["prel"], cj["name"]
|
2820
|
+
)
|
2821
|
+
|
2793
2822
|
if vfs.flags.get("up_ts", "") == "fu" or not cj["lmod"]:
|
2794
2823
|
# force upload time rather than last-modified
|
2795
2824
|
cj["lmod"] = int(time.time())
|
@@ -2802,10 +2831,10 @@ class Up2k(object):
|
|
2802
2831
|
|
2803
2832
|
if self.no_expr_idx:
|
2804
2833
|
q = r"select * from up where w = ?"
|
2805
|
-
argv = [
|
2834
|
+
argv = [dwark]
|
2806
2835
|
else:
|
2807
2836
|
q = r"select * from up where substr(w,1,16)=? and +w=?"
|
2808
|
-
argv = [
|
2837
|
+
argv = [dwark[:16], dwark]
|
2809
2838
|
|
2810
2839
|
c2 = cur.execute(q, tuple(argv))
|
2811
2840
|
for _, dtime, dsize, dp_dir, dp_fn, ip, at in c2:
|
@@ -2813,6 +2842,9 @@ class Up2k(object):
|
|
2813
2842
|
dp_dir, dp_fn = s3dec(dp_dir, dp_fn)
|
2814
2843
|
|
2815
2844
|
dp_abs = djoin(ptop, dp_dir, dp_fn)
|
2845
|
+
if noclone and dp_abs != inc_ap:
|
2846
|
+
continue
|
2847
|
+
|
2816
2848
|
try:
|
2817
2849
|
st = bos.stat(dp_abs)
|
2818
2850
|
if stat.S_ISLNK(st.st_mode):
|
@@ -2821,7 +2853,7 @@ class Up2k(object):
|
|
2821
2853
|
if st.st_size != dsize:
|
2822
2854
|
t = "candidate ignored (db/fs desync): {}, size fs={} db={}, mtime fs={} db={}, file: {}"
|
2823
2855
|
t = t.format(
|
2824
|
-
|
2856
|
+
dwark, st.st_size, dsize, st.st_mtime, dtime, dp_abs
|
2825
2857
|
)
|
2826
2858
|
self.log(t)
|
2827
2859
|
raise Exception()
|
@@ -2868,7 +2900,6 @@ class Up2k(object):
|
|
2868
2900
|
alts.append((score, -len(alts), j, cur, dp_dir, dp_fn))
|
2869
2901
|
|
2870
2902
|
job = None
|
2871
|
-
inc_ap = djoin(cj["ptop"], cj["prel"], cj["name"])
|
2872
2903
|
for dupe in sorted(alts, reverse=True):
|
2873
2904
|
rj = dupe[2]
|
2874
2905
|
orig_ap = djoin(rj["ptop"], rj["prel"], rj["name"])
|
@@ -2878,11 +2909,11 @@ class Up2k(object):
|
|
2878
2909
|
break
|
2879
2910
|
else:
|
2880
2911
|
self.log("asserting contents of %s" % (orig_ap,))
|
2881
|
-
|
2882
|
-
|
2883
|
-
if
|
2912
|
+
hashes2, st = self._hashlist_from_file(orig_ap)
|
2913
|
+
wark2 = up2k_wark_from_hashlist(self.salt, st.st_size, hashes2)
|
2914
|
+
if dwark != wark2:
|
2884
2915
|
t = "will not dedup (fs index desync): fs=%s, db=%s, file: %s"
|
2885
|
-
self.log(t % (
|
2916
|
+
self.log(t % (wark2, dwark, orig_ap))
|
2886
2917
|
lost.append(dupe[3:])
|
2887
2918
|
continue
|
2888
2919
|
data_ok = True
|
@@ -2946,11 +2977,11 @@ class Up2k(object):
|
|
2946
2977
|
|
2947
2978
|
elif inc_ap != orig_ap and not data_ok and "done" in reg[wark]:
|
2948
2979
|
self.log("asserting contents of %s" % (orig_ap,))
|
2949
|
-
|
2950
|
-
|
2951
|
-
if wark !=
|
2980
|
+
hashes2, _ = self._hashlist_from_file(orig_ap)
|
2981
|
+
wark2 = up2k_wark_from_hashlist(self.salt, st.st_size, hashes2)
|
2982
|
+
if wark != wark2:
|
2952
2983
|
t = "will not dedup (fs index desync): fs=%s, idx=%s, file: %s"
|
2953
|
-
self.log(t % (
|
2984
|
+
self.log(t % (wark2, wark, orig_ap))
|
2954
2985
|
del reg[wark]
|
2955
2986
|
|
2956
2987
|
if job or wark in reg:
|
@@ -3007,6 +3038,7 @@ class Up2k(object):
|
|
3007
3038
|
|
3008
3039
|
job = deepcopy(job)
|
3009
3040
|
job["wark"] = wark
|
3041
|
+
job["dwrk"] = dwark
|
3010
3042
|
job["at"] = cj.get("at") or now
|
3011
3043
|
zs = "vtop ptop prel name lmod host user addr poke"
|
3012
3044
|
for k in zs.split():
|
@@ -3077,7 +3109,7 @@ class Up2k(object):
|
|
3077
3109
|
raise
|
3078
3110
|
|
3079
3111
|
if cur and not self.args.nw:
|
3080
|
-
zs = "prel name lmod size ptop vtop wark host user addr at"
|
3112
|
+
zs = "prel name lmod size ptop vtop wark dwrk host user addr at"
|
3081
3113
|
a = [job[x] for x in zs.split()]
|
3082
3114
|
self.db_add(cur, vfs.flags, *a)
|
3083
3115
|
cur.connection.commit()
|
@@ -3107,6 +3139,7 @@ class Up2k(object):
|
|
3107
3139
|
|
3108
3140
|
job = {
|
3109
3141
|
"wark": wark,
|
3142
|
+
"dwrk": dwark,
|
3110
3143
|
"t0": now,
|
3111
3144
|
"sprs": sprs,
|
3112
3145
|
"hash": deepcopy(cj["hash"]),
|
@@ -3149,6 +3182,7 @@ class Up2k(object):
|
|
3149
3182
|
"lmod": job["lmod"],
|
3150
3183
|
"sprs": job.get("sprs", sprs),
|
3151
3184
|
"hash": job["need"],
|
3185
|
+
"dwrk": dwark,
|
3152
3186
|
"wark": wark,
|
3153
3187
|
}
|
3154
3188
|
|
@@ -3175,7 +3209,7 @@ class Up2k(object):
|
|
3175
3209
|
):
|
3176
3210
|
sql = "update up set mt=? where substr(w,1,16)=? and +rd=? and +fn=?"
|
3177
3211
|
try:
|
3178
|
-
cur.execute(sql, (cj["lmod"],
|
3212
|
+
cur.execute(sql, (cj["lmod"], dwark[:16], job["prel"], job["name"]))
|
3179
3213
|
cur.connection.commit()
|
3180
3214
|
|
3181
3215
|
ap = djoin(job["ptop"], job["prel"], job["name"])
|
@@ -3416,19 +3450,19 @@ class Up2k(object):
|
|
3416
3450
|
self.mutex.release()
|
3417
3451
|
return -1, ""
|
3418
3452
|
try:
|
3419
|
-
return self._confirm_chunks(ptop, wark, chashes)
|
3453
|
+
return self._confirm_chunks(ptop, wark, chashes, chashes)
|
3420
3454
|
finally:
|
3421
3455
|
self.reg_mutex.release()
|
3422
3456
|
self.mutex.release()
|
3423
3457
|
|
3424
3458
|
def confirm_chunks(
|
3425
|
-
self, ptop , wark ,
|
3459
|
+
self, ptop , wark , written , locked
|
3426
3460
|
) :
|
3427
3461
|
with self.mutex, self.reg_mutex:
|
3428
|
-
return self._confirm_chunks(ptop, wark,
|
3462
|
+
return self._confirm_chunks(ptop, wark, written, locked)
|
3429
3463
|
|
3430
3464
|
def _confirm_chunks(
|
3431
|
-
self, ptop , wark ,
|
3465
|
+
self, ptop , wark , written , locked
|
3432
3466
|
) :
|
3433
3467
|
if True:
|
3434
3468
|
self.db_act = self.vol_act[ptop] = time.time()
|
@@ -3440,11 +3474,11 @@ class Up2k(object):
|
|
3440
3474
|
except Exception as ex:
|
3441
3475
|
return -2, "confirm_chunk, wark(%r)" % (ex,) # type: ignore
|
3442
3476
|
|
3443
|
-
for chash in
|
3477
|
+
for chash in locked:
|
3444
3478
|
job["busy"].pop(chash, None)
|
3445
3479
|
|
3446
3480
|
try:
|
3447
|
-
for chash in
|
3481
|
+
for chash in written:
|
3448
3482
|
job["need"].remove(chash)
|
3449
3483
|
except Exception as ex:
|
3450
3484
|
return -2, "confirm_chunk, chash(%s) %r" % (chash, ex) # type: ignore
|
@@ -3496,7 +3530,7 @@ class Up2k(object):
|
|
3496
3530
|
except:
|
3497
3531
|
self.log("failed to utime ({}, {})".format(dst, times))
|
3498
3532
|
|
3499
|
-
zs = "prel name lmod size ptop vtop wark host user addr"
|
3533
|
+
zs = "prel name lmod size ptop vtop wark dwrk host user addr"
|
3500
3534
|
z2 = [job[x] for x in zs.split()]
|
3501
3535
|
wake_sr = False
|
3502
3536
|
try:
|
@@ -3569,6 +3603,7 @@ class Up2k(object):
|
|
3569
3603
|
ptop ,
|
3570
3604
|
vtop ,
|
3571
3605
|
wark ,
|
3606
|
+
dwark ,
|
3572
3607
|
host ,
|
3573
3608
|
usr ,
|
3574
3609
|
ip ,
|
@@ -3591,6 +3626,7 @@ class Up2k(object):
|
|
3591
3626
|
ptop,
|
3592
3627
|
vtop,
|
3593
3628
|
wark,
|
3629
|
+
dwark,
|
3594
3630
|
host,
|
3595
3631
|
usr,
|
3596
3632
|
ip,
|
@@ -3604,7 +3640,7 @@ class Up2k(object):
|
|
3604
3640
|
raise
|
3605
3641
|
|
3606
3642
|
if "e2t" in self.flags[ptop]:
|
3607
|
-
self.tagq.put((ptop,
|
3643
|
+
self.tagq.put((ptop, dwark, rd, fn, sz, ip, at))
|
3608
3644
|
self.n_tagq += 1
|
3609
3645
|
|
3610
3646
|
return True
|
@@ -3631,6 +3667,7 @@ class Up2k(object):
|
|
3631
3667
|
ptop ,
|
3632
3668
|
vtop ,
|
3633
3669
|
wark ,
|
3670
|
+
dwark ,
|
3634
3671
|
host ,
|
3635
3672
|
usr ,
|
3636
3673
|
ip ,
|
@@ -3647,12 +3684,12 @@ class Up2k(object):
|
|
3647
3684
|
db_ip = "1.1.1.1" if self.args.no_db_ip else ip
|
3648
3685
|
|
3649
3686
|
sql = "insert into up values (?,?,?,?,?,?,?)"
|
3650
|
-
v = (
|
3687
|
+
v = (dwark, int(ts), sz, rd, fn, db_ip, int(at or 0))
|
3651
3688
|
try:
|
3652
3689
|
db.execute(sql, v)
|
3653
3690
|
except:
|
3654
3691
|
rd, fn = s3enc(self.mem_cur, rd, fn)
|
3655
|
-
v = (
|
3692
|
+
v = (dwark, int(ts), sz, rd, fn, db_ip, int(at or 0))
|
3656
3693
|
db.execute(sql, v)
|
3657
3694
|
|
3658
3695
|
self.volsize[db] += sz
|
@@ -3696,10 +3733,10 @@ class Up2k(object):
|
|
3696
3733
|
for cd in cds:
|
3697
3734
|
# one for each unique cooldown duration
|
3698
3735
|
try:
|
3699
|
-
db.execute(q, (cd,
|
3736
|
+
db.execute(q, (cd, dwark[:16], rd, fn))
|
3700
3737
|
except:
|
3701
3738
|
rd, fn = s3enc(self.mem_cur, rd, fn)
|
3702
|
-
db.execute(q, (cd,
|
3739
|
+
db.execute(q, (cd, dwark[:16], rd, fn))
|
3703
3740
|
|
3704
3741
|
if self.xiu_asleep:
|
3705
3742
|
self.xiu_asleep = False
|
@@ -3791,10 +3828,12 @@ class Up2k(object):
|
|
3791
3828
|
with self.mutex, self.reg_mutex:
|
3792
3829
|
abrt_cfg = self.flags.get(ptop, {}).get("u2abort", 1)
|
3793
3830
|
addr = (ip or "\n") if abrt_cfg in (1, 2) else ""
|
3794
|
-
user = (uname or "\n") if abrt_cfg in (1, 3) else
|
3831
|
+
user = ((uname or "\n"), "*") if abrt_cfg in (1, 3) else None
|
3795
3832
|
reg = self.registry.get(ptop, {}) if abrt_cfg else {}
|
3796
3833
|
for wark, job in reg.items():
|
3797
|
-
if (
|
3834
|
+
if (addr and addr != job["addr"]) or (
|
3835
|
+
user and job["user"] not in user
|
3836
|
+
):
|
3798
3837
|
continue
|
3799
3838
|
jrem = djoin(job["prel"], job["name"])
|
3800
3839
|
if ANYWIN:
|
@@ -4153,6 +4192,7 @@ class Up2k(object):
|
|
4153
4192
|
dvn.realpath,
|
4154
4193
|
dvn.vpath,
|
4155
4194
|
w,
|
4195
|
+
w,
|
4156
4196
|
"",
|
4157
4197
|
"",
|
4158
4198
|
ip or "",
|
@@ -4834,6 +4874,7 @@ class Up2k(object):
|
|
4834
4874
|
ptop,
|
4835
4875
|
vtop,
|
4836
4876
|
wark,
|
4877
|
+
wark,
|
4837
4878
|
"",
|
4838
4879
|
usr,
|
4839
4880
|
ip,
|
copyparty/util.py
CHANGED
@@ -643,11 +643,15 @@ class HLog(logging.Handler):
|
|
643
643
|
|
644
644
|
|
645
645
|
class NetMap(object):
|
646
|
-
def __init__(
|
646
|
+
def __init__(
|
647
|
+
self, ips , cidrs , keep_lo=False, strict_cidr=False
|
648
|
+
) :
|
647
649
|
"""
|
648
650
|
ips: list of plain ipv4/ipv6 IPs, not cidr
|
649
651
|
cidrs: list of cidr-notation IPs (ip/prefix)
|
650
652
|
"""
|
653
|
+
self.mutex = threading.Lock()
|
654
|
+
|
651
655
|
if "::" in ips:
|
652
656
|
ips = [x for x in ips if x != "::"] + list(
|
653
657
|
[x.split("/")[0] for x in cidrs if ":" in x]
|
@@ -674,7 +678,7 @@ class NetMap(object):
|
|
674
678
|
bip = socket.inet_pton(fam, ip.split("/")[0])
|
675
679
|
self.bip.append(bip)
|
676
680
|
self.b2sip[bip] = ip.split("/")[0]
|
677
|
-
self.b2net[bip] = (IPv6Network if v6 else IPv4Network)(ip,
|
681
|
+
self.b2net[bip] = (IPv6Network if v6 else IPv4Network)(ip, strict_cidr)
|
678
682
|
|
679
683
|
self.bip.sort(reverse=True)
|
680
684
|
|
@@ -685,8 +689,10 @@ class NetMap(object):
|
|
685
689
|
try:
|
686
690
|
return self.cache[ip]
|
687
691
|
except:
|
688
|
-
|
692
|
+
with self.mutex:
|
693
|
+
return self._map(ip)
|
689
694
|
|
695
|
+
def _map(self, ip ) :
|
690
696
|
v6 = ":" in ip
|
691
697
|
ci = IPv6Address(ip) if v6 else IPv4Address(ip)
|
692
698
|
bip = next((x for x in self.bip if ci in self.b2net[x]), None)
|
@@ -1082,7 +1088,7 @@ class Magician(object):
|
|
1082
1088
|
return ret
|
1083
1089
|
|
1084
1090
|
mime = magic.from_file(fpath, mime=True)
|
1085
|
-
mime = re.split("[; ]", mime, 1)[0]
|
1091
|
+
mime = re.split("[; ]", mime, maxsplit=1)[0]
|
1086
1092
|
try:
|
1087
1093
|
return EXTS[mime]
|
1088
1094
|
except:
|
@@ -2592,6 +2598,31 @@ def build_netmap(csv ):
|
|
2592
2598
|
return NetMap(ips, cidrs, True)
|
2593
2599
|
|
2594
2600
|
|
2601
|
+
def load_ipu(log , ipus ) :
|
2602
|
+
ip_u = {"": "*"}
|
2603
|
+
cidr_u = {}
|
2604
|
+
for ipu in ipus:
|
2605
|
+
try:
|
2606
|
+
cidr, uname = ipu.split("=")
|
2607
|
+
cip, csz = cidr.split("/")
|
2608
|
+
except:
|
2609
|
+
t = "\n invalid value %r for argument --ipu; must be CIDR=UNAME (192.168.0.0/16=amelia)"
|
2610
|
+
raise Exception(t % (ipu,))
|
2611
|
+
uname2 = cidr_u.get(cidr)
|
2612
|
+
if uname2 is not None:
|
2613
|
+
t = "\n invalid value %r for argument --ipu; cidr %s already mapped to %r"
|
2614
|
+
raise Exception(t % (ipu, cidr, uname2))
|
2615
|
+
cidr_u[cidr] = uname
|
2616
|
+
ip_u[cip] = uname
|
2617
|
+
try:
|
2618
|
+
nm = NetMap(["::"], list(cidr_u.keys()), True, True)
|
2619
|
+
except Exception as ex:
|
2620
|
+
t = "failed to translate --ipu into netmap, probably due to invalid config: %r"
|
2621
|
+
log("root", t % (ex,), 1)
|
2622
|
+
raise
|
2623
|
+
return ip_u, nm
|
2624
|
+
|
2625
|
+
|
2595
2626
|
def yieldfile(fn , bufsz ) :
|
2596
2627
|
readsz = min(bufsz, 128 * 1024)
|
2597
2628
|
with open(fsenc(fn), "rb", bufsz) as f:
|
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-
|
4
|
+
S_VERSION = "2.2"
|
5
|
+
S_BUILD_DT = "2024-10-13"
|
6
6
|
|
7
7
|
"""
|
8
8
|
u2c.py: upload to copyparty
|
@@ -728,6 +728,7 @@ def handshake(ar, file, search):
|
|
728
728
|
while True:
|
729
729
|
sc = 600
|
730
730
|
txt = ""
|
731
|
+
t0 = time.time()
|
731
732
|
try:
|
732
733
|
zs = json.dumps(req, separators=(",\n", ": "))
|
733
734
|
sc, txt = web.req("POST", url, {}, zs.encode("utf-8"), MJ)
|
@@ -752,7 +753,9 @@ def handshake(ar, file, search):
|
|
752
753
|
print("\nERROR: login required, or wrong password:\n%s" % (txt,))
|
753
754
|
raise BadAuth()
|
754
755
|
|
755
|
-
|
756
|
+
t = "handshake failed, retrying: %s\n t0=%.3f t1=%.3f td=%.3f\n %s\n\n"
|
757
|
+
now = time.time()
|
758
|
+
eprint(t % (file.name, t0, now, now - t0, em))
|
756
759
|
time.sleep(ar.cd)
|
757
760
|
|
758
761
|
try:
|
@@ -869,8 +872,8 @@ class Ctl(object):
|
|
869
872
|
self.hash_b = 0
|
870
873
|
self.up_f = 0
|
871
874
|
self.up_c = 0
|
872
|
-
self.up_b = 0
|
873
|
-
self.up_br = 0
|
875
|
+
self.up_b = 0 # num bytes handled
|
876
|
+
self.up_br = 0 # num bytes actually transferred
|
874
877
|
self.uploader_busy = 0
|
875
878
|
self.serialized = False
|
876
879
|
|
@@ -1013,11 +1016,14 @@ class Ctl(object):
|
|
1013
1016
|
t = "%s eta @ %s/s, %s, %d# left\033[K" % (self.eta, spd, sleft, nleft)
|
1014
1017
|
eprint(txt + "\033]0;{0}\033\\\r{0}{1}".format(t, tail))
|
1015
1018
|
|
1019
|
+
if self.ar.wlist:
|
1020
|
+
self.at_hash = time.time() - self.t0
|
1021
|
+
|
1016
1022
|
if self.hash_b and self.at_hash:
|
1017
1023
|
spd = humansize(self.hash_b / self.at_hash)
|
1018
1024
|
eprint("\nhasher: %.2f sec, %s/s\n" % (self.at_hash, spd))
|
1019
|
-
if self.
|
1020
|
-
spd = humansize(self.
|
1025
|
+
if self.up_br and self.at_up:
|
1026
|
+
spd = humansize(self.up_br / self.at_up)
|
1021
1027
|
eprint("upload: %.2f sec, %s/s\n" % (self.at_up, spd))
|
1022
1028
|
|
1023
1029
|
if not self.recheck:
|
@@ -1136,10 +1142,16 @@ class Ctl(object):
|
|
1136
1142
|
self.up_b = self.hash_b
|
1137
1143
|
|
1138
1144
|
if self.ar.wlist:
|
1145
|
+
vp = file.rel.decode("utf-8")
|
1146
|
+
if self.ar.chs:
|
1147
|
+
zsl = [
|
1148
|
+
"%s %d %d" % (zsii[0], n, zsii[1])
|
1149
|
+
for n, zsii in enumerate(file.cids)
|
1150
|
+
]
|
1151
|
+
print("chs: %s\n%s" % (vp, "\n".join(zsl)))
|
1139
1152
|
zsl = [self.ar.wsalt, str(file.size)] + [x[0] for x in file.kchunks]
|
1140
1153
|
zb = hashlib.sha512("\n".join(zsl).encode("utf-8")).digest()[:33]
|
1141
1154
|
wark = ub64enc(zb).decode("utf-8")
|
1142
|
-
vp = file.rel.decode("utf-8")
|
1143
1155
|
if self.ar.jw:
|
1144
1156
|
print("%s %s" % (wark, vp))
|
1145
1157
|
else:
|
@@ -1177,6 +1189,7 @@ class Ctl(object):
|
|
1177
1189
|
self.q_upload.put(None)
|
1178
1190
|
return
|
1179
1191
|
|
1192
|
+
chunksz = up2k_chunksize(file.size)
|
1180
1193
|
upath = file.abs.decode("utf-8", "replace")
|
1181
1194
|
if not VT100:
|
1182
1195
|
upath = upath.lstrip("\\?")
|
@@ -1236,9 +1249,14 @@ class Ctl(object):
|
|
1236
1249
|
file.up_c -= len(hs)
|
1237
1250
|
for cid in hs:
|
1238
1251
|
sz = file.kchunks[cid][1]
|
1252
|
+
self.up_br -= sz
|
1239
1253
|
self.up_b -= sz
|
1240
1254
|
file.up_b -= sz
|
1241
1255
|
|
1256
|
+
if hs and not file.up_b:
|
1257
|
+
# first hs of this file; is this an upload resume?
|
1258
|
+
file.up_b = chunksz * max(0, len(file.kchunks) - len(hs))
|
1259
|
+
|
1242
1260
|
file.ucids = hs
|
1243
1261
|
|
1244
1262
|
if not hs:
|
@@ -1252,7 +1270,7 @@ class Ctl(object):
|
|
1252
1270
|
c1 = c2 = ""
|
1253
1271
|
|
1254
1272
|
spd_h = humansize(file.size / file.t_hash, True)
|
1255
|
-
if file.
|
1273
|
+
if file.up_c:
|
1256
1274
|
t_up = file.t1_up - file.t0_up
|
1257
1275
|
spd_u = humansize(file.size / t_up, True)
|
1258
1276
|
|
@@ -1262,13 +1280,12 @@ class Ctl(object):
|
|
1262
1280
|
t = " found %s %s(%.2fs,%s/s)%s"
|
1263
1281
|
print(t % (upath, c1, file.t_hash, spd_h, c2))
|
1264
1282
|
else:
|
1265
|
-
kw = "uploaded" if file.
|
1283
|
+
kw = "uploaded" if file.up_c else " found"
|
1266
1284
|
print("{0} {1}".format(kw, upath))
|
1267
1285
|
|
1268
1286
|
self._check_if_done()
|
1269
1287
|
continue
|
1270
1288
|
|
1271
|
-
chunksz = up2k_chunksize(file.size)
|
1272
1289
|
njoin = (self.ar.sz * 1024 * 1024) // chunksz
|
1273
1290
|
cs = hs[:]
|
1274
1291
|
while cs:
|
@@ -1365,7 +1382,7 @@ def main():
|
|
1365
1382
|
cores = (os.cpu_count() if hasattr(os, "cpu_count") else 0) or 2
|
1366
1383
|
hcores = min(cores, 3) # 4% faster than 4+ on py3.9 @ r5-4500U
|
1367
1384
|
|
1368
|
-
ver = "{0}
|
1385
|
+
ver = "{0}, v{1}".format(S_BUILD_DT, S_VERSION)
|
1369
1386
|
if "--version" in sys.argv:
|
1370
1387
|
print(ver)
|
1371
1388
|
return
|
@@ -1403,6 +1420,7 @@ source file/folder selection uses rsync syntax, meaning that:
|
|
1403
1420
|
|
1404
1421
|
ap = app.add_argument_group("file-ID calculator; enable with url '-' to list warks (file identifiers) instead of upload/search")
|
1405
1422
|
ap.add_argument("--wsalt", type=unicode, metavar="S", default="hunter2", help="salt to use when creating warks; must match server config")
|
1423
|
+
ap.add_argument("--chs", action="store_true", help="verbose (print the hash/offset of each chunk in each file)")
|
1406
1424
|
ap.add_argument("--jw", action="store_true", help="just identifier+filepath, not mtime/size too")
|
1407
1425
|
|
1408
1426
|
ap = app.add_argument_group("performance tweaks")
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.js.gz
CHANGED
Binary file
|