New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@isomp4/parser

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@isomp4/parser - npm Package Compare versions

Comparing version
0.1.2
to
0.1.3
+4
-6
package.json
{
"name": "@isomp4/parser",
"version": "0.1.2",
"version": "0.1.3",
"description": "",

@@ -39,13 +39,11 @@ "keywords": [

"cjs/**/*.js",
"cjs/**/*.js.map",
"cjs/**/package.json",
"dist/**/*.js",
"dist/**/*.js.map",
"dist/**/*.d.ts"
],
"dependencies": {
"@isomp4/core": "^0.1.2"
"@isomp4/core": "^0.1.3"
},
"devDependencies": {
"@isomp4/box-moov": "^0.1.2"
"@isomp4/box-moov": "^0.1.3"
},

@@ -59,3 +57,3 @@ "scripts": {

},
"gitHead": "0e1228d97be1b70c4e186be3aa2030e9dbb25430"
"gitHead": "e9a1443618ef08f11ca714fbccde5ad434d5e2ae"
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MP4Parser = exports.AbstractMP4Parser = void 0;
const buffer_1 = require("buffer");
const core_1 = require("@isomp4/core");
const EMPTY_BUFFER = buffer_1.Buffer.allocUnsafe(0);
/**
* Parses the ISO BMFF box structure of an MP4 stream.
*/
class AbstractMP4Parser {
/**
* Creates a new parser for an MP4 stream.
*/
constructor() {
this.boxes = new Map();
this.boxStack = [];
this.buffer = EMPTY_BUFFER;
this.bytesNeeded = 0;
this.currentBox = null;
}
/**
*
* @param encodings
*/
registerBox(...encodings) {
for (const encoding of encodings) {
if (this.boxes.has(encoding.type)) {
throw new Error("Box type is already registered: " + encoding.type);
}
this.boxes.set(encoding.type, encoding);
}
}
/**
*
* @param boxType
*/
isBoxRegistered(boxType) {
return this.boxes.has(boxType);
}
/**
* Appends new data to the stream.
* @param data The new data to append. This data does NOT need to be a complete segment (or even a fragment).
*/
append(data) {
let input = buffer_1.Buffer.from(data.buffer, data.byteOffset, data.byteLength);
while (input.length > 0) {
if (this.bytesNeeded > 0) {
// Ensure that buffer is the correct size
this.ensureBuffer(this.bytesNeeded);
// Don't copy more data into the temp buffer than is needed for the next part!
const needed = this.bytesNeeded - this.buffer.byteOffset;
if (needed > 0) {
if (needed <= input.length) {
// Only copy 'needed' number of bytes into the temp buffer
input.copy(this.buffer, 0, 0, needed);
input = input.slice(needed);
}
else {
// All input can be copied into temp buffer
this.buffer = this.buffer.slice(input.copy(this.buffer));
// More input data is needed
return;
}
}
// Temp buffer now contains all bytes needed
// Flip buffer
const bytesNeeded = this.bytesNeeded;
const buf = buffer_1.Buffer.from(this.buffer.buffer, 0, bytesNeeded);
this.bytesNeeded = 0; // This must be reset before calling processBuffer()
const bytesConsumed = this.processBuffer(buf);
if (this.bytesNeeded > 0) {
// More bytes are needed
continue;
}
if (bytesConsumed !== bytesNeeded) {
throw new Error(`bytes consumed(${bytesConsumed}) != bytes needed(${bytesNeeded})`);
}
// Reset buffer
this.buffer = buffer_1.Buffer.from(this.buffer.buffer);
}
else {
// Avoid copying data by using the input buffer directly
const consumed = this.processBuffer(input);
if (consumed > 0) {
input = input.slice(consumed);
}
}
}
}
ensureBuffer(capacity) {
if (this.buffer.buffer.byteLength < capacity) {
const newBuffer = buffer_1.Buffer.alloc(capacity);
// If the byteOffset is zero, then this indicates that there is no data written to the buffer
if (this.buffer.byteOffset > 0) {
// Must copy old buffer to new buffer
buffer_1.Buffer.from(this.buffer.buffer).copy(newBuffer);
}
this.buffer = newBuffer;
}
}
/**
* Processes the given buffer.
* @param buffer The input buffer.
* @return The number of bytes consumed.
*/
processBuffer(buffer) {
stackCheck: if (this.boxStack.length > 0) {
const top = this.boxStack[this.boxStack.length - 1];
const header = top.header;
const needed = header.size - top.offset;
if (needed > 0) {
if (top.children) {
// Skip and parse children normally
break stackCheck;
}
const available = buffer.length;
if (needed > available) {
// Don't have enough data
this.onBoxData(header, buffer);
top.offset += available;
return available;
}
// Have enough data
this.onBoxData(header, buffer.slice(0, needed));
}
// End box
if (top.box != null) {
this.onBoxEnded(header, top.box);
}
else {
this.onBoxEnded(header);
}
// Pop box state
this.boxStack.pop();
// Check next box state
if (this.boxStack.length > 0) {
const next = this.boxStack[this.boxStack.length - 1];
next.offset += header.size;
if (top.box != null && next.box != null && core_1.BoxContainer.isInstance(next.box)) {
core_1.BoxContainer.add(next.box, top.box);
}
}
// Trigger parsing of next box
this.currentBox = null;
return needed;
}
if (this.currentBox == null) {
const header = core_1.BoxHeader.parse(buffer);
if (typeof header === "number") {
this.bytesNeeded = header;
return 0;
}
const headerLength = core_1.BoxHeader.decodedBytes;
// Invoke box started event
const content = this.onBoxStarted(header, buffer.slice(0, headerLength));
// Start box
this.currentBox = {
header,
headerLength,
content,
};
return headerLength;
}
const header = this.currentBox.header;
if (this.currentBox.content) {
const encoding = this.boxes.get(header.type);
if (encoding != null) {
const box = encoding.decode(buffer, header);
if (typeof box === "number") {
this.bytesNeeded = box;
return 0;
}
const consumed = encoding.decodedBytes;
// Invoke box decoded event
const children = this.onBoxDecoded(box, buffer.slice(0, consumed));
// Push box onto stack (and record whether to parse children)
this.boxStack.push({
header,
box,
children,
offset: this.currentBox.headerLength + consumed,
});
// Trigger parsing of child boxes
if (children) {
box.children = {};
this.currentBox = null;
}
return consumed;
}
// No encoding, so reset content boolean
this.currentBox.content = false;
}
// No encoding for box type, must skip entire box and children
this.boxStack.push({
header,
box: null,
children: false,
offset: this.currentBox.headerLength,
});
return this.processBuffer(buffer);
}
}
exports.AbstractMP4Parser = AbstractMP4Parser;
/**
* An implementation of {@link AbstractMP4Parser} that delegates to optional function properties.
*/
class MP4Parser extends AbstractMP4Parser {
/**
* Create a new MP4Parser.
*/
constructor() {
super();
}
onBoxStarted(header, headerData) {
return this.boxStarted ? this.boxStarted(header, headerData) : true;
}
onBoxDecoded(box, boxData) {
return this.boxDecoded ? this.boxDecoded(box, boxData) : true;
}
onBoxData(header, boxData) {
this.boxData?.(header, boxData);
}
onBoxEnded(header, box) {
this.boxEnded?.(header, box);
}
}
exports.MP4Parser = MP4Parser;
//# sourceMappingURL=parser.js.map
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
import { Buffer } from "buffer";
import type { Box, BoxEncoding, FourCC } from "@isomp4/core";
import { BoxHeader } from "@isomp4/core";
/**
* Parses the ISO BMFF box structure of an MP4 stream.
*/
export declare abstract class AbstractMP4Parser {
/**
* Registered box encodings.
*/
private readonly boxes;
/**
* A stack that keeps track of the current state in the MP4 box structure traversal.
*/
private readonly boxStack;
/**
* A temporary buffer to store appended data before it's parsed.
* This buffer may be resized if a box requires more space before it can be fully parsed.
*/
private buffer;
/**
* The number of bytes needed in the buffer to parse the next part.
*/
private bytesNeeded;
/**
* The current box state.
* If this is <code>null</code>, then a box header will be parsed next.
*/
private currentBox;
/**
* Creates a new parser for an MP4 stream.
*/
protected constructor();
/**
*
* @param encodings
*/
registerBox(...encodings: BoxEncoding[]): void;
/**
*
* @param boxType
*/
isBoxRegistered(boxType: FourCC): boolean;
/**
* Appends new data to the stream.
* @param data The new data to append. This data does NOT need to be a complete segment (or even a fragment).
*/
append(data: ArrayBufferView): void;
private ensureBuffer;
/**
* Processes the given buffer.
* @param buffer The input buffer.
* @return The number of bytes consumed.
*/
private processBuffer;
/**
* Invoked when a new box starts from the source.
* @param header The parsed header data of the box.
* @param headerData The raw header data of the box.
* @return Whether to decode the box content (fields).
*/
protected abstract onBoxStarted(header: BoxHeader, headerData: Buffer): boolean;
/**
* Invoked when the box content is parsed.
* This will be invoked if {@link onBoxStarted} returns <code>true</code> for a box
* and there is a registered box encoding for the box type,
* otherwise {@link onBoxData} will be invoked with the remaining box data.
* @param box The box that was parsed.
* @param boxData The raw content data of the box (excluding header and children).
* @return Whether to decode the children boxes.
*/
protected abstract onBoxDecoded(box: Box, boxData: Buffer): boolean;
/**
* Invoked when new data is received for the current box.
* This will be invoked if either {@link onBoxStarted} or {@link onBoxDecoded} return <code>false</code> for a box.
* @param header The box that the data is for.
* @param boxData The raw data of the box (excluding header).
*/
protected abstract onBoxData(header: BoxHeader, boxData: Buffer): void;
/**
* Invoked when a box ends.
* @param header The header of the box that ended.
* @param box The box that ended, if it was parsed.
*/
protected abstract onBoxEnded(header: BoxHeader, box?: Box): void;
}
/**
* An implementation of {@link AbstractMP4Parser} that delegates to optional function properties.
*/
export declare class MP4Parser extends AbstractMP4Parser {
boxStarted?: typeof MP4Parser.prototype.onBoxStarted;
boxDecoded?: typeof MP4Parser.prototype.onBoxDecoded;
boxData?: typeof MP4Parser.prototype.onBoxData;
boxEnded?: typeof MP4Parser.prototype.onBoxEnded;
/**
* Create a new MP4Parser.
*/
constructor();
protected onBoxStarted(header: BoxHeader, headerData: Buffer): boolean;
protected onBoxDecoded(box: Box, boxData: Buffer): boolean;
protected onBoxData(header: BoxHeader, boxData: Buffer): void;
protected onBoxEnded(header: BoxHeader, box?: Box): void;
}
import { Buffer } from "buffer";
import { BoxContainer, BoxHeader } from "@isomp4/core";
const EMPTY_BUFFER = Buffer.allocUnsafe(0);
/**
* Parses the ISO BMFF box structure of an MP4 stream.
*/
export class AbstractMP4Parser {
/**
* Creates a new parser for an MP4 stream.
*/
constructor() {
this.boxes = new Map();
this.boxStack = [];
this.buffer = EMPTY_BUFFER;
this.bytesNeeded = 0;
this.currentBox = null;
}
/**
*
* @param encodings
*/
registerBox(...encodings) {
for (const encoding of encodings) {
if (this.boxes.has(encoding.type)) {
throw new Error("Box type is already registered: " + encoding.type);
}
this.boxes.set(encoding.type, encoding);
}
}
/**
*
* @param boxType
*/
isBoxRegistered(boxType) {
return this.boxes.has(boxType);
}
/**
* Appends new data to the stream.
* @param data The new data to append. This data does NOT need to be a complete segment (or even a fragment).
*/
append(data) {
let input = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
while (input.length > 0) {
if (this.bytesNeeded > 0) {
// Ensure that buffer is the correct size
this.ensureBuffer(this.bytesNeeded);
// Don't copy more data into the temp buffer than is needed for the next part!
const needed = this.bytesNeeded - this.buffer.byteOffset;
if (needed > 0) {
if (needed <= input.length) {
// Only copy 'needed' number of bytes into the temp buffer
input.copy(this.buffer, 0, 0, needed);
input = input.slice(needed);
}
else {
// All input can be copied into temp buffer
this.buffer = this.buffer.slice(input.copy(this.buffer));
// More input data is needed
return;
}
}
// Temp buffer now contains all bytes needed
// Flip buffer
const bytesNeeded = this.bytesNeeded;
const buf = Buffer.from(this.buffer.buffer, 0, bytesNeeded);
this.bytesNeeded = 0; // This must be reset before calling processBuffer()
const bytesConsumed = this.processBuffer(buf);
if (this.bytesNeeded > 0) {
// More bytes are needed
continue;
}
if (bytesConsumed !== bytesNeeded) {
throw new Error(`bytes consumed(${bytesConsumed}) != bytes needed(${bytesNeeded})`);
}
// Reset buffer
this.buffer = Buffer.from(this.buffer.buffer);
}
else {
// Avoid copying data by using the input buffer directly
const consumed = this.processBuffer(input);
if (consumed > 0) {
input = input.slice(consumed);
}
}
}
}
ensureBuffer(capacity) {
if (this.buffer.buffer.byteLength < capacity) {
const newBuffer = Buffer.alloc(capacity);
// If the byteOffset is zero, then this indicates that there is no data written to the buffer
if (this.buffer.byteOffset > 0) {
// Must copy old buffer to new buffer
Buffer.from(this.buffer.buffer).copy(newBuffer);
}
this.buffer = newBuffer;
}
}
/**
* Processes the given buffer.
* @param buffer The input buffer.
* @return The number of bytes consumed.
*/
processBuffer(buffer) {
stackCheck: if (this.boxStack.length > 0) {
const top = this.boxStack[this.boxStack.length - 1];
const header = top.header;
const needed = header.size - top.offset;
if (needed > 0) {
if (top.children) {
// Skip and parse children normally
break stackCheck;
}
const available = buffer.length;
if (needed > available) {
// Don't have enough data
this.onBoxData(header, buffer);
top.offset += available;
return available;
}
// Have enough data
this.onBoxData(header, buffer.slice(0, needed));
}
// End box
if (top.box != null) {
this.onBoxEnded(header, top.box);
}
else {
this.onBoxEnded(header);
}
// Pop box state
this.boxStack.pop();
// Check next box state
if (this.boxStack.length > 0) {
const next = this.boxStack[this.boxStack.length - 1];
next.offset += header.size;
if (top.box != null && next.box != null && BoxContainer.isInstance(next.box)) {
BoxContainer.add(next.box, top.box);
}
}
// Trigger parsing of next box
this.currentBox = null;
return needed;
}
if (this.currentBox == null) {
const header = BoxHeader.parse(buffer);
if (typeof header === "number") {
this.bytesNeeded = header;
return 0;
}
const headerLength = BoxHeader.decodedBytes;
// Invoke box started event
const content = this.onBoxStarted(header, buffer.slice(0, headerLength));
// Start box
this.currentBox = {
header,
headerLength,
content,
};
return headerLength;
}
const header = this.currentBox.header;
if (this.currentBox.content) {
const encoding = this.boxes.get(header.type);
if (encoding != null) {
const box = encoding.decode(buffer, header);
if (typeof box === "number") {
this.bytesNeeded = box;
return 0;
}
const consumed = encoding.decodedBytes;
// Invoke box decoded event
const children = this.onBoxDecoded(box, buffer.slice(0, consumed));
// Push box onto stack (and record whether to parse children)
this.boxStack.push({
header,
box,
children,
offset: this.currentBox.headerLength + consumed,
});
// Trigger parsing of child boxes
if (children) {
box.children = {};
this.currentBox = null;
}
return consumed;
}
// No encoding, so reset content boolean
this.currentBox.content = false;
}
// No encoding for box type, must skip entire box and children
this.boxStack.push({
header,
box: null,
children: false,
offset: this.currentBox.headerLength,
});
return this.processBuffer(buffer);
}
}
/**
* An implementation of {@link AbstractMP4Parser} that delegates to optional function properties.
*/
export class MP4Parser extends AbstractMP4Parser {
/**
* Create a new MP4Parser.
*/
constructor() {
super();
}
onBoxStarted(header, headerData) {
return this.boxStarted ? this.boxStarted(header, headerData) : true;
}
onBoxDecoded(box, boxData) {
return this.boxDecoded ? this.boxDecoded(box, boxData) : true;
}
onBoxData(header, boxData) {
this.boxData?.(header, boxData);
}
onBoxEnded(header, box) {
this.boxEnded?.(header, box);
}
}
//# sourceMappingURL=parser.js.map
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}