diff --git a/copyparty/__main__.py b/copyparty/__main__.py index aeee2591e..593104197 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1813,6 +1813,7 @@ def add_safety(ap): ap2.add_argument("--csp-dl", metavar="TXT", default="", help="content-security-policy to apply for static files (volflag=csp_dl)") ap2.add_argument("--no-script", action="store_true", help="disables javascript in html files; helps prevent XSS but kills interactive websites; this will override \033[33m--csp-dl\033[0m with [\033[32mscript-src 'none'\033[0m] (volflag=noscript)") ap2.add_argument("--no-html", action="store_true", help="show html-files as plain text; helps prevent XSS but kills websites/blogs, also enables --no-script (volflag=nohtml)") + ap2.add_argument("--no-mime", action="store_true", help="disallow changing the response mimetype with url-parameter ?mime=... (volflag=nomime)") ap2.add_argument("--vague-403", action="store_true", help="send 404 instead of 403 (security through ambiguity, very enterprise). \033[1;31mWARNING:\033[0m Not compatible with WebDAV") 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") ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)") diff --git a/copyparty/cfg.py b/copyparty/cfg.py index ec832a3e6..36e6a7a3a 100644 --- a/copyparty/cfg.py +++ b/copyparty/cfg.py @@ -22,6 +22,7 @@ def vf_bmap() -> dict[str, str]: "no_dupe_m": "nodupem", "no_forget": "noforget", "no_html": "nohtml", + "no_mime": "nomime", "no_pipe": "nopipe", "no_robots": "norobots", "no_script": "noscript", @@ -386,6 +387,7 @@ flagcats = { "csp_ui": "content-security-policy for the web-UI", "csp_dl": "content-security-policy for static files", "nohtml": "return html and markdown as text/html", + "nomime": "disallow ?mime to change response type", "noscript": "disable most javascript by use of CSP", "allow_svg_js": "allow javascript in svg images", "ui_noacci": "hide account-info in the UI", diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 3ee612326..abd7aab77 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -5041,7 +5041,7 @@ class HttpCli(object): if "txt" in self.uparam: mime = "text/plain; charset={}".format(self.uparam["txt"] or "utf-8") - elif "mime" in self.uparam: + elif "mime" in self.uparam and "nomime" not in self.vn.flags: mime = str(self.uparam.get("mime")) elif "rmagic" in self.vn.flags: mime = guess_mime(req_path, fs_path) diff --git a/tests/util.py b/tests/util.py index 1c66a7ee8..3822a556c 100644 --- a/tests/util.py +++ b/tests/util.py @@ -145,7 +145,7 @@ class Cfg(Namespace): def __init__(self, a=None, v=None, c=None, **ka0): ka = {} - ex = "allow_flac allow_wav allow_svg_js chpw cookie_lax daw dav_auth dav_mac dav_rt dlni dothidden e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only http_no_tcp ih ihead localtime log_badxml magic md_no_br nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_dupe_m no_fnugg no_html no_lifetime no_logues no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_script no_tail no_tarcmp no_thumb no_vthumb no_u2abrt no_zip no_zls nrand nsort nw og og_no_head og_s_title ohead opds q rand re_dirsz reflink rm_partial rmagic rss show_hist smb srch_dbg srch_excl srch_nfkc srch_icase stats ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi uqe usernames vague_403 vc ver vol_nospawn vol_or_crash wo_up_readme wopi write_uplog xdev xlink xvol zipmaxu zs" + ex = "allow_flac allow_wav allow_svg_js chpw cookie_lax daw dav_auth dav_mac dav_rt dlni dothidden e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only http_no_tcp ih ihead localtime log_badxml magic md_no_br nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_dupe_m no_fnugg no_html no_lifetime no_logues no_mime no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_script no_tail no_tarcmp no_thumb no_vthumb no_u2abrt no_zip no_zls nrand nsort nw og og_no_head og_s_title ohead opds q rand re_dirsz reflink rm_partial rmagic rss show_hist smb srch_dbg srch_excl srch_nfkc srch_icase stats ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi uqe usernames vague_403 vc ver vol_nospawn vol_or_crash wo_up_readme wopi write_uplog xdev xlink xvol zipmaxu zs" ka.update(**{k: False for k in ex.split()}) ex = "dav_inf dedup dotpart dotsrch hook_v no_dhash no_fastboot no_fpool no_htp no_rescan no_sendfile no_ses no_snap no_up_list no_voldump wram re_dhash see_dots plain_ip"