copyparty 1.18.9__py3-none-any.whl → 1.19.0__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/__init__.py +0 -4
- copyparty/__main__.py +85 -69
- copyparty/__version__.py +3 -3
- copyparty/authsrv.py +31 -2
- copyparty/cfg.py +2 -0
- copyparty/ftpd.py +7 -2
- copyparty/httpcli.py +87 -31
- copyparty/httpsrv.py +2 -1
- copyparty/mtag.py +5 -1
- copyparty/multicast.py +1 -5
- copyparty/pwhash.py +4 -0
- copyparty/svchub.py +2 -11
- copyparty/tcpsrv.py +16 -6
- copyparty/tftpd.py +1 -1
- copyparty/th_cli.py +2 -2
- copyparty/th_srv.py +68 -2
- copyparty/up2k.py +21 -18
- copyparty/util.py +11 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/md2.js.gz +0 -0
- copyparty/web/mde.js.gz +0 -0
- copyparty/web/rups.html +1 -8
- copyparty/web/rups.js.gz +0 -0
- copyparty/web/shares.js.gz +0 -0
- copyparty/web/splash.html +6 -1
- copyparty/web/splash.js.gz +0 -0
- copyparty/web/svcs.html +1 -0
- copyparty/web/svcs.js.gz +0 -0
- copyparty/web/up2k.js.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.18.9.dist-info → copyparty-1.19.0.dist-info}/METADATA +50 -9
- {copyparty-1.18.9.dist-info → copyparty-1.19.0.dist-info}/RECORD +37 -42
- copyparty/web/dd/2.png +0 -0
- copyparty/web/dd/3.png +0 -0
- copyparty/web/dd/4.png +0 -0
- copyparty/web/dd/5.png +0 -0
- copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.18.9.dist-info → copyparty-1.19.0.dist-info}/WHEEL +0 -0
- {copyparty-1.18.9.dist-info → copyparty-1.19.0.dist-info}/entry_points.txt +0 -0
- {copyparty-1.18.9.dist-info → copyparty-1.19.0.dist-info}/licenses/LICENSE +0 -0
- {copyparty-1.18.9.dist-info → copyparty-1.19.0.dist-info}/top_level.txt +0 -0
copyparty/__init__.py
CHANGED
copyparty/__main__.py
CHANGED
@@ -87,6 +87,10 @@ u = unicode
|
|
87
87
|
printed = []
|
88
88
|
zsid = uuid.uuid4().urn[4:]
|
89
89
|
|
90
|
+
CFG_DEF = [os.environ.get("PRTY_CONFIG", "")]
|
91
|
+
if not CFG_DEF[0]:
|
92
|
+
CFG_DEF.pop()
|
93
|
+
|
90
94
|
|
91
95
|
class RiceFormatter(argparse.HelpFormatter):
|
92
96
|
def __init__(self, *args , **kwargs ) :
|
@@ -524,7 +528,7 @@ def get_sects():
|
|
524
528
|
dedent(
|
525
529
|
"""
|
526
530
|
\033[33m-i\033[0m takes a comma-separated list of interfaces to listen on;
|
527
|
-
IP-addresses and/or
|
531
|
+
IP-addresses, unix-sockets, and/or open file descriptors
|
528
532
|
|
529
533
|
the default (\033[32m-i ::\033[0m) means all IPv4 and IPv6 addresses
|
530
534
|
|
@@ -550,7 +554,9 @@ def get_sects():
|
|
550
554
|
\033[32m-i unix:\033[33m/dev/shm/party.sock\033[0m keeps umask-defined permission
|
551
555
|
(usually \033[33m0600\033[0m) and the same user/group as copyparty
|
552
556
|
|
553
|
-
\033[
|
557
|
+
\033[32m-i fd:\033[33m3\033[0m uses the socket passed to copyparty on file descriptor 3
|
558
|
+
|
559
|
+
\033[33m-p\033[0m (tcp ports) is ignored for unix-sockets and FDs
|
554
560
|
"""
|
555
561
|
),
|
556
562
|
],
|
@@ -566,7 +572,7 @@ def get_sects():
|
|
566
572
|
|
567
573
|
--grp takes groupname:username1,username2,...
|
568
574
|
and groupnames can be used instead of usernames in -v
|
569
|
-
by prefixing the groupname with
|
575
|
+
by prefixing the groupname with @
|
570
576
|
|
571
577
|
list of permissions:
|
572
578
|
"r" (read): list folder contents, download files
|
@@ -904,6 +910,9 @@ def get_sects():
|
|
904
910
|
copyparty will also hash and print any passwords that are non-hashed
|
905
911
|
(password which do not start with '+') and then terminate afterwards
|
906
912
|
|
913
|
+
if you have enabled --usernames then the password
|
914
|
+
must be provided as username:password for hashing
|
915
|
+
|
907
916
|
\033[36m--ah-alg\033[0m specifies the hashing algorithm and a
|
908
917
|
list of optional comma-separated arguments:
|
909
918
|
|
@@ -981,18 +990,19 @@ def build_flags_desc():
|
|
981
990
|
|
982
991
|
|
983
992
|
def add_general(ap, nc, srvname):
|
984
|
-
ap2 = ap.add_argument_group(
|
985
|
-
ap2.add_argument("-c", metavar="PATH", type=u, action="append", help="add config file")
|
993
|
+
ap2 = ap.add_argument_group("general options")
|
994
|
+
ap2.add_argument("-c", metavar="PATH", type=u, default=CFG_DEF, action="append", help="\033[34mREPEATABLE:\033[0m add config file")
|
986
995
|
ap2.add_argument("-nc", metavar="NUM", type=int, default=nc, help="max num clients")
|
987
996
|
ap2.add_argument("-j", metavar="CORES", type=int, default=1, help="max num cpu cores, 0=all")
|
988
|
-
ap2.add_argument("-a", metavar="ACCT", type=u, action="append", help="add account, \033[33mUSER\033[0m:\033[33mPASS\033[0m; example [\033[32med:wark\033[0m]")
|
989
|
-
ap2.add_argument("-v", metavar="VOL", type=u, action="append", help="add volume, \033[33mSRC\033[0m:\033[33mDST\033[0m:\033[33mFLAG\033[0m; examples [\033[32m.::r\033[0m], [\033[32m/mnt/nas/music:/music:r:aed\033[0m], see --help-accounts")
|
990
|
-
ap2.add_argument("--grp", metavar="G:N,N", type=u, action="append", help="add group, \033[33mNAME\033[0m:\033[33mUSER1\033[0m,\033[33mUSER2\033[0m,\033[33m...\033[0m; example [\033[32madmins:ed,foo,bar\033[0m]")
|
997
|
+
ap2.add_argument("-a", metavar="ACCT", type=u, action="append", help="\033[34mREPEATABLE:\033[0m add account, \033[33mUSER\033[0m:\033[33mPASS\033[0m; example [\033[32med:wark\033[0m]")
|
998
|
+
ap2.add_argument("-v", metavar="VOL", type=u, action="append", help="\033[34mREPEATABLE:\033[0m add volume, \033[33mSRC\033[0m:\033[33mDST\033[0m:\033[33mFLAG\033[0m; examples [\033[32m.::r\033[0m], [\033[32m/mnt/nas/music:/music:r:aed\033[0m], see --help-accounts")
|
999
|
+
ap2.add_argument("--grp", metavar="G:N,N", type=u, action="append", help="\033[34mREPEATABLE:\033[0m add group, \033[33mNAME\033[0m:\033[33mUSER1\033[0m,\033[33mUSER2\033[0m,\033[33m...\033[0m; example [\033[32madmins:ed,foo,bar\033[0m]")
|
1000
|
+
ap2.add_argument("--usernames", action="store_true", help="require username and password for login; default is just password")
|
991
1001
|
ap2.add_argument("-ed", action="store_true", help="enable the ?dots url parameter / client option which allows clients to see dotfiles / hidden files (volflag=dots)")
|
992
1002
|
ap2.add_argument("--urlform", metavar="MODE", type=u, default="print,xm", help="how to handle url-form POSTs; see \033[33m--help-urlform\033[0m")
|
993
1003
|
ap2.add_argument("--wintitle", metavar="TXT", type=u, default="cpp @ $pub", help="server terminal title, for example [\033[32m$ip-10.1.2.\033[0m] or [\033[32m$ip-]")
|
994
1004
|
ap2.add_argument("--name", metavar="TXT", type=u, default=srvname, help="server name (displayed topleft in browser and in mDNS)")
|
995
|
-
ap2.add_argument("--mime", metavar="EXT=MIME", type=u, action="append", help="map file \033[33mEXT\033[0mension to \033[33mMIME\033[0mtype, for example [\033[32mjpg=image/jpeg\033[0m]")
|
1005
|
+
ap2.add_argument("--mime", metavar="EXT=MIME", type=u, action="append", help="\033[34mREPEATABLE:\033[0m map file \033[33mEXT\033[0mension to \033[33mMIME\033[0mtype, for example [\033[32mjpg=image/jpeg\033[0m]")
|
996
1006
|
ap2.add_argument("--mimes", action="store_true", help="list default mimetype mapping and exit")
|
997
1007
|
ap2.add_argument("--rmagic", action="store_true", help="do expensive analysis to improve accuracy of returned mimetypes; will make file-downloads, rss, and webdav slower (volflag=rmagic)")
|
998
1008
|
ap2.add_argument("--license", action="store_true", help="show licenses and exit")
|
@@ -1000,7 +1010,7 @@ def add_general(ap, nc, srvname):
|
|
1000
1010
|
|
1001
1011
|
|
1002
1012
|
def add_qr(ap, tty):
|
1003
|
-
ap2 = ap.add_argument_group(
|
1013
|
+
ap2 = ap.add_argument_group("qr options")
|
1004
1014
|
ap2.add_argument("--qr", action="store_true", help="show http:// QR-code on startup")
|
1005
1015
|
ap2.add_argument("--qrs", action="store_true", help="show https:// QR-code on startup")
|
1006
1016
|
ap2.add_argument("--qrl", metavar="PATH", type=u, default="", help="location to include in the url, for example [\033[32mpriv/?pw=hunter2\033[0m]")
|
@@ -1022,7 +1032,7 @@ def add_fs(ap):
|
|
1022
1032
|
|
1023
1033
|
def add_share(ap):
|
1024
1034
|
db_path = os.path.join(E.cfg, "shares.db")
|
1025
|
-
ap2 = ap.add_argument_group(
|
1035
|
+
ap2 = ap.add_argument_group("share-url options")
|
1026
1036
|
ap2.add_argument("--shr", metavar="DIR", type=u, default="", help="toplevel virtual folder for shared files/folders, for example [\033[32m/share\033[0m]")
|
1027
1037
|
ap2.add_argument("--shr-db", metavar="FILE", type=u, default=db_path, help="database to store shares in")
|
1028
1038
|
ap2.add_argument("--shr-adm", metavar="U,U", type=u, default="", help="comma-separated list of users allowed to view/delete any share")
|
@@ -1031,7 +1041,7 @@ def add_share(ap):
|
|
1031
1041
|
|
1032
1042
|
|
1033
1043
|
def add_upload(ap):
|
1034
|
-
ap2 = ap.add_argument_group(
|
1044
|
+
ap2 = ap.add_argument_group("upload options")
|
1035
1045
|
ap2.add_argument("--dotpart", action="store_true", help="dotfile incomplete uploads, hiding them from clients unless \033[33m-ed\033[0m")
|
1036
1046
|
ap2.add_argument("--plain-ip", action="store_true", help="when avoiding filename collisions by appending the uploader's ip to the filename: append the plaintext ip instead of salting and hashing the ip")
|
1037
1047
|
ap2.add_argument("--put-name", metavar="TXT", type=u, default="put-{now.6f}-{cip}.bin", help="filename for nameless uploads (when uploader doesn't provide a name); default is [\033[32mput-UNIXTIME-IP.bin\033[0m] (the \033[32m.6f\033[0m means six decimal places) (volflag=put_name)")
|
@@ -1073,14 +1083,14 @@ def add_upload(ap):
|
|
1073
1083
|
|
1074
1084
|
|
1075
1085
|
def add_network(ap):
|
1076
|
-
ap2 = ap.add_argument_group(
|
1077
|
-
ap2.add_argument("-i", metavar="IP", type=u, default="::", help="IPs and/or unix-sockets to listen on (see \033[33m--help-bind\033[0m). Default: all IPv4 and IPv6")
|
1086
|
+
ap2 = ap.add_argument_group("network options")
|
1087
|
+
ap2.add_argument("-i", metavar="IP", type=u, default="::", help="IPs and/or unix-sockets to listen on (comma-separated list; see \033[33m--help-bind\033[0m). Default: all IPv4 and IPv6")
|
1078
1088
|
ap2.add_argument("-p", metavar="PORT", type=u, default="3923", help="ports to listen on (comma/range); ignored for unix-sockets")
|
1079
1089
|
ap2.add_argument("--ll", action="store_true", help="include link-local IPv4/IPv6 in mDNS replies, even if the NIC has routable IPs (breaks some mDNS clients)")
|
1080
|
-
ap2.add_argument("--rproxy", metavar="DEPTH", type=int, default=
|
1090
|
+
ap2.add_argument("--rproxy", metavar="DEPTH", type=int, default=9999999, help="which ip to associate clients with; [\033[32m0\033[0m]=tcp, [\033[32m1\033[0m]=origin (first x-fwd, unsafe), [\033[32m-1\033[0m]=closest-proxy, [\033[32m-2\033[0m]=second-hop, [\033[32m-3\033[0m]=third-hop")
|
1081
1091
|
ap2.add_argument("--xff-hdr", metavar="NAME", type=u, default="x-forwarded-for", help="if reverse-proxied, which http header to read the client's real ip from")
|
1082
|
-
ap2.add_argument("--xff-src", metavar="CIDR", type=u, default="127.0.0.0/8, ::1/128", help="
|
1083
|
-
ap2.add_argument("--ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m; examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
1092
|
+
ap2.add_argument("--xff-src", metavar="CIDR", type=u, default="127.0.0.0/8, ::1/128", help="list of trusted reverse-proxy CIDRs (comma-separated); only accept the real-ip header (\033[33m--xff-hdr\033[0m) and IdP headers if the incoming connection is from an IP within either of these subnets. Specify [\033[32mlan\033[0m] to allow all LAN / private / non-internet IPs. Can be disabled with [\033[32many\033[0m] if you are behind cloudflare (or similar) and are using \033[32m--xff-hdr=cf-connecting-ip\033[0m (or similar)")
|
1093
|
+
ap2.add_argument("--ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m (comma-separated); examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
1084
1094
|
ap2.add_argument("--rp-loc", metavar="PATH", type=u, default="", help="if reverse-proxying on a location instead of a dedicated domain/subdomain, provide the base location here; example: [\033[32m/foo/bar\033[0m]")
|
1085
1095
|
if ANYWIN:
|
1086
1096
|
ap2.add_argument("--reuseaddr", action="store_true", help="set reuseaddr on listening sockets on windows; allows rapid restart of copyparty at the expense of being able to accidentally start multiple instances")
|
@@ -1098,10 +1108,10 @@ def add_network(ap):
|
|
1098
1108
|
|
1099
1109
|
|
1100
1110
|
def add_tls(ap, cert_path):
|
1101
|
-
ap2 = ap.add_argument_group(
|
1111
|
+
ap2 = ap.add_argument_group("SSL/TLS options")
|
1102
1112
|
ap2.add_argument("--http-only", action="store_true", help="disable ssl/tls -- force plaintext")
|
1103
1113
|
ap2.add_argument("--https-only", action="store_true", help="disable plaintext -- force tls")
|
1104
|
-
ap2.add_argument("--cert", metavar="PATH", type=u, default=cert_path, help="path to TLS certificate")
|
1114
|
+
ap2.add_argument("--cert", metavar="PATH", type=u, default=cert_path, help="path to file containing a concatenation of TLS key and certificate chain")
|
1105
1115
|
ap2.add_argument("--ssl-ver", metavar="LIST", type=u, default="", help="set allowed ssl/tls versions; [\033[32mhelp\033[0m] shows available versions; default is what your python version considers safe")
|
1106
1116
|
ap2.add_argument("--ciphers", metavar="LIST", type=u, default="", help="set allowed ssl/tls ciphers; [\033[32mhelp\033[0m] shows available ciphers")
|
1107
1117
|
ap2.add_argument("--ssl-dbg", action="store_true", help="dump some tls info")
|
@@ -1110,7 +1120,7 @@ def add_tls(ap, cert_path):
|
|
1110
1120
|
|
1111
1121
|
def add_cert(ap, cert_path):
|
1112
1122
|
cert_dir = os.path.dirname(cert_path)
|
1113
|
-
ap2 = ap.add_argument_group(
|
1123
|
+
ap2 = ap.add_argument_group("TLS certificate generator options")
|
1114
1124
|
ap2.add_argument("--no-crt", action="store_true", help="disable automatic certificate creation")
|
1115
1125
|
ap2.add_argument("--crt-ns", metavar="N,N", type=u, default="", help="comma-separated list of FQDNs (domains) to add into the certificate")
|
1116
1126
|
ap2.add_argument("--crt-exact", action="store_true", help="do not add wildcard entries for each \033[33m--crt-ns\033[0m")
|
@@ -1130,7 +1140,7 @@ def add_cert(ap, cert_path):
|
|
1130
1140
|
def add_auth(ap):
|
1131
1141
|
idp_db = os.path.join(E.cfg, "idp.db")
|
1132
1142
|
ses_db = os.path.join(E.cfg, "sessions.db")
|
1133
|
-
ap2 = ap.add_argument_group(
|
1143
|
+
ap2 = ap.add_argument_group("IdP / identity provider / user authentication options")
|
1134
1144
|
ap2.add_argument("--idp-h-usr", metavar="HN", type=u, default="", help="bypass the copyparty authentication checks if the request-header \033[33mHN\033[0m contains a username to associate the request with (for use with authentik/oauth/...)\n\033[1;31mWARNING:\033[0m if you enable this, make sure clients are unable to specify this header themselves; must be washed away and replaced by a reverse-proxy")
|
1135
1145
|
ap2.add_argument("--idp-h-grp", metavar="HN", type=u, default="", help="assume the request-header \033[33mHN\033[0m contains the groupname of the requesting user; can be referenced in config files for group-based access control")
|
1136
1146
|
ap2.add_argument("--idp-h-key", metavar="HN", type=u, default="", help="optional but recommended safeguard; your reverse-proxy will insert a secret header named \033[33mHN\033[0m into all requests, and the other IdP headers will be ignored if this header is not present")
|
@@ -1138,19 +1148,20 @@ def add_auth(ap):
|
|
1138
1148
|
ap2.add_argument("--idp-db", metavar="PATH", type=u, default=idp_db, help="where to store the known IdP users/groups (if you run multiple copyparty instances, make sure they use different DBs)")
|
1139
1149
|
ap2.add_argument("--idp-store", metavar="N", type=int, default=1, help="how to use \033[33m--idp-db\033[0m; [\033[32m0\033[0m] = entirely disable, [\033[32m1\033[0m] = write-only (effectively disabled), [\033[32m2\033[0m] = remember users, [\033[32m3\033[0m] = remember users and groups.\nNOTE: Will remember and restore the IdP-volumes of all users for all eternity if set to 2 or 3, even when user is deleted from your IdP")
|
1140
1150
|
ap2.add_argument("--idp-adm", metavar="U,U", type=u, default="", help="comma-separated list of users allowed to use /?idp (the cache management UI)")
|
1151
|
+
ap2.add_argument("--idp-cookie", metavar="S", type=int, default=0, help="generate a session-token for IdP users which is written to cookie \033[33mcppws\033[0m (or \033[33mcppwd\033[0m if plaintext), to reduce the load on the IdP server, lifetime \033[33mS\033[0m seconds.\n └─note: The expiration time is a client hint only; the actual lifetime of the session-token is infinite (until next restart with \033[33m--ses-db\033[0m wiped)")
|
1141
1152
|
ap2.add_argument("--no-bauth", action="store_true", help="disable basic-authentication support; do not accept passwords from the 'Authenticate' header at all. NOTE: This breaks support for the android app")
|
1142
1153
|
ap2.add_argument("--bauth-last", action="store_true", help="keeps basic-authentication enabled, but only as a last-resort; if a cookie is also provided then the cookie wins")
|
1143
1154
|
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
1144
1155
|
ap2.add_argument("--ses-len", metavar="CHARS", type=int, default=20, help="session key length; default is 120 bits ((20//4)*4*6)")
|
1145
1156
|
ap2.add_argument("--no-ses", action="store_true", help="disable sessions; use plaintext passwords in cookies")
|
1146
|
-
ap2.add_argument("--ipu", metavar="CIDR=USR", type=u, action="append", help="users with IP matching \033[33mCIDR\033[0m are auto-authenticated as username \033[33mUSR\033[0m; example: [\033[32m172.16.24.0/24=dave]")
|
1157
|
+
ap2.add_argument("--ipu", metavar="CIDR=USR", type=u, action="append", help="\033[34mREPEATABLE:\033[0m users with IP matching \033[33mCIDR\033[0m are auto-authenticated as username \033[33mUSR\033[0m; example: [\033[32m172.16.24.0/24=dave]")
|
1147
1158
|
|
1148
1159
|
|
1149
1160
|
def add_chpw(ap):
|
1150
1161
|
db_path = os.path.join(E.cfg, "chpw.json")
|
1151
|
-
ap2 = ap.add_argument_group(
|
1162
|
+
ap2 = ap.add_argument_group("user-changeable passwords options")
|
1152
1163
|
ap2.add_argument("--chpw", action="store_true", help="allow users to change their own passwords")
|
1153
|
-
ap2.add_argument("--chpw-no", metavar="U,U,U", type=u, action="append", help="do not allow password-changes for this comma-separated list of usernames")
|
1164
|
+
ap2.add_argument("--chpw-no", metavar="U,U,U", type=u, action="append", help="\033[34mREPEATABLE:\033[0m do not allow password-changes for this comma-separated list of usernames")
|
1154
1165
|
ap2.add_argument("--chpw-db", metavar="PATH", type=u, default=db_path, help="where to store the passwords database (if you run multiple copyparty instances, make sure they use different DBs)")
|
1155
1166
|
ap2.add_argument("--chpw-len", metavar="N", type=int, default=8, help="minimum password length")
|
1156
1167
|
ap2.add_argument("--chpw-v", metavar="LVL", type=int, default=2, help="verbosity of summary on config load [\033[32m0\033[0m] = nothing at all, [\033[32m1\033[0m] = number of users, [\033[32m2\033[0m] = list users with default-pw, [\033[32m3\033[0m] = list all users")
|
@@ -1199,12 +1210,12 @@ def add_zc_ssdp(ap):
|
|
1199
1210
|
|
1200
1211
|
|
1201
1212
|
def add_ftp(ap):
|
1202
|
-
ap2 = ap.add_argument_group(
|
1213
|
+
ap2 = ap.add_argument_group("FTP options (TCP only)")
|
1203
1214
|
ap2.add_argument("--ftp", metavar="PORT", type=int, default=0, help="enable FTP server on \033[33mPORT\033[0m, for example \033[32m3921")
|
1204
1215
|
ap2.add_argument("--ftps", metavar="PORT", type=int, default=0, help="enable FTPS server on \033[33mPORT\033[0m, for example \033[32m3990")
|
1205
1216
|
ap2.add_argument("--ftpv", action="store_true", help="verbose")
|
1206
1217
|
ap2.add_argument("--ftp4", action="store_true", help="only listen on IPv4")
|
1207
|
-
ap2.add_argument("--ftp-ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m; specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m. Examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
1218
|
+
ap2.add_argument("--ftp-ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m (comma-separated); specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m. Examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
1208
1219
|
ap2.add_argument("--ftp-no-ow", action="store_true", help="if target file exists, reject upload instead of overwrite")
|
1209
1220
|
ap2.add_argument("--ftp-wt", metavar="SEC", type=int, default=7, help="grace period for resuming interrupted uploads (any client can write to any file last-modified more recently than \033[33mSEC\033[0m seconds ago)")
|
1210
1221
|
ap2.add_argument("--ftp-nat", metavar="ADDR", type=u, default="", help="the NAT address to use for passive connections")
|
@@ -1212,7 +1223,7 @@ def add_ftp(ap):
|
|
1212
1223
|
|
1213
1224
|
|
1214
1225
|
def add_webdav(ap):
|
1215
|
-
ap2 = ap.add_argument_group(
|
1226
|
+
ap2 = ap.add_argument_group("WebDAV options")
|
1216
1227
|
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)")
|
1217
1228
|
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")
|
1218
1229
|
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)")
|
@@ -1222,7 +1233,7 @@ def add_webdav(ap):
|
|
1222
1233
|
|
1223
1234
|
|
1224
1235
|
def add_tftp(ap):
|
1225
|
-
ap2 = ap.add_argument_group(
|
1236
|
+
ap2 = ap.add_argument_group("TFTP options (UDP only)")
|
1226
1237
|
ap2.add_argument("--tftp", metavar="PORT", type=int, default=0, help="enable TFTP server on \033[33mPORT\033[0m, for example \033[32m69 \033[0mor \033[32m3969")
|
1227
1238
|
ap2.add_argument("--tftp4", action="store_true", help="only listen on IPv4")
|
1228
1239
|
ap2.add_argument("--tftpv", action="store_true", help="verbose")
|
@@ -1230,12 +1241,12 @@ def add_tftp(ap):
|
|
1230
1241
|
ap2.add_argument("--tftp-no-fast", action="store_true", help="debug: disable optimizations")
|
1231
1242
|
ap2.add_argument("--tftp-lsf", metavar="PTN", type=u, default="\\.?(dir|ls)(\\.txt)?", help="return a directory listing if a file with this name is requested and it does not exist; defaults matches .ls, dir, .dir.txt, ls.txt, ...")
|
1232
1243
|
ap2.add_argument("--tftp-nols", action="store_true", help="if someone tries to download a directory, return an error instead of showing its directory listing")
|
1233
|
-
ap2.add_argument("--tftp-ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m; specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m. Examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
1244
|
+
ap2.add_argument("--tftp-ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m (comma-separated); specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m. Examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
1234
1245
|
ap2.add_argument("--tftp-pr", metavar="P-P", type=u, default="", help="the range of UDP ports to use for data transfer, for example \033[32m12000-13000")
|
1235
1246
|
|
1236
1247
|
|
1237
1248
|
def add_smb(ap):
|
1238
|
-
ap2 = ap.add_argument_group(
|
1249
|
+
ap2 = ap.add_argument_group("SMB/CIFS options")
|
1239
1250
|
ap2.add_argument("--smb", action="store_true", help="enable smb (read-only) -- this requires running copyparty as root on linux and macos unless \033[33m--smb-port\033[0m is set above 1024 and your OS does port-forwarding from 445 to that.\n\033[1;31mWARNING:\033[0m this protocol is DANGEROUS and buggy! Never expose to the internet!")
|
1240
1251
|
ap2.add_argument("--smbw", action="store_true", help="enable write support (please dont)")
|
1241
1252
|
ap2.add_argument("--smb1", action="store_true", help="disable SMBv2, only enable SMBv1 (CIFS)")
|
@@ -1249,30 +1260,30 @@ def add_smb(ap):
|
|
1249
1260
|
|
1250
1261
|
|
1251
1262
|
def add_handlers(ap):
|
1252
|
-
ap2 = ap.add_argument_group(
|
1253
|
-
ap2.add_argument("--on404", metavar="PY", type=u, action="append", help="handle 404s by executing \033[33mPY\033[0m file")
|
1254
|
-
ap2.add_argument("--on403", metavar="PY", type=u, action="append", help="handle 403s by executing \033[33mPY\033[0m file")
|
1263
|
+
ap2 = ap.add_argument_group("handlers (see --help-handlers)")
|
1264
|
+
ap2.add_argument("--on404", metavar="PY", type=u, action="append", help="\033[34mREPEATABLE:\033[0m handle 404s by executing \033[33mPY\033[0m file")
|
1265
|
+
ap2.add_argument("--on403", metavar="PY", type=u, action="append", help="\033[34mREPEATABLE:\033[0m handle 403s by executing \033[33mPY\033[0m file")
|
1255
1266
|
ap2.add_argument("--hot-handlers", action="store_true", help="recompile handlers on each request -- expensive but convenient when hacking on stuff")
|
1256
1267
|
|
1257
1268
|
|
1258
1269
|
def add_hooks(ap):
|
1259
|
-
ap2 = ap.add_argument_group(
|
1260
|
-
ap2.add_argument("--xbu", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file upload starts")
|
1261
|
-
ap2.add_argument("--xau", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file upload finishes")
|
1262
|
-
ap2.add_argument("--xiu", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after all uploads finish and volume is idle")
|
1263
|
-
ap2.add_argument("--xbc", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file copy")
|
1264
|
-
ap2.add_argument("--xac", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file copy")
|
1265
|
-
ap2.add_argument("--xbr", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file move/rename")
|
1266
|
-
ap2.add_argument("--xar", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file move/rename")
|
1267
|
-
ap2.add_argument("--xbd", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file delete")
|
1268
|
-
ap2.add_argument("--xad", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file delete")
|
1269
|
-
ap2.add_argument("--xm", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m on message")
|
1270
|
-
ap2.add_argument("--xban", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m if someone gets banned (pw/404/403/url)")
|
1270
|
+
ap2 = ap.add_argument_group("event hooks (see --help-hooks)")
|
1271
|
+
ap2.add_argument("--xbu", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m before a file upload starts")
|
1272
|
+
ap2.add_argument("--xau", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m after a file upload finishes")
|
1273
|
+
ap2.add_argument("--xiu", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m after all uploads finish and volume is idle")
|
1274
|
+
ap2.add_argument("--xbc", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m before a file copy")
|
1275
|
+
ap2.add_argument("--xac", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m after a file copy")
|
1276
|
+
ap2.add_argument("--xbr", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m before a file move/rename")
|
1277
|
+
ap2.add_argument("--xar", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m after a file move/rename")
|
1278
|
+
ap2.add_argument("--xbd", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m before a file delete")
|
1279
|
+
ap2.add_argument("--xad", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m after a file delete")
|
1280
|
+
ap2.add_argument("--xm", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m on message")
|
1281
|
+
ap2.add_argument("--xban", metavar="CMD", type=u, action="append", help="\033[34mREPEATABLE:\033[0m execute \033[33mCMD\033[0m if someone gets banned (pw/404/403/url)")
|
1271
1282
|
ap2.add_argument("--hook-v", action="store_true", help="verbose hooks")
|
1272
1283
|
|
1273
1284
|
|
1274
1285
|
def add_stats(ap):
|
1275
|
-
ap2 = ap.add_argument_group(
|
1286
|
+
ap2 = ap.add_argument_group("grafana/prometheus metrics endpoint")
|
1276
1287
|
ap2.add_argument("--stats", action="store_true", help="enable openmetrics at /.cpr/metrics for admin accounts")
|
1277
1288
|
ap2.add_argument("--nos-hdd", action="store_true", help="disable disk-space metrics (used/free space)")
|
1278
1289
|
ap2.add_argument("--nos-vol", action="store_true", help="disable volume size metrics (num files, total bytes, vmaxb/vmaxn)")
|
@@ -1282,15 +1293,16 @@ def add_stats(ap):
|
|
1282
1293
|
|
1283
1294
|
|
1284
1295
|
def add_yolo(ap):
|
1285
|
-
ap2 = ap.add_argument_group(
|
1296
|
+
ap2 = ap.add_argument_group("yolo options")
|
1286
1297
|
ap2.add_argument("--allow-csrf", action="store_true", help="disable csrf protections; let other domains/sites impersonate you through cross-site requests")
|
1287
1298
|
ap2.add_argument("--cookie-lax", action="store_true", help="allow cookies from other domains (if you follow a link from another website into your server, you will arrive logged-in); this reduces protection against CSRF")
|
1299
|
+
ap2.add_argument("--no-fnugg", action="store_true", help="disable the smoketest for caching-related issues in the web-UI")
|
1288
1300
|
ap2.add_argument("--getmod", action="store_true", help="permit ?move=[...] and ?delete as GET")
|
1289
1301
|
ap2.add_argument("--wo-up-readme", action="store_true", help="allow users with write-only access to upload logues and readmes without adding the _wo_ filename prefix (volflag=wo_up_readme)")
|
1290
1302
|
|
1291
1303
|
|
1292
1304
|
def add_optouts(ap):
|
1293
|
-
ap2 = ap.add_argument_group(
|
1305
|
+
ap2 = ap.add_argument_group("opt-outs")
|
1294
1306
|
ap2.add_argument("-nw", action="store_true", help="never write anything to disk (debug/benchmark)")
|
1295
1307
|
ap2.add_argument("--keep-qem", action="store_true", help="do not disable quick-edit-mode on windows (it is disabled to avoid accidental text selection in the terminal window, as this would pause execution)")
|
1296
1308
|
ap2.add_argument("--no-dav", action="store_true", help="disable webdav support")
|
@@ -1316,7 +1328,7 @@ def add_optouts(ap):
|
|
1316
1328
|
|
1317
1329
|
|
1318
1330
|
def add_safety(ap):
|
1319
|
-
ap2 = ap.add_argument_group(
|
1331
|
+
ap2 = ap.add_argument_group("safety options")
|
1320
1332
|
ap2.add_argument("-s", action="count", default=0, help="increase safety: Disable thumbnails / potentially dangerous software (ffmpeg/pillow/vips), hide partial uploads, avoid crawlers.\n └─Alias of\033[32m --dotpart --no-thumb --no-mtag-ff --no-robots --force-js")
|
1321
1333
|
ap2.add_argument("-ss", action="store_true", help="further increase safety: Prevent js-injection, accidental move/delete, broken symlinks, webdav, 404 on 403, ban on excessive 404s.\n └─Alias of\033[32m -s --unpost=0 --no-del --no-mv --hardlink --vague-403 -nih")
|
1322
1334
|
ap2.add_argument("-sss", action="store_true", help="further increase safety: Enable logging to disk, scan for dangerous symlinks.\n └─Alias of\033[32m -ss --no-dav --no-logues --no-readme -lo=cpp-%%Y-%%m%%d-%%H%%M%%S.txt.xz --ls=**,*,ln,p,r")
|
@@ -1347,7 +1359,7 @@ def add_safety(ap):
|
|
1347
1359
|
|
1348
1360
|
|
1349
1361
|
def add_salt(ap, fk_salt, dk_salt, ah_salt):
|
1350
|
-
ap2 = ap.add_argument_group(
|
1362
|
+
ap2 = ap.add_argument_group("salting options")
|
1351
1363
|
ap2.add_argument("--ah-alg", metavar="ALG", type=u, default="none", help="account-pw hashing algorithm; one of these, best to worst: \033[32margon2 scrypt sha2 none\033[0m (each optionally followed by alg-specific comma-sep. config)")
|
1352
1364
|
ap2.add_argument("--ah-salt", metavar="SALT", type=u, default=ah_salt, help="account-pw salt; ignored if \033[33m--ah-alg\033[0m is none (default)")
|
1353
1365
|
ap2.add_argument("--ah-gen", metavar="PW", type=u, default="", help="generate hashed password for \033[33mPW\033[0m, or read passwords from STDIN if \033[33mPW\033[0m is [\033[32m-\033[0m]")
|
@@ -1361,14 +1373,14 @@ def add_salt(ap, fk_salt, dk_salt, ah_salt):
|
|
1361
1373
|
|
1362
1374
|
|
1363
1375
|
def add_shutdown(ap):
|
1364
|
-
ap2 = ap.add_argument_group(
|
1376
|
+
ap2 = ap.add_argument_group("shutdown options")
|
1365
1377
|
ap2.add_argument("--ign-ebind", action="store_true", help="continue running even if it's impossible to listen on some of the requested endpoints")
|
1366
1378
|
ap2.add_argument("--ign-ebind-all", action="store_true", help="continue running even if it's impossible to receive connections at all")
|
1367
1379
|
ap2.add_argument("--exit", metavar="WHEN", type=u, default="", help="shutdown after \033[33mWHEN\033[0m has finished; [\033[32mcfg\033[0m] config parsing, [\033[32midx\033[0m] volscan + multimedia indexing")
|
1368
1380
|
|
1369
1381
|
|
1370
1382
|
def add_logging(ap):
|
1371
|
-
ap2 = ap.add_argument_group(
|
1383
|
+
ap2 = ap.add_argument_group("logging options")
|
1372
1384
|
ap2.add_argument("-q", action="store_true", help="quiet; disable most STDOUT messages")
|
1373
1385
|
ap2.add_argument("-lo", metavar="PATH", type=u, default="", help="logfile, example: \033[32mcpp-%%Y-%%m%%d-%%H%%M%%S.txt.xz\033[0m (NB: some errors may appear on STDOUT only)")
|
1374
1386
|
ap2.add_argument("--no-ansi", action="store_true", default=not VT100, help="disable colors; same as environment-variable NO_COLOR")
|
@@ -1377,7 +1389,7 @@ def add_logging(ap):
|
|
1377
1389
|
ap2.add_argument("--no-voldump", action="store_true", help="do not list volumes and permissions on startup")
|
1378
1390
|
ap2.add_argument("--log-utc", action="store_true", help="do not use local timezone; assume the TZ env-var is UTC (tiny bit faster)")
|
1379
1391
|
ap2.add_argument("--log-tdec", metavar="N", type=int, default=3, help="timestamp resolution / number of timestamp decimals")
|
1380
|
-
ap2.add_argument("--log-badpwd", metavar="N", type=int, default=
|
1392
|
+
ap2.add_argument("--log-badpwd", metavar="N", type=int, default=2, help="log failed login attempt passwords: 0=terse, 1=plaintext, 2=hashed")
|
1381
1393
|
ap2.add_argument("--log-conn", action="store_true", help="debug: print tcp-server msgs")
|
1382
1394
|
ap2.add_argument("--log-htp", action="store_true", help="debug: print http-server threadpool scaling")
|
1383
1395
|
ap2.add_argument("--ihead", metavar="HEADER", type=u, action='append', help="print request \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
@@ -1386,7 +1398,7 @@ def add_logging(ap):
|
|
1386
1398
|
|
1387
1399
|
|
1388
1400
|
def add_admin(ap):
|
1389
|
-
ap2 = ap.add_argument_group(
|
1401
|
+
ap2 = ap.add_argument_group("admin panel options")
|
1390
1402
|
ap2.add_argument("--no-reload", action="store_true", help="disable ?reload=cfg (reload users/volumes/volflags from config file)")
|
1391
1403
|
ap2.add_argument("--no-rescan", action="store_true", help="disable ?scan (volume reindexing)")
|
1392
1404
|
ap2.add_argument("--no-stack", action="store_true", help="disable ?stack (list all stacks)")
|
@@ -1400,7 +1412,7 @@ def add_admin(ap):
|
|
1400
1412
|
def add_thumbnail(ap):
|
1401
1413
|
th_ram = (RAM_AVAIL or RAM_TOTAL or 9) * 0.6
|
1402
1414
|
th_ram = int(max(min(th_ram, 6), 0.3) * 10) / 10
|
1403
|
-
ap2 = ap.add_argument_group(
|
1415
|
+
ap2 = ap.add_argument_group("thumbnail options")
|
1404
1416
|
ap2.add_argument("--no-thumb", action="store_true", help="disable all thumbnails (volflag=dthumb)")
|
1405
1417
|
ap2.add_argument("--no-vthumb", action="store_true", help="disable video thumbnails (volflag=dvthumb)")
|
1406
1418
|
ap2.add_argument("--no-athumb", action="store_true", help="disable audio thumbnails (spectrograms) (volflag=dathumb)")
|
@@ -1432,9 +1444,11 @@ def add_thumbnail(ap):
|
|
1432
1444
|
|
1433
1445
|
|
1434
1446
|
def add_transcoding(ap):
|
1435
|
-
ap2 = ap.add_argument_group(
|
1447
|
+
ap2 = ap.add_argument_group("transcoding options")
|
1436
1448
|
ap2.add_argument("--q-opus", metavar="KBPS", type=int, default=128, help="target bitrate for transcoding to opus; set 0 to disable")
|
1437
1449
|
ap2.add_argument("--q-mp3", metavar="QUALITY", type=u, default="q2", help="target quality for transcoding to mp3, for example [\033[32m192k\033[0m] (CBR) or [\033[32mq0\033[0m] (CQ/CRF, q0=maxquality, q9=smallest); set 0 to disable")
|
1450
|
+
ap2.add_argument("--allow-wav", action="store_true", help="allow transcoding to wav (lossless, uncompressed)")
|
1451
|
+
ap2.add_argument("--allow-flac", action="store_true", help="allow transcoding to flac (lossless, compressed)")
|
1438
1452
|
ap2.add_argument("--no-caf", action="store_true", help="disable transcoding to caf-opus (affects iOS v12~v17), will use mp3 instead")
|
1439
1453
|
ap2.add_argument("--no-owa", action="store_true", help="disable transcoding to webm-opus (iOS v18 and later), will use mp3 instead")
|
1440
1454
|
ap2.add_argument("--no-acode", action="store_true", help="disable audio transcoding")
|
@@ -1443,7 +1457,7 @@ def add_transcoding(ap):
|
|
1443
1457
|
|
1444
1458
|
|
1445
1459
|
def add_tail(ap):
|
1446
|
-
ap2 = ap.add_argument_group(
|
1460
|
+
ap2 = ap.add_argument_group("tailing options (realtime streaming of a growing file)")
|
1447
1461
|
ap2.add_argument("--tail-who", metavar="LVL", type=int, default=2, help="who can tail? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=authenticated-with-read-access, [\033[32m3\033[0m]=everyone-with-read-access (volflag=tail_who)")
|
1448
1462
|
ap2.add_argument("--tail-cmax", metavar="N", type=int, default=64, help="do not allow starting a new tail if more than \033[33mN\033[0m active downloads")
|
1449
1463
|
ap2.add_argument("--tail-tmax", metavar="SEC", type=float, default=0, help="terminate connection after \033[33mSEC\033[0m seconds; [\033[32m0\033[0m]=never (volflag=tail_tmax)")
|
@@ -1453,7 +1467,7 @@ def add_tail(ap):
|
|
1453
1467
|
|
1454
1468
|
|
1455
1469
|
def add_rss(ap):
|
1456
|
-
ap2 = ap.add_argument_group(
|
1470
|
+
ap2 = ap.add_argument_group("RSS options")
|
1457
1471
|
ap2.add_argument("--rss", action="store_true", help="enable RSS output (experimental) (volflag=rss)")
|
1458
1472
|
ap2.add_argument("--rss-nf", metavar="HITS", type=int, default=250, help="default number of files to return (url-param 'nf')")
|
1459
1473
|
ap2.add_argument("--rss-fext", metavar="E,E", type=u, default="", help="default list of file extensions to include (url-param 'fext'); blank=all")
|
@@ -1462,7 +1476,7 @@ def add_rss(ap):
|
|
1462
1476
|
|
1463
1477
|
def add_db_general(ap, hcores):
|
1464
1478
|
noidx = APPLESAN_TXT if MACOS else ""
|
1465
|
-
ap2 = ap.add_argument_group(
|
1479
|
+
ap2 = ap.add_argument_group("general db options")
|
1466
1480
|
ap2.add_argument("-e2d", action="store_true", help="enable up2k database; this enables file search, upload-undo, improves deduplication")
|
1467
1481
|
ap2.add_argument("-e2ds", action="store_true", help="scan writable folders for new files on startup; sets \033[33m-e2d\033[0m")
|
1468
1482
|
ap2.add_argument("-e2dsa", action="store_true", help="scans all folders on startup; sets \033[33m-e2ds\033[0m")
|
@@ -1491,7 +1505,7 @@ def add_db_general(ap, hcores):
|
|
1491
1505
|
|
1492
1506
|
|
1493
1507
|
def add_db_metadata(ap):
|
1494
|
-
ap2 = ap.add_argument_group(
|
1508
|
+
ap2 = ap.add_argument_group("metadata db options")
|
1495
1509
|
ap2.add_argument("-e2t", action="store_true", help="enable metadata indexing; makes it possible to search for artist/title/codec/resolution/...")
|
1496
1510
|
ap2.add_argument("-e2ts", action="store_true", help="scan newly discovered files for metadata on startup; sets \033[33m-e2t\033[0m")
|
1497
1511
|
ap2.add_argument("-e2tsr", action="store_true", help="delete all metadata from DB and do a full rescan; sets \033[33m-e2ts\033[0m")
|
@@ -1501,15 +1515,16 @@ def add_db_metadata(ap):
|
|
1501
1515
|
ap2.add_argument("--mtag-mt", metavar="CORES", type=int, default=CORES, help="num cpu cores to use for tag scanning")
|
1502
1516
|
ap2.add_argument("--mtag-v", action="store_true", help="verbose tag scanning; print errors from mtp subprocesses and such")
|
1503
1517
|
ap2.add_argument("--mtag-vv", action="store_true", help="debug mtp settings and mutagen/FFprobe parsers")
|
1504
|
-
ap2.add_argument("-mtm", metavar="M=t,t,t", type=u, action="append", help="add/replace metadata mapping")
|
1518
|
+
ap2.add_argument("-mtm", metavar="M=t,t,t", type=u, action="append", help="\033[34mREPEATABLE:\033[0m add/replace metadata mapping")
|
1505
1519
|
ap2.add_argument("-mte", metavar="M,M,M", type=u, help="tags to index/display (comma-sep.); either an entire replacement list, or add/remove stuff on the default-list with +foo or /bar", default=DEF_MTE)
|
1506
1520
|
ap2.add_argument("-mth", metavar="M,M,M", type=u, help="tags to hide by default (comma-sep.); assign/add/remove same as \033[33m-mte\033[0m", default=DEF_MTH)
|
1507
|
-
ap2.add_argument("-mtp", metavar="M=[f,]BIN", type=u, action="append", help="read tag \033[33mM\033[0m using program \033[33mBIN\033[0m to parse the file")
|
1521
|
+
ap2.add_argument("-mtp", metavar="M=[f,]BIN", type=u, action="append", help="\033[34mREPEATABLE:\033[0m read tag \033[33mM\033[0m using program \033[33mBIN\033[0m to parse the file")
|
1508
1522
|
|
1509
1523
|
|
1510
1524
|
def add_txt(ap):
|
1511
|
-
ap2 = ap.add_argument_group(
|
1525
|
+
ap2 = ap.add_argument_group("textfile options")
|
1512
1526
|
ap2.add_argument("--md-hist", metavar="TXT", type=u, default="s", help="where to store old version of markdown files; [\033[32ms\033[0m]=subfolder, [\033[32mv\033[0m]=volume-histpath, [\033[32mn\033[0m]=nope/disabled (volflag=md_hist)")
|
1527
|
+
ap2.add_argument("--txt-eol", metavar="TYPE", type=u, default="", help="enable EOL conversion when writing documents; supported: CRLF, LF (volflag=txt_eol)")
|
1513
1528
|
ap2.add_argument("-mcr", metavar="SEC", type=int, default=60, help="the textfile editor will check for serverside changes every \033[33mSEC\033[0m seconds")
|
1514
1529
|
ap2.add_argument("-emp", action="store_true", help="enable markdown plugins -- neat but dangerous, big XSS risk")
|
1515
1530
|
ap2.add_argument("--exp", action="store_true", help="enable textfile expansion -- replace {{self.ip}} and such; see \033[33m--help-exp\033[0m (volflag=exp)")
|
@@ -1519,7 +1534,7 @@ def add_txt(ap):
|
|
1519
1534
|
|
1520
1535
|
|
1521
1536
|
def add_og(ap):
|
1522
|
-
ap2 = ap.add_argument_group(
|
1537
|
+
ap2 = ap.add_argument_group("og / open graph / discord-embed options")
|
1523
1538
|
ap2.add_argument("--og", action="store_true", help="disable hotlinking and return an html document instead; this is required by open-graph, but can also be useful on its own (volflag=og)")
|
1524
1539
|
ap2.add_argument("--og-ua", metavar="RE", type=u, default="", help="only disable hotlinking / engage OG behavior if the useragent matches regex \033[33mRE\033[0m (volflag=og_ua)")
|
1525
1540
|
ap2.add_argument("--og-tpl", metavar="PATH", type=u, default="", help="do not return the regular copyparty html, but instead load the jinja2 template at \033[33mPATH\033[0m (if path contains 'EXT' then EXT will be replaced with the requested file's extension) (volflag=og_tpl)")
|
@@ -1537,7 +1552,7 @@ def add_og(ap):
|
|
1537
1552
|
|
1538
1553
|
|
1539
1554
|
def add_ui(ap, retry):
|
1540
|
-
ap2 = ap.add_argument_group(
|
1555
|
+
ap2 = ap.add_argument_group("ui options")
|
1541
1556
|
ap2.add_argument("--grid", action="store_true", help="show grid/thumbnails by default (volflag=grid)")
|
1542
1557
|
ap2.add_argument("--gsel", action="store_true", help="select files in grid by ctrl-click (volflag=gsel)")
|
1543
1558
|
ap2.add_argument("--localtime", action="store_true", help="default to local timezone instead of UTC")
|
@@ -1552,8 +1567,8 @@ def add_ui(ap, retry):
|
|
1552
1567
|
ap2.add_argument("--qdel", metavar="LVL", type=int, default=2, help="number of confirmations to show when deleting files (2/1/0)")
|
1553
1568
|
ap2.add_argument("--unlist", metavar="REGEX", type=u, default="", help="don't show files/folders matching \033[33mREGEX\033[0m in file list. WARNING: Purely cosmetic! Does not affect API calls, just the browser. Example: [\033[32m\\.(js|css)$\033[0m] (volflag=unlist)")
|
1554
1569
|
ap2.add_argument("--favico", metavar="TXT", type=u, default="c 000 none" if retry else "🎉 000 none", help="\033[33mfavicon-text\033[0m [ \033[33mforeground\033[0m [ \033[33mbackground\033[0m ] ], set blank to disable")
|
1555
|
-
ap2.add_argument("--ext-th", metavar="E=VP", type=u, action="append", help="use thumbnail-image \033[33mVP\033[0m for file-extension \033[33mE\033[0m, example: [\033[32mexe=/.res/exe.png\033[0m] (volflag=ext_th)")
|
1556
|
-
ap2.add_argument("--mpmc",
|
1570
|
+
ap2.add_argument("--ext-th", metavar="E=VP", type=u, action="append", help="\033[34mREPEATABLE:\033[0m use thumbnail-image \033[33mVP\033[0m for file-extension \033[33mE\033[0m, example: [\033[32mexe=/.res/exe.png\033[0m] (volflag=ext_th)")
|
1571
|
+
ap2.add_argument("--mpmc", type=u, default="", help=argparse.SUPPRESS)
|
1557
1572
|
ap2.add_argument("--spinner", metavar="TXT", type=u, default="🌲", help="\033[33memoji\033[0m or \033[33memoji,css\033[0m Example: [\033[32m🥖,padding:0\033[0m]")
|
1558
1573
|
ap2.add_argument("--css-browser", metavar="L", type=u, default="", help="URL to additional CSS to include in the filebrowser html")
|
1559
1574
|
ap2.add_argument("--js-browser", metavar="L", type=u, default="", help="URL to additional JS to include in the filebrowser html")
|
@@ -1568,6 +1583,7 @@ def add_ui(ap, retry):
|
|
1568
1583
|
ap2.add_argument("--ver", action="store_true", help="show version on the control panel (incompatible with \033[33m-nb\033[0m)")
|
1569
1584
|
ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
1570
1585
|
ap2.add_argument("--no304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable no304 on the controlpanel (workaround for buggy caching in browsers); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
1586
|
+
ap2.add_argument("--ctl-re", metavar="SEC", type=int, default=1, help="the controlpanel Refresh-button will autorefresh every SEC; [\033[32m0\033[0m] = just once")
|
1571
1587
|
ap2.add_argument("--md-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to allow in the iframe 'sandbox' attribute for README.md docs (volflag=md_sbf); see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox")
|
1572
1588
|
ap2.add_argument("--lg-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to allow in the iframe 'sandbox' attribute for prologue/epilogue docs (volflag=lg_sbf)")
|
1573
1589
|
ap2.add_argument("--md-sba", metavar="TXT", type=u, default="", help="the value of the iframe 'allow' attribute for README.md docs, for example [\033[32mfullscreen\033[0m] (volflag=md_sba)")
|
@@ -1578,7 +1594,7 @@ def add_ui(ap, retry):
|
|
1578
1594
|
|
1579
1595
|
|
1580
1596
|
def add_debug(ap):
|
1581
|
-
ap2 = ap.add_argument_group(
|
1597
|
+
ap2 = ap.add_argument_group("debug options")
|
1582
1598
|
ap2.add_argument("--vc", action="store_true", help="verbose config file parser (explain config)")
|
1583
1599
|
ap2.add_argument("--cgen", action="store_true", help="generate config file from current config (best-effort; probably buggy)")
|
1584
1600
|
ap2.add_argument("--deps", action="store_true", help="list information about detected optional dependencies")
|
@@ -1778,7 +1794,7 @@ def main(argv = None) :
|
|
1778
1794
|
argv[idx] = nk + ov
|
1779
1795
|
time.sleep(2)
|
1780
1796
|
|
1781
|
-
da = len(argv) == 1
|
1797
|
+
da = len(argv) == 1 and not CFG_DEF
|
1782
1798
|
try:
|
1783
1799
|
if da:
|
1784
1800
|
argv.extend(["--qr"])
|
copyparty/__version__.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
VERSION = (1,
|
4
|
-
CODENAME = "
|
5
|
-
BUILD_DT = (2025, 8,
|
3
|
+
VERSION = (1, 19, 0)
|
4
|
+
CODENAME = "usernames"
|
5
|
+
BUILD_DT = (2025, 8, 7)
|
6
6
|
|
7
7
|
S_VERSION = ".".join(map(str, VERSION))
|
8
8
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
copyparty/authsrv.py
CHANGED
@@ -1692,6 +1692,7 @@ class AuthSrv(object):
|
|
1692
1692
|
if not mount and not self.args.idp_h_usr:
|
1693
1693
|
# -h says our defaults are CWD at root and read/write for everyone
|
1694
1694
|
axs = AXS(["*"], ["*"], None, None)
|
1695
|
+
ehint = ""
|
1695
1696
|
if self.is_lxc:
|
1696
1697
|
t = "Read-access has been disabled due to failsafe: Docker detected, but %s. This failsafe is to prevent unintended access if this is due to accidental loss of config. You can override this safeguard and allow read/write to all of /w/ by adding the following arguments to the docker container: -v .::rw"
|
1697
1698
|
if len(cfg_files_loaded) == 1:
|
@@ -1701,11 +1702,23 @@ class AuthSrv(object):
|
|
1701
1702
|
else:
|
1702
1703
|
self.log(t % ("the config does not define any volumes",), 1)
|
1703
1704
|
axs = AXS()
|
1705
|
+
ehint = "; please try moving them up one level, into the parent folder:"
|
1704
1706
|
elif self.args.c:
|
1705
1707
|
t = "Read-access has been disabled due to failsafe: No volumes were defined by the config-file. This failsafe is to prevent unintended access if this is due to accidental loss of config. You can override this safeguard and allow read/write to the working-directory by adding the following arguments: -v .::rw"
|
1706
1708
|
self.log(t, 1)
|
1707
1709
|
axs = AXS()
|
1708
|
-
|
1710
|
+
ehint = ":"
|
1711
|
+
if ehint:
|
1712
|
+
try:
|
1713
|
+
files = os.listdir(E.cfg)
|
1714
|
+
except:
|
1715
|
+
files = []
|
1716
|
+
hits = [x for x in files if x.lower().endswith(".conf")]
|
1717
|
+
if hits:
|
1718
|
+
t = "Hint: Found some config files in [%s], but these were not automatically loaded because they are in the wrong place%s %s\n"
|
1719
|
+
self.log(t % (E.cfg, ehint, ", ".join(hits)), 3)
|
1720
|
+
zvf = {"tcolor": self.args.tcolor}
|
1721
|
+
vfs = VFS(self.log_func, absreal("."), "", "", axs, zvf)
|
1709
1722
|
if not axs.uread:
|
1710
1723
|
self.badcfg1 = True
|
1711
1724
|
elif "" not in mount:
|
@@ -2620,6 +2633,8 @@ class AuthSrv(object):
|
|
2620
2633
|
self.re_pwd = None
|
2621
2634
|
pwds = [re.escape(x) for x in self.iacct.keys()]
|
2622
2635
|
pwds.extend(list(self.sesa))
|
2636
|
+
if self.args.usernames:
|
2637
|
+
pwds.extend([x.split(":", 1)[1] for x in pwds if ":" in x])
|
2623
2638
|
if pwds:
|
2624
2639
|
if self.ah.on:
|
2625
2640
|
zs = r"(\[H\] pw:.*|[?&]pw=)([^&]+)"
|
@@ -2742,6 +2757,8 @@ class AuthSrv(object):
|
|
2742
2757
|
"s_name": self.args.bname,
|
2743
2758
|
"have_up2k_idx": "e2d" in vf,
|
2744
2759
|
"have_acode": not self.args.no_acode,
|
2760
|
+
"have_c2flac": self.args.allow_flac,
|
2761
|
+
"have_c2wav": self.args.allow_wav,
|
2745
2762
|
"have_shr": self.args.shr,
|
2746
2763
|
"have_zip": not self.args.no_zip,
|
2747
2764
|
"have_mv": not self.args.no_mv,
|
@@ -2854,7 +2871,10 @@ class AuthSrv(object):
|
|
2854
2871
|
|
2855
2872
|
n = []
|
2856
2873
|
q = "insert into us values (?,?,?)"
|
2857
|
-
|
2874
|
+
accs = list(self.acct)
|
2875
|
+
if self.args.idp_h_usr and self.args.idp_cookie:
|
2876
|
+
accs.extend(self.idp_accs.keys())
|
2877
|
+
for uname in accs:
|
2858
2878
|
if uname not in ases:
|
2859
2879
|
sid = ub64enc(os.urandom(blen)).decode("ascii")
|
2860
2880
|
cur.execute(q, (uname, sid, int(time.time())))
|
@@ -2911,6 +2931,9 @@ class AuthSrv(object):
|
|
2911
2931
|
t = "minimum password length: %d characters"
|
2912
2932
|
return False, t % (self.args.chpw_len,)
|
2913
2933
|
|
2934
|
+
if self.args.usernames:
|
2935
|
+
pw = "%s:%s" % (uname, pw)
|
2936
|
+
|
2914
2937
|
hpw = self.ah.hash(pw) if self.ah.on else pw
|
2915
2938
|
|
2916
2939
|
if hpw == self.acct[uname]:
|
@@ -3002,6 +3025,12 @@ class AuthSrv(object):
|
|
3002
3025
|
self.log("chpw: " + msg, 6)
|
3003
3026
|
|
3004
3027
|
def setup_pwhash(self, acct ) :
|
3028
|
+
if self.args.usernames:
|
3029
|
+
for uname, pw in list(acct.items())[:]:
|
3030
|
+
if pw.startswith("+") and len(pw) == 33:
|
3031
|
+
continue
|
3032
|
+
acct[uname] = "%s:%s" % (uname, pw)
|
3033
|
+
|
3005
3034
|
self.ah = PWHash(self.args)
|
3006
3035
|
if not self.ah.on:
|
3007
3036
|
if self.args.ah_cli or self.args.ah_gen:
|