-
Notifications
You must be signed in to change notification settings - Fork 280
Expand file tree
/
Copy pathvalidateThemeRoot.ts
More file actions
70 lines (57 loc) · 2.36 KB
/
validateThemeRoot.ts
File metadata and controls
70 lines (57 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { getLocationHref } from "./Location.js";
const getMetaTagValue = (metaTagName: string) => {
const metaTag = document.querySelector(`META[name="${metaTagName}"]`),
metaTagContent = metaTag && metaTag.getAttribute("content");
return metaTagContent;
};
const validateThemeOrigin = (origin: string, isSameOrigin: boolean = false) => {
const allowedOrigins = getMetaTagValue("sap-allowed-theme-origins") ?? getMetaTagValue("sap-allowedThemeOrigins"); // Prioritize the new meta tag name
// If no allowed origins are specified, block.
if (!allowedOrigins) {
return false;
}
// If it's same-origin (relative URL resolved to current page), allow it when there's any meta tag present
// The presence of the meta tag indicates the user wants to use theme roots
if (isSameOrigin) {
return true;
}
return allowedOrigins.split(",").some(allowedOrigin => {
return allowedOrigin === "*" || origin === allowedOrigin.trim();
});
};
const validateThemeRoot = (themeRoot: string) => {
let resultUrl;
let isSameOrigin = false;
try {
if (themeRoot.startsWith(".") || (themeRoot.startsWith("/") && !themeRoot.startsWith("//"))) {
// Handle relative url
// new URL("/newExmPath", "http://example.com/exmPath") => http://example.com/newExmPath
// new URL("./newExmPath", "http://example.com/exmPath") => http://example.com/exmPath/newExmPath
// new URL("../newExmPath", "http://example.com/exmPath") => http://example.com/newExmPath
resultUrl = new URL(themeRoot, getLocationHref()).toString();
isSameOrigin = true;
} else {
// Protocol-relative URLs (//host/path) need a base to resolve the protocol
const themeRootURL = themeRoot.startsWith("//") ? new URL(themeRoot, getLocationHref()) : new URL(themeRoot);
const origin = themeRootURL.origin;
const currentOrigin = new URL(getLocationHref()).origin;
// Check if the absolute URL is same-origin
isSameOrigin = origin === currentOrigin;
if (origin && validateThemeOrigin(origin, isSameOrigin)) {
// If origin is allowed, use it
resultUrl = themeRootURL.toString();
} else {
// If origin is not allowed, return undefined to indicate validation failed
return undefined;
}
}
if (!resultUrl.endsWith("/")) {
resultUrl = `${resultUrl}/`;
}
return `${resultUrl}UI5/`;
} catch (e) {
// Catch if URL is not correct
return undefined;
}
};
export default validateThemeRoot;