Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c01cad091e | ||
|
|
eb349f339c | ||
|
|
24d8caaf3e | ||
|
|
5ac2c20959 | ||
|
|
bb72e6bf30 | ||
|
|
d8142e866a | ||
|
|
7b7979fd61 | ||
|
|
749616d09d | ||
|
|
5485c6d7ca | ||
|
|
b7aea38d77 | ||
|
|
0ecd9f99e6 | ||
|
|
ca04a00662 | ||
|
|
8a09601be8 | ||
|
|
1fe0d4693e | ||
|
|
bba8a3c6bc | ||
|
|
e3d7f0c7d5 | ||
|
|
be7bb71bbc | ||
|
|
e0c4829ec6 | ||
|
|
5af1575329 | ||
|
|
884f966b86 | ||
|
|
f6c6fbc223 |
84
README.md
84
README.md
@@ -1,29 +1,16 @@
|
||||
# 💾🎉 copyparty
|
||||
|
||||
* portable file sharing hub (py2/py3) [(on PyPI)](https://pypi.org/project/copyparty/)
|
||||
* MIT-Licensed, 2019-05-26, ed @ irc.rizon.net
|
||||
turn almost any device into a file server with resumable uploads/downloads using [*any*](#browser-support) web browser
|
||||
|
||||
* server only needs Python (2 or 3), all dependencies optional
|
||||
* 🔌 protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
|
||||
* 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
|
||||
|
||||
## summary
|
||||
|
||||
turn your phone or raspi into a portable file server with resumable uploads/downloads using *any* web browser
|
||||
|
||||
* server only needs Python (`2.7` or `3.3+`), all dependencies optional
|
||||
* browse/upload with [IE4](#browser-support) / netscape4.0 on win3.11 (heh)
|
||||
* protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
|
||||
|
||||
try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
|
||||
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
|
||||
|
||||
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
||||
|
||||
|
||||
## get the app
|
||||
|
||||
<a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
|
||||
|
||||
(the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet)
|
||||
|
||||
|
||||
## readme toc
|
||||
|
||||
* top
|
||||
@@ -82,12 +69,16 @@ try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running fro
|
||||
* [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
|
||||
* [browser support](#browser-support) - TLDR: yes
|
||||
* [client examples](#client-examples) - interact with copyparty using non-browser clients
|
||||
* [folder sync](#folder-sync) - sync folders to/from copyparty
|
||||
* [mount as drive](#mount-as-drive) - a remote copyparty server as a local filesystem
|
||||
* [android app](#android-app) - upload to copyparty with one tap
|
||||
* [iOS shortcuts](#iOS-shortcuts) - there is no iPhone app, but
|
||||
* [performance](#performance) - defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
||||
* [client-side](#client-side) - when uploading files
|
||||
* [security](#security) - some notes on hardening
|
||||
* [gotchas](#gotchas) - behavior that might be unexpected
|
||||
* [cors](#cors) - cross-site request config
|
||||
* [https](#https) - both HTTP and HTTPS are accepted
|
||||
* [recovering from crashes](#recovering-from-crashes)
|
||||
* [client crashes](#client-crashes)
|
||||
* [frefox wsod](#frefox-wsod) - firefox 87 can crash during uploads
|
||||
@@ -108,6 +99,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
|
||||
|
||||
* or install through pypi (python3 only): `python3 -m pip install --user -U copyparty`
|
||||
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
||||
* or if you are on android, [install copyparty in termux](#install-on-android)
|
||||
* or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
|
||||
* docker has all deps built-in, so skip this step:
|
||||
|
||||
@@ -165,11 +157,15 @@ firewall-cmd --reload
|
||||
* ☑ [smb/cifs server](#smb-server)
|
||||
* ☑ [qr-code](#qr-code) for quick access
|
||||
* ☑ [upnp / zeroconf / mdns / ssdp](#zeroconf)
|
||||
* ☑ [event hooks](#event-hooks) / script runner
|
||||
* ☑ [reverse-proxy support](https://github.com/9001/copyparty#reverse-proxy)
|
||||
* upload
|
||||
* ☑ basic: plain multipart, ie6 support
|
||||
* ☑ [up2k](#uploading): js, resumable, multithreaded
|
||||
* unaffected by cloudflare's max-upload-size (100 MiB)
|
||||
* ☑ stash: simple PUT filedropper
|
||||
* ☑ filename randomizer
|
||||
* ☑ write-only folders
|
||||
* ☑ [unpost](#unpost): undo/delete accidental uploads
|
||||
* ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
|
||||
* ☑ symlink/discard existing files (content-matching)
|
||||
@@ -193,10 +189,15 @@ firewall-cmd --reload
|
||||
* ☑ [locate files by contents](#file-search)
|
||||
* ☑ search by name/path/date/size
|
||||
* ☑ [search by ID3-tags etc.](#searching)
|
||||
* client support
|
||||
* ☑ [folder sync](#folder-sync)
|
||||
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
||||
* markdown
|
||||
* ☑ [viewer](#markdown-viewer)
|
||||
* ☑ editor (sure why not)
|
||||
|
||||
PS: something missing? post any crazy ideas you've got as a [feature request](https://github.com/9001/copyparty/issues/new?assignees=9001&labels=enhancement&template=feature_request.md) or [discussion](https://github.com/9001/copyparty/discussions/new?category=ideas) 🤙
|
||||
|
||||
|
||||
## testimonials
|
||||
|
||||
@@ -268,7 +269,7 @@ server notes:
|
||||
|
||||
* iPhones: the volume control doesn't work because [apple doesn't want it to](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW11)
|
||||
* *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
|
||||
* "future" because `AudioContext` is broken in the current iOS version (15.1), maybe one day...
|
||||
* "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
|
||||
|
||||
* Windows: folders cannot be accessed if the name ends with `.`
|
||||
* python or windows bug
|
||||
@@ -1092,13 +1093,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
|
||||
|
||||
## reverse-proxy
|
||||
|
||||
running copyparty next to other websites hosted on an existing webserver such as nginx or apache
|
||||
running copyparty next to other websites hosted on an existing webserver such as nginx, caddy, or apache
|
||||
|
||||
you can either:
|
||||
* give copyparty its own domain or subdomain (recommended)
|
||||
* or do location-based proxying, using `--rp-loc=/stuff` to tell copyparty where it is mounted -- has a slight performance cost and higher chance of bugs
|
||||
* if copyparty says `incorrect --rp-loc or webserver config; expected vpath starting with [...]` it's likely because the webserver is stripping away the proxy location from the request URLs -- see the `ProxyPass` in the apache example below
|
||||
|
||||
some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatically obtain a valid https/tls certificate for you, and some support HTTP/2 and QUIC which could be a nice speed boost
|
||||
|
||||
example webserver configs:
|
||||
|
||||
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
||||
@@ -1176,7 +1179,7 @@ interact with copyparty using non-browser clients
|
||||
* `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
|
||||
|
||||
* python: [up2k.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) is a command-line up2k client [(webm)](https://ocv.me/stuff/u2cli.webm)
|
||||
* file uploads, file-search, folder sync, autoresume of aborted/broken uploads
|
||||
* file uploads, file-search, [folder sync](#folder-sync), autoresume of aborted/broken uploads
|
||||
* can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
|
||||
* see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
|
||||
|
||||
@@ -1197,6 +1200,15 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
|
||||
NOTE: curl will not send the original filename if you use `-T` combined with url-params! Also, make sure to always leave a trailing slash in URLs unless you want to override the filename
|
||||
|
||||
|
||||
## folder sync
|
||||
|
||||
sync folders to/from copyparty
|
||||
|
||||
the commandline uploader [up2k.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#up2kpy) 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)
|
||||
|
||||
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 for instance), although syncing to copyparty is about 5x slower than up2k.py if you have many small files in particular
|
||||
|
||||
|
||||
## mount as drive
|
||||
|
||||
a remote copyparty server as a local filesystem; go to the control-panel and click `connect` to see a list of commands to do that
|
||||
@@ -1215,6 +1227,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
|
||||
most clients will fail to mount the root of a copyparty server unless there is a root volume (so you get the admin-panel instead of a browser when accessing it) -- in that case, mount a specific volume instead
|
||||
|
||||
|
||||
# android app
|
||||
|
||||
upload to copyparty with one tap
|
||||
|
||||
<a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
|
||||
|
||||
the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
|
||||
|
||||
if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
|
||||
|
||||
|
||||
# iOS shortcuts
|
||||
|
||||
there is no iPhone app, but the following shortcuts are almost as good:
|
||||
|
||||
* [upload to copyparty](https://www.icloud.com/shortcuts/41e98dd985cb4d3bb433222bc1e9e770) ([offline](https://github.com/9001/copyparty/raw/hovudstraum/contrib/ios/upload-to-copyparty.shortcut)) ([png](https://user-images.githubusercontent.com/241032/226118053-78623554-b0ed-482e-98e4-6d57ada58ea4.png)) based on the [original](https://www.icloud.com/shortcuts/ab415d5b4de3467b9ce6f151b439a5d7) by [Daedren](https://github.com/Daedren) (thx!)
|
||||
* can strip exif, upload files, pics, vids, links, clipboard
|
||||
* can download links and rehost the target file on copyparty (see first comment inside the shortcut)
|
||||
* pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
|
||||
|
||||
|
||||
# performance
|
||||
|
||||
defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
||||
@@ -1310,6 +1343,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
|
||||
cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
|
||||
|
||||
|
||||
## https
|
||||
|
||||
both HTTP and HTTPS are accepted by default, but letting a [reverse proxy](#reverse-proxy) handle the https/tls/ssl would be better (probably more secure by default)
|
||||
|
||||
copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
|
||||
|
||||
|
||||
# recovering from crashes
|
||||
|
||||
## client crashes
|
||||
@@ -1377,7 +1417,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
||||
|
||||
the self-contained "binary" [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py) will unpack itself and run copyparty, assuming you have python installed of course
|
||||
|
||||
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](#./docs/devnotes.md#sfx-repack)
|
||||
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
||||
|
||||
|
||||
## copyparty.exe
|
||||
|
||||
@@ -118,6 +118,15 @@ mkdir -p "$jail/tmp"
|
||||
chmod 777 "$jail/tmp"
|
||||
|
||||
|
||||
# create a dev
|
||||
(cd $jail; mkdir -p dev; cd dev
|
||||
[ -e null ] || mknod -m 666 null c 1 3
|
||||
[ -e zero ] || mknod -m 666 zero c 1 5
|
||||
[ -e random ] || mknod -m 444 random c 1 8
|
||||
[ -e urandom ] || mknod -m 444 urandom c 1 9
|
||||
)
|
||||
|
||||
|
||||
# run copyparty
|
||||
export HOME=$(getent passwd $uid | cut -d: -f6)
|
||||
export USER=$(getent passwd $uid | cut -d: -f1)
|
||||
|
||||
BIN
contrib/ios/upload-to-copyparty.shortcut
Normal file
BIN
contrib/ios/upload-to-copyparty.shortcut
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
# Maintainer: icxes <dev.null@need.moe>
|
||||
pkgname=copyparty
|
||||
pkgver="1.6.7"
|
||||
pkgver="1.6.9"
|
||||
pkgrel=1
|
||||
pkgdesc="Portable file sharing hub"
|
||||
arch=("any")
|
||||
@@ -26,7 +26,7 @@ source=("${url}/releases/download/v${pkgver}/${pkgname}-sfx.py"
|
||||
"https://raw.githubusercontent.com/9001/${pkgname}/v${pkgver}/LICENSE"
|
||||
)
|
||||
backup=("etc/${pkgname}.d/init" )
|
||||
sha256sums=("3fb40a631e9decf0073db06aab6fd8d743de91f4ddb82a65164d39d53e0b413f"
|
||||
sha256sums=("64f3b6a7120b3e1c1167e6aa7c0f023c39abb18e50525013b97467326a2f73ab"
|
||||
"b8565eba5e64dedba1cf6c7aac7e31c5a731ed7153d6810288a28f00a36c28b2"
|
||||
"f65c207e0670f9d78ad2e399bda18d5502ff30d2ac79e0e7fc48e7fbdc39afdc"
|
||||
"c4f396b083c9ec02ad50b52412c84d2a82be7f079b2d016e1c9fad22d68285ff"
|
||||
|
||||
@@ -758,7 +758,7 @@ def add_ftp(ap):
|
||||
|
||||
def add_webdav(ap):
|
||||
ap2 = ap.add_argument_group('WebDAV options')
|
||||
ap2.add_argument("--daw", action="store_true", help="enable full write support. \033[1;31mWARNING:\033[0m This has side-effects -- PUT-operations will now \033[1;31mOVERWRITE\033[0m existing files, rather than inventing new filenames to avoid loss of data. You might want to instead set this as a volflag where needed. By not setting this flag, uploaded files can get written to a filename which the client does not expect (which might be okay, depending on client)")
|
||||
ap2.add_argument("--daw", action="store_true", help="enable full write support, even if client may not be webdav. \033[1;31mWARNING:\033[0m This has side-effects -- PUT-operations will now \033[1;31mOVERWRITE\033[0m existing files, rather than inventing new filenames to avoid loss of data. You might want to instead set this as a volflag where needed. By not setting this flag, uploaded files can get written to a filename which the client does not expect (which might be okay, depending on client)")
|
||||
ap2.add_argument("--dav-inf", action="store_true", help="allow depth:infinite requests (recursive file listing); extremely server-heavy but required for spec compliance -- luckily few clients rely on this")
|
||||
ap2.add_argument("--dav-mac", action="store_true", help="disable apple-garbage filter -- allow macos to create junk files (._* and .DS_Store, .Spotlight-*, .fseventsd, .Trashes, .AppleDouble, __MACOS)")
|
||||
|
||||
@@ -946,6 +946,7 @@ def add_ui(ap, retry):
|
||||
ap2.add_argument("--js-browser", metavar="L", type=u, help="URL to additional JS to include")
|
||||
ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include")
|
||||
ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages")
|
||||
ap2.add_argument("--ih", action="store_true", help="if a folder contains index.html, show that instead of the directory listing by default (can be changed in the client settings UI)")
|
||||
ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext")
|
||||
ap2.add_argument("--txt-max", metavar="KiB", type=int, default=64, help="max size of embedded textfiles on ?doc= (anything bigger will be lazy-loaded by JS)")
|
||||
ap2.add_argument("--doctitle", metavar="TXT", type=u, default="copyparty", help="title / service-name to show in html documents")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (1, 6, 8)
|
||||
VERSION = (1, 6, 10)
|
||||
CODENAME = "cors k"
|
||||
BUILD_DT = (2023, 3, 12)
|
||||
BUILD_DT = (2023, 3, 20)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
||||
@@ -129,6 +129,7 @@ class FtpFs(AbstractedFS):
|
||||
|
||||
def die(self, msg):
|
||||
self.h.die(msg)
|
||||
raise Exception()
|
||||
|
||||
def v2a(
|
||||
self,
|
||||
|
||||
@@ -778,8 +778,8 @@ class HttpCli(object):
|
||||
if "k304" in self.uparam:
|
||||
return self.set_k304()
|
||||
|
||||
if "am_js" in self.uparam:
|
||||
return self.set_am_js()
|
||||
if "setck" in self.uparam:
|
||||
return self.setck()
|
||||
|
||||
if "reset" in self.uparam:
|
||||
return self.set_cfg_reset()
|
||||
@@ -865,7 +865,17 @@ class HttpCli(object):
|
||||
vn, rem = self.asrv.vfs.get(self.vpath, self.uname, True, False, err=401)
|
||||
depth = self.headers.get("depth", "infinity").lower()
|
||||
|
||||
if depth == "infinity":
|
||||
try:
|
||||
topdir = {"vp": "", "st": bos.stat(vn.canonical(rem))}
|
||||
except OSError as ex:
|
||||
if ex.errno != errno.ENOENT:
|
||||
raise
|
||||
raise Pebkac(404)
|
||||
|
||||
if not stat.S_ISDIR(topdir["st"].st_mode):
|
||||
fgen = []
|
||||
|
||||
elif depth == "infinity":
|
||||
if not self.args.dav_inf:
|
||||
self.log("client wants --dav-inf", 3)
|
||||
zb = b'<?xml version="1.0" encoding="utf-8"?>\n<D:error xmlns:D="DAV:"><D:propfind-finite-depth/></D:error>'
|
||||
@@ -904,13 +914,6 @@ class HttpCli(object):
|
||||
t2 = " or 'infinity'" if self.args.dav_inf else ""
|
||||
raise Pebkac(412, t.format(depth, t2))
|
||||
|
||||
try:
|
||||
topdir = {"vp": "", "st": os.stat(vn.canonical(rem))}
|
||||
except OSError as ex:
|
||||
if ex.errno != errno.ENOENT:
|
||||
raise
|
||||
raise Pebkac(404)
|
||||
|
||||
fgen = itertools.chain([topdir], fgen) # type: ignore
|
||||
vtop = vjoin(self.args.R, vjoin(vn.vpath, rem))
|
||||
|
||||
@@ -1426,9 +1429,9 @@ class HttpCli(object):
|
||||
self.log(t, 1)
|
||||
raise Pebkac(403, t)
|
||||
|
||||
if is_put and not (self.args.no_dav or self.args.nw):
|
||||
if is_put and not (self.args.no_dav or self.args.nw) and bos.path.exists(path):
|
||||
# allow overwrite if...
|
||||
# * volflag 'daw' is set
|
||||
# * volflag 'daw' is set, or client is definitely webdav
|
||||
# * and account has delete-access
|
||||
# or...
|
||||
# * file exists, is empty, sufficiently new
|
||||
@@ -1438,9 +1441,11 @@ class HttpCli(object):
|
||||
if self.args.dotpart:
|
||||
tnam = "." + tnam
|
||||
|
||||
if (vfs.flags.get("daw") and self.can_delete) or (
|
||||
if (
|
||||
self.can_delete
|
||||
and (vfs.flags.get("daw") or "x-oc-mtime" in self.headers)
|
||||
) or (
|
||||
not bos.path.exists(os.path.join(fdir, tnam))
|
||||
and bos.path.exists(path)
|
||||
and not bos.path.getsize(path)
|
||||
and bos.path.getmtime(path) >= time.time() - self.args.blank_wt
|
||||
):
|
||||
@@ -1464,6 +1469,16 @@ class HttpCli(object):
|
||||
if self.args.nw:
|
||||
return post_sz, sha_hex, sha_b64, remains, path, ""
|
||||
|
||||
at = mt = time.time() - lifetime
|
||||
cli_mt = self.headers.get("x-oc-mtime")
|
||||
if cli_mt:
|
||||
try:
|
||||
mt = int(cli_mt)
|
||||
times = (int(time.time()), mt)
|
||||
bos.utime(path, times, False)
|
||||
except:
|
||||
pass
|
||||
|
||||
if nameless and "magic" in vfs.flags:
|
||||
try:
|
||||
ext = self.conn.hsrv.magician.ext(path)
|
||||
@@ -1486,7 +1501,6 @@ class HttpCli(object):
|
||||
fn = fn2
|
||||
path = path2
|
||||
|
||||
at = time.time() - lifetime
|
||||
if xau and not runhook(
|
||||
self.log,
|
||||
xau,
|
||||
@@ -1494,7 +1508,7 @@ class HttpCli(object):
|
||||
self.vpath,
|
||||
self.host,
|
||||
self.uname,
|
||||
at,
|
||||
mt,
|
||||
post_sz,
|
||||
self.ip,
|
||||
at,
|
||||
@@ -1757,12 +1771,13 @@ class HttpCli(object):
|
||||
hits = idx.fsearch(vols, body)
|
||||
msg: Any = repr(hits)
|
||||
taglist: list[str] = []
|
||||
trunc = False
|
||||
else:
|
||||
# search by query params
|
||||
q = body["q"]
|
||||
n = body.get("n", self.args.srch_hits)
|
||||
self.log("qj: {} |{}|".format(q, n))
|
||||
hits, taglist = idx.search(vols, q, n)
|
||||
hits, taglist, trunc = idx.search(vols, q, n)
|
||||
msg = len(hits)
|
||||
|
||||
idx.p_end = time.time()
|
||||
@@ -1782,7 +1797,8 @@ class HttpCli(object):
|
||||
for hit in hits:
|
||||
hit["rp"] = self.args.RS + hit["rp"]
|
||||
|
||||
r = json.dumps({"hits": hits, "tag_order": order}).encode("utf-8")
|
||||
rj = {"hits": hits, "tag_order": order, "trunc": trunc}
|
||||
r = json.dumps(rj).encode("utf-8")
|
||||
self.reply(r, mime="application/json")
|
||||
return True
|
||||
|
||||
@@ -2896,15 +2912,16 @@ class HttpCli(object):
|
||||
self.redirect("", "?h#cc")
|
||||
return True
|
||||
|
||||
def set_am_js(self) -> bool:
|
||||
v = "n" if self.uparam["am_js"] == "n" else "y"
|
||||
ck = gencookie("js", v, self.args.R, False, 86400 * 299)
|
||||
def setck(self) -> bool:
|
||||
k, v = self.uparam["setck"].split("=", 1)
|
||||
t = None if v == "" else 86400 * 299
|
||||
ck = gencookie(k, v, self.args.R, False, t)
|
||||
self.out_headerlist.append(("Set-Cookie", ck))
|
||||
self.reply(b"promoted\n")
|
||||
self.reply(b"o7\n")
|
||||
return True
|
||||
|
||||
def set_cfg_reset(self) -> bool:
|
||||
for k in ("k304", "js", "cppwd", "cppws"):
|
||||
for k in ("k304", "js", "idxh", "cppwd", "cppws"):
|
||||
cookie = gencookie(k, "x", self.args.R, False, None)
|
||||
self.out_headerlist.append(("Set-Cookie", cookie))
|
||||
|
||||
@@ -3433,6 +3450,7 @@ class HttpCli(object):
|
||||
"dtheme": self.args.theme,
|
||||
"themes": self.args.themes,
|
||||
"turbolvl": self.args.turbo,
|
||||
"idxh": int(self.args.ih),
|
||||
"u2sort": self.args.u2sort,
|
||||
}
|
||||
|
||||
@@ -3566,6 +3584,20 @@ class HttpCli(object):
|
||||
files.append(item)
|
||||
item["rd"] = rem
|
||||
|
||||
if (
|
||||
self.cookies.get("idxh") == "y"
|
||||
and "ls" not in self.uparam
|
||||
and "v" not in self.uparam
|
||||
):
|
||||
idx_html = set(["index.htm", "index.html"])
|
||||
for item in files:
|
||||
if item["name"] in idx_html:
|
||||
# do full resolve in case of shadowed file
|
||||
vp = vjoin(self.vpath.split("?")[0], item["name"])
|
||||
vn, rem = self.asrv.vfs.get(vp, self.uname, True, False)
|
||||
ap = vn.canonical(rem)
|
||||
return self.tx_file(ap) # is no-cache
|
||||
|
||||
tagset: set[str] = set()
|
||||
for fe in files:
|
||||
fn = fe["name"]
|
||||
|
||||
@@ -561,12 +561,19 @@ class ThumbSrv(object):
|
||||
if "ac" not in ret:
|
||||
raise Exception("not audio")
|
||||
|
||||
try:
|
||||
dur = ret[".dur"][1]
|
||||
except:
|
||||
dur = 0
|
||||
|
||||
src_opus = abspath.lower().endswith(".opus") or ret["ac"][1] == "opus"
|
||||
want_caf = tpath.endswith(".caf")
|
||||
tmp_opus = tpath
|
||||
if want_caf:
|
||||
tmp_opus = tpath.rsplit(".", 1)[0] + ".opus"
|
||||
|
||||
caf_src = abspath if src_opus else tmp_opus
|
||||
|
||||
if not want_caf or (not src_opus and not bos.path.isfile(tmp_opus)):
|
||||
# fmt: off
|
||||
cmd = [
|
||||
@@ -584,7 +591,32 @@ class ThumbSrv(object):
|
||||
# fmt: on
|
||||
self._run_ff(cmd)
|
||||
|
||||
if want_caf:
|
||||
# iOS fails to play some "insufficiently complex" files
|
||||
# (average file shorter than 8 seconds), so of course we
|
||||
# fix that by mixing in some inaudible pink noise :^)
|
||||
# 6.3 sec seems like the cutoff so lets do 7, and
|
||||
# 7 sec of psyqui-musou.opus @ 3:50 is 174 KiB
|
||||
if want_caf and (dur < 20 or bos.path.getsize(caf_src) < 256 * 1024):
|
||||
# fmt: off
|
||||
cmd = [
|
||||
b"ffmpeg",
|
||||
b"-nostdin",
|
||||
b"-v", b"error",
|
||||
b"-hide_banner",
|
||||
b"-i", fsenc(abspath),
|
||||
b"-filter_complex", b"anoisesrc=a=0.001:d=7:c=pink,asplit[l][r]; [l][r]amerge[s]; [0:a:0][s]amix",
|
||||
b"-map_metadata", b"-1",
|
||||
b"-ac", b"2",
|
||||
b"-c:a", b"libopus",
|
||||
b"-b:a", b"128k",
|
||||
b"-f", b"caf",
|
||||
fsenc(tpath)
|
||||
]
|
||||
# fmt: on
|
||||
self._run_ff(cmd)
|
||||
|
||||
elif want_caf:
|
||||
# simple remux should be safe
|
||||
# fmt: off
|
||||
cmd = [
|
||||
b"ffmpeg",
|
||||
|
||||
@@ -120,10 +120,10 @@ class U2idx(object):
|
||||
|
||||
def search(
|
||||
self, vols: list[tuple[str, str, dict[str, Any]]], uq: str, lim: int
|
||||
) -> tuple[list[dict[str, Any]], list[str]]:
|
||||
) -> tuple[list[dict[str, Any]], list[str], bool]:
|
||||
"""search by query params"""
|
||||
if not HAVE_SQLITE3:
|
||||
return [], []
|
||||
return [], [], False
|
||||
|
||||
q = ""
|
||||
v: Union[str, int] = ""
|
||||
@@ -275,7 +275,7 @@ class U2idx(object):
|
||||
have_up: bool,
|
||||
have_mt: bool,
|
||||
lim: int,
|
||||
) -> tuple[list[dict[str, Any]], list[str]]:
|
||||
) -> tuple[list[dict[str, Any]], list[str], bool]:
|
||||
done_flag: list[bool] = []
|
||||
self.active_id = "{:.6f}_{}".format(
|
||||
time.time(), threading.current_thread().ident
|
||||
@@ -316,9 +316,6 @@ class U2idx(object):
|
||||
c = cur.execute(uq, tuple(vuv))
|
||||
for hit in c:
|
||||
w, ts, sz, rd, fn, ip, at = hit[:7]
|
||||
lim -= 1
|
||||
if lim < 0:
|
||||
break
|
||||
|
||||
if rd.startswith("//") or fn.startswith("//"):
|
||||
rd, fn = s3dec(rd, fn)
|
||||
@@ -346,6 +343,10 @@ class U2idx(object):
|
||||
)[:fk]
|
||||
)
|
||||
|
||||
lim -= 1
|
||||
if lim < 0:
|
||||
break
|
||||
|
||||
seen_rps.add(rp)
|
||||
sret.append({"ts": int(ts), "sz": sz, "rp": rp + suf, "w": w[:16]})
|
||||
|
||||
@@ -368,7 +369,7 @@ class U2idx(object):
|
||||
|
||||
ret.sort(key=itemgetter("rp"))
|
||||
|
||||
return ret, list(taglist.keys())
|
||||
return ret, list(taglist.keys()), lim < 0
|
||||
|
||||
def terminator(self, identifier: str, done_flag: list[bool]) -> None:
|
||||
for _ in range(self.timeout):
|
||||
|
||||
@@ -1251,12 +1251,15 @@ class Up2k(object):
|
||||
if n_rm2:
|
||||
self.log("forgetting {} shadowed deleted files".format(n_rm2))
|
||||
|
||||
c2.connection.commit()
|
||||
|
||||
# then covers
|
||||
n_rm3 = 0
|
||||
qu = "select 1 from up where rd=? and +fn=? limit 1"
|
||||
q = "delete from cv where rd=? and dn=? and +fn=?"
|
||||
for crd, cdn, fn in cur.execute("select * from cv"):
|
||||
ap = os.path.join(top, crd, cdn, fn)
|
||||
if not bos.path.exists(ap):
|
||||
urd = vjoin(crd, cdn)
|
||||
if not c2.execute(qu, (urd, fn)).fetchone():
|
||||
c2.execute(q, (crd, cdn, fn))
|
||||
n_rm3 += 1
|
||||
|
||||
|
||||
@@ -796,6 +796,8 @@ html.y #path a:hover {
|
||||
}
|
||||
.logue {
|
||||
padding: .2em 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.logue.hidden,
|
||||
.logue:empty {
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
sb_lg = "{{ sb_lg }}",
|
||||
lifetime = {{ lifetime }},
|
||||
turbolvl = {{ turbolvl }},
|
||||
idxh = {{ idxh }},
|
||||
frand = {{ frand|tojson }},
|
||||
u2sort = "{{ u2sort }}",
|
||||
have_emp = {{ have_emp|tojson }},
|
||||
|
||||
@@ -193,6 +193,7 @@ var Ls = {
|
||||
"ct_dots": "show hidden files (if server permits)",
|
||||
"ct_dir1st": "sort folders before files",
|
||||
"ct_readme": "show README.md in folder listings",
|
||||
"ct_idxh": "show index.html instead of folder listing",
|
||||
"ct_sbars": "show scrollbars",
|
||||
|
||||
"cut_turbo": "the yolo button, you probably DO NOT want to enable this:$N$Nuse this if you were uploading a huge amount of files and had to restart for some reason, and want to continue the upload ASAP$N$Nthis replaces the hash-check with a simple <em>"does this have the same filesize on the server?"</em> so if the file contents are different it will NOT be uploaded$N$Nyou should turn this off when the upload is done, and then "upload" the same files again to let the client verify them",
|
||||
@@ -652,6 +653,7 @@ var Ls = {
|
||||
"ct_dots": "vis skjulte filer (gitt at serveren tillater det)",
|
||||
"ct_dir1st": "sorter slik at mapper kommer foran filer",
|
||||
"ct_readme": "vis README.md nedenfor filene",
|
||||
"ct_idxh": "vis index.html istedenfor fil-liste",
|
||||
"ct_sbars": "vis rullgardiner / skrollefelt",
|
||||
|
||||
"cut_turbo": "forenklet befaring ved opplastning; bør sannsynlig <em>ikke</em> skrus på:$N$Nnyttig dersom du var midt i en svær opplastning som måtte restartes av en eller annen grunn, og du vil komme igang igjen så raskt som overhodet mulig.$N$Nnår denne er skrudd på så forenkles befaringen kraftig; istedenfor å utføre en trygg sjekk på om filene finnes på serveren i god stand, så sjekkes kun om <em>filstørrelsen</em> stemmer. Så dersom en korrupt fil skulle befinne seg på serveren allerede, på samme sted med samme størrelse og navn, så blir det <em>ikke oppdaget</em>.$N$Ndet anbefales å kun benytte denne funksjonen for å komme seg raskt igjennom selve opplastningen, for så å skru den av, og til slutt "laste opp" de samme filene én gang til -- slik at integriteten kan verifiseres",
|
||||
@@ -1083,6 +1085,7 @@ ebi('op_cfg').innerHTML = (
|
||||
' <a id="dotfiles" class="tgl btn" href="#" tt="' + L.ct_dots + '">dotfiles</a>\n' +
|
||||
' <a id="dir1st" class="tgl btn" href="#" tt="' + L.ct_dir1st + '">📁 first</a>\n' +
|
||||
' <a id="ireadme" class="tgl btn" href="#" tt="' + L.ct_readme + '">📜 readme</a>\n' +
|
||||
' <a id="idxh" class="tgl btn" href="#" tt="' + L.ct_idxh + '">htm</a>\n' +
|
||||
' <a id="sbars" class="tgl btn" href="#" tt="' + L.ct_sbars + '">⟊</a>\n' +
|
||||
' </div>\n' +
|
||||
'</div>\n' +
|
||||
@@ -1278,6 +1281,7 @@ function set_files_html(html) {
|
||||
|
||||
|
||||
var ACtx = window.AudioContext || window.webkitAudioContext,
|
||||
noih = /[?&]v\b/.exec('' + location),
|
||||
hash0 = location.hash,
|
||||
mp;
|
||||
|
||||
@@ -4872,7 +4876,7 @@ document.onkeydown = function (e) {
|
||||
|
||||
var html = mk_files_header(tagord), seen = {};
|
||||
html.push('<tbody>');
|
||||
html.push('<tr class="srch_hdr"><td>-</td><td><a href="#" id="unsearch"><big style="font-weight:bold">[❌] ' + L.sl_close + '</big></a> -- ' + L.sl_hits.format(res.hits.length) + (res.hits.length == cap ? ' -- <a href="#" id="moar">' + L.sl_moar + '</a>' : '') + '</td></tr>');
|
||||
html.push('<tr class="srch_hdr"><td>-</td><td><a href="#" id="unsearch"><big style="font-weight:bold">[❌] ' + L.sl_close + '</big></a> -- ' + L.sl_hits.format(res.hits.length) + (res.trunc ? ' -- <a href="#" id="moar">' + L.sl_moar + '</a>' : '') + '</td></tr>');
|
||||
|
||||
for (var a = 0; a < res.hits.length; a++) {
|
||||
var r = res.hits[a],
|
||||
@@ -4986,6 +4990,7 @@ var treectl = (function () {
|
||||
treesz = clamp(icfg_get('treesz', 16), 10, 50);
|
||||
|
||||
bcfg_bind(r, 'ireadme', 'ireadme', true);
|
||||
bcfg_bind(r, 'idxh', 'idxh', idxh, setidxh);
|
||||
bcfg_bind(r, 'dyn', 'dyntree', true, onresize);
|
||||
bcfg_bind(r, 'dots', 'dotfiles', false, function (v) {
|
||||
r.goto(get_evpath());
|
||||
@@ -5010,6 +5015,16 @@ var treectl = (function () {
|
||||
}
|
||||
setwrap(r.wtree);
|
||||
|
||||
function setidxh(v) {
|
||||
if (!v == !/\bidxh=y\b/.exec('' + document.cookie))
|
||||
return;
|
||||
|
||||
var xhr = new XHR();
|
||||
xhr.open('GET', SR + '/?setck=idxh=' + (v ? 'y' : 'n'), true);
|
||||
xhr.send();
|
||||
}
|
||||
setidxh(r.idxh);
|
||||
|
||||
r.entree = function (e, nostore) {
|
||||
ev(e);
|
||||
entreed = true;
|
||||
@@ -5438,6 +5453,9 @@ var treectl = (function () {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.chk_index_html(this.top, res))
|
||||
return;
|
||||
|
||||
for (var a = 0; a < res.files.length; a++)
|
||||
if (res.files[a].tags === undefined)
|
||||
res.files[a].tags = {};
|
||||
@@ -5485,6 +5503,17 @@ var treectl = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
r.chk_index_html = function (top, res) {
|
||||
if (!r.idxh || !res || !res.files || noih)
|
||||
return;
|
||||
|
||||
for (var a = 0; a < res.files.length; a++)
|
||||
if (/^index.html?(\?|$)/i.exec(res.files[a].href)) {
|
||||
window.location = vjoin(top, res.files[a].href);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
r.gentab = function (top, res) {
|
||||
var nodes = res.dirs.concat(res.files),
|
||||
html = mk_files_header(res.taglist),
|
||||
@@ -5605,14 +5634,18 @@ var treectl = (function () {
|
||||
qsr('#bbsw');
|
||||
if (ls0 === null) {
|
||||
var xhr = new XHR();
|
||||
xhr.open('GET', SR + '/?am_js', true);
|
||||
xhr.open('GET', SR + '/?setck=js=y', true);
|
||||
xhr.send();
|
||||
|
||||
r.ls_cb = showfile.addlinks;
|
||||
return r.reqls(get_evpath(), false);
|
||||
}
|
||||
|
||||
r.gentab(get_evpath(), ls0);
|
||||
var top = get_evpath();
|
||||
if (r.chk_index_html(top, ls0))
|
||||
return;
|
||||
|
||||
r.gentab(top, ls0);
|
||||
pbar.onresize();
|
||||
vbar.onresize();
|
||||
showfile.addlinks();
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<p><em>note: rclone-FTP is a bit faster, so {% if args.ftp or args.ftps %}try that first{% else %}consider enabling FTP in server settings{% endif %}</em></p>
|
||||
<p>if you can, install <a href="https://winfsp.dev/rel/">winfsp</a>+<a href="https://downloads.rclone.org/rclone-current-windows-amd64.zip">rclone</a> and then paste this in cmd:</p>
|
||||
<pre>
|
||||
rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=other{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
|
||||
rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=owncloud{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
|
||||
rclone mount --vfs-cache-mode writes --dir-cache-time 5s {{ aname }}-dav:{{ rvp }} <b>W:</b>
|
||||
</pre>
|
||||
{% if s %}
|
||||
@@ -69,9 +69,9 @@
|
||||
printf '%s\n' "http{{ s }}://{{ ep }}/{{ rvp }} <b>{{ pw }}</b> k" >> /etc/davfs2/secrets
|
||||
printf '%s\n' "http{{ s }}://{{ ep }}/{{ rvp }} <b>mp</b> davfs rw,user,uid=1000,noauto 0 0" >> /etc/fstab
|
||||
</pre>
|
||||
<p>or you can use rclone instead, which is much slower but doesn't require root:</p>
|
||||
<p>or you can use rclone instead, which is much slower but doesn't require root (plus it keeps lastmodified on upload):</p>
|
||||
<pre>
|
||||
rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=other{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
|
||||
rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=owncloud{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
|
||||
rclone mount --vfs-cache-mode writes --dir-cache-time 5s {{ aname }}-dav:{{ rvp }} <b>mp</b>
|
||||
</pre>
|
||||
{% if s %}
|
||||
|
||||
@@ -632,6 +632,29 @@ function vsplit(vp) {
|
||||
}
|
||||
|
||||
|
||||
function vjoin(p1, p2) {
|
||||
if (!p1)
|
||||
p1 = '';
|
||||
|
||||
if (!p2)
|
||||
p2 = '';
|
||||
|
||||
if (p1.endsWith('/'))
|
||||
p1 = p1.slice(0, -1);
|
||||
|
||||
if (p2.startsWith('/'))
|
||||
p2 = p2.slice(1);
|
||||
|
||||
if (!p1)
|
||||
return p2;
|
||||
|
||||
if (!p2)
|
||||
return p1;
|
||||
|
||||
return p1 + '/' + p2;
|
||||
}
|
||||
|
||||
|
||||
function uricom_enc(txt, do_fb_enc) {
|
||||
try {
|
||||
return encodeURIComponent(txt);
|
||||
@@ -1183,13 +1206,13 @@ var tt = (function () {
|
||||
r.th.style.top = (e.pageY + 12 * sy) + 'px';
|
||||
};
|
||||
|
||||
if (IPHONE) {
|
||||
if (TOUCH) {
|
||||
var f1 = r.show,
|
||||
f2 = r.hide,
|
||||
q = [];
|
||||
|
||||
// if an onclick-handler creates a new timer,
|
||||
// iOS 13.1.2 delays the entire handler by up to 401ms,
|
||||
// webkits delay the entire handler by up to 401ms,
|
||||
// win by using a shared timer instead
|
||||
|
||||
timer.add(function () {
|
||||
|
||||
@@ -1,3 +1,59 @@
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
# 2023-0316-2106 `v1.6.9` index.html
|
||||
|
||||
## new features
|
||||
* option to show `index.html` instead of the folder listing
|
||||
* arg `--ih` makes it default-enabled
|
||||
* clients can enable/disable it in the `[⚙️]` settings tab
|
||||
* url-param `?v` skips it for a particular folder
|
||||
* faster folder-thumbnail validation on startup (mostly on conventional HDDs)
|
||||
|
||||
## bugfixes
|
||||
* "load more" button didn't always show up when search results got truncated
|
||||
* ux: tooltips could block buttons on android
|
||||
|
||||
|
||||
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
# 2023-0312-1610 `v1.6.8` folder thumbs
|
||||
|
||||
* read-only demo server at https://a.ocv.me/pub/demo/
|
||||
* [docker image](https://github.com/9001/copyparty/tree/hovudstraum/scripts/docker) ╱ [similar software](https://github.com/9001/copyparty/blob/hovudstraum/docs/versus.md) ╱ [client testbed](https://cd.ocv.me/b/)
|
||||
|
||||
## new features
|
||||
* folder thumbnails are indexed in the db
|
||||
* now supports non-lowercase names (`Cover.jpg`, `Folder.JPG`)
|
||||
* folders without a specific cover/folder image will show the first pic inside
|
||||
* when audio playback continues into an empty folder, keep trying for a bit
|
||||
* add no-index hints (google etc) in basic-browser HTML (`?b`, `?b=u`)
|
||||
* [commandline uploader](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) supports long filenames on win7
|
||||
|
||||
## bugfixes
|
||||
* rotated logfiles didn't get xz compressed
|
||||
* image-gallery links pointing to a deleted image shows an error instead of a crashpage
|
||||
|
||||
## other changes
|
||||
* folder thumbnails have purple text to differentiate from files
|
||||
* `copyparty32.exe` starts 30% faster (but is 6% larger)
|
||||
|
||||
----
|
||||
|
||||
# what to download?
|
||||
| download link | is it good? | description |
|
||||
| -- | -- | -- |
|
||||
| **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py)** | ✅ the best 👍 | runs anywhere! only needs python |
|
||||
| [a docker image](https://github.com/9001/copyparty/blob/hovudstraum/scripts/docker/README.md) | it's ok | good if you prefer docker 🐋 |
|
||||
| [copyparty.exe](https://github.com/9001/copyparty/releases/latest/download/copyparty.exe) | ⚠️ [acceptable](https://github.com/9001/copyparty#copypartyexe) | for [win8](https://user-images.githubusercontent.com/241032/221445946-1e328e56-8c5b-44a9-8b9f-dee84d942535.png) or later; built-in thumbnailer |
|
||||
| [up2k.exe](https://github.com/9001/copyparty/releases/latest/download/up2k.exe) | ⚠️ acceptable | [CLI uploader](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) as a win7+ exe ([video](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm)) |
|
||||
| [copyparty32.exe](https://github.com/9001/copyparty/releases/latest/download/copyparty32.exe) | ⛔️ [dangerous](https://github.com/9001/copyparty#copypartyexe) | for [win7](https://user-images.githubusercontent.com/241032/221445944-ae85d1f4-d351-4837-b130-82cab57d6cca.png) -- never expose to the internet! |
|
||||
| [cpp-winpe64.exe](https://github.com/9001/copyparty/releases/download/v1.6.8/copyparty-winpe64.exe) | ⛔️ dangerous | runs on [64bit WinPE](https://user-images.githubusercontent.com/241032/205454984-e6b550df-3c49-486d-9267-1614078dd0dd.png), otherwise useless |
|
||||
|
||||
* except for [up2k.exe](https://github.com/9001/copyparty/releases/latest/download/up2k.exe), all of the options above are equivalent
|
||||
* the zip and tar.gz files below are just source code
|
||||
* python packages are available at [PyPI](https://pypi.org/project/copyparty/#files)
|
||||
|
||||
|
||||
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
# 2023-0305-2018 `v1.6.7` fix no-dedup + add up2k.exe
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ when server is on another machine (1gbit LAN),
|
||||
|
||||
# creating the config file
|
||||
|
||||
the copyparty "connect" page at `/?hc` (so for example http://127.0.0.1:3923/?hc) will generate commands to autoconfigure rclone for your server
|
||||
|
||||
**if you prefer to configure rclone manually, continue reading:**
|
||||
|
||||
replace `hunter2` with your password, or remove the `hunter2` lines if you allow anonymous access
|
||||
|
||||
|
||||
@@ -22,7 +26,7 @@ replace `hunter2` with your password, or remove the `hunter2` lines if you allow
|
||||
(
|
||||
echo [cpp-rw]
|
||||
echo type = webdav
|
||||
echo vendor = other
|
||||
echo vendor = owncloud
|
||||
echo url = http://127.0.0.1:3923/
|
||||
echo headers = Cookie,cppwd=hunter2
|
||||
echo(
|
||||
@@ -41,7 +45,7 @@ also install the windows dependencies: [winfsp](https://github.com/billziss-gh/w
|
||||
cat > ~/.config/rclone/rclone.conf <<'EOF'
|
||||
[cpp-rw]
|
||||
type = webdav
|
||||
vendor = other
|
||||
vendor = owncloud
|
||||
url = http://127.0.0.1:3923/
|
||||
headers = Cookie,cppwd=hunter2
|
||||
|
||||
@@ -62,6 +66,17 @@ rclone.exe mount --vfs-cache-mode writes --vfs-cache-max-age 5s --attr-timeout 5
|
||||
```
|
||||
|
||||
|
||||
# sync folders to/from copyparty
|
||||
|
||||
note that the up2k client [up2k.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#up2kpy) (available on the "connect" page of your copyparty server) does uploads much faster and safer, but rclone is bidirectional and more ubiquitous
|
||||
|
||||
```
|
||||
rclone sync /usr/share/icons/ cpp-rw:fds/
|
||||
```
|
||||
|
||||
TODO: rclone bug? `--transfers=4` doesn't seem to do anything (it does one request at a time), doesn't matter if the webdav server is copyparty or rclone
|
||||
|
||||
|
||||
# use rclone as server too, replacing copyparty
|
||||
|
||||
feels out of place but is too good not to mention
|
||||
@@ -70,3 +85,26 @@ feels out of place but is too good not to mention
|
||||
rclone.exe serve http --read-only .
|
||||
rclone.exe serve webdav .
|
||||
```
|
||||
|
||||
|
||||
# devnotes
|
||||
|
||||
copyparty supports and expects [the following](https://github.com/rclone/rclone/blob/46484022b08f8756050aa45505ea0db23e62df8b/backend/webdav/webdav.go#L575-L578) from rclone,
|
||||
|
||||
```go
|
||||
case "owncloud":
|
||||
f.canStream = true
|
||||
f.precision = time.Second
|
||||
f.useOCMtime = true
|
||||
f.hasOCMD5 = true
|
||||
f.hasOCSHA1 = true
|
||||
```
|
||||
|
||||
notably,
|
||||
* `useOCMtime` enables the `x-oc-mtime` header to retain mtime of uploads from rclone
|
||||
* `canStream` is supported but not required by us
|
||||
* `hasOCMD5` / `hasOCSHA1` is conveniently dontcare on both ends
|
||||
|
||||
there's a scary comment mentioning PROPSET of lastmodified which is not something we wish to support
|
||||
|
||||
and if `vendor=owncloud` ever stops working, try `vendor=fastmail` instead
|
||||
|
||||
375
docs/versus.md
375
docs/versus.md
@@ -17,6 +17,7 @@ currently up to date with [awesome-selfhosted](https://github.com/awesome-selfho
|
||||
|
||||
### ...in reviews:
|
||||
* ✅ = advantages over copyparty
|
||||
* 💾 = what copyparty offers as an alternative
|
||||
* 🔵 = similarities
|
||||
* ⚠️ = disadvantages (something copyparty does "better")
|
||||
|
||||
@@ -46,6 +47,7 @@ currently up to date with [awesome-selfhosted](https://github.com/awesome-selfho
|
||||
* [kodbox](#kodbox)
|
||||
* [filebrowser](#filebrowser)
|
||||
* [filegator](#filegator)
|
||||
* [sftpgo](#sftpgo)
|
||||
* [updog](#updog)
|
||||
* [goshs](#goshs)
|
||||
* [gimme-that](#gimme-that)
|
||||
@@ -53,6 +55,7 @@ currently up to date with [awesome-selfhosted](https://github.com/awesome-selfho
|
||||
* [linx](#linx)
|
||||
* [h5ai](#h5ai)
|
||||
* [autoindex](#autoindex)
|
||||
* [miniserve](#miniserve)
|
||||
* [briefly considered](#briefly-considered)
|
||||
|
||||
|
||||
@@ -89,6 +92,7 @@ the softwares,
|
||||
* `i` = [kodbox](https://github.com/kalcaddle/kodbox)
|
||||
* `j` = [filebrowser](https://github.com/filebrowser/filebrowser)
|
||||
* `k` = [filegator](https://github.com/filegator/filegator)
|
||||
* `l` = [sftpgo](https://github.com/drakkan/sftpgo)
|
||||
|
||||
some softwares not in the matrixes,
|
||||
* [updog](#updog)
|
||||
@@ -96,6 +100,9 @@ some softwares not in the matrixes,
|
||||
* [gimme-that](#gimmethat)
|
||||
* [ass](#ass)
|
||||
* [linx](#linx)
|
||||
* [h5ai](#h5ai)
|
||||
* [autoindex](#autoindex)
|
||||
* [miniserve](#miniserve)
|
||||
|
||||
symbol legend,
|
||||
* `█` = absolutely
|
||||
@@ -106,62 +113,64 @@ symbol legend,
|
||||
|
||||
## general
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| intuitive UX | | ╱ | █ | █ | █ | | █ | █ | █ | █ | █ |
|
||||
| config GUI | | █ | █ | █ | █ | | | █ | █ | █ | |
|
||||
| good documentation | | | | █ | █ | █ | █ | | | █ | █ |
|
||||
| runs on iOS | ╱ | | | | | ╱ | | | | | |
|
||||
| runs on Android | █ | | | | | █ | | | | | |
|
||||
| runs on WinXP | █ | █ | | | | █ | | | | | |
|
||||
| runs on Windows | █ | █ | █ | █ | █ | █ | █ | ╱ | █ | █ | █ |
|
||||
| runs on Linux | █ | ╱ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| runs on Macos | █ | | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| runs on FreeBSD | █ | | | • | █ | █ | █ | • | █ | █ | |
|
||||
| portable binary | █ | █ | █ | | | █ | █ | | | █ | |
|
||||
| zero setup, just go | █ | █ | █ | | | ╱ | █ | | | █ | |
|
||||
| android app | ╱ | | | █ | █ | | | | | | |
|
||||
| iOS app | | | | █ | █ | | | | | | |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| intuitive UX | | ╱ | █ | █ | █ | | █ | █ | █ | █ | █ | █ |
|
||||
| config GUI | | █ | █ | █ | █ | | | █ | █ | █ | | █ |
|
||||
| good documentation | | | | █ | █ | █ | █ | | | █ | █ | ╱ |
|
||||
| runs on iOS | ╱ | | | | | ╱ | | | | | | |
|
||||
| runs on Android | █ | | | | | █ | | | | | | |
|
||||
| runs on WinXP | █ | █ | | | | █ | | | | | | |
|
||||
| runs on Windows | █ | █ | █ | █ | █ | █ | █ | ╱ | █ | █ | █ | █ |
|
||||
| runs on Linux | █ | ╱ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| runs on Macos | █ | | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| runs on FreeBSD | █ | | | • | █ | █ | █ | • | █ | █ | | █ |
|
||||
| portable binary | █ | █ | █ | | | █ | █ | | | █ | | █ |
|
||||
| zero setup, just go | █ | █ | █ | | | ╱ | █ | | | █ | | ╱ |
|
||||
| android app | ╱ | | | █ | █ | | | | | | | |
|
||||
| iOS app | ╱ | | | █ | █ | | | | | | | |
|
||||
|
||||
* `zero setup` = you can get a mostly working setup by just launching the app, without having to install any software or configure whatever
|
||||
* `a`/copyparty remarks:
|
||||
* no gui for server settings; only for client-side stuff
|
||||
* can theoretically run on iOS / iPads using [iSH](https://ish.app/), but only the iPad will offer sufficient multitasking i think
|
||||
* [android app](https://f-droid.org/en/packages/me.ocv.partyup/) is for uploading only
|
||||
* no iOS app but has [shortcuts](https://github.com/9001/copyparty#ios-shortcuts) for easy uploading
|
||||
* `b`/hfs2 runs on linux through wine
|
||||
* `f`/rclone must be started with the command `rclone serve webdav .` or similar
|
||||
* `h`/chibisafe has undocumented windows support
|
||||
* `i`/sftpgo must be launched with a command
|
||||
|
||||
|
||||
## file transfer
|
||||
|
||||
*the thing that copyparty is actually kinda good at*
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| download folder as zip | █ | █ | █ | █ | █ | | █ | | █ | █ | ╱ |
|
||||
| download folder as tar | █ | | | | | | | | | █ | |
|
||||
| upload | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| parallel uploads | █ | | | █ | █ | | • | | █ | | █ |
|
||||
| resumable uploads | █ | | | | | | | | █ | | █ |
|
||||
| upload segmenting | █ | | | | | | | █ | █ | | █ |
|
||||
| upload acceleration | █ | | | | | | | | █ | | █ |
|
||||
| upload verification | █ | | | █ | █ | | | | █ | | |
|
||||
| upload deduplication | █ | | | | █ | | | | █ | | |
|
||||
| upload a 999 TiB file | █ | | | | █ | █ | • | | █ | | █ |
|
||||
| keep last-modified time | █ | | | █ | █ | █ | | | | | |
|
||||
| upload rules | ╱ | ╱ | ╱ | ╱ | ╱ | | | ╱ | ╱ | | ╱ |
|
||||
| ┗ max disk usage | █ | █ | | | █ | | | | █ | | |
|
||||
| ┗ max filesize | █ | | | | | | | █ | | | █ |
|
||||
| ┗ max items in folder | █ | | | | | | | | | | |
|
||||
| ┗ max file age | █ | | | | | | | | █ | | |
|
||||
| ┗ max uploads over time | █ | | | | | | | | | | |
|
||||
| ┗ compress before write | █ | | | | | | | | | | |
|
||||
| ┗ randomize filename | █ | | | | | | | █ | █ | | |
|
||||
| ┗ mimetype reject-list | ╱ | | | | | | | | • | ╱ | |
|
||||
| ┗ extension reject-list | ╱ | | | | | | | █ | • | ╱ | |
|
||||
| checksums provided | | | | █ | █ | | | | █ | ╱ | |
|
||||
| cloud storage backend | ╱ | ╱ | ╱ | █ | █ | █ | ╱ | | | ╱ | █ |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| download folder as zip | █ | █ | █ | █ | █ | | █ | | █ | █ | ╱ | █ |
|
||||
| download folder as tar | █ | | | | | | | | | █ | | |
|
||||
| upload | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| parallel uploads | █ | | | █ | █ | | • | | █ | | █ | |
|
||||
| resumable uploads | █ | | | | | | | | █ | | █ | ╱ |
|
||||
| upload segmenting | █ | | | | | | | █ | █ | | █ | ╱ |
|
||||
| upload acceleration | █ | | | | | | | | █ | | █ | |
|
||||
| upload verification | █ | | | █ | █ | | | | █ | | | |
|
||||
| upload deduplication | █ | | | | █ | | | | █ | | | |
|
||||
| upload a 999 TiB file | █ | | | | █ | █ | • | | █ | | █ | ╱ |
|
||||
| keep last-modified time | █ | | | █ | █ | █ | | | | | | █ |
|
||||
| upload rules | ╱ | ╱ | ╱ | ╱ | ╱ | | | ╱ | ╱ | | ╱ | ╱ |
|
||||
| ┗ max disk usage | █ | █ | | | █ | | | | █ | | | █ |
|
||||
| ┗ max filesize | █ | | | | | | | █ | | | █ | █ |
|
||||
| ┗ max items in folder | █ | | | | | | | | | | | ╱ |
|
||||
| ┗ max file age | █ | | | | | | | | █ | | | |
|
||||
| ┗ max uploads over time | █ | | | | | | | | | | | ╱ |
|
||||
| ┗ compress before write | █ | | | | | | | | | | | |
|
||||
| ┗ randomize filename | █ | | | | | | | █ | █ | | | |
|
||||
| ┗ mimetype reject-list | ╱ | | | | | | | | • | ╱ | | ╱ |
|
||||
| ┗ extension reject-list | ╱ | | | | | | | █ | • | ╱ | | ╱ |
|
||||
| checksums provided | | | | █ | █ | | | | █ | ╱ | | |
|
||||
| cloud storage backend | ╱ | ╱ | ╱ | █ | █ | █ | ╱ | | | ╱ | █ | █ |
|
||||
|
||||
* `upload segmenting` = files are sliced into chunks, making it possible to upload files larger than 100 MiB on cloudflare for example
|
||||
|
||||
@@ -178,25 +187,29 @@ symbol legend,
|
||||
* can provide checksums for single files on request
|
||||
* can probably do extension/mimetype rejection similar to copyparty
|
||||
* `k`/filegator download-as-zip is not streaming; it creates the full zipfile before download can start
|
||||
* `l`/sftpgo:
|
||||
* resumable/segmented uploads only over SFTP, not over HTTP
|
||||
* upload rules are totals only, not over time
|
||||
* can probably do extension/mimetype rejection similar to copyparty
|
||||
|
||||
|
||||
## protocols and client support
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| serve https | █ | | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| serve webdav | █ | | | █ | █ | █ | █ | | █ | | |
|
||||
| serve ftp | █ | | | | | █ | | | | | |
|
||||
| serve ftps | █ | | | | | █ | | | | | |
|
||||
| serve sftp | | | | | | █ | | | | | |
|
||||
| serve smb/cifs | ╱ | | | | | █ | | | | | |
|
||||
| serve dlna | | | | | | █ | | | | | |
|
||||
| listen on unix-socket | | | | █ | █ | | █ | █ | █ | | █ |
|
||||
| zeroconf | █ | | | | | | | | | | |
|
||||
| supports netscape 4 | ╱ | | | | | █ | | | | | • |
|
||||
| ...internet explorer 6 | ╱ | █ | | █ | | █ | | | | | • |
|
||||
| mojibake filenames | █ | | | • | • | █ | █ | • | • | • | |
|
||||
| undecodable filenames | █ | | | • | • | █ | | • | • | | |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| serve https | █ | | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| serve webdav | █ | | | █ | █ | █ | █ | | █ | | | █ |
|
||||
| serve ftp | █ | | | | | █ | | | | | | █ |
|
||||
| serve ftps | █ | | | | | █ | | | | | | █ |
|
||||
| serve sftp | | | | | | █ | | | | | | █ |
|
||||
| serve smb/cifs | ╱ | | | | | █ | | | | | | |
|
||||
| serve dlna | | | | | | █ | | | | | | |
|
||||
| listen on unix-socket | | | | █ | █ | | █ | █ | █ | | █ | █ |
|
||||
| zeroconf | █ | | | | | | | | | | | |
|
||||
| supports netscape 4 | ╱ | | | | | █ | | | | | • | |
|
||||
| ...internet explorer 6 | ╱ | █ | | █ | | █ | | | | | • | |
|
||||
| mojibake filenames | █ | | | • | • | █ | █ | • | • | • | | ╱ |
|
||||
| undecodable filenames | █ | | | • | • | █ | | • | • | | | ╱ |
|
||||
|
||||
* `webdav` = protocol convenient for mounting a remote server as a local filesystem; see zeroconf:
|
||||
* `zeroconf` = the server announces itself on the LAN, [automatically appearing](https://user-images.githubusercontent.com/241032/215344737-0eae8d98-9496-4256-9aa8-cd2f6971810d.png) on other zeroconf-capable devices
|
||||
@@ -206,57 +219,62 @@ symbol legend,
|
||||
* `a`/copyparty remarks:
|
||||
* extremely minimal samba/cifs server
|
||||
* netscape 4 / ie6 support is mostly listed as a joke altho some people have actually found it useful ([ie4 tho](https://user-images.githubusercontent.com/241032/118192791-fb31fe00-b446-11eb-9647-898ea8efc1f7.png))
|
||||
* `l`/sftpgo translates mojibake filenames into valid utf-8 (information loss)
|
||||
|
||||
|
||||
## server configuration
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| config from cmd args | █ | | | | | █ | █ | | | █ | |
|
||||
| config files | █ | █ | █ | ╱ | ╱ | █ | | █ | | █ | • |
|
||||
| runtime config reload | █ | █ | █ | | | | | █ | █ | █ | █ |
|
||||
| same-port http / https | █ | | | | | | | | | | |
|
||||
| listen multiple ports | █ | | | | | | | | | | |
|
||||
| virtual file system | █ | █ | █ | | | | █ | | | | |
|
||||
| reverse-proxy ok | █ | | █ | █ | █ | █ | █ | █ | • | • | • |
|
||||
| folder-rproxy ok | █ | | | | █ | █ | | • | • | • | • |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| config from cmd args | █ | | | | | █ | █ | | | █ | | ╱ |
|
||||
| config files | █ | █ | █ | ╱ | ╱ | █ | | █ | | █ | • | ╱ |
|
||||
| runtime config reload | █ | █ | █ | | | | | █ | █ | █ | █ | |
|
||||
| same-port http / https | █ | | | | | | | | | | | |
|
||||
| listen multiple ports | █ | | | | | | | | | | | █ |
|
||||
| virtual file system | █ | █ | █ | | | | █ | | | | | █ |
|
||||
| reverse-proxy ok | █ | | █ | █ | █ | █ | █ | █ | • | • | • | █ |
|
||||
| folder-rproxy ok | █ | | | | █ | █ | | • | • | • | • | |
|
||||
|
||||
* `folder-rproxy` = reverse-proxying without dedicating an entire (sub)domain, using a subfolder instead
|
||||
* `l`/sftpgo:
|
||||
* config: users must be added through gui / api calls
|
||||
|
||||
|
||||
## server capabilities
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| accounts | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| single-sign-on | | | | █ | █ | | | | • | | |
|
||||
| token auth | | | | █ | █ | | | █ | | | |
|
||||
| per-volume permissions | █ | █ | █ | █ | █ | █ | █ | | █ | █ | ╱ |
|
||||
| per-folder permissions | ╱ | | | █ | █ | | █ | | █ | █ | ╱ |
|
||||
| per-file permissions | | | | █ | █ | | █ | | █ | | |
|
||||
| per-file passwords | █ | | | █ | █ | | █ | | █ | | |
|
||||
| unmap subfolders | █ | | | | | | █ | | | █ | ╱ |
|
||||
| index.html blocks list | | | | | | | █ | | | • | |
|
||||
| write-only folders | █ | | | | | | | | | | █ |
|
||||
| files stored as-is | █ | █ | █ | █ | | █ | █ | | | █ | █ |
|
||||
| file versioning | | | | █ | █ | | | | | | |
|
||||
| file encryption | | | | █ | █ | █ | | | | | |
|
||||
| file indexing | █ | | █ | █ | █ | | | █ | █ | █ | |
|
||||
| ┗ per-volume db | █ | | • | • | • | | | • | • | | |
|
||||
| ┗ db stored in folder | █ | | | | | | | • | • | █ | |
|
||||
| ┗ db stored out-of-tree | █ | | █ | █ | █ | | | • | • | █ | |
|
||||
| ┗ existing file tree | █ | | █ | | | | | | | █ | |
|
||||
| file action event hooks | █ | | | | | | | | | █ | |
|
||||
| one-way folder sync | █ | | | █ | █ | █ | | | | | |
|
||||
| full sync | | | | █ | █ | | | | | | |
|
||||
| speed throttle | | █ | █ | | | █ | | | █ | | |
|
||||
| anti-bruteforce | █ | █ | █ | █ | █ | | | | • | | |
|
||||
| dyndns updater | | █ | | | | | | | | | |
|
||||
| self-updater | | | █ | | | | | | | | |
|
||||
| log rotation | █ | | █ | █ | █ | | | • | █ | | |
|
||||
| upload tracking / log | █ | █ | • | █ | █ | | | █ | █ | | |
|
||||
| curl-friendly ls | █ | | | | | | | | | | |
|
||||
| curl-friendly upload | █ | | | | | █ | █ | • | | | |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| accounts | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ | █ |
|
||||
| per-account chroot | | | | | | | | | | | | █ |
|
||||
| single-sign-on | | | | █ | █ | | | | • | | | |
|
||||
| token auth | | | | █ | █ | | | █ | | | | |
|
||||
| 2fa | | | | █ | █ | | | | | | | █ |
|
||||
| per-volume permissions | █ | █ | █ | █ | █ | █ | █ | | █ | █ | ╱ | █ |
|
||||
| per-folder permissions | ╱ | | | █ | █ | | █ | | █ | █ | ╱ | █ |
|
||||
| per-file permissions | | | | █ | █ | | █ | | █ | | | |
|
||||
| per-file passwords | █ | | | █ | █ | | █ | | █ | | | |
|
||||
| unmap subfolders | █ | | | | | | █ | | | █ | ╱ | • |
|
||||
| index.html blocks list | | | | | | | █ | | | • | | |
|
||||
| write-only folders | █ | | | | | | | | | | █ | █ |
|
||||
| files stored as-is | █ | █ | █ | █ | | █ | █ | | | █ | █ | █ |
|
||||
| file versioning | | | | █ | █ | | | | | | | |
|
||||
| file encryption | | | | █ | █ | █ | | | | | | █ |
|
||||
| file indexing | █ | | █ | █ | █ | | | █ | █ | █ | | |
|
||||
| ┗ per-volume db | █ | | • | • | • | | | • | • | | | |
|
||||
| ┗ db stored in folder | █ | | | | | | | • | • | █ | | |
|
||||
| ┗ db stored out-of-tree | █ | | █ | █ | █ | | | • | • | █ | | |
|
||||
| ┗ existing file tree | █ | | █ | | | | | | | █ | | |
|
||||
| file action event hooks | █ | | | | | | | | | █ | | █ |
|
||||
| one-way folder sync | █ | | | █ | █ | █ | | | | | | |
|
||||
| full sync | | | | █ | █ | | | | | | | |
|
||||
| speed throttle | | █ | █ | | | █ | | | █ | | | █ |
|
||||
| anti-bruteforce | █ | █ | █ | █ | █ | | | | • | | | █ |
|
||||
| dyndns updater | | █ | | | | | | | | | | |
|
||||
| self-updater | | | █ | | | | | | | | | |
|
||||
| log rotation | █ | | █ | █ | █ | | | • | █ | | | █ |
|
||||
| upload tracking / log | █ | █ | • | █ | █ | | | █ | █ | | | ╱ |
|
||||
| curl-friendly ls | █ | | | | | | | | | | | |
|
||||
| curl-friendly upload | █ | | | | | █ | █ | • | | | | |
|
||||
|
||||
* `unmap subfolders` = "shadowing"; mounting a local folder in the middle of an existing filesystem tree in order to disable access below that path
|
||||
* `files stored as-is` = uploaded files are trivially readable from the server HDD, not sliced into chunks or in weird folder structures or anything like that
|
||||
@@ -277,49 +295,52 @@ symbol legend,
|
||||
* `k`/filegator remarks:
|
||||
* `per-* permissions` -- can limit a user to one folder and its subfolders
|
||||
* `unmap subfolders` -- can globally filter a list of paths
|
||||
* `l`/sftpgo:
|
||||
* `file action event hooks` also include on-download triggers
|
||||
* `upload tracking / log` in main logfile
|
||||
|
||||
|
||||
## client features
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ---------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| single-page app | █ | | █ | █ | █ | | | █ | █ | █ | █ |
|
||||
| themes | █ | █ | | █ | | | | | █ | | |
|
||||
| directory tree nav | █ | ╱ | | | █ | | | | █ | | ╱ |
|
||||
| multi-column sorting | █ | | | | | | | | | | |
|
||||
| thumbnails | █ | | | ╱ | ╱ | | | █ | █ | ╱ | |
|
||||
| ┗ image thumbnails | █ | | | █ | █ | | | █ | █ | █ | |
|
||||
| ┗ video thumbnails | █ | | | █ | █ | | | | █ | | |
|
||||
| ┗ audio spectrograms | █ | | | | | | | | | | |
|
||||
| audio player | █ | | | █ | █ | | | | █ | ╱ | |
|
||||
| ┗ gapless playback | █ | | | | | | | | • | | |
|
||||
| ┗ audio equalizer | █ | | | | | | | | | | |
|
||||
| ┗ waveform seekbar | █ | | | | | | | | | | |
|
||||
| ┗ OS integration | █ | | | | | | | | | | |
|
||||
| ┗ transcode to lossy | █ | | | | | | | | | | |
|
||||
| video player | █ | | | █ | █ | | | | █ | █ | |
|
||||
| ┗ video transcoding | | | | | | | | | █ | | |
|
||||
| audio BPM detector | █ | | | | | | | | | | |
|
||||
| audio key detector | █ | | | | | | | | | | |
|
||||
| search by path / name | █ | █ | █ | █ | █ | | █ | | █ | █ | ╱ |
|
||||
| search by date / size | █ | | | | █ | | | █ | █ | | |
|
||||
| search by bpm / key | █ | | | | | | | | | | |
|
||||
| search by custom tags | | | | | | | | █ | █ | | |
|
||||
| search in file contents | | | | █ | █ | | | | █ | | |
|
||||
| search by custom parser | █ | | | | | | | | | | |
|
||||
| find local file | █ | | | | | | | | | | |
|
||||
| undo recent uploads | █ | | | | | | | | | | |
|
||||
| create directories | █ | | | █ | █ | ╱ | █ | █ | █ | █ | █ |
|
||||
| image viewer | █ | | | █ | █ | | | | █ | █ | █ |
|
||||
| markdown viewer | █ | | | | █ | | | | █ | ╱ | ╱ |
|
||||
| markdown editor | █ | | | | █ | | | | █ | ╱ | ╱ |
|
||||
| readme.md in listing | █ | | | █ | | | | | | | |
|
||||
| rename files | █ | █ | █ | █ | █ | ╱ | █ | | █ | █ | █ |
|
||||
| batch rename | █ | | | | | | | | █ | | |
|
||||
| cut / paste files | █ | █ | | █ | █ | | | | █ | | |
|
||||
| move files | █ | █ | | █ | █ | | █ | | █ | █ | █ |
|
||||
| delete files | █ | █ | | █ | █ | ╱ | █ | █ | █ | █ | █ |
|
||||
| copy files | | | | | █ | | | | █ | █ | █ |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ---------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| single-page app | █ | | █ | █ | █ | | | █ | █ | █ | █ | |
|
||||
| themes | █ | █ | | █ | | | | | █ | | | |
|
||||
| directory tree nav | █ | ╱ | | | █ | | | | █ | | ╱ | |
|
||||
| multi-column sorting | █ | | | | | | | | | | | |
|
||||
| thumbnails | █ | | | ╱ | ╱ | | | █ | █ | ╱ | | |
|
||||
| ┗ image thumbnails | █ | | | █ | █ | | | █ | █ | █ | | |
|
||||
| ┗ video thumbnails | █ | | | █ | █ | | | | █ | | | |
|
||||
| ┗ audio spectrograms | █ | | | | | | | | | | | |
|
||||
| audio player | █ | | | █ | █ | | | | █ | ╱ | | |
|
||||
| ┗ gapless playback | █ | | | | | | | | • | | | |
|
||||
| ┗ audio equalizer | █ | | | | | | | | | | | |
|
||||
| ┗ waveform seekbar | █ | | | | | | | | | | | |
|
||||
| ┗ OS integration | █ | | | | | | | | | | | |
|
||||
| ┗ transcode to lossy | █ | | | | | | | | | | | |
|
||||
| video player | █ | | | █ | █ | | | | █ | █ | | |
|
||||
| ┗ video transcoding | | | | | | | | | █ | | | |
|
||||
| audio BPM detector | █ | | | | | | | | | | | |
|
||||
| audio key detector | █ | | | | | | | | | | | |
|
||||
| search by path / name | █ | █ | █ | █ | █ | | █ | | █ | █ | ╱ | |
|
||||
| search by date / size | █ | | | | █ | | | █ | █ | | | |
|
||||
| search by bpm / key | █ | | | | | | | | | | | |
|
||||
| search by custom tags | | | | | | | | █ | █ | | | |
|
||||
| search in file contents | | | | █ | █ | | | | █ | | | |
|
||||
| search by custom parser | █ | | | | | | | | | | | |
|
||||
| find local file | █ | | | | | | | | | | | |
|
||||
| undo recent uploads | █ | | | | | | | | | | | |
|
||||
| create directories | █ | | | █ | █ | ╱ | █ | █ | █ | █ | █ | █ |
|
||||
| image viewer | █ | | | █ | █ | | | | █ | █ | █ | |
|
||||
| markdown viewer | █ | | | | █ | | | | █ | ╱ | ╱ | |
|
||||
| markdown editor | █ | | | | █ | | | | █ | ╱ | ╱ | |
|
||||
| readme.md in listing | █ | | | █ | | | | | | | | |
|
||||
| rename files | █ | █ | █ | █ | █ | ╱ | █ | | █ | █ | █ | █ |
|
||||
| batch rename | █ | | | | | | | | █ | | | |
|
||||
| cut / paste files | █ | █ | | █ | █ | | | | █ | | | |
|
||||
| move files | █ | █ | | █ | █ | | █ | | █ | █ | █ | |
|
||||
| delete files | █ | █ | | █ | █ | ╱ | █ | █ | █ | █ | █ | █ |
|
||||
| copy files | | | | | █ | | | | █ | █ | █ | |
|
||||
|
||||
* `single-page app` = multitasking; possible to continue navigating while uploading
|
||||
* `audio player » os-integration` = use the [lockscreen](https://user-images.githubusercontent.com/241032/142711926-0700be6c-3e31-47b3-9928-53722221f722.png) or [media hotkeys](https://user-images.githubusercontent.com/241032/215347492-b4250797-6c90-4e09-9a4c-721edf2fb15c.png) to play/pause, prev/next song
|
||||
@@ -335,20 +356,21 @@ symbol legend,
|
||||
|
||||
## integration
|
||||
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| OS alert on upload | █ | | | | | | | | | ╱ | |
|
||||
| discord | █ | | | | | | | | | ╱ | |
|
||||
| ┗ announce uploads | █ | | | | | | | | | | |
|
||||
| ┗ custom embeds | | | | | | | | | | | |
|
||||
| sharex | █ | | | █ | | █ | ╱ | █ | | | |
|
||||
| flameshot | | | | | | █ | | | | | |
|
||||
| feature / software | a | b | c | d | e | f | g | h | i | j | k | l |
|
||||
| ----------------------- | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||
| OS alert on upload | █ | | | | | | | | | ╱ | | ╱ |
|
||||
| discord | █ | | | | | | | | | ╱ | | ╱ |
|
||||
| ┗ announce uploads | █ | | | | | | | | | | | ╱ |
|
||||
| ┗ custom embeds | | | | | | | | | | | | ╱ |
|
||||
| sharex | █ | | | █ | | █ | ╱ | █ | | | | |
|
||||
| flameshot | | | | | | █ | | | | | | |
|
||||
|
||||
* sharex `╱` = yes, but does not provide example sharex config
|
||||
* `a`/copyparty remarks:
|
||||
* `OS alert on upload` available as [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/notify.py)
|
||||
* `discord » announce uploads` available as [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/discord-announce.py)
|
||||
* `j`/filebrowser can probably pull those off with command runners similar to copyparty
|
||||
* `l`/sftpgo has nothing built-in but is very extensible
|
||||
|
||||
|
||||
## another matrix
|
||||
@@ -366,6 +388,7 @@ symbol legend,
|
||||
| kodbox | php | ░ gpl3 | 92 MB |
|
||||
| filebrowser | go | █ apl2 | 20 MB |
|
||||
| filegator | php | █ mit | • |
|
||||
| sftpgo | go | ‼ agpl | 44 MB |
|
||||
| updog | python | █ mit | 17 MB |
|
||||
| goshs | go | █ mit | 11 MB |
|
||||
| gimme-that | python | █ mit | 4.8 MB |
|
||||
@@ -379,6 +402,7 @@ symbol legend,
|
||||
# reviews
|
||||
|
||||
* ✅ are advantages over copyparty
|
||||
* 💾 are what copyparty offers as an alternative
|
||||
* 🔵 are similarities
|
||||
* ⚠️ are disadvantages (something copyparty does "better")
|
||||
|
||||
@@ -412,10 +436,11 @@ symbol legend,
|
||||
* ⚠️ http/webdav only; no ftp, zeroconf
|
||||
* ⚠️ less awesome music player
|
||||
* ⚠️ doesn't run on android or ipads
|
||||
* ⚠️ AGPL licensed
|
||||
* ✅ great ui/ux
|
||||
* ✅ config gui
|
||||
* ✅ apps (android / iphone)
|
||||
* copyparty: android upload-only app
|
||||
* 💾 android upload-only app + iPhone upload shortcut
|
||||
* ✅ more granular permissions (per-file)
|
||||
* ✅ search: fulltext indexing of file contents
|
||||
* ✅ webauthn passwordless authentication
|
||||
@@ -430,10 +455,11 @@ symbol legend,
|
||||
* ⚠️ http/webdav only; no ftp, zeroconf
|
||||
* ⚠️ less awesome music player
|
||||
* ⚠️ doesn't run on android or ipads
|
||||
* ⚠️ AGPL licensed
|
||||
* ✅ great ui/ux
|
||||
* ✅ config gui
|
||||
* ✅ apps (android / iphone)
|
||||
* copyparty: android upload-only app
|
||||
* 💾 android upload-only app + iPhone upload shortcut
|
||||
* ✅ more granular permissions (per-file)
|
||||
* ✅ search: fulltext indexing of file contents
|
||||
|
||||
@@ -467,7 +493,7 @@ symbol legend,
|
||||
* ✅ searchable image tags; delete by tag
|
||||
* ✅ browser extension to upload files to the server
|
||||
* ✅ reject uploads by file extension
|
||||
* copyparty: can reject uploads [by extension](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-extension.py) or [mimetype](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-mimetype.py) using plugins
|
||||
* 💾 can reject uploads [by extension](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-extension.py) or [mimetype](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-mimetype.py) using plugins
|
||||
* ✅ token auth (api keys)
|
||||
|
||||
## [kodbox](https://github.com/kalcaddle/kodbox)
|
||||
@@ -512,6 +538,30 @@ symbol legend,
|
||||
* ⚠️ doesn't support crazy filenames
|
||||
* ⚠️ limited file search
|
||||
|
||||
## [sftpgo](https://github.com/drakkan/sftpgo)
|
||||
* go; cross-platform (windows, linux, mac)
|
||||
* ⚠️ http uploads not resumable / accelerated / integrity-checked
|
||||
* ⚠️ on cloudflare: max upload size 100 MiB
|
||||
* 🔵 sftp uploads are resumable
|
||||
* ⚠️ web UI is very minimal + a bit slow
|
||||
* ⚠️ no thumbnails / image viewer / audio player
|
||||
* ⚠️ basic file manager (no cut/paste/move)
|
||||
* ⚠️ no filesystem indexing / search
|
||||
* ⚠️ doesn't run on phones, tablets
|
||||
* ⚠️ no zeroconf (mdns/ssdp)
|
||||
* ⚠️ AGPL licensed
|
||||
* 🔵 ftp, ftps, webdav
|
||||
* ✅ sftp server
|
||||
* ✅ settings gui
|
||||
* ✅ acme (automatic tls certs)
|
||||
* 💾 relies on caddy/certbot/acme.sh
|
||||
* ✅ at-rest encryption
|
||||
* 💾 relies on LUKS/BitLocker
|
||||
* ✅ can use S3/GCS as storage backend
|
||||
* 💾 relies on rclone-mount
|
||||
* ✅ on-download event hook (otherwise same as copyparty)
|
||||
* ✅ more extensive permissions control
|
||||
|
||||
## [updog](https://github.com/sc0tfree/updog)
|
||||
* python; cross-platform
|
||||
* basic directory listing with upload feature
|
||||
@@ -526,7 +576,7 @@ symbol legend,
|
||||
* ⚠️ uploads not resumable / accelerated / integrity-checked
|
||||
* ⚠️ on cloudflare: max upload size 100 MiB
|
||||
* ✅ cool clipboard widget
|
||||
* copyparty: the markdown editor is an ok substitute
|
||||
* 💾 the markdown editor is an ok substitute
|
||||
* 🔵 read-only and upload-only modes (same as copyparty's write-only)
|
||||
* 🔵 https, webdav, but no ftp
|
||||
|
||||
@@ -538,7 +588,7 @@ symbol legend,
|
||||
* ⚠️ weird folder structure for uploads
|
||||
* ✅ clamav antivirus check on upload! neat
|
||||
* 🔵 optional max-filesize, os-notification on uploads
|
||||
* copyparty: os-notification available as [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/notify.py)
|
||||
* 💾 os-notification available as [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/notify.py)
|
||||
|
||||
## [ass](https://github.com/tycrek/ass)
|
||||
* nodejs; recommends docker
|
||||
@@ -549,12 +599,13 @@ symbol legend,
|
||||
* ⚠️ on cloudflare: max upload size 100 MiB
|
||||
* ✅ token auth
|
||||
* ✅ gps metadata stripping
|
||||
* copyparty: possible with [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/mtag/image-noexif.py)
|
||||
* 💾 possible with [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/mtag/image-noexif.py)
|
||||
* ✅ discord integration (custom embeds, upload webhook)
|
||||
* copyparty: [upload webhook plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/discord-announce.py)
|
||||
* 💾 [upload webhook plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/discord-announce.py)
|
||||
* ✅ reject uploads by mimetype
|
||||
* copyparty: can reject uploads [by extension](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-extension.py) or [mimetype](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-mimetype.py) using plugins
|
||||
* ✅ can use S3 as storage backend; copyparty relies on rclone-mount for that
|
||||
* 💾 can reject uploads [by extension](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-extension.py) or [mimetype](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/reject-mimetype.py) using plugins
|
||||
* ✅ can use S3 as storage backend
|
||||
* 💾 relies on rclone-mount
|
||||
* ✅ custom 404 pages
|
||||
|
||||
## [linx](https://github.com/ZizzyDizzyMC/linx-server/)
|
||||
@@ -564,12 +615,13 @@ symbol legend,
|
||||
* 🔵 some of its unique features have been added to copyparty as former linx users have migrated
|
||||
* file expiration timers, filename randomization
|
||||
* ✅ password-protected files
|
||||
* copyparty: password-protected folders + filekeys to skip the folder password seem to cover most usecases
|
||||
* 💾 password-protected folders + filekeys to skip the folder password seem to cover most usecases
|
||||
* ✅ file deletion keys
|
||||
* ✅ download files as torrents
|
||||
* ✅ remote uploads (send a link to the server and it downloads it)
|
||||
* copyparty: available as [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/wget.py)
|
||||
* ✅ can use S3 as storage backend; copyparty relies on rclone-mount for that
|
||||
* 💾 available as [a plugin](https://github.com/9001/copyparty/blob/hovudstraum/bin/hooks/wget.py)
|
||||
* ✅ can use S3 as storage backend
|
||||
* 💾 relies on rclone-mount
|
||||
|
||||
## [h5ai](https://larsjung.de/h5ai/)
|
||||
* ⚠️ read only; no upload/move/delete
|
||||
@@ -581,7 +633,16 @@ symbol legend,
|
||||
## [autoindex](https://github.com/nielsAD/autoindex)
|
||||
* ⚠️ read only; no upload/move/delete
|
||||
* ✅ directory cache for faster browsing of cloud storage
|
||||
* copyparty: local index/cache for recursive search (names/attrs/tags), but not for browsing
|
||||
* 💾 local index/cache for recursive search (names/attrs/tags), but not for browsing
|
||||
|
||||
## [miniserve](https://github.com/svenstaro/miniserve)
|
||||
* rust; cross-platform (windows, linux, mac)
|
||||
* ⚠️ uploads not resumable / accelerated / integrity-checked
|
||||
* ⚠️ on cloudflare: max upload size 100 MiB
|
||||
* ⚠️ no thumbnails / image viewer / audio player / file manager
|
||||
* ⚠️ no filesystem indexing / search
|
||||
* 🔵 upload, tar/zip download, qr-code
|
||||
* ✅ faster at loading huge folders
|
||||
|
||||
|
||||
# briefly considered
|
||||
|
||||
@@ -14,6 +14,7 @@ docker run --rm -it -u 1000 -p 3923:3923 -v /mnt/nas:/w -v $PWD/cfgdir:/cfg copy
|
||||
* `/cfg` is an optional folder with zero or more config files (*.conf) to load
|
||||
* `copyparty/ac` is the recommended [image edition](#editions)
|
||||
* you can download the image from github instead by replacing `copyparty/ac` with `ghcr.io/9001/copyparty-ac`
|
||||
* if you are using rootless podman, remove `-u 1000`
|
||||
|
||||
i'm unfamiliar with docker-compose and alternatives so let me know if this section could be better 🙏
|
||||
|
||||
|
||||
@@ -9,11 +9,14 @@ tee build2.sh | cmp build.sh && rm build2.sh || {
|
||||
[[ $r =~ [yY] ]] && mv build{2,}.sh && exec ./build.sh
|
||||
}
|
||||
|
||||
./up2k.sh
|
||||
[ -e up2k.sh ] && ./up2k.sh
|
||||
|
||||
uname -s | grep WOW64 && m= || m=32
|
||||
uname -s | grep WOW64 && m=64 || m=32
|
||||
uname -s | grep NT-10 && w10=1 || w7=1
|
||||
[ $w7 ] && pyv=37 || pyv=311
|
||||
esuf=
|
||||
[ $w7 ] && [ $m = 32 ] && esuf=32
|
||||
[ $w7 ] && [ $m = 64 ] && esuf=-winpe64
|
||||
|
||||
appd=$(cygpath.exe "$APPDATA")
|
||||
spkgs=$appd/Python/Python$pyv/site-packages
|
||||
@@ -59,8 +62,7 @@ read a b c d _ < <(
|
||||
sed -r 's/[^0-9]+//;s/[" )]//g;s/[-,]/ /g;s/$/ 0/'
|
||||
)
|
||||
sed -r 's/1,2,3,0/'$a,$b,$c,$d'/;s/1\.2\.3/'$a.$b.$c/ <loader.rc >loader.rc2
|
||||
[ $m ] &&
|
||||
sed -ri 's/copyparty.exe/copyparty32.exe/' loader.rc2
|
||||
sed -ri s/copyparty.exe/copyparty$esuf.exe/ loader.rc2
|
||||
|
||||
excl=(
|
||||
copyparty.broker_mp
|
||||
@@ -105,4 +107,4 @@ base64 | head -c12 >> dist/copyparty.exe
|
||||
|
||||
dist/copyparty.exe --version
|
||||
|
||||
curl -fkT dist/copyparty.exe -b cppwd=wark https://192.168.123.1:3923/copyparty$m.exe
|
||||
curl -fkT dist/copyparty.exe -b cppwd=wark https://192.168.123.1:3923/copyparty$esuf.exe
|
||||
|
||||
@@ -30,6 +30,9 @@ if possible, for performance and security reasons, please use this instead:
|
||||
https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py
|
||||
"""
|
||||
|
||||
if sys.maxsize > 2 ** 32:
|
||||
v = v.replace("32-bit", "64-bit")
|
||||
|
||||
try:
|
||||
print(v.replace("\n", "\n▒▌ ")[1:] + "\n")
|
||||
except:
|
||||
|
||||
@@ -98,7 +98,7 @@ class Cfg(Namespace):
|
||||
def __init__(self, a=None, v=None, c=None):
|
||||
ka = {}
|
||||
|
||||
ex = "daw dav_inf dav_mac dotsrch e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp ed emp force_js getmod hardlink ihead magic never_symlink nid nih no_acode no_athumb no_dav no_dedup no_del no_dupe no_logues no_mv no_readme no_robots no_sb_md no_sb_lg no_scandir no_thumb no_vthumb no_zip nrand nw rand vc xdev xlink xvol"
|
||||
ex = "daw dav_inf dav_mac dotsrch e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp ed emp force_js getmod hardlink ih ihead magic never_symlink nid nih no_acode no_athumb no_dav no_dedup no_del no_dupe no_logues no_mv no_readme no_robots no_sb_md no_sb_lg no_scandir no_thumb no_vthumb no_zip nrand nw rand vc xdev xlink xvol"
|
||||
ka.update(**{k: False for k in ex.split()})
|
||||
|
||||
ex = "dotpart no_rescan no_sendfile no_voldump plain_ip"
|
||||
|
||||
Reference in New Issue
Block a user