diff --git a/src/config.ts b/src/config.ts index 40cff0a..5d4781b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -17,7 +17,7 @@ export const set = (key: string, value: any) => { if (typeof value !== 'number') { throw new Error(`release must be a number but it's a "${typeof value}".`); } if ((value | 0) !== value) { throw new Error(`release must be an integer but it's ${value}.`); } if (value < 0) { throw new Error(`release must be a non-negative integer but it's ${value}.`); } - if (settings.from !== undefined && value <= settings.from ) { throw new Error(`release must be bigger than from but ${value} is not bigger than ${settings.from}.`); } + if (settings.from !== undefined && value <= settings.from ) { throw new Error(`release must be greater than from but ${value} is not greater than ${settings.from}.`); } settings.release = value; break; case 'from': @@ -25,7 +25,7 @@ export const set = (key: string, value: any) => { if (typeof value !== 'number') { throw new Error(`from must be a number but it's a "${typeof value}".`); } if ((value | 0) !== value) { throw new Error(`from must be an integer but it's ${value}.`); } if (value < -1) { throw new Error(`from must be a non-negative integer or -1, but it's ${value}.`); } - if (settings.release !== undefined && value >= settings.release ) { throw new Error(`from must be smaller than release but ${value} is not smaller than ${settings.release}.`); } + if (settings.release !== undefined && value >= settings.release ) { throw new Error(`from must be less than release but ${value} is not less than ${settings.release}.`); } settings.from = value; break; case 'outputType': diff --git a/src/ssn/getSolidpkg.ts b/src/ssn/getSolidpkg.ts index 78e1c09..5dafc1b 100644 --- a/src/ssn/getSolidpkg.ts +++ b/src/ssn/getSolidpkg.ts @@ -9,13 +9,13 @@ export default function getSolidpkg(product: Product, from: number, to: number): } if (typeof from !== 'number' || (from | 0) !== from || from < -1) { - throw new Error(`from must be an integer at least -1 but it is "${from}"`); + throw new Error(`from must be an integer greater than or equal to -1 but it is "${from}"`); } if (typeof to !== 'number' || (to | 0) !== to || to < 0) { - throw new Error(`to must be an integer at least 0 but it is "${to}"`); + throw new Error(`to must be an integer greater than or equal to 0 but it is "${to}"`); } if (from >= to) { - throw new Error(`from must be smaller than to but "${from}" is not smaller than "${to}".`); + throw new Error(`from must be less than to but "${from}" is not less than "${to}".`); } return getUrlContents({ host: 'cdn-patch.swtor.com', path: `/patch/${product}/${product}_${from}to${to}.solidpkg` }); diff --git a/src/ssn/readSolidpkg.ts b/src/ssn/readSolidpkg.ts index 2e1f525..789418e 100644 --- a/src/ssn/readSolidpkg.ts +++ b/src/ssn/readSolidpkg.ts @@ -1,3 +1,8 @@ +/** + * The file format used by Solid State Networks is based on the .zip format. + * Check the .ZIP File Format Specification . + */ + import { TextDecoder } from 'util'; import modifyPassword from './modifyPassword'; @@ -50,7 +55,7 @@ export default function readSolidpkg(buffer: Buffer) { throw new Error(`Central dir points before file start (0x${(pos - centralDirSize).toString(16)})`); } - //--------------- READ CENTRAL DIR --------------- + //--------------- READ CENTRAL DIRECTORY --------------- //Go to start of central dir pos -= 20 + centralDirSize; @@ -62,31 +67,41 @@ export default function readSolidpkg(buffer: Buffer) { } } - pos += 4; //skip version + pos += 4; //skip version made by and version needed to extract - /** The bitflag stores whether the file is encrypted or not. Most files are encrypted but there are - * some exceptions: assets_swtor_test_main_248to249.solidpkg, assets_swtor_test_en_us_270to271.solidpkg, and - * retailclient_publictest_246to247.solidpkg are not encrypted. + /** The general purpose bit flag stores whether the file is encrypted or not. + * Most files are encrypted but there are some exceptions: assets_swtor_test_main_248to249.solidpkg, + * assets_swtor_test_en_us_270to271.solidpkg, and retailclient_publictest_246to247.solidpkg are not encrypted. */ const bitFlag = dv.getUint16(pos, true); pos += 2; - /** Type of compression, 8 = DEFLATE. Files are always compressed. */ + /** Compression method, always set to 8 = DEFLATE. */ const compression = dv.getUint16(pos, true); pos += 2; if (compression !== COMPRESSION_DEFLATE) { throw new Error(`File is not using DEFLATE compression but "${compression}"`); } + /** last mod file time */ const lastMod1 = dv.getUint16(pos, true); pos += 2; + /** last mod file date */ const lastMod2 = dv.getUint16(pos, true); pos += 2; + /** crc-32 */ const fileCrc = dv.getUint32(pos, true); pos += 4; + /** compressed size */ const comprSize = dv.getUint32(pos, true); pos += 4; + /** uncompressed size */ const uncomprSize = dv.getUint32(pos, true); pos += 4; + /** file name length */ const fileNameLength = dv.getUint16(pos, true); pos += 2; + /** extra field length */ const extraFieldLength = dv.getUint16(pos, true); pos += 2; + /** file comment length */ const fileCommentLength = dv.getUint16(pos, true); pos += 2; - pos += 8; //skip disk num start and file attributes + pos += 8; //skip disk number start, internal file attributes and external file attributes + /** relative offset of local header */ const relOffset = dv.getUint32(pos, true); pos += 4; - const fileName = Decoder.decode(new DataView(arrayBuffer, pos, fileNameLength)); pos += fileNameLength; //skip file name + /** file name (variable size) */ + const fileName = Decoder.decode(new DataView(arrayBuffer, pos, fileNameLength)); pos += fileNameLength; if (fileName !== 'metafile.solid') { throw new Error(`Expected file name to be "metafile.solid" but it was "${fileName}".`); } @@ -100,7 +115,7 @@ export default function readSolidpkg(buffer: Buffer) { switch (fieldId) { case 0x8810: { //password if (fieldLength > 120) { - throw new Error(`Password is too long, it should be 120 characters at most but is ${fieldLength} characters long.`); + throw new Error(`Password is too long, it should be 120 characters at most but it is ${fieldLength} characters long.`); } const passwordLength = fieldLength; encodedPassword = new Uint8Array(arrayBuffer, pos, fieldLength);