PageSourceSearch

https://pupwife.com/scripts/effects/spaDashboardCsp.js

js pupwife.com collected 2026-09-30 15:04:03 UTC 6,037 bytes, 99 lines download raw bytes

1/**
2 * Shared Content-Security-Policy for SPA dashboard entry pages.
3 *
4 * Load synchronously in <head> (before restrictive CSP meta tags):
5 *   <script src="/scripts/effects/spaDashboardCsp.js"></script>
6 *
7 * Optional extra connect-src hosts (tool pages):
8 *   <script>window.__spaCspExtraConnect = 'https://example.com';</script>
9 *   <script src="/scripts/effects/spaDashboardCsp.js"></script>
10 *
11 * Meta-tag CSP is fixed at first paint — changing it later via JS does NOT relax the policy.
12 */
13(function (global) {
14    'use strict';
15
16    var SPA_DASHBOARD_CSP_PARTS = [
17        "default-src 'self' https:",
18        "script-src 'self' 'unsafe-inline' https: blob: 'wasm-unsafe-eval' 'unsafe-eval'",
19        "style-src 'self' 'unsafe-inline' https:",
20        "font-src 'self' https://cdnjs.cloudflare.com https://fonts.googleapis.com https://fonts.gstatic.com data:",
21        "img-src 'self' data: blob: https: https://cdn.throne.com https://cdn.discordapp.com https://i.scdn.co https://storage.googleapis.com https://static.wikia.nocookie.net https://adriansblinkiecollection.neocities.org https://wowee.neocities.org https://i.pinimg.com https://64.media.tumblr.com https://deckofcardsapi.com",
22        "connect-src 'self' https://api.pexels.com https://litter.catbox.moe https://media1.vocaroo.com https://raw.githubusercontent.com https://cdn.pixabay.com https://storage.googleapis.com https://www.gstatic.com https://*.firebaseio.com wss://*.firebaseio.com https://cdn.jsdelivr.net https://*.jsdelivr.net https://weirdscifi.ratiosemper.com https://api.sunrise-sunset.org https://api.weatherapi.com https://api.ipify.org https://ipapi.co https://icanhazip.com https://do.pishock.com https://api.allorigins.win https://corsproxy.io https://throne.com https://cdn.throne.com https://api.lanyard.rest wss://api.lanyard.rest https://discord.com https://open.spotify.com https://secure.geonames.org https://api.dictionaryapi.dev https://words.bighugelabs.com https://esm.sh https://unpkg.com https://*.unpkg.com https://0.peerjs.com wss://0.peerjs.com https://linkmeta.dev https://api.klipy.com https://api.themoviedb.org https://latest.currency-api.pages.dev https://api.bigdatacloud.net https://archive.org https://*.archive.org https://hearthis.at https://*.hearthis.at https://hearthis.app https://*.hearthis.app https://api.mixfall.com https://mixfall.com https://cdn.mixfall.com https://stream.mixfall.com https://img.hearthis.at https://cdn.hearthis.at https://strudel.cc https://*.strudel.cc",
23        "media-src 'self' https: blob: data:",
24        "frame-src 'self' https://throne.com https://*.firebaseio.com https://*.firebaseapp.com https://app.hearthis.at https://strudel.cc https://*.strudel.cc https://wowee.neocities.org",
25        "worker-src 'self' blob:"
26    ];
27
28    function mergeConnectExtras(baseParts, extraConnect) {
29        if (!extraConnect || !String(extraConnect).trim()) return baseParts.join('; ') + ';';
30        var parts = baseParts.slice();
31        var i;
32        for (i = 0; i < parts.length; i++) {
33            if (parts[i].indexOf('connect-src ') === 0) {
34                parts[i] = parts[i] + ' ' + String(extraConnect).trim();
35                break;
36            }
37        }
38        return parts.join('; ') + ';';
39    }
40
41    function buildDashboardCsp() {
42        var extra = global.__spaCspExtraConnect || '';
43        return mergeConnectExtras(SPA_DASHBOARD_CSP_PARTS, extra);
44    }
45
46    /** True only when the policy already includes hosts added for global voice + chatroom. */
47    function cspHasDashboardHosts(content) {
48        var c = content || '';
49        return c.indexOf('api.lanyard.rest') !== -1
50            && c.indexOf('0.peerjs.com') !== -1
51            && c.indexOf('fonts.gstatic.com') !== -1;
52    }
53
54    function injectDashboardCspMeta() {
55        var content = buildDashboardCsp();
56        global.SPA_DASHBOARD_CSP = content;
57
58        var existing = document.querySelector('meta[http-equiv="Content-Security-Policy"], meta[http-equiv="content-security-policy"]');
59        if (existing && cspHasDashboardHosts(existing.content || '')) {
60            return;
61        }
62
63        var metas = document.querySelectorAll('meta[http-equiv="Content-Security-Policy"], meta[http-equiv="content-security-policy"]');
64        var i;
65        for (i = metas.length - 1; i >= 0; i--) {
66            if (metas[i].parentNode) metas[i].parentNode.removeChild(metas[i]);
67        }
68
69        if (document.readyState === 'loading' && typeof document.write === 'function') {
70            document.write('<meta http-equiv="Content-Security-Policy" content="' + content.replace(/"/g, '&quot;') + '">');
71            return;
72        }
73
74        var meta = document.createElement('meta');
75        meta.setAttribute('http-equiv', 'Content-Security-Policy');
76        meta.setAttribute('content', content);
77        var head = document.head || document.getElementsByTagName('head')[0];
78        if (head) head.insertBefore(meta, head.firstChild);
79    }
80
81    global.SPA_DASHBOARD_CSP = buildDashboardCsp();
82    global.SpaDashboardCsp = {
83        build: buildDashboardCsp,
84        hasDashboardHosts: cspHasDashboardHosts,
85        inject: injectDashboardCspMeta,
86        warnIfIncomplete: function () {
87            var meta = document.querySelector('meta[http-equiv="Content-Security-Policy"], meta[http-equiv="content-security-policy"]');
88            if (!meta || !cspHasDashboardHosts(meta.content || '')) {
89                console.warn(
90                    '[SpaDashboardCsp] This page CSP is missing dashboard hosts (e.g. api.lanyard.rest, 0.peerjs.com). ' +
91                    'Add a synchronous <script src="/scripts/effects/spaDashboardCsp.js"></script> in <head> ' +
92                    'and remove restrictive CSP meta tags. SPA navigation cannot upgrade CSP after first paint.'
93                );
94            }
95        }
96    };
97
98    injectDashboardCspMeta();
99})(typeof window !== 'undefined' ? window : this);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.