tighten CSP
parent
35d9d7c3bc
commit
6114111654
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const CACHE_NAME = "offlineCache-v1";
|
||||
const OFFLINE_URL = "/assets/offline.html";
|
||||
const OFFLINE_URL = "/offline.html";
|
||||
|
||||
self.addEventListener("install", () => {
|
||||
const cacheOfflinePage = async () => {
|
||||
|
|
|
@ -13,26 +13,30 @@ def session_init():
|
|||
|
||||
@app.before_request
|
||||
def before_request():
|
||||
g.desires_auth = False
|
||||
if not IS_LOCALHOST:
|
||||
app.config["COOKIE_DOMAIN"] = f".{request.host}"
|
||||
app.config["SESSION_COOKIE_DOMAIN"] = app.config["COOKIE_DOMAIN"]
|
||||
if SITE == 'marsey.world' and request.path != '/kofi':
|
||||
abort(404)
|
||||
|
||||
g.agent = request.headers.get("User-Agent", "")
|
||||
if not g.agent and request.path != '/kofi':
|
||||
return 'Please use a "User-Agent" header!', 403
|
||||
|
||||
ua = g.agent.lower()
|
||||
|
||||
if request.host != SITE:
|
||||
abort(403, "Unauthorized host provided!")
|
||||
|
||||
if SITE == 'marsey.world' and request.path != '/kofi':
|
||||
abort(404)
|
||||
|
||||
if request.headers.get("CF-Worker"):
|
||||
abort(403, "Cloudflare workers are not allowed to access this website.")
|
||||
|
||||
if not get_setting('bots') and request.headers.get("Authorization"): abort(403)
|
||||
g.agent = request.headers.get("User-Agent", "")
|
||||
if not g.agent and request.path != '/kofi':
|
||||
abort(403, 'Please use a "User-Agent" header!')
|
||||
|
||||
if not get_setting('bots') and request.headers.get("Authorization"):
|
||||
abort(403)
|
||||
|
||||
g.desires_auth = False
|
||||
if not IS_LOCALHOST:
|
||||
app.config["COOKIE_DOMAIN"] = f".{request.host}"
|
||||
app.config["SESSION_COOKIE_DOMAIN"] = app.config["COOKIE_DOMAIN"]
|
||||
|
||||
ua = g.agent.lower()
|
||||
|
||||
g.nonce = None
|
||||
|
||||
if '; wv) ' in ua:
|
||||
g.browser = 'webview'
|
||||
|
@ -54,11 +58,57 @@ def before_request():
|
|||
limiter.check()
|
||||
g.db = db_session()
|
||||
|
||||
|
||||
|
||||
CSP = {
|
||||
"upgrade-insecure-requests": "",
|
||||
|
||||
"default-src": "'none'",
|
||||
"frame-ancestors": "'none'",
|
||||
|
||||
"form-action": "'self'",
|
||||
"manifest-src": "'self'",
|
||||
"worker-src": "'self'",
|
||||
"base-uri": "'self'",
|
||||
"font-src": "'self'",
|
||||
"media-src": "'self'",
|
||||
|
||||
"style-src-elem": "'self' 'nonce-{nonce}'",
|
||||
"style-src-attr": "'unsafe-inline'",
|
||||
"style-src": "'self' 'unsafe-inline'",
|
||||
|
||||
"script-src-elem": "'self' 'nonce-{nonce}' challenges.cloudflare.com",
|
||||
"script-src-attr": "'unsafe-inline'",
|
||||
"script-src": "'self' 'unsafe-inline' challenges.cloudflare.com",
|
||||
|
||||
"img-src": "https:",
|
||||
"frame-src": "challenges.cloudflare.com www.youtube-nocookie.com platform.twitter.com",
|
||||
"connect-src": "'self' tls-use1.fpapi.io api.fpjs.io",
|
||||
|
||||
"report-to": "csp",
|
||||
"report-uri": "/csp_violations",
|
||||
}
|
||||
|
||||
if IS_LOCALHOST:
|
||||
CSP["style-src-elem"] += " rdrama.net"
|
||||
CSP["script-src-elem"] += " rdrama.net"
|
||||
CSP["img-src"] += " http:"
|
||||
|
||||
CSP_str = ''
|
||||
|
||||
for k, val in CSP.items():
|
||||
CSP_str += f'{k} {val}; '
|
||||
|
||||
@app.after_request
|
||||
def after_request(response:Response):
|
||||
if response.status_code < 400:
|
||||
_set_cloudflare_cookie(response)
|
||||
_commit_and_close_db()
|
||||
|
||||
if g.nonce:
|
||||
response.headers.add("Report-To", {"group":"csp","max_age":10886400,"endpoints":[{"url":"/csp_violations"}]})
|
||||
response.headers.add("Content-Security-Policy", CSP_str.format(nonce=g.nonce))
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
|
|
@ -333,3 +333,11 @@ if not os.path.exists(f'files/templates/donate_{SITE_NAME}.html'):
|
|||
@auth_desired_with_logingate
|
||||
def donate(v):
|
||||
return render_template(f'donate_{SITE_NAME}.html', v=v)
|
||||
|
||||
|
||||
@app.post('/csp_violations')
|
||||
@limiter.limit("10/minute;50/day")
|
||||
def csp_violations():
|
||||
content = request.get_json(force=True)
|
||||
print(json.dumps(content, indent=4, sort_keys=True), flush=True)
|
||||
return ''
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import time
|
||||
import secrets
|
||||
from flask import g, request, session
|
||||
|
||||
from files.classes.clients import ClientAuth
|
||||
|
@ -40,7 +41,8 @@ def get_logged_in_user():
|
|||
else:
|
||||
session.pop("lo_user")
|
||||
|
||||
g.is_api_or_xhr = bool((v and v.client) or request.headers.get("xhr"))
|
||||
g.is_api = v and v.client
|
||||
g.is_api_or_xhr = bool(g.is_api or request.headers.get("xhr"))
|
||||
|
||||
if request.method.lower() != "get" and get_setting('read_only_mode') and not (v and v.admin_level >= PERMS['SITE_BYPASS_READ_ONLY_MODE']):
|
||||
abort(403)
|
||||
|
@ -67,6 +69,10 @@ def get_logged_in_user():
|
|||
if f'@{v.username}, ' not in f.read():
|
||||
t = time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(time.time()))
|
||||
log_file(f'@{v.username}, {v.truescore}, {ip}, {t}\n', 'eg.log')
|
||||
|
||||
if not g.is_api:
|
||||
g.nonce = secrets.token_urlsafe(16)
|
||||
|
||||
return v
|
||||
|
||||
def auth_desired(f):
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
</section>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function submitAddAlt(element) {
|
||||
if (!element || !element.form) return;
|
||||
const isLinking = element.id == 'add-alt-form-link';
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
</form>
|
||||
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
@media (max-width: 767.98px) {
|
||||
table {
|
||||
display: inline-block;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block content %}
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function unbanDomain(t, domain) {
|
||||
postToastSwitch(t,'/admin/unban_domain/' + domain);
|
||||
t.parentElement.parentElement.remove();
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if p.award_count("tilt", v) %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
@keyframes post-tilt {
|
||||
0% {transform: rotate(0deg);}
|
||||
25% {transform: rotate({{p.award_count("tilt", v)}}deg);}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "casino/game_screen.html" %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function makeBlackjackRequest(action) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("post", `/casino/twentyone/${action}`);
|
||||
|
@ -236,7 +236,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block actions %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.blackjack-cardset {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "default.html" %}
|
||||
{% block pagetitle %}{{game.capitalize()}}{% endblock %}
|
||||
{% block content %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.game_screen-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -27,7 +27,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
<script nonce="{{g.nonce}}">
|
||||
/**
|
||||
* This script block contains generic helper function usable across casino games:
|
||||
* - Wagers
|
||||
|
@ -233,7 +233,7 @@
|
|||
|
||||
{% block script %} {% endblock %}
|
||||
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
@keyframes drawing {
|
||||
from {
|
||||
left: 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
<script nonce="{{g.nonce}}">
|
||||
if (
|
||||
document.readyState === "complete" ||
|
||||
(document.readyState !== "loading" && !document.documentElement.doScroll)
|
||||
|
@ -393,7 +393,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block screen %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.roulette-table-number {
|
||||
flex: 1;
|
||||
height: 60px;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
<script nonce="{{g.nonce}}">
|
||||
function pullSlots() {
|
||||
const { amount, currency } = getWager();
|
||||
|
||||
|
@ -73,7 +73,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block screen %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.slots_reels {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
data-avatar="{{v.profile_url}}"
|
||||
data-hat="{{v.hat_active(v)[0]}}">
|
||||
</div>
|
||||
<script>window.global = window</script>
|
||||
<script nonce="{{g.nonce}}">window.global = window</script>
|
||||
{% if IS_LOCALHOST %}
|
||||
<script defer src="https://rdrama.net/assets/js/chat_done.js"></script>
|
||||
{% else %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{%- import 'util/macros.html' as macros with context -%}
|
||||
{% if not request.headers.get("xhr") %}
|
||||
{% if comment_info %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
if (location.hash != 'context')
|
||||
location.hash = 'context'
|
||||
</script>
|
||||
|
@ -246,7 +246,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if c.award_count("tilt", v) %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
@keyframes c{{c.id}}-tilt {
|
||||
0% {transform: rotate(0deg);}
|
||||
25% {transform: rotate({{c.award_count("tilt", v)}}deg);}
|
||||
|
@ -786,7 +786,7 @@
|
|||
<script defer src="{{'js/comments+submission_listing.js' | asset}}"></script>
|
||||
<script defer src="{{'js/comments.js' | asset}}"></script>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
{% if p and (not v or v.highlightcomments) %}
|
||||
comments = JSON.parse(localStorage.getItem("comment-counts")) || {}
|
||||
lastCount = comments['{{p.id}}']
|
||||
|
@ -852,7 +852,7 @@
|
|||
{# TODO: disabled pending fix #}
|
||||
{% if false %}
|
||||
<div id="detection" style="display:none;background-color:canvas;color-scheme:light"></div>
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
const detectionDiv = document.querySelector('#detection');
|
||||
const isAutoDark = getComputedStyle(detectionDiv).backgroundColor != 'rgb(255, 255, 255)';
|
||||
if (!isAutoDark) {
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if g.browser == 'apple' %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const videos = document.querySelectorAll('video')
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="description" content="{{DESCRIPTION}}">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
|
|
@ -3,35 +3,8 @@
|
|||
<head>
|
||||
<meta name="description" content="People die and this is the place to see it. You only have one life, don't make the mistakes seen here.">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'self'; font-src 'self'; img-src 'self';">
|
||||
|
||||
<style>
|
||||
:root{--primary:#ff66ac}
|
||||
.mod:before {
|
||||
content: "(((";
|
||||
}
|
||||
.mod:after {
|
||||
content: ")))";
|
||||
}
|
||||
body {
|
||||
padding-top: 54px !important;
|
||||
}
|
||||
@media (max-width: 767.98px) {
|
||||
body {
|
||||
padding-top: 44px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 380px) {
|
||||
#logo {
|
||||
width: 100px;
|
||||
margin-left: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
.pad {
|
||||
padding-bottom: 7.4px;
|
||||
padding-top: 7.4px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/main.css?v=4032">
|
||||
<link rel="stylesheet" href="/assets/css/midnight.css?v=4000">
|
||||
|
||||
|
@ -50,7 +23,6 @@
|
|||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/icon.webp?v=1">
|
||||
<link rel="manifest" href="/assets/manifest_WPD.json?v=426">
|
||||
<link rel="mask-icon" href="/icon.webp?v=1">
|
||||
<link rel="shortcut icon" href="/icon.webp?v=1">
|
||||
<meta name="apple-mobile-web-app-title" content="WPD">
|
||||
|
@ -93,7 +65,7 @@
|
|||
|
||||
<nav class="shadow-md fixed-top">
|
||||
<div class="navbar navbar-expand-md navbar-light" id="navbar">
|
||||
<div class="container-fluid" style="padding: 0;">
|
||||
<div class="container-fluid p-0">
|
||||
<a href="/" class="navbar-brand mr-auto">
|
||||
<img id="header--icon" alt="header icon" src="/i/WPD/headericon.webp?v=3009">
|
||||
</a>
|
||||
|
@ -105,10 +77,10 @@
|
|||
</div>
|
||||
|
||||
<div class="flex-grow-1 d-fl d-mob-none pad">
|
||||
<form class="form-inline search flex-nowrap mx-0 mx-lg-auto" style="margin-right: 40rem !important;" action="/search/posts/" method="get">
|
||||
<form class="form-inline search flex-nowrap mx-0 mx-lg-auto" action="/search/posts/" method="get">
|
||||
<input autocomplete="off" class="form-control w-100" type="search" placeholder="Search" name="q" value="">
|
||||
<span class="input-group-append">
|
||||
<span class="input-group-text border-0 bg-transparent" style="margin-left: -2.5rem;">
|
||||
<span class="input-group-text border-0 bg-transparent">
|
||||
<i class="fa fa-search"></i>
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
@ -3,35 +3,8 @@
|
|||
<head>
|
||||
<meta name="description" content="rdrama.net caters to drama in all forms such as: Real life, videos, photos, gossip, rumors, news sites, Reddit, and Beyond™. There isn't drama we won't touch, and we want it all!">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'self'; font-src 'self'; img-src 'self';">
|
||||
|
||||
<style>
|
||||
:root{--primary:#ff66ac}
|
||||
.mod:before {
|
||||
content: "(((";
|
||||
}
|
||||
.mod:after {
|
||||
content: ")))";
|
||||
}
|
||||
body {
|
||||
padding-top: 54px !important;
|
||||
}
|
||||
@media (max-width: 767.98px) {
|
||||
body {
|
||||
padding-top: 44px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 380px) {
|
||||
#logo {
|
||||
width: 100px;
|
||||
margin-left: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
.pad {
|
||||
padding-bottom: 7.4px;
|
||||
padding-top: 7.4px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/main.css?v=4032">
|
||||
<link rel="stylesheet" href="/assets/css/midnight.css?v=4000">
|
||||
|
||||
|
@ -50,7 +23,6 @@
|
|||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/icon.webp?v=1">
|
||||
<link rel="manifest" href="/assets/manifest_rDrama.json?v=426">
|
||||
<link rel="mask-icon" href="/icon.webp?v=1">
|
||||
<link rel="shortcut icon" href="/icon.webp?v=1">
|
||||
<meta name="apple-mobile-web-app-title" content="rDrama">
|
||||
|
@ -93,7 +65,7 @@
|
|||
|
||||
<nav class="shadow-md fixed-top">
|
||||
<div class="navbar navbar-expand-md navbar-light" id="navbar">
|
||||
<div class="container-fluid" style="padding: 0;">
|
||||
<div class="container-fluid p-0">
|
||||
<a href="/" class="navbar-brand mr-auto">
|
||||
<img id="header--icon" alt="header icon" src="/i/rDrama/headericon.webp?v=3009">
|
||||
</a>
|
||||
|
@ -105,10 +77,10 @@
|
|||
</div>
|
||||
|
||||
<div class="flex-grow-1 d-fl d-mob-none pad">
|
||||
<form class="form-inline search flex-nowrap mx-0 mx-lg-auto" style="margin-right: 40rem !important;" action="/search/posts/" method="get">
|
||||
<form class="form-inline search flex-nowrap mx-0 mx-lg-auto" action="/search/posts/" method="get">
|
||||
<input autocomplete="off" class="form-control w-100" type="search" placeholder="Search" name="q" value="">
|
||||
<span class="input-group-append">
|
||||
<span class="input-group-text border-0 bg-transparent" style="margin-left: -2.5rem;">
|
||||
<span class="input-group-text border-0 bg-transparent">
|
||||
<i class="fa fa-search"></i>
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
@ -9,19 +9,19 @@
|
|||
{# idk why snow isn't working vvvvvvvvvv #}
|
||||
{% if p.award_count("snow", v) %}
|
||||
<script src="{{'event/js/snow.js'|asset}}"></script>
|
||||
<script>snow(80);</script>
|
||||
<script nonce="{{g.nonce}}">snow(80);</script>
|
||||
{% endif %}
|
||||
|
||||
{% if p.award_count("frostbite", v) %}
|
||||
<div class="frost"></div>
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
const root = document.querySelector(':root');
|
||||
|
||||
const count = 5;
|
||||
const opacity = count * 0.1;
|
||||
root.style.setProperty('--opacity-frost', opacity);
|
||||
</script>
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
:root {
|
||||
--opacity-frost: 0.25;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
|||
{% if p.award_count("snowed-in", v) %}
|
||||
<canvas id="canvas-snowed-in-overlay"></canvas>
|
||||
<canvas id="canvas-snowed-in-lines"></canvas>
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
#canvas-snowed-in-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -64,7 +64,7 @@
|
|||
</div>
|
||||
|
||||
{% if p.award_count("lights", v) %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
#post-root::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
@ -81,7 +81,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if p.award_count("candycane", v) %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
#post-title, #post-content p {
|
||||
--color2: #cc4145;
|
||||
--color1: rgb(12, 128, 101);
|
||||
|
@ -108,7 +108,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if p.award_count("fireplace", v) %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
#banner-skybox {
|
||||
fill: url(#skybox-gradient-night)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{# <script src="{{'event/js/neko.js'|asset}}"></script> #}
|
||||
{% if request.path == '/' %}
|
||||
<script src="{{'event/js/snow.js'|asset}}"></script>
|
||||
<script>snow(80);</script>
|
||||
<script nonce="{{g.nonce}}">snow(80);</script>
|
||||
{% endif %}
|
||||
|
||||
<a rel="nofollow noopener noreferrer" href="https://www.youtube.com/watch?v=BuKft9LpL_0" style="text-decoration: none !important">
|
||||
|
|
|
@ -199,7 +199,7 @@
|
|||
<circle cx="169.44" cy="10.935"/>
|
||||
</g>
|
||||
<defs>
|
||||
<style>.star1 circle {r: 0.5;}
|
||||
<style nonce="{{g.nonce}}">.star1 circle {r: 0.5;}
|
||||
.star2 circle {r: 0.75;}
|
||||
.star3 circle {r: 1.0;}
|
||||
.star4 circle {r: 1.2;}
|
||||
|
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
@ -199,7 +199,7 @@
|
|||
<circle cx="169.44" cy="10.935"/>
|
||||
</g>
|
||||
<defs>
|
||||
<style>.star1 circle {r: 0.5;}
|
||||
<style nonce="{{g.nonce}}">.star1 circle {r: 0.5;}
|
||||
.star2 circle {r: 0.75;}
|
||||
.star3 circle {r: 1.0;}
|
||||
.star4 circle {r: 1.2;}
|
||||
|
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
@ -3,7 +3,7 @@
|
|||
{% set path = "assets/event/media/music" %}
|
||||
{% set song = "/" ~ path ~ "/" ~ listdir('files/' ~ path)|random() ~ '?v=45' %}
|
||||
{% endif %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
const audio = new Audio("{{song}}");
|
||||
audio.loop=true;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block pagetype %}message{% endblock %}
|
||||
|
||||
{% block banner %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.shop-tabs {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function equip_hat(t, hat_id, hat_name) {
|
||||
const profile_pic_hat = document.getElementById("profile-pic-35-hat");
|
||||
function extra_actions(xhr) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{%- endif -%}
|
||||
|
||||
<nav class="shadow-md fixed-top">
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
body {padding-top: 83px !important}
|
||||
@media (max-width: 767.98px) {
|
||||
body {
|
||||
|
@ -50,7 +50,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
body {padding-top: 54px !important}
|
||||
@media (max-width: 767.98px) {
|
||||
body {
|
||||
|
@ -75,7 +75,7 @@
|
|||
{% if sub %}
|
||||
<a id="sub-name" href="/h/{{sub}}" class="font-weight-bold ml-2 flex-grow-1 mt-1" {% if sub.name|length >= 17 %}style="font-size:max(10px,1.2vw)"{% else %}style="font-size:max(14px,1.2vw)"{% endif %}>{% if not HOLE_STYLE_FLAIR %}/h/{% endif %}{{sub}}</a>
|
||||
{% elif has_logo %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
{% if SITE_NAME == 'WPD' %}
|
||||
@media (min-width: 1000px) {
|
||||
{% else %}
|
||||
|
@ -358,12 +358,12 @@
|
|||
<div id="formkey" class="d-none">{{v|formkey}}</div>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
IMAGE_FORMATS = {{IMAGE_FORMATS|safe}};
|
||||
</script>
|
||||
|
||||
{% if not v %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.pad {
|
||||
padding-bottom: 7.4px;
|
||||
padding-top: 7.4px;
|
||||
|
@ -372,7 +372,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if v and v.poor -%}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
* :not(img[src="/i/hand.webp"] + img, img.golden, img[g], img[glow], .live-circle) {
|
||||
animation: unset !important;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
{% block navbar %}
|
||||
<div class="d-flex align-items-center">
|
||||
{% if SITE_NAME != 'WPD' and not sub %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
@media (max-width: 427px) {
|
||||
.smol-fp {
|
||||
font-size: 2.7vw;
|
||||
|
@ -169,7 +169,7 @@
|
|||
|
||||
{% if request.path == '/' and v %}
|
||||
<script defer src="/assets/js/register_service_worker.js"></script>
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
registerServiceWorker(
|
||||
"/assets/js/service_worker.js",
|
||||
|
@ -180,7 +180,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if request.path == '/' and g.browser != 'webview' and time.time() > session.get('tooltip_last_dismissed',0)+86400*30 %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.dismiss-beg {
|
||||
color: #919191;
|
||||
float: left;
|
||||
|
@ -193,7 +193,7 @@
|
|||
<div id="mobile-prompt" data-bs-toggle="tooltip" data-bs-container="#mobile-prompt-container" data-bs-placement="top" data-bs-trigger="click" data-bs-html="true" title="<i class='dismiss-beg fas fa-x'></i>Click me to install the {{SITE_NAME}} mobile app!"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
if (!window.matchMedia('(display-mode: minimal-ui)')['matches']) {
|
||||
if (window.innerWidth <= 737) {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
@ -214,7 +214,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
#mobile-prompt + .bs-tooltip-bottom {
|
||||
transform: None !important;
|
||||
inset: 0px 0px auto auto !important;
|
||||
|
@ -224,7 +224,7 @@
|
|||
|
||||
{% if request.path == '/' and v and FP %}
|
||||
{% if not v.fp %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function fp(fp) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", '/fp/'+fp);
|
||||
|
|
|
@ -2,25 +2,25 @@
|
|||
{% block pagetitle %}Moderation Log{% endblock %}
|
||||
{% block content %}
|
||||
{% if v %}
|
||||
<style>:root{--primary:#{{v.themecolor}}}</style>
|
||||
<style nonce="{{g.nonce}}">:root{--primary:#{{v.themecolor}}}</style>
|
||||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
{% if v.theme == 'classic_dark' %}
|
||||
<link rel="stylesheet" href="{{('css/classic.css') | asset}}">
|
||||
{% endif %}
|
||||
<link rel="stylesheet" href="{{('css/'~v.theme~'.css') | asset}}">
|
||||
{% if v.agendaposter %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
html {
|
||||
cursor:url('/i/dildo.webp?v=2000'), auto;
|
||||
}
|
||||
</style>
|
||||
{% elif v.css %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
{{v.css | safe}}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<style>:root{--primary:#{{DEFAULT_COLOR}}</style>
|
||||
<style nonce="{{g.nonce}}">:root{--primary:#{{DEFAULT_COLOR}}</style>
|
||||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
<link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}">
|
||||
{% endif %}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<small><a href="/lost_2fa">Lost your 2FA device?</a></small>
|
||||
<button type="submit" class="btn btn-primary login w-100 mt-3" id="login_button">Sign in</button>
|
||||
</form>
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.getElementById('2fa_token').focus()
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div id="form" class="d-none"></div>
|
||||
<div class="modal fade" id="emojiModal" tabindex="-1" role="dialog">
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
#emojiTabs {height: 80%;}
|
||||
@media (max-width: 650px) {
|
||||
#emojiTabs {height: 100%;}
|
||||
|
@ -70,7 +70,7 @@
|
|||
I've took the liberty to populate this tab with a selection of Anton's emojis 😽. Next time you'll find the ones you used the most in there 📚
|
||||
</div>
|
||||
<div id="tab-content" class="tab-content d-flex flex-wrap py-3 pl-2" hidden style="text-align:center;">
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.emoji2 {
|
||||
/*background: None!important;*/
|
||||
width:60px;
|
||||
|
|
|
@ -152,7 +152,7 @@
|
|||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.comment {
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
for (const x of ['css','profilecss']) {
|
||||
const ta = document.getElementById(`${x}-textarea`);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "settings.html" %}
|
||||
{% block pagetitle %}Personal Settings{% endblock %}
|
||||
{% block content %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.bg-image {
|
||||
padding: 0.25rem;
|
||||
width: 15rem;
|
||||
|
@ -279,7 +279,7 @@
|
|||
{% include "modals/gif.html" %}
|
||||
|
||||
{% if v.flairchanged %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const date = formatDate(new Date({{v.flairchanged}}*1000));
|
||||
const text = ` - Your flair has been locked until ${date}`;
|
||||
|
@ -326,7 +326,7 @@
|
|||
{{permanent_filter_modal('profanityreplacer', '/settings/personal', 'profanityreplacer', 'Profanity Replacer', 'Soapy-Mouthed Angel')}}
|
||||
{%- endif %}
|
||||
{% if FEATURES['USERS_PERMANENT_WORD_FILTERS'] -%}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.addEventListener("DOMContentLoaded", function (event) {
|
||||
const sr_toggle = document.getElementById("slurreplacer");
|
||||
const sr_link = document.getElementById('slurreplacer-perma-link');
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
{% block pagetitle %}Shop{% endblock %}
|
||||
{% block pagetype %}message{% endblock %}
|
||||
{% block banner %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.shop-tabs {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% block pagetitle %}/h/{{sub}} Mods{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function removeMod(e) {
|
||||
sendFormXHR(e,
|
||||
() => {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{% endblock %}
|
||||
{% block pagetype %}thread{% endblock %}
|
||||
{% block head_final %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
body > .container {
|
||||
padding-left: 20px !important;
|
||||
padding-right: 20px !important;
|
||||
|
@ -350,7 +350,7 @@
|
|||
</div>
|
||||
|
||||
{% if offset %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function viewmore(pid,sort,offset,ids) {
|
||||
btn = document.getElementById("viewbtn");
|
||||
btn.disabled = true;
|
||||
|
@ -417,7 +417,7 @@
|
|||
{% if not p.replies %}{% include "comments.html" %}{% endif %}
|
||||
|
||||
{% if not v or v.highlightcomments %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
showNewCommentCounts('{{p.id}}', {{p.comment_count}})
|
||||
{% if "?context" not in request.full_path %}
|
||||
|
@ -429,10 +429,11 @@
|
|||
localStorage.setItem("comment-counts", JSON.stringify(comments))
|
||||
{% endif %}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% if success %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
history.pushState(null, null, '{{p.permalink}}');
|
||||
localStorage.setItem("post-title", "")
|
||||
localStorage.setItem("post-text", "")
|
||||
|
@ -448,7 +449,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if fart and not (v and v.has_badge(128)) %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
fart = Math.floor(Math.random() * 5) + 1
|
||||
let audio = new Audio(`/assets/images/${fart}.webp`);
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
</div>
|
||||
|
||||
{% if offset %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
function viewmore(pid,sort,offset,ids) {
|
||||
btn = document.getElementById("viewbtn");
|
||||
btn.disabled = true;
|
||||
|
|
|
@ -214,7 +214,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
{% if not v or v.highlightcomments %}
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
showNewCommentCounts({{p.id}}, {{p.comment_count}})
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
</div>
|
||||
{% endblock %}
|
||||
{% if request.path == '/submit' %}
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
let sub = document.getElementById('sub')
|
||||
if (sub) sub.value = localStorage.getItem("sub")
|
||||
</script>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.onpaste = function(event) {
|
||||
files = structuredClone(event.clipboardData.files);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% block pagetitle %}Submit Marseys{% endblock %}
|
||||
{% block pagetype %}message{% endblock %}
|
||||
{% block content %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
input:not(.btn) {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.onpaste = function(event) {
|
||||
files = structuredClone(event.clipboardData.files);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
document.onpaste = function(event) {
|
||||
files = structuredClone(event.clipboardData.files);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
{% if not HOLIDAY_EVENT %}
|
||||
<link rel="stylesheet" href="{{('css/transparent.css') | asset}}">
|
||||
{% endif %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
body {
|
||||
background-image: url('{{u.profile_background}}') !important;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<script defer src="{{'js/vendor/bootstrap.js' | asset}}"></script>
|
||||
<script defer src="{{'js/core.js' | asset}}"></script>
|
||||
|
||||
<script>
|
||||
<script nonce="{{g.nonce}}">
|
||||
if (window.matchMedia('(display-mode: minimal-ui)')['matches']) {
|
||||
const links = document.querySelectorAll('a[data-target="t"]');
|
||||
for (const link of links) {
|
||||
|
@ -106,9 +106,9 @@
|
|||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
<link id="favicon" rel="icon" type="image/webp" href="/icon.webp?v=1">
|
||||
{% if v %}
|
||||
<style>:root{--primary:#{{v.themecolor}}}</style>
|
||||
<style nonce="{{g.nonce}}">:root{--primary:#{{v.themecolor}}}</style>
|
||||
{% if v.agendaposter %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
html {
|
||||
cursor:url('/i/dildo.webp?v=2000'), auto;
|
||||
}
|
||||
|
@ -120,12 +120,12 @@
|
|||
{% endif %}
|
||||
<link rel="stylesheet" href="{{('css/'~v.theme~'.css') | asset}}">
|
||||
{% if v.css and not request.path.startswith('/settings') %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
{{v.css | safe}}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% if v.themecolor == '30409f' %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
p a {
|
||||
color: #2a96f3;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if SITE_NAME == 'rDrama' %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
.mod:before {
|
||||
content: '(((';
|
||||
}
|
||||
|
@ -188,7 +188,7 @@
|
|||
{% if not HOLIDAY_EVENT %}
|
||||
<link rel="stylesheet" href="{{('css/transparent.css') | asset}}">
|
||||
{% endif %}
|
||||
<style>
|
||||
<style nonce="{{g.nonce}}">
|
||||
body {
|
||||
background:url("{{background}}") center center fixed;
|
||||
background-color: rgb(var(--background));
|
||||
|
@ -202,7 +202,7 @@
|
|||
{% endmacro %}
|
||||
|
||||
{% macro default_theme() %}
|
||||
<style>:root{--primary:#{{DEFAULT_COLOR}}}</style>
|
||||
<style nonce="{{g.nonce}}">:root{--primary:#{{DEFAULT_COLOR}}}</style>
|
||||
<link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}">
|
||||
{% endmacro %}
|
||||
|
||||
|
|
|
@ -2,4 +2,3 @@ add_header Referrer-Policy "same-origin";
|
|||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
|
||||
add_header X-Frame-Options "deny";
|
||||
add_header X-Content-Type-Options "nosniff";
|
||||
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' challenges.cloudflare.com rdrama.net; connect-src 'self' tls-use1.fpapi.io api.fpjs.io; object-src 'none';";
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
include includes/headers;
|
||||
add_header Content-Security-Policy "default-src 'none';";
|
||||
sendfile on;
|
||||
sendfile_max_chunk 1m;
|
||||
tcp_nopush on;
|
||||
|
|
12
nginx.conf
12
nginx.conf
|
@ -5,6 +5,7 @@ server {
|
|||
listen [::]:80;
|
||||
proxy_set_header Host $http_host;
|
||||
include includes/headers;
|
||||
add_header Content-Security-Policy "default-src 'none';";
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:5000/;
|
||||
|
@ -18,6 +19,7 @@ server {
|
|||
proxy_set_header Connection "Upgrade";
|
||||
proxy_pass http://localhost:5001/socket.io;
|
||||
include includes/headers;
|
||||
add_header Content-Security-Policy "default-src 'none';";
|
||||
}
|
||||
location /chat {
|
||||
proxy_pass http://localhost:5001/chat;
|
||||
|
@ -70,6 +72,16 @@ server {
|
|||
alias /rDrama/files/assets/images/rDrama/icon.webp;
|
||||
include includes/serve-static;
|
||||
}
|
||||
location =/favicon.ico {
|
||||
alias /rDrama/files/assets/images/rDrama/icon.webp;
|
||||
include includes/serve-static;
|
||||
}
|
||||
location =/offline.html {
|
||||
alias /rDrama/files/assets/offline.html;
|
||||
add_header Content-Security-Policy "default-src 'none'; style-src 'unsafe-inline'; img-src data:;";
|
||||
|
||||
}
|
||||
|
||||
|
||||
error_page 502 = /502.html;
|
||||
location =/502.html {
|
||||
|
|
Loading…
Reference in New Issue