Skip to content

Commit

Permalink
- feat: inputMd5 validation in embeded patch object
Browse files Browse the repository at this point in the history
- fix (patch-builder): do not load webworker if Patch Builder JS is not initialized
  • Loading branch information
marcrobledo committed Aug 31, 2024
1 parent a428479 commit 9da53f0
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 60 deletions.
2 changes: 1 addition & 1 deletion _cache_service_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

var PRECACHE_ID = 'rom-patcher-js';
var PRECACHE_VERSION = 'v30rc4';
var PRECACHE_VERSION = 'v30rc4b';
var PRECACHE_URLS = [
'/RomPatcher.js/', '/RomPatcher.js/index.html',
'/RomPatcher.js/manifest.json',
Expand Down
179 changes: 120 additions & 59 deletions rom-patcher-js/RomPatcher.webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

const ROM_PATCHER_JS_PATH = './rom-patcher-js/';

var RomPatcherWeb = (function () {
const RomPatcherWeb = (function () {
const SCRIPT_DEPENDENCIES = [
'modules/BinFile.js',
'modules/HashCalculator.js',
Expand Down Expand Up @@ -103,25 +103,54 @@ var RomPatcherWeb = (function () {
parsedPatch.outputExtension = embededPatchInfo.outputExtension;
}

if (typeof embededPatchInfo.inputMd5 !== 'undefined') {
if (!Array.isArray(embededPatchInfo.inputMd5))
embededPatchInfo.inputMd5 = [embededPatchInfo.inputMd5];

const validMd5s = embededPatchInfo.inputMd5.reduce(function (acc, md5) {
if (typeof md5 === 'string' && /^(0x)?[0-9a-fA-F]{32}$/i.test(md5.trim())) {
acc.push(md5.trim().toLowerCase());
} else {
console.warn('Rom Patcher JS: inputMd5 must be a string (32 characters long, characters allowed: 0-9, a-f)');
}
return acc;
}, []);

if (validMd5s.length) {
parsedPatch.inputValidation = {
'type': 'MD5',
'value': validMd5s
};
} else {
console.warn('Rom Patcher JS: invalid inputMd5 for embeded patch', embededPatchInfo.inputMd5);
}
}
if (typeof embededPatchInfo.inputCrc32 !== 'undefined') {
if (!Array.isArray(embededPatchInfo.inputCrc32))
embededPatchInfo.inputCrc32 = [embededPatchInfo.inputCrc32];

const validCrcs = embededPatchInfo.inputCrc32.map(function (crc32) {
if (typeof crc32 === 'string' && /^(0x)?[0-9a-fA-F]{8}$/i.test(crc32.trim())) {
return parseInt(crc32.replace('0x', ''), 16);
} else if (typeof crc32 === 'number') {
return crc32 >>> 0;
if (!parsedPatch.inputValidation) {
if (!Array.isArray(embededPatchInfo.inputCrc32))
embededPatchInfo.inputCrc32 = [embededPatchInfo.inputCrc32];

const validCrcs = embededPatchInfo.inputCrc32.reduce(function (acc, crc32) {
if (typeof crc32 === 'string' && /^(0x)?[0-9a-fA-F]{8}$/i.test(crc32.trim())) {
acc.push(parseInt(crc32.trim().replace('0x', ''), 16));
} else if (typeof crc32 === 'number') {
acc.push((crc32 >>> 0) & 0xffffffff);
} else {
console.warn('Rom Patcher JS: invalid inputCrc32 value');
}
return acc;
}, []);

if (validCrcs.length) {
parsedPatch.inputValidation = {
'type': 'CRC32',
'value': validCrcs
};
} else {
return null;
console.warn('Rom Patcher JS: invalid inputCrc32 for embeded patch', embededPatchInfo.inputCrc32);
}
}).filter(function (crc32) {
return typeof crc32 === 'number';
});
if (validCrcs.length) {
parsedPatch.inputCrc32 = validCrcs;
} else {
console.warn('Invalid inputCrc32 for embeded patch', embededPatchInfo);
console.warn('Rom Patcher JS: a valid inputMd5 was provided, inputCrc32 will be ignored', embededPatchInfo);
}
}

Expand Down Expand Up @@ -521,6 +550,9 @@ var RomPatcherWeb = (function () {
const _initialize = function (newSettings, embededPatchInfo) {
/* embeded patches */
var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo);
if (newSettings && typeof newSettings.file === 'string') {
console.warn('Rom Patcher JS: embeded patch info was provided in settings and will be ignored, must be passed as second parameter');
}



Expand Down Expand Up @@ -737,39 +769,48 @@ var RomPatcherWeb = (function () {
if (ZIPManager.isZipFile(binFile)) {
ZIPManager.unzipPatches(binFile._u8array.buffer);
} else {
try{
try {
const parsedPatch = RomPatcher.parsePatchFile(binFile);
if (parsedPatch) {
patch = parsedPatch;
_setPatchInputSpinner(false);

const embededPatchInfo = _getEmbededPatchInfo(binFile.fileName);
if (embededPatchInfo) {
/* custom crc32s validation */
if (embededPatchInfo.inputCrc32) {
patch.validateSource = function (romFile, headerSize) {
for (var i = 0; i < embededPatchInfo.inputCrc32.length; i++) {
if (embededPatchInfo.inputCrc32[i] === romFile.hashCRC32(headerSize))
return true;
/* custom input validation */
if (embededPatchInfo.inputValidation) {
if (embededPatchInfo.inputValidation.type === 'CRC32') {
patch.validateSource = function (romFile, headerSize) {
for (var i = 0; i < embededPatchInfo.inputValidation.value.length; i++) {
if (embededPatchInfo.inputValidation.value[i] === romFile.hashCRC32(headerSize))
return true;
}
return false;
}
} else if (embededPatchInfo.inputValidation.type === 'MD5') {
patch.validateSource = function (romFile, headerSize) {
for (var i = 0; i < embededPatchInfo.inputValidation.value.length; i++) {
if (embededPatchInfo.inputValidation.value[i] === romFile.hashMD5(headerSize))
return true;
}
return false;
}
return false;
} else {
throw new Error('Rom Patcher JS: Invalid inputValidation type');
}
patch.getValidationInfo = function () {
return {
'type': 'CRC32',
'value': embededPatchInfo.inputCrc32
}
return embededPatchInfo.inputValidation
};
}

/* custom description */
if (embededPatchInfo.description) {
patch.getDescription = function () {
return embededPatchInfo.description;
}
}
}

/* toggle ROM requirements */
if (htmlElements.get('row-patch-requirements') && htmlElements.get('patch-requirements-value')) {
if (typeof patch.getValidationInfo === 'function' && patch.getValidationInfo()) {
Expand All @@ -781,12 +822,12 @@ var RomPatcherWeb = (function () {
}
}
htmlElements.setText('patch-requirements-value', '');

htmlElements.setText('patch-requirements-type', validationInfo.type === 'ROM' ? _('Required ROM:') : _('Required %s:').replace('%s', validationInfo.type));

if (!Array.isArray(validationInfo.value))
validationInfo.value = [validationInfo.value];

validationInfo.value.forEach(function (value) {
var line = document.createElement('div');
if (typeof value !== 'string') {
Expand Down Expand Up @@ -815,7 +856,7 @@ var RomPatcherWeb = (function () {
htmlElements.removeClass('row-patch-requirements', 'show');
}
}

/* toggle patch description */
if (typeof patch.getDescription === 'function' && patch.getDescription()) {
htmlElements.setText('patch-description', patch.getDescription()/* .replace(/\n/g, '<br/>') */);
Expand All @@ -826,20 +867,20 @@ var RomPatcherWeb = (function () {
//htmlElements.setTitle('patch-description', '');
htmlElements.removeClass('row-patch-description', 'show');
}

RomPatcherWeb.validateCurrentRom(_getChecksumStartOffset());

if (typeof settings.onloadpatch === 'function') {
settings.onloadpatch(binFile, embededPatchInfo, parsedPatch);
}

if (transferFakeFile) {
htmlElements.setFakeFile('patch', binFile.fileName);
}
} else {
_setToastError(_('Invalid patch file'));
}
}catch(ex){
} catch (ex) {
_setToastError(ex.message);
}
}
Expand Down Expand Up @@ -1489,26 +1530,7 @@ const PatchBuilderWeb = (function (romPatcherWeb) {
}
};

const webWorkerCreate = new Worker(ROM_PATCHER_JS_PATH + 'RomPatcher.webworker.create.js');
webWorkerCreate.onmessage = event => { // listen for events from the worker
//retrieve arraybuffers back from webworker
originalRom._u8array = event.data.originalRomU8Array;
modifiedRom._u8array = event.data.modifiedRomU8Array;

_setElementsStatus(true);
_setCreateButtonSpinner(false);

const patchFile = new BinFile(event.data.patchFileU8Array.buffer);
patchFile.fileName = modifiedRom.getName() + '.' + document.getElementById('patch-builder-select-patch-type').value;
patchFile.save();

_setToastError();
};
webWorkerCreate.onerror = event => { // listen for events from the worker
_setElementsStatus(true);
_setCreateButtonSpinner(false);
_setToastError('webWorkerCreate error: ' + event.message);
};
var webWorkerCreate;

var initialized = false;
return {
Expand All @@ -1522,6 +1544,45 @@ const PatchBuilderWeb = (function (romPatcherWeb) {
else if (!romPatcherWeb.isInitialized())
throw new Error('Rom Patcher JS must be initialized before Patch Builder JS');


if (!document.getElementById('patch-builder-button-create') || document.getElementById('patch-builder-button-create').tagName !== 'BUTTON') {
console.error('Patch Builder JS: button#patch-builder-button-create not found');
throw new Error('Patch Builder JS: button#patch-builder-button-create not found');
}
if (!document.getElementById('patch-builder-select-patch-type') || document.getElementById('patch-builder-select-patch-type').tagName !== 'SELECT') {
console.error('Patch Builder JS: select#patch-builder-select-patch-type not found');
throw new Error('Patch Builder JS: select#patch-builder-select-patch-type not found');
}
if (!document.getElementById('patch-builder-input-file-original') || document.getElementById('patch-builder-input-file-original').tagName !== 'INPUT' || document.getElementById('patch-builder-input-file-original').type !== 'file') {
console.error('Patch Builder JS: input[type=file]#patch-builder-input-file-original not found');
throw new Error('Patch Builder JS: input[type=file]#patch-builder-input-file-original not found');
}
if (!document.getElementById('patch-builder-input-file-modified') || document.getElementById('patch-builder-input-file-modified').tagName !== 'INPUT' || document.getElementById('patch-builder-input-file-modified').type !== 'file') {
console.error('Patch Builder JS: input[type=file]#patch-builder-input-file-modified not found');
throw new Error('Patch Builder JS: input[type=file]#patch-builder-input-file-modified not found');
}

webWorkerCreate = new Worker(ROM_PATCHER_JS_PATH + 'RomPatcher.webworker.create.js');
webWorkerCreate.onmessage = event => { // listen for events from the worker
//retrieve arraybuffers back from webworker
originalRom._u8array = event.data.originalRomU8Array;
modifiedRom._u8array = event.data.modifiedRomU8Array;

_setElementsStatus(true);
_setCreateButtonSpinner(false);

const patchFile = new BinFile(event.data.patchFileU8Array.buffer);
patchFile.fileName = modifiedRom.getName() + '.' + document.getElementById('patch-builder-select-patch-type').value;
patchFile.save();

_setToastError();
};
webWorkerCreate.onerror = event => { // listen for events from the worker
_setElementsStatus(true);
_setCreateButtonSpinner(false);
_setToastError('webWorkerCreate error: ' + event.message);
};

document.getElementById('patch-builder-button-create').disabled = true;

document.getElementById('patch-builder-input-file-original').addEventListener('change', function () {
Expand Down

0 comments on commit 9da53f0

Please sign in to comment.