copyparty 1.19.15__py3-none-any.whl → 1.19.17__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 +19 -0
- copyparty/__main__.py +47 -11
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +45 -9
- copyparty/bos/bos.py +5 -1
- copyparty/cfg.py +20 -0
- copyparty/ftpd.py +5 -3
- copyparty/httpcli.py +114 -27
- copyparty/mdns.py +53 -18
- copyparty/mtag.py +18 -4
- copyparty/qrkode.py +107 -0
- copyparty/res/COPYING.txt +76 -5
- copyparty/smbd.py +1 -1
- copyparty/stolen/qrcodegen.py +1 -64
- copyparty/svchub.py +13 -2
- copyparty/tcpsrv.py +6 -7
- copyparty/tftpd.py +1 -1
- copyparty/th_srv.py +11 -5
- copyparty/up2k.py +40 -16
- copyparty/util.py +63 -16
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.html +3 -1
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.html +3 -0
- copyparty/web/splash.js.gz +0 -0
- copyparty/web/tl/chi.js.gz +0 -0
- copyparty/web/tl/cze.js.gz +0 -0
- copyparty/web/tl/deu.js.gz +0 -0
- copyparty/web/tl/epo.js.gz +0 -0
- copyparty/web/tl/fin.js.gz +0 -0
- copyparty/web/tl/fra.js.gz +0 -0
- copyparty/web/tl/grc.js.gz +0 -0
- copyparty/web/tl/ita.js.gz +0 -0
- copyparty/web/tl/kor.js.gz +0 -0
- copyparty/web/tl/nld.js.gz +0 -0
- copyparty/web/tl/nno.js.gz +0 -0
- copyparty/web/tl/nor.js.gz +0 -0
- copyparty/web/tl/pol.js.gz +0 -0
- copyparty/web/tl/por.js.gz +0 -0
- copyparty/web/tl/rus.js.gz +0 -0
- copyparty/web/tl/spa.js.gz +0 -0
- copyparty/web/tl/swe.js.gz +0 -0
- copyparty/web/tl/tur.js.gz +0 -0
- copyparty/web/tl/ukr.js.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.19.15.dist-info → copyparty-1.19.17.dist-info}/METADATA +47 -2
- {copyparty-1.19.15.dist-info → copyparty-1.19.17.dist-info}/RECORD +52 -32
- {copyparty-1.19.15.dist-info → copyparty-1.19.17.dist-info}/WHEEL +0 -0
- {copyparty-1.19.15.dist-info → copyparty-1.19.17.dist-info}/entry_points.txt +0 -0
- {copyparty-1.19.15.dist-info → copyparty-1.19.17.dist-info}/licenses/LICENSE +0 -0
- {copyparty-1.19.15.dist-info → copyparty-1.19.17.dist-info}/top_level.txt +0 -0
copyparty/__init__.py
CHANGED
|
@@ -97,6 +97,25 @@ web/splash.html
|
|
|
97
97
|
web/splash.js
|
|
98
98
|
web/svcs.html
|
|
99
99
|
web/svcs.js
|
|
100
|
+
web/tl/chi.js
|
|
101
|
+
web/tl/cze.js
|
|
102
|
+
web/tl/deu.js
|
|
103
|
+
web/tl/epo.js
|
|
104
|
+
web/tl/fin.js
|
|
105
|
+
web/tl/fra.js
|
|
106
|
+
web/tl/grc.js
|
|
107
|
+
web/tl/ita.js
|
|
108
|
+
web/tl/kor.js
|
|
109
|
+
web/tl/nld.js
|
|
110
|
+
web/tl/nno.js
|
|
111
|
+
web/tl/nor.js
|
|
112
|
+
web/tl/pol.js
|
|
113
|
+
web/tl/por.js
|
|
114
|
+
web/tl/rus.js
|
|
115
|
+
web/tl/spa.js
|
|
116
|
+
web/tl/swe.js
|
|
117
|
+
web/tl/tur.js
|
|
118
|
+
web/tl/ukr.js
|
|
100
119
|
web/ui.css
|
|
101
120
|
web/up2k.js
|
|
102
121
|
web/util.js
|
copyparty/__main__.py
CHANGED
|
@@ -641,8 +641,11 @@ def get_sects():
|
|
|
641
641
|
if no accounts or volumes are configured,
|
|
642
642
|
current folder will be read/write for everyone
|
|
643
643
|
|
|
644
|
-
the group @acct will always have every user with an account
|
|
645
|
-
(the name of that group can be changed with --grp-all)
|
|
644
|
+
the group \033[33m@acct\033[0m will always have every user with an account
|
|
645
|
+
(the name of that group can be changed with \033[32m--grp-all\033[0m)
|
|
646
|
+
|
|
647
|
+
to hide a volume from authenticated users, specify \033[33m*,-@acct\033[0m
|
|
648
|
+
to subtract \033[33m@acct\033[0m from \033[33m*\033[0m (can subtract users from groups too)
|
|
646
649
|
|
|
647
650
|
consider the config file for more flexible account/volume management,
|
|
648
651
|
including dynamic reload at runtime (and being more readable w)
|
|
@@ -664,12 +667,12 @@ def get_sects():
|
|
|
664
667
|
|
|
665
668
|
send the password in the '\033[36mPW\033[0m' http-header:
|
|
666
669
|
\033[36mPW: \033[35mhunter2\033[0m
|
|
667
|
-
or if you have \033[33m--
|
|
670
|
+
or if you have \033[33m--usernames\033[0m enabled,
|
|
668
671
|
\033[36mPW: \033[35med:hunter2\033[0m
|
|
669
672
|
|
|
670
673
|
send the password in the URL itself:
|
|
671
674
|
\033[36mhttp://127.0.0.1:3923/\033[35m?pw=hunter2\033[0m
|
|
672
|
-
or if you have \033[33m--
|
|
675
|
+
or if you have \033[33m--usernames\033[0m enabled,
|
|
673
676
|
\033[36mhttp://127.0.0.1:3923/\033[35m?pw=ed:hunter2\033[0m
|
|
674
677
|
|
|
675
678
|
use basic-authentication:
|
|
@@ -805,9 +808,11 @@ def get_sects():
|
|
|
805
808
|
\033[36mf\033[35m forks the process, doesn't wait for completion
|
|
806
809
|
\033[36mc\033[35m checks return code, blocks the action if non-zero
|
|
807
810
|
\033[36mj\033[35m provides json with info as 1st arg instead of filepath
|
|
811
|
+
\033[36ms\033[35m provides input data on stdin (instead of 1st arg)
|
|
808
812
|
\033[36mwN\033[35m waits N sec after command has been started before continuing
|
|
809
813
|
\033[36mtN\033[35m sets an N sec timeout before the command is abandoned
|
|
810
814
|
\033[36miN\033[35m xiu only: volume must be idle for N sec (default = 5)
|
|
815
|
+
\033[36mI\033[35m import and run as module, not as subprocess
|
|
811
816
|
|
|
812
817
|
\033[36mar\033[35m only run hook if user has read-access
|
|
813
818
|
\033[36marw\033[35m only run hook if user has read-write-access
|
|
@@ -837,6 +842,9 @@ def get_sects():
|
|
|
837
842
|
the \033[33m--\033[35m stops notify-send from reading the message as args
|
|
838
843
|
and the alert will be "hey" followed by the messagetext
|
|
839
844
|
|
|
845
|
+
\033[36m--xm s,,tee,-a,log.txt\033[35m appends each msg to log.txt;
|
|
846
|
+
\033[36m--xm s,j,,tee,-a,log.txt\033[35m writes it as json instead
|
|
847
|
+
|
|
840
848
|
\033[36m--xau zmq:pub:tcp://*:5556\033[35m announces uploads on zeromq;
|
|
841
849
|
\033[36m--xau t3,zmq:push:tcp://*:5557\033[35m also works, and you can
|
|
842
850
|
\033[36m--xau t3,j,zmq:req:tcp://localhost:5555\033[35m too for example
|
|
@@ -846,7 +854,8 @@ def get_sects():
|
|
|
846
854
|
as soon as the volume has been idle for iN seconds (5 by default)
|
|
847
855
|
|
|
848
856
|
\033[36mxiu\033[0m is also unique in that it will pass the metadata to the
|
|
849
|
-
executed program on STDIN instead of as argv arguments
|
|
857
|
+
executed program on STDIN instead of as argv arguments (so
|
|
858
|
+
just like the \033[36ms\033[0m option does for the other hook types), and
|
|
850
859
|
it also includes the wark (file-id/hash) as a json property
|
|
851
860
|
|
|
852
861
|
\033[36mxban\033[0m can be used to overrule / cancel a user ban event;
|
|
@@ -857,6 +866,12 @@ def get_sects():
|
|
|
857
866
|
on new uploads, but with certain limitations. See
|
|
858
867
|
bin/hooks/reloc* and docs/devnotes.md#hook-effects
|
|
859
868
|
|
|
869
|
+
the \033[36mI\033[0m option will override most other options, because
|
|
870
|
+
it entirely hands over control to the hook, which is
|
|
871
|
+
then able to tamper with copyparty's internal memory
|
|
872
|
+
and wreck havoc if it wants to -- but this is worh it
|
|
873
|
+
because it makes the hook 140x faster
|
|
874
|
+
|
|
860
875
|
except for \033[36mxm\033[0m, only one hook / one action can run at a time,
|
|
861
876
|
so it's recommended to use the \033[36mf\033[0m flag unless you really need
|
|
862
877
|
to wait for the hook to finish before continuing (without \033[36mf\033[0m
|
|
@@ -1147,11 +1162,14 @@ def add_general(ap, nc, srvname):
|
|
|
1147
1162
|
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")
|
|
1148
1163
|
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-]")
|
|
1149
1164
|
ap2.add_argument("--name", metavar="TXT", type=u, default=srvname, help="server name (displayed topleft in browser and in mDNS)")
|
|
1165
|
+
ap2.add_argument("--name-url", metavar="TXT", type=u, help="URL for server name hyperlink (displayed topleft in browser)")
|
|
1166
|
+
ap2.add_argument("--name-html", type=u, help=argparse.SUPPRESS)
|
|
1150
1167
|
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]")
|
|
1151
1168
|
ap2.add_argument("--mimes", action="store_true", help="list default mimetype mapping and exit")
|
|
1152
1169
|
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)")
|
|
1153
1170
|
ap2.add_argument("--license", action="store_true", help="show licenses and exit")
|
|
1154
1171
|
ap2.add_argument("--version", action="store_true", help="show versions and exit")
|
|
1172
|
+
ap2.add_argument("--versionb", action="store_true", help="show version and exit")
|
|
1155
1173
|
|
|
1156
1174
|
|
|
1157
1175
|
def add_qr(ap, tty):
|
|
@@ -1219,6 +1237,7 @@ def add_upload(ap):
|
|
|
1219
1237
|
ap2.add_argument("--hardlink-only", action="store_true", help="do not fallback to symlinks when a hardlink cannot be made (volflag=hardlinkonly)")
|
|
1220
1238
|
ap2.add_argument("--reflink", action="store_true", help="enable reflink-based dedup; will fallback on full copies when that is impossible (non-CoW filesystem) (volflag=reflink)")
|
|
1221
1239
|
ap2.add_argument("--no-dupe", action="store_true", help="reject duplicate files during upload; only matches within the same volume (volflag=nodupe)")
|
|
1240
|
+
ap2.add_argument("--no-dupe-m", action="store_true", help="also reject dupes when moving a file into another volume (volflag=nodupem)")
|
|
1222
1241
|
ap2.add_argument("--no-clone", action="store_true", help="do not use existing data on disk to satisfy dupe uploads; reduces server HDD reads in exchange for much more network load (volflag=noclone)")
|
|
1223
1242
|
ap2.add_argument("--no-snap", action="store_true", help="disable snapshots -- forget unfinished uploads on shutdown; don't create .hist/up2k.snap files -- abandoned/interrupted uploads must be cleaned up manually")
|
|
1224
1243
|
ap2.add_argument("--snap-wri", metavar="SEC", type=int, default=300, help="write upload state to ./hist/up2k.snap every \033[33mSEC\033[0m seconds; allows resuming incomplete uploads after a server crash")
|
|
@@ -1506,6 +1525,7 @@ def add_optouts(ap):
|
|
|
1506
1525
|
ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
|
|
1507
1526
|
ap2.add_argument("--no-tail", action="store_true", help="disable streaming a growing files with ?tail (volflag=notail)")
|
|
1508
1527
|
ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader-IP into the database; will also disable unpost, you may want \033[32m--forget-ip\033[0m instead (volflag=no_db_ip)")
|
|
1528
|
+
ap2.add_argument("--no-zls", action="store_true", help="disable browsing the contents of zip/cbz files, does not affect thumbnails")
|
|
1509
1529
|
|
|
1510
1530
|
|
|
1511
1531
|
def add_safety(ap):
|
|
@@ -1524,6 +1544,7 @@ def add_safety(ap):
|
|
|
1524
1544
|
ap2.add_argument("--force-js", action="store_true", help="don't send folder listings as HTML, force clients to use the embedded json instead -- slight protection against misbehaving search engines which ignore \033[33m--no-robots\033[0m")
|
|
1525
1545
|
ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)")
|
|
1526
1546
|
ap2.add_argument("--logout", metavar="H", type=float, default=8086.0, help="logout clients after \033[33mH\033[0m hours of inactivity; [\033[32m0.0028\033[0m]=10sec, [\033[32m0.1\033[0m]=6min, [\033[32m24\033[0m]=day, [\033[32m168\033[0m]=week, [\033[32m720\033[0m]=month, [\033[32m8760\033[0m]=year)")
|
|
1547
|
+
ap2.add_argument("--dont-ban", metavar="TXT", type=u, default="no", help="anyone at this accesslevel or above will not get banned: [\033[32mav\033[0m]=admin-in-volume, [\033[32maa\033[0m]=has-admin-anywhere, [\033[32mrw\033[0m]=read-write, [\033[32mauth\033[0m]=authenticated, [\033[32many\033[0m]=disable-all-bans, [\033[32mno\033[0m]=anyone-can-get-banned")
|
|
1527
1548
|
ap2.add_argument("--ban-pw", metavar="N,W,B", type=u, default="9,60,1440", help="more than \033[33mN\033[0m wrong passwords in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; disable with [\033[32mno\033[0m]")
|
|
1528
1549
|
ap2.add_argument("--ban-pwc", metavar="N,W,B", type=u, default="5,60,1440", help="more than \033[33mN\033[0m password-changes in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; disable with [\033[32mno\033[0m]")
|
|
1529
1550
|
ap2.add_argument("--ban-404", metavar="N,W,B", type=u, default="50,60,1440", help="hitting more than \033[33mN\033[0m 404's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; only affects users who cannot see directory listings because their access is either g/G/h")
|
|
@@ -1531,7 +1552,7 @@ def add_safety(ap):
|
|
|
1531
1552
|
ap2.add_argument("--ban-422", metavar="N,W,B", type=u, default="9,2,1440", help="hitting more than \033[33mN\033[0m 422's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes (invalid requests, attempted exploits ++)")
|
|
1532
1553
|
ap2.add_argument("--ban-url", metavar="N,W,B", type=u, default="9,2,1440", help="hitting more than \033[33mN\033[0m sus URL's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; applies only to permissions g/G/h (decent replacement for \033[33m--ban-404\033[0m if that can't be used)")
|
|
1533
1554
|
ap2.add_argument("--sus-urls", metavar="R", type=u, default=r"\.php$|(^|/)wp-(admin|content|includes)/", help="URLs which are considered sus / eligible for banning; disable with blank or [\033[32mno\033[0m]")
|
|
1534
|
-
ap2.add_argument("--nonsus-urls", metavar="R", type=u, default=r"^(favicon
|
|
1555
|
+
ap2.add_argument("--nonsus-urls", metavar="R", type=u, default=r"^(favicon\..{3}|robots\.txt)$|^apple-touch-icon|^\.well-known", help="harmless URLs ignored from 403/404-bans; disable with blank or [\033[32mno\033[0m]")
|
|
1535
1556
|
ap2.add_argument("--early-ban", action="store_true", help="if a client is banned, reject its connection as soon as possible; not a good idea to enable when proxied behind cloudflare since it could ban your reverse-proxy")
|
|
1536
1557
|
ap2.add_argument("--cookie-nmax", metavar="N", type=int, default=50, help="reject HTTP-request from client if they send more than N cookies")
|
|
1537
1558
|
ap2.add_argument("--cookie-cmax", metavar="N", type=int, default=8192, help="reject HTTP-request from client if more than N characters in Cookie header")
|
|
@@ -1588,12 +1609,14 @@ def add_admin(ap):
|
|
|
1588
1609
|
ap2 = ap.add_argument_group("admin panel options")
|
|
1589
1610
|
ap2.add_argument("--no-reload", action="store_true", help="disable ?reload=cfg (reload users/volumes/volflags from config file)")
|
|
1590
1611
|
ap2.add_argument("--no-rescan", action="store_true", help="disable ?scan (volume reindexing)")
|
|
1591
|
-
ap2.add_argument("--no-stack", action="store_true", help="disable ?stack (list all stacks)")
|
|
1612
|
+
ap2.add_argument("--no-stack", action="store_true", help="disable ?stack (list all stacks); same as --stack-who=no")
|
|
1592
1613
|
ap2.add_argument("--no-ups-page", action="store_true", help="disable ?ru (list of recent uploads)")
|
|
1593
1614
|
ap2.add_argument("--no-up-list", action="store_true", help="don't show list of incoming files in controlpanel")
|
|
1594
1615
|
ap2.add_argument("--dl-list", metavar="LVL", type=int, default=2, help="who can see active downloads in the controlpanel? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=everyone")
|
|
1595
1616
|
ap2.add_argument("--ups-who", metavar="LVL", type=int, default=2, help="who can see recent uploads on the ?ru page? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=everyone (volflag=ups_who)")
|
|
1596
1617
|
ap2.add_argument("--ups-when", action="store_true", help="let everyone see upload timestamps on the ?ru page, not just admins")
|
|
1618
|
+
ap2.add_argument("--stack-who", metavar="LVL", type=u, default="a", help="who can see the ?stack page (list of threads)? [\033[32mno\033[0m]=nobody, [\033[32ma\033[0m]=admins, [\033[32mrw\033[0m]=read+write, [\033[32mall\033[0m]=everyone")
|
|
1619
|
+
ap2.add_argument("--stack-v", action="store_true", help="verbose ?stack")
|
|
1597
1620
|
|
|
1598
1621
|
|
|
1599
1622
|
def add_thumbnail(ap):
|
|
@@ -1791,6 +1814,15 @@ def add_ui(ap, retry ):
|
|
|
1791
1814
|
ap2.add_argument("--lg-sba", metavar="TXT", type=u, default="", help="the value of the iframe 'allow' attribute for prologue/epilogue docs (volflag=lg_sba); see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy#iframes")
|
|
1792
1815
|
ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")
|
|
1793
1816
|
ap2.add_argument("--no-sb-lg", action="store_true", help="don't sandbox prologue/epilogue docs (volflags: no_sb_lg | sb_lg); enables non-js support")
|
|
1817
|
+
ap2.add_argument("--ui-nombar", action="store_true", help="hide top-menu in the UI (volflag=ui_nombar)")
|
|
1818
|
+
ap2.add_argument("--ui-noacci", action="store_true", help="hide account-info in the UI (volflag=ui_noacci)")
|
|
1819
|
+
ap2.add_argument("--ui-nosrvi", action="store_true", help="hide server-info in the UI (volflag=ui_nosrvi)")
|
|
1820
|
+
ap2.add_argument("--ui-nonav", action="store_true", help="hide navpane+breadcrumbs (volflag=ui_nonav)")
|
|
1821
|
+
ap2.add_argument("--ui-notree", action="store_true", help="hide navpane in the UI (volflag=ui_nonav)")
|
|
1822
|
+
ap2.add_argument("--ui-nocpla", action="store_true", help="hide cpanel-link in the UI (volflag=ui_nocpla)")
|
|
1823
|
+
ap2.add_argument("--ui-nolbar", action="store_true", help="hide link-bar in the UI (volflag=ui_nolbar)")
|
|
1824
|
+
ap2.add_argument("--ui-noctxb", action="store_true", help="hide context-buttons in the UI (volflag=ui_noctxb)")
|
|
1825
|
+
ap2.add_argument("--ui-norepl", action="store_true", help="hide repl-button in the UI (volflag=ui_norepl)")
|
|
1794
1826
|
ap2.add_argument("--have-unlistc", action="store_true", help=argparse.SUPPRESS)
|
|
1795
1827
|
|
|
1796
1828
|
|
|
@@ -1918,15 +1950,19 @@ def run_argparse(
|
|
|
1918
1950
|
|
|
1919
1951
|
|
|
1920
1952
|
def main(argv = None) :
|
|
1953
|
+
if argv is None:
|
|
1954
|
+
argv = sys.argv
|
|
1955
|
+
|
|
1956
|
+
if "--versionb" in argv:
|
|
1957
|
+
print(S_VERSION)
|
|
1958
|
+
sys.exit(0)
|
|
1959
|
+
|
|
1921
1960
|
time.strptime("19970815", "%Y%m%d") # python#7980
|
|
1922
1961
|
if WINDOWS:
|
|
1923
1962
|
os.system("rem") # enables colors
|
|
1924
1963
|
|
|
1925
1964
|
init_E(E)
|
|
1926
1965
|
|
|
1927
|
-
if argv is None:
|
|
1928
|
-
argv = sys.argv
|
|
1929
|
-
|
|
1930
1966
|
f = '\033[36mcopyparty v{} "\033[35m{}\033[36m" ({})\n{}\033[0;36m\n sqlite {} | jinja {} | pyftpd {} | tftp {}\n\033[0m'
|
|
1931
1967
|
f = f.format(
|
|
1932
1968
|
S_VERSION,
|
|
@@ -2053,7 +2089,7 @@ def main(argv = None) :
|
|
|
2053
2089
|
|
|
2054
2090
|
# propagate implications
|
|
2055
2091
|
for k1, k2 in IMPLICATIONS:
|
|
2056
|
-
if getattr(al, k1):
|
|
2092
|
+
if getattr(al, k1, None):
|
|
2057
2093
|
setattr(al, k2, True)
|
|
2058
2094
|
|
|
2059
2095
|
# propagate unplications
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
|
@@ -1961,9 +1961,18 @@ class AuthSrv(object):
|
|
|
1961
1961
|
axs_key = "u" + perm
|
|
1962
1962
|
for vp, vol in vfs.all_vols.items():
|
|
1963
1963
|
zx = getattr(vol.axs, axs_key)
|
|
1964
|
-
if "*" in zx:
|
|
1964
|
+
if "*" in zx and "-@acct" not in zx:
|
|
1965
1965
|
for usr in unames:
|
|
1966
1966
|
zx.add(usr)
|
|
1967
|
+
for zs in list(zx):
|
|
1968
|
+
if zs.startswith("-"):
|
|
1969
|
+
zx.discard(zs)
|
|
1970
|
+
zs = zs[1:]
|
|
1971
|
+
zx.discard(zs)
|
|
1972
|
+
if zs.startswith("@"):
|
|
1973
|
+
zs = zs[1:]
|
|
1974
|
+
for zs in grps.get(zs) or []:
|
|
1975
|
+
zx.discard(zs)
|
|
1967
1976
|
|
|
1968
1977
|
# aread,... = dict[uname, list[volnames] or []]
|
|
1969
1978
|
umap = {x: [] for x in unames}
|
|
@@ -2503,13 +2512,17 @@ class AuthSrv(object):
|
|
|
2503
2512
|
|
|
2504
2513
|
ico_url = vol.flags.get("ufavico")
|
|
2505
2514
|
if ico_url:
|
|
2515
|
+
ico_h = ""
|
|
2506
2516
|
ico_ext = ico_url.split("?")[0].split(".")[-1].lower()
|
|
2507
2517
|
if ico_ext in FAVICON_MIMES:
|
|
2508
2518
|
zs = '<link rel="icon" type="%s" href="%s">\n'
|
|
2509
|
-
|
|
2519
|
+
ico_h = zs % (FAVICON_MIMES[ico_ext], ico_url)
|
|
2510
2520
|
elif ico_ext == "ico":
|
|
2511
2521
|
zs = '<link rel="shortcut icon" href="%s">\n'
|
|
2512
|
-
|
|
2522
|
+
ico_h = zs % (ico_url,)
|
|
2523
|
+
if ico_h:
|
|
2524
|
+
vol.flags["ufavico_h"] = ico_h
|
|
2525
|
+
head_s += ico_h
|
|
2513
2526
|
|
|
2514
2527
|
if head_s:
|
|
2515
2528
|
vol.flags["html_head_s"] = head_s
|
|
@@ -2573,6 +2586,15 @@ class AuthSrv(object):
|
|
|
2573
2586
|
for x in drop:
|
|
2574
2587
|
vol.flags.pop(x)
|
|
2575
2588
|
|
|
2589
|
+
zi = vol.flags.get("lifetime") or 0
|
|
2590
|
+
zi2 = time.time() // (86400 * 365)
|
|
2591
|
+
zi3 = zi2 * 86400 * 365
|
|
2592
|
+
if zi < 0 or zi > zi3:
|
|
2593
|
+
t = "the lifetime of volume [/%s] (%d) exceeds max value (%d years; %d)"
|
|
2594
|
+
t = t % (vol.vpath, zi, zi2, zi3)
|
|
2595
|
+
self.log(t, 1)
|
|
2596
|
+
raise Exception(t)
|
|
2597
|
+
|
|
2576
2598
|
# verify tags mentioned by -mt[mp] are used by -mte
|
|
2577
2599
|
local_mtp = {}
|
|
2578
2600
|
local_only_mtp = {}
|
|
@@ -2739,9 +2761,13 @@ class AuthSrv(object):
|
|
|
2739
2761
|
["uadmin", "uadmin"],
|
|
2740
2762
|
]:
|
|
2741
2763
|
u = list(sorted(getattr(zv.axs, attr)))
|
|
2742
|
-
u
|
|
2743
|
-
|
|
2744
|
-
|
|
2764
|
+
if u == ["*"] and acct:
|
|
2765
|
+
u = ["\033[35monly-anonymous\033[0m"]
|
|
2766
|
+
elif "*" in u:
|
|
2767
|
+
u = ["\033[35meverybody\033[0m"]
|
|
2768
|
+
if not u:
|
|
2769
|
+
u = ["\033[36m--none--\033[0m"]
|
|
2770
|
+
u = ", ".join(u)
|
|
2745
2771
|
t += "\n| {}: {}".format(txt, u)
|
|
2746
2772
|
|
|
2747
2773
|
if "e2d" in zv.flags:
|
|
@@ -2853,8 +2879,6 @@ class AuthSrv(object):
|
|
|
2853
2879
|
|
|
2854
2880
|
if have_reflink:
|
|
2855
2881
|
t = "WARNING: Reflink-based dedup was requested, but %s. This will not work; files will be full copies instead."
|
|
2856
|
-
if sys.version_info < (3, 14):
|
|
2857
|
-
self.log(t % "your python version is not new enough", 1)
|
|
2858
2882
|
if not sys.platform.startswith("linux"):
|
|
2859
2883
|
self.log(t % "your OS is not Linux", 1)
|
|
2860
2884
|
|
|
@@ -2931,6 +2955,11 @@ class AuthSrv(object):
|
|
|
2931
2955
|
shn.shr_src = (s_vfs, s_rem)
|
|
2932
2956
|
shn.realpath = s_vfs.canonical(s_rem)
|
|
2933
2957
|
|
|
2958
|
+
o_vn, _ = shn._get_share_src("")
|
|
2959
|
+
shn.flags = o_vn.flags.copy()
|
|
2960
|
+
shn.dbpath = o_vn.dbpath
|
|
2961
|
+
shn.histpath = o_vn.histpath
|
|
2962
|
+
|
|
2934
2963
|
# root.all_aps doesn't include any shares, so make a copy where the
|
|
2935
2964
|
# share appears in all abspaths it can provide (for example for chk_ap)
|
|
2936
2965
|
ap = shn.realpath
|
|
@@ -2994,6 +3023,8 @@ class AuthSrv(object):
|
|
|
2994
3023
|
"unlist": vf.get("unlist") or "",
|
|
2995
3024
|
"sb_lg": "" if "no_sb_lg" in vf else (vf.get("lg_sbf") or "y"),
|
|
2996
3025
|
}
|
|
3026
|
+
if "ufavico_h" in vf:
|
|
3027
|
+
vn.js_ls["ufavico"] = vf["ufavico_h"]
|
|
2997
3028
|
js_htm = {
|
|
2998
3029
|
"SPINNER": self.args.spinner,
|
|
2999
3030
|
"s_name": self.args.bname,
|
|
@@ -3005,6 +3036,7 @@ class AuthSrv(object):
|
|
|
3005
3036
|
"have_shr": self.args.shr,
|
|
3006
3037
|
"shr_who": vf["shr_who"],
|
|
3007
3038
|
"have_zip": not self.args.no_zip,
|
|
3039
|
+
"have_zls": not self.args.no_zls,
|
|
3008
3040
|
"have_mv": not self.args.no_mv,
|
|
3009
3041
|
"have_del": not self.args.no_del,
|
|
3010
3042
|
"have_unpost": int(self.args.unpost),
|
|
@@ -3029,7 +3061,7 @@ class AuthSrv(object):
|
|
|
3029
3061
|
"dvol": self.args.au_vol,
|
|
3030
3062
|
"idxh": int(self.args.ih),
|
|
3031
3063
|
"dutc": not self.args.localtime,
|
|
3032
|
-
"dfszf": self.args.ui_filesz,
|
|
3064
|
+
"dfszf": self.args.ui_filesz.strip("-"),
|
|
3033
3065
|
"themes": self.args.themes,
|
|
3034
3066
|
"turbolvl": self.args.turbo,
|
|
3035
3067
|
"nosubtle": self.args.nosubtle,
|
|
@@ -3041,6 +3073,10 @@ class AuthSrv(object):
|
|
|
3041
3073
|
"lifetime": vn.js_ls["lifetime"],
|
|
3042
3074
|
"u2sort": self.args.u2sort,
|
|
3043
3075
|
}
|
|
3076
|
+
zs = "ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi"
|
|
3077
|
+
for zs in zs.split():
|
|
3078
|
+
if vf.get(zs):
|
|
3079
|
+
js_htm[zs] = 1
|
|
3044
3080
|
vn.js_htm = json_hesc(json.dumps(js_htm))
|
|
3045
3081
|
|
|
3046
3082
|
vols = list(vfs.all_nodes.values())
|
copyparty/bos/bos.py
CHANGED
copyparty/cfg.py
CHANGED
|
@@ -19,6 +19,7 @@ def vf_bmap() :
|
|
|
19
19
|
"no_clone": "noclone",
|
|
20
20
|
"no_dirsz": "nodirsz",
|
|
21
21
|
"no_dupe": "nodupe",
|
|
22
|
+
"no_dupe_m": "nodupem",
|
|
22
23
|
"no_forget": "noforget",
|
|
23
24
|
"no_pipe": "nopipe",
|
|
24
25
|
"no_robots": "norobots",
|
|
@@ -58,6 +59,15 @@ def vf_bmap() :
|
|
|
58
59
|
"rm_partial",
|
|
59
60
|
"rmagic",
|
|
60
61
|
"rss",
|
|
62
|
+
"ui_noacci",
|
|
63
|
+
"ui_nocpla",
|
|
64
|
+
"ui_nolbar",
|
|
65
|
+
"ui_nombar",
|
|
66
|
+
"ui_nonav",
|
|
67
|
+
"ui_notree",
|
|
68
|
+
"ui_norepl",
|
|
69
|
+
"ui_nosrvi",
|
|
70
|
+
"ui_noctxb",
|
|
61
71
|
"wo_up_readme",
|
|
62
72
|
"wram",
|
|
63
73
|
"xdev",
|
|
@@ -189,6 +199,7 @@ flagcats = {
|
|
|
189
199
|
"safededup": "verify on-disk data before using it for dedup",
|
|
190
200
|
"noclone": "take dupe data from clients, even if available on HDD",
|
|
191
201
|
"nodupe": "rejects existing files (instead of linking/cloning them)",
|
|
202
|
+
"nodupem": "rejects existing files during moves as well",
|
|
192
203
|
"chmod_d=755": "unix-permission for new dirs/folders",
|
|
193
204
|
"chmod_f=644": "unix-permission for new files",
|
|
194
205
|
"uid=573": "change owner of new files/folders to unix-user 573",
|
|
@@ -325,6 +336,15 @@ flagcats = {
|
|
|
325
336
|
"md_sba": "value of iframe allow-prop for markdown-sandbox",
|
|
326
337
|
"lg_sba": "value of iframe allow-prop for *logue-sandbox",
|
|
327
338
|
"nohtml": "return html and markdown as text/html",
|
|
339
|
+
"ui_noacci": "hide account-info in the UI",
|
|
340
|
+
"ui_nocpla": "hide cpanel-link in the UI",
|
|
341
|
+
"ui_nolbar": "hide link-bar in the UI",
|
|
342
|
+
"ui_nombar": "hide top-menu in the UI",
|
|
343
|
+
"ui_nonav": "hide navpane+breadcrumbs in the UI",
|
|
344
|
+
"ui_notree": "hide navpane in the UI",
|
|
345
|
+
"ui_norepl": "hide repl-button in the UI",
|
|
346
|
+
"ui_nosrvi": "hide server-info in the UI",
|
|
347
|
+
"ui_noctxb": "hide context-buttons in the UI",
|
|
328
348
|
},
|
|
329
349
|
"opengraph (discord embeds)": {
|
|
330
350
|
"og": "enable OG (disables hotlinking)",
|
copyparty/ftpd.py
CHANGED
|
@@ -247,7 +247,7 @@ class FtpFs(AbstractedFS):
|
|
|
247
247
|
|
|
248
248
|
if w and need_unlink:
|
|
249
249
|
if td >= -1 and td <= self.args.ftp_wt:
|
|
250
|
-
# within permitted timeframe;
|
|
250
|
+
# within permitted timeframe; allow overwrite or resume
|
|
251
251
|
do_it = True
|
|
252
252
|
elif self.args.no_del or self.args.ftp_no_ow:
|
|
253
253
|
# file too old, or overwrite not allowed; reject
|
|
@@ -264,7 +264,9 @@ class FtpFs(AbstractedFS):
|
|
|
264
264
|
if not do_it:
|
|
265
265
|
raise FSE("File already exists")
|
|
266
266
|
|
|
267
|
-
|
|
267
|
+
# Don't unlink file for append mode
|
|
268
|
+
elif "a" not in mode:
|
|
269
|
+
wunlink(self.log, ap, VF_CAREFUL)
|
|
268
270
|
|
|
269
271
|
ret = open(fsenc(ap), mode, self.args.iobuf)
|
|
270
272
|
if w and "fperms" in vfs.flags:
|
|
@@ -505,7 +507,7 @@ class FtpHandler(FTPHandler):
|
|
|
505
507
|
0,
|
|
506
508
|
self.cli_ip,
|
|
507
509
|
time.time(),
|
|
508
|
-
|
|
510
|
+
None,
|
|
509
511
|
)
|
|
510
512
|
t = hr.get("rejectmsg") or ""
|
|
511
513
|
if t or not hr:
|