fix: prevent JsonResourceStorage from generating too long filenames

This commit is contained in:
Wannes Kerckhove
2022-05-10 14:07:55 +02:00
committed by Joachim Van Herwegen
parent 16cff45110
commit 13dbcb662b
2 changed files with 41 additions and 5 deletions

View File

@@ -1,13 +1,19 @@
import { createHash } from 'crypto';
import { parse } from 'path';
import { BasicRepresentation } from '../../http/representation/BasicRepresentation';
import type { Representation } from '../../http/representation/Representation';
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
import { NotFoundHttpError } from '../../util/errors/NotFoundHttpError';
import { ensureLeadingSlash, ensureTrailingSlash, isContainerIdentifier, joinUrl } from '../../util/PathUtil';
import { ensureLeadingSlash, ensureTrailingSlash, isContainerIdentifier, joinUrl,
joinFilePath } from '../../util/PathUtil';
import { readableToString } from '../../util/StreamUtil';
import { LDP } from '../../util/Vocabularies';
import type { ResourceStore } from '../ResourceStore';
import type { KeyValueStorage } from './KeyValueStorage';
// Maximum allowed length for the keys, longer keys will be hashed.
const KEY_LENGTH_LIMIT = 255;
/**
* A {@link KeyValueStorage} for JSON-like objects using a {@link ResourceStore} as backend.
*
@@ -114,6 +120,15 @@ export class JsonResourceStorage<T> implements KeyValueStorage<string, T> {
* Converts a key into an identifier for internal storage.
*/
private keyToIdentifier(key: string): ResourceIdentifier {
// Parse the key as a file path
const parsedPath = parse(key);
// Hash long filenames to prevent issues with the underlying storage.
// E.g. a UNIX a file name cannot exceed 255 bytes.
// This is a temporary fix for https://github.com/CommunitySolidServer/CommunitySolidServer/issues/1013,
// until we have a solution for data migration.
if (parsedPath.base.length > KEY_LENGTH_LIMIT) {
key = joinFilePath(parsedPath.dir, this.applyHash(parsedPath.base));
}
return { path: joinUrl(this.container, key) };
}
@@ -127,4 +142,8 @@ export class JsonResourceStorage<T> implements KeyValueStorage<string, T> {
// on the `entries` results matching a key that was sent before.
return ensureLeadingSlash(identifier.path.slice(this.container.length));
}
private applyHash(key: string): string {
return createHash('sha256').update(key).digest('hex');
}
}