UPG-100 batch selection CSV: also neutralise a leading TAB or CR (OWASP's full list of formula triggers), asserted by the gate
This commit is contained in:
parent
03af1d87b5
commit
ee955bac5a
2 changed files with 7 additions and 3 deletions
|
|
@ -45,8 +45,9 @@ const records = [
|
|||
{ slug: 'q-comma', name: 'Bhil, Tadvi "Hill"', country_code: 'IND', population: 3100 },
|
||||
{ slug: 'q-formula', name: '=HYPERLINK("x")', country_code: 'NPL', population: 450 },
|
||||
{ slug: 'q-newline', name: 'Line one\nLine two', country_code: 'NPL', population: 7 },
|
||||
{ slug: 'q-tab', name: '\t=cmd', country_code: 'NPL', population: 1 },
|
||||
]
|
||||
const from = new Map([['agaria', ['Mahārāshtra', 'Goa']], ['q-comma', ['Goa']], ['q-formula', ['Nepal']], ['q-newline', ['Nepal']]])
|
||||
const from = new Map([['agaria', ['Mahārāshtra', 'Goa']], ['q-comma', ['Goa']], ['q-formula', ['Nepal']], ['q-newline', ['Nepal']], ['q-tab', ['Nepal']]])
|
||||
const color = '#e69f00'
|
||||
const csv = X.selectionCsv(records, from, { color })
|
||||
const text = X.selectionClipboard(selection, { color }, csv)
|
||||
|
|
@ -86,6 +87,8 @@ ok(col(rows[4], 'name') === 'Line one\nLine two', `a name with a line break read
|
|||
'commas, quotes and line breaks survive a real CSV parse')
|
||||
ok(col(rows[3], 'name') === '\'=HYPERLINK("x")', `a leading = reads back as ${JSON.stringify(col(rows[3], 'name'))}: a spreadsheet would run it`,
|
||||
'a leading = + - @ is neutralised')
|
||||
ok(col(rows[5], 'name') === "'\t=cmd", `a leading TAB reads back as ${JSON.stringify(col(rows[5], 'name'))}: OWASP lists it as a formula trigger`,
|
||||
'a leading TAB or CR is neutralised too (OWASP)')
|
||||
ok(col(rows[1], 'territories') === 'Mahārāshtra; Goa' && col(rows[1], 'color') === color && col(rows[1], 'slug') === 'agaria',
|
||||
`row 1 is ${JSON.stringify(rows[1])}`, 'each row carries its slug, the territories that contain it, and the colour')
|
||||
|
||||
|
|
|
|||
|
|
@ -13,14 +13,15 @@
|
|||
//
|
||||
// THE CSV: one row per people group, header first, CRLF line ends. The cells follow the library's rules
|
||||
// (useCsvExport's esc): quote a cell holding , " CR or LF and double its quotes; prefix a leading = + - @
|
||||
// with a single quote, so a spreadsheet never runs a name as a formula.
|
||||
// with a single quote, so a spreadsheet never runs a name as a formula. Also a leading TAB or CR (OWASP's
|
||||
// full list of formula triggers; the library's esc stops at = + - @).
|
||||
import { formatClipboard } from './territory-counts.js';
|
||||
|
||||
export const SELECTION_CSV_COLUMNS = ['slug', 'name', 'country_code', 'population', 'territories', 'color'];
|
||||
|
||||
export function csvCell(v) {
|
||||
let s = v === null || v === undefined ? '' : String(v);
|
||||
if (/^[=+\-@]/.test(s)) s = "'" + s;
|
||||
if (/^[=+\-@\t\r]/.test(s)) s = "'" + s;
|
||||
if (/[",\n\r]/.test(s)) s = '"' + s.replace(/"/g, '""') + '"';
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue