Permalink
Browse files

Updated to use the YUI compressor instead of JSMin

  • Loading branch information...
1 parent 76fce81 commit f56172a61de09173221fb8160496d7fe54ee651d @chriso chriso committed Dec 19, 2010
Showing with 154 additions and 199 deletions.
  1. +7 −7 README.md
  2. +3 −0 bin/packnode
  3. +1 −0 index.js
  4. +1 −0 lib/index.js
  5. +136 −0 lib/packnode.js
  6. BIN yui.jar → lib/yuicompressor-2.4.2.jar
  7. +6 −4 package.json
  8. +0 −188 packnode
View
@@ -1,16 +1,20 @@
-`packnode` runs node modules through JSMin and encrypts them for private use.
+`packnode` minifies, obfuscates or encrypts node modules for private use.
To install packnode, use [npm](http://github.com/isaacs/npm)
$ npm install pack
## Packing a module
-To pack `myscript.js` using the password `pass123`, run
+To compress and obfuscate `myscript.js` using the YUI compressor, run
+
+ $ cat myscript.js | packnode > packed.js
+
+To encrypt `myscript.js` using the password `pass123`, run
$ cat myscript.js | packnode pass123 > packed.js
-Encrypted modules can be accessed by calling require(packed).unpack(password);
+Encrypted modules can be accessed by calling require(packed).unpack(password);
## Example
@@ -41,10 +45,6 @@ CoffeeScript modules can be packed using
$ cat myscript.coffee | coffee -c -s | packnode pass123 > packed.js
-To obfuscate code, use the included YUI Compressor v2.4.2 (requires Java)
-
- $ java -jar yui.jar myscript.js | packnode pass123 > packed.js
-
To specify a custom encryption algorithm or output encoding, use `-a` and `-e`
$ packnode -a aes256 -e hex < myscript.js > packed.js
View
@@ -0,0 +1,3 @@
+#!/usr/bin/env node
+
+require('packnode').pack();
View
@@ -0,0 +1 @@
+exports = module.exports = require('./lib');
View
@@ -0,0 +1 @@
+exports = module.exports = require('./packnode');
View
@@ -0,0 +1,136 @@
+var fs = require('fs'),
+ crypto = require('crypto'),
+ child = require('child_process'),
+ args = process.argv.slice(2);
+
+var stdin = process.openStdin(), input = '';
+
+var cipher, data = '', encrypted, out, chunk = [],
+ packed, decipher,
+ encoding = 'base64',
+ algorithm = 'aes256',
+ chunk_length = 100,
+ password, unpack, minify;
+
+var exit = function (msg, is_error) {
+ console.log(msg);
+ process.exit(1);
+};
+
+var usage = ''
+ + '\x1b[1mUsage\x1b[0m: packnode [OPTIONS] <PASSWORD>\n'
+ + '\n'
+ + '\x1b[1mExample 1\x1b[0m: cat input.js | packnode mypassword > output.js\n'
+ + '\x1b[1mExample 2\x1b[0m: cat input.coffee | coffee -c -s | packnode mypassword > output.js\n'
+ + '\n'
+ + '\x1b[1mOptions\x1b[0m:\n'
+ + ' -m, --minify Just run input through the YUI Compressor\n'
+ + ' -a, --algorithm <..> Use the specified algorithm. Default is "aes256"\n'
+ + ' -e, --encoding <..> Encode with base64|hex|binary. Default is "hex"\n'
+ + ' -u, --unpack Unpack the module using the specified password\n'
+ + ' -h, --help Display help information\n'
+ ;
+
+var min = function (data, callback) {
+ var tmp_file = Math.floor(Math.random() * 1000000) + '.js';
+
+ fs.writeFileSync(__dirname + '/' + tmp_file, data, 'utf8');
+
+ var remove_tmp = function () {
+ try {
+ fs.unlinkSync(__dirname + '/' + tmp_file);
+ } catch (e) {}
+ };
+
+ ['SIGINT', 'SIGTERM', 'SIGKILL', 'SIGQUIT', 'SIGHUP', 'exit'].forEach(function (signal) {
+ process.on(signal, remove_tmp);
+ });
+
+ child.exec('java -jar yuicompressor-2.4.2.jar "' + tmp_file + '"', {cwd: __dirname}, function (err, stdout, stderr) {
+ remove_tmp();
+ if (err || stderr) throw err || stderr;
+ callback(stdout);
+ });
+};
+
+exports.pack = function () {
+
+ if (!args.length) {
+ exit(usage);
+ }
+
+ while (args.length) {
+ arg = args.shift();
+ switch (arg) {
+ case '-a':
+ case '--algorithm':
+ algorithm = args.shift();
+ break;
+ case '-e':
+ case '--encoding':
+ encoding = args.shift();
+ break;
+ case '-u':
+ case '--unpack':
+ unpack = true;
+ break;
+ case '-m':
+ case '--minify':
+ minify = true;
+ break;
+ case '-h':
+ case '--help':
+ exit(usage);
+ break;
+ default:
+ password = arg;
+ break;
+ }
+ }
+
+ // Read from stdin
+ stdin.setEncoding('utf8');
+ stdin.on('data', function (input) { data += input; });
+ stdin.on('end', function () {
+
+ if (!unpack) {
+
+ // Minify the file
+ min(data, function (data) {
+
+ // Are we just minifying the file?
+ if (minify) {
+ process.stdout.write(data);
+ return;
+ }
+
+ // Encrypt the file
+ cipher = crypto.createCipher(algorithm, password);
+ encrypted = cipher.update(data, 'binary', encoding) + cipher.final(encoding);
+ for (var i = 0, l = encrypted.length; i < l; i += chunk_length) {
+ chunk.push(encrypted.substr(i, chunk_length));
+ }
+
+ // Prepare the output
+ out = 'e="' + chunk.join('"\n+"') + '";\n';
+ out += 'exports.unpack=function(p){var d=require("crypto").createDecipher("' + algorithm + '",p);\n';
+ out += 'eval(d.update(e,"' + encoding + '","utf8")+d.final("utf8"));return exports;}';
+
+ // ..and write to stdout
+ process.stdout.write(out);
+
+ });
+
+ } else {
+
+ // Read and decrypt the file
+ packed = (function () { eval(data); return e; }());
+ decipher = crypto.createDecipher(algorithm, password);
+ out = decipher.update(packed, encoding, 'utf8') + decipher.final('utf8');
+
+ process.stdout.write(out);
+
+ }
+
+ });
+}
File renamed without changes.
View
@@ -1,9 +1,11 @@
{ "name" : "pack",
- "description" : "Create private node modules",
- "version" : "0.1.5",
+ "description" : "Minify, obfuscate and encrypt node modules",
+ "version" : "0.2.0",
"homepage" : "http://github.com/chriso/packnode",
- "keywords" : ["pack","packnode","encrypt","compress","unpack"],
+ "keywords" : ["pack","packnode","encrypt","compress","unpack","yui","obfuscate","compressor","closure","jsmin"],
"author" : "Chris O'Hara <cohara87@gmail.com>",
+ "main" : "./lib",
+ "directories" : { "lib" : "./lib" },
"bugs": {
"mail": "cohara87@gmail.com",
"web": "http://github.com/chriso/packnode/issues"
@@ -14,7 +16,7 @@
},
"engines": { "node": ">=0.2.5" },
"bin": {
- "packnode": "./packnode",
+ "packnode": "./bin/packnode",
},
"licenses": [{
"type": "MIT",
View
188 packnode
@@ -1,188 +0,0 @@
-#!/usr/bin/env node
-
-var fs = require('fs'),
- crypto = require('crypto'),
- args = process.argv.slice(2);
-
-var stdin = process.openStdin(), input = '';
-
-var cipher, data = '', encrypted, out, chunk = [],
- packed, decipher,
- encoding = 'base64',
- algorithm = 'aes256',
- chunk_length = 100,
- password, unpack, minify;
-
-var exit = function (msg, is_error) {
- console.log(msg);
- process.exit(1);
-};
-
-var usage = ''
- + '\x1b[1mUsage\x1b[0m: packnode [OPTIONS] <PASSWORD>\n'
- + '\n'
- + '\x1b[1mExample 1\x1b[0m: cat input.js | packnode mypassword > output.js\n'
- + '\x1b[1mExample 2\x1b[0m: cat input.coffee | coffee -c -s | packnode mypassword > output.js\n'
- + '\n'
- + '\x1b[1mOptions\x1b[0m:\n'
- + ' -m, --minify Just minify the input using JSMin\n'
- + ' -a, --algorithm <..> Use the specified algorithm. Default is "aes256"\n'
- + ' -e, --encoding <..> Encode with base64|hex|binary. Default is "hex"\n'
- + ' -u, --unpack Unpack the module using the specified password\n'
- + ' -h, --help Display help information\n'
- ;
-
-if (!args.length) {
- exit(usage);
-}
-
-while (args.length) {
- arg = args.shift();
- switch (arg) {
- case '-a':
- case '--algorithm':
- algorithm = args.shift();
- break;
- case '-e':
- case '--encoding':
- encoding = args.shift();
- break;
- case '-u':
- case '--unpack':
- unpack = true;
- break;
- case '-m':
- case '--minify':
- minify = true;
- break;
- case '-h':
- case '--help':
- exit(usage);
- break;
- default:
- password = arg;
- break;
- }
-}
-
-/*
-jsmin.js - 2010-01-15
-Author: NanaLich (http://www.cnblogs.com/NanaLich)
-Another patched version for jsmin.js patched by Billy Hoffman,
-this version will try to keep CR LF pairs inside the important comments
-away from being changed into double LF pairs.
-
-jsmin.js - 2009-11-05
-Author: Billy Hoffman
-This is a patched version of jsmin.js created by Franck Marcia which
-supports important comments denoted with /! ...
-Permission is hereby granted to use the Javascript version under the same
-conditions as the jsmin.js on which it is based.
-
-jsmin.js - 2006-08-31
-Author: Franck Marcia
-This work is an adaptation of jsminc.c published by Douglas Crockford.
-Permission is hereby granted to use the Javascript version under the same
-conditions as the jsmin.c on which it is based.
-
-jsmin.c
-2006-05-04
-
-Copyright (c) 2002 Douglas Crockford (www.crockford.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-The Software shall be used for Good, not Evil.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-String.prototype.has=function(c){return this.indexOf(c)>-1;};function jsmin(input,level,comment){if(!input)return'';if(!level)level=2;if(!comment)comment='';var a='',b='',EOF=-1,LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',DIGITS='0123456789',ALNUM=LETTERS+DIGITS+'_$\\',theLookahead=EOF;function isAlphanum(c){return c!=EOF&&(ALNUM.has(c)||c.charCodeAt(0)>126);}
-var iChar=0,lInput=input.length;function getc(){var c=theLookahead;if(iChar==lInput){return EOF;}
-theLookahead=EOF;if(c==EOF){c=input.charAt(iChar);++iChar;}
-if(c>=' '||c=='\n'){return c;}
-if(c=='\r'){return'\n';}
-return' ';}
-function getcIC(){var c=theLookahead;if(iChar==lInput){return EOF;}
-theLookahead=EOF;if(c==EOF){c=input.charAt(iChar);++iChar;}
-if(c>=' '||c=='\n'||c=='\r'){return c;}
-return' ';}
-function peek(){theLookahead=getc();return theLookahead;}
-function next(){var c=getc();if(c=='/'){switch(peek()){case'/':for(;;){c=getc();if(c<='\n'){return c;}}
-break;case'*':getc();if(peek()=='!'){getc();var d='/*!';for(;;){c=getcIC();switch(c){case'*':if(peek()=='/'){getc();return d+'*/';}
-break;case EOF:throw'Error: Unterminated comment.';default:d+=c;}}}else{for(;;){switch(getc()){case'*':if(peek()=='/'){getc();return' ';}
-break;case EOF:throw'Error: Unterminated comment.';}}}
-break;default:return c;}}
-return c;}
-function action(d){var r=[];if(d==1){r.push(a);}
-if(d<3){a=b;if(a=='\''||a=='"'){for(;;){r.push(a);a=getc();if(a==b){break;}
-if(a<='\n'){throw'Error: unterminated string literal: '+a;}
-if(a=='\\'){r.push(a);a=getc();}}}}
-b=next();if(b=='/'&&'(,=:[!&|'.has(a)){r.push(a);r.push(b);for(;;){a=getc();if(a=='/'){break;}else if(a=='\\'){r.push(a);a=getc();}else if(a<='\n'){throw'Error: unterminated Regular Expression literal';}
-r.push(a);}
-b=next();}
-return r.join('');}
-function m(){var r=[];a='';r.push(action(3));while(a!=EOF){switch(a){case' ':if(isAlphanum(b)){r.push(action(1));}else{r.push(action(2));}
-break;case'\n':switch(b){case'{':case'[':case'(':case'+':case'-':r.push(action(1));break;case' ':r.push(action(3));break;default:if(isAlphanum(b)){r.push(action(1));}else{if(level==1&&b!='\n'){r.push(action(1));}else{r.push(action(2));}}}
-break;default:switch(b){case' ':if(isAlphanum(a)){r.push(action(1));break;}
-r.push(action(3));break;case'\n':if(level==1&&a!='\n'){r.push(action(1));}else{switch(a){case'}':case']':case')':case'+':case'-':case'"':case'\'':if(level==3){r.push(action(3));}else{r.push(action(1));}
-break;default:if(isAlphanum(a)){r.push(action(1));}else{r.push(action(3));}}}
-break;default:r.push(action(1));break;}}}
-return r.join('');}
-ret=m(input);if(comment){return comment+'\n'+ret;}
-return ret;}
-
-// Read from stdin
-stdin.setEncoding('utf8');
-stdin.on('data', function (input) { data += input; });
-stdin.on('end', function () {
-
- if (!unpack) {
-
- // Minify the file
- data = jsmin(data);
-
- if (minify) {
- // Are we just minifying the file?
- process.stdout.write(data);
- return;
- }
-
- // Encrypt the file
- cipher = crypto.createCipher(algorithm, password);
- encrypted = cipher.update(data, 'binary', encoding) + cipher.final(encoding);
- for (var i = 0, l = encrypted.length; i < l; i += chunk_length) {
- chunk.push(encrypted.substr(i, chunk_length));
- }
-
- // Prepare the output
- out = 'e="' + chunk.join('"\n+"') + '";\n';
- out += 'exports.unpack=function(p){var d=require("crypto").createDecipher("' + algorithm + '",p);\n';
- out += 'eval(d.update(e,"' + encoding + '","utf8")+d.final("utf8"));return exports;}';
-
- } else {
-
- // Read and decrypt the file
- packed = (function () { eval(data); return e; }());
- decipher = crypto.createDecipher(algorithm, password);
- out = decipher.update(packed, encoding, 'utf8') + decipher.final('utf8');
-
- }
-
- // ..and write to stdout
- process.stdout.write(out);
-
-});

0 comments on commit f56172a

Please sign in to comment.