forked from jdavisclark/JsFormat
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
switching to latest python jsbeautifier
- Loading branch information
Showing
20 changed files
with
1,351 additions
and
104 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Empty file :) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import re | ||
import unittest | ||
import jsbeautifier | ||
|
||
class TestJSBeautifierIndentation(unittest.TestCase): | ||
def test_tabs(self): | ||
test_fragment = self.decodesto | ||
|
||
self.options.indent_with_tabs = 1; | ||
test_fragment('{tabs()}', "{\n\ttabs()\n}"); | ||
|
||
def test_function_indent(self): | ||
test_fragment = self.decodesto | ||
|
||
self.options.indent_with_tabs = 1; | ||
self.options.keep_function_indentation = 1; | ||
test_fragment('var foo = function(){ bar() }();', "var foo = function() {\n\tbar()\n}();"); | ||
|
||
self.options.tabs = 1; | ||
self.options.keep_function_indentation = 0; | ||
test_fragment('var foo = function(){ baz() }();', "var foo = function() {\n\tbaz()\n}();"); | ||
|
||
def decodesto(self, input, expectation=None): | ||
self.assertEqual( | ||
jsbeautifier.beautify(input, self.options), expectation or input) | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
options = jsbeautifier.default_options() | ||
options.indent_size = 4 | ||
options.indent_char = ' ' | ||
options.preserve_newlines = True | ||
options.jslint_happy = False | ||
options.keep_array_indentation = False | ||
options.brace_style = 'collapse' | ||
options.indent_level = 0 | ||
|
||
cls.options = options | ||
cls.wrapregex = re.compile('^(.+)$', re.MULTILINE) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# UNPACKERS SPECIFICATIONS | ||
|
||
Nothing very difficult: an unpacker is a submodule placed in the directory | ||
where this file was found. Each unpacker must define three symbols: | ||
|
||
* `PRIORITY` : integer number expressing the priority in applying this | ||
unpacker. Lower number means higher priority. | ||
Makes sense only if a source file has been packed with | ||
more than one packer. | ||
* `detect(source)` : returns `True` if source is packed, otherwise, `False`. | ||
* `unpack(source)` : takes a `source` string and unpacks it. Must always return | ||
valid JavaScript. That is to say, your code should look | ||
like: | ||
|
||
``` | ||
if detect(source): | ||
return do_your_fancy_things_with(source) | ||
else: | ||
return source | ||
``` | ||
|
||
*You can safely define any other symbol in your module, as it will be ignored.* | ||
|
||
`__init__` code will automatically load new unpackers, without any further step | ||
to be accomplished. Simply drop it in this directory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# | ||
# General code for JSBeautifier unpackers infrastructure. See README.specs | ||
# written by Stefano Sanfilippo <a.little.coder@gmail.com> | ||
# | ||
|
||
"""General code for JSBeautifier unpackers infrastructure.""" | ||
|
||
import pkgutil | ||
import re | ||
from jsbeautifier.unpackers import evalbased | ||
|
||
# NOTE: AT THE MOMENT, IT IS DEACTIVATED FOR YOUR SECURITY: it runs js! | ||
BLACKLIST = ['jsbeautifier.unpackers.evalbased'] | ||
|
||
class UnpackingError(Exception): | ||
"""Badly packed source or general error. Argument is a | ||
meaningful description.""" | ||
pass | ||
|
||
def getunpackers(): | ||
"""Scans the unpackers dir, finds unpackers and add them to UNPACKERS list. | ||
An unpacker will be loaded only if it is a valid python module (name must | ||
adhere to naming conventions) and it is not blacklisted (i.e. inserted | ||
into BLACKLIST.""" | ||
path = __path__ | ||
prefix = __name__ + '.' | ||
unpackers = [] | ||
interface = ['unpack', 'detect', 'PRIORITY'] | ||
for _importer, modname, _ispkg in pkgutil.iter_modules(path, prefix): | ||
if 'tests' not in modname and modname not in BLACKLIST: | ||
try: | ||
module = __import__(modname, fromlist=interface) | ||
except ImportError: | ||
raise UnpackingError('Bad unpacker: %s' % modname) | ||
else: | ||
unpackers.append(module) | ||
|
||
return sorted(unpackers, key = lambda mod: mod.PRIORITY) | ||
|
||
UNPACKERS = getunpackers() | ||
|
||
def run(source, evalcode=False): | ||
"""Runs the applicable unpackers and return unpacked source as a string.""" | ||
for unpacker in [mod for mod in UNPACKERS if mod.detect(source)]: | ||
source = unpacker.unpack(source) | ||
if evalcode and evalbased.detect(source): | ||
source = evalbased.unpack(source) | ||
return source | ||
|
||
def filtercomments(source): | ||
"""NOT USED: strips trailing comments and put them at the top.""" | ||
trailing_comments = [] | ||
comment = True | ||
|
||
while comment: | ||
if re.search(r'^\s*\/\*', source): | ||
comment = source[0, source.index('*/') + 2] | ||
elif re.search(r'^\s*\/\/', source): | ||
comment = re.search(r'^\s*\/\/', source).group(0) | ||
else: | ||
comment = None | ||
|
||
if comment: | ||
source = re.sub(r'^\s+', '', source[len(comment):]) | ||
trailing_comments.append(comment) | ||
|
||
return '\n'.join(trailing_comments) + source |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# | ||
# Unpacker for eval() based packers, a part of javascript beautifier | ||
# by Einar Lielmanis <einar@jsbeautifier.org> | ||
# | ||
# written by Stefano Sanfilippo <a.little.coder@gmail.com> | ||
# | ||
# usage: | ||
# | ||
# if detect(some_string): | ||
# unpacked = unpack(some_string) | ||
# | ||
|
||
"""Unpacker for eval() based packers: runs JS code and returns result. | ||
Works only if a JS interpreter (e.g. Mozilla's Rhino) is installed and | ||
properly set up on host.""" | ||
|
||
from subprocess import PIPE, Popen | ||
|
||
PRIORITY = 3 | ||
|
||
def detect(source): | ||
"""Detects if source is likely to be eval() packed.""" | ||
return source.strip().lower().startswith('eval(function(') | ||
|
||
def unpack(source): | ||
"""Runs source and return resulting code.""" | ||
return jseval('print %s;' % source[4:]) if detect(source) else source | ||
|
||
# In case of failure, we'll just return the original, without crashing on user. | ||
def jseval(script): | ||
"""Run code in the JS interpreter and return output.""" | ||
try: | ||
interpreter = Popen(['js'], stdin=PIPE, stdout=PIPE) | ||
except OSError: | ||
return script | ||
result, errors = interpreter.communicate(script) | ||
if interpreter.poll() or errors: | ||
return script | ||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# | ||
# simple unpacker/deobfuscator for scripts messed up with | ||
# javascriptobfuscator.com | ||
# | ||
# written by Einar Lielmanis <einar@jsbeautifier.org> | ||
# rewritten in Python by Stefano Sanfilippo <a.little.coder@gmail.com> | ||
# | ||
# Will always return valid javascript: if `detect()` is false, `code` is | ||
# returned, unmodified. | ||
# | ||
# usage: | ||
# | ||
# if javascriptobfuscator.detect(some_string): | ||
# some_string = javascriptobfuscator.unpack(some_string) | ||
# | ||
|
||
"""deobfuscator for scripts messed up with JavascriptObfuscator.com""" | ||
|
||
import re | ||
|
||
PRIORITY = 1 | ||
|
||
def smartsplit(code): | ||
"""Split `code` at " symbol, only if it is not escaped.""" | ||
strings = [] | ||
pos = 0 | ||
while pos < len(code): | ||
if code[pos] == '"': | ||
word = '' # new word | ||
pos += 1 | ||
while pos < len(code): | ||
if code[pos] == '"': | ||
break | ||
if code[pos] == '\\': | ||
word += '\\' | ||
pos += 1 | ||
word += code[pos] | ||
pos += 1 | ||
strings.append('"%s"' % word) | ||
pos += 1 | ||
return strings | ||
|
||
def detect(code): | ||
"""Detects if `code` is JavascriptObfuscator.com packed.""" | ||
# prefer `is not` idiom, so that a true boolean is returned | ||
return (re.search(r'^var _0x[a-f0-9]+ ?\= ?\[', code) is not None) | ||
|
||
def unpack(code): | ||
"""Unpacks JavascriptObfuscator.com packed code.""" | ||
if detect(code): | ||
matches = re.search(r'var (_0x[a-f\d]+) ?\= ?\[(.*?)\];', code) | ||
if matches: | ||
variable = matches.group(1) | ||
dictionary = smartsplit(matches.group(2)) | ||
code = code[len(matches.group(0)):] | ||
for key, value in enumerate(dictionary): | ||
code = code.replace(r'%s[%s]' % (variable, key), value) | ||
return code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# | ||
# deobfuscator for scripts messed up with myobfuscate.com | ||
# by Einar Lielmanis <einar@jsbeautifier.org> | ||
# | ||
# written by Stefano Sanfilippo <a.little.coder@gmail.com> | ||
# | ||
# usage: | ||
# | ||
# if detect(some_string): | ||
# unpacked = unpack(some_string) | ||
# | ||
|
||
# CAVEAT by Einar Lielmanis | ||
|
||
# | ||
# You really don't want to obfuscate your scripts there: they're tracking | ||
# your unpackings, your script gets turned into something like this, | ||
# as of 2011-08-26: | ||
# | ||
# var _escape = 'your_script_escaped'; | ||
# var _111 = document.createElement('script'); | ||
# _111.src = 'http://api.www.myobfuscate.com/?getsrc=ok' + | ||
# '&ref=' + encodeURIComponent(document.referrer) + | ||
# '&url=' + encodeURIComponent(document.URL); | ||
# var 000 = document.getElementsByTagName('head')[0]; | ||
# 000.appendChild(_111); | ||
# document.write(unescape(_escape)); | ||
# | ||
|
||
"""Deobfuscator for scripts messed up with MyObfuscate.com""" | ||
|
||
import re | ||
import base64 | ||
|
||
# Python 2 retrocompatibility | ||
# pylint: disable=F0401 | ||
# pylint: disable=E0611 | ||
try: | ||
from urllib import unquote | ||
except ImportError: | ||
from urllib.parse import unquote | ||
|
||
from jsbeautifier.unpackers import UnpackingError | ||
|
||
PRIORITY = 1 | ||
|
||
CAVEAT = """// | ||
// Unpacker warning: be careful when using myobfuscate.com for your projects: | ||
// scripts obfuscated by the free online version call back home. | ||
// | ||
""" | ||
|
||
SIGNATURE = (r'["\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F' | ||
r'\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x61\x62\x63\x64\x65' | ||
r'\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75' | ||
r'\x76\x77\x78\x79\x7A\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2B' | ||
r'\x2F\x3D","","\x63\x68\x61\x72\x41\x74","\x69\x6E\x64\x65\x78' | ||
r'\x4F\x66","\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","' | ||
r'\x6C\x65\x6E\x67\x74\x68"]') | ||
|
||
def detect(source): | ||
"""Detects MyObfuscate.com packer.""" | ||
return SIGNATURE in source | ||
|
||
def unpack(source): | ||
"""Unpacks js code packed with MyObfuscate.com""" | ||
if not detect(source): | ||
return source | ||
payload = unquote(_filter(source)) | ||
match = re.search(r"^var _escape\='<script>(.*)<\/script>'", | ||
payload, re.DOTALL) | ||
polished = match.group(1) if match else source | ||
return CAVEAT + polished | ||
|
||
def _filter(source): | ||
"""Extracts and decode payload (original file) from `source`""" | ||
try: | ||
varname = re.search(r'eval\(\w+\(\w+\((\w+)\)\)\);', source).group(1) | ||
reverse = re.search(r"var +%s *\= *'(.*)';" % varname, source).group(1) | ||
except AttributeError: | ||
raise UnpackingError('Malformed MyObfuscate data.') | ||
try: | ||
return base64.b64decode(reverse[::-1].encode('utf8')).decode('utf8') | ||
except TypeError: | ||
raise UnpackingError('MyObfuscate payload is not base64-encoded.') |
Oops, something went wrong.