Skip to content

Commit

Permalink
🐞sanitize file path for export
Browse files Browse the repository at this point in the history
  • Loading branch information
yannick-beot-sp committed Feb 28, 2024
1 parent 954c01c commit 83fa257
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 8 deletions.
9 changes: 5 additions & 4 deletions src/services/PathProposer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as os from 'os';
import * as configuration from '../configurationConstants';
import { getConfigKey, getWorkspaceFolder } from '../utils/configurationUtils';
import { sanitizePath } from '../utils';

interface ContextValues {
/**
Expand Down Expand Up @@ -102,16 +103,16 @@ export class PathProposer {
objectType: string,
objectName: string,
): string {
let path = getConfigKey(key);
path = this.replaceVariables(path, {
let result = getConfigKey(key);
result = this.replaceVariables(result, {
t: tenantName,
// eslint-disable-next-line @typescript-eslint/naming-convention
T: tenantDisplayName,
o: objectType,
// eslint-disable-next-line @typescript-eslint/naming-convention
S: objectName
});
return path as string;
return sanitizePath(result);
}

private static getTenantBasedReportFilename(
Expand Down Expand Up @@ -214,7 +215,7 @@ export class PathProposer {
tenantName,
tenantDisplayName);
}

public static getRoleReportFilename(
tenantName: string,
tenantDisplayName: string
Expand Down
63 changes: 59 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require('node:path');

export function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Expand All @@ -14,7 +16,7 @@ export function str2Uint8Array(str: string): Uint8Array {
}

export function toTimestamp(strDate: string): number {
var datum = Date.parse(strDate);
const datum = Date.parse(strDate);
return datum / 1000;
}

Expand All @@ -23,7 +25,7 @@ export function toTimestamp(strDate: string): number {
* It is modified from the ISO8601 string to remove ':' and second
*/
export function toDateSuffix(): string {
var date = new Date();
const date = new Date();
let str = date.toISOString(); //"2011-12-19T15:28:46.493Z"
str = str.replaceAll(':', '-').replace(/\..*$/, '');
return str;
Expand All @@ -44,7 +46,7 @@ export const compareByName = (a: any, b: any) => (a.name.toLowerCase() > b.name.
/**
* Function used to compare 2 objects by the property 'priority'. Useful for sorting identity profiles
*/
export const compareByPriority = (a: any, b: any) => (a.priority > b.priority) ? 1 : -1;
export const compareByPriority = (a: any, b: any) => (a.priority > b.priority) ? 1 : -1;


/**
Expand All @@ -61,4 +63,57 @@ export function normalizeTenant(tenantName: string) {
// cf. https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library
export function parseJwt(token: string): any {
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
}
}


// cf. https://github.com/parshap/node-sanitize-filename/blob/master/index.js

const illegalRe = /[\/\\\?<>:\*\|":]/g;
const controlRe = /[\x00-\x1f\x80-\x9f]/g;
const reservedRe = /^\.+$/;
const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;

function sanitizeImpl(input: any, replacement: string, maxLength: number) {
if (typeof input !== 'string') {
throw new Error('Input must be string')
}
const sanitized = input
.replace(illegalRe, replacement)
.replace(controlRe, replacement)
.replace(reservedRe, replacement)
.replace(windowsReservedRe, replacement);

if (maxLength > 0) {
return truncate(sanitized, maxLength);
}
return sanitized
}

// cf. https://gist.github.com/barbietunnie/7bc6d48a424446c44ff4
function truncate(sanitized: string, length: number): string {
const uint8Array = new TextEncoder().encode(sanitized)
const truncated = uint8Array.slice(0, length)
return new TextDecoder().decode(truncated)
}

/**
*
* @param input Can be a path. For instance: WORKFLOW/Template: my super workflow.json
* @param options optional parameters for invalid character remplacement ('' by default) and max length (255 by default)
* @returns sanitized path
*/
export function sanitizePath(input: string, options: undefined | { replacement?: string, maxLength?: number } = undefined) {
const replacement: string = (options && options.replacement) || '';
let maxLength: number = (options && options.maxLength) || 255;

const parts = path.parse(input);
maxLength = maxLength - (parts.ext ?? '').length
parts.name = sanitizeImpl(parts.name, replacement, maxLength)
if (replacement !== '') {
parts.name = sanitizeImpl(parts.name, '', maxLength);
}
// Need to remove base otherwise it takes precedence
parts.base = undefined;
const output = path.format(parts);
return output
};

0 comments on commit 83fa257

Please sign in to comment.