mirror of
https://github.com/beautifier/js-beautify.git
synced 2024-11-27 06:30:32 +00:00
javascriptobfuscator.com support
...and wrote a tiny testing harness for easier testing.
This commit is contained in:
parent
796d7647b0
commit
7883b4d823
@ -1,7 +1,4 @@
|
||||
/*global js_beautify */
|
||||
var tests_passed = 0;
|
||||
var tests_failed = 0;
|
||||
var test_result = '';
|
||||
|
||||
|
||||
var indent_size = 4;
|
||||
@ -9,40 +6,26 @@ var indent_char = ' ';
|
||||
var preserve_newlines = true;
|
||||
var space_after_anon_function = true;
|
||||
|
||||
function lazy_escape(str)
|
||||
function test_beautifier(input)
|
||||
{
|
||||
return str.replace(/</g, '<').replace(/\>/g, '>').replace(/\n/g, '<br />');
|
||||
}
|
||||
|
||||
function test_beautifier(input, expected)
|
||||
{
|
||||
expected = expected || input;
|
||||
|
||||
var result = js_beautify(input, {
|
||||
return js_beautify(input, {
|
||||
indent_size: indent_size,
|
||||
indent_char: indent_char,
|
||||
preserve_newlines: preserve_newlines,
|
||||
space_after_anon_function: space_after_anon_function
|
||||
});
|
||||
|
||||
if (result !== expected) {
|
||||
test_result +=
|
||||
'\n---- input --------\n' + lazy_escape(input) +
|
||||
'\n---- expected -----\n' + lazy_escape(expected) +
|
||||
'\n---- received -----\n' + lazy_escape(result) +
|
||||
'\n-------------------';
|
||||
tests_failed += 1;
|
||||
} else {
|
||||
tests_passed += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var sanitytest;
|
||||
|
||||
|
||||
function bt(input, expected)
|
||||
{
|
||||
var wrapped_input, wrapped_expectation;
|
||||
|
||||
expected = expected || input;
|
||||
test_beautifier(input, expected);
|
||||
sanitytest.expect(input, expected);
|
||||
|
||||
// test also the returned indentation
|
||||
// e.g if input = "asdf();"
|
||||
@ -56,23 +39,17 @@ function bt(input, expected)
|
||||
wrapped_input = '{\n' + input + '\nindent;}';
|
||||
//wrapped_expectation = '{\n ' + expected.replace(/^\s{4}/gm, 'g ') + '\n indent;\n}';
|
||||
wrapped_expectation = '{\n' + expected.replace(/^(.+)$/mg, ' $1') + '\n indent;\n}';
|
||||
test_beautifier(wrapped_input, wrapped_expectation);
|
||||
sanitytest.expect(wrapped_input, wrapped_expectation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function results()
|
||||
{
|
||||
if (tests_failed === 0) {
|
||||
test_result += 'All ' + tests_passed + ' tests passed.';
|
||||
} else {
|
||||
test_result += '\n' + tests_failed + ' tests failed.';
|
||||
}
|
||||
return test_result;
|
||||
}
|
||||
|
||||
function test_js_beautify()
|
||||
function run_beautifier_tests(test_obj)
|
||||
{
|
||||
sanitytest = test_obj || new SanityTest();
|
||||
sanitytest.test_function(test_beautifier, 'js_beautify');
|
||||
|
||||
indent_size = 4;
|
||||
tests_passed = 0;
|
||||
tests_failed = 0;
|
||||
@ -276,5 +253,5 @@ function test_js_beautify()
|
||||
preserve_newlines = true;
|
||||
bt('var\na=do_preserve_newlines', 'var\na = do_preserve_newlines');
|
||||
|
||||
return results();
|
||||
return sanitytest;
|
||||
}
|
||||
|
45
index.html
45
index.html
@ -46,16 +46,23 @@ function unpacker_filter(source)
|
||||
|
||||
if (document.getElementById('detect-packers').checked) {
|
||||
|
||||
stripped_source = trim_leading_comments(source);
|
||||
var stripped_source = trim_leading_comments(source);
|
||||
|
||||
if (starts_with(stripped_source.toLowerCase().replace(/ +/g, ''), 'eval(function(p,a,c,k')) {
|
||||
try {
|
||||
eval('var unpacked_source = ' + stripped_source.substring(4) + ';')
|
||||
return unpacker_filter(unpacked_source);
|
||||
} catch (error) {
|
||||
source = '// jsbeautifier: unpacking failed\n' + source;
|
||||
//try {
|
||||
if (starts_with(stripped_source.toLowerCase().replace(/ +/g, ''), 'eval(function(p,a,c,k')) {
|
||||
eval('var unpacked_source = ' + stripped_source.substring(4) + ';')
|
||||
return unpacker_filter(unpacked_source);
|
||||
} else if (JavascriptObfuscator.detect(stripped_source)) {
|
||||
var unpacked = JavascriptObfuscator.unpack(stripped_source);
|
||||
if (unpacked !== stripped_source) { // avoid infinite loop if nothing done
|
||||
return unpacker_filter(unpacked);
|
||||
}
|
||||
}
|
||||
}
|
||||
//} catch (error) {
|
||||
//source = '// jsbeautifier: unpacking failed\n'
|
||||
//+ '// You may wish to send me a report to einar@jsbeautifier.org\n'
|
||||
//+ source;
|
||||
//}
|
||||
}
|
||||
return source;
|
||||
|
||||
@ -93,9 +100,19 @@ function get_var( name )
|
||||
return res ? res[1] : "";
|
||||
}
|
||||
|
||||
function run_tests()
|
||||
{
|
||||
var st = new SanityTest();
|
||||
run_beautifier_tests(st);
|
||||
JavascriptObfuscator.run_tests(st);
|
||||
return st.results();
|
||||
}
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="sanitytest.js" ></script>
|
||||
<script type="text/javascript" src="beautify.js" ></script>
|
||||
<script type="text/javascript" src="beautify-tests.js" ></script>
|
||||
<script type="text/javascript" src="javascriptobfuscator_unpacker.js" ></script>
|
||||
<script type="text/javascript" src="HTML-Beautify.js" ></script>
|
||||
|
||||
<style type="text/css">
|
||||
@ -105,7 +122,7 @@ form {
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 320px;
|
||||
height: 420px;
|
||||
border: 1px solid #ccc; padding: 3px;
|
||||
}
|
||||
h1 {
|
||||
@ -192,8 +209,8 @@ if('this_is'==/an_example/){do_something();}else{var a=b?(c%d):e[f];}
|
||||
<p>You can always see the latest version of the code in <a
|
||||
href="http://github.com/einars/js-beautify">github</a>, and you can download the beautifier for
|
||||
local use (<a href="http://github.com/einars/js-beautify/zipball/master">zip</a>, <a href="http://github.com/einars/js-beautify/tarball/master">tar.gz</a>) as well.</p>
|
||||
<h2>Unpacking javascript</h2>
|
||||
<p>The beautifier has a simple unpacker for <a href="http://dean.edwards.name/packer/">Dean Edward's packer</a>. To unpack javascript, paste (p,a,c,k,e,d) scripts and they'll hopefully get decoded. Your feedback is welcome.</p>
|
||||
<h2>Packers and obfuscators</h2>
|
||||
<p>The beautifier contains automatic unpacker for <a href="http://dean.edwards.name/packer/">Dean Edward's p.a.c.k.e.r</a> and scripts obfuscated by javascriptobfuscator.com.</p>
|
||||
<h2>Formatting from command-line</h2>
|
||||
<p>To beautify from the command-line you can use provided beautify-cl.js script, using <a href="http://www.mozilla.org/rhino/">Rhino javascript engine</a>. See the file contents for the details.</p>
|
||||
<h2><a href="http://fiddler2.com/">Fiddler</a></h2>
|
||||
@ -203,11 +220,11 @@ if('this_is'==/an_example/){do_something();}else{var a=b?(c%d):e[f];}
|
||||
<h2>Other nice things</h2>
|
||||
<p>If you're writing javascript code, <a href="http://jslint.com/">JSLint</a> is a really fine piece of software, too. You don't have to follow its recommendations blindly, but understanding what it says about your code can greatly improve your skills.</p>
|
||||
<h2>Contacts</h2>
|
||||
<p>If you find some problems with the generated javascript, adapt the script for your favorite editor, or something, my email is einars@gmail.com.</p>
|
||||
<p>If you find some problems with the generated javascript, adapt the script for your favorite editor, or something, my email is einar@jsbeautifier.org.</p>
|
||||
<div id="footer">
|
||||
<pre id="testresults"></pre>
|
||||
Written by <a href="mailto:einars@gmail.com">Einar Lielmanis</a>, with the help of <a href="http://jason.diamond.name/weblog/">Jason Diamond</a>, Patrick Hof, Nochum, Andreas Schneider, Dave Vasilevsky, <a href="http://my.opera.com/Vital/blog/">Vital,</a> Ron Baldwin and others.
|
||||
<a href="#" onclick="document.getElementById('testresults').style.display='block'; document.getElementById('testresults').innerHTML=test_js_beautify(); return false;">Run tests?</a>
|
||||
Written by <a href="mailto:einar@jsbeautifier.org">Einar Lielmanis</a>, with the help of <a href="http://jason.diamond.name/weblog/">Jason Diamond</a>, Patrick Hof, Nochum, Andreas Schneider, Dave Vasilevsky, <a href="http://my.opera.com/Vital/blog/">Vital,</a> Ron Baldwin and others.
|
||||
<a href="#" onclick="document.getElementById('testresults').style.display='block'; document.getElementById('testresults').innerHTML=run_tests(); return false;">Run tests?</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
101
javascriptobfuscator_unpacker.js
Normal file
101
javascriptobfuscator_unpacker.js
Normal file
@ -0,0 +1,101 @@
|
||||
//
|
||||
// simple unpacker/deobfuscator for scripts messed up with javascriptobfuscator.com
|
||||
// written by Einar Lielmanis <einar@jsbeautifier.org>
|
||||
//
|
||||
// usage:
|
||||
//
|
||||
// if (JavascriptObfuscator.detect(some_string)) {
|
||||
// var unpacked = JavascriptObfuscator.unpack(some_string);
|
||||
// }
|
||||
//
|
||||
//
|
||||
|
||||
var JavascriptObfuscator = {
|
||||
detect: function (str) {
|
||||
return /^var _0x[a-f0-9]+ ?\= ?\[/.test(str);
|
||||
},
|
||||
|
||||
unpack: function (str) {
|
||||
if (JavascriptObfuscator.detect(str)) {
|
||||
var matches = /var (_0x[a-f\d]+) ?\= ?\[(.*?)\];/.exec(str);
|
||||
if (matches) {
|
||||
var var_name = matches[1];
|
||||
var strings = JavascriptObfuscator._smart_split(JavascriptObfuscator._unescape(matches[2]));
|
||||
var str = str.substring(matches[0].length);
|
||||
for (var k in strings) {
|
||||
str = str.replace(var_name + '[' + k + ']', strings[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
_smart_split: function(str) {
|
||||
var strings = [];
|
||||
var pos = 0;
|
||||
while (pos < str.length) {
|
||||
switch(str[pos]) {
|
||||
case ' ':
|
||||
case ',':
|
||||
break;
|
||||
case '"':
|
||||
// new word
|
||||
var word = '';
|
||||
pos += 1;
|
||||
while (pos < str.length) {
|
||||
if (str[pos] == '"') {
|
||||
break;
|
||||
}
|
||||
if (str[pos] == '\\') {
|
||||
word += '\\';
|
||||
pos++;
|
||||
}
|
||||
word += str[pos];
|
||||
pos++;
|
||||
}
|
||||
strings.push('"' + word + '"');
|
||||
break;
|
||||
case ',':
|
||||
// string separator
|
||||
break;
|
||||
case ']':
|
||||
// la finita
|
||||
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return strings;
|
||||
},
|
||||
|
||||
|
||||
_unescape: function (str) {
|
||||
for (var i = 32; i < 128; i++) {
|
||||
str = str.replace(new RegExp('\\\\x' + i.toString(16), 'ig'), String.fromCharCode(i));
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
|
||||
run_tests: function (sanity_test) {
|
||||
var t = sanity_test || new SanityTest();
|
||||
t.test_function(JavascriptObfuscator._smart_split, "JavascriptObfuscator._smart_split");
|
||||
t.expect('', []);
|
||||
t.expect('"a", "b"', ['"a"', '"b"']);
|
||||
t.expect('"aaa","bbbb"', ['"aaa"', '"bbbb"']);
|
||||
t.expect('"a", "b\\\""', ['"a"', '"b\\\""']);
|
||||
t.test_function(JavascriptObfuscator._unescape, 'JavascriptObfuscator._unescape');
|
||||
t.expect('\\x40', '@');
|
||||
t.expect('\\x10', '\\x10');
|
||||
t.expect('\\x1', '\\x1');
|
||||
t.test_function(JavascriptObfuscator.detect, 'JavascriptObfuscator.detect');
|
||||
t.expect('', false);
|
||||
t.expect('abcd', false);
|
||||
t.expect('var _0xaaaa', false);
|
||||
t.expect('var _0xaaaa = ["a", "b"]', true);
|
||||
t.expect('var _0xaaaa=["a", "b"]', true);
|
||||
t.expect('var _0x1234=["a","b"]', true);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
}
|
128
sanitytest.js
Normal file
128
sanitytest.js
Normal file
@ -0,0 +1,128 @@
|
||||
//
|
||||
// simple testing interface
|
||||
// written by Einar Lielmanis, einar@jsbeautifier.org
|
||||
//
|
||||
// usage:
|
||||
//
|
||||
// var t = new SanityTest(function (x) { return x; }, 'my function');
|
||||
// t.expect('input', 'output');
|
||||
// t.expect('a', 'a');
|
||||
// output_somewhere(t.results()); // good for <pre>, html safe-ish
|
||||
// alert(t.results_raw()); // html unescaped
|
||||
|
||||
|
||||
function SanityTest (func, test_name) {
|
||||
|
||||
var test_func = func || function (x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
var test_name = test_name || '';
|
||||
|
||||
var n_failed = 0;
|
||||
var n_succeeded = 0;
|
||||
|
||||
var failures = [];
|
||||
|
||||
this.test_function = function(func, name) {
|
||||
test_func = func;
|
||||
test_name = name || '';
|
||||
}
|
||||
|
||||
|
||||
this.expect = function(parameters, expected_value) {
|
||||
// multi-parameter calls not supported (I don't need them now).
|
||||
var result = test_func(parameters);
|
||||
// proper array checking is a pain. i'll do it later, compare as strings now :P (fails under IE, I guess)
|
||||
if ((result === expected_value) || (expected_value instanceof Array && result.join(', ') == expected_value.join(', '))) {
|
||||
n_succeeded += 1;
|
||||
} else {
|
||||
n_failed += 1;
|
||||
failures.push([test_name, parameters, expected_value, result]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.results_raw = function() {
|
||||
var results = '';
|
||||
if (n_failed === 0) {
|
||||
if (n_succeeded === 0) {
|
||||
results = 'No tests run.';
|
||||
} else {
|
||||
results = 'All ' + n_succeeded + ' tests passed.';
|
||||
}
|
||||
} else {
|
||||
for (var i = 0 ; i < failures.length; i++) {
|
||||
var f = failures[i];
|
||||
if (f[0]) {
|
||||
f[0] = f[0] + ' ';
|
||||
}
|
||||
results += '---- ' + f[0] + 'input -------\n' + this.prettyprint(f[1]) + '\n';
|
||||
results += '---- ' + f[0] + 'expected ----\n' + this.prettyprint(f[2]) + '\n';
|
||||
results += '---- ' + f[0] + 'output ------\n' + this.prettyprint(f[3]) + '\n\n';
|
||||
|
||||
}
|
||||
results += n_failed + ' tests failed.\n';
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
this.results = function() {
|
||||
return this.lazy_escape(this.results_raw());
|
||||
}
|
||||
|
||||
|
||||
this.prettyprint = function(something, quote_strings) {
|
||||
var type = typeof something;
|
||||
switch(type.toLowerCase()) {
|
||||
case 'string':
|
||||
if (quote_strings) {
|
||||
return "'" + something.replace("'", "\\'") + "'";
|
||||
} else {
|
||||
return something;
|
||||
}
|
||||
case 'number':
|
||||
return '' + something;
|
||||
case 'boolean':
|
||||
return something ? 'true' : 'false';
|
||||
case 'undefined':
|
||||
return 'undefined';
|
||||
case 'object':
|
||||
if (something instanceof Array) {
|
||||
var x = [];
|
||||
var expected_index = 0;
|
||||
for (k in something) {
|
||||
if (k == expected_index) {
|
||||
x.push(this.prettyprint(something[k], true));
|
||||
expected_index += 1;
|
||||
} else {
|
||||
x.push('\n' + k + ': ' + this.prettyprint(something[k], true));
|
||||
}
|
||||
}
|
||||
return '[' + x.join(', ') + ']';
|
||||
} else {
|
||||
return 'object: ' + something;
|
||||
}
|
||||
default:
|
||||
return type + ': ' + something;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.lazy_escape = function (str) {
|
||||
return str.replace(/</g, '<').replace(/\>/g, '>').replace(/\n/g, '<br />');
|
||||
}
|
||||
|
||||
|
||||
this.log = function () {
|
||||
if (window.console) {
|
||||
if (console.firebug) {
|
||||
console.log.apply(console, Array.prototype.slice.call(arguments));
|
||||
} else {
|
||||
console.log.call(console, Array.prototype.slice.call(arguments));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user