diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 20400540..ef0ed8e9 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1003,6 +1003,7 @@ def add_upload(ap): ap2 = ap.add_argument_group('upload options') ap2.add_argument("--dotpart", action="store_true", help="dotfile incomplete uploads, hiding them from clients unless \033[33m-ed\033[0m") 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") + 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)") ap2.add_argument("--unpost", metavar="SEC", type=int, default=3600*12, help="grace period where uploads can be deleted by the uploader, even without delete permissions; 0=disabled, default=12h") ap2.add_argument("--u2abort", metavar="NUM", type=int, default=1, help="clients can abort incomplete uploads by using the unpost tab (requires \033[33m-e2d\033[0m). [\033[32m0\033[0m] = never allowed (disable feature), [\033[32m1\033[0m] = allow if client has the same IP as the upload AND is using the same account, [\033[32m2\033[0m] = just check the IP, [\033[32m3\033[0m] = just check account-name (volflag=u2abort)") ap2.add_argument("--blank-wt", metavar="SEC", type=int, default=300, help="file write grace period (any client can write to a blank file last-modified more recently than \033[33mSEC\033[0m seconds ago)") @@ -1380,7 +1381,7 @@ def add_thumbnail(ap): ap2.add_argument("--th-r-ffi", metavar="T,T", type=u, default="apng,avif,avifs,bmp,cbz,dds,dib,fit,fits,fts,gif,hdr,heic,heics,heif,heifs,icns,ico,jp2,jpeg,jpg,jpx,jxl,pbm,pcx,pfm,pgm,png,pnm,ppm,psd,qoi,sgi,tga,tif,tiff,webp,xbm,xpm", help="image formats to decode using ffmpeg") ap2.add_argument("--th-r-ffv", metavar="T,T", type=u, default="3gp,asf,av1,avc,avi,flv,h264,h265,hevc,m4v,mjpeg,mjpg,mkv,mov,mp4,mpeg,mpeg2,mpegts,mpg,mpg2,mts,nut,ogm,ogv,rm,ts,vob,webm,wmv", help="video formats to decode using ffmpeg") ap2.add_argument("--th-r-ffa", metavar="T,T", type=u, default="aac,ac3,aif,aiff,alac,alaw,amr,apac,ape,au,bonk,dfpwm,dts,flac,gsm,ilbc,it,itgz,itxz,itz,m4a,mdgz,mdxz,mdz,mo3,mod,mp2,mp3,mpc,mptm,mt2,mulaw,ogg,okt,opus,ra,s3m,s3gz,s3xz,s3z,tak,tta,ulaw,wav,wma,wv,xm,xmgz,xmxz,xmz,xpk", help="audio formats to decode using ffmpeg") - ap2.add_argument("--th-spec-cnv", metavar="T,T", type=u, default="it,itgz,itxz,itz,mdgz,mdxz,mdz,mo3,mod,s3m,s3gz,s3xz,s3z,xm,xmgz,xmxz,xmz,xpk", help="audio formats which provoke https://trac.ffmpeg.org/ticket/10797 (huge ram usage for s3xmodit spectrograms)") + ap2.add_argument("--th-spec-cnv", metavar="T", type=u, default="it,itgz,itxz,itz,mdgz,mdxz,mdz,mo3,mod,s3m,s3gz,s3xz,s3z,xm,xmgz,xmxz,xmz,xpk", help="audio formats which provoke https://trac.ffmpeg.org/ticket/10797 (huge ram usage for s3xmodit spectrograms)") ap2.add_argument("--au-unpk", metavar="E=F.C", type=u, default="mdz=mod.zip, mdgz=mod.gz, mdxz=mod.xz, s3z=s3m.zip, s3gz=s3m.gz, s3xz=s3m.xz, xmz=xm.zip, xmgz=xm.gz, xmxz=xm.xz, itz=it.zip, itgz=it.gz, itxz=it.xz, cbz=jpg.cbz", help="audio/image formats to decompress before passing to ffmpeg") diff --git a/copyparty/authsrv.py b/copyparty/authsrv.py index 8f570e89..92fccf75 100644 --- a/copyparty/authsrv.py +++ b/copyparty/authsrv.py @@ -2074,6 +2074,10 @@ class AuthSrv(object): if len(zs) == 3: # fc5 => ffcc55 vol.flags["tcolor"] = "".join([x * 2 for x in zs]) + # volflag syntax currently doesn't allow for ':' in value + zs = vol.flags["put_name"] + vol.flags["put_name2"] = zs.replace("{now.", "{now:.") + if vol.flags.get("neversymlink"): vol.flags["hardlinkonly"] = True # was renamed if vol.flags.get("hardlinkonly"): diff --git a/copyparty/cfg.py b/copyparty/cfg.py index 563a0299..458feeb4 100644 --- a/copyparty/cfg.py +++ b/copyparty/cfg.py @@ -95,6 +95,7 @@ def vf_vmap() -> dict[str, str]: "og_title_i", "og_tpl", "og_ua", + "put_name", "mv_retry", "rm_retry", "sort", @@ -165,6 +166,7 @@ flagcats = { "daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files", "nosub": "forces all uploads into the top folder of the vfs", "magic": "enables filetype detection for nameless uploads", + "put_name": "fallback filename for nameless uploads", "gz": "allows server-side gzip compression of uploads with ?gz", "xz": "allows server-side lzma compression of uploads with ?xz", "pk": "forces server-side compression, optional arg: xz,9", diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 82de30de..afd06ea9 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -2100,8 +2100,7 @@ class HttpCli(object): suffix = "-{:.6f}-{}".format(time.time(), self.dip()) nameless = not fn if nameless: - suffix += ".bin" - fn = "put" + suffix + fn = vfs.flags["put_name2"].format(now=time.time(), cip=self.dip()) params = {"suffix": suffix, "fdir": fdir} if self.args.nw: diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 72019f04..d9d3fae0 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -1119,7 +1119,7 @@ class Up2k(object): ft = "\033[0;32m{}{:.0}" ff = "\033[0;35m{}{:.0}" fv = "\033[0;36m{}:\033[90m{}" - zs = "ext_th_d html_head mv_re_r mv_re_t rm_re_r rm_re_t srch_re_dots srch_re_nodot zipmax zipmaxn_v zipmaxs_v" + zs = "ext_th_d html_head put_name2 mv_re_r mv_re_t rm_re_r rm_re_t srch_re_dots srch_re_nodot zipmax zipmaxn_v zipmaxs_v" fx = set(zs.split()) fd = vf_bmap() fd.update(vf_cmap()) diff --git a/tests/util.py b/tests/util.py index 8899bb57..fb76b289 100644 --- a/tests/util.py +++ b/tests/util.py @@ -178,6 +178,7 @@ class Cfg(Namespace): mte={"a": True}, mth={}, mtp=[], + put_name="put-{now.6f}-{cip}.bin", mv_retry="0/0", rm_retry="0/0", s_rd_sz=256 * 1024,