* Improving the urls utils to not break dynamic protocols and testing the utils Signed-off-by: iifawzi <iifawzie@gmail.com> * Adding a list of blocked protocols Signed-off-by: iifawzi <iifawzie@gmail.com> * Update the way of sanitizing blocked protocols Signed-off-by: iifawzi <iifawzie@gmail.com> * Update shared/utils/urls.ts Javascript pseudo protocol does not require the // Co-authored-by: Tom Moor <tom.moor@gmail.com> * updating the javascript protocol sanitizing tests Signed-off-by: iifawzi <iifawzie@gmail.com> * Update shared/utils/urls.test.ts Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com> * Update shared/utils/urls.ts Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com> * Using toBe instead of toEqual in tests Signed-off-by: iifawzi <iifawzie@gmail.com> * Sanitizing data: and vbscript: Signed-off-by: iifawzi <iifawzie@gmail.com> * Using toBeUndefined instead of toEqual in tests Signed-off-by: iifawzi <iifawzie@gmail.com> * Using URL to check the protocols Signed-off-by: iifawzi <iifawzie@gmail.com> * Allowing sms, fax, and tel protocols Signed-off-by: iifawzi <iifawzie@gmail.com> * Update shared/utils/urls.ts inlining the protocols in the same file Co-authored-by: Tom Moor <tom.moor@gmail.com> * removing unused protocols constant Signed-off-by: iifawzi <iifawzie@gmail.com> Signed-off-by: iifawzi <iifawzie@gmail.com> Co-authored-by: Tom Moor <tom.moor@gmail.com> Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>
111 lines
2.7 KiB
TypeScript
111 lines
2.7 KiB
TypeScript
import { escapeRegExp } from "lodash";
|
|
import env from "../env";
|
|
import { parseDomain } from "./domains";
|
|
|
|
/**
|
|
* Prepends the CDN url to the given path (If a CDN is configured).
|
|
*
|
|
* @param path The path to prepend the CDN url to.
|
|
* @returns The path with the CDN url prepended.
|
|
*/
|
|
export function cdnPath(path: string): string {
|
|
return `${env.CDN_URL}${path}`;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given string is a link to inside the application.
|
|
*
|
|
* Important Note: If this is called server-side, it will always return false.
|
|
* The reason this is in a shared util is because it's used in an editor plugin
|
|
* which is also in the shared code
|
|
*
|
|
* @param url The url to check.
|
|
* @returns True if the url is internal, false otherwise.
|
|
*/
|
|
export function isInternalUrl(href: string) {
|
|
// empty strings are never internal
|
|
if (href === "") {
|
|
return false;
|
|
}
|
|
|
|
// relative paths are always internal
|
|
if (href[0] === "/") {
|
|
return true;
|
|
}
|
|
|
|
const outline =
|
|
typeof window !== "undefined"
|
|
? parseDomain(window.location.href)
|
|
: undefined;
|
|
|
|
const domain = parseDomain(href);
|
|
return outline?.host === domain.host;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given string is a url.
|
|
*
|
|
* @param url The url to check.
|
|
* @returns True if a url, false otherwise.
|
|
*/
|
|
export function isUrl(text: string) {
|
|
if (text.match(/\n/)) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const url = new URL(text);
|
|
const blockedProtocols = ["javascript:", "file:", "vbscript:", "data:"];
|
|
|
|
return url.hostname !== "" && !blockedProtocols.includes(url.protocol);
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given string is a link to outside the application.
|
|
*
|
|
* @param url The url to check.
|
|
* @returns True if the url is external, false otherwise.
|
|
*/
|
|
export function isExternalUrl(url: string) {
|
|
return !!url && !isInternalUrl(url);
|
|
}
|
|
|
|
/**
|
|
* For use in the editor, this function will ensure that a url is
|
|
* potentially valid, and filter out unsupported and malicious protocols.
|
|
*
|
|
* @param url The url to sanitize
|
|
* @returns The sanitized href
|
|
*/
|
|
export function sanitizeUrl(url: string | null | undefined) {
|
|
if (!url) {
|
|
return undefined;
|
|
}
|
|
|
|
if (
|
|
!isUrl(url) &&
|
|
!url.startsWith("/") &&
|
|
!url.startsWith("#") &&
|
|
!url.startsWith("mailto:") &&
|
|
!url.startsWith("sms:") &&
|
|
!url.startsWith("fax:") &&
|
|
!url.startsWith("tel:")
|
|
) {
|
|
return `https://${url}`;
|
|
}
|
|
return url;
|
|
}
|
|
|
|
export function urlRegex(url: string | null | undefined): RegExp | undefined {
|
|
if (!url || !isUrl(url)) {
|
|
return undefined;
|
|
}
|
|
|
|
const urlObj = new URL(sanitizeUrl(url) as string);
|
|
|
|
return new RegExp(escapeRegExp(`${urlObj.protocol}//${urlObj.host}`));
|
|
}
|