🎨 Improve Bencode parser
This commit is contained in:
parent
a221ee3a6b
commit
a578d21663
2 changed files with 64 additions and 57 deletions
|
@ -7,67 +7,74 @@ import { TextDecoder } from 'util';
|
||||||
const Decoder = new TextDecoder('utf-8');
|
const Decoder = new TextDecoder('utf-8');
|
||||||
|
|
||||||
/** Takes a Bencoded-encoded file, parses it at the given starting position and returns a JSON object, or rejects on error. */
|
/** Takes a Bencoded-encoded file, parses it at the given starting position and returns a JSON object, or rejects on error. */
|
||||||
export default function bpParse(dv: DataView, posIn: number = 0): { obj: any, pos: number } {
|
function bpParse(dv: DataView, posIn: number = 0): { obj: any, pos: number } {
|
||||||
let pos = posIn;
|
let pos = posIn;
|
||||||
let obj;
|
let obj;
|
||||||
const header = dv.getUint8(pos); pos += 1;
|
const header = dv.getUint8(pos); pos += 1;
|
||||||
switch (header) {
|
switch (header) {
|
||||||
case 0x64: { //'d' - dictionary (key-value object)
|
case 0x64: { //'d' - dictionary (key-value object)
|
||||||
obj = [];
|
obj = [];
|
||||||
do {
|
do {
|
||||||
//read key
|
//read key
|
||||||
const out1 = bpParse(dv, pos);
|
const out1 = bpParse(dv, pos);
|
||||||
pos = out1.pos;
|
pos = out1.pos;
|
||||||
//read value
|
//read value
|
||||||
const out2 = bpParse(dv, pos);
|
const out2 = bpParse(dv, pos);
|
||||||
pos = out2.pos;
|
pos = out2.pos;
|
||||||
obj[out1.obj] = out2.obj;
|
obj[out1.obj] = out2.obj;
|
||||||
} while (dv.getUint8(pos) !== 0x65); //'e' - end
|
} while (dv.getUint8(pos) !== 0x65); //'e' - end
|
||||||
pos += 1;
|
pos += 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case 0x6C: { //'l' - list (array)
|
||||||
|
obj = [];
|
||||||
|
do {
|
||||||
|
//read entry
|
||||||
|
const out = bpParse(dv, pos);
|
||||||
|
pos = out.pos;
|
||||||
|
obj.push(out.obj);
|
||||||
|
} while (dv.getUint8(pos) !== 0x65); //'e' - end
|
||||||
|
pos += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x69: { //'i' - integer
|
||||||
|
let curChar = dv.getUint8(pos); pos += 1;
|
||||||
|
let curNumber = 0;
|
||||||
|
while (curChar !== 0x65) { //'e' - end
|
||||||
|
if (curChar < 0x30 || curChar > 0x39) {
|
||||||
|
throw new Error('Unexpected int char during bencode parsing');
|
||||||
|
}
|
||||||
|
curNumber *= 10;
|
||||||
|
curNumber += curChar - 0x30;
|
||||||
|
curChar = dv.getUint8(pos); pos += 1;
|
||||||
}
|
}
|
||||||
case 0x6C: { //'l' - list (array)
|
obj = curNumber;
|
||||||
obj = [];
|
break;
|
||||||
do {
|
}
|
||||||
//read entry
|
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||||
const out = bpParse(dv, pos);
|
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: { //string prefixed by length
|
||||||
pos = out.pos;
|
//read string length
|
||||||
obj.push(out.obj);
|
let curChar: number = header;
|
||||||
} while (dv.getUint8(pos) !== 0x65); //'e' - end
|
let strLen = 0;
|
||||||
pos += 1;
|
while (curChar !== 0x3A) { //':' - integer delimiter, beginning of string
|
||||||
break;
|
if (curChar < 0x30 || curChar > 0x39) {
|
||||||
|
throw new Error('Unexpected string length during bencode parsing');
|
||||||
|
}
|
||||||
|
strLen *= 10;
|
||||||
|
strLen += curChar - 0x30;
|
||||||
|
curChar = dv.getUint8(pos); pos += 1;
|
||||||
}
|
}
|
||||||
case 0x69: { //'i' - integer
|
//read string
|
||||||
let curChar = dv.getUint8(pos); pos += 1;
|
obj = Decoder.decode(new DataView(dv.buffer, pos, strLen));
|
||||||
let curNumber = 0;
|
pos += strLen;
|
||||||
while (curChar !== 0x65) { //'e' - end
|
break;
|
||||||
if (curChar < 0x30 || curChar > 0x39) {
|
}
|
||||||
throw new Error('Unexpected int char during bencode parsing');
|
default:
|
||||||
}
|
throw new Error('Unexpected leading char during bencode parsing.');
|
||||||
curNumber *= 10;
|
|
||||||
curNumber += curChar - 0x30;
|
|
||||||
curChar = dv.getUint8(pos); pos += 1;
|
|
||||||
}
|
|
||||||
obj = curNumber;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
|
||||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: { //string prefixed by length
|
|
||||||
//read string length
|
|
||||||
let curChar: number = header;
|
|
||||||
let strLen = 0;
|
|
||||||
while (curChar !== 0x3A) { //':' - integer delimiter, beginning of string
|
|
||||||
strLen *= 10;
|
|
||||||
strLen += curChar - 0x30;
|
|
||||||
curChar = dv.getUint8(pos); pos += 1;
|
|
||||||
}
|
|
||||||
//read string
|
|
||||||
obj = Decoder.decode(new DataView(dv.buffer, pos, strLen));
|
|
||||||
pos += strLen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new Error('Unexpected leading char during bencode parsing.');
|
|
||||||
}
|
}
|
||||||
return { obj, pos };
|
return { obj, pos };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default function parseBencode(dv: DataView): any {
|
||||||
|
return bpParse(dv).obj;
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import getUrlContents from '../getUrlContents';
|
||||||
import { Product } from '../interfaces/ISettings';
|
import { Product } from '../interfaces/ISettings';
|
||||||
import ISolid from '../interfaces/ISolidFile';
|
import ISolid from '../interfaces/ISolidFile';
|
||||||
import verifyProductName from '../ssn/verifyProductName';
|
import verifyProductName from '../ssn/verifyProductName';
|
||||||
import bpParse from './bencodeParser';
|
import parseBencode from './bencodeParser';
|
||||||
import extractFile from './extractFile';
|
import extractFile from './extractFile';
|
||||||
import readSsnFile from './readSsnFile';
|
import readSsnFile from './readSsnFile';
|
||||||
import verifySolidpkg from './verifySolidpkg';
|
import verifySolidpkg from './verifySolidpkg';
|
||||||
|
@ -39,7 +39,7 @@ export default async function getSolidpkg(product: Product, from: number, to: nu
|
||||||
|
|
||||||
//Extract metafile.solid file
|
//Extract metafile.solid file
|
||||||
const solidFile = await extractFile(firstFile, [new DataView(ssnFile)]);
|
const solidFile = await extractFile(firstFile, [new DataView(ssnFile)]);
|
||||||
const solidContents = bpParse(new DataView(solidFile)).obj as ISolid;
|
const solidContents = parseBencode(new DataView(solidFile)) as ISolid;
|
||||||
|
|
||||||
//Verify metafile.solid for correctness
|
//Verify metafile.solid for correctness
|
||||||
verifySolidpkg(solidContents, { product, from, to });
|
verifySolidpkg(solidContents, { product, from, to });
|
||||||
|
|
Loading…
Reference in a new issue