Skip to content

Commit

Permalink
updated base64 detection regexp. updated README. hygiene.
Browse files Browse the repository at this point in the history
  • Loading branch information
mreinstein committed Sep 27, 2012
1 parent efac250 commit d4b2689
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 32 deletions.
30 changes: 13 additions & 17 deletions README.md
@@ -1,19 +1,17 @@
node-plist
==========
# node-plist

This library contains a parser/builder for Mac OS X Plist (property list) files. These
are often used in programming OS X and iOS applications, as well as the iTunes
Provides facilities for reading and writing Mac OS X Plist (property list) files. These are often used in programming OS X and iOS applications, as well as the iTunes
configuration XML file.

Plist files represent stored programming "object"s. This makes them very similar
in nature to a JSON file. A valid Plist file should be directly representable as
a native JavaScript Object and vice-versa.
Plist files represent stored programming "object"s. They are very similar
to JSON. A valid Plist file is representable as a native JavaScript Object and vice-versa.

Usage
-----
## Tests
`npm test`

Exported are `parseFile`, `parseString` and `build` functions. Here's some examples:
## Usage

Parsing a plist from filename
``` javascript
var plist = require('plist');

Expand All @@ -24,23 +22,21 @@ plist.parseFile('myPlist.plist', function(err, obj) {
});
```

Just a `String` payload works as well:

Parsing a plist from string payload
``` javascript
var plist = require('plist');

plist.parseString('<plist><string>Hello World!</string></plist>', function(err, obj) {
if (err) throw err;

console.log(obj[0]);
// Hello World!
console.log(obj[0]); // Hello World!
});
```

Given an existing JavaScript Object, you can turn it into an XML document that complies with the plist DTD:
Given an existing JavaScript Object, you can turn it into an XML document that complies with the plist DTD

``` javascript
var plist = require('plist');

console.log(plist.build({foo : "bar"}).toString());
```
console.log(plist.build({'foo' : 'bar'}).toString());
```
28 changes: 13 additions & 15 deletions lib/plist.js
@@ -1,5 +1,5 @@
;(function (exports, sax, xmlbuilder) {
//Checks if running in a non-browser environment
// Checks if running in a non-browser environment
var inNode = typeof window === 'undefined' ? true : false;

function Parser() {
Expand All @@ -9,7 +9,7 @@
var inherits = null;
if (inNode) {
var fs = require('fs');
inherits = require('util').inherits; //use node provided function
inherits = require('util').inherits; // use node provided function
} else { //use in browser
if ("create" in Object) {
inherits = function(ctor, superCtor) {
Expand All @@ -32,7 +32,7 @@
}
}
}
inherits(Parser, sax.SAXParser); //inherit from sax (browser-style or node-style)
inherits(Parser, sax.SAXParser); // inherit from sax (browser-style or node-style)

Parser.prototype.getInteger = function (string) {
this.value = parseInt(string, 10);
Expand Down Expand Up @@ -164,7 +164,7 @@
throw error;
}

if (inNode) Parser.prototype.parseFile = function (xmlfile, callback) { //browsers aren't capable of opening files, instead use AJAX
if (inNode) Parser.prototype.parseFile = function (xmlfile, callback) { // browsers aren't capable of opening files, instead use AJAX
var parser = this;
parser.stack = [ ];
parser.context = {
Expand Down Expand Up @@ -204,7 +204,7 @@
parser.parseString(xml, callback);
}

if (inNode) exports.parseFile = function (filename, callback) { //Do not expose no created method
if (inNode) exports.parseFile = function (filename, callback) { // Do not expose no created method
var parser = new Parser();
parser.parseFile(filename, callback);
}
Expand All @@ -219,38 +219,37 @@
+ pad(d.getUTCSeconds())+'Z'
}

// instanceof is horribly unreliable.
// instanceof is horribly unreliable so we use these hackish but safer checks
// http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}

function isDate(obj) {
return (toString.call(obj) == '[object Date]');
return Object.prototype.toString.call(obj) === '[object Date]';
}

function isBoolean(obj) {
return (obj === true || obj === false || toString.call(obj) == '[object Boolean]');
}

function isNumber(obj) {
return (toString.call(obj) == '[object Number]');
return Object.prototype.toString.call(obj) === '[object Number]';
}

function isObject(obj) {
return (toString.call(obj) == '[object Object]');
return Object.prototype.toString.call(obj) === '[object Object]';
}

function isString(obj) {
return (toString.call(obj) == '[object String]');
return Object.prototype.toString.call(obj) === '[object String]';
}

exports.build = function(obj) {
var XMLHDR = { 'version': '1.0','encoding': 'UTF-8'}
, XMLDTD = { 'ext': 'PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"'}
, doc = xmlbuilder.create()
, child = doc.begin('plist', XMLHDR, XMLDTD).att('version', '1.0')
, next, tag_type, i, prop;
, child = doc.begin('plist', XMLHDR, XMLDTD).att('version', '1.0');

walk_obj(obj, child);
return child.end({pretty: true });
Expand Down Expand Up @@ -288,16 +287,15 @@
}
else if(isString(next)) {
//if (str!=obj || str.indexOf("\n")>=0) str = "<![CDATA["+str+"]]>";
// TODO this is sloppy base64 detection, use Buffer
var base64Matcher = new RegExp("^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$");
var base64Matcher = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$");
//var base64Matcher = new RegExp("^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$");
if (base64Matcher.test(next.replace(/\s/g,'')) && (next.length>125)) {
next_child.ele('data').raw(next);
} else {
next_child.ele('string').raw(next);
}
}
};


})(typeof exports === 'undefined' ? plist = {} : exports, typeof window === "undefined" ? require('sax') : sax, typeof window === "undefined" ? require('xmlbuilder') : xmlbuilder)
//the above line checks for exports (defined in node) and uses it, or creates a global variable and exports to that.
Expand Down
11 changes: 11 additions & 0 deletions tests/test-build.js
Expand Up @@ -21,6 +21,17 @@ exports.testBuildFromPlistFile = function(test) {
}
*/

exports.testBuildFromObjectWithFunctions = function(test) {
var test_object = { 'a': 'test stringy thingy', 'b': function(c,d){ return 'neat'; } };

// Try stringifying
plist.parseString(plist.build(test_object), function(err, dicts) {
test.equal(dicts[0].b, undefined);
test.equal(dicts[0].a, 'test stringy thingy');
test.done();
});
}


exports.testBuildFromSmallItunesXML = function(test) {
var file = path.join(__dirname, 'iTunes-small.xml');
Expand Down

0 comments on commit d4b2689

Please sign in to comment.