copyparty 1.16.7__py3-none-any.whl → 1.16.9__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 +15 -8
 - copyparty/__version__.py +2 -2
 - copyparty/authsrv.py +8 -1
 - copyparty/cfg.py +5 -0
 - copyparty/dxml.py +48 -3
 - copyparty/httpcli.py +62 -30
 - copyparty/svchub.py +13 -0
 - copyparty/up2k.py +32 -12
 - copyparty/util.py +154 -8
 - copyparty/web/a/u2c.py +3 -3
 - copyparty/web/browser.js.gz +0 -0
 - copyparty/web/splash.css.gz +0 -0
 - copyparty/web/svcs.html +64 -3
 - copyparty/web/svcs.js.gz +0 -0
 - copyparty/web/ui.css.gz +0 -0
 - copyparty/web/up2k.js.gz +0 -0
 - copyparty/web/util.js.gz +0 -0
 - {copyparty-1.16.7.dist-info → copyparty-1.16.9.dist-info}/METADATA +84 -16
 - {copyparty-1.16.7.dist-info → copyparty-1.16.9.dist-info}/RECORD +23 -23
 - {copyparty-1.16.7.dist-info → copyparty-1.16.9.dist-info}/WHEEL +1 -1
 - {copyparty-1.16.7.dist-info → copyparty-1.16.9.dist-info}/LICENSE +0 -0
 - {copyparty-1.16.7.dist-info → copyparty-1.16.9.dist-info}/entry_points.txt +0 -0
 - {copyparty-1.16.7.dist-info → copyparty-1.16.9.dist-info}/top_level.txt +0 -0
 
    
        copyparty/util.py
    CHANGED
    
    | 
         @@ -120,6 +120,13 @@ try: 
     | 
|
| 
       120 
120 
     | 
    
         
             
            except:
         
     | 
| 
       121 
121 
     | 
    
         
             
                HAVE_SQLITE3 = False
         
     | 
| 
       122 
122 
     | 
    
         | 
| 
      
 123 
     | 
    
         
            +
            try:
         
     | 
| 
      
 124 
     | 
    
         
            +
                import importlib.util
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                HAVE_ZMQ = bool(importlib.util.find_spec("zmq"))
         
     | 
| 
      
 127 
     | 
    
         
            +
            except:
         
     | 
| 
      
 128 
     | 
    
         
            +
                HAVE_ZMQ = False
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
       123 
130 
     | 
    
         
             
            try:
         
     | 
| 
       124 
131 
     | 
    
         
             
                if os.environ.get("PRTY_NO_PSUTIL"):
         
     | 
| 
       125 
132 
     | 
    
         
             
                    raise Exception()
         
     | 
| 
         @@ -208,6 +215,10 @@ META_NOBOTS = '<meta name="robots" content="noindex, nofollow">\n' 
     | 
|
| 
       208 
215 
     | 
    
         | 
| 
       209 
216 
     | 
    
         
             
            FFMPEG_URL = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z"
         
     | 
| 
       210 
217 
     | 
    
         | 
| 
      
 218 
     | 
    
         
            +
            URL_PRJ = "https://github.com/9001/copyparty"
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
            URL_BUG = URL_PRJ + "/issues/new?labels=bug&template=bug_report.md"
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
       211 
222 
     | 
    
         
             
            HTTPCODE = {
         
     | 
| 
       212 
223 
     | 
    
         
             
                200: "OK",
         
     | 
| 
       213 
224 
     | 
    
         
             
                201: "Created",
         
     | 
| 
         @@ -470,6 +481,15 @@ def py_desc()  : 
     | 
|
| 
       470 
481 
     | 
    
         
             
                )
         
     | 
| 
       471 
482 
     | 
    
         | 
| 
       472 
483 
     | 
    
         | 
| 
      
 484 
     | 
    
         
            +
            def expat_ver()  :
         
     | 
| 
      
 485 
     | 
    
         
            +
                try:
         
     | 
| 
      
 486 
     | 
    
         
            +
                    import pyexpat
         
     | 
| 
      
 487 
     | 
    
         
            +
             
     | 
| 
      
 488 
     | 
    
         
            +
                    return ".".join([str(x) for x in pyexpat.version_info])
         
     | 
| 
      
 489 
     | 
    
         
            +
                except:
         
     | 
| 
      
 490 
     | 
    
         
            +
                    return "?"
         
     | 
| 
      
 491 
     | 
    
         
            +
             
     | 
| 
      
 492 
     | 
    
         
            +
             
     | 
| 
       473 
493 
     | 
    
         
             
            def _sqlite_ver()  :
         
     | 
| 
       474 
494 
     | 
    
         
             
                try:
         
     | 
| 
       475 
495 
     | 
    
         
             
                    co = sqlite3.connect(":memory:")
         
     | 
| 
         @@ -3297,6 +3317,7 @@ def _parsehook( 
     | 
|
| 
       3297 
3317 
     | 
    
         | 
| 
       3298 
3318 
     | 
    
         
             
            def runihook(
         
     | 
| 
       3299 
3319 
     | 
    
         
             
                log ,
         
     | 
| 
      
 3320 
     | 
    
         
            +
                verbose ,
         
     | 
| 
       3300 
3321 
     | 
    
         
             
                cmd ,
         
     | 
| 
       3301 
3322 
     | 
    
         
             
                vol ,
         
     | 
| 
       3302 
3323 
     | 
    
         
             
                ups       ,
         
     | 
| 
         @@ -3326,6 +3347,17 @@ def runihook( 
     | 
|
| 
       3326 
3347 
     | 
    
         
             
                else:
         
     | 
| 
       3327 
3348 
     | 
    
         
             
                    sp_ka["sin"] = b"\n".join(fsenc(x) for x in aps)
         
     | 
| 
       3328 
3349 
     | 
    
         | 
| 
      
 3350 
     | 
    
         
            +
                if acmd[0].startswith("zmq:"):
         
     | 
| 
      
 3351 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 3352 
     | 
    
         
            +
                        msg = sp_ka["sin"].decode("utf-8", "replace")
         
     | 
| 
      
 3353 
     | 
    
         
            +
                        _zmq_hook(log, verbose, "xiu", acmd[0][4:].lower(), msg, wait, sp_ka)
         
     | 
| 
      
 3354 
     | 
    
         
            +
                        if verbose and log:
         
     | 
| 
      
 3355 
     | 
    
         
            +
                            log("hook(xiu) %r OK" % (cmd,), 6)
         
     | 
| 
      
 3356 
     | 
    
         
            +
                    except Exception as ex:
         
     | 
| 
      
 3357 
     | 
    
         
            +
                        if log:
         
     | 
| 
      
 3358 
     | 
    
         
            +
                            log("zeromq failed: %r" % (ex,))
         
     | 
| 
      
 3359 
     | 
    
         
            +
                    return True
         
     | 
| 
      
 3360 
     | 
    
         
            +
             
     | 
| 
       3329 
3361 
     | 
    
         
             
                t0 = time.time()
         
     | 
| 
       3330 
3362 
     | 
    
         
             
                if fork:
         
     | 
| 
       3331 
3363 
     | 
    
         
             
                    Daemon(runcmd, cmd, bcmd, ka=sp_ka)
         
     | 
| 
         @@ -3335,15 +3367,118 @@ def runihook( 
     | 
|
| 
       3335 
3367 
     | 
    
         
             
                        retchk(rc, bcmd, err, log, 5)
         
     | 
| 
       3336 
3368 
     | 
    
         
             
                        return False
         
     | 
| 
       3337 
3369 
     | 
    
         | 
| 
       3338 
     | 
    
         
            -
                wait 
     | 
| 
       3339 
     | 
    
         
            -
             
     | 
| 
       3340 
     | 
    
         
            -
                     
     | 
| 
      
 3370 
     | 
    
         
            +
                if wait:
         
     | 
| 
      
 3371 
     | 
    
         
            +
                    wait -= time.time() - t0
         
     | 
| 
      
 3372 
     | 
    
         
            +
                    if wait > 0:
         
     | 
| 
      
 3373 
     | 
    
         
            +
                        time.sleep(wait)
         
     | 
| 
       3341 
3374 
     | 
    
         | 
| 
       3342 
3375 
     | 
    
         
             
                return True
         
     | 
| 
       3343 
3376 
     | 
    
         | 
| 
       3344 
3377 
     | 
    
         | 
| 
      
 3378 
     | 
    
         
            +
            ZMQ = {}
         
     | 
| 
      
 3379 
     | 
    
         
            +
            ZMQ_DESC = {
         
     | 
| 
      
 3380 
     | 
    
         
            +
                "pub": "fire-and-forget to all/any connected SUB-clients",
         
     | 
| 
      
 3381 
     | 
    
         
            +
                "push": "fire-and-forget to one of the connected PULL-clients",
         
     | 
| 
      
 3382 
     | 
    
         
            +
                "req": "send messages to a REP-server and blocking-wait for ack",
         
     | 
| 
      
 3383 
     | 
    
         
            +
            }
         
     | 
| 
      
 3384 
     | 
    
         
            +
             
     | 
| 
      
 3385 
     | 
    
         
            +
             
     | 
| 
      
 3386 
     | 
    
         
            +
            def _zmq_hook(
         
     | 
| 
      
 3387 
     | 
    
         
            +
                log ,
         
     | 
| 
      
 3388 
     | 
    
         
            +
                verbose ,
         
     | 
| 
      
 3389 
     | 
    
         
            +
                src ,
         
     | 
| 
      
 3390 
     | 
    
         
            +
                cmd ,
         
     | 
| 
      
 3391 
     | 
    
         
            +
                msg ,
         
     | 
| 
      
 3392 
     | 
    
         
            +
                wait ,
         
     | 
| 
      
 3393 
     | 
    
         
            +
                sp_ka  ,
         
     | 
| 
      
 3394 
     | 
    
         
            +
            )  :
         
     | 
| 
      
 3395 
     | 
    
         
            +
                import zmq
         
     | 
| 
      
 3396 
     | 
    
         
            +
             
     | 
| 
      
 3397 
     | 
    
         
            +
                try:
         
     | 
| 
      
 3398 
     | 
    
         
            +
                    mtx = ZMQ["mtx"]
         
     | 
| 
      
 3399 
     | 
    
         
            +
                except:
         
     | 
| 
      
 3400 
     | 
    
         
            +
                    ZMQ["mtx"] = threading.Lock()
         
     | 
| 
      
 3401 
     | 
    
         
            +
                    time.sleep(0.1)
         
     | 
| 
      
 3402 
     | 
    
         
            +
                    mtx = ZMQ["mtx"]
         
     | 
| 
      
 3403 
     | 
    
         
            +
             
     | 
| 
      
 3404 
     | 
    
         
            +
                ret = ""
         
     | 
| 
      
 3405 
     | 
    
         
            +
                t0 = time.time()
         
     | 
| 
      
 3406 
     | 
    
         
            +
                if verbose and log:
         
     | 
| 
      
 3407 
     | 
    
         
            +
                    log("hook(%s) %r entering zmq-main-lock" % (src, cmd), 6)
         
     | 
| 
      
 3408 
     | 
    
         
            +
             
     | 
| 
      
 3409 
     | 
    
         
            +
                with mtx:
         
     | 
| 
      
 3410 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 3411 
     | 
    
         
            +
                        mode, sck, mtx = ZMQ[cmd]
         
     | 
| 
      
 3412 
     | 
    
         
            +
                    except:
         
     | 
| 
      
 3413 
     | 
    
         
            +
                        mode, uri = cmd.split(":", 1)
         
     | 
| 
      
 3414 
     | 
    
         
            +
                        try:
         
     | 
| 
      
 3415 
     | 
    
         
            +
                            desc = ZMQ_DESC[mode]
         
     | 
| 
      
 3416 
     | 
    
         
            +
                            if log:
         
     | 
| 
      
 3417 
     | 
    
         
            +
                                t = "libzmq(%s) pyzmq(%s) init(%s); %s"
         
     | 
| 
      
 3418 
     | 
    
         
            +
                                log(t % (zmq.zmq_version(), zmq.__version__, cmd, desc))
         
     | 
| 
      
 3419 
     | 
    
         
            +
                        except:
         
     | 
| 
      
 3420 
     | 
    
         
            +
                            raise Exception("the only supported ZMQ modes are REQ PUB PUSH")
         
     | 
| 
      
 3421 
     | 
    
         
            +
             
     | 
| 
      
 3422 
     | 
    
         
            +
                        try:
         
     | 
| 
      
 3423 
     | 
    
         
            +
                            ctx = ZMQ["ctx"]
         
     | 
| 
      
 3424 
     | 
    
         
            +
                        except:
         
     | 
| 
      
 3425 
     | 
    
         
            +
                            ctx = ZMQ["ctx"] = zmq.Context()
         
     | 
| 
      
 3426 
     | 
    
         
            +
             
     | 
| 
      
 3427 
     | 
    
         
            +
                        timeout = sp_ka["timeout"]
         
     | 
| 
      
 3428 
     | 
    
         
            +
             
     | 
| 
      
 3429 
     | 
    
         
            +
                        if mode == "pub":
         
     | 
| 
      
 3430 
     | 
    
         
            +
                            sck = ctx.socket(zmq.PUB)
         
     | 
| 
      
 3431 
     | 
    
         
            +
                            sck.bind(uri)
         
     | 
| 
      
 3432 
     | 
    
         
            +
                            time.sleep(1)  # give clients time to connect; avoids losing first msg
         
     | 
| 
      
 3433 
     | 
    
         
            +
                        elif mode == "push":
         
     | 
| 
      
 3434 
     | 
    
         
            +
                            sck = ctx.socket(zmq.PUSH)
         
     | 
| 
      
 3435 
     | 
    
         
            +
                            sck.bind(uri)
         
     | 
| 
      
 3436 
     | 
    
         
            +
                            if timeout:
         
     | 
| 
      
 3437 
     | 
    
         
            +
                                sck.SNDTIMEO = int(timeout * 1000)
         
     | 
| 
      
 3438 
     | 
    
         
            +
                        elif mode == "req":
         
     | 
| 
      
 3439 
     | 
    
         
            +
                            sck = ctx.socket(zmq.REQ)
         
     | 
| 
      
 3440 
     | 
    
         
            +
                            sck.connect(uri)
         
     | 
| 
      
 3441 
     | 
    
         
            +
                            if timeout:
         
     | 
| 
      
 3442 
     | 
    
         
            +
                                sck.RCVTIMEO = int(timeout * 1000)
         
     | 
| 
      
 3443 
     | 
    
         
            +
                        else:
         
     | 
| 
      
 3444 
     | 
    
         
            +
                            raise Exception()
         
     | 
| 
      
 3445 
     | 
    
         
            +
             
     | 
| 
      
 3446 
     | 
    
         
            +
                        mtx = threading.Lock()
         
     | 
| 
      
 3447 
     | 
    
         
            +
                        ZMQ[cmd] = (mode, sck, mtx)
         
     | 
| 
      
 3448 
     | 
    
         
            +
             
     | 
| 
      
 3449 
     | 
    
         
            +
                if verbose and log:
         
     | 
| 
      
 3450 
     | 
    
         
            +
                    log("hook(%s) %r entering socket-lock" % (src, cmd), 6)
         
     | 
| 
      
 3451 
     | 
    
         
            +
             
     | 
| 
      
 3452 
     | 
    
         
            +
                with mtx:
         
     | 
| 
      
 3453 
     | 
    
         
            +
                    if verbose and log:
         
     | 
| 
      
 3454 
     | 
    
         
            +
                        log("hook(%s) %r sending |%d|" % (src, cmd, len(msg)), 6)
         
     | 
| 
      
 3455 
     | 
    
         
            +
             
     | 
| 
      
 3456 
     | 
    
         
            +
                    sck.send_string(msg)  # PUSH can safely timeout here
         
     | 
| 
      
 3457 
     | 
    
         
            +
             
     | 
| 
      
 3458 
     | 
    
         
            +
                    if mode == "req":
         
     | 
| 
      
 3459 
     | 
    
         
            +
                        if verbose and log:
         
     | 
| 
      
 3460 
     | 
    
         
            +
                            log("hook(%s) %r awaiting ack from req" % (src, cmd), 6)
         
     | 
| 
      
 3461 
     | 
    
         
            +
                        try:
         
     | 
| 
      
 3462 
     | 
    
         
            +
                            ret = sck.recv().decode("utf-8", "replace")
         
     | 
| 
      
 3463 
     | 
    
         
            +
                        except:
         
     | 
| 
      
 3464 
     | 
    
         
            +
                            sck.close()
         
     | 
| 
      
 3465 
     | 
    
         
            +
                            del ZMQ[cmd]  # bad state; must reset
         
     | 
| 
      
 3466 
     | 
    
         
            +
                            raise Exception("ack timeout; zmq socket killed")
         
     | 
| 
      
 3467 
     | 
    
         
            +
             
     | 
| 
      
 3468 
     | 
    
         
            +
                if ret and log:
         
     | 
| 
      
 3469 
     | 
    
         
            +
                    log("hook(%s) %r ACK: %r" % (src, cmd, ret), 6)
         
     | 
| 
      
 3470 
     | 
    
         
            +
             
     | 
| 
      
 3471 
     | 
    
         
            +
                if wait:
         
     | 
| 
      
 3472 
     | 
    
         
            +
                    wait -= time.time() - t0
         
     | 
| 
      
 3473 
     | 
    
         
            +
                    if wait > 0:
         
     | 
| 
      
 3474 
     | 
    
         
            +
                        time.sleep(wait)
         
     | 
| 
      
 3475 
     | 
    
         
            +
             
     | 
| 
      
 3476 
     | 
    
         
            +
                return ret
         
     | 
| 
      
 3477 
     | 
    
         
            +
             
     | 
| 
      
 3478 
     | 
    
         
            +
             
     | 
| 
       3345 
3479 
     | 
    
         
             
            def _runhook(
         
     | 
| 
       3346 
3480 
     | 
    
         
             
                log ,
         
     | 
| 
      
 3481 
     | 
    
         
            +
                verbose ,
         
     | 
| 
       3347 
3482 
     | 
    
         
             
                src ,
         
     | 
| 
       3348 
3483 
     | 
    
         
             
                cmd ,
         
     | 
| 
       3349 
3484 
     | 
    
         
             
                ap ,
         
     | 
| 
         @@ -3384,6 +3519,15 @@ def _runhook( 
     | 
|
| 
       3384 
3519 
     | 
    
         
             
                else:
         
     | 
| 
       3385 
3520 
     | 
    
         
             
                    arg = txt or ap
         
     | 
| 
       3386 
3521 
     | 
    
         | 
| 
      
 3522 
     | 
    
         
            +
                if acmd[0].startswith("zmq:"):
         
     | 
| 
      
 3523 
     | 
    
         
            +
                    zs = "zmq-error"
         
     | 
| 
      
 3524 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 3525 
     | 
    
         
            +
                        zs = _zmq_hook(log, verbose, src, acmd[0][4:].lower(), arg, wait, sp_ka)
         
     | 
| 
      
 3526 
     | 
    
         
            +
                    except Exception as ex:
         
     | 
| 
      
 3527 
     | 
    
         
            +
                        if log:
         
     | 
| 
      
 3528 
     | 
    
         
            +
                            log("zeromq failed: %r" % (ex,))
         
     | 
| 
      
 3529 
     | 
    
         
            +
                    return {"rc": 0, "stdout": zs}
         
     | 
| 
      
 3530 
     | 
    
         
            +
             
     | 
| 
       3387 
3531 
     | 
    
         
             
                acmd += [arg]
         
     | 
| 
       3388 
3532 
     | 
    
         
             
                if acmd[0].endswith(".py"):
         
     | 
| 
       3389 
3533 
     | 
    
         
             
                    acmd = [pybin] + acmd
         
     | 
| 
         @@ -3412,9 +3556,10 @@ def _runhook( 
     | 
|
| 
       3412 
3556 
     | 
    
         
             
                        except:
         
     | 
| 
       3413 
3557 
     | 
    
         
             
                            ret = {"rc": rc, "stdout": v}
         
     | 
| 
       3414 
3558 
     | 
    
         | 
| 
       3415 
     | 
    
         
            -
                wait 
     | 
| 
       3416 
     | 
    
         
            -
             
     | 
| 
       3417 
     | 
    
         
            -
                     
     | 
| 
      
 3559 
     | 
    
         
            +
                if wait:
         
     | 
| 
      
 3560 
     | 
    
         
            +
                    wait -= time.time() - t0
         
     | 
| 
      
 3561 
     | 
    
         
            +
                    if wait > 0:
         
     | 
| 
      
 3562 
     | 
    
         
            +
                        time.sleep(wait)
         
     | 
| 
       3418 
3563 
     | 
    
         | 
| 
       3419 
3564 
     | 
    
         
             
                return ret
         
     | 
| 
       3420 
3565 
     | 
    
         | 
| 
         @@ -3437,14 +3582,15 @@ def runhook( 
     | 
|
| 
       3437 
3582 
     | 
    
         
             
                txt ,
         
     | 
| 
       3438 
3583 
     | 
    
         
             
            )   :
         
     | 
| 
       3439 
3584 
     | 
    
         
             
                args = (broker or up2k).args
         
     | 
| 
      
 3585 
     | 
    
         
            +
                verbose = args.hook_v
         
     | 
| 
       3440 
3586 
     | 
    
         
             
                vp = vp.replace("\\", "/")
         
     | 
| 
       3441 
3587 
     | 
    
         
             
                ret = {"rc": 0}
         
     | 
| 
       3442 
3588 
     | 
    
         
             
                for cmd in cmds:
         
     | 
| 
       3443 
3589 
     | 
    
         
             
                    try:
         
     | 
| 
       3444 
3590 
     | 
    
         
             
                        hr = _runhook(
         
     | 
| 
       3445 
     | 
    
         
            -
                            log, src, cmd, ap, vp, host, uname, perms, mt, sz, ip, at, txt
         
     | 
| 
      
 3591 
     | 
    
         
            +
                            log, verbose, src, cmd, ap, vp, host, uname, perms, mt, sz, ip, at, txt
         
     | 
| 
       3446 
3592 
     | 
    
         
             
                        )
         
     | 
| 
       3447 
     | 
    
         
            -
                        if  
     | 
| 
      
 3593 
     | 
    
         
            +
                        if verbose and log:
         
     | 
| 
       3448 
3594 
     | 
    
         
             
                            log("hook(%s) %r => \033[32m%s" % (src, cmd, hr), 6)
         
     | 
| 
       3449 
3595 
     | 
    
         
             
                        if not hr:
         
     | 
| 
       3450 
3596 
     | 
    
         
             
                            return {}
         
     | 
    
        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 = " 
     | 
| 
      
 4 
     | 
    
         
            +
            S_VERSION = "2.8"
         
     | 
| 
      
 5 
     | 
    
         
            +
            S_BUILD_DT = "2025-01-21"
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            """
         
     | 
| 
       8 
8 
     | 
    
         
             
            u2c.py: upload to copyparty
         
     | 
| 
         @@ -1247,7 +1247,7 @@ class Ctl(object): 
     | 
|
| 
       1247 
1247 
     | 
    
         
             
                                    for n, zsii in enumerate(file.cids)
         
     | 
| 
       1248 
1248 
     | 
    
         
             
                                ]
         
     | 
| 
       1249 
1249 
     | 
    
         
             
                                print("chs: %s\n%s" % (vp, "\n".join(zsl)))
         
     | 
| 
       1250 
     | 
    
         
            -
                            zsl = [self.ar.wsalt, str(file.size)] + [x[0] for x in file. 
     | 
| 
      
 1250 
     | 
    
         
            +
                            zsl = [self.ar.wsalt, str(file.size)] + [x[0] for x in file.cids]
         
     | 
| 
       1251 
1251 
     | 
    
         
             
                            zb = hashlib.sha512("\n".join(zsl).encode("utf-8")).digest()[:33]
         
     | 
| 
       1252 
1252 
     | 
    
         
             
                            wark = ub64enc(zb).decode("utf-8")
         
     | 
| 
       1253 
1253 
     | 
    
         
             
                            if self.ar.jw:
         
     | 
    
        copyparty/web/browser.js.gz
    CHANGED
    
    | 
         Binary file 
     | 
    
        copyparty/web/splash.css.gz
    CHANGED
    
    | 
         Binary file 
     | 
    
        copyparty/web/svcs.html
    CHANGED
    
    | 
         @@ -9,7 +9,7 @@ 
     | 
|
| 
       9 
9 
     | 
    
         
             
            	<meta name="theme-color" content="#{{ tcolor }}">
         
     | 
| 
       10 
10 
     | 
    
         
             
            	<link rel="stylesheet" media="screen" href="{{ r }}/.cpr/splash.css?_={{ ts }}">
         
     | 
| 
       11 
11 
     | 
    
         
             
            	<link rel="stylesheet" media="screen" href="{{ r }}/.cpr/ui.css?_={{ ts }}">
         
     | 
| 
       12 
     | 
    
         
            -
            	<style>ul{padding-left:1.3em}li{margin:.4em 0}</style>
         
     | 
| 
      
 12 
     | 
    
         
            +
            	<style>ul{padding-left:1.3em}li{margin:.4em 0}.txa{float:right;margin:0 0 0 1em}</style>
         
     | 
| 
       13 
13 
     | 
    
         
             
            {{ html_head }}
         
     | 
| 
       14 
14 
     | 
    
         
             
            </head>
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
         @@ -31,15 +31,22 @@ 
     | 
|
| 
       31 
31 
     | 
    
         
             
                        <br />
         
     | 
| 
       32 
32 
     | 
    
         
             
                        <span class="os win lin mac">placeholders:</span>
         
     | 
| 
       33 
33 
     | 
    
         
             
                        <span class="os win">
         
     | 
| 
       34 
     | 
    
         
            -
                            {% if accs %}<code><b>{{ pw }}</b></code>=password, {% endif %}<code><b>W:</b></code>=mountpoint
         
     | 
| 
      
 34 
     | 
    
         
            +
                            {% if accs %}<code><b id="pw0">{{ pw }}</b></code>=password, {% endif %}<code><b>W:</b></code>=mountpoint
         
     | 
| 
       35 
35 
     | 
    
         
             
                        </span>
         
     | 
| 
       36 
36 
     | 
    
         
             
                        <span class="os lin mac">
         
     | 
| 
       37 
     | 
    
         
            -
                            {% if accs %}<code><b>{{ pw }}</b></code>=password, {% endif %}<code><b>mp</b></code>=mountpoint
         
     | 
| 
      
 37 
     | 
    
         
            +
                            {% if accs %}<code><b id="pw0">{{ pw }}</b></code>=password, {% endif %}<code><b>mp</b></code>=mountpoint
         
     | 
| 
       38 
38 
     | 
    
         
             
                        </span>
         
     | 
| 
      
 39 
     | 
    
         
            +
                        <a href="#" id="setpw">use real password</a>
         
     | 
| 
       39 
40 
     | 
    
         
             
                    </p>
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
42 
     | 
    
         | 
| 
       42 
43 
     | 
    
         | 
| 
      
 44 
     | 
    
         
            +
                    {% if args.idp_h_usr %}
         
     | 
| 
      
 45 
     | 
    
         
            +
                    <p style="line-height:2em"><b>WARNING:</b> this server is using IdP-based authentication, so this stuff may not work as advertised. Depending on server config, these commands can probably only be used to access areas which don't require authentication, unless you auth using any non-IdP accounts defined in the copyparty config. Please see <a href="https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients">the IdP docs</a></p>
         
     | 
| 
      
 46 
     | 
    
         
            +
                    {% endif %}
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
       43 
50 
     | 
    
         
             
                    {% if not args.no_dav %}
         
     | 
| 
       44 
51 
     | 
    
         
             
                    <h1>WebDAV</h1>
         
     | 
| 
       45 
52 
     | 
    
         | 
| 
         @@ -229,6 +236,60 @@ 
     | 
|
| 
       229 
236 
     | 
    
         | 
| 
       230 
237 
     | 
    
         | 
| 
       231 
238 
     | 
    
         | 
| 
      
 239 
     | 
    
         
            +
                    <div class="os win">
         
     | 
| 
      
 240 
     | 
    
         
            +
                        <h1>ShareX</h1>
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                        <p>to upload screenshots using ShareX <a href="https://github.com/ShareX/ShareX/releases/tag/v12.1.1">v12</a> or <a href="https://getsharex.com/">v15+</a>, save this as <code>copyparty.sxcu</code> and run it:</p>
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
                        <pre class="dl" name="copyparty.sxcu">
         
     | 
| 
      
 245 
     | 
    
         
            +
                            { "Name": "copyparty",
         
     | 
| 
      
 246 
     | 
    
         
            +
                            "RequestURL": "http{{ s }}://{{ ep }}/{{ rvp }}",
         
     | 
| 
      
 247 
     | 
    
         
            +
                            "Headers": {
         
     | 
| 
      
 248 
     | 
    
         
            +
                                {% if accs %}"pw": "<b>{{ pw }}</b>",{% endif %}
         
     | 
| 
      
 249 
     | 
    
         
            +
                                "accept": "url"
         
     | 
| 
      
 250 
     | 
    
         
            +
                            },
         
     | 
| 
      
 251 
     | 
    
         
            +
                            "DestinationType": "ImageUploader, TextUploader, FileUploader",
         
     | 
| 
      
 252 
     | 
    
         
            +
                            "FileFormName": "f" }
         
     | 
| 
      
 253 
     | 
    
         
            +
                        </pre>
         
     | 
| 
      
 254 
     | 
    
         
            +
                    </div>
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                    <div class="os mac">
         
     | 
| 
      
 259 
     | 
    
         
            +
                        <h1>ishare</h1>
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                        <p>to upload screenshots using <a href="https://isharemac.app/">ishare</a>, save this as <code>copyparty.iscu</code> and run it:</p>
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
                        <pre class="dl" name="copyparty.iscu">
         
     | 
| 
      
 264 
     | 
    
         
            +
                            { "Name": "copyparty",
         
     | 
| 
      
 265 
     | 
    
         
            +
                            "RequestURL": "http{{ s }}://{{ ep }}/{{ rvp }}",
         
     | 
| 
      
 266 
     | 
    
         
            +
                            "Headers": {
         
     | 
| 
      
 267 
     | 
    
         
            +
                                {% if accs %}"pw": "<b>{{ pw }}</b>",{% endif %}
         
     | 
| 
      
 268 
     | 
    
         
            +
                                "accept": "json"
         
     | 
| 
      
 269 
     | 
    
         
            +
                            },
         
     | 
| 
      
 270 
     | 
    
         
            +
                            "ResponseURL": "{{ '{{fileurl}}' }}",
         
     | 
| 
      
 271 
     | 
    
         
            +
                            "FileFormName": "f" }
         
     | 
| 
      
 272 
     | 
    
         
            +
                        </pre>
         
     | 
| 
      
 273 
     | 
    
         
            +
                    </div>
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
                    <div class="os lin">
         
     | 
| 
      
 278 
     | 
    
         
            +
                        <h1>flameshot</h1>
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
                        <p>to upload screenshots using <a href="https://flameshot.org/">flameshot</a>, save this as <code>flameshot.sh</code> and run it:</p>
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                        <pre class="dl" name="flameshot.sh">
         
     | 
| 
      
 283 
     | 
    
         
            +
                            #!/bin/bash
         
     | 
| 
      
 284 
     | 
    
         
            +
                            pw="<b>{{ pw }}</b>"
         
     | 
| 
      
 285 
     | 
    
         
            +
                            url="http{{ s }}://{{ ep }}/{{ rvp }}"
         
     | 
| 
      
 286 
     | 
    
         
            +
                            filename="$(date +%Y-%m%d-%H%M%S).png"
         
     | 
| 
      
 287 
     | 
    
         
            +
                            flameshot gui -s -r | curl -sT- "$url$filename?want=url&pw=$pw" | xsel -ib
         
     | 
| 
      
 288 
     | 
    
         
            +
                        </pre>
         
     | 
| 
      
 289 
     | 
    
         
            +
                    </div>
         
     | 
| 
      
 290 
     | 
    
         
            +
             
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
       232 
293 
     | 
    
         
             
                </div>
         
     | 
| 
       233 
294 
     | 
    
         
             
            	<a href="#" id="repl">π</a>
         
     | 
| 
       234 
295 
     | 
    
         
             
            	<script>
         
     | 
    
        copyparty/web/svcs.js.gz
    CHANGED
    
    | 
         Binary file 
     | 
    
        copyparty/web/ui.css.gz
    CHANGED
    
    | 
         Binary file 
     | 
    
        copyparty/web/up2k.js.gz
    CHANGED
    
    | 
         Binary file 
     | 
    
        copyparty/web/util.js.gz
    CHANGED
    
    | 
         Binary file 
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            Metadata-Version: 2. 
     | 
| 
      
 1 
     | 
    
         
            +
            Metadata-Version: 2.2
         
     | 
| 
       2 
2 
     | 
    
         
             
            Name: copyparty
         
     | 
| 
       3 
     | 
    
         
            -
            Version: 1.16. 
     | 
| 
      
 3 
     | 
    
         
            +
            Version: 1.16.9
         
     | 
| 
       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
         
     | 
| 
         @@ -52,6 +52,8 @@ Provides-Extra: tftpd 
     | 
|
| 
       52 
52 
     | 
    
         
             
            Requires-Dist: partftpy>=0.4.0; extra == "tftpd"
         
     | 
| 
       53 
53 
     | 
    
         
             
            Provides-Extra: pwhash
         
     | 
| 
       54 
54 
     | 
    
         
             
            Requires-Dist: argon2-cffi; extra == "pwhash"
         
     | 
| 
      
 55 
     | 
    
         
            +
            Provides-Extra: zeromq
         
     | 
| 
      
 56 
     | 
    
         
            +
            Requires-Dist: pyzmq; extra == "zeromq"
         
     | 
| 
       55 
57 
     | 
    
         | 
| 
       56 
58 
     | 
    
         
             
            <img src="https://github.com/9001/copyparty/raw/hovudstraum/docs/logo.svg" width="250" align="right"/>
         
     | 
| 
       57 
59 
     | 
    
         | 
| 
         @@ -135,6 +137,7 @@ turn almost any device into a file server with resumable uploads/downloads using 
     | 
|
| 
       135 
137 
     | 
    
         
             
                * [metadata from audio files](#metadata-from-audio-files) - set `-e2t` to index tags on upload
         
     | 
| 
       136 
138 
     | 
    
         
             
                * [file parser plugins](#file-parser-plugins) - provide custom parsers to index additional tags
         
     | 
| 
       137 
139 
     | 
    
         
             
                * [event hooks](#event-hooks) - trigger a program on uploads, renames etc ([examples](./bin/hooks/))
         
     | 
| 
      
 140 
     | 
    
         
            +
                    * [zeromq](#zeromq) - event-hooks can send zeromq messages
         
     | 
| 
       138 
141 
     | 
    
         
             
                    * [upload events](#upload-events) - the older, more powerful approach ([examples](./bin/mtag/))
         
     | 
| 
       139 
142 
     | 
    
         
             
                * [handlers](#handlers) - redefine behavior with plugins ([examples](./bin/handlers/))
         
     | 
| 
       140 
143 
     | 
    
         
             
                * [ip auth](#ip-auth) - autologin based on IP range (CIDR)
         
     | 
| 
         @@ -147,6 +150,7 @@ turn almost any device into a file server with resumable uploads/downloads using 
     | 
|
| 
       147 
150 
     | 
    
         
             
                * [listen on port 80 and 443](#listen-on-port-80-and-443) - become a *real* webserver
         
     | 
| 
       148 
151 
     | 
    
         
             
                * [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
         
     | 
| 
       149 
152 
     | 
    
         
             
                    * [real-ip](#real-ip) - teaching copyparty how to see client IPs
         
     | 
| 
      
 153 
     | 
    
         
            +
                    * [reverse-proxy performance](#reverse-proxy-performance)
         
     | 
| 
       150 
154 
     | 
    
         
             
                * [prometheus](#prometheus) - metrics/stats can be enabled
         
     | 
| 
       151 
155 
     | 
    
         
             
                * [other extremely specific features](#other-extremely-specific-features) - you'll never find a use for these
         
     | 
| 
       152 
156 
     | 
    
         
             
                    * [custom mimetypes](#custom-mimetypes) - change the association of a file extension
         
     | 
| 
         @@ -195,6 +199,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/ 
     | 
|
| 
       195 
199 
     | 
    
         
             
            * or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
         
     | 
| 
       196 
200 
     | 
    
         
             
            * or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
         
     | 
| 
       197 
201 
     | 
    
         
             
            * or if you are on android, [install copyparty in termux](#install-on-android)
         
     | 
| 
      
 202 
     | 
    
         
            +
            * or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
         
     | 
| 
       198 
203 
     | 
    
         
             
            * or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
         
     | 
| 
       199 
204 
     | 
    
         
             
            * or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
         
     | 
| 
       200 
205 
     | 
    
         
             
              * docker has all deps built-in, so skip this step:
         
     | 
| 
         @@ -668,8 +673,8 @@ select which type of archive you want in the `[⚙️] config` tab: 
     | 
|
| 
       668 
673 
     | 
    
         
             
            | `pax` | `?tar=pax` | pax-format tar, futureproof, not as fast |
         
     | 
| 
       669 
674 
     | 
    
         
             
            | `tgz` | `?tar=gz` | gzip compressed gnu-tar (slow), for `curl \| tar -xvz` |
         
     | 
| 
       670 
675 
     | 
    
         
             
            | `txz` | `?tar=xz` | gnu-tar with xz / lzma compression (v.slow) |
         
     | 
| 
       671 
     | 
    
         
            -
            | `zip` | `?zip 
     | 
| 
       672 
     | 
    
         
            -
            | `zip_dos` | `?zip` | traditional cp437 (no unicode) to fix glitchy filenames |
         
     | 
| 
      
 676 
     | 
    
         
            +
            | `zip` | `?zip` | works everywhere, glitchy filenames on win7 and older |
         
     | 
| 
      
 677 
     | 
    
         
            +
            | `zip_dos` | `?zip=dos` | traditional cp437 (no unicode) to fix glitchy filenames |
         
     | 
| 
       673 
678 
     | 
    
         
             
            | `zip_crc` | `?zip=crc` | cp437 with crc32 computed early for truly ancient software |
         
     | 
| 
       674 
679 
     | 
    
         | 
| 
       675 
680 
     | 
    
         
             
            * gzip default level is `3` (0=fast, 9=best), change with `?tar=gz:9`
         
     | 
| 
         @@ -677,7 +682,7 @@ select which type of archive you want in the `[⚙️] config` tab: 
     | 
|
| 
       677 
682 
     | 
    
         
             
            * bz2 default level is `2` (1=fast, 9=best), change with `?tar=bz2:9`
         
     | 
| 
       678 
683 
     | 
    
         
             
            * hidden files ([dotfiles](#dotfiles)) are excluded unless account is allowed to list them
         
     | 
| 
       679 
684 
     | 
    
         
             
              * `up2k.db` and `dir.txt` is always excluded
         
     | 
| 
       680 
     | 
    
         
            -
            * bsdtar supports streaming unzipping: `curl foo?zip 
     | 
| 
      
 685 
     | 
    
         
            +
            * bsdtar supports streaming unzipping: `curl foo?zip | bsdtar -xv`
         
     | 
| 
       681 
686 
     | 
    
         
             
              * good, because copyparty's zip is faster than tar on small files
         
     | 
| 
       682 
687 
     | 
    
         
             
            * `zip_crc` will take longer to download since the server has to read each file twice
         
     | 
| 
       683 
688 
     | 
    
         
             
              * this is only to support MS-DOS PKZIP v2.04g (october 1993) and older
         
     | 
| 
         @@ -701,7 +706,7 @@ dragdrop is the recommended way, but you may also: 
     | 
|
| 
       701 
706 
     | 
    
         | 
| 
       702 
707 
     | 
    
         
             
            * select some files (not folders) in your file explorer and press CTRL-V inside the browser window
         
     | 
| 
       703 
708 
     | 
    
         
             
            * use the [command-line uploader](https://github.com/9001/copyparty/tree/hovudstraum/bin#u2cpy)
         
     | 
| 
       704 
     | 
    
         
            -
            * upload using [curl  
     | 
| 
      
 709 
     | 
    
         
            +
            * upload using [curl, sharex, ishare, ...](#client-examples)
         
     | 
| 
       705 
710 
     | 
    
         | 
| 
       706 
711 
     | 
    
         
             
            when uploading files through dragdrop or CTRL-V, this initiates an upload using `up2k`; there are two browser-based uploaders available:
         
     | 
| 
       707 
712 
     | 
    
         
             
            * `[🎈] bup`, the basic uploader, supports almost every browser since netscape 4.0
         
     | 
| 
         @@ -1159,6 +1164,8 @@ on macos, connect from finder: 
     | 
|
| 
       1159 
1164 
     | 
    
         | 
| 
       1160 
1165 
     | 
    
         
             
            in order to grant full write-access to webdav clients, the volflag `daw` must be set and the account must also have delete-access (otherwise the client won't be allowed to replace the contents of existing files, which is how webdav works)
         
     | 
| 
       1161 
1166 
     | 
    
         | 
| 
      
 1167 
     | 
    
         
            +
            > note: if you have enabled [IdP authentication](#identity-providers) then that may cause issues for some/most webdav clients; see [the webdav section in the IdP docs](https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients)
         
     | 
| 
      
 1168 
     | 
    
         
            +
             
     | 
| 
       1162 
1169 
     | 
    
         | 
| 
       1163 
1170 
     | 
    
         
             
            ### connecting to webdav from windows
         
     | 
| 
       1164 
1171 
     | 
    
         | 
| 
         @@ -1509,6 +1516,23 @@ there's a bunch of flags and stuff, see `--help-hooks` 
     | 
|
| 
       1509 
1516 
     | 
    
         
             
            if you want to write your own hooks, see [devnotes](./docs/devnotes.md#event-hooks)
         
     | 
| 
       1510 
1517 
     | 
    
         | 
| 
       1511 
1518 
     | 
    
         | 
| 
      
 1519 
     | 
    
         
            +
            ### zeromq
         
     | 
| 
      
 1520 
     | 
    
         
            +
             
     | 
| 
      
 1521 
     | 
    
         
            +
            event-hooks can send zeromq messages  instead of running programs
         
     | 
| 
      
 1522 
     | 
    
         
            +
             
     | 
| 
      
 1523 
     | 
    
         
            +
            to send a 0mq message every time a file is uploaded,
         
     | 
| 
      
 1524 
     | 
    
         
            +
             
     | 
| 
      
 1525 
     | 
    
         
            +
            * `--xau zmq:pub:tcp://*:5556` sends a PUB to any/all connected SUB clients
         
     | 
| 
      
 1526 
     | 
    
         
            +
            * `--xau t3,zmq:push:tcp://*:5557` sends a PUSH to exactly one connected PULL client
         
     | 
| 
      
 1527 
     | 
    
         
            +
            * `--xau t3,j,zmq:req:tcp://localhost:5555` sends a REQ to the connected REP client
         
     | 
| 
      
 1528 
     | 
    
         
            +
             
     | 
| 
      
 1529 
     | 
    
         
            +
            the PUSH and REQ examples have `t3` (timeout after 3 seconds) because they block if there's no clients to talk to
         
     | 
| 
      
 1530 
     | 
    
         
            +
             
     | 
| 
      
 1531 
     | 
    
         
            +
            * the REQ example does `t3,j` to send extended upload-info as json instead of just the filesystem-path
         
     | 
| 
      
 1532 
     | 
    
         
            +
             
     | 
| 
      
 1533 
     | 
    
         
            +
            see [zmq-recv.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/zmq-recv.py) if you need something to receive the messages with
         
     | 
| 
      
 1534 
     | 
    
         
            +
             
     | 
| 
      
 1535 
     | 
    
         
            +
             
     | 
| 
       1512 
1536 
     | 
    
         
             
            ### upload events
         
     | 
| 
       1513 
1537 
     | 
    
         | 
| 
       1514 
1538 
     | 
    
         
             
            the older, more powerful approach ([examples](./bin/mtag/)):
         
     | 
| 
         @@ -1596,12 +1620,16 @@ connecting to an aws s3 bucket and similar 
     | 
|
| 
       1596 
1620 
     | 
    
         | 
| 
       1597 
1621 
     | 
    
         
             
            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
         
     | 
| 
       1598 
1622 
     | 
    
         | 
| 
       1599 
     | 
    
         
            -
            you  
     | 
| 
      
 1623 
     | 
    
         
            +
            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
         
     | 
| 
      
 1624 
     | 
    
         
            +
             
     | 
| 
      
 1625 
     | 
    
         
            +
            > 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)
         
     | 
| 
       1600 
1626 
     | 
    
         | 
| 
       1601 
1627 
     | 
    
         
             
            someone has also tested geesefs in combination with [gocryptfs](https://nuetzlich.net/gocryptfs/) with surprisingly good results, getting 60 MiB/s upload speeds on a gbit line, but JuiceFS won with 80 MiB/s using its built-in encryption
         
     | 
| 
       1602 
1628 
     | 
    
         | 
| 
       1603 
1629 
     | 
    
         
             
            you may improve performance by specifying larger values for `--iobuf` / `--s-rd-sz` / `--s-wr-sz`
         
     | 
| 
       1604 
1630 
     | 
    
         | 
| 
      
 1631 
     | 
    
         
            +
            > if you've experimented with this and made interesting observations, please share your findings so we can add a section with specific recommendations :-)
         
     | 
| 
      
 1632 
     | 
    
         
            +
             
     | 
| 
       1605 
1633 
     | 
    
         | 
| 
       1606 
1634 
     | 
    
         
             
            ## hiding from google
         
     | 
| 
       1607 
1635 
     | 
    
         | 
| 
         @@ -1724,10 +1752,16 @@ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatical 
     | 
|
| 
       1724 
1752 
     | 
    
         | 
| 
       1725 
1753 
     | 
    
         
             
            for improved security (and a 10% performance boost) consider listening on a unix-socket with `-i unix:770:www:/tmp/party.sock` (permission `770` means only members of group `www` can access it)
         
     | 
| 
       1726 
1754 
     | 
    
         | 
| 
       1727 
     | 
    
         
            -
            example webserver configs:
         
     | 
| 
      
 1755 
     | 
    
         
            +
            example webserver / reverse-proxy configs:
         
     | 
| 
       1728 
1756 
     | 
    
         | 
| 
       1729 
     | 
    
         
            -
            * [ 
     | 
| 
       1730 
     | 
    
         
            -
            *  
     | 
| 
      
 1757 
     | 
    
         
            +
            * [apache config](contrib/apache/copyparty.conf)
         
     | 
| 
      
 1758 
     | 
    
         
            +
            * caddy uds: `caddy reverse-proxy --from :8080 --to unix///dev/shm/party.sock`
         
     | 
| 
      
 1759 
     | 
    
         
            +
            * caddy tcp: `caddy reverse-proxy --from :8081 --to http://127.0.0.1:3923`
         
     | 
| 
      
 1760 
     | 
    
         
            +
            * [haproxy config](contrib/haproxy/copyparty.conf)
         
     | 
| 
      
 1761 
     | 
    
         
            +
            * [lighttpd subdomain](contrib/lighttpd/subdomain.conf) -- entire domain/subdomain
         
     | 
| 
      
 1762 
     | 
    
         
            +
            * [lighttpd subpath](contrib/lighttpd/subpath.conf) -- location-based (not optimal, but in case you need it)
         
     | 
| 
      
 1763 
     | 
    
         
            +
            * [nginx config](contrib/nginx/copyparty.conf) -- recommended
         
     | 
| 
      
 1764 
     | 
    
         
            +
            * [traefik config](contrib/traefik/copyparty.yaml)
         
     | 
| 
       1731 
1765 
     | 
    
         | 
| 
       1732 
1766 
     | 
    
         | 
| 
       1733 
1767 
     | 
    
         
             
            ### real-ip
         
     | 
| 
         @@ -1739,6 +1773,38 @@ if you (and maybe everybody else) keep getting a message that says `thank you fo 
     | 
|
| 
       1739 
1773 
     | 
    
         
             
            for most common setups, there should be a helpful message in the server-log explaining what to do, but see [docs/xff.md](docs/xff.md) if you want to learn more, including a quick hack to **just make it work** (which is **not** recommended, but hey...)
         
     | 
| 
       1740 
1774 
     | 
    
         | 
| 
       1741 
1775 
     | 
    
         | 
| 
      
 1776 
     | 
    
         
            +
            ### reverse-proxy performance
         
     | 
| 
      
 1777 
     | 
    
         
            +
             
     | 
| 
      
 1778 
     | 
    
         
            +
            most reverse-proxies support connecting to copyparty either using uds/unix-sockets (`/dev/shm/party.sock`, faster/recommended) or using tcp (`127.0.0.1`)
         
     | 
| 
      
 1779 
     | 
    
         
            +
             
     | 
| 
      
 1780 
     | 
    
         
            +
            with copyparty listening on a uds / unix-socket / unix-domain-socket and the reverse-proxy connecting to that:
         
     | 
| 
      
 1781 
     | 
    
         
            +
             
     | 
| 
      
 1782 
     | 
    
         
            +
            | index.html   | upload      | download    | software |
         
     | 
| 
      
 1783 
     | 
    
         
            +
            | ------------ | ----------- | ----------- | -------- |
         
     | 
| 
      
 1784 
     | 
    
         
            +
            | 28'900 req/s | 6'900 MiB/s | 7'400 MiB/s | no-proxy |
         
     | 
| 
      
 1785 
     | 
    
         
            +
            | 18'750 req/s | 3'500 MiB/s | 2'370 MiB/s | haproxy |
         
     | 
| 
      
 1786 
     | 
    
         
            +
            |  9'900 req/s | 3'750 MiB/s | 2'200 MiB/s | caddy |
         
     | 
| 
      
 1787 
     | 
    
         
            +
            | 18'700 req/s | 2'200 MiB/s | 1'570 MiB/s | nginx |
         
     | 
| 
      
 1788 
     | 
    
         
            +
            |  9'700 req/s | 1'750 MiB/s | 1'830 MiB/s | apache |
         
     | 
| 
      
 1789 
     | 
    
         
            +
            |  9'900 req/s | 1'300 MiB/s | 1'470 MiB/s | lighttpd |
         
     | 
| 
      
 1790 
     | 
    
         
            +
             
     | 
| 
      
 1791 
     | 
    
         
            +
            when connecting the reverse-proxy to `127.0.0.1` instead (the basic and/or old-fasioned way), speeds are a bit worse:
         
     | 
| 
      
 1792 
     | 
    
         
            +
             
     | 
| 
      
 1793 
     | 
    
         
            +
            | index.html   | upload      | download    | software |
         
     | 
| 
      
 1794 
     | 
    
         
            +
            | ------------ | ----------- | ----------- | -------- |
         
     | 
| 
      
 1795 
     | 
    
         
            +
            | 21'200 req/s | 5'700 MiB/s | 6'700 MiB/s | no-proxy |
         
     | 
| 
      
 1796 
     | 
    
         
            +
            | 14'500 req/s | 1'700 MiB/s | 2'170 MiB/s | haproxy |
         
     | 
| 
      
 1797 
     | 
    
         
            +
            | 11'100 req/s | 2'750 MiB/s | 2'000 MiB/s | traefik |
         
     | 
| 
      
 1798 
     | 
    
         
            +
            |  8'400 req/s | 2'300 MiB/s | 1'950 MiB/s | caddy |
         
     | 
| 
      
 1799 
     | 
    
         
            +
            | 13'400 req/s | 1'100 MiB/s | 1'480 MiB/s | nginx |
         
     | 
| 
      
 1800 
     | 
    
         
            +
            |  8'400 req/s | 1'000 MiB/s | 1'000 MiB/s | apache |
         
     | 
| 
      
 1801 
     | 
    
         
            +
            |  6'500 req/s | 1'270 MiB/s | 1'500 MiB/s | lighttpd |
         
     | 
| 
      
 1802 
     | 
    
         
            +
             
     | 
| 
      
 1803 
     | 
    
         
            +
            in summary, `haproxy > caddy > traefik > nginx > apache > lighttpd`, and use uds when possible (traefik does not support it yet)
         
     | 
| 
      
 1804 
     | 
    
         
            +
             
     | 
| 
      
 1805 
     | 
    
         
            +
            * if these results are bullshit because my config exampels are bad, please submit corrections!
         
     | 
| 
      
 1806 
     | 
    
         
            +
             
     | 
| 
      
 1807 
     | 
    
         
            +
             
     | 
| 
       1742 
1808 
     | 
    
         
             
            ## prometheus
         
     | 
| 
       1743 
1809 
     | 
    
         | 
| 
       1744 
1810 
     | 
    
         
             
            metrics/stats can be enabled  at URL `/.cpr/metrics` for grafana / prometheus / etc (openmetrics 1.0.0)
         
     | 
| 
         @@ -2052,7 +2118,8 @@ interact with copyparty using non-browser clients 
     | 
|
| 
       2052 
2118 
     | 
    
         
             
              * can be downloaded from copyparty: controlpanel -> connect -> [partyfuse.py](http://127.0.0.1:3923/.cpr/a/partyfuse.py)
         
     | 
| 
       2053 
2119 
     | 
    
         
             
              * [rclone](https://rclone.org/) as client can give ~5x performance, see [./docs/rclone.md](docs/rclone.md)
         
     | 
| 
       2054 
2120 
     | 
    
         | 
| 
       2055 
     | 
    
         
            -
            * sharex (screenshot utility): see [./contrib/sharex.sxcu](contrib/#sharexsxcu)
         
     | 
| 
      
 2121 
     | 
    
         
            +
            * sharex (screenshot utility): see [./contrib/sharex.sxcu](./contrib/#sharexsxcu)
         
     | 
| 
      
 2122 
     | 
    
         
            +
              * and for screenshots on macos, see [./contrib/ishare.iscu](./contrib/#ishareiscu)
         
     | 
| 
       2056 
2123 
     | 
    
         
             
              * and for screenshots on linux, see [./contrib/flameshot.sh](./contrib/flameshot.sh)
         
     | 
| 
       2057 
2124 
     | 
    
         | 
| 
       2058 
2125 
     | 
    
         
             
            * contextlet (web browser integration); see [contrib contextlet](contrib/#send-to-cppcontextletjson)
         
     | 
| 
         @@ -2316,13 +2383,13 @@ mandatory deps: 
     | 
|
| 
       2316 
2383 
     | 
    
         | 
| 
       2317 
2384 
     | 
    
         
             
            install these to enable bonus features
         
     | 
| 
       2318 
2385 
     | 
    
         | 
| 
       2319 
     | 
    
         
            -
            enable hashed passwords in config: `argon2-cffi`
         
     | 
| 
      
 2386 
     | 
    
         
            +
            enable [hashed passwords](#password-hashing) in config: `argon2-cffi`
         
     | 
| 
       2320 
2387 
     | 
    
         | 
| 
       2321 
     | 
    
         
            -
            enable ftp-server:
         
     | 
| 
      
 2388 
     | 
    
         
            +
            enable [ftp-server](#ftp-server):
         
     | 
| 
       2322 
2389 
     | 
    
         
             
            * for just plaintext FTP, `pyftpdlib` (is built into the SFX)
         
     | 
| 
       2323 
2390 
     | 
    
         
             
            * with TLS encryption, `pyftpdlib pyopenssl`
         
     | 
| 
       2324 
2391 
     | 
    
         | 
| 
       2325 
     | 
    
         
            -
            enable music tags:
         
     | 
| 
      
 2392 
     | 
    
         
            +
            enable [music tags](#metadata-from-audio-files):
         
     | 
| 
       2326 
2393 
     | 
    
         
             
            * either `mutagen` (fast, pure-python, skips a few tags, makes copyparty GPL? idk)
         
     | 
| 
       2327 
2394 
     | 
    
         
             
            * or `ffprobe` (20x slower, more accurate, possibly dangerous depending on your distro and users)
         
     | 
| 
       2328 
2395 
     | 
    
         | 
| 
         @@ -2333,8 +2400,9 @@ enable [thumbnails](#thumbnails) of... 
     | 
|
| 
       2333 
2400 
     | 
    
         
             
            * **AVIF pictures:** `pyvips` or `ffmpeg` or `pillow-avif-plugin`
         
     | 
| 
       2334 
2401 
     | 
    
         
             
            * **JPEG XL pictures:** `pyvips` or `ffmpeg`
         
     | 
| 
       2335 
2402 
     | 
    
         | 
| 
       2336 
     | 
    
         
            -
            enable [ 
     | 
| 
       2337 
     | 
    
         
            -
             
     | 
| 
      
 2403 
     | 
    
         
            +
            enable sending [zeromq messages](#zeromq) from event-hooks: `pyzmq`
         
     | 
| 
      
 2404 
     | 
    
         
            +
             
     | 
| 
      
 2405 
     | 
    
         
            +
            enable [smb](#smb-server) support (**not** recommended): `impacket==0.12.0`
         
     | 
| 
       2338 
2406 
     | 
    
         | 
| 
       2339 
2407 
     | 
    
         
             
            `pyvips` gives higher quality thumbnails than `Pillow` and is 320% faster, using 270% more ram: `sudo apt install libvips42 && python3 -m pip install --user -U pyvips`
         
     | 
| 
       2340 
2408 
     | 
    
         |