mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Encode HTML when entered in edit data cells (#1302)
* Encode HTML when entered in edit data cells * Use VS Code's string encoding function
This commit is contained in:
@@ -88,19 +88,6 @@ export function parseNumAsTimeString(value: number): string {
|
|||||||
return tempVal > 0 ? rs + '.' + mss : rs;
|
return tempVal > 0 ? rs + '.' + mss : rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts <, >, &, ", ', and any characters that are outside \u00A0 to numeric HTML entity values
|
|
||||||
* like {
|
|
||||||
* (Adapted from http://stackoverflow.com/a/18750001)
|
|
||||||
* @param str String to convert
|
|
||||||
* @return String with characters replaced.
|
|
||||||
*/
|
|
||||||
export function htmlEntities(str: string): string {
|
|
||||||
return typeof (str) === 'string'
|
|
||||||
? str.replace(/[\u00A0-\u9999<>\&"']/gim, (i) => { return `&#${i.charCodeAt(0)};`; })
|
|
||||||
: undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
||||||
let prefix = purpose ? uriPrefixes[purpose] : uriPrefixes.default;
|
let prefix = purpose ? uriPrefixes[purpose] : uriPrefixes.default;
|
||||||
let uri = generateUriWithPrefix(connection, prefix);
|
let uri = generateUriWithPrefix(connection, prefix);
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as Utils from 'sql/parts/connection/common/utils';
|
import * as Strings from 'vs/base/common/strings';
|
||||||
|
|
||||||
export class DBCellValue {
|
export class DBCellValue {
|
||||||
displayValue: string;
|
displayValue: string;
|
||||||
isNull: boolean;
|
isNull: boolean;
|
||||||
|
|
||||||
public static isDBCellValue(object: any): boolean {
|
public static isDBCellValue(object: any): boolean {
|
||||||
return (object !== undefined && object.displayValue !== undefined && object.isNull !== undefined);
|
return (object !== undefined && object.displayValue !== undefined && object.isNull !== undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export function hyperLinkFormatter(row: number, cell: any, value: any, columnDef
|
|||||||
valueToDisplay = 'NULL';
|
valueToDisplay = 'NULL';
|
||||||
if (!value.isNull) {
|
if (!value.isNull) {
|
||||||
cellClasses += ' xmlLink';
|
cellClasses += ' xmlLink';
|
||||||
valueToDisplay = Utils.htmlEntities(value.displayValue);
|
valueToDisplay = Strings.escape(value.displayValue);
|
||||||
return `<a class="${cellClasses}" href="#" >${valueToDisplay}</a>`;
|
return `<a class="${cellClasses}" href="#" >${valueToDisplay}</a>`;
|
||||||
} else {
|
} else {
|
||||||
cellClasses += ' missing-value';
|
cellClasses += ' missing-value';
|
||||||
@@ -44,13 +44,12 @@ export function textFormatter(row: number, cell: any, value: any, columnDef: any
|
|||||||
if (DBCellValue.isDBCellValue(value)) {
|
if (DBCellValue.isDBCellValue(value)) {
|
||||||
valueToDisplay = 'NULL';
|
valueToDisplay = 'NULL';
|
||||||
if (!value.isNull) {
|
if (!value.isNull) {
|
||||||
valueToDisplay = Utils.htmlEntities(value.displayValue.replace(/(\r\n|\n|\r)/g, ' '));
|
valueToDisplay = Strings.escape(value.displayValue.replace(/(\r\n|\n|\r)/g, ' '));
|
||||||
} else {
|
} else {
|
||||||
cellClasses += ' missing-value';
|
cellClasses += ' missing-value';
|
||||||
}
|
}
|
||||||
} else if (typeof value === 'string'){
|
} else if (typeof value === 'string') {
|
||||||
valueToDisplay = value;
|
valueToDisplay = Strings.escape(value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<span title="${valueToDisplay}" class="${cellClasses}">${valueToDisplay}</span>`;
|
return `<span title="${valueToDisplay}" class="${cellClasses}">${valueToDisplay}</span>`;
|
||||||
|
|||||||
43
src/sqltest/parts/grid/services/sharedServices.test.ts
Normal file
43
src/sqltest/parts/grid/services/sharedServices.test.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import * as SharedServices from 'sql/parts/grid/services/sharedServices';
|
||||||
|
|
||||||
|
const testText = '<div>test text</div>';
|
||||||
|
|
||||||
|
suite('Grid shared services tests', () => {
|
||||||
|
test('textFormatter should encode HTML when formatting a DBCellValue object', () => {
|
||||||
|
// If I format a DBCellValue object that contains HTML
|
||||||
|
let cellValue = new SharedServices.DBCellValue();
|
||||||
|
cellValue.displayValue = testText;
|
||||||
|
cellValue.isNull = false;
|
||||||
|
let formattedHtml = SharedServices.textFormatter(undefined, undefined, cellValue, undefined, undefined);
|
||||||
|
|
||||||
|
// Then the result is HTML for a span element containing the cell value's display value as plain text
|
||||||
|
verifyFormattedHtml(formattedHtml, testText);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('textFormatter should encode HTML when formatting a string', () => {
|
||||||
|
// If I format a string that contains HTML
|
||||||
|
let formattedHtml = SharedServices.textFormatter(undefined, undefined, testText, undefined, undefined);
|
||||||
|
|
||||||
|
// Then the result is HTML for a span element containing the given text as plain text
|
||||||
|
verifyFormattedHtml(formattedHtml, testText);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function verifyFormattedHtml(formattedHtml: string, expectedText: string): void {
|
||||||
|
// Create an element containing the span returned by the format call
|
||||||
|
let element = document.createElement('div');
|
||||||
|
element.innerHTML = formattedHtml;
|
||||||
|
let spanElement = element.children[0];
|
||||||
|
|
||||||
|
// Verify that the span element's text, not its innerHTML, matches the expected text
|
||||||
|
assert.equal(spanElement.textContent, testText);
|
||||||
|
assert.notEqual(spanElement.innerHTML, testText);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user