diff --git a/README.md b/README.md index 93784495..d74f8f4f 100644 --- a/README.md +++ b/README.md @@ -494,6 +494,27 @@ you can also set transaction limits which apply per-IP and per-volume, but these * `:c,maxb=1g,300` allows 1 GiB total over 5 minutes from each IP (tracked per-volume) +## compress uploads + +files can be autocompressed on upload, either on user-request (if config allows) or forced by server-config + +* volume flag `gz` allows gz compression +* volume flag `xz` allows lzma compression +* volume flag `pk` **forces** compression on all files +* url parameter `pk` requests compression with server-default algorithm +* url parameter `gz` or `xz` requests compression with a specific algorithm +* url parameter `xz` requests xz compression + +things to note, +* the `gz` and `xz` arguments take a single optional argument, the compression level (range 0 to 9) +* the `pk` volume flag takes the optional argument `ALGORITHM,LEVEL` which will then be forced for all uploads, for example `gz,9` or `xz,0` +* default compression is gzip level 9 +* all upload methods except up2k are supported +* the files will be indexed after compression, so dupe-detection and file-search will not work as expected + +some examples, + + ## database location copyparty creates a subfolder named `.hist` inside each volume where it stores the database, thumbnails, and some other stuff @@ -600,11 +621,11 @@ quick summary of more eccentric web-browsers trying to view a directory index: * `var xhr = new XMLHttpRequest(); xhr.open('POST', 'https://127.0.0.1:3923/msgs?raw'); xhr.send('foo');` * curl/wget: upload some files (post=file, chunk=stdin) - * `post(){ curl -b cppwd=wark http://127.0.0.1:3923/ -F act=bput -F f=@"$1";}` + * `post(){ curl -b cppwd=wark -F act=bput -F f=@"$1" http://127.0.0.1:3923/;}` `post movie.mkv` - * `post(){ wget --header='Cookie: cppwd=wark' http://127.0.0.1:3923/?raw --post-file="$1" -O-;}` + * `post(){ wget --header='Cookie: cppwd=wark' --post-file="$1" -O- http://127.0.0.1:3923/?raw;}` `post movie.mkv` - * `chunk(){ curl -b cppwd=wark http://127.0.0.1:3923/ -T-;}` + * `chunk(){ curl -b cppwd=wark -T- http://127.0.0.1:3923/;}` `chunk 10 or len(cookies) > 50: + raise Pebkac(400, "u wot m8") + self.uparam = uparam self.cookies = cookies self.vpath = unquotep(vpath) # not query, so + means + @@ -503,7 +511,59 @@ class HttpCli(object): if self.args.nw: path = os.devnull - with open(fsenc(path), "wb", 512 * 1024) as f: + open_f = open + open_a = [fsenc(path), "wb", 512 * 1024] + open_ka = {} + + # user-request || config-force + if ("gz" in vfs.flags or "xz" in vfs.flags) and ( + "pk" in vfs.flags + or "pk" in self.uparam + or "gz" in self.uparam + or "xz" in self.uparam + ): + fb = {"gz": 9, "xz": 0} # default/fallback level + lv = {} # selected level + alg = None # selected algo (gz=preferred) + + # user-prefs first + if "gz" in self.uparam or "pk" in self.uparam: # def.pk + alg = "gz" + if "xz" in self.uparam: + alg = "xz" + if alg: + v = self.uparam.get(alg) + lv[alg] = fb[alg] if v is None else int(v) + + if alg not in vfs.flags: + alg = "gz" if "gz" in vfs.flags else "xz" + + # then server overrides + pk = vfs.flags.get("pk") + if pk is not None: + # config-forced on + alg = alg or "gz" # def.pk + try: + # config-forced opts + alg, lv = pk.split(",") + lv[alg] = int(lv) + except: + pass + + lv[alg] = lv.get(alg) or fb.get(alg) + + self.log("compressing with {} level {}".format(alg, lv.get(alg))) + if alg == "gz": + open_f = gzip.GzipFile + open_a = [fsenc(path), "wb", lv[alg], None, 0x5FEE6600] # 2021-01-01 + elif alg == "xz": + open_f = lzma.open + open_a = [fsenc(path), "wb"] + open_ka = {"preset": lv[alg]} + else: + self.log("fallthrough? thats a bug", 1) + + with open_f(*open_a, **open_ka) as f: post_sz, _, sha_b64 = hashcopy(reader, f) if lim: