fix(editor): should check url origin and ip address url (#12663)

Closes: [BS-3578](https://linear.app/affine-design/issue/BS-3578/复制本的-url-无法识别)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Improved URL validation to recognize and allow IPv4 addresses when the origin matches the provided base URL.

- **Tests**
  - Added a test to ensure URLs with IP addresses (e.g., http://127.0.0.1) are considered valid when the origin matches.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fundon
2025-06-03 03:08:16 +00:00
parent ac3f247f01
commit 658393159b
2 changed files with 16 additions and 5 deletions

View File

@@ -80,4 +80,8 @@ describe('isValidUrl: determining whether a URL is valid is very complicated', (
// See also https://stackoverflow.com/questions/9238640/how-long-can-a-tld-possibly-be#:~:text=Longest%20TLD%20up%20to%20date,17%20when%20decoded%20%5Bverm%C3%B6gensberatung%5D.
expect(isValidUrl('example.xn--vermgensberatung-pwb')).toEqual(false);
});
test('should allow ip address url when origin is same', () => {
expect(isValidUrl('http://127.0.0.1', 'http://127.0.0.1')).toEqual(true);
});
});

View File

@@ -11,6 +11,9 @@ const ALLOWED_SCHEMES = new Set([
// https://publicsuffix.org/
const TLD_REGEXP = /(?:\.[a-zA-Z]+)?(\.[a-zA-Z]{2,})$/;
const IPV4_ADDR_REGEXP =
/^(25[0-5]|2[0-4]\d|[01]?\d\d?)(\.(25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/;
const toURL = (str: string) => {
try {
if (!URL.canParse(str)) return null;
@@ -21,16 +24,20 @@ const toURL = (str: string) => {
}
};
function resolveURL(str: string) {
function resolveURL(str: string, baseUrl: string, padded = false) {
const url = toURL(str);
if (!url) return null;
const protocol = url.protocol.substring(0, url.protocol.length - 1);
const hostname = url.hostname;
const origin = url.origin;
let allowed = ALLOWED_SCHEMES.has(protocol);
if (allowed && hostname.includes('.')) {
allowed = TLD_REGEXP.test(hostname);
allowed =
origin === baseUrl ||
TLD_REGEXP.test(hostname) ||
(padded ? false : IPV4_ADDR_REGEXP.test(hostname));
}
return { url, allowed };
@@ -68,10 +75,10 @@ export function normalizeUrl(str: string) {
*
* For more detail see https://www.ietf.org/rfc/rfc1738.txt
*/
export function isValidUrl(str: string) {
export function isValidUrl(str: string, baseUrl = location.origin) {
str = str.trim();
let result = resolveURL(str);
let result = resolveURL(str, baseUrl);
if (result && !result.allowed) return false;
@@ -80,7 +87,7 @@ export function isValidUrl(str: string) {
if (!hasScheme) {
const dotIdx = str.indexOf('.');
if (dotIdx > 0 && dotIdx < str.length - 1) {
result = resolveURL(`https://${str}`);
result = resolveURL(`https://${str}`, baseUrl, true);
}
}
}