copyparty 1.16.11__py3-none-any.whl → 1.16.12__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 +2 -1
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +9 -1
- copyparty/cfg.py +3 -0
- copyparty/httpcli.py +27 -7
- copyparty/metrics.py +1 -1
- copyparty/multicast.py +1 -0
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.html +0 -2
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/deps/marked.js.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.16.11.dist-info → copyparty-1.16.12.dist-info}/METADATA +223 -6
- {copyparty-1.16.11.dist-info → copyparty-1.16.12.dist-info}/RECORD +19 -19
- {copyparty-1.16.11.dist-info → copyparty-1.16.12.dist-info}/LICENSE +0 -0
- {copyparty-1.16.11.dist-info → copyparty-1.16.12.dist-info}/WHEEL +0 -0
- {copyparty-1.16.11.dist-info → copyparty-1.16.12.dist-info}/entry_points.txt +0 -0
- {copyparty-1.16.11.dist-info → copyparty-1.16.12.dist-info}/top_level.txt +0 -0
copyparty/__main__.py
CHANGED
@@ -1255,7 +1255,8 @@ def add_optouts(ap):
|
|
1255
1255
|
ap2.add_argument("-nih", action="store_true", help="no info hostname -- don't show in UI")
|
1256
1256
|
ap2.add_argument("-nid", action="store_true", help="no info disk-usage -- don't show in UI")
|
1257
1257
|
ap2.add_argument("-nb", action="store_true", help="no powered-by-copyparty branding in UI")
|
1258
|
-
ap2.add_argument("--
|
1258
|
+
ap2.add_argument("--zip-who", metavar="LVL", type=int, default=3, help="who can download as zip/tar? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=authenticated-with-read-access, [\033[32m3\033[0m]=everyone-with-read-access (volflag=zip_who)\n\033[1;31mWARNING:\033[0m if a nested volume has a more restrictive value than a parent volume, then this will be \033[33mignored\033[0m if the download is initiated from the parent, more lenient volume")
|
1259
|
+
ap2.add_argument("--no-zip", action="store_true", help="disable download as zip/tar; same as \033[33m--zip-who=0\033[0m")
|
1259
1260
|
ap2.add_argument("--no-tarcmp", action="store_true", help="disable download as compressed tar (?tar=gz, ?tar=bz2, ?tar=xz, ?tar=gz:9, ...)")
|
1260
1261
|
ap2.add_argument("--no-lifetime", action="store_true", help="do not allow clients (or server config) to schedule an upload to be deleted after a given time")
|
1261
1262
|
ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -1508,6 +1508,14 @@ class AuthSrv(object):
|
|
1508
1508
|
if not mount and not self.args.idp_h_usr:
|
1509
1509
|
# -h says our defaults are CWD at root and read/write for everyone
|
1510
1510
|
axs = AXS(["*"], ["*"], None, None)
|
1511
|
+
if os.path.exists("/z/initcfg"):
|
1512
|
+
t = "Read-access has been disabled due to failsafe: Docker detected, but the config does not define any volumes. This failsafe is to prevent unintended access if this is due to accidental loss of config. You can override this safeguard and allow read/write to all of /w/ by adding the following arguments to the docker container: -v .::rw"
|
1513
|
+
self.log(t, 1)
|
1514
|
+
axs = AXS()
|
1515
|
+
elif self.args.c:
|
1516
|
+
t = "Read-access has been disabled due to failsafe: No volumes were defined by the config-file. This failsafe is to prevent unintended access if this is due to accidental loss of config. You can override this safeguard and allow read/write to the working-directory by adding the following arguments: -v .::rw"
|
1517
|
+
self.log(t, 1)
|
1518
|
+
axs = AXS()
|
1511
1519
|
vfs = VFS(self.log_func, absreal("."), "", axs, {})
|
1512
1520
|
elif "" not in mount:
|
1513
1521
|
# there's volumes but no root; make root inaccessible
|
@@ -1907,7 +1915,7 @@ class AuthSrv(object):
|
|
1907
1915
|
if k not in vol.flags:
|
1908
1916
|
vol.flags[k] = getattr(self.args, k)
|
1909
1917
|
|
1910
|
-
for k in ("nrand", "u2abort"):
|
1918
|
+
for k in ("nrand", "u2abort", "ups_who", "zip_who"):
|
1911
1919
|
if k in vol.flags:
|
1912
1920
|
vol.flags[k] = int(vol.flags[k])
|
1913
1921
|
|
copyparty/cfg.py
CHANGED
@@ -94,6 +94,7 @@ def vf_vmap() :
|
|
94
94
|
"u2abort",
|
95
95
|
"u2ts",
|
96
96
|
"ups_who",
|
97
|
+
"zip_who",
|
97
98
|
):
|
98
99
|
ret[k] = k
|
99
100
|
return ret
|
@@ -252,6 +253,8 @@ flagcats = {
|
|
252
253
|
"dots": "allow all users with read-access to\nenable the option to show dotfiles in listings",
|
253
254
|
"fk=8": 'generates per-file accesskeys,\nwhich are then required at the "g" permission;\nkeys are invalidated if filesize or inode changes',
|
254
255
|
"fka=8": 'generates slightly weaker per-file accesskeys,\nwhich are then required at the "g" permission;\nnot affected by filesize or inode numbers',
|
256
|
+
"ups_who=2": "restrict viewing the list of recent uploads",
|
257
|
+
"zip_who=2": "restrict access to download-as-zip/tar",
|
255
258
|
"mv_retry": "ms-windows: timeout for renaming busy files",
|
256
259
|
"rm_retry": "ms-windows: timeout for deleting busy files",
|
257
260
|
"davauth": "ask webdav clients to login for all folders",
|
copyparty/httpcli.py
CHANGED
@@ -1228,6 +1228,20 @@ class HttpCli(object):
|
|
1228
1228
|
else:
|
1229
1229
|
return self.tx_404(True)
|
1230
1230
|
else:
|
1231
|
+
vfs = self.asrv.vfs
|
1232
|
+
if (
|
1233
|
+
not vfs.nodes
|
1234
|
+
and not vfs.axs.uread
|
1235
|
+
and not vfs.axs.uwrite
|
1236
|
+
and not vfs.axs.uget
|
1237
|
+
and not vfs.axs.uhtml
|
1238
|
+
and not vfs.axs.uadmin
|
1239
|
+
):
|
1240
|
+
t = "<h2>access denied due to failsafe; check server log</h2>"
|
1241
|
+
html = self.j2s("splash", this=self, msg=t)
|
1242
|
+
self.reply(html.encode("utf-8", "replace"), 500)
|
1243
|
+
return True
|
1244
|
+
|
1231
1245
|
if self.vpath:
|
1232
1246
|
ptn = self.args.nonsus_urls
|
1233
1247
|
if not ptn or not ptn.search(self.vpath):
|
@@ -4263,8 +4277,14 @@ class HttpCli(object):
|
|
4263
4277
|
rem ,
|
4264
4278
|
items ,
|
4265
4279
|
) :
|
4266
|
-
|
4267
|
-
|
4280
|
+
lvl = vn.flags["zip_who"]
|
4281
|
+
if self.args.no_zip or not lvl:
|
4282
|
+
raise Pebkac(400, "download-as-zip/tar is disabled in server config")
|
4283
|
+
elif lvl <= 1 and not self.can_admin:
|
4284
|
+
raise Pebkac(400, "download-as-zip/tar is admin-only on this server")
|
4285
|
+
elif lvl <= 2 and self.uname in ("", "*"):
|
4286
|
+
t = "you must be authenticated to download-as-zip/tar on this server"
|
4287
|
+
raise Pebkac(400, t)
|
4268
4288
|
|
4269
4289
|
logmsg = "{:4} {} ".format("", self.req)
|
4270
4290
|
self.keepalive = False
|
@@ -4804,7 +4824,7 @@ class HttpCli(object):
|
|
4804
4824
|
|
4805
4825
|
def scanvol(self) :
|
4806
4826
|
if not self.can_admin:
|
4807
|
-
raise Pebkac(403, "not allowed for user " + self.uname)
|
4827
|
+
raise Pebkac(403, "'scanvol' not allowed for user " + self.uname)
|
4808
4828
|
|
4809
4829
|
if self.args.no_rescan:
|
4810
4830
|
raise Pebkac(403, "the rescan feature is disabled in server config")
|
@@ -4827,7 +4847,7 @@ class HttpCli(object):
|
|
4827
4847
|
raise Pebkac(400, "only config files ('cfg') can be reloaded rn")
|
4828
4848
|
|
4829
4849
|
if not self.avol:
|
4830
|
-
raise Pebkac(403, "not allowed for user " + self.uname)
|
4850
|
+
raise Pebkac(403, "'reload' not allowed for user " + self.uname)
|
4831
4851
|
|
4832
4852
|
if self.args.no_reload:
|
4833
4853
|
raise Pebkac(403, "the reload feature is disabled in server config")
|
@@ -4837,7 +4857,7 @@ class HttpCli(object):
|
|
4837
4857
|
|
4838
4858
|
def tx_stack(self) :
|
4839
4859
|
if not self.avol and not [x for x in self.wvol if x in self.rvol]:
|
4840
|
-
raise Pebkac(403, "not allowed for user " + self.uname)
|
4860
|
+
raise Pebkac(403, "'stack' not allowed for user " + self.uname)
|
4841
4861
|
|
4842
4862
|
if self.args.no_stack:
|
4843
4863
|
raise Pebkac(403, "the stackdump feature is disabled in server config")
|
@@ -5130,7 +5150,7 @@ class HttpCli(object):
|
|
5130
5150
|
adm = "*" in vol.axs.uadmin or self.uname in vol.axs.uadmin
|
5131
5151
|
dots = "*" in vol.axs.udot or self.uname in vol.axs.udot
|
5132
5152
|
|
5133
|
-
lvl =
|
5153
|
+
lvl = vol.flags["ups_who"]
|
5134
5154
|
if not lvl:
|
5135
5155
|
continue
|
5136
5156
|
elif lvl == 1 and not adm:
|
@@ -5399,7 +5419,7 @@ class HttpCli(object):
|
|
5399
5419
|
|
5400
5420
|
def handle_rm(self, req ) :
|
5401
5421
|
if not req and not self.can_delete:
|
5402
|
-
raise Pebkac(403, "not allowed for user " + self.uname)
|
5422
|
+
raise Pebkac(403, "'delete' not allowed for user " + self.uname)
|
5403
5423
|
|
5404
5424
|
if self.args.no_del:
|
5405
5425
|
raise Pebkac(403, "the delete feature is disabled in server config")
|
copyparty/metrics.py
CHANGED
copyparty/multicast.py
CHANGED
@@ -160,6 +160,7 @@ class MCast(object):
|
|
160
160
|
sck.settimeout(None)
|
161
161
|
sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
162
162
|
try:
|
163
|
+
# safe for this purpose; https://lwn.net/Articles/853637/
|
163
164
|
sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
164
165
|
except:
|
165
166
|
pass
|
copyparty/web/baguettebox.js.gz
CHANGED
Binary file
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.html
CHANGED
copyparty/web/browser.js.gz
CHANGED
Binary file
|
copyparty/web/deps/marked.js.gz
CHANGED
Binary file
|
copyparty/web/util.js.gz
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.16.
|
3
|
+
Version: 1.16.12
|
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
|
@@ -201,6 +201,9 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
|
|
201
201
|
* or if you are on android, [install copyparty in termux](#install-on-android)
|
202
202
|
* or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
|
203
203
|
* or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
|
204
|
+
* or if you don't trust copyparty yet and want to isolate it a little, then...
|
205
|
+
* ...maybe [prisonparty](./bin/prisonparty.sh) to create a tiny [chroot](https://wiki.archlinux.org/title/Chroot) (very portable),
|
206
|
+
* ...or [bubbleparty](./bin/bubbleparty.sh) to wrap it in [bubblewrap](https://github.com/containers/bubblewrap) (much better)
|
204
207
|
* or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
|
205
208
|
* docker has all deps built-in, so skip this step:
|
206
209
|
|
@@ -312,7 +315,7 @@ also see [comparison to similar software](./docs/versus.md)
|
|
312
315
|
* ☑ search by name/path/date/size
|
313
316
|
* ☑ [search by ID3-tags etc.](#searching)
|
314
317
|
* client support
|
315
|
-
* ☑ [folder sync](#folder-sync)
|
318
|
+
* ☑ [folder sync](#folder-sync) (one-way only; full sync will never be supported)
|
316
319
|
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
317
320
|
* ☑ [opengraph](#opengraph) (discord embeds)
|
318
321
|
* markdown
|
@@ -529,6 +532,40 @@ examples:
|
|
529
532
|
|
530
533
|
anyone trying to bruteforce a password gets banned according to `--ban-pw`; default is 24h ban for 9 failed attempts in 1 hour
|
531
534
|
|
535
|
+
and if you want to use config files instead of commandline args (good!) then here's the same examples as a configfile; save it as `foobar.conf` and use it like this: `python copyparty-sfx.py -c foobar.conf`
|
536
|
+
|
537
|
+
```yaml
|
538
|
+
[accounts]
|
539
|
+
u1: p1 # create account "u1" with password "p1"
|
540
|
+
u2: p2 # (note that comments must have
|
541
|
+
u3: p3 # two spaces before the # sign)
|
542
|
+
|
543
|
+
[/] # this URL will be mapped to...
|
544
|
+
/srv # ...this folder on the server filesystem
|
545
|
+
accs:
|
546
|
+
r: * # read-only for everyone, no account necessary
|
547
|
+
|
548
|
+
[/music] # create another volume at this URL,
|
549
|
+
/mnt/music # which is mapped to this folder
|
550
|
+
accs:
|
551
|
+
r: u1, u2 # only these accounts can read,
|
552
|
+
rw: u3 # and only u3 can read-write
|
553
|
+
|
554
|
+
[/inc]
|
555
|
+
/mnt/incoming
|
556
|
+
accs:
|
557
|
+
w: u1 # u1 can upload but not see/download any files,
|
558
|
+
rm: u2 # u2 can browse + move files out of this volume
|
559
|
+
|
560
|
+
[/i]
|
561
|
+
/mnt/ss
|
562
|
+
accs:
|
563
|
+
rw: u1 # u1 can read-write,
|
564
|
+
g: * # everyone can access files if they know the URL
|
565
|
+
flags:
|
566
|
+
fk: 4 # each file URL will have a 4-character password
|
567
|
+
```
|
568
|
+
|
532
569
|
|
533
570
|
## shadowing
|
534
571
|
|
@@ -536,6 +573,8 @@ hiding specific subfolders by mounting another volume on top of them
|
|
536
573
|
|
537
574
|
for example `-v /mnt::r -v /var/empty:web/certs:r` mounts the server folder `/mnt` as the webroot, but another volume is mounted at `/web/certs` -- so visitors can only see the contents of `/mnt` and `/mnt/web` (at URLs `/` and `/web`), but not `/mnt/web/certs` because URL `/web/certs` is mapped to `/var/empty`
|
538
575
|
|
576
|
+
the example config file right above this section may explain this better; the first volume `/` is mapped to `/srv` which means http://127.0.0.1:3923/music would try to read `/srv/music` on the server filesystem, but since there's another volume at `/music` mapped to `/mnt/music` then it'll go to `/mnt/music` instead
|
577
|
+
|
539
578
|
|
540
579
|
## dotfiles
|
541
580
|
|
@@ -547,6 +586,19 @@ a client can request to see dotfiles in directory listings if global option `-ed
|
|
547
586
|
|
548
587
|
dotfiles do not appear in search results unless one of the above is true, **and** the global option / volflag `dotsrch` is set
|
549
588
|
|
589
|
+
config file example, where the same permission to see dotfiles is given in two different ways just for reference:
|
590
|
+
|
591
|
+
```yaml
|
592
|
+
[/foo]
|
593
|
+
/srv/foo
|
594
|
+
accs:
|
595
|
+
r.: ed # user "ed" has read-access + dot-access in this volume;
|
596
|
+
# dotfiles are visible in listings, but not in searches
|
597
|
+
flags:
|
598
|
+
dotsrch # dotfiles will now appear in search results too
|
599
|
+
dots # another way to let everyone see dotfiles in this vol
|
600
|
+
```
|
601
|
+
|
550
602
|
|
551
603
|
# the browser
|
552
604
|
|
@@ -669,6 +721,23 @@ enabling `multiselect` lets you click files to select them, and then shift-click
|
|
669
721
|
* `multiselect` is mostly intended for phones/tablets, but the `sel` option in the `[⚙️] settings` tab is better suited for desktop use, allowing selection by CTRL-clicking and range-selection with SHIFT-click, all without affecting regular clicking
|
670
722
|
* the `sel` option can be made default globally with `--gsel` or per-volume with volflag `gsel`
|
671
723
|
|
724
|
+
config file example:
|
725
|
+
|
726
|
+
```yaml
|
727
|
+
[global]
|
728
|
+
no-thumb # disable ALL thumbnails and audio transcoding
|
729
|
+
no-vthumb # only disable video thumbnails
|
730
|
+
|
731
|
+
[/music]
|
732
|
+
/mnt/nas/music
|
733
|
+
accs:
|
734
|
+
r: * # everyone can read
|
735
|
+
flags:
|
736
|
+
dthumb # disable ALL thumbnails and audio transcoding
|
737
|
+
dvthumb # only disable video thumbnails
|
738
|
+
th-covers: folder.png,folder.jpg,cover.png,cover.jpg # the default
|
739
|
+
```
|
740
|
+
|
672
741
|
|
673
742
|
## zip downloads
|
674
743
|
|
@@ -793,6 +862,14 @@ undo/delete accidental uploads using the `[🧯]` tab in the UI
|
|
793
862
|
|
794
863
|
you can unpost even if you don't have regular move/delete access, however only for files uploaded within the past `--unpost` seconds (default 12 hours) and the server must be running with `-e2d`
|
795
864
|
|
865
|
+
config file example:
|
866
|
+
|
867
|
+
```yaml
|
868
|
+
[global]
|
869
|
+
e2d # enable up2k database (remember uploads)
|
870
|
+
unpost: 43200 # 12 hours (default)
|
871
|
+
```
|
872
|
+
|
796
873
|
|
797
874
|
### self-destruct
|
798
875
|
|
@@ -958,6 +1035,15 @@ will show uploader IP and upload-time if the visitor has the admin permission
|
|
958
1035
|
|
959
1036
|
note that the [🧯 unpost](#unpost) feature is better suited for viewing *your own* recent uploads, as it includes the option to undo/delete them
|
960
1037
|
|
1038
|
+
config file example:
|
1039
|
+
|
1040
|
+
```yaml
|
1041
|
+
[global]
|
1042
|
+
ups-when # everyone can see upload times
|
1043
|
+
ups-who: 1 # but only admins can see the list,
|
1044
|
+
# so ups-when doesn't take effect
|
1045
|
+
```
|
1046
|
+
|
961
1047
|
|
962
1048
|
## media player
|
963
1049
|
|
@@ -1102,7 +1188,16 @@ using arguments or config files, or a mix of both:
|
|
1102
1188
|
|
1103
1189
|
announce enabled services on the LAN ([pic](https://user-images.githubusercontent.com/241032/215344737-0eae8d98-9496-4256-9aa8-cd2f6971810d.png)) -- `-z` enables both [mdns](#mdns) and [ssdp](#ssdp)
|
1104
1190
|
|
1105
|
-
* `--z-on` / `--z-off`
|
1191
|
+
* `--z-on` / `--z-off` limits the feature to certain networks
|
1192
|
+
|
1193
|
+
config file example:
|
1194
|
+
|
1195
|
+
```yaml
|
1196
|
+
[global]
|
1197
|
+
z # enable all zeroconf features (mdns, ssdp)
|
1198
|
+
zm # only enables mdns (does nothing since we already have z)
|
1199
|
+
z-on: 192.168.0.0/16, 10.1.2.0/24 # restrict to certain subnets
|
1200
|
+
```
|
1106
1201
|
|
1107
1202
|
|
1108
1203
|
### mdns
|
@@ -1243,7 +1338,7 @@ dependencies: `python3 -m pip install --user -U impacket==0.11.0`
|
|
1243
1338
|
|
1244
1339
|
some **BIG WARNINGS** specific to SMB/CIFS, in decreasing importance:
|
1245
1340
|
* not entirely confident that read-only is read-only
|
1246
|
-
* the smb backend is not fully integrated with vfs, meaning there could be security issues (path traversal). Please use `--smb-port` (see below) and [prisonparty](./bin/prisonparty.sh)
|
1341
|
+
* the smb backend is not fully integrated with vfs, meaning there could be security issues (path traversal). Please use `--smb-port` (see below) and [prisonparty](./bin/prisonparty.sh) or [bubbleparty](./bin/bubbleparty.sh)
|
1247
1342
|
* account passwords work per-volume as expected, and so does account permissions (read/write/move/delete), but `--smbw` must be given to allow write-access from smb
|
1248
1343
|
* [shadowing](#shadowing) probably works as expected but no guarantees
|
1249
1344
|
|
@@ -1329,6 +1424,18 @@ advantages of using symlinks (default):
|
|
1329
1424
|
|
1330
1425
|
global-option `--xlink` / volflag `xlink` additionally enables deduplication across volumes, but this is probably buggy and not recommended
|
1331
1426
|
|
1427
|
+
config file example:
|
1428
|
+
|
1429
|
+
```yaml
|
1430
|
+
[global]
|
1431
|
+
e2dsa # scan and index filesystem on startup
|
1432
|
+
dedup # symlink-based deduplication for all volumes
|
1433
|
+
|
1434
|
+
[/media]
|
1435
|
+
/mnt/nas/media
|
1436
|
+
flags:
|
1437
|
+
hardlinkonly # this vol does hardlinks instead of symlinks
|
1438
|
+
```
|
1332
1439
|
|
1333
1440
|
|
1334
1441
|
## file indexing
|
@@ -1360,6 +1467,14 @@ note:
|
|
1360
1467
|
* `e2tsr` is probably always overkill, since `e2ds`/`e2dsa` would pick up any file modifications and `e2ts` would then reindex those, unless there is a new copyparty version with new parsers and the release note says otherwise
|
1361
1468
|
* the rescan button in the admin panel has no effect unless the volume has `-e2ds` or higher
|
1362
1469
|
|
1470
|
+
config file example (these options are recommended btw):
|
1471
|
+
|
1472
|
+
```yaml
|
1473
|
+
[global]
|
1474
|
+
e2dsa # scan and index all files in all volumes on startup
|
1475
|
+
e2ts # check newly-discovered or uploaded files for media tags
|
1476
|
+
```
|
1477
|
+
|
1363
1478
|
### exclude-patterns
|
1364
1479
|
|
1365
1480
|
to save some time, you can provide a regex pattern for filepaths to only index by filename/path/size/last-modified (and not the hash of the file contents) by setting `--no-hash '\.iso$'` or the volflag `:c,nohash=\.iso$`, this has the following consequences:
|
@@ -1369,12 +1484,24 @@ to save some time, you can provide a regex pattern for filepaths to only index
|
|
1369
1484
|
|
1370
1485
|
similarly, you can fully ignore files/folders using `--no-idx [...]` and `:c,noidx=\.iso$`
|
1371
1486
|
|
1487
|
+
NOTE: `no-idx` and/or `no-hash` prevents deduplication of those files
|
1488
|
+
|
1372
1489
|
* when running on macos, all the usual apple metadata files are excluded by default
|
1373
1490
|
|
1374
1491
|
if you set `--no-hash [...]` globally, you can enable hashing for specific volumes using flag `:c,nohash=`
|
1375
1492
|
|
1376
1493
|
to exclude certain filepaths from search-results, use `--srch-excl` or volflag `srch_excl` instead of `--no-idx`, for example `--srch-excl 'password|logs/[0-9]'`
|
1377
1494
|
|
1495
|
+
config file example:
|
1496
|
+
|
1497
|
+
```yaml
|
1498
|
+
[/games]
|
1499
|
+
/mnt/nas/games
|
1500
|
+
flags:
|
1501
|
+
noidx: \.iso$ # skip indexing iso-files
|
1502
|
+
srch_excl: password|logs/[0-9] # filter search results
|
1503
|
+
```
|
1504
|
+
|
1378
1505
|
### filesystem guards
|
1379
1506
|
|
1380
1507
|
avoid traversing into other filesystems using `--xdev` / volflag `:c,xdev`, skipping any symlinks or bind-mounts to another HDD for example
|
@@ -1395,6 +1522,20 @@ argument `--re-maxage 60` will rescan all volumes every 60 sec, same as volflag
|
|
1395
1522
|
|
1396
1523
|
uploads are disabled while a rescan is happening, so rescans will be delayed by `--db-act` (default 10 sec) when there is write-activity going on (uploads, renames, ...)
|
1397
1524
|
|
1525
|
+
note: folder-thumbnails are selected during filesystem indexing, so periodic rescans can be used to keep them accurate as images are uploaded/deleted (or manually do a rescan with the `reload` button in the controlpanel)
|
1526
|
+
|
1527
|
+
config file example:
|
1528
|
+
|
1529
|
+
```yaml
|
1530
|
+
[global]
|
1531
|
+
re-maxage: 3600
|
1532
|
+
|
1533
|
+
[/pics]
|
1534
|
+
/mnt/nas/pics
|
1535
|
+
flags:
|
1536
|
+
scan: 900
|
1537
|
+
```
|
1538
|
+
|
1398
1539
|
|
1399
1540
|
## upload rules
|
1400
1541
|
|
@@ -1420,6 +1561,26 @@ you can also set transaction limits which apply per-IP and per-volume, but these
|
|
1420
1561
|
notes:
|
1421
1562
|
* `vmaxb` and `vmaxn` requires either the `e2ds` volflag or `-e2dsa` global-option
|
1422
1563
|
|
1564
|
+
config file example:
|
1565
|
+
|
1566
|
+
```yaml
|
1567
|
+
[/inc]
|
1568
|
+
/mnt/nas/uploads
|
1569
|
+
accs:
|
1570
|
+
w: * # anyone can upload here
|
1571
|
+
rw: ed # only user "ed" can read-write
|
1572
|
+
flags:
|
1573
|
+
e2ds: # filesystem indexing is required for many of these:
|
1574
|
+
sz: 1k-3m # accept upload only if filesize in this range
|
1575
|
+
df: 4g # free disk space cannot go lower than this
|
1576
|
+
vmaxb: 1g # volume can never exceed 1 GiB
|
1577
|
+
vmaxn: 4k # ...or 4000 files, whichever comes first
|
1578
|
+
nosub # must upload to toplevel folder
|
1579
|
+
lifetime: 300 # uploads are deleted after 5min
|
1580
|
+
maxn: 250,3600 # each IP can upload 250 files in 1 hour
|
1581
|
+
maxb: 1g,300 # each IP can upload 1 GiB over 5 minutes
|
1582
|
+
```
|
1583
|
+
|
1423
1584
|
|
1424
1585
|
## compress uploads
|
1425
1586
|
|
@@ -1465,10 +1626,24 @@ this can instead be kept in a single place using the `--hist` argument, or the `
|
|
1465
1626
|
* `--hist ~/.cache/copyparty -v ~/music::r:c,hist=-` sets `~/.cache/copyparty` as the default place to put volume info, but `~/music` gets the regular `.hist` subfolder (`-` restores default behavior)
|
1466
1627
|
|
1467
1628
|
note:
|
1629
|
+
* putting the hist-folders on an SSD is strongly recommended for performance
|
1468
1630
|
* markdown edits are always stored in a local `.hist` subdirectory
|
1469
1631
|
* on windows the volflag path is cyglike, so `/c/temp` means `C:\temp` but use regular paths for `--hist`
|
1470
1632
|
* you can use cygpaths for volumes too, `-v C:\Users::r` and `-v /c/users::r` both work
|
1471
1633
|
|
1634
|
+
config file example:
|
1635
|
+
|
1636
|
+
```yaml
|
1637
|
+
[global]
|
1638
|
+
hist: ~/.cache/copyparty # put db/thumbs/etc. here by default
|
1639
|
+
|
1640
|
+
[/pics]
|
1641
|
+
/mnt/nas/pics
|
1642
|
+
flags:
|
1643
|
+
hist: - # restore the default (/mnt/nas/pics/.hist/)
|
1644
|
+
hist: /mnt/nas/cache/pics/ # can be absolute path
|
1645
|
+
```
|
1646
|
+
|
1472
1647
|
|
1473
1648
|
## metadata from audio files
|
1474
1649
|
|
@@ -1520,6 +1695,18 @@ copyparty can invoke external programs to collect additional metadata for files
|
|
1520
1695
|
|
1521
1696
|
if something doesn't work, try `--mtag-v` for verbose error messages
|
1522
1697
|
|
1698
|
+
config file example; note that `mtp` is an additive option so all of the mtp options will take effect:
|
1699
|
+
|
1700
|
+
```yaml
|
1701
|
+
[/music]
|
1702
|
+
/mnt/nas/music
|
1703
|
+
flags:
|
1704
|
+
mtp: .bpm=~/bin/audio-bpm.py # assign ".bpm" (numeric) with script
|
1705
|
+
mtp: key=f,t5,~/bin/audio-key.py # force/overwrite, 5sec timeout
|
1706
|
+
mtp: ext=an,~/bin/file-ext.py # will only run on non-audio files
|
1707
|
+
mtp: arch,built,ver,orig=an,eexe,edll,~/bin/exe.py # only exe/dll
|
1708
|
+
```
|
1709
|
+
|
1523
1710
|
|
1524
1711
|
## event hooks
|
1525
1712
|
|
@@ -1548,13 +1735,35 @@ the PUSH and REQ examples have `t3` (timeout after 3 seconds) because they block
|
|
1548
1735
|
|
1549
1736
|
see [zmq-recv.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/zmq-recv.py) if you need something to receive the messages with
|
1550
1737
|
|
1738
|
+
config file example; note that the hooks are additive options, so all of the xau options will take effect:
|
1739
|
+
|
1740
|
+
```yaml
|
1741
|
+
[global]
|
1742
|
+
xau: zmq:pub:tcp://*:5556` # send a PUB to any/all connected SUB clients
|
1743
|
+
xau: t3,zmq:push:tcp://*:5557` # send PUSH to exactly one connected PULL cli
|
1744
|
+
xau: t3,j,zmq:req:tcp://localhost:5555` # send REQ to the connected REP cli
|
1745
|
+
```
|
1746
|
+
|
1551
1747
|
|
1552
1748
|
### upload events
|
1553
1749
|
|
1554
1750
|
the older, more powerful approach ([examples](./bin/mtag/)):
|
1555
1751
|
|
1556
1752
|
```
|
1557
|
-
-v /mnt/inc:inc:w:c,mte=+x1:c,mtp=x1=ad,kn,/usr/bin/notify-send
|
1753
|
+
-v /mnt/inc:inc:w:c,e2d,e2t,mte=+x1:c,mtp=x1=ad,kn,/usr/bin/notify-send
|
1754
|
+
```
|
1755
|
+
|
1756
|
+
that was the commandline example; here's the config file example:
|
1757
|
+
|
1758
|
+
```yaml
|
1759
|
+
[/inc]
|
1760
|
+
/mnt/inc
|
1761
|
+
accs:
|
1762
|
+
w: *
|
1763
|
+
flags:
|
1764
|
+
e2d, e2t # enable indexing of uploaded files and their tags
|
1765
|
+
mte: +x1
|
1766
|
+
mtp: x1=ad,kn,/usr/bin/notify-send
|
1558
1767
|
```
|
1559
1768
|
|
1560
1769
|
so filesystem location `/mnt/inc` shared at `/inc`, write-only for everyone, appending `x1` to the list of tags to index (`mte`), and using `/usr/bin/notify-send` to "provide" tag `x1` for any filetype (`ad`) with kill-on-timeout disabled (`kn`)
|
@@ -1568,6 +1777,8 @@ note that this is way more complicated than the new [event hooks](#event-hooks)
|
|
1568
1777
|
|
1569
1778
|
note that it will occupy the parsing threads, so fork anything expensive (or set `kn` to have copyparty fork it for you) -- otoh if you want to intentionally queue/singlethread you can combine it with `--mtag-mt 1`
|
1570
1779
|
|
1780
|
+
for reference, if you were to do this using event hooks instead, it would be like this: `-e2d --xau notify-send,hello,--`
|
1781
|
+
|
1571
1782
|
|
1572
1783
|
## handlers
|
1573
1784
|
|
@@ -1575,6 +1786,8 @@ redefine behavior with plugins ([examples](./bin/handlers/))
|
|
1575
1786
|
|
1576
1787
|
replace 404 and 403 errors with something completely different (that's it for now)
|
1577
1788
|
|
1789
|
+
as for client-side stuff, there is [plugins for modifying UI/UX](./contrib/plugins/)
|
1790
|
+
|
1578
1791
|
|
1579
1792
|
## ip auth
|
1580
1793
|
|
@@ -1636,6 +1849,8 @@ connecting to an aws s3 bucket and similar
|
|
1636
1849
|
|
1637
1850
|
there is no built-in support for this, but you can use FUSE-software such as [rclone](https://rclone.org/) / [geesefs](https://github.com/yandex-cloud/geesefs) / [JuiceFS](https://juicefs.com/en/) to first mount your cloud storage as a local disk, and then let copyparty use (a folder in) that disk as a volume
|
1638
1851
|
|
1852
|
+
if copyparty is unable to access the local folder that rclone/geesefs/JuiceFS provides (for example if it looks invisible) then you may need to run rclone with `--allow-other` and/or enable `user_allow_other` in `/etc/fuse.conf`
|
1853
|
+
|
1639
1854
|
you will probably get decent speeds with the default config, however most likely restricted to using one TCP connection per file, so the upload-client won't be able to send multiple chunks in parallel
|
1640
1855
|
|
1641
1856
|
> before [v1.13.5](https://github.com/9001/copyparty/releases/tag/v1.13.5) it was recommended to use the volflag `sparse` to force-allow multiple chunks in parallel; this would improve the upload-speed from `1.5 MiB/s` to over `80 MiB/s` at the risk of provoking latent bugs in S3 or JuiceFS. But v1.13.5 added chunk-stitching, so this is now probably much less important. On the contrary, `nosparse` *may* now increase performance in some cases. Please try all three options (default, `sparse`, `nosparse`) as the optimal choice depends on your network conditions and software stack (both the FUSE-driver and cloud-server)
|
@@ -1896,7 +2111,7 @@ change the association of a file extension
|
|
1896
2111
|
|
1897
2112
|
using commandline args, you can do something like `--mime gif=image/jif` and `--mime ts=text/x.typescript` (can be specified multiple times)
|
1898
2113
|
|
1899
|
-
in a config
|
2114
|
+
in a config file, this is the same as:
|
1900
2115
|
|
1901
2116
|
```yaml
|
1902
2117
|
[global]
|
@@ -2156,6 +2371,8 @@ NOTE: curl will not send the original filename if you use `-T` combined with url
|
|
2156
2371
|
|
2157
2372
|
sync folders to/from copyparty
|
2158
2373
|
|
2374
|
+
NOTE: full bidirectional sync, like what [nextcloud](https://docs.nextcloud.com/server/latest/user_manual/sv/files/desktop_mobile_sync.html) and [syncthing](https://syncthing.net/) does, will never be supported! Only single-direction sync (server-to-client, or client-to-server) is possible with copyparty
|
2375
|
+
|
2159
2376
|
the commandline uploader [u2c.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#u2cpy) with `--dr` is the best way to sync a folder to copyparty; verifies checksums and does files in parallel, and deletes unexpected files on the server after upload has finished which makes file-renames really cheap (it'll rename serverside and skip uploading)
|
2160
2377
|
|
2161
2378
|
alternatively there is [rclone](./docs/rclone.md) which allows for bidirectional sync and is *way* more flexible (stream files straight from sftp/s3/gcs to copyparty, ...), although there is no integrity check and it won't work with files over 100 MiB if copyparty is behind cloudflare
|
@@ -1,24 +1,24 @@
|
|
1
1
|
copyparty/__init__.py,sha256=VR6ZZhB9IxaK5TDXDTBM_OIP5ydkrdbaEnstktLM__s,2649
|
2
|
-
copyparty/__main__.py,sha256=
|
3
|
-
copyparty/__version__.py,sha256=
|
4
|
-
copyparty/authsrv.py,sha256=
|
2
|
+
copyparty/__main__.py,sha256=ATbSyFWmocvOlarT6d-nglHBf3O4KmX4zrSwW-Bz1WQ,115851
|
3
|
+
copyparty/__version__.py,sha256=hb9GoVB8qCxT8TBRr_QaRRAT3xQiXkZaGN_wbrwbd-w,251
|
4
|
+
copyparty/authsrv.py,sha256=SJoNXQmE2yx-3DvLiHWCfrcW67uF2b9v3mzD0gFNaWY,105412
|
5
5
|
copyparty/broker_mp.py,sha256=QdOXXvV2Xn6J0CysEqyY3GZbqxQMyWnTpnba-a5lMc0,4987
|
6
6
|
copyparty/broker_mpw.py,sha256=PpSS4SK3pItlpfD8OwVr3QmJEPKlUgaf2nuMOozixgU,3347
|
7
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=n6mZmlcvT7spUIyhyKfUfd3V6ZX8mX-8QpdeMvYqb9w,10788
|
11
11
|
copyparty/dxml.py,sha256=vu5uZQtwvwoqnFHbULs2Zh_y2DETu0T-ENpMZ1i2CV4,2505
|
12
12
|
copyparty/fsutil.py,sha256=IVOFG8zBQPMQDDv7RIStSJHwHiAnVNROZS37O5k465A,4524
|
13
13
|
copyparty/ftpd.py,sha256=T97SFS7JFtvRLbJX8C4fJSYwe13vhN3-E6emtlVmqLA,17608
|
14
|
-
copyparty/httpcli.py,sha256=
|
14
|
+
copyparty/httpcli.py,sha256=zIzrI9BRTDiBxj8ptDjPCzB3mK46JrRrbmz2K4dygJM,217236
|
15
15
|
copyparty/httpconn.py,sha256=mQSgljh0Q-jyWjF4tQLrHbRKRe9WKl19kGqsGMsJpWo,6880
|
16
16
|
copyparty/httpsrv.py,sha256=pxH_Eh8ElBLvOEDejgpP9Bvk65HNEou-03aYIcgXhrs,18090
|
17
17
|
copyparty/ico.py,sha256=eWSxEae4wOCfheHl-m-wchYvFRAR_97kJDb4NGaB-Z8,3561
|
18
18
|
copyparty/mdns.py,sha256=G73OWWg1copda47LgayCRK7qjVrk6cnUGpMR5ugmi7o,18315
|
19
|
-
copyparty/metrics.py,sha256=
|
19
|
+
copyparty/metrics.py,sha256=1dim0ShnsD5cfspRbeN9Mt14wOIxPRtxCZY2IScikKw,8974
|
20
20
|
copyparty/mtag.py,sha256=wWWc3BHMRP0u85KvdZpX3Dp4djDgAbXVrL9Pvab4nPQ,19925
|
21
|
-
copyparty/multicast.py,sha256=
|
21
|
+
copyparty/multicast.py,sha256=Me4XEEJijvvK2lMRwmGU2hsaI5_E9AEpCjIC4b9UefA,12393
|
22
22
|
copyparty/pwhash.py,sha256=X87RWeay8IhzGVZLDKE5LctF9YVUcYxPAJ1BX6r_9CU,4248
|
23
23
|
copyparty/smbd.py,sha256=dixFl2wlWymq_Cycc8a4cVB4gY8RSg2e3tE7Xr-aDa0,14614
|
24
24
|
copyparty/ssdp.py,sha256=R1Z61GZOxBMF2Sk4RTxKWMOemogmcjEWG-CvLihd45k,7023
|
@@ -54,10 +54,10 @@ copyparty/stolen/ifaddr/__init__.py,sha256=vpREjAyPubr5s1NJi91icXV3q1o4DrKAvHABw
|
|
54
54
|
copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUuTOrU,2626
|
55
55
|
copyparty/stolen/ifaddr/_shared.py,sha256=uNC4SdEIgdSLKvuUzsf1aM-H1Xrc_9mpLoOT43YukGs,6206
|
56
56
|
copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
|
57
|
-
copyparty/web/baguettebox.js.gz,sha256=
|
58
|
-
copyparty/web/browser.css.gz,sha256=
|
59
|
-
copyparty/web/browser.html,sha256=
|
60
|
-
copyparty/web/browser.js.gz,sha256=
|
57
|
+
copyparty/web/baguettebox.js.gz,sha256=r2c_hOZV_RTyl4CqWWX14FDWP8nnDVwGkDl4Sfk0rU4,8239
|
58
|
+
copyparty/web/browser.css.gz,sha256=WwVIXAbrqU2TlNEoDg5D7XJU1o7iAogJoS8aCfSvuOo,11645
|
59
|
+
copyparty/web/browser.html,sha256=auvhLVE_t0aIN0q-nk0zOWFqITgDhroMAAviBNLoFfc,4788
|
60
|
+
copyparty/web/browser.js.gz,sha256=XmTA7KN35cL_Av3nHJy6L8zkg2H307spGoagnBXKg3g,91462
|
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
|
@@ -84,7 +84,7 @@ copyparty/web/svcs.html,sha256=dnE1fG15zOpq7u0GYt8ij6BUv_LTwsiipFeneVYlMsM,14140
|
|
84
84
|
copyparty/web/svcs.js.gz,sha256=lMXEP9W-VlXyANlva4q0ASSxvvHYlE2CrmxGgZXZop0,713
|
85
85
|
copyparty/web/ui.css.gz,sha256=0sHIwGsL3_xH8Uu6N0Ag3bKBTjf-e_yfFbKynEZXAnk,2800
|
86
86
|
copyparty/web/up2k.js.gz,sha256=N4idIqOefXurVh4ZhN6lv9nFPX_azLwE41vhXT2qBkI,23833
|
87
|
-
copyparty/web/util.js.gz,sha256=
|
87
|
+
copyparty/web/util.js.gz,sha256=wD3tP5j1iE5Uj5AvLW5zZbQJXDIFDlqgBTGdXeRVqo0,15110
|
88
88
|
copyparty/web/w.hash.js.gz,sha256=l3GpSJD6mcU-1CRWkIj7PybgbjlfSr8oeO3vortIrQk,1105
|
89
89
|
copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
90
90
|
copyparty/web/a/partyfuse.py,sha256=9p5Hpg_IBiSimv7j9kmPhCGpy-FLXSRUOYnLjJ5JifU,28049
|
@@ -100,7 +100,7 @@ copyparty/web/deps/busy.mp3.gz,sha256=EVphk1_HYyRKJmtpeK99vbAstF7ub1f9ndu020H8PQ
|
|
100
100
|
copyparty/web/deps/easymde.css.gz,sha256=vWxfueI64rPikuqFj69wJBtGisqf93AheQtOZqgUI_c,3041
|
101
101
|
copyparty/web/deps/easymde.js.gz,sha256=rHBs4XWQe2bmv7ZzDIk43oxnTwrwpq5laYHhV5sKQQo,77014
|
102
102
|
copyparty/web/deps/fuse.py,sha256=6j4Zy3VpQg629pwwIW77v2LJ1hy-qlyrxwhXfKl9B7I,33426
|
103
|
-
copyparty/web/deps/marked.js.gz,sha256=
|
103
|
+
copyparty/web/deps/marked.js.gz,sha256=M6FwmQujGDX33fpo32JZRbxqtSdPzmh7WcaHK6SpZlc,22650
|
104
104
|
copyparty/web/deps/mini-fa.css.gz,sha256=CTPrNaH8OTVmxajrGP88E2MkjadY9_81TBVnd9sw9Y8,572
|
105
105
|
copyparty/web/deps/mini-fa.woff,sha256=L9DNncV2TIyvsrspMbJouvnnt7F068Hbn7YZYvN76AU,2784
|
106
106
|
copyparty/web/deps/prism.css.gz,sha256=Z_A6rJ3MN5KWnjvXaV787aTW_5DT-xjFd0YZ7_W-Krk,1468
|
@@ -109,9 +109,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
|
|
109
109
|
copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
|
110
110
|
copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
|
111
111
|
copyparty/web/deps/sha512.hw.js.gz,sha256=UAed2_ocklZCnIzcSYz2h4P1ycztlCLj-ewsRTud2lU,7939
|
112
|
-
copyparty-1.16.
|
113
|
-
copyparty-1.16.
|
114
|
-
copyparty-1.16.
|
115
|
-
copyparty-1.16.
|
116
|
-
copyparty-1.16.
|
117
|
-
copyparty-1.16.
|
112
|
+
copyparty-1.16.12.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
|
113
|
+
copyparty-1.16.12.dist-info/METADATA,sha256=VzmaUTc62j97TcHYADjryHTMmKHBa1GhobpWJdtI9pk,153975
|
114
|
+
copyparty-1.16.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
115
|
+
copyparty-1.16.12.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
|
116
|
+
copyparty-1.16.12.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
|
117
|
+
copyparty-1.16.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|