remove csp and assetProtocol, escape problem in production that don't appear in dev

This commit is contained in:
polv committed 2026-03-22 04:21:37 +07:00
1 parent a26cfceaf4
commit 9f88b6d93c
7 files changed
+40 -48

No files matched your search

Generated
-7
View File
@@ -1981,12 +1981,6 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "http-range"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.10.1" version = "1.10.1"
@@ -4843,7 +4837,6 @@ dependencies = [
"gtk", "gtk",
"heck 0.5.0", "heck 0.5.0",
"http", "http",
"http-range",
"jni", "jni",
"libc", "libc",
"log", "log",
+1 -1
View File
@@ -50,7 +50,7 @@ html.dark .glossaries {
word-break: keep-all; word-break: keep-all;
} }
img[src$=".svg"] { img[src$=".svg"], img[src^="data:image/svg"] {
filter: invert(1) hue-rotate(180deg); filter: invert(1) hue-rotate(180deg);
} }
+30 -19
View File
@@ -1,13 +1,12 @@
import { createElement as h } from "react"; import { createElement as h, useEffect, useState } from "react";
import { BaseDirectory, readFile } from "@tauri-apps/plugin-fs";
export default function Glossary({ export default function Glossary({
glossary, glossary,
yomitanURL,
maxLength, maxLength,
onTermClicked, onTermClicked,
}: { }: {
glossary: any; glossary: any;
yomitanURL: string;
maxLength?: number; maxLength?: number;
onTermClicked: (t: string) => void; onTermClicked: (t: string) => void;
}) { }) {
@@ -31,17 +30,14 @@ export default function Glossary({
// GlossaryImage // GlossaryImage
if ("type" in glossary && glossary.type === "image") { if ("type" in glossary && glossary.type === "image") {
return <GlossaryImage img={glossary} yomitanURL={yomitanURL} />; return <GlossaryImage img={glossary} />;
} }
// GlossaryStructuredContent // GlossaryStructuredContent
if ("type" in glossary && glossary.type === "structured-content") { if ("type" in glossary && glossary.type === "structured-content") {
const sc = glossary; const sc = glossary;
return ( return (
<StructuredContent <StructuredContent node={sc.content} {...{ maxLength, onTermClicked }} />
node={sc.content}
{...{ yomitanURL, maxLength, onTermClicked }}
/>
); );
} }
@@ -54,11 +50,32 @@ export default function Glossary({
return null; return null;
} }
function GlossaryImage({ img, yomitanURL }: { img: any; yomitanURL: string }) { function GlossaryImage({ img }: { img: any }) {
const [src, set_src] = useState(img.path);
useEffect(() => {
readFile("yomitan/" + img.path, {
baseDir: BaseDirectory.AppData,
}).then((b) => {
const r = new FileReader();
r.onload = () => {
const dataSrc = r.result as string;
const ext = img.path.split(".").pop();
set_src(
dataSrc.replace(
"data:application/octet-stream",
"data:image/" + (ext === "svg" ? "svg+xml" : ext),
),
);
};
r.readAsDataURL(new File([b], img.path));
});
});
return ( return (
<img <img
className="glossary-image" className="glossary-image"
src={`${yomitanURL || ""}/${img.path}`} src={src}
title={img.title} title={img.title}
alt={img.alt} alt={img.alt}
style={{ style={{
@@ -72,12 +89,10 @@ function GlossaryImage({ img, yomitanURL }: { img: any; yomitanURL: string }) {
function StructuredContent({ function StructuredContent({
node, node,
yomitanURL,
maxLength, maxLength,
onTermClicked, onTermClicked,
}: { }: {
node: any; node: any;
yomitanURL: string;
maxLength?: number; maxLength?: number;
onTermClicked: (t: string) => void; onTermClicked: (t: string) => void;
}): any { }): any {
@@ -102,7 +117,7 @@ function StructuredContent({
<StructuredContent <StructuredContent
key={i} key={i}
node={n} node={n}
{...{ yomitanURL, maxLength, onTermClicked }} {...{ maxLength, onTermClicked }}
/> />
))} ))}
</> </>
@@ -119,7 +134,7 @@ function StructuredContent({
// Image // Image
if (tag === "img") { if (tag === "img") {
return <GlossaryImage img={node} yomitanURL={yomitanURL} />; return <GlossaryImage img={node} />;
} }
// Link // Link
@@ -144,10 +159,7 @@ function StructuredContent({
}} }}
> >
{content ? ( {content ? (
<StructuredContent <StructuredContent node={content} {...{ maxLength, onTermClicked }} />
node={content}
{...{ yomitanURL, maxLength, onTermClicked }}
/>
) : null} ) : null}
</a> </a>
); );
@@ -161,7 +173,6 @@ function StructuredContent({
{ style: block.style, title: block.title, open: block.open }, { style: block.style, title: block.title, open: block.open },
StructuredContent({ StructuredContent({
node: block.content, node: block.content,
yomitanURL,
maxLength, maxLength,
onTermClicked, onTermClicked,
}), }),
+2 -14
View File
@@ -18,8 +18,7 @@ import {
Stack, Stack,
Switch, Switch,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { convertFileSrc, invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
import { appDataDir, join } from "@tauri-apps/api/path";
import { readText } from "@tauri-apps/plugin-clipboard-manager"; import { readText } from "@tauri-apps/plugin-clipboard-manager";
import Glossary from "../components/Glossary"; import Glossary from "../components/Glossary";
@@ -55,13 +54,6 @@ function SearchPage() {
const [furigana, set_furigana] = useState(""); const [furigana, set_furigana] = useState("");
const [isAutoKana, set_isAutoKana] = useState(true); const [isAutoKana, set_isAutoKana] = useState(true);
const [isScrollEnd, set_isScrollEnd] = useState(false); const [isScrollEnd, set_isScrollEnd] = useState(false);
const [yomitanURL, set_yomitanURL] = useState("");
useEffect(() => {
(async () => {
set_yomitanURL(convertFileSrc(await join(await appDataDir(), "yomitan")));
})();
});
const nSearch = useRef(0); const nSearch = useRef(0);
const searchboxRef = useRef<HTMLInputElement | null>(null); const searchboxRef = useRef<HTMLInputElement | null>(null);
@@ -420,11 +412,7 @@ function SearchPage() {
}} }}
> >
{JSON.parse(glossary_json).map((g: any, i: number) => ( {JSON.parse(glossary_json).map((g: any, i: number) => (
<Glossary <Glossary key={i} glossary={g} {...{ onTermClicked }} />
key={i}
glossary={g}
{...{ yomitanURL, onTermClicked }}
/>
))} ))}
</div> </div>
</Card.Body> </Card.Body>
+1 -1
View File
@@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
tauri-build = { version = "2", features = [] } tauri-build = { version = "2", features = [] }
[dependencies] [dependencies]
tauri = { version = "2", features = ["protocol-asset"] } tauri = { version = "2", features = [] }
tauri-plugin-opener = "2" tauri-plugin-opener = "2"
cjdic2-core = { path = "../src-core" } cjdic2-core = { path = "../src-core" }
tauri-plugin-http = "2" tauri-plugin-http = "2"
+4
View File
@@ -16,6 +16,10 @@
] ]
}, },
"fs:default", "fs:default",
{
"identifier": "fs:allow-appdata-read",
"allow": [{ "path": "$APPDATA/yomitan/**" }]
},
"clipboard-manager:allow-read-text" "clipboard-manager:allow-read-text"
] ]
} }
+2 -6
View File
@@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "cjdic2", "productName": "cjdic2",
"version": "0.1.2", "version": "0.1.3",
"identifier": "cc.polv.cjdic2", "identifier": "cc.polv.cjdic2",
"build": { "build": {
"beforeDevCommand": "pnpm dev", "beforeDevCommand": "pnpm dev",
@@ -19,11 +19,7 @@
} }
], ],
"security": { "security": {
"csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost", "csp": null
"assetProtocol": {
"enable": true,
"scope": ["$APPDATA/yomitan/**"]
}
} }
}, },
"bundle": { "bundle": {