mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
check for encoded components (#18231)
* check for encoded components * address comments * relocate and simplify test * move encodeUrl to notebookLinkHandler * added comments * add containsEncodedUri to network.ts
This commit is contained in:
14
src/sql/base/common/network.ts
Normal file
14
src/sql/base/common/network.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified URL is already URI-encoded by checking if there are any unencoded reserved URI component characters
|
||||||
|
* (such as ?, =, &, /, etc.) in the URL. See https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent for more details.
|
||||||
|
* @returns true if the URL contains encoded URI component reserved characters
|
||||||
|
*/
|
||||||
|
export function containsEncodedUriComponentReservedCharacters(url: string): boolean {
|
||||||
|
// ie ?,=,&,/ etc
|
||||||
|
return (decodeURI(url) !== decodeURIComponent(url));
|
||||||
|
}
|
||||||
@@ -278,8 +278,8 @@ export class MarkdownToolbarComponent extends AngularDisposable {
|
|||||||
// Otherwise, re-focus on the output element, and insert the link directly.
|
// Otherwise, re-focus on the output element, and insert the link directly.
|
||||||
this.output?.nativeElement?.focus();
|
this.output?.nativeElement?.focus();
|
||||||
// Need to encode URI here in order for user to click the proper encoded link in WYSIWYG
|
// Need to encode URI here in order for user to click the proper encoded link in WYSIWYG
|
||||||
let encodedLinkURL = encodeURI(linkUrl);
|
let encodedLinkURL = notebookLink.getEncodedLinkUrl();
|
||||||
document.execCommand('insertHTML', false, `<a href="${encodedLinkURL}" title="${encodedLinkURL}" is-encoded="true" is-absolute=${notebookLink.isAbsolutePath}>${escape(linkCalloutResult?.insertUnescapedLinkLabel)}</a>`);
|
document.execCommand('insertHTML', false, `<a href="${encodedLinkURL}" title="${linkUrl}" is-encoded="true" is-absolute=${notebookLink.isAbsolutePath}>${escape(linkCalloutResult?.insertUnescapedLinkLabel)}</a>`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (type === MarkdownButtonType.IMAGE_PREVIEW) {
|
} else if (type === MarkdownButtonType.IMAGE_PREVIEW) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import * as path from 'vs/base/common/path';
|
|||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { replaceInvalidLinkPath } from 'sql/workbench/contrib/notebook/common/utils';
|
import { replaceInvalidLinkPath } from 'sql/workbench/contrib/notebook/common/utils';
|
||||||
import { isWindows } from 'vs/base/common/platform';
|
import { isWindows } from 'vs/base/common/platform';
|
||||||
|
import { containsEncodedUriComponentReservedCharacters } from 'sql/base/common/network';
|
||||||
|
|
||||||
const useAbsolutePathConfigName = 'notebook.useAbsoluteFilePaths';
|
const useAbsolutePathConfigName = 'notebook.useAbsoluteFilePaths';
|
||||||
|
|
||||||
@@ -118,6 +119,24 @@ export class NotebookLinkHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to get encoded url, Gets the link URI-encoded link URL
|
||||||
|
* (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
|
||||||
|
* @returns the encoded url
|
||||||
|
*/
|
||||||
|
public getEncodedLinkUrl(): string | undefined {
|
||||||
|
if (typeof this._link === 'string') {
|
||||||
|
// Need to encode URI here in order for user to click the proper encoded link in WYSIWYG
|
||||||
|
// skip encoding it if it's already encoded
|
||||||
|
if (!containsEncodedUriComponentReservedCharacters(this._link)) {
|
||||||
|
return encodeURI(this._link);
|
||||||
|
}
|
||||||
|
return this._link;
|
||||||
|
}
|
||||||
|
// since we only handle strings that come from call out dialogs
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a URI for for a link with a anchor (#)
|
* Creates a URI for for a link with a anchor (#)
|
||||||
* @param node is the HTMLAnchorElement of the target notebook
|
* @param node is the HTMLAnchorElement of the target notebook
|
||||||
|
|||||||
@@ -43,4 +43,3 @@ export function highlightSelectedText(): void {
|
|||||||
document.execCommand('hiliteColor', false, 'Yellow');
|
document.execCommand('hiliteColor', false, 'Yellow');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,4 +103,31 @@ suite('Noteboook Link Handler', function (): void {
|
|||||||
result = new NotebookLinkHandler(notebookUri, Object.assign(document.createElement('a'), { href: '/tmp/my%20stuff.png' }), configurationService);
|
result = new NotebookLinkHandler(notebookUri, Object.assign(document.createElement('a'), { href: '/tmp/my%20stuff.png' }), configurationService);
|
||||||
assert.strictEqual(result.getLinkUrl(), `.${path.sep}my%2520stuff.png`, 'Basic link test with %20 filename failed');
|
assert.strictEqual(result.getLinkUrl(), `.${path.sep}my%2520stuff.png`, 'Basic link test with %20 filename failed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Should return correctly encoded url/filePath', () => {
|
||||||
|
test('when given an already-encoded URL', () => {
|
||||||
|
let notebookLinkHandler = new NotebookLinkHandler(notebookUri, 'https://github.com/search/advanced?q=test&r=microsoft%2Fazuredatastudio&type=Code', configurationService);
|
||||||
|
assert.strictEqual(notebookLinkHandler.getEncodedLinkUrl(), `https://github.com/search/advanced?q=test&r=microsoft%2Fazuredatastudio&type=Code`, 'HTTPS link does not need encoding');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('when given an already encoded URL with non-reserved characters', () => {
|
||||||
|
let notebookLinkHandler = new NotebookLinkHandler(notebookUri, 'https://github.com/search/advanced?q=test&r=(microsoft%2Fazuredatastudio)&type=Code', configurationService);
|
||||||
|
assert.strictEqual(notebookLinkHandler.getEncodedLinkUrl(), `https://github.com/search/advanced?q=test&r=(microsoft%2Fazuredatastudio)&type=Code`, '() in HTTP link should not be encoded');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('when given an unencoded URL with a space', () => {
|
||||||
|
let notebookLinkHandler = new NotebookLinkHandler(notebookUri, 'https://github.com/search/advanced?q=test&r=(microsoft/azuredata studio)&type=Code', configurationService);
|
||||||
|
assert.strictEqual(notebookLinkHandler.getEncodedLinkUrl(), `https://github.com/search/advanced?q=test&r=(microsoft/azuredata%20studio)&type=Code`, 'space in the url failed to be encoded');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('when given file path with a space', () => {
|
||||||
|
let notebookLinkHandler = new NotebookLinkHandler(notebookUri, '/Notebooks/Test_Paths/My File.ipynb', configurationService);
|
||||||
|
assert.strictEqual(notebookLinkHandler.getEncodedLinkUrl(), `/Notebooks/Test_Paths/My%20File.ipynb`, 'space in file path failed to be encoded');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('when given file path has special characters such as %', () => {
|
||||||
|
let notebookLinkHandler = new NotebookLinkHandler(notebookUri, '/Notebooks/Test_Paths/My%20File.ipynb', configurationService);
|
||||||
|
assert.strictEqual(notebookLinkHandler.getEncodedLinkUrl(), `/Notebooks/Test_Paths/My%2520File.ipynb`, '% in file path failed to be encoded');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user