Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bplist-parser

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bplist-parser - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

208

bplistParser.js

@@ -5,5 +5,5 @@ 'use strict';

var fs = require('fs');
var bigInt = require("big-integer");
var debug = false;
const fs = require('fs');
const bigInt = require("big-integer");
const debug = false;

@@ -16,36 +16,41 @@ exports.maxObjectSize = 100 * 1000 * 1000; // 100Meg

// So we just hardcode the correct value.
var EPOCH = 978307200000;
const EPOCH = 978307200000;
// UID object definition
var UID = exports.UID = function(id) {
const UID = exports.UID = function(id) {
this.UID = id;
}
};
var parseFile = exports.parseFile = function (fileNameOrBuffer, callback) {
function tryParseBuffer(buffer) {
var err = null;
var result;
try {
result = parseBuffer(buffer);
} catch (ex) {
err = ex;
const parseFile = exports.parseFile = function (fileNameOrBuffer, callback) {
return new Promise(function (resolve, reject) {
function tryParseBuffer(buffer) {
let err = null;
let result;
try {
result = parseBuffer(buffer);
resolve(result);
} catch (ex) {
err = ex;
reject(err);
} finally {
if (callback) callback(err, result);
}
}
callback(err, result);
}
if (Buffer.isBuffer(fileNameOrBuffer)) {
return tryParseBuffer(fileNameOrBuffer);
} else {
if (Buffer.isBuffer(fileNameOrBuffer)) {
return tryParseBuffer(fileNameOrBuffer);
}
fs.readFile(fileNameOrBuffer, function (err, data) {
if (err) { return callback(err); }
if (err) {
reject(err);
return callback(err);
}
tryParseBuffer(data);
});
}
});
};
var parseBuffer = exports.parseBuffer = function (buffer) {
var result = {};
const parseBuffer = exports.parseBuffer = function (buffer) {
// check header
var header = buffer.slice(0, 'bplist'.length).toString('utf8');
const header = buffer.slice(0, 'bplist'.length).toString('utf8');
if (header !== 'bplist') {

@@ -56,21 +61,21 @@ throw new Error("Invalid binary plist. Expected 'bplist' at offset 0.");

// Handle trailer, last 32 bytes of the file
var trailer = buffer.slice(buffer.length - 32, buffer.length);
const trailer = buffer.slice(buffer.length - 32, buffer.length);
// 6 null bytes (index 0 to 5)
var offsetSize = trailer.readUInt8(6);
const offsetSize = trailer.readUInt8(6);
if (debug) {
console.log("offsetSize: " + offsetSize);
}
var objectRefSize = trailer.readUInt8(7);
const objectRefSize = trailer.readUInt8(7);
if (debug) {
console.log("objectRefSize: " + objectRefSize);
}
var numObjects = readUInt64BE(trailer, 8);
const numObjects = readUInt64BE(trailer, 8);
if (debug) {
console.log("numObjects: " + numObjects);
}
var topObject = readUInt64BE(trailer, 16);
const topObject = readUInt64BE(trailer, 16);
if (debug) {
console.log("topObject: " + topObject);
}
var offsetTableOffset = readUInt64BE(trailer, 24);
const offsetTableOffset = readUInt64BE(trailer, 24);
if (debug) {

@@ -85,6 +90,6 @@ console.log("offsetTableOffset: " + offsetTableOffset);

// Handle offset table
var offsetTable = [];
const offsetTable = [];
for (var i = 0; i < numObjects; i++) {
var offsetBytes = buffer.slice(offsetTableOffset + i * offsetSize, offsetTableOffset + (i + 1) * offsetSize);
for (let i = 0; i < numObjects; i++) {
const offsetBytes = buffer.slice(offsetTableOffset + i * offsetSize, offsetTableOffset + (i + 1) * offsetSize);
offsetTable[i] = readUInt(offsetBytes, 0);

@@ -101,6 +106,6 @@ if (debug) {

function parseObject(tableOffset) {
var offset = offsetTable[tableOffset];
var type = buffer[offset];
var objType = (type & 0xF0) >> 4; //First 4 bits
var objInfo = (type & 0x0F); //Second 4 bits
const offset = offsetTable[tableOffset];
const type = buffer[offset];
const objType = (type & 0xF0) >> 4; //First 4 bits
const objInfo = (type & 0x0F); //Second 4 bits
switch (objType) {

@@ -148,4 +153,4 @@ case 0x0:

function bufferToHexString(buffer) {
var str = '';
var i;
let str = '';
let i;
for (i = 0; i < buffer.length; i++) {

@@ -157,3 +162,3 @@ if (buffer[i] != 0x00) {

for (; i < buffer.length; i++) {
var part = '00' + buffer[i].toString(16);
const part = '00' + buffer[i].toString(16);
str += part.substr(part.length - 2);

@@ -165,31 +170,34 @@ }

function parseInteger() {
var length = Math.pow(2, objInfo);
if (length > 4) {
var data = buffer.slice(offset + 1, offset + 1 + length);
var str = bufferToHexString(data);
const length = Math.pow(2, objInfo);
if (objInfo == 0x4) {
const data = buffer.slice(offset + 1, offset + 1 + length);
const str = bufferToHexString(data);
return bigInt(str, 16);
} if (length < exports.maxObjectSize) {
}
if (objInfo == 0x3) {
return buffer.readInt32BE(offset + 1);
}
if (length < exports.maxObjectSize) {
return readUInt(buffer.slice(offset + 1, offset + 1 + length));
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
function parseUID() {
var length = objInfo + 1;
const length = objInfo + 1;
if (length < exports.maxObjectSize) {
return new UID(readUInt(buffer.slice(offset + 1, offset + 1 + length)));
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
function parseReal() {
var length = Math.pow(2, objInfo);
const length = Math.pow(2, objInfo);
if (length < exports.maxObjectSize) {
var realBuffer = buffer.slice(offset + 1, offset + 1 + length);
const realBuffer = buffer.slice(offset + 1, offset + 1 + length);
if (length === 4) {
return realBuffer.readFloatBE(0);
}
else if (length === 8) {
if (length === 8) {
return realBuffer.readDoubleBE(0);

@@ -206,3 +214,3 @@ }

}
var dateBuffer = buffer.slice(offset + 1, offset + 9);
const dateBuffer = buffer.slice(offset + 1, offset + 9);
return new Date(EPOCH + (1000 * dateBuffer.readDoubleBE(0)));

@@ -212,12 +220,12 @@ }

function parseData() {
var dataoffset = 1;
var length = objInfo;
let dataoffset = 1;
let length = objInfo;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
const int_type = buffer[offset + 1];
const intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.error("0x4: UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
const intInfo = int_type & 0x0F;
const intLength = Math.pow(2, intInfo);
dataoffset = 2 + intLength;

@@ -232,5 +240,4 @@ if (intLength < 3) {

return buffer.slice(offset + dataoffset, offset + dataoffset + length);
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}

@@ -240,14 +247,14 @@

isUtf16 = isUtf16 || 0;
var enc = "utf8";
var length = objInfo;
var stroffset = 1;
let enc = "utf8";
let length = objInfo;
let stroffset = 1;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
const int_type = buffer[offset + 1];
const intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.err("UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
var stroffset = 2 + intLength;
const intInfo = int_type & 0x0F;
const intLength = Math.pow(2, intInfo);
stroffset = 2 + intLength;
if (intLength < 3) {

@@ -262,3 +269,3 @@ length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));

if (length < exports.maxObjectSize) {
var plistString = new Buffer(buffer.slice(offset + stroffset, offset + stroffset + length));
let plistString = Buffer.from(buffer.slice(offset + stroffset, offset + stroffset + length));
if (isUtf16) {

@@ -269,18 +276,17 @@ plistString = swapBytes(plistString);

return plistString.toString(enc);
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
function parseArray() {
var length = objInfo;
var arrayoffset = 1;
let length = objInfo;
let arrayoffset = 1;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
const int_type = buffer[offset + 1];
const intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.error("0xa: UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
const intInfo = int_type & 0x0F;
const intLength = Math.pow(2, intInfo);
arrayoffset = 2 + intLength;

@@ -296,5 +302,5 @@ if (intLength < 3) {

}
var array = [];
for (var i = 0; i < length; i++) {
var objRef = readUInt(buffer.slice(offset + arrayoffset + i * objectRefSize, offset + arrayoffset + (i + 1) * objectRefSize));
const array = [];
for (let i = 0; i < length; i++) {
const objRef = readUInt(buffer.slice(offset + arrayoffset + i * objectRefSize, offset + arrayoffset + (i + 1) * objectRefSize));
array[i] = parseObject(objRef);

@@ -306,12 +312,12 @@ }

function parseDictionary() {
var length = objInfo;
var dictoffset = 1;
let length = objInfo;
let dictoffset = 1;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
const int_type = buffer[offset + 1];
const intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.error("0xD: UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
const intInfo = int_type & 0x0F;
const intLength = Math.pow(2, intInfo);
dictoffset = 2 + intLength;

@@ -330,8 +336,8 @@ if (intLength < 3) {

}
var dict = {};
for (var i = 0; i < length; i++) {
var keyRef = readUInt(buffer.slice(offset + dictoffset + i * objectRefSize, offset + dictoffset + (i + 1) * objectRefSize));
var valRef = readUInt(buffer.slice(offset + dictoffset + (length * objectRefSize) + i * objectRefSize, offset + dictoffset + (length * objectRefSize) + (i + 1) * objectRefSize));
var key = parseObject(keyRef);
var val = parseObject(valRef);
const dict = {};
for (let i = 0; i < length; i++) {
const keyRef = readUInt(buffer.slice(offset + dictoffset + i * objectRefSize, offset + dictoffset + (i + 1) * objectRefSize));
const valRef = readUInt(buffer.slice(offset + dictoffset + (length * objectRefSize) + i * objectRefSize, offset + dictoffset + (length * objectRefSize) + (i + 1) * objectRefSize));
const key = parseObject(keyRef);
const val = parseObject(valRef);
if (debug) {

@@ -352,4 +358,4 @@ console.log(" DICT #" + tableOffset + ": Mapped " + key + " to " + val);

var l = 0;
for (var i = start; i < buffer.length; i++) {
let l = 0;
for (let i = start; i < buffer.length; i++) {
l <<= 8;

@@ -363,3 +369,3 @@ l |= buffer[i] & 0xFF;

function readUInt64BE(buffer, start) {
var data = buffer.slice(start, start + 8);
const data = buffer.slice(start, start + 8);
return data.readUInt32BE(4, 8);

@@ -369,5 +375,5 @@ }

function swapBytes(buffer) {
var len = buffer.length;
for (var i = 0; i < len; i += 2) {
var a = buffer[i];
const len = buffer.length;
for (let i = 0; i < len; i += 2) {
const a = buffer[i];
buffer[i] = buffer[i+1];

@@ -374,0 +380,0 @@ buffer[i+1] = a;

{
"name": "bplist-parser",
"version": "0.1.1",
"version": "0.2.0",
"description": "Binary plist parser.",
"main": "bplistParser.js",
"scripts": {
"test": "./node_modules/nodeunit/bin/nodeunit test"
"test": "mocha test"
},

@@ -15,6 +15,14 @@ "keywords": [

"author": "Joe Ferner <joe.ferner@nearinfinity.com>",
"contributors": [
"Brett Zamir"
],
"license": "MIT",
"devDependencies": {
"nodeunit": "~0.9.1"
"mocha": "^6.1.4"
},
"homepage": "https://github.com/nearinfinity/node-bplist-parser",
"bugs": "https://github.com/nearinfinity/node-bplist-parser/issues",
"engines": {
"node": ">= 5.10.0"
},
"repository": {

@@ -25,4 +33,4 @@ "type": "git",

"dependencies": {
"big-integer": "^1.6.7"
"big-integer": "^1.6.44"
}
}

@@ -1,3 +0,2 @@

bplist-parser
=============
# bplist-parser

@@ -15,9 +14,11 @@ Binary Mac OS X Plist (property list) parser.

```javascript
var bplist = require('bplist-parser');
const bplist = require('bplist-parser');
bplist.parseFile('myPlist.bplist', function(err, obj) {
if (err) throw err;
(async () => {
const obj = await bplist.parseFile('myPlist.bplist');
console.log(JSON.stringify(obj));
});
})();
```

@@ -24,0 +25,0 @@

@@ -5,156 +5,101 @@ 'use strict';

var path = require('path');
var nodeunit = require('nodeunit');
var bplist = require('../');
const assert = require('assert');
const path = require('path');
const bplist = require('../');
module.exports = {
'iTunes Small': function (test) {
var file = path.join(__dirname, "iTunes-small.bplist");
var startTime1 = new Date();
describe('bplist-parser', function () {
it('iTunes Small', async function () {
const file = path.join(__dirname, "iTunes-small.bplist");
const startTime1 = new Date();
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime1) + 'ms');
assert.equal(dict['Application Version'], "9.0.3");
assert.equal(dict['Library Persistent ID'], "6F81D37F95101437");
});
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime1) + 'ms');
var dict = dicts[0];
test.equal(dict['Application Version'], "9.0.3");
test.equal(dict['Library Persistent ID'], "6F81D37F95101437");
test.done();
});
},
it('sample1', async function () {
const file = path.join(__dirname, "sample1.bplist");
const startTime = new Date();
'sample1': function (test) {
var file = path.join(__dirname, "sample1.bplist");
var startTime = new Date();
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
assert.equal(dict['CFBundleIdentifier'], 'com.apple.dictionary.MySample');
});
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
var dict = dicts[0];
test.equal(dict['CFBundleIdentifier'], 'com.apple.dictionary.MySample');
test.done();
});
},
it('sample2', async function () {
const file = path.join(__dirname, "sample2.bplist");
const startTime = new Date();
'sample2': function (test) {
var file = path.join(__dirname, "sample2.bplist");
var startTime = new Date();
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
assert.equal(dict['PopupMenu'][2]['Key'], "\n #import <Cocoa/Cocoa.h>\n\n#import <MacRuby/MacRuby.h>\n\nint main(int argc, char *argv[])\n{\n return macruby_main(\"rb_main.rb\", argc, argv);\n}\n");
});
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
var dict = dicts[0];
test.equal(dict['PopupMenu'][2]['Key'], "\n #import <Cocoa/Cocoa.h>\n\n#import <MacRuby/MacRuby.h>\n\nint main(int argc, char *argv[])\n{\n return macruby_main(\"rb_main.rb\", argc, argv);\n}\n");
test.done();
});
},
it('airplay', async function () {
const file = path.join(__dirname, "airplay.bplist");
const startTime = new Date();
'airplay': function (test) {
var file = path.join(__dirname, "airplay.bplist");
var startTime = new Date();
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
assert.equal(dict['duration'], 5555.0495000000001);
assert.equal(dict['position'], 4.6269989039999997);
});
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
it('utf16', async function () {
const file = path.join(__dirname, "utf16.bplist");
const startTime = new Date();
var dict = dicts[0];
test.equal(dict['duration'], 5555.0495000000001);
test.equal(dict['position'], 4.6269989039999997);
test.done();
});
},
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
'utf16': function (test) {
var file = path.join(__dirname, "utf16.bplist");
var startTime = new Date();
assert.equal(dict['CFBundleName'], 'sellStuff');
assert.equal(dict['CFBundleShortVersionString'], '2.6.1');
assert.equal(dict['NSHumanReadableCopyright'], '©2008-2012, sellStuff, Inc.');
});
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
it('utf16chinese', async function () {
const file = path.join(__dirname, "utf16_chinese.plist");
const startTime = new Date();
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
var dict = dicts[0];
test.equal(dict['CFBundleName'], 'sellStuff');
test.equal(dict['CFBundleShortVersionString'], '2.6.1');
test.equal(dict['NSHumanReadableCopyright'], '©2008-2012, sellStuff, Inc.');
test.done();
});
},
assert.equal(dict['CFBundleName'], '天翼阅读');
assert.equal(dict['CFBundleDisplayName'], '天翼阅读');
});
'utf16chinese': function (test) {
var file = path.join(__dirname, "utf16_chinese.plist");
var startTime = new Date();
it('uid', async function () {
const file = path.join(__dirname, "uid.bplist");
const startTime = new Date();
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
assert.deepEqual(dict['$objects'][1]['NS.keys'], [{UID:2}, {UID:3}, {UID:4}]);
assert.deepEqual(dict['$objects'][1]['NS.objects'], [{UID: 5}, {UID:6}, {UID:7}]);
assert.deepEqual(dict['$top']['root'], {UID:1});
});
var dict = dicts[0];
test.equal(dict['CFBundleName'], '天翼阅读');
test.equal(dict['CFBundleDisplayName'], '天翼阅读');
test.done();
});
},
it('int64', async function () {
const file = path.join(__dirname, "int64.bplist");
const startTime = new Date();
const [dict] = await bplist.parseFile(file);
const endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
'uid': function (test) {
var file = path.join(__dirname, "uid.bplist");
var startTime = new Date();
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
var dict = dicts[0];
test.deepEqual(dict['$objects'][1]['NS.keys'], [{UID:2}, {UID:3}, {UID:4}]);
test.deepEqual(dict['$objects'][1]['NS.objects'], [{UID: 5}, {UID:6}, {UID:7}]);
test.deepEqual(dict['$top']['root'], {UID:1});
test.done();
});
},
'int64': function (test) {
var file = path.join(__dirname, "int64.bplist");
var startTime = new Date();
bplist.parseFile(file, function (err, dicts) {
if (err) {
throw err;
}
var endTime = new Date();
console.log('Parsed "' + file + '" in ' + (endTime - startTime) + 'ms');
var dict = dicts[0];
test.equal(dict['zero'], '0');
test.equal(dict['int64item'], '12345678901234567890');
test.done();
});
}
};
assert.equal(dict['zero'], '0');
assert.equal(dict['int64item'], '12345678901234567890');
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc