mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-30 21:51:26 +00:00
Merge pull request #6 from Philreact/master-kenny2
pass ui language to qapps
This commit is contained in:
@@ -1,14 +1,13 @@
|
|||||||
package org.qortal.api;
|
package org.qortal.api;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.select.Elements;
|
import org.jsoup.select.Elements;
|
||||||
import org.qortal.arbitrary.misc.Service;
|
import org.qortal.arbitrary.misc.Service;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class HTMLParser {
|
public class HTMLParser {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(HTMLParser.class);
|
private static final Logger LOGGER = LogManager.getLogger(HTMLParser.class);
|
||||||
@@ -22,10 +21,11 @@ public class HTMLParser {
|
|||||||
private String identifier;
|
private String identifier;
|
||||||
private String path;
|
private String path;
|
||||||
private String theme;
|
private String theme;
|
||||||
|
private String lang;
|
||||||
private boolean usingCustomRouting;
|
private boolean usingCustomRouting;
|
||||||
|
|
||||||
public HTMLParser(String resourceId, String inPath, String prefix, boolean includeResourceIdInPrefix, byte[] data,
|
public HTMLParser(String resourceId, String inPath, String prefix, boolean includeResourceIdInPrefix, byte[] data,
|
||||||
String qdnContext, Service service, String identifier, String theme, boolean usingCustomRouting) {
|
String qdnContext, Service service, String identifier, String theme, boolean usingCustomRouting, String lang) {
|
||||||
String inPathWithoutFilename = inPath.contains("/") ? inPath.substring(0, inPath.lastIndexOf('/')) : String.format("/%s",inPath);
|
String inPathWithoutFilename = inPath.contains("/") ? inPath.substring(0, inPath.lastIndexOf('/')) : String.format("/%s",inPath);
|
||||||
this.qdnBase = includeResourceIdInPrefix ? String.format("%s/%s", prefix, resourceId) : prefix;
|
this.qdnBase = includeResourceIdInPrefix ? String.format("%s/%s", prefix, resourceId) : prefix;
|
||||||
this.qdnBaseWithPath = includeResourceIdInPrefix ? String.format("%s/%s%s", prefix, resourceId, inPathWithoutFilename) : String.format("%s%s", prefix, inPathWithoutFilename);
|
this.qdnBaseWithPath = includeResourceIdInPrefix ? String.format("%s/%s%s", prefix, resourceId, inPathWithoutFilename) : String.format("%s%s", prefix, inPathWithoutFilename);
|
||||||
@@ -36,6 +36,7 @@ public class HTMLParser {
|
|||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
this.path = inPath;
|
this.path = inPath;
|
||||||
this.theme = theme;
|
this.theme = theme;
|
||||||
|
this.lang = lang;
|
||||||
this.usingCustomRouting = usingCustomRouting;
|
this.usingCustomRouting = usingCustomRouting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,9 +62,13 @@ public class HTMLParser {
|
|||||||
String identifier = this.identifier != null ? this.identifier.replace("\\", "").replace("\"","\\\"") : "";
|
String identifier = this.identifier != null ? this.identifier.replace("\\", "").replace("\"","\\\"") : "";
|
||||||
String path = this.path != null ? this.path.replace("\\", "").replace("\"","\\\"") : "";
|
String path = this.path != null ? this.path.replace("\\", "").replace("\"","\\\"") : "";
|
||||||
String theme = this.theme != null ? this.theme.replace("\\", "").replace("\"","\\\"") : "";
|
String theme = this.theme != null ? this.theme.replace("\\", "").replace("\"","\\\"") : "";
|
||||||
|
String lang = this.lang != null ? this.lang.replace("\\", "").replace("\"", "\\\"") : "";
|
||||||
String qdnBase = this.qdnBase != null ? this.qdnBase.replace("\\", "").replace("\"","\\\"") : "";
|
String qdnBase = this.qdnBase != null ? this.qdnBase.replace("\\", "").replace("\"","\\\"") : "";
|
||||||
String qdnBaseWithPath = this.qdnBaseWithPath != null ? this.qdnBaseWithPath.replace("\\", "").replace("\"","\\\"") : "";
|
String qdnBaseWithPath = this.qdnBaseWithPath != null ? this.qdnBaseWithPath.replace("\\", "").replace("\"","\\\"") : "";
|
||||||
String qdnContextVar = String.format("<script>var _qdnContext=\"%s\"; var _qdnTheme=\"%s\"; var _qdnService=\"%s\"; var _qdnName=\"%s\"; var _qdnIdentifier=\"%s\"; var _qdnPath=\"%s\"; var _qdnBase=\"%s\"; var _qdnBaseWithPath=\"%s\";</script>", qdnContext, theme, service, name, identifier, path, qdnBase, qdnBaseWithPath);
|
String qdnContextVar = String.format(
|
||||||
|
"<script>var _qdnContext=\"%s\"; var _qdnTheme=\"%s\"; var _qdnLang=\"%s\"; var _qdnService=\"%s\"; var _qdnName=\"%s\"; var _qdnIdentifier=\"%s\"; var _qdnPath=\"%s\"; var _qdnBase=\"%s\"; var _qdnBaseWithPath=\"%s\";</script>",
|
||||||
|
qdnContext, theme, lang, service, name, identifier, path, qdnBase, qdnBaseWithPath
|
||||||
|
);
|
||||||
head.get(0).prepend(qdnContextVar);
|
head.get(0).prepend(qdnContextVar);
|
||||||
|
|
||||||
// Add base href tag
|
// Add base href tag
|
||||||
|
@@ -142,10 +142,20 @@ public class DevProxyServerResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String lang = request.getParameter("lang");
|
||||||
|
if (lang == null || lang.isBlank()) {
|
||||||
|
lang = "en"; // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
String theme = request.getParameter("theme");
|
||||||
|
if (theme == null || theme.isBlank()) {
|
||||||
|
theme = "light";
|
||||||
|
}
|
||||||
|
|
||||||
// Parse and modify output if needed
|
// Parse and modify output if needed
|
||||||
if (HTMLParser.isHtmlFile(filename)) {
|
if (HTMLParser.isHtmlFile(filename)) {
|
||||||
// HTML file - needs to be parsed
|
// HTML file - needs to be parsed
|
||||||
HTMLParser htmlParser = new HTMLParser("", inPath, "", false, data, "proxy", Service.APP, null, "light", true);
|
HTMLParser htmlParser = new HTMLParser("", inPath, "", false, data, "proxy", Service.APP, null, theme , true, lang);
|
||||||
htmlParser.addAdditionalHeaderTags();
|
htmlParser.addAdditionalHeaderTags();
|
||||||
response.addHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval'; media-src 'self' data: blob:; img-src 'self' data: blob:; connect-src 'self' ws:; font-src 'self' data:;");
|
response.addHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval'; media-src 'self' data: blob:; img-src 'self' data: blob:; connect-src 'self' ws:; font-src 'self' data:;");
|
||||||
response.setContentType(con.getContentType());
|
response.setContentType(con.getContentType());
|
||||||
|
@@ -71,33 +71,33 @@ public class RenderResource {
|
|||||||
@Path("/signature/{signature}")
|
@Path("/signature/{signature}")
|
||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getIndexBySignature(@PathParam("signature") String signature,
|
public HttpServletResponse getIndexBySignature(@PathParam("signature") String signature,
|
||||||
@QueryParam("theme") String theme) {
|
@QueryParam("theme") String theme, @QueryParam("lang") String lang) {
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
||||||
Security.requirePriorAuthorization(request, signature, Service.WEBSITE, null);
|
Security.requirePriorAuthorization(request, signature, Service.WEBSITE, null);
|
||||||
|
|
||||||
return this.get(signature, ResourceIdType.SIGNATURE, null, null, "/", null, "/render/signature", true, true, theme);
|
return this.get(signature, ResourceIdType.SIGNATURE, null, null, "/", null, "/render/signature", true, true, theme, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/signature/{signature}/{path:.*}")
|
@Path("/signature/{signature}/{path:.*}")
|
||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getPathBySignature(@PathParam("signature") String signature, @PathParam("path") String inPath,
|
public HttpServletResponse getPathBySignature(@PathParam("signature") String signature, @PathParam("path") String inPath,
|
||||||
@QueryParam("theme") String theme) {
|
@QueryParam("theme") String theme, @QueryParam("lang") String lang) {
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
||||||
Security.requirePriorAuthorization(request, signature, Service.WEBSITE, null);
|
Security.requirePriorAuthorization(request, signature, Service.WEBSITE, null);
|
||||||
|
|
||||||
return this.get(signature, ResourceIdType.SIGNATURE, null, null, inPath,null, "/render/signature", true, true, theme);
|
return this.get(signature, ResourceIdType.SIGNATURE, null, null, inPath,null, "/render/signature", true, true, theme, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/hash/{hash}")
|
@Path("/hash/{hash}")
|
||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getIndexByHash(@PathParam("hash") String hash58, @QueryParam("secret") String secret58,
|
public HttpServletResponse getIndexByHash(@PathParam("hash") String hash58, @QueryParam("secret") String secret58,
|
||||||
@QueryParam("theme") String theme) {
|
@QueryParam("theme") String theme, @QueryParam("lang") String lang) {
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
||||||
Security.requirePriorAuthorization(request, hash58, Service.WEBSITE, null);
|
Security.requirePriorAuthorization(request, hash58, Service.WEBSITE, null);
|
||||||
|
|
||||||
return this.get(hash58, ResourceIdType.FILE_HASH, Service.ARBITRARY_DATA, null, "/", secret58, "/render/hash", true, false, theme);
|
return this.get(hash58, ResourceIdType.FILE_HASH, Service.ARBITRARY_DATA, null, "/", secret58, "/render/hash", true, false, theme, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@@ -105,11 +105,11 @@ public class RenderResource {
|
|||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getPathByHash(@PathParam("hash") String hash58, @PathParam("path") String inPath,
|
public HttpServletResponse getPathByHash(@PathParam("hash") String hash58, @PathParam("path") String inPath,
|
||||||
@QueryParam("secret") String secret58,
|
@QueryParam("secret") String secret58,
|
||||||
@QueryParam("theme") String theme) {
|
@QueryParam("theme") String theme, @QueryParam("lang") String lang) {
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
||||||
Security.requirePriorAuthorization(request, hash58, Service.WEBSITE, null);
|
Security.requirePriorAuthorization(request, hash58, Service.WEBSITE, null);
|
||||||
|
|
||||||
return this.get(hash58, ResourceIdType.FILE_HASH, Service.ARBITRARY_DATA, null, inPath, secret58, "/render/hash", true, false, theme);
|
return this.get(hash58, ResourceIdType.FILE_HASH, Service.ARBITRARY_DATA, null, inPath, secret58, "/render/hash", true, false, theme, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@@ -119,12 +119,12 @@ public class RenderResource {
|
|||||||
@PathParam("name") String name,
|
@PathParam("name") String name,
|
||||||
@PathParam("path") String inPath,
|
@PathParam("path") String inPath,
|
||||||
@QueryParam("identifier") String identifier,
|
@QueryParam("identifier") String identifier,
|
||||||
@QueryParam("theme") String theme) {
|
@QueryParam("theme") String theme, @QueryParam("lang") String lang) {
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
||||||
Security.requirePriorAuthorization(request, name, service, null);
|
Security.requirePriorAuthorization(request, name, service, null);
|
||||||
|
|
||||||
String prefix = String.format("/render/%s", service);
|
String prefix = String.format("/render/%s", service);
|
||||||
return this.get(name, ResourceIdType.NAME, service, identifier, inPath, null, prefix, true, true, theme);
|
return this.get(name, ResourceIdType.NAME, service, identifier, inPath, null, prefix, true, true, theme, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@@ -133,18 +133,18 @@ public class RenderResource {
|
|||||||
public HttpServletResponse getIndexByName(@PathParam("service") Service service,
|
public HttpServletResponse getIndexByName(@PathParam("service") Service service,
|
||||||
@PathParam("name") String name,
|
@PathParam("name") String name,
|
||||||
@QueryParam("identifier") String identifier,
|
@QueryParam("identifier") String identifier,
|
||||||
@QueryParam("theme") String theme) {
|
@QueryParam("theme") String theme, @QueryParam("lang") String lang) {
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
if (!Settings.getInstance().isQDNAuthBypassEnabled())
|
||||||
Security.requirePriorAuthorization(request, name, service, null);
|
Security.requirePriorAuthorization(request, name, service, null);
|
||||||
|
|
||||||
String prefix = String.format("/render/%s", service);
|
String prefix = String.format("/render/%s", service);
|
||||||
return this.get(name, ResourceIdType.NAME, service, identifier, "/", null, prefix, true, true, theme);
|
return this.get(name, ResourceIdType.NAME, service, identifier, "/", null, prefix, true, true, theme, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private HttpServletResponse get(String resourceId, ResourceIdType resourceIdType, Service service, String identifier,
|
private HttpServletResponse get(String resourceId, ResourceIdType resourceIdType, Service service, String identifier,
|
||||||
String inPath, String secret58, String prefix, boolean includeResourceIdInPrefix, boolean async, String theme) {
|
String inPath, String secret58, String prefix, boolean includeResourceIdInPrefix, boolean async, String theme, String lang) {
|
||||||
|
|
||||||
ArbitraryDataRenderer renderer = new ArbitraryDataRenderer(resourceId, resourceIdType, service, identifier, inPath,
|
ArbitraryDataRenderer renderer = new ArbitraryDataRenderer(resourceId, resourceIdType, service, identifier, inPath,
|
||||||
secret58, prefix, includeResourceIdInPrefix, async, "render", request, response, context);
|
secret58, prefix, includeResourceIdInPrefix, async, "render", request, response, context);
|
||||||
@@ -152,6 +152,9 @@ public class RenderResource {
|
|||||||
if (theme != null) {
|
if (theme != null) {
|
||||||
renderer.setTheme(theme);
|
renderer.setTheme(theme);
|
||||||
}
|
}
|
||||||
|
if (lang != null) {
|
||||||
|
renderer.setLang(lang);
|
||||||
|
}
|
||||||
return renderer.render();
|
return renderer.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@ public class ArbitraryDataRenderer {
|
|||||||
private final Service service;
|
private final Service service;
|
||||||
private final String identifier;
|
private final String identifier;
|
||||||
private String theme = "light";
|
private String theme = "light";
|
||||||
|
private String lang = "en";
|
||||||
private String inPath;
|
private String inPath;
|
||||||
private final String secret58;
|
private final String secret58;
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
@@ -166,7 +167,7 @@ public class ArbitraryDataRenderer {
|
|||||||
if (HTMLParser.isHtmlFile(filename)) {
|
if (HTMLParser.isHtmlFile(filename)) {
|
||||||
// HTML file - needs to be parsed
|
// HTML file - needs to be parsed
|
||||||
byte[] data = Files.readAllBytes(filePath); // TODO: limit file size that can be read into memory
|
byte[] data = Files.readAllBytes(filePath); // TODO: limit file size that can be read into memory
|
||||||
HTMLParser htmlParser = new HTMLParser(resourceId, inPath, prefix, includeResourceIdInPrefix, data, qdnContext, service, identifier, theme, usingCustomRouting);
|
HTMLParser htmlParser = new HTMLParser(resourceId, inPath, prefix, includeResourceIdInPrefix, data, qdnContext, service, identifier, theme, usingCustomRouting, lang);
|
||||||
htmlParser.addAdditionalHeaderTags();
|
htmlParser.addAdditionalHeaderTags();
|
||||||
response.addHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; media-src 'self' data: blob:; img-src 'self' data: blob:; connect-src 'self' wss:;");
|
response.addHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; media-src 'self' data: blob:; img-src 'self' data: blob:; connect-src 'self' wss:;");
|
||||||
response.setContentType(context.getMimeType(filename));
|
response.setContentType(context.getMimeType(filename));
|
||||||
@@ -256,5 +257,8 @@ public class ArbitraryDataRenderer {
|
|||||||
public void setTheme(String theme) {
|
public void setTheme(String theme) {
|
||||||
this.theme = theme;
|
this.theme = theme;
|
||||||
}
|
}
|
||||||
|
public void setLang(String lang) {
|
||||||
|
this.lang = lang;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,7 @@ function parseUrl(url) {
|
|||||||
|
|
||||||
// Remove theme, identifier, and time queries if they exist
|
// Remove theme, identifier, and time queries if they exist
|
||||||
parsedUrl.searchParams.delete("theme");
|
parsedUrl.searchParams.delete("theme");
|
||||||
|
parsedUrl.searchParams.delete("lang");
|
||||||
parsedUrl.searchParams.delete("identifier");
|
parsedUrl.searchParams.delete("identifier");
|
||||||
parsedUrl.searchParams.delete("time");
|
parsedUrl.searchParams.delete("time");
|
||||||
parsedUrl.searchParams.delete("isManualNavigation");
|
parsedUrl.searchParams.delete("isManualNavigation");
|
||||||
@@ -213,8 +214,11 @@ function buildResourceUrl(service, name, identifier, path, isLink) {
|
|||||||
if (path != null) url = url.concat((path.startsWith("/") ? "" : "/") + path);
|
if (path != null) url = url.concat((path.startsWith("/") ? "" : "/") + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLink) url = url.concat((url.includes("?") ? "" : "?") + "&theme=" + _qdnTheme);
|
if (isLink) {
|
||||||
|
const hasQuery = url.includes("?");
|
||||||
|
const queryPrefix = hasQuery ? "&" : "?";
|
||||||
|
url += queryPrefix + "theme=" + _qdnTheme + "&lang=" + _qdnLang;
|
||||||
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user