~ubuntu-branches/debian/sid/bluefish/sid

« back to all changes in this revision

Viewing changes to data/jsbeautifier/unpackers/packer.py

  • Committer: Package Import Robot
  • Author(s): Daniel Leidert
  • Date: 2013-05-09 14:36:58 UTC
  • mfrom: (17.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130509143658-kgqxj5c23oi0lk20
Tags: 2.2.4-2
* debian/control (Standards-Version): Bumped to 3.9.4.
* debian/copyright: Updated.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier
 
3
# by Einar Lielmanis <einar@jsbeautifier.org>
 
4
#
 
5
#     written by Stefano Sanfilippo <a.little.coder@gmail.com>
 
6
#
 
7
# usage:
 
8
#
 
9
# if detect(some_string):
 
10
#     unpacked = unpack(some_string)
 
11
#
 
12
 
 
13
"""Unpacker for Dean Edward's p.a.c.k.e.r"""
 
14
 
 
15
import re
 
16
import string
 
17
from jsbeautifier.unpackers import UnpackingError
 
18
 
 
19
PRIORITY = 1
 
20
 
 
21
def detect(source):
 
22
    """Detects whether `source` is P.A.C.K.E.R. coded."""
 
23
    return source.replace(' ', '').startswith('eval(function(p,a,c,k,e,r')
 
24
 
 
25
def unpack(source):
 
26
    """Unpacks P.A.C.K.E.R. packed js code."""
 
27
    payload, symtab, radix, count = _filterargs(source)
 
28
 
 
29
    if count != len(symtab):
 
30
        raise UnpackingError('Malformed p.a.c.k.e.r. symtab.')
 
31
 
 
32
    try:
 
33
        unbase = Unbaser(radix)
 
34
    except TypeError:
 
35
        raise UnpackingError('Unknown p.a.c.k.e.r. encoding.')
 
36
 
 
37
    def lookup(match):
 
38
        """Look up symbols in the synthetic symtab."""
 
39
        word  = match.group(0)
 
40
        return symtab[unbase(word)] or word
 
41
 
 
42
    source = re.sub(r'\b\w+\b', lookup, payload)
 
43
    return _replacestrings(source)
 
44
 
 
45
def _filterargs(source):
 
46
    """Juice from a source file the four args needed by decoder."""
 
47
    argsregex = (r"}\('(.*)', *(\d+), *(\d+), *'(.*)'\."
 
48
                 r"split\('\|'\), *(\d+), *(.*)\)\)")
 
49
    args = re.search(argsregex, source, re.DOTALL).groups()
 
50
 
 
51
    try:
 
52
        return args[0], args[3].split('|'), int(args[1]), int(args[2])
 
53
    except ValueError:
 
54
        raise UnpackingError('Corrupted p.a.c.k.e.r. data.')
 
55
 
 
56
def _replacestrings(source):
 
57
    """Strip string lookup table (list) and replace values in source."""
 
58
    match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL)
 
59
 
 
60
    if match:
 
61
        varname, strings = match.groups()
 
62
        startpoint = len(match.group(0))
 
63
        lookup = strings.split('","')
 
64
        variable = '%s[%%d]' % varname
 
65
        for index, value in enumerate(lookup):
 
66
            source = source.replace(variable % index, '"%s"' % value)
 
67
        return source[startpoint:]
 
68
    return source
 
69
 
 
70
 
 
71
class Unbaser(object):
 
72
    """Functor for a given base. Will efficiently convert
 
73
    strings to natural numbers."""
 
74
    ALPHABET  = {
 
75
        62 : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
 
76
        95 : (' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
77
              '[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
 
78
    }
 
79
 
 
80
    def __init__(self, base):
 
81
        self.base = base
 
82
 
 
83
        # If base can be handled by int() builtin, let it do it for us
 
84
        if 2 <= base <= 36:
 
85
            self.unbase = lambda string: int(string, base)
 
86
        else:
 
87
            # Build conversion dictionary cache
 
88
            try:
 
89
                self.dictionary = dict((cipher, index) for
 
90
                    index, cipher in enumerate(self.ALPHABET[base]))
 
91
            except KeyError:
 
92
                raise TypeError('Unsupported base encoding.')
 
93
 
 
94
            self.unbase = self._dictunbaser
 
95
 
 
96
    def __call__(self, string):
 
97
        return self.unbase(string)
 
98
 
 
99
    def _dictunbaser(self, string):
 
100
        """Decodes a  value to an integer."""
 
101
        ret = 0
 
102
        for index, cipher in enumerate(string[::-1]):
 
103
            ret += (self.base ** index) * self.dictionary[cipher]
 
104
        return ret