diff --git a/bin/README.md b/bin/README.md index 759fae9a..3fb5b6e5 100644 --- a/bin/README.md +++ b/bin/README.md @@ -4,6 +4,8 @@ * faster than browsers * early beta, if something breaks just restart it + + # [`copyparty-fuse.py`](copyparty-fuse.py) * mount a copyparty server as a local filesystem (read-only) * **supports Windows!** -- expect `194 MiB/s` sequential read @@ -53,6 +55,7 @@ you could replace winfsp with [dokan](https://github.com/dokan-dev/dokany/releas * copyparty can Popen programs like these during file indexing to collect additional metadata + # [`dbtool.py`](dbtool.py) upgrade utility which can show db info and help transfer data between databases, for example when a new version of copyparty is incompatible with the old DB and automatically rebuilds the DB from scratch, but you have some really expensive `-mtp` parsers and want to copy over the tags from the old db @@ -69,6 +72,7 @@ cd /mnt/nas/music/.hist ``` + # [`prisonparty.sh`](prisonparty.sh) * run copyparty in a chroot, preventing any accidental file access * creates bindmounts for /bin, /lib, and so on, see `sysdirs=` diff --git a/bin/mtag/README.md b/bin/mtag/README.md index d4603b9c..2adda0ba 100644 --- a/bin/mtag/README.md +++ b/bin/mtag/README.md @@ -10,6 +10,7 @@ some of these rely on libraries which are not MIT-compatible these do not have any problematic dependencies: +* [cksum.py](./cksum.py) computes various checksums * [exe.py](./exe.py) grabs metadata from .exe and .dll files (example for retrieving multiple tags with one parser) * [wget.py](./wget.py) lets you download files by POSTing URLs to copyparty diff --git a/bin/mtag/cksum.py b/bin/mtag/cksum.py new file mode 100755 index 00000000..c70a1b87 --- /dev/null +++ b/bin/mtag/cksum.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +import sys +import json +import zlib +import struct +import base64 +import hashlib + +try: + from copyparty.util import fsenc +except: + + def fsenc(p): + return p + + +""" +calculates various checksums for uploads, +usage: -mtp crc32,md5,sha1,sha256b=bin/mtag/cksum.py +""" + + +def main(): + config = "crc32 md5 md5b sha1 sha1b sha256 sha256b sha512/240 sha512b/240" + # b suffix = base64 encoded + # slash = truncate to n bits + + known = { + "md5": hashlib.md5, + "sha1": hashlib.sha1, + "sha256": hashlib.sha256, + "sha512": hashlib.sha512, + } + config = config.split() + hashers = { + k: v() + for k, v in known.items() + if k in [x.split("/")[0].rstrip("b") for x in known] + } + crc32 = 0 if "crc32" in config else None + + with open(fsenc(sys.argv[1]), "rb", 512 * 1024) as f: + while True: + buf = f.read(64 * 1024) + if not buf: + break + + for x in hashers.values(): + x.update(buf) + + if crc32 is not None: + crc32 = zlib.crc32(buf, crc32) + + ret = {} + for s in config: + alg = s.split("/")[0] + b64 = alg.endswith("b") + alg = alg.rstrip("b") + if alg in hashers: + v = hashers[alg].digest() + elif alg == "crc32": + v = crc32 + if v < 0: + v &= 2 ** 32 - 1 + v = struct.pack(">L", v) + else: + raise Exception("what is {}".format(s)) + + if "/" in s: + v = v[: int(int(s.split("/")[1]) / 8)] + + if b64: + v = base64.b64encode(v).decode("ascii").rstrip("=") + else: + try: + v = v.hex() + except: + import binascii + + v = binascii.hexlify(v) + + ret[s] = v + + print(json.dumps(ret, indent=4)) + + +if __name__ == "__main__": + main()