From a578d216635b7c196de4ae54e9b10e7384c3952d Mon Sep 17 00:00:00 2001 From: C-3PO Date: Fri, 22 Jun 2018 17:17:12 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Improve=20Bencode=20parser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssn/bencodeParser.ts | 117 +++++++++++++++++++++------------------ src/ssn/getSolidpkg.ts | 4 +- 2 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/ssn/bencodeParser.ts b/src/ssn/bencodeParser.ts index c3f5189..0ea91cf 100644 --- a/src/ssn/bencodeParser.ts +++ b/src/ssn/bencodeParser.ts @@ -7,67 +7,74 @@ import { TextDecoder } from 'util'; 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. */ -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 obj; const header = dv.getUint8(pos); pos += 1; switch (header) { - case 0x64: { //'d' - dictionary (key-value object) - obj = []; - do { - //read key - const out1 = bpParse(dv, pos); - pos = out1.pos; - //read value - const out2 = bpParse(dv, pos); - pos = out2.pos; - obj[out1.obj] = out2.obj; - } while (dv.getUint8(pos) !== 0x65); //'e' - end - pos += 1; - break; + case 0x64: { //'d' - dictionary (key-value object) + obj = []; + do { + //read key + const out1 = bpParse(dv, pos); + pos = out1.pos; + //read value + const out2 = bpParse(dv, pos); + pos = out2.pos; + obj[out1.obj] = out2.obj; + } while (dv.getUint8(pos) !== 0x65); //'e' - end + pos += 1; + 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 = []; - 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; + 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 + 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 - 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; - } - 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.'); + //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 }; } + +export default function parseBencode(dv: DataView): any { + return bpParse(dv).obj; +} diff --git a/src/ssn/getSolidpkg.ts b/src/ssn/getSolidpkg.ts index 3604ba8..7bf080d 100644 --- a/src/ssn/getSolidpkg.ts +++ b/src/ssn/getSolidpkg.ts @@ -2,7 +2,7 @@ import getUrlContents from '../getUrlContents'; import { Product } from '../interfaces/ISettings'; import ISolid from '../interfaces/ISolidFile'; import verifyProductName from '../ssn/verifyProductName'; -import bpParse from './bencodeParser'; +import parseBencode from './bencodeParser'; import extractFile from './extractFile'; import readSsnFile from './readSsnFile'; import verifySolidpkg from './verifySolidpkg'; @@ -39,7 +39,7 @@ export default async function getSolidpkg(product: Product, from: number, to: nu //Extract metafile.solid file 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 verifySolidpkg(solidContents, { product, from, to });