Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/json-language-features/client/src/utils/urlMatch.ts
5237 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Uri } from 'vscode';
7
8
/**
9
* Check whether a URL matches the list of trusted domains or URIs.
10
*
11
* trustedDomains is an object where:
12
* - Keys are full domains (https://www.microsoft.com) or full URIs (https://www.test.com/schemas/mySchema.json)
13
* - Keys can include wildcards (https://*.microsoft.com) or glob patterns
14
* - Values are booleans indicating if the domain/URI is trusted (true) or blocked (false)
15
*
16
* @param url The URL to check
17
* @param trustedDomains Object mapping domain patterns to boolean trust values
18
*/
19
export function matchesUrlPattern(url: Uri, trustedDomains: Record<string, boolean>): boolean {
20
// Check localhost
21
if (isLocalhostAuthority(url.authority)) {
22
return true;
23
}
24
25
for (const [pattern, isTrusted] of Object.entries(trustedDomains)) {
26
if (typeof pattern !== 'string' || pattern.trim() === '') {
27
continue;
28
}
29
30
// Wildcard matches everything
31
if (pattern === '*') {
32
return isTrusted;
33
}
34
35
try {
36
const patternUri = Uri.parse(pattern);
37
38
// Scheme must match
39
if (url.scheme !== patternUri.scheme) {
40
continue;
41
}
42
43
// Check authority (host:port)
44
if (!matchesAuthority(url.authority, patternUri.authority)) {
45
continue;
46
}
47
48
// Check path
49
if (!matchesPath(url.path, patternUri.path)) {
50
continue;
51
}
52
53
return isTrusted;
54
} catch {
55
// Invalid pattern, skip
56
continue;
57
}
58
}
59
60
return false;
61
}
62
63
function matchesAuthority(urlAuthority: string, patternAuthority: string): boolean {
64
urlAuthority = urlAuthority.toLowerCase();
65
patternAuthority = patternAuthority.toLowerCase();
66
67
if (patternAuthority === urlAuthority) {
68
return true;
69
}
70
// Handle wildcard subdomains (e.g., *.github.com)
71
if (patternAuthority.startsWith('*.')) {
72
const patternDomain = patternAuthority.substring(2);
73
// Exact match or subdomain match
74
return urlAuthority === patternDomain || urlAuthority.endsWith('.' + patternDomain);
75
}
76
77
return false;
78
}
79
80
function matchesPath(urlPath: string, patternPath: string): boolean {
81
// Empty pattern path or just "/" matches any path
82
if (!patternPath || patternPath === '/') {
83
return true;
84
}
85
86
// Exact match
87
if (urlPath === patternPath) {
88
return true;
89
}
90
91
// If pattern ends with '/', it matches any path starting with it
92
if (patternPath.endsWith('/')) {
93
return urlPath.startsWith(patternPath);
94
}
95
96
// Otherwise, pattern must be a prefix
97
return urlPath.startsWith(patternPath + '/') || urlPath === patternPath;
98
}
99
100
101
const rLocalhost = /^(.+\.)?localhost(:\d+)?$/i;
102
const r127 = /^127\.0\.0\.1(:\d+)?$/;
103
const rIPv6Localhost = /^\[::1\](:\d+)?$/;
104
105
function isLocalhostAuthority(authority: string): boolean {
106
return rLocalhost.test(authority) || r127.test(authority) || rIPv6Localhost.test(authority);
107
}
108
109