#!/usr/bin/env python

__description__ = 'BIFF plugin for oledump.py'
__author__ = 'Didier Stevens'
__version__ = '0.0.22'
__date__ = '2021/02/23'

"""

Source code put in public domain by Didier Stevens, no Copyright
https://DidierStevens.com
Use at your own risk

History:
  2014/11/15: start
  2014/11/21: changed interface: added options; added options -a (asciidump) and -s (strings)
  2017/12/10: 0.0.2 added optparse & option -o
  2017/12/12: added option -f
  2017/12/13: added 0x support for option -f
  2018/10/24: 0.0.3 started coding Excel 4.0 macro support
  2018/10/25: continue
  2018/10/26: continue
  2019/01/05: 0.0.4 added option -x
  2019/03/06: 0.0.5 enhanced parsing of formula expressions
  2019/11/05: 0.0.6 Python 3 support
  2020/02/23: 0.0.7 performance improvement
  2020/03/08: 0.0.8 added options -X and -d
  2020/03/09: 0.0.9 improved formula parsing; Python 3 bugfixes
  2020/03/27: 0.0.10 improved formula parsing and debug modes. (by @JohnLaTwC)
              05219f8c047f1dff861634c4b50d4f6978c87c35f4c14d21ee9d757cac9280cf (ptgConcat)
              94b26003699efba54ced98006379a230d1154f340589cc89af7d0cbedb861a53 (encoding, ptgFuncVarA, ptgNameX)
              d3c1627ca2775d98717eb1abf2b70aedf383845d87993c6b924f2f55d9d4d696 (ptgArea)
              01761b06c24baa818b0a75059e745871246a5e9c6ce0243ad96e8632342cbb59 (ptgFuncVarA)
              d3c1627ca2775d98717eb1abf2b70aedf383845d87993c6b924f2f55d9d4d696 (ptgFunc)
              1d48a42a0b06a087e966b860c8f293a9bf57da8d70f5f83c61242afc5b81eb4f (=SELECT($B$1:$1000:$1000:$B:$B,$B$1))
  2020/04/06: 0.0.11 Python 2 bugfixes; password protect record FILEPASS
  2020/05/16: 0.0.12 option -c
  2020/05/17: option -r
  2020/05/18: continue
  2020/05/20: 0.0.13 option -j
  2020/05/21: 0.0.14 improved parsing for a83890bbc081b9ec839c9a32ec06eae6f549a0f85fe0a30751ef229a58e440af, bc39d3bb128f329d95393bf0a4f6ec813356e847a00794c18258bfa48df6937f, 002a8371570487bc81eec4aeea9fdfb7
  2020/05/22: 0.0.15 Python 3 fix STRING record 0x207
  2020/05/26: 0.0.16 added logic for reserved bits in BOUNDSHEET
  2020/07/17: 0.0.17 added option --statistics
  2020/10/03: 0.0.18 improved FILEPASS record handling
  2020/12/03: 0.0.19 added detection of BIFF5/BIFF7 and FILEPASS record parsing
  2020/12/19: 0.0.20 added FILEPASS XOR Obfuscation password cracking (option -w)
  2021/02/06: 0.0.21 added option --hexrecord, added option -D
  2021/02/07: added key extraction for XOR obfuscation
  2021/02/09: added recordsNotXORObfuscated
  2021/02/21: 0.0.22 bug fix
  2021/02/23: added PASSWORD record cracking

Todo:
  updated parsing of records for BIFF5 record format
"""

import struct
import re
import optparse
import json

DEFAULT_SEPARATOR = ','
QUOTE = '"'

def P23Decode(value):
    if sys.version_info[0] > 2:
        try:
            return value.decode('utf-8')
        except UnicodeDecodeError as u:
            return value.decode('windows-1252')
    else:
        return value

def ToString(value):
    if isinstance(value, str):
        return value
    else:
        return str(value)

def Quote(value, separator, quote):
    value = ToString(value)
    if len(value) > 1 and value[0] == quote and value[-1] == quote:
        return value
    if separator in value or value == '':
        return quote + value + quote
    else:
        return value

def MakeCSVLine(row, separator, quote):
    return separator.join([Quote(value, separator, quote) for value in row])

def CombineHexASCII(hexDump, asciiDump, length):
    if hexDump == '':
        return ''
    return hexDump + '  ' + (' ' * (3 * (length - len(asciiDump)))) + asciiDump

def HexASCII(data, length=16):
    result = []
    if len(data) > 0:
        hexDump = ''
        asciiDump = ''
        for i, b in enumerate(data):
            if i % length == 0:
                if hexDump != '':
                    result.append(CombineHexASCII(hexDump, asciiDump, length))
                hexDump = '%08X:' % i
                asciiDump = ''
            hexDump += ' %02X' % P23Ord(b)
            asciiDump += IFF(P23Ord(b) >= 32, P23Chr(b), '.')
        result.append(CombineHexASCII(hexDump, asciiDump, length))
    return result

def StringsASCII(data):
    return list(map(P23Decode, re.findall(b'[^\x00-\x08\x0A-\x1F\x7F-\xFF]{4,}', data)))

def StringsUNICODE(data):
    return [P23Decode(foundunicodestring.replace(b'\x00', b'')) for foundunicodestring, dummy in re.findall(b'(([^\x00-\x08\x0A-\x1F\x7F-\xFF]\x00){4,})', data)]

def Strings(data, encodings='sL'):
    dStrings = {}
    for encoding in encodings:
        if encoding == 's':
            dStrings[encoding] = StringsASCII(data)
        elif encoding == 'L':
            dStrings[encoding] = StringsUNICODE(data)
    return dStrings

def ContainsWP23Ord(word, expression):
    return struct.pack('<H', word) in expression

# https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/75afd109-b1ce-4511-b56f-2d63116f6647
def ParseArea(expression):
    formatcodes = 'HHHH'
    formatsize = struct.calcsize(formatcodes)
    if len(expression) < formatsize:
        return '*ERROR*'
    row1,row2,col1,col2 = struct.unpack(formatcodes, expression[0:formatsize])
    row1Relative = col1 & 0x8000
    col1Relative = col1 & 0x4000
    row2Relative = col2 & 0x8000
    col2Relative = col2 & 0x4000
    col1 = col1 & 0x3FFF
    col2 = col2 & 0x3FFF

    if row1Relative:
        row1indicator = '~'
    else:
        row1indicator = ''
        row1 += 1
    if col1Relative:
        col1indicator = '~'
    else:
        col1indicator = ''
        col1 += 1
    if row2Relative:
        row2indicator = '~'
    else:
        row2indicator = ''
        row2 += 1
    if col2Relative:
        col2indicator = '~'
    else:
        col2indicator = ''
        col2 += 1

    if row1 == row2 and col2 >=256:
        return 'R%s%d' % (row1indicator, row1)
    if col1 == col2 and row2 >= 65536:
        return 'C%s%d' % (col1indicator, col1)

    return 'R%s%dC%s%d' % (row1indicator, row1, col1indicator, col1)

# https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad
def ParseLocRelU(expression):
    row = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
    column = P23Ord(expression[2]) + P23Ord(expression[3]) * 0x100
    rowRelative = False #column & 0x8000
    colRelative = False #column & 0x4000
    column = column & 0x3FFF
    if rowRelative:
        rowindicator = '~'
    else:
        rowindicator = ''
        row += 1
    if colRelative:
        colindicator = '~'
    else:
        colindicator = ''
        column += 1
    return 'R%s%dC%s%d' % (rowindicator, row, colindicator, column)

#https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad
def ParseLoc(expression, cellrefformat, ignoreRelFlags=False):
    formatcodes = 'HH'
    formatsize = struct.calcsize(formatcodes)
    row, column = struct.unpack(formatcodes, expression[0:formatsize])
    if ignoreRelFlags:
        rowRelative = False
        colRelative = False
    else:
        rowRelative = column & 0x8000
        colRelative = column & 0x4000
    column = column & 0x3FFF
    if rowRelative:
        rowindicator = '~'
    else:
        rowindicator = ''
        row += 1
    if colRelative:
        colindicator = '~'
    else:
        colindicator = ''
        column += 1
    if cellrefformat.upper() == 'RC':
        result = 'R%s%dC%s%d' % (rowindicator, row, colindicator, column)
    elif cellrefformat.upper() == 'LN':
        column -= 1
        first = int(column / 26)
        second = column % 26
        if first == 0:
            result = ''
        else:
            result = chr(first + ord('A'))
        result += chr(second + ord('A'))
        result = '%s%d' % (result, row)
    else:
        raise Exception('Unknown cell reference format: %s' % cellrefformat)
    return result, expression[formatsize:]

def StackBinary(stack, operator):
    if len(stack) < 2:
        stack.append('*STACKERROR* not enough operands for operator: %s' % operator)
    else:
        operand2 = stack.pop()
        operand1 = stack.pop()
        stack.append(operand1 + operator + operand2)

def StackFunction(stack, function, arity):
    if len(stack) < arity:
        stack.append('*STACKERROR* not enough arguments for function: %s' % function)
    else:
        arguments = []
        for i in range(arity):
            arguments.insert(0, stack.pop())
        if function == 'User Defined Function':
            function = arguments[0]
            arguments = arguments[1:]
        stack.append('%s(%s)' % (function, ','.join(arguments)))

def ParseExpression(expression, definesNames, sheetNames, cellrefformat):
    dTokens = {
0x01: 'ptgExp',
0x02: 'ptgTbl',
0x03: 'ptgAdd',
0x04: 'ptgSub',
0x05: 'ptgMul',
0x06: 'ptgDiv',
0x07: 'ptgPower',
0x08: 'ptgConcat',
0x09: 'ptgLT',
0x0A: 'ptgLE',
0x0B: 'ptgEQ',
0x0C: 'ptgGE',
0x0D: 'ptgGT',
0x0E: 'ptgNE',
0x0F: 'ptgIsect',
0x10: 'ptgUnion',
0x11: 'ptgRange',
0x12: 'ptgUplus',
0x13: 'ptgUminus',
0x14: 'ptgPercent',
0x15: 'ptgParen',
0x16: 'ptgMissArg',
0x17: 'ptgStr',
0x18: 'ptgExtend',
0x19: 'ptgAttr',
0x1A: 'ptgSheet',
0x1B: 'ptgEndSheet',
0x1C: 'ptgErr',
0x1D: 'ptgBool',
0x1E: 'ptgInt',
0x1F: 'ptgNum',
0x20: 'ptgArray',
0x21: 'ptgFunc',
0x22: 'ptgFuncVar',
0x23: 'ptgName',
0x24: 'ptgRef',
0x25: 'ptgArea',
0x26: 'ptgMemArea',
0x27: 'ptgMemErr',
0x28: 'ptgMemNoMem',
0x29: 'ptgMemFunc',
0x2A: 'ptgRefErr',
0x2B: 'ptgAreaErr',
0x2C: 'ptgRefN',
0x2D: 'ptgAreaN',
0x2E: 'ptgMemAreaN',
0x2F: 'ptgMemNoMemN',
0x39: 'ptgNameX',
0x3A: 'ptgRef3d',
0x3B: 'ptgArea3d',
0x3C: 'ptgRefErr3d',
0x3D: 'ptgAreaErr3d',
0x40: 'ptgArrayV',
0x41: 'ptgFuncV',
0x42: 'ptgFuncVarV',
0x43: 'ptgNameV',
0x44: 'ptgRefV',
0x45: 'ptgAreaV',
0x46: 'ptgMemAreaV',
0x47: 'ptgMemErrV',
0x48: 'ptgMemNoMemV',
0x49: 'ptgMemFuncV',
0x4A: 'ptgRefErrV',
0x4B: 'ptgAreaErrV',
0x4C: 'ptgRefNV',
0x4D: 'ptgAreaNV',
0x4E: 'ptgMemAreaNV',
0x4F: 'ptgMemNoMemNV',
0x58: 'ptgFuncCEV',
0x59: 'ptgNameXV',
0x5A: 'ptgRef3dV',
0x5B: 'ptgArea3dV',
0x5C: 'ptgRefErr3dV',
0x5D: 'ptgAreaErr3dV',
0x60: 'ptgArrayA',
0x61: 'ptgFuncA',
0x62: 'ptgFuncVarA',
0x63: 'ptgNameA',
0x64: 'ptgRefA',
0x65: 'ptgAreaA',
0x66: 'ptgMemAreaA',
0x67: 'ptgMemErrA',
0x68: 'ptgMemNoMemA',
0x69: 'ptgMemFuncA',
0x6A: 'ptgRefErrA',
0x6B: 'ptgAreaErrA',
0x6C: 'ptgRefNA',
0x6D: 'ptgAreaNA',
0x6E: 'ptgMemAreaNA',
0x6F: 'ptgMemNoMemNA',
0x78: 'ptgFuncCEA',
0x79: 'ptgNameXA',
0x7A: 'ptgRef3dA',
0x7B: 'ptgArea3dA',
0x7C: 'ptgRefErr3dA',
0x7D: 'ptgAreaErr3dA',
}

    dFunctions = {
#https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/00b5dd7d-51ca-4938-b7b7-483fe0e5933b
0x0000: 'COUNT',
0x0001: 'IF',
0x0002: 'ISNA',
0x0003: 'ISERROR',
0x0004: 'SUM',
0x0005: 'AVERAGE',
0x0006: 'MIN',
0x0007: 'MAX',
0x0008: 'ROW',
0x0009: 'COLUMN',
0x000A: 'NA',
0x000B: 'NPV',
0x000C: 'STDEV',
0x000D: 'DOLLAR',
0x000E: 'FIXED',
0x000F: 'SIN',
0x0010: 'COS',
0x0011: 'TAN',
0x0012: 'ATAN',
0x0013: 'PI',
0x0014: 'SQRT',
0x0015: 'EXP',
0x0016: 'LN',
0x0017: 'LOG10',
0x0018: 'ABS',
0x0019: 'INT',
0x001A: 'SIGN',
0x001B: 'ROUND',
0x001C: 'LOOKUP',
0x001D: 'INDEX',
0x001E: 'REPT',
0x001F: ['MID', 3],
0x0020: 'LEN',
0x0021: 'VALUE',
0x0022: 'TRUE',
0x0023: 'FALSE',
0x0024: 'AND',
0x0025: 'OR',
0x0026: 'NOT',
0x0027: 'MOD',
0x0028: 'DCOUNT',
0x0029: 'DSUM',
0x002A: 'DAVERAGE',
0x002B: 'DMIN',
0x002C: 'DMAX',
0x002D: 'DSTDEV',
0x002E: 'VAR',
0x002F: 'DVAR',
0x0030: 'TEXT',
0x0031: 'LINEST',
0x0032: 'TREND',
0x0033: 'LOGEST',
0x0034: 'GROWTH',
0x0035: 'GOTO',
0x0036: 'HALT',
0x0037: 'RETURN',
0x0038: 'PV',
0x0039: 'FV',
0x003A: 'NPER',
0x003B: 'PMT',
0x003C: 'RATE',
0x003D: 'MIRR',
0x003E: 'IRR',
0x003F: 'RAND',
0x0040: 'MATCH',
0x0041: 'DATE',
0x0042: 'TIME',
0x0043: 'DAY',
0x0044: 'MONTH',
0x0045: 'YEAR',
0x0046: 'WEEKDAY',
0x0047: 'HOUR',
0x0048: 'MINUTE',
0x0049: 'SECOND',
0x004A: ['NOW', 0],
0x004B: 'AREAS',
0x004C: 'ROWS',
0x004D: 'COLUMNS',
0x004E: 'OFFSET',
0x004F: 'ABSREF',
0x0050: 'RELREF',
0x0051: 'ARGUMENT',
0x0052: 'SEARCH',
0x0053: 'TRANSPOSE',
0x0054: 'ERROR',
0x0055: 'STEP',
0x0056: 'TYPE',
0x0057: 'ECHO',
0x0058: 'SET.NAME',
0x0059: 'CALLER',
0x005A: 'DEREF',
0x005B: 'WINDOWS',
0x005C: 'SERIES',
0x005D: 'DOCUMENTS',
0x005E: ['ACTIVE.CELL', 0],
0x005F: 'SELECTION',
0x0060: 'RESULT',
0x0061: 'ATAN2',
0x0062: 'ASIN',
0x0063: 'ACOS',
0x0064: 'CHOOSE',
0x0065: 'HLOOKUP',
0x0066: 'VLOOKUP',
0x0067: 'LINKS',
0x0068: 'INPUT',
0x0069: 'ISREF',
0x006A: 'GET.FORMULA',
0x006B: 'GET.NAME',
0x006C: ['SET.VALUE', 2],
0x006D: 'LOG',
0x006E: 'EXEC',
0x006F: 'CHAR',
0x0070: 'LOWER',
0x0071: 'UPPER',
0x0072: 'PROPER',
0x0073: 'LEFT',
0x0074: 'RIGHT',
0x0075: 'EXACT',
0x0076: 'TRIM',
0x0077: 'REPLACE',
0x0078: 'SUBSTITUTE',
0x0079: 'CODE',
0x007A: 'NAMES',
0x007B: 'DIRECTORY',
0x007C: 'FIND',
0x007D: 'CELL',
0x007E: 'ISERR',
0x007F: 'ISTEXT',
0x0080: 'ISNUMBER',
0x0081: 'ISBLANK',
0x0082: 'T',
0x0083: 'N',
0x0084: 'FOPEN',
0x0085: 'FCLOSE',
0x0086: 'FSIZE',
0x0087: 'FREADLN',
0x0088: 'FREAD',
0x0089: 'FWRITELN',
0x008A: 'FWRITE',
0x008B: 'FPOS',
0x008C: 'DATEVALUE',
0x008D: 'TIMEVALUE',
0x008E: 'SLN',
0x008F: 'SYD',
0x0090: 'DDB',
0x0091: 'GET.DEF',
0x0092: 'REFTEXT',
0x0093: 'TEXTREF',
0x0094: 'INDIRECT',
0x0095: 'REGISTER',
0x0096: 'CALL',
0x0097: 'ADD.BAR',
0x0098: 'ADD.MENU',
0x0099: 'ADD.COMMAND',
0x009A: 'ENABLE.COMMAND',
0x009B: 'CHECK.COMMAND',
0x009C: 'RENAME.COMMAND',
0x009D: 'SHOW.BAR',
0x009E: 'DELETE.MENU',
0x009F: 'DELETE.COMMAND',
0x00A0: 'GET.CHART.ITEM',
0x00A1: 'DIALOG.BOX',
0x00A2: 'CLEAN',
0x00A3: 'MDETERM',
0x00A4: 'MINVERSE',
0x00A5: 'MMULT',
0x00A6: 'FILES',
0x00A7: 'IPMT',
0x00A8: 'PPMT',
0x00A9: 'COUNTA',
0x00AA: 'CANCEL.KEY',
0x00AB: 'FOR',
0x00AC: 'WHILE',
0x00AD: 'BREAK',
0x00AE: ['NEXT', 0],
0x00AF: 'INITIATE',
0x00B0: 'REQUEST',
0x00B1: 'POKE',
0x00B2: 'EXECUTE',
0x00B3: 'TERMINATE',
0x00B4: 'RESTART',
0x00B5: 'HELP',
0x00B6: 'GET.BAR',
0x00B7: 'PRODUCT',
0x00B8: 'FACT',
0x00B9: 'GET.CELL',
0x00BA: 'GET.WORKSPACE',
0x00BB: 'GET.WINDOW',
0x00BC: 'GET.DOCUMENT',
0x00BD: 'DPRODUCT',
0x00BE: 'ISNONTEXT',
0x00BF: 'GET.NOTE',
0x00C0: 'NOTE',
0x00C1: 'STDEVP',
0x00C2: 'VARP',
0x00C3: 'DSTDEVP',
0x00C4: 'DVARP',
0x00C5: 'TRUNC',
0x00C6: 'ISLOGICAL',
0x00C7: 'DCOUNTA',
0x00C8: 'DELETE.BAR',
0x00C9: 'UNREGISTER',
0x00CC: 'USDOLLAR',
0x00CD: 'FINDB',
0x00CE: 'SEARCHB',
0x00CF: 'REPLACEB',
0x00D0: 'LEFTB',
0x00D1: 'RIGHTB',
0x00D2: 'MIDB',
0x00D3: 'LENB',
0x00D4: 'ROUNDUP',
0x00D5: 'ROUNDDOWN',
0x00D6: 'ASC',
0x00D7: 'DBCS',
0x00D8: 'RANK',
0x00DB: 'ADDRESS',
0x00DC: 'DAYS360',
0x00DD: 'TODAY',
0x00DE: 'VDB',
0x00DF: 'ELSE',
0x00E0: 'ELSE.IF',
0x00E1: 'END.IF',
0x00E2: 'FOR.CELL',
0x00E3: 'MEDIAN',
0x00E4: 'SUMPRODUCT',
0x00E5: 'SINH',
0x00E6: 'COSH',
0x00E7: 'TANH',
0x00E8: 'ASINH',
0x00E9: 'ACOSH',
0x00EA: 'ATANH',
0x00EB: 'DGET',
0x00EC: 'CREATE.OBJECT',
0x00ED: 'VOLATILE',
0x00EE: 'LAST.ERROR',
0x00EF: 'CUSTOM.UNDO',
0x00F0: 'CUSTOM.REPEAT',
0x00F1: 'FORMULA.CONVERT',
0x00F2: 'GET.LINK.INFO',
0x00F3: 'TEXT.BOX',
0x00F4: 'INFO',
0x00F5: 'GROUP',
0x00F6: 'GET.OBJECT',
0x00F7: 'DB',
0x00F8: 'PAUSE',
0x00FB: 'RESUME',
0x00FC: 'FREQUENCY',
0x00FD: 'ADD.TOOLBAR',
0x00FE: 'DELETE.TOOLBAR',
0x00FF: 'User Defined Function',
0x0100: 'RESET.TOOLBAR',
0x0101: 'EVALUATE',
0x0102: 'GET.TOOLBAR',
0x0103: 'GET.TOOL',
0x0104: 'SPELLING.CHECK',
0x0105: 'ERROR.TYPE',
0x0106: 'APP.TITLE',
0x0107: 'WINDOW.TITLE',
0x0108: 'SAVE.TOOLBAR',
0x0109: 'ENABLE.TOOL',
0x010A: 'PRESS.TOOL',
0x010B: 'REGISTER.ID',
0x010C: 'GET.WORKBOOK',
0x010D: 'AVEDEV',
0x010E: 'BETADIST',
0x010F: 'GAMMALN',
0x0110: 'BETAINV',
0x0111: 'BINOMDIST',
0x0112: 'CHIDIST',
0x0113: 'CHIINV',
0x0114: 'COMBIN',
0x0115: 'CONFIDENCE',
0x0116: 'CRITBINOM',
0x0117: 'EVEN',
0x0118: 'EXPONDIST',
0x0119: 'FDIST',
0x011A: 'FINV',
0x011B: 'FISHER',
0x011C: 'FISHERINV',
0x011D: 'FLOOR',
0x011E: 'GAMMADIST',
0x011F: 'GAMMAINV',
0x0120: 'CEILING',
0x0121: 'HYPGEOMDIST',
0x0122: 'LOGNORMDIST',
0x0123: 'LOGINV',
0x0124: 'NEGBINOMDIST',
0x0125: 'NORMDIST',
0x0126: 'NORMSDIST',
0x0127: 'NORMINV',
0x0128: 'NORMSINV',
0x0129: 'STANDARDIZE',
0x012A: 'ODD',
0x012B: 'PERMUT',
0x012C: 'POISSON',
0x012D: 'TDIST',
0x012E: 'WEIBULL',
0x012F: 'SUMXMY2',
0x0130: 'SUMX2MY2',
0x0131: 'SUMX2PY2',
0x0132: 'CHITEST',
0x0133: 'CORREL',
0x0134: 'COVAR',
0x0135: 'FORECAST',
0x0136: 'FTEST',
0x0137: 'INTERCEPT',
0x0138: 'PEARSON',
0x0139: 'RSQ',
0x013A: 'STEYX',
0x013B: 'SLOPE',
0x013C: 'TTEST',
0x013D: 'PROB',
0x013E: 'DEVSQ',
0x013F: 'GEOMEAN',
0x0140: 'HARMEAN',
0x0141: 'SUMSQ',
0x0142: 'KURT',
0x0143: 'SKEW',
0x0144: 'ZTEST',
0x0145: 'LARGE',
0x0146: 'SMALL',
0x0147: 'QUARTILE',
0x0148: 'PERCENTILE',
0x0149: 'PERCENTRANK',
0x014A: 'MODE',
0x014B: 'TRIMMEAN',
0x014C: 'TINV',
0x014E: 'MOVIE.COMMAND',
0x014F: 'GET.MOVIE',
0x0150: 'CONCATENATE',
0x0151: 'POWER',
0x0152: 'PIVOT.ADD.DATA',
0x0153: 'GET.PIVOT.TABLE',
0x0154: 'GET.PIVOT.FIELD',
0x0155: 'GET.PIVOT.ITEM',
0x0156: 'RADIANS',
0x0157: 'DEGREES',
0x0158: 'SUBTOTAL',
0x0159: 'SUMIF',
0x015A: 'COUNTIF',
0x015B: 'COUNTBLANK',
0x015C: 'SCENARIO.GET',
0x015D: 'OPTIONS.LISTS.GET',
0x015E: 'ISPMT',
0x015F: 'DATEDIF',
0x0160: 'DATESTRING',
0x0161: 'NUMBERSTRING',
0x0162: 'ROMAN',
0x0163: 'OPEN.DIALOG',
0x0164: 'SAVE.DIALOG',
0x0165: 'VIEW.GET',
0x0166: 'GETPIVOTDATA',
0x0167: 'HYPERLINK',
0x0168: 'PHONETIC',
0x0169: 'AVERAGEA',
0x016A: 'MAXA',
0x016B: 'MINA',
0x016C: 'STDEVPA',
0x016D: 'VARPA',
0x016E: 'STDEVA',
0x016F: 'VARA',
0x0170: 'BAHTTEXT',
0x0171: 'THAIDAYOFWEEK',
0x0172: 'THAIDIGIT',
0x0173: 'THAIMONTHOFYEAR',
0x0174: 'THAINUMSOUND',
0x0175: 'THAINUMSTRING',
0x0176: 'THAISTRINGLENGTH',
0x0177: 'ISTHAIDIGIT',
0x0178: 'ROUNDBAHTDOWN',
0x0179: 'ROUNDBAHTUP',
0x017A: 'THAIYEAR',
0x017B: 'RTD',
0x01E0: 'IFERROR',

#https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/0b8acba5-86d2-4854-836e-0afaee743d44
0x8000: 'BEEP',
0x8001: 'OPEN',
0x8002: 'OPEN.LINKS',
0x8003: 'CLOSE.ALL',
0x8004: 'SAVE',
0x8005: 'SAVE.AS',
0x8006: 'FILE.DELETE',
0x8007: 'PAGE.SETUP',
0x8008: 'PRINT',
0x8009: 'PRINTER.SETUP',
0x800A: 'QUIT',
0x800B: 'NEW.WINDOW',
0x800C: 'ARRANGE.ALL',
0x800D: 'WINDOW.SIZE',
0x800E: 'WINDOW.MOVE',
0x800F: 'FULL',
0x8010: 'CLOSE',
0x8011: 'RUN',
0x8016: 'SET.PRINT.AREA',
0x8017: 'SET.PRINT.TITLES',
0x8018: 'SET.PAGE.BREAK',
0x8019: 'REMOVE.PAGE.BREAK',
0x801A: 'FONT',
0x801B: 'DISPLAY',
0x801C: 'PROTECT.DOCUMENT',
0x801D: 'PRECISION',
0x801E: 'A1.R1C1',
0x801F: 'CALCULATE.NOW',
0x8020: 'CALCULATION',
0x8022: 'DATA.FIND',
0x8023: 'EXTRACT',
0x8024: 'DATA.DELETE',
0x8025: 'SET.DATABASE',
0x8026: 'SET.CRITERIA',
0x8027: 'SORT',
0x8028: 'DATA.SERIES',
0x8029: 'TABLE',
0x802A: 'FORMAT.NUMBER',
0x802B: 'ALIGNMENT',
0x802C: 'STYLE',
0x802D: 'BORDER',
0x802E: 'CELL.PROTECTION',
0x802F: 'COLUMN.WIDTH',
0x8030: 'UNDO',
0x8031: 'CUT',
0x8032: 'COPY',
0x8033: 'PASTE',
0x8034: 'CLEAR',
0x8035: 'PASTE.SPECIAL',
0x8036: 'EDIT.DELETE',
0x8037: 'INSERT',
0x8038: 'FILL.RIGHT',
0x8039: 'FILL.DOWN',
0x803D: 'DEFINE.NAME',
0x803E: 'CREATE.NAMES',
0x803F: 'FORMULA.GOTO',
0x8040: 'FORMULA.FIND',
0x8041: 'SELECT.LAST.CELL',
0x8042: 'SHOW.ACTIVE.CELL',
0x8043: 'GALLERY.AREA',
0x8044: 'GALLERY.BAR',
0x8045: 'GALLERY.COLUMN',
0x8046: 'GALLERY.LINE',
0x8047: 'GALLERY.PIE',
0x8048: 'GALLERY.SCATTER',
0x8049: 'COMBINATION',
0x804A: 'PREFERRED',
0x804B: 'ADD.OVERLAY',
0x804C: 'GRIDLINES',
0x804D: 'SET.PREFERRED',
0x804E: 'AXES',
0x804F: 'LEGEND',
0x8050: 'ATTACH.TEXT',
0x8051: 'ADD.ARROW',
0x8052: 'SELECT.CHART',
0x8053: 'SELECT.PLOT.AREA',
0x8054: 'PATTERNS',
0x8055: 'MAIN.CHART',
0x8056: 'OVERLAY',
0x8057: 'SCALE',
0x8058: 'FORMAT.LEGEND',
0x8059: 'FORMAT.TEXT',
0x805A: 'EDIT.REPEAT',
0x805B: 'PARSE',
0x805C: 'JUSTIFY',
0x805D: 'HIDE',
0x805E: 'UNHIDE',
0x805F: 'WORKSPACE',
0x8060: 'FORMULA',
0x8061: 'FORMULA.FILL',
0x8062: 'FORMULA.ARRAY',
0x8063: 'DATA.FIND.NEXT',
0x8064: 'DATA.FIND.PREV',
0x8065: 'FORMULA.FIND.NEXT',
0x8066: 'FORMULA.FIND.PREV',
0x8067: 'ACTIVATE',
0x8068: 'ACTIVATE.NEXT',
0x8069: 'ACTIVATE.PREV',
0x806A: 'UNLOCKED.NEXT',
0x806B: 'UNLOCKED.PREV',
0x806C: 'COPY.PICTURE',
0x806D: 'SELECT',
0x806E: 'DELETE.NAME',
0x806F: 'DELETE.FORMAT',
0x8070: 'VLINE',
0x8071: 'HLINE',
0x8072: 'VPAGE',
0x8073: 'HPAGE',
0x8074: 'VSCROLL',
0x8075: 'HSCROLL',
0x8076: 'ALERT',
0x8077: 'NEW',
0x8078: 'CANCEL.COPY',
0x8079: 'SHOW.CLIPBOARD',
0x807A: 'MESSAGE',
0x807C: 'PASTE.LINK',
0x807D: 'APP.ACTIVATE',
0x807E: 'DELETE.ARROW',
0x807F: 'ROW.HEIGHT',
0x8080: 'FORMAT.MOVE',
0x8081: 'FORMAT.SIZE',
0x8082: 'FORMULA.REPLACE',
0x8083: 'SEND.KEYS',
0x8084: 'SELECT.SPECIAL',
0x8085: 'APPLY.NAMES',
0x8086: 'REPLACE.FONT',
0x8087: 'FREEZE.PANES',
0x8088: 'SHOW.INFO',
0x8089: 'SPLIT',
0x808A: 'ON.WINDOW',
0x808B: 'ON.DATA',
0x808C: 'DISABLE.INPUT',
0x808E: 'OUTLINE',
0x808F: 'LIST.NAMES',
0x8090: 'FILE.CLOSE',
0x8091: 'SAVE.WORKBOOK',
0x8092: 'DATA.FORM',
0x8093: 'COPY.CHART',
0x8094: 'ON.TIME',
0x8095: 'WAIT',
0x8096: 'FORMAT.FONT',
0x8097: 'FILL.UP',
0x8098: 'FILL.LEFT',
0x8099: 'DELETE.OVERLAY',
0x809B: 'SHORT.MENUS',
0x809F: 'SET.UPDATE.STATUS',
0x80A1: 'COLOR.PALETTE',
0x80A2: 'DELETE.STYLE',
0x80A3: 'WINDOW.RESTORE',
0x80A4: 'WINDOW.MAXIMIZE',
0x80A6: 'CHANGE.LINK',
0x80A7: 'CALCULATE.DOCUMENT',
0x80A8: 'ON.KEY',
0x80A9: 'APP.RESTORE',
0x80AA: 'APP.MOVE',
0x80AB: 'APP.SIZE',
0x80AC: 'APP.MINIMIZE',
0x80AD: 'APP.MAXIMIZE',
0x80AE: 'BRING.TO.FRONT',
0x80AF: 'SEND.TO.BACK',
0x80B9: 'MAIN.CHART.TYPE',
0x80BA: 'OVERLAY.CHART.TYPE',
0x80BB: 'SELECT.END',
0x80BC: 'OPEN.MAIL',
0x80BD: 'SEND.MAIL',
0x80BE: 'STANDARD.FONT',
0x80BF: 'CONSOLIDATE',
0x80C0: 'SORT.SPECIAL',
0x80C1: 'GALLERY.3D.AREA',
0x80C2: 'GALLERY.3D.COLUMN',
0x80C3: 'GALLERY.3D.LINE',
0x80C4: 'GALLERY.3D.PIE',
0x80C5: 'VIEW.3D',
0x80C6: 'GOAL.SEEK',
0x80C7: 'WORKGROUP',
0x80C8: 'FILL.GROUP',
0x80C9: 'UPDATE.LINK',
0x80CA: 'PROMOTE',
0x80CB: 'DEMOTE',
0x80CC: 'SHOW.DETAIL',
0x80CE: 'UNGROUP',
0x80CF: 'OBJECT.PROPERTIES',
0x80D0: 'SAVE.NEW.OBJECT',
0x80D1: 'SHARE',
0x80D2: 'SHARE.NAME',
0x80D3: 'DUPLICATE',
0x80D4: 'APPLY.STYLE',
0x80D5: 'ASSIGN.TO.OBJECT',
0x80D6: 'OBJECT.PROTECTION',
0x80D7: 'HIDE.OBJECT',
0x80D8: 'SET.EXTRACT',
0x80D9: 'CREATE.PUBLISHER',
0x80DA: 'SUBSCRIBE.TO',
0x80DB: 'ATTRIBUTES',
0x80DC: 'SHOW.TOOLBAR',
0x80DE: 'PRINT.PREVIEW',
0x80DF: 'EDIT.COLOR',
0x80E0: 'SHOW.LEVELS',
0x80E1: 'FORMAT.MAIN',
0x80E2: 'FORMAT.OVERLAY',
0x80E3: 'ON.RECALC',
0x80E4: 'EDIT.SERIES',
0x80E5: 'DEFINE.STYLE',
0x80F0: 'LINE.PRINT',
0x80F3: 'ENTER.DATA',
0x80F9: 'GALLERY.RADAR',
0x80FA: 'MERGE.STYLES',
0x80FB: 'EDITION.OPTIONS',
0x80FC: 'PASTE.PICTURE',
0x80FD: 'PASTE.PICTURE.LINK',
0x80FE: 'SPELLING',
0x8100: 'ZOOM',
0x8103: 'INSERT.OBJECT',
0x8104: 'WINDOW.MINIMIZE',
0x8109: 'SOUND.NOTE',
0x810A: 'SOUND.PLAY',
0x810B: 'FORMAT.SHAPE',
0x810C: 'EXTEND.POLYGON',
0x810D: 'FORMAT.AUTO',
0x8110: 'GALLERY.3D.BAR',
0x8111: 'GALLERY.3D.SURFACE',
0x8112: 'FILL.AUTO',
0x8114: 'CUSTOMIZE.TOOLBAR',
0x8115: 'ADD.TOOL',
0x8116: 'EDIT.OBJECT',
0x8117: 'ON.DOUBLECLICK',
0x8118: 'ON.ENTRY',
0x8119: 'WORKBOOK.ADD',
0x811A: 'WORKBOOK.MOVE',
0x811B: 'WORKBOOK.COPY',
0x811C: 'WORKBOOK.OPTIONS',
0x811D: 'SAVE.WORKSPACE',
0x8120: 'CHART.WIZARD',
0x8121: 'DELETE.TOOL',
0x8122: 'MOVE.TOOL',
0x8123: 'WORKBOOK.SELECT',
0x8124: 'WORKBOOK.ACTIVATE',
0x8125: 'ASSIGN.TO.TOOL',
0x8127: 'COPY.TOOL',
0x8128: 'RESET.TOOL',
0x8129: 'CONSTRAIN.NUMERIC',
0x812A: 'PASTE.TOOL',
0x812E: 'WORKBOOK.NEW',
0x8131: 'SCENARIO.CELLS',
0x8132: 'SCENARIO.DELETE',
0x8133: 'SCENARIO.ADD',
0x8134: 'SCENARIO.EDIT',
0x8135: 'SCENARIO.SHOW',
0x8136: 'SCENARIO.SHOW.NEXT',
0x8137: 'SCENARIO.SUMMARY',
0x8138: 'PIVOT.TABLE.WIZARD',
0x8139: 'PIVOT.FIELD.PROPERTIES',
0x813A: 'PIVOT.FIELD',
0x813B: 'PIVOT.ITEM',
0x813C: 'PIVOT.ADD.FIELDS',
0x813E: 'OPTIONS.CALCULATION',
0x813F: 'OPTIONS.EDIT',
0x8140: 'OPTIONS.VIEW',
0x8141: 'ADDIN.MANAGER',
0x8142: 'MENU.EDITOR',
0x8143: 'ATTACH.TOOLBARS',
0x8144: 'VBAActivate',
0x8145: 'OPTIONS.CHART',
0x8148: 'VBA.INSERT.FILE',
0x814A: 'VBA.PROCEDURE.DEFINITION',
0x8150: 'ROUTING.SLIP',
0x8152: 'ROUTE.DOCUMENT',
0x8153: 'MAIL.LOGON',
0x8156: 'INSERT.PICTURE',
0x8157: 'EDIT.TOOL',
0x8158: 'GALLERY.DOUGHNUT',
0x815E: 'CHART.TREND',
0x8160: 'PIVOT.ITEM.PROPERTIES',
0x8162: 'WORKBOOK.INSERT',
0x8163: 'OPTIONS.TRANSITION',
0x8164: 'OPTIONS.GENERAL',
0x8172: 'FILTER.ADVANCED',
0x8175: 'MAIL.ADD.MAILER',
0x8176: 'MAIL.DELETE.MAILER',
0x8177: 'MAIL.REPLY',
0x8178: 'MAIL.REPLY.ALL',
0x8179: 'MAIL.FORWARD',
0x817A: 'MAIL.NEXT.LETTER',
0x817B: 'DATA.LABEL',
0x817C: 'INSERT.TITLE',
0x817D: 'FONT.PROPERTIES',
0x817E: 'MACRO.OPTIONS',
0x817F: 'WORKBOOK.HIDE',
0x8180: 'WORKBOOK.UNHIDE',
0x8181: 'WORKBOOK.DELETE',
0x8182: 'WORKBOOK.NAME',
0x8184: 'GALLERY.CUSTOM',
0x8186: 'ADD.CHART.AUTOFORMAT',
0x8187: 'DELETE.CHART.AUTOFORMAT',
0x8188: 'CHART.ADD.DATA',
0x8189: 'AUTO.OUTLINE',
0x818A: 'TAB.ORDER',
0x818B: 'SHOW.DIALOG',
0x818C: 'SELECT.ALL',
0x818D: 'UNGROUP.SHEETS',
0x818E: 'SUBTOTAL.CREATE',
0x818F: 'SUBTOTAL.REMOVE',
0x8190: 'RENAME.OBJECT',
0x819C: 'WORKBOOK.SCROLL',
0x819D: 'WORKBOOK.NEXT',
0x819E: 'WORKBOOK.PREV',
0x819F: 'WORKBOOK.TAB.SPLIT',
0x81A0: 'FULL.SCREEN',
0x81A1: 'WORKBOOK.PROTECT',
0x81A4: 'SCROLLBAR.PROPERTIES',
0x81A5: 'PIVOT.SHOW.PAGES',
0x81A6: 'TEXT.TO.COLUMNS',
0x81A7: 'FORMAT.CHARTTYPE',
0x81A8: 'LINK.FORMAT',
0x81A9: 'TRACER.DISPLAY',
0x81AE: 'TRACER.NAVIGATE',
0x81AF: 'TRACER.CLEAR',
0x81B0: 'TRACER.ERROR',
0x81B1: 'PIVOT.FIELD.GROUP',
0x81B2: 'PIVOT.FIELD.UNGROUP',
0x81B3: 'CHECKBOX.PROPERTIES',
0x81B4: 'LABEL.PROPERTIES',
0x81B5: 'LISTBOX.PROPERTIES',
0x81B6: 'EDITBOX.PROPERTIES',
0x81B7: 'PIVOT.REFRESH',
0x81B8: 'LINK.COMBO',
0x81B9: 'OPEN.TEXT',
0x81BA: 'HIDE.DIALOG',
0x81BB: 'SET.DIALOG.FOCUS',
0x81BC: 'ENABLE.OBJECT',
0x81BD: 'PUSHBUTTON.PROPERTIES',
0x81BE: 'SET.DIALOG.DEFAULT',
0x81BF: 'FILTER',
0x81C0: 'FILTER.SHOW.ALL',
0x81C1: 'CLEAR.OUTLINE',
0x81C2: 'FUNCTION.WIZARD',
0x81C3: 'ADD.LIST.ITEM',
0x81C4: 'SET.LIST.ITEM',
0x81C5: 'REMOVE.LIST.ITEM',
0x81C6: 'SELECT.LIST.ITEM',
0x81C7: 'SET.CONTROL.VALUE',
0x81C8: 'SAVE.COPY.AS',
0x81CA: 'OPTIONS.LISTS.ADD',
0x81CB: 'OPTIONS.LISTS.DELETE',
0x81CC: 'SERIES.AXES',
0x81CD: 'SERIES.X',
0x81CE: 'SERIES.Y',
0x81CF: 'ERRORBAR.X',
0x81D0: 'ERRORBAR.Y',
0x81D1: 'FORMAT.CHART',
0x81D2: 'SERIES.ORDER',
0x81D3: 'MAIL.LOGOFF',
0x81D4: 'CLEAR.ROUTING.SLIP',
0x81D5: 'APP.ACTIVATE.MICROSOFT',
0x81D6: 'MAIL.EDIT.MAILER',
0x81D7: 'ON.SHEET',
0x81D8: 'STANDARD.WIDTH',
0x81D9: 'SCENARIO.MERGE',
0x81DA: 'SUMMARY.INFO',
0x81DB: 'FIND.FILE',
0x81DC: 'ACTIVE.CELL.FONT',
0x81DD: 'ENABLE.TIPWIZARD',
0x81DE: 'VBA.MAKE.ADDIN',
0x81E0: 'INSERTDATATABLE',
0x81E1: 'WORKGROUP.OPTIONS',
0x81E2: 'MAIL.SEND.MAILER',
0x81E5: 'AUTOCORRECT',
0x81E9: 'POST.DOCUMENT',
0x81EB: 'PICKLIST',
0x81ED: 'VIEW.SHOW',
0x81EE: 'VIEW.DEFINE',
0x81EF: 'VIEW.DELETE',
0x81FD: 'SHEET.BACKGROUND',
0x81FE: 'INSERT.MAP.OBJECT',
0x81FF: 'OPTIONS.MENONO',
0x8205: 'MSOCHECKS',
0x8206: 'NORMAL',
0x8207: 'LAYOUT',
0x8208: 'RM.PRINT.AREA',
0x8209: 'CLEAR.PRINT.AREA',
0x820A: 'ADD.PRINT.AREA',
0x820B: 'MOVE.BRK',
0x8221: 'HIDECURR.NOTE',
0x8222: 'HIDEALL.NOTES',
0x8223: 'DELETE.NOTE',
0x8224: 'TRAVERSE.NOTES',
0x8225: 'ACTIVATE.NOTES',
0x826C: 'PROTECT.REVISIONS',
0x826D: 'UNPROTECT.REVISIONS',
0x8287: 'OPTIONS.ME',
0x828D: 'WEB.PUBLISH',
0x829B: 'NEWWEBQUERY',
0x82A1: 'PIVOT.TABLE.CHART',
0x82F1: 'OPTIONS.SAVE',
0x82F3: 'OPTIONS.SPELL',
0x8328: 'HIDEALL.INKANNOTS',
    }

    def GetFunctionName(functionid):
        if functionid in dFunctions:
            name = dFunctions[functionid]
            if isinstance(name, list):
                return name[0]
        else:
            name = '*UNKNOWN FUNCTION*'
        return name

    def GetFunctionArity(functionid):
        arity = 1
        if functionid in dFunctions:
            entry = dFunctions[functionid]
            if isinstance(entry, list):
                arity = entry[1]
        return arity

    result = ''
    stack = []
    while len(expression) > 0:
        ptgid = P23Ord(expression[0])
        expression = expression[1:]
        if ptgid in dTokens:
            result += dTokens[ptgid] + ' '
            if ptgid == 0x03: # ptgAdd https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/27db2f45-11e8-4238-94ed-92fd9c5721fb
                StackBinary(stack, '+')
            elif ptgid == 0x4: # ptgSub
                StackBinary(stack, '-')
            elif ptgid == 0x5: # ptgMul
                StackBinary(stack, '*')
            elif ptgid == 0x6: # ptgDiv
                StackBinary(stack, '/')
            elif ptgid == 0x8: # ptgConcat
                StackBinary(stack, '&')
            elif ptgid == 0x09: # ptgLt https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/28de4981-1352-4a5e-a3b7-f15a8a6ce7fb
                StackBinary(stack, '<')
            elif ptgid == 0x0A: # ptgLE
                StackBinary(stack, '<=')
            elif ptgid == 0x0B: # ptgEQ
                StackBinary(stack, '=')
            elif ptgid == 0x0C: # ptgGE
                StackBinary(stack, '>=')
            elif ptgid == 0x0D: # ptgGT
                StackBinary(stack, '>')
            elif ptgid == 0x0E: # ptgNE
                StackBinary(stack, '<>')
            elif ptgid == 0x15: # ptgParen
                operand1 = stack.pop()
                stack.append('(' + operand1 + ')')
            elif ptgid == 0x17: # ptgStr https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/87c2a057-705c-4473-a168-6d5fac4a9eba
                length = P23Ord(expression[0])
                expression = expression[1:]
                if P23Ord(expression[0]) == 0: # probably BIFF8 -> UNICODE (compressed)
                    expression = expression[1:]
                    stringValue = P23Decode(expression[:length])
                    result += '"%s" ' % stringValue
                    expression = expression[length:]
                elif P23Ord(expression[0]) == 1: # if 1, then double byte chars
                    # doublebyte check: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/05162858-0ca9-44cb-bb07-a720928f63f8
                    expression = expression[1:]
                    stringValue = P23Decode(expression[:length*2])
                    result += '"%s" ' % stringValue
                    expression = expression[length*2:]
                else:
                    stringValue = '<ERROR>'
                stack.append('"' + stringValue + '"')
            elif ptgid == 0x19:
                grbit = P23Ord(expression[0])
                expression = expression[1:]
                if grbit & 0x04:
                    result += 'CHOOSE '
                    break
                else:
                    expression = expression[2:]
            elif ptgid == 0x16: #ptgMissArg
                stack.append('')
            elif ptgid == 0x1d: # ptgBool https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/d59e28db-4d6f-4c86-bcc9-c8a783e352ec
                boolValue = IFF(P23Ord(expression[0]), 'TRUE', 'FALSE')
                result += '%s ' % (boolValue)
                expression = expression[1:]
                stack.append(boolValue)
            elif ptgid == 0x1e: #ptgInt
                value = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
                result += '%d ' % (value)
                expression = expression[2:]
                stack.append(str(value))
            elif ptgid == 0x41: #ptgFuncV
                functionid = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
                result += '%s (0x%04x) ' % (GetFunctionName(functionid), functionid)
                expression = expression[2:]
                StackFunction(stack, GetFunctionName(functionid), GetFunctionArity(functionid))
            elif ptgid == 0x22 or ptgid == 0x42 or ptgid == 0x62:
                functionid = P23Ord(expression[1]) + P23Ord(expression[2]) * 0x100
                numberOfArguments = P23Ord(expression[0])
                result += 'args %d func %s (0x%04x) ' % (numberOfArguments, GetFunctionName(functionid), functionid)
                expression = expression[3:]
                if functionid == 0x806D:
                    expression = expression[9:]
                StackFunction(stack, GetFunctionName(functionid), numberOfArguments)
            elif ptgid == 0x23: # ptgName https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/5f05c166-dfe3-4bbf-85aa-31c09c0258c0
                nameValue = struct.unpack('<I', expression[0:4])[0]
                result += '0x%08x ' % (nameValue)
                expression = expression[4:]
                if nameValue <= len(definesNames):
                    stack.append(definesNames[nameValue - 1])
                else:
                    stack.append('ptgName:0x%08x' % (nameValue))
            elif ptgid == 0x1f:
                value = struct.unpack('<d', expression[:8])[0]
                result += 'FLOAT %f ' % value
                stack.append('%.20f' % value)
                expression = expression[8:]
            elif ptgid == 0x26:
                ## expression = expression[4:]
                ## expression = expression[P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100:]
                expression = expression[6:]
                result += 'REFERENCE-EXPRESSION '
            elif ptgid == 0x01:
                cellref, expression = ParseLoc(expression, cellrefformat, True)
                result += '%s ' % cellref
            elif ptgid == 0x24 or ptgid == 0x44: #ptgRef #ptgRefV
                cellref, expression = ParseLoc(expression, cellrefformat, True)
                result += '%s ' % cellref
                stack.append(cellref)
            elif ptgid == 0x11: # ptgRange
                pass
            elif ptgid == 0x25: # ptgArea
                arearef = ParseArea(expression[0:8])
                result += '%s ' % arearef
                expression = expression[8:]
                stack.append(arearef)
            elif ptgid == 0x3A or ptgid == 0x5A: # ptgRef3d ptgRef3dV
                formatcodes = 'H'
                formatsize = struct.calcsize(formatcodes)
                sheetindex = struct.unpack(formatcodes, expression[0:formatsize])[0]
                expression = expression[formatsize:]
                cellref, expression = ParseLoc(expression, cellrefformat, True)
                if sheetindex < len(sheetNames):
                    cellref3d = '%s!%s' % (sheetNames[sheetindex], cellref)
                else:
                    cellref3d = '%d!%s' % (sheetindex, cellref)
                result += '%s ' % cellref3d
                stack.append(cellref3d)
            elif ptgid == 0x39: # PtgNameX
                expression = expression[2:]
                formatcodes = 'H'
                formatsize = struct.calcsize(formatcodes)
                nameindex = struct.unpack(formatcodes, expression[0:formatsize])[0]
                result += ' NAMEIDX %d ' % nameindex
                expression = expression[4:]
            elif ptgid == 0x21: #ptgFunc
                functionid = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
                result += '%s ' % GetFunctionName(functionid)
                expression = expression[2:]
                StackFunction(stack, GetFunctionName(functionid), GetFunctionArity(functionid))
            elif ptgid == 0x61 or ptgid == 0x62: # ptgFuncVar  ptgFuncVarA
                params_count = P23Ord(expression[0])
                functionid = P23Ord(expression[1]) + P23Ord(expression[2]) * 0x100
                result += '%s ' % GetFunctionName(functionid)
                expression = expression[(2+params_count):]
            else:
                break
        else:
            result += '*UNKNOWN TOKEN* 0x%04x' % ptgid
            break
    if expression == b'':
        return result, stack
    else:
        functions = [dFunctions[functionid] for functionid in [0x6E, 0x95] if ContainsWP23Ord(functionid, expression)]
        if functions != []:
            message = ' Could contain following functions: ' + ','.join(functions) + ' -'
        else:
            message = ''
        return result + ' *INCOMPLETE FORMULA PARSING*' + message + ' Remaining, unparsed expression: ' + repr(expression), stack

def DecodeRKValue(data):
    number = P23Ord(data[0])
    divider = 1.0
    if number & 0x01:
        divider = 100.0
    if number & 0x02:
        return (struct.unpack('<i', data)[0] >> 2) / divider
    else:
        return struct.unpack('<d', b'\x00\x00\x00\x00' + data)[0] / divider

def ShortXLUnicodeString(data, isBIFF8):
    cch = P23Ord(data[0])
    if isBIFF8:
        highbyte = P23Ord(data[1])
        if highbyte == 0:
            return P23Decode(data[2:2 + cch])
        else:
            return repr(data[2:2 + cch * 2])
    else:
        return P23Decode(data[1:1 + cch])

def GetDictionary(passwordfile):
    if passwordfile != '.':
        return File2Strings(passwordfile)
    else:
# https://github.com/magnumripper/JohnTheRipper/blob/bleeding-jumbo/run/password.lst
        return [
          'infected',
          'P@ssw0rd',
          'VelvetSweatshop',
          '123456',
          '12345',
          'password',
          'password1',
          '123456789',
          '12345678',
          '1234567890',
          'abc123',
          'computer',
          'tigger',
          '1234',
          'qwerty',
          'money',
          'carmen',
          'mickey',
          'secret',
          'summer',
          'internet',
          'a1b2c3',
          '123',
          'service',
          'canada',
          'hello',
          'ranger',
          'shadow',
          'baseball',
          'donald',
          'harley',
          'hockey',
          'letmein',
          'maggie',
          'mike',
          'mustang',
          'snoopy',
          'buster',
          'dragon',
          'jordan',
          'michael',
          'michelle',
          'mindy',
          'patrick',
          '123abc',
          'andrew',
          'bear',
          'calvin',
          'changeme',
          'diamond',
          'fuckme',
          'fuckyou',
          'matthew',
          'miller',
          'tiger',
          'trustno1',
          'alex',
          'apple',
          'avalon',
          'brandy',
          'chelsea',
          'coffee',
          'falcon',
          'freedom',
          'gandalf',
          'green',
          'helpme',
          'linda',
          'magic',
          'merlin',
          'newyork',
          'soccer',
          'thomas',
          'wizard',
          'asdfgh',
          'bandit',
          'batman',
          'boris',
          'butthead',
          'dorothy',
          'eeyore',
          'fishing',
          'football',
          'george',
          'happy',
          'iloveyou',
          'jennifer',
          'jonathan',
          'love',
          'marina',
          'master',
          'missy',
          'monday',
          'monkey',
          'natasha',
          'ncc1701',
          'pamela',
          'pepper',
          'piglet',
          'poohbear',
          'pookie',
          'rabbit',
          'rachel',
          'rocket',
          'rose',
          'smile',
          'sparky',
          'spring',
          'steven',
          'success',
          'sunshine',
          'victoria',
          'whatever',
          'zapata',
          '8675309',
          'amanda',
          'andy',
          'angel',
          'august',
          'barney',
          'biteme',
          'boomer',
          'brian',
          'casey',
          'cowboy',
          'delta',
          'doctor',
          'fisher',
          'island',
          'john',
          'joshua',
          'karen',
          'marley',
          'orange',
          'please',
          'rascal',
          'richard',
          'sarah',
          'scooter',
          'shalom',
          'silver',
          'skippy',
          'stanley',
          'taylor',
          'welcome',
          'zephyr',
          '111111',
          'aaaaaa',
          'access',
          'albert',
          'alexander',
          'andrea',
          'anna',
          'anthony',
          'asdfjkl;',
          'ashley',
          'basketball',
          'beavis',
          'black',
          'bob',
          'booboo',
          'bradley',
          'brandon',
          'buddy',
          'caitlin',
          'camaro',
          'charlie',
          'chicken',
          'chris',
          'cindy',
          'cricket',
          'dakota',
          'dallas',
          'daniel',
          'david',
          'debbie',
          'dolphin',
          'elephant',
          'emily',
          'friend',
          'fucker',
          'ginger',
          'goodluck',
          'hammer',
          'heather',
          'iceman',
          'jason',
          'jessica',
          'jesus',
          'joseph',
          'jupiter',
          'justin',
          'kevin',
          'knight',
          'lacrosse',
          'lakers',
          'lizard',
          'madison',
          'mary',
          'mother',
          'muffin',
          'murphy',
          'nirvana',
          'paris',
          'pentium',
          'phoenix',
          'picture',
          'rainbow',
          'sandy',
          'saturn',
          'scott',
          'shannon',
          'shithead',
          'skeeter',
          'sophie',
          'special',
          'stephanie',
          'stephen',
          'steve',
          'sweetie',
          'teacher',
          'tennis',
          'test',
          'test123',
          'tommy',
          'topgun',
          'tristan',
          'wally',
          'william',
          'wilson',
          '1q2w3e',
          '654321',
          '666666',
          'a12345',
          'a1b2c3d4',
          'alpha',
          'amber',
          'angela',
          'angie',
          'archie',
          'asdf',
          'blazer',
          'bond007',
          'booger',
          'charles',
          'christin',
          'claire',
          'control',
          'danny',
          'david1',
          'dennis',
          'digital',
          'disney',
          'edward',
          'elvis',
          'felix',
          'flipper',
          'franklin',
          'frodo',
          'honda',
          'horses',
          'hunter',
          'indigo',
          'james',
          'jasper',
          'jeremy',
          'julian',
          'kelsey',
          'killer',
          'lauren',
          'marie',
          'maryjane',
          'matrix',
          'maverick',
          'mayday',
          'mercury',
          'mitchell',
          'morgan',
          'mountain',
          'niners',
          'nothing',
          'oliver',
          'peace',
          'peanut',
          'pearljam',
          'phantom',
          'popcorn',
          'princess',
          'psycho',
          'pumpkin',
          'purple',
          'randy',
          'rebecca',
          'reddog',
          'robert',
          'rocky',
          'roses',
          'salmon',
          'samson',
          'sharon',
          'sierra',
          'smokey',
          'startrek',
          'steelers',
          'stimpy',
          'sunflower',
          'superman',
          'support',
          'sydney',
          'techno',
          'walter',
          'willie',
          'willow',
          'winner',
          'ziggy',
          'zxcvbnm',
          'alaska',
          'alexis',
          'alice',
          'animal',
          'apples',
          'barbara',
          'benjamin',
          'billy',
          'blue',
          'bluebird',
          'bobby',
          'bonnie',
          'bubba',
          'camera',
          'chocolate',
          'clark',
          'claudia',
          'cocacola',
          'compton',
          'connect',
          'cookie',
          'cruise',
          'douglas',
          'dreamer',
          'dreams',
          'duckie',
          'eagles',
          'eddie',
          'einstein',
          'enter',
          'explorer',
          'faith',
          'family',
          'ferrari',
          'flamingo',
          'flower',
          'foxtrot',
          'francis',
          'freddy',
          'friday',
          'froggy',
          'giants',
          'gizmo',
          'global',
          'goofy',
          'happy1',
          'hendrix',
          'henry',
          'herman',
          'homer',
          'honey',
          'house',
          'houston',
          'iguana',
          'indiana',
          'insane',
          'inside',
          'irish',
          'ironman',
          'jake',
          'jasmin',
          'jeanne',
          'jerry',
          'joey',
          'justice',
          'katherine',
          'kermit',
          'kitty',
          'koala',
          'larry',
          'leslie',
          'logan',
          'lucky',
          'mark',
          'martin',
          'matt',
          'minnie',
          'misty',
          'mitch',
          'mouse',
          'nancy',
          'nascar',
          'nelson',
          'pantera',
          'parker',
          'penguin',
          'peter',
          'piano',
          'pizza',
          'prince',
          'punkin',
          'pyramid',
          'raymond',
          'robin',
          'roger',
          'rosebud',
          'route66',
          'royal',
          'running',
          'sadie',
          'sasha',
          'security',
          'sheena',
          'sheila',
          'skiing',
          'snapple',
          'snowball',
          'sparrow',
          'spencer',
          'spike',
          'star',
          'stealth',
          'student',
          'sunny',
          'sylvia',
          'tamara',
          'taurus',
          'teresa',
          'theresa',
          'thunderbird',
          'tigers',
          'tony',
          'toyota',
          'travel',
          'tuesday',
          'victory',
          'viper1',
          'wesley',
          'whisky',
          'winnie',
          'winter',
          'wolves',
          'xyz123',
          'zorro',
          '123123',
          '1234567',
          '696969',
          '888888',
          'Anthony',
          'Joshua',
          'Matthew',
          'Tigger',
          'aaron',
          'abby',
          'abcdef',
          'adidas',
          'adrian',
          'alfred',
          'arthur',
          'athena',
          'austin',
          'awesome',
          'badger',
          'bamboo',
          'beagle',
          'bears',
          'beatles',
          'beautiful',
          'beaver',
          'benny',
          'bigmac',
          'bingo',
          'bitch',
          'blonde',
          'boogie',
          'boston',
          'brenda',
          'bright',
          'bubba1',
          'bubbles',
          'buffy',
          'button',
          'buttons',
          'cactus',
          'candy',
          'captain',
          'carlos',
          'caroline',
          'carrie',
          'casper',
          'catch22',
          'chance',
          'charity',
          'charlotte',
          'cheese',
          'cheryl',
          'chloe',
          'chris1',
          'clancy',
          'compaq',
          'conrad',
          'cooper',
          'cooter',
          'copper',
          'cosmos',
          'cougar',
          'cracker',
          'crawford',
          'crystal',
          'curtis',
          'cyclone',
          'dance',
          'diablo',
          'dollars',
          'dookie',
          'dumbass',
          'dundee',
          'elizabeth',
          'eric',
          'europe',
          'farmer',
          'firebird',
          'fletcher',
          'fluffy',
          'france',
          'freak1',
          'friends',
          'fuckoff',
          'gabriel',
          'galaxy',
          'gambit',
          'garden',
          'garfield',
          'garnet',
          'genesis',
          'genius',
          'godzilla',
          'golfer',
          'goober',
          'grace',
          'greenday',
          'groovy',
          'grover',
          'guitar',
          'hacker',
          'harry',
          'hazel',
          'hector',
          'herbert',
          'horizon',
          'hornet',
          'howard',
          'icecream',
          'imagine',
          'impala',
          'jack',
          'janice',
          'jasmine',
          'jason1',
          'jeanette',
          'jeffrey',
          'jenifer',
          'jenni',
          'jesus1',
          'jewels',
          'joker',
          'julie',
          'julie1',
          'junior',
          'justin1',
          'kathleen',
          'keith',
          'kelly',
          'kelly1',
          'kennedy',
          'kevin1',
          'knicks',
          'larry1',
          'leonard',
          'lestat',
          'library',
          'lincoln',
          'lionking',
          'london',
          'louise',
          'lucky1',
          'lucy',
          'maddog',
          'margaret',
          'mariposa',
          'marlboro',
          'martin1',
          'marty',
          'master1',
          'mensuck',
          'mercedes',
          'metal',
          'midori',
          'mikey',
          'millie',
          'mirage',
          'molly',
          'monet',
          'money1',
          'monica',
          'monopoly',
          'mookie',
          'moose',
          'moroni',
          'music',
          'naomi',
          'nathan',
          'nguyen',
          'nicholas',
          'nicole',
          'nimrod',
          'october',
          'olive',
          'olivia',
          'online',
          'oscar',
          'oxford',
          'pacific',
          'painter',
          'peaches',
          'penelope',
          'pepsi',
          'petunia',
          'philip',
          'phoenix1',
          'photo',
          'pickle',
          'player',
          'poiuyt',
          'porsche',
          'porter',
          'puppy',
          'python',
          'quality',
          'raquel',
          'raven',
          'remember',
          'robbie',
          'robert1',
          'roman',
          'rugby',
          'runner',
          'russell',
          'ryan',
          'sailing',
          'sailor',
          'samantha',
          'savage',
          'scarlett',
          'school',
          'sean',
          'seven',
          'shadow1',
          'sheba',
          'shelby',
          'shit',
          'shoes',
          'simba',
          'simple',
          'skipper',
          'smiley',
          'snake',
          'snickers',
          'sniper',
          'snoopdog',
          'snowman',
          'sonic',
          'spitfire',
          'sprite',
          'spunky',
          'starwars',
          'station',
          'stella',
          'stingray',
          'storm',
          'stormy',
          'stupid',
          'sunny1',
          'sunrise',
          'surfer',
          'susan',
          'tammy',
          'tango',
          'tanya',
          'teddy1',
          'theboss',
          'theking',
          'thumper',
          'tina',
          'tintin',
          'tomcat',
          'trebor',
          'trevor',
          'tweety',
          'unicorn',
          'valentine',
          'valerie',
          'vanilla',
          'veronica',
          'victor',
          'vincent',
          'viper',
          'warrior',
          'warriors',
          'weasel',
          'wheels',
          'wilbur',
          'winston',
          'wisdom',
          'wombat',
          'xavier',
          'yellow',
          'zeppelin',
          '1111',
          '1212',
          'Andrew',
          'Family',
          'Friends',
          'Michael',
          'Michelle',
          'Snoopy',
          'abcd1234',
          'abcdefg',
          'abigail',
          'account',
          'adam',
          'alex1',
          'alice1',
          'allison',
          'alpine',
          'andre1',
          'andrea1',
          'angel1',
          'anita',
          'annette',
          'antares',
          'apache',
          'apollo',
          'aragorn',
          'arizona',
          'arnold',
          'arsenal',
          'asdfasdf',
          'asdfg',
          'asdfghjk',
          'avenger',
          'baby',
          'babydoll',
          'bailey',
          'banana',
          'barry',
          'basket',
          'batman1',
          'beaner',
          'beast',
          'beatrice',
          'bella',
          'bertha',
          'bigben',
          'bigdog',
          'biggles',
          'bigman',
          'binky',
          'biology',
          'bishop',
          'blondie',
          'bluefish',
          'bobcat',
          'bosco',
          'braves',
          'brazil',
          'bruce',
          'bruno',
          'brutus',
          'buffalo',
          'bulldog',
          'bullet',
          'bullshit',
          'bunny',
          'business',
          'butch',
          'butler',
          'butter',
          'california',
          'carebear',
          'carol',
          'carol1',
          'carole',
          'cassie',
          'castle',
          'catalina',
          'catherine',
          'cccccc',
          'celine',
          'center',
          'champion',
          'chanel',
          'chaos',
          'chelsea1',
          'chester1',
          'chicago',
          'chico',
          'christian',
          'christy',
          'church',
          'cinder',
          'colleen',
          'colorado',
          'columbia',
          'commander',
          'connie',
          'cookies',
          'cooking',
          'corona',
          'cowboys',
          'coyote',
          'craig',
          'creative',
          'cuddles',
          'cuervo',
          'cutie',
          'daddy',
          'daisy',
          'daniel1',
          'danielle',
          'davids',
          'death',
          'denis',
          'derek',
          'design',
          'destiny',
          'diana',
          'diane',
          'dickhead',
          'digger',
          'dodger',
          'donna',
          'dougie',
          'dragonfly',
          'dylan',
          'eagle',
          'eclipse',
          'electric',
          'emerald',
          'etoile',
          'excalibur',
          'express',
          'fender',
          'fiona',
          'fireman',
          'flash',
          'florida',
          'flowers',
          'foster',
          'francesco',
          'francine',
          'francois',
          'frank',
          'french',
          'fuckface',
          'gemini',
          'general',
          'gerald',
          'germany',
          'gilbert',
          'goaway',
          'golden',
          'goldfish',
          'goose',
          'gordon',
          'graham',
          'grant',
          'gregory',
          'gretchen',
          'gunner',
          'hannah',
          'harold',
          'harrison',
          'harvey',
          'hawkeye',
          'heaven',
          'heidi',
          'helen',
          'helena',
          'hithere',
          'hobbit',
          'ibanez',
          'idontknow',
          'integra',
          'ireland',
          'irene',
          'isaac',
          'isabel',
          'jackass',
          'jackie',
          'jackson',
          'jaguar',
          'jamaica',
          'japan',
          'jenny1',
          'jessie',
          'johan',
          'johnny',
          'joker1',
          'jordan23',
          'judith',
          'julia',
          'jumanji',
          'kangaroo',
          'karen1',
          'kathy',
          'keepout',
          'keith1',
          'kenneth',
          'kimberly',
          'kingdom',
          'kitkat',
          'kramer',
          'kristen',
          'laura',
          'laurie',
          'lawrence',
          'lawyer',
          'legend',
          'liberty',
          'light',
          'lindsay',
          'lindsey',
          'lisa',
          'liverpool',
          'lola',
          'lonely',
          'louis',
          'lovely',
          'loveme',
          'lucas',
          'madonna',
          'malcolm',
          'malibu',
          'marathon',
          'marcel',
          'maria1',
          'mariah',
          'mariah1',
          'marilyn',
          'mario',
          'marvin',
          'maurice',
          'maxine',
          'maxwell',
          'me',
          'meggie',
          'melanie',
          'melissa',
          'melody',
          'mexico',
          'michael1',
          'michele',
          'midnight',
          'mike1',
          'miracle',
          'misha',
          'mishka',
          'molly1',
          'monique',
          'montreal',
          'moocow',
          'moore',
          'morris',
          'mouse1',
          'mulder',
          'nautica',
          'nellie',
          'newton',
          'nick',
          'nirvana1',
          'nissan',
          'norman',
          'notebook',
          'ocean',
          'olivier',
          'ollie',
          'oranges',
          'oregon',
          'orion',
          'panda',
          'pandora',
          'panther',
          'passion',
          'patricia',
          'pearl',
          'peewee',
          'pencil',
          'penny',
          'people',
          'percy',
          'person',
          'peter1',
          'petey',
          'picasso',
          'pierre',
          'pinkfloyd',
          'polaris',
          'police',
          'pookie1',
          'poppy',
          'power',
          'predator',
          'preston',
          'q1w2e3',
          'queen',
          'queenie',
          'quentin',
          'ralph',
          'random',
          'rangers',
          'raptor',
          'reality',
          'redrum',
          'remote',
          'reynolds',
          'rhonda',
          'ricardo',
          'ricardo1',
          'ricky',
          'river',
          'roadrunner',
          'robinhood',
          'rocknroll',
          'rocky1',
          'ronald',
          'roxy',
          'ruthie',
          'sabrina',
          'sakura',
          'sally',
          'sampson',
          'samuel',
          'sandra',
          'santa',
          'sapphire',
          'scarlet',
          'scorpio',
          'scott1',
          'scottie',
          'scruffy',
          'seattle',
          'serena',
          'shanti',
          'shark',
          'shogun',
          'simon',
          'singer',
          'skull',
          'skywalker',
          'slacker',
          'smashing',
          'smiles',
          'snowflake',
          'snuffy',
          'soccer1',
          'soleil',
          'sonny',
          'spanky',
          'speedy',
          'spider',
          'spooky',
          'stacey',
          'star69',
          'start',
          'steven1',
          'stinky',
          'strawberry',
          'stuart',
          'sugar',
          'sundance',
          'superfly',
          'suzanne',
          'suzuki',
          'swimmer',
          'swimming',
          'system',
          'taffy',
          'tarzan',
          'teddy',
          'teddybear',
          'terry',
          'theatre',
          'thunder',
          'thursday',
          'tinker',
          'tootsie',
          'tornado',
          'tracy',
          'tricia',
          'trident',
          'trojan',
          'truman',
          'trumpet',
          'tucker',
          'turtle',
          'tyler',
          'utopia',
          'voyager',
          'warcraft',
          'warlock',
          'warren',
          'water',
          'wayne',
          'wendy',
          'williams',
          'willy',
          'winona',
          'woody',
          'woofwoof',
          'wrangler',
          'wright',
          'xfiles',
          'xxxxxx',
          'yankees',
          'yvonne',
          'zebra',
          'zenith',
          'zigzag',
          'zombie',
          'zxc123',
          'zxcvb',
          '000000',
          '007007',
          '11111',
          '11111111',
          '123321',
          '171717',
          '181818',
          '1a2b3c',
          '1chris',
          '4runner',
          '54321',
          '55555',
          '6969',
          '7777777',
          '789456',
          '88888888',
          'Alexis',
          'Bailey',
          'Charlie',
          'Chris',
          'Daniel',
          'Dragon',
          'Elizabeth',
          'HARLEY',
          'Heather',
          'Jennifer',
          'Jessica',
          'Jordan',
          'KILLER',
          'Nicholas',
          'Password',
          'Princess',
          'Purple',
          'Rebecca',
          'Robert',
          'Shadow',
          'Steven',
          'Summer',
          'Sunshine',
          'Superman',
          'Taylor',
          'Thomas',
          'Victoria',
          'abcd123',
          'abcde',
          'accord',
          'active',
          'africa',
          'airborne',
          'alfaro',
          'alicia',
          'aliens',
          'alina',
          'aline',
          'alison',
          'allen',
          'aloha',
          'alpha1',
          'althea',
          'altima',
          'amanda1',
          'amazing',
          'america',
          'amour',
          'anderson',
          'andre',
          'andrew1',
          'andromeda',
          'angels',
          'angie1',
          'annie',
          'anything',
          'apple1',
          'apple2',
          'applepie',
          'april',
          'aquarius',
          'ariane',
          'ariel',
          'arlene',
          'artemis',
          'asdf1234',
          'asdfjkl',
          'ashley1',
          'ashraf',
          'ashton',
          'asterix',
          'attila',
          'autumn',
          'avatar',
          'babes',
          'bambi',
          'barbie',
          'barney1',
          'barrett',
          'bball',
          'beaches',
          'beanie',
          'beans',
          'beauty',
          'becca',
          'belize',
          'belle',
          'belmont',
          'benji',
          'benson',
          'bernardo',
          'berry',
          'betsy',
          'betty',
          'bigboss',
          'bigred',
          'billy1',
          'birdie',
          'birthday',
          'biscuit',
          'bitter',
          'blackjack',
          'blah',
          'blanche',
          'blood',
          'blowjob',
          'blowme',
          'blueeyes',
          'blues',
          'bogart',
          'bombay',
          'boobie',
          'boots',
          'bootsie',
          'boxers',
          'brandi',
          'brent',
          'brewster',
          'bridge',
          'bronco',
          'bronte',
          'brooke',
          'brother',
          'bryan',
          'bubble',
          'buddha',
          'budgie',
          'burton',
          'butterfly',
          'byron',
          'calendar',
          'calvin1',
          'camel',
          'camille',
          'campbell',
          'camping',
          'cancer',
          'canela',
          'cannon',
          'carbon',
          'carnage',
          'carolyn',
          'carrot',
          'cascade',
          'catfish',
          'cathy',
          'catwoman',
          'cecile',
          'celica',
          'change',
          'chantal',
          'charger',
          'cherry',
          'chiara',
          'chiefs',
          'china',
          'chris123',
          'christ1',
          'christmas',
          'christopher',
          'chuck',
          'cindy1',
          'cinema',
          'civic',
          'claude',
          'clueless',
          'cobain',
          'cobra',
          'cody',
          'colette',
          'college',
          'colors',
          'colt45',
          'confused',
          'cool',
          'corvette',
          'cosmo',
          'country',
          'crusader',
          'cunningham',
          'cupcake',
          'cynthia',
          'dagger',
          'dammit',
          'dancer',
          'daphne',
          'darkstar',
          'darren',
          'darryl',
          'darwin',
          'deborah',
          'december',
          'deedee',
          'deeznuts',
          'delano',
          'delete',
          'demon',
          'denise',
          'denny',
          'desert',
          'deskjet',
          'detroit',
          'devil',
          'devine',
          'devon',
          'dexter',
          'dianne',
          'diesel',
          'director',
          'dixie',
          'dodgers',
          'doggy',
          'dollar',
          'dolly',
          'dominique',
          'domino',
          'dontknow',
          'doogie',
          'doudou',
          'downtown',
          'dragon1',
          'driver',
          'dude',
          'dudley',
          'dutchess',
          'dwight',
          'eagle1',
          'easter',
          'eastern',
          'edith',
          'edmund',
          'eight',
          'element',
          'elissa',
          'ellen',
          'elliot',
          'empire',
          'enigma',
          'enterprise',
          'erin',
          'escort',
          'estelle',
          'eugene',
          'evelyn',
          'explore',
          'family1',
          'fatboy',
          'felipe',
          'ferguson',
          'ferret',
          'ferris',
          'fireball',
          'fishes',
          'fishie',
          'flight',
          'florida1',
          'flowerpot',
          'forward',
          'freddie',
          'freebird',
          'freeman',
          'frisco',
          'fritz',
          'froggie',
          'froggies',
          'frogs',
          'fucku',
          'future',
          'gabby',
          'games',
          'garcia',
          'gaston',
          'gateway',
          'george1',
          'georgia',
          'german',
          'germany1',
          'getout',
          'ghost',
          'gibson',
          'giselle',
          'gmoney',
          'goblin',
          'goblue',
          'gollum',
          'grandma',
          'gremlin',
          'grizzly',
          'grumpy',
          'guess',
          'guitar1',
          'gustavo',
          'haggis',
          'haha',
          'hailey',
          'halloween',
          'hamilton',
          'hamlet',
          'hanna',
          'hanson',
          'happy123',
          'happyday',
          'hardcore',
          'harley1',
          'harriet',
          'harris',
          'harvard',
          'health',
          'heart',
          'heather1',
          'heather2',
          'hedgehog',
          'helene',
          'hello1',
          'hello123',
          'hellohello',
          'hermes',
          'heythere',
          'highland',
          'hilda',
          'hillary',
          'history',
          'hitler',
          'hobbes',
          'holiday',
          'holly',
          'honda1',
          'hongkong',
          'hootie',
          'horse',
          'hotrod',
          'hudson',
          'hummer',
          'huskies',
          'idiot',
          'iforget',
          'iloveu',
          'impact',
          'indonesia',
          'irina',
          'isabelle',
          'israel',
          'italia',
          'italy',
          'jackie1',
          'jacob',
          'jakey',
          'james1',
          'jamesbond',
          'jamie',
          'jamjam',
          'jeffrey1',
          'jennie',
          'jenny',
          'jensen',
          'jesse',
          'jesse1',
          'jester',
          'jethro',
          'jimbob',
          'jimmy',
          'joanna',
          'joelle',
          'john316',
          'jordie',
          'jorge',
          'josh',
          'journey',
          'joyce',
          'jubilee',
          'jules',
          'julien',
          'juliet',
          'junebug',
          'juniper',
          'justdoit',
          'karin',
          'karine',
          'karma',
          'katerina',
          'katie',
          'katie1',
          'kayla',
          'keeper',
          'keller',
          'kendall',
          'kenny',
          'ketchup',
          'kings',
          'kissme',
          'kitten',
          'kittycat',
          'kkkkkk',
          'kristi',
          'kristine',
          'labtec',
          'laddie',
          'ladybug',
          'lance',
          'laurel',
          'lawson',
          'leader',
          'leland',
          'lemon',
          'lester',
          'letter',
          'letters',
          'lexus1',
          'libra',
          'lights',
          'lionel',
          'little',
          'lizzy',
          'lolita',
          'lonestar',
          'longhorn',
          'looney',
          'loren',
          'lorna',
          'loser',
          'lovers',
          'loveyou',
          'lucia',
          'lucifer',
          'lucky14',
          'maddie',
          'madmax',
          'magic1',
          'magnum',
          'maiden',
          'maine',
          'management',
          'manson',
          'manuel',
          'marcus',
          'maria',
          'marielle',
          'marine',
          'marino',
          'marshall',
          'martha',
          'maxmax',
          'meatloaf',
          'medical',
          'megan',
          'melina',
          'memphis',
          'mermaid',
          'miami',
          'michel',
          'michigan',
          'mickey1',
          'microsoft',
          'mikael',
          'milano',
          'miles',
          'millenium',
          'million',
          'miranda',
          'miriam',
          'mission',
          'mmmmmm',
          'mobile',
          'monkey1',
          'monroe',
          'montana',
          'monty',
          'moomoo',
          'moonbeam',
          'morpheus',
          'motorola',
          'movies',
          'mozart',
          'munchkin',
          'murray',
          'mustang1',
          'nadia',
          'nadine',
          'napoleon',
          'nation',
          'national',
          'nestle',
          'newlife',
          'newyork1',
          'nichole',
          'nikita',
          'nikki',
          'nintendo',
          'nokia',
          'nomore',
          'normal',
          'norton',
          'noway',
          'nugget',
          'number9',
          'numbers',
          'nurse',
          'nutmeg',
          'ohshit',
          'oicu812',
          'omega',
          'openup',
          'orchid',
          'oreo',
          'orlando',
          'packard',
          'packers',
          'paloma',
          'pancake',
          'panic',
          'parola',
          'parrot',
          'partner',
          'pascal',
          'patches',
          'patriots',
          'paula',
          'pauline',
          'payton',
          'peach',
          'peanuts',
          'pedro1',
          'peggy',
          'perfect',
          'perry',
          'peterpan',
          'philips',
          'phillips',
          'phone',
          'pierce',
          'pigeon',
          'pink',
          'pioneer',
          'piper1',
          'pirate',
          'pisces',
          'playboy',
          'pluto',
          'poetry',
          'pontiac',
          'pookey',
          'popeye',
          'prayer',
          'precious',
          'prelude',
          'premier',
          'puddin',
          'pulsar',
          'pussy',
          'pussy1',
          'qwert',
          'qwerty12',
          'qwertyui',
          'rabbit1',
          'rachelle',
          'racoon',
          'rambo',
          'randy1',
          'ravens',
          'redman',
          'redskins',
          'reggae',
          'reggie',
          'renee',
          'renegade',
          'rescue',
          'revolution',
          'richard1',
          'richards',
          'richmond',
          'riley',
          'ripper',
          'robby',
          'roberts',
          'rock',
          'rocket1',
          'rockie',
          'rockon',
          'roger1',
          'rogers',
          'roland',
          'rommel',
          'rookie',
          'rootbeer',
          'rosie',
          'rufus',
          'rusty',
          'ruthless',
          'sabbath',
          'sabina',
          'safety',
          'saint',
          'samiam',
          'sammie',
          'sammy',
          'samsam',
          'sandi',
          'sanjose',
          'saphire',
          'sarah1',
          'saskia',
          'sassy',
          'saturday',
          'science',
          'scooby',
          'scoobydoo',
          'scooter1',
          'scorpion',
          'scotty',
          'scouts',
          'search',
          'september',
          'server',
          'seven7',
          'sexy',
          'shaggy',
          'shanny',
          'shaolin',
          'shasta',
          'shayne',
          'shelly',
          'sherry',
          'shirley',
          'shorty',
          'shotgun',
          'sidney',
          'simba1',
          'sinatra',
          'sirius',
          'skate',
          'skipper1',
          'skyler',
          'slayer',
          'sleepy',
          'slider',
          'smile1',
          'smitty',
          'smoke',
          'snakes',
          'snapper',
          'snoop',
          'solomon',
          'sophia',
          'space',
          'sparks',
          'spartan',
          'spike1',
          'sponge',
          'spurs',
          'squash',
          'stargate',
          'starlight',
          'stars',
          'steph1',
          'steve1',
          'stevens',
          'stewart',
          'stone',
          'stranger',
          'stretch',
          'strong',
          'studio',
          'stumpy',
          'sucker',
          'suckme',
          'sultan',
          'summit',
          'sunfire',
          'sunset',
          'super',
          'superstar',
          'surfing',
          'susan1',
          'sutton',
          'sweden',
          'sweetpea',
          'sweety',
          'swordfish',
          'tabatha',
          'tacobell',
          'taiwan',
          'tamtam',
          'tanner',
          'target',
          'tasha',
          'tattoo',
          'tequila',
          'terry1',
          'texas',
          'thankyou',
          'theend',
          'thompson',
          'thrasher',
          'tiger2',
          'timber',
          'timothy',
          'tinkerbell',
          'topcat',
          'topher',
          'toshiba',
          'tototo',
          'travis',
          'treasure',
          'trees',
          'tricky',
          'trish',
          'triton',
          'trombone',
          'trouble',
          'trucker',
          'turbo',
          'twins',
          'tyler1',
          'ultimate',
          'unique',
          'united',
          'ursula',
          'vacation',
          'valley',
          'vampire',
          'vanessa',
          'venice',
          'venus',
          'vermont',
          'vicki',
          'vicky',
          'victor1',
          'vincent1',
          'violet',
          'violin',
          'virgil',
          'virginia',
          'vision',
          'volley',
          'voodoo',
          'vortex',
          'waiting',
          'wanker',
          'warner',
          'water1',
          'wayne1',
          'webster',
          'weezer',
          'wendy1',
          'western',
          'white',
          'whitney',
          'whocares',
          'wildcat',
          'william1',
          'wilma',
          'window',
          'winniethepooh',
          'wolfgang',
          'wolverine',
          'wonder',
          'xxxxxxxx',
          'yamaha',
          'yankee',
          'yogibear',
          'yolanda',
          'yomama',
          'yvette',
          'zachary',
          'zebras',
          'zxcvbn',
          '00000000',
          '121212',
          '1234qwer',
          '131313',
          '13579',
          '90210',
          '99999999',
          'ABC123',
          'action',
          'amelie',
          'anaconda',
          'apollo13',
          'artist',
          'asshole',
          'benoit',
          'bernard',
          'bernie',
          'bigbird',
          'blizzard',
          'bluesky',
          'bonjour',
          'caesar',
          'cardinal',
          'carolina',
          'cesar',
          'chandler',
          'chapman',
          'charlie1',
          'chevy',
          'chiquita',
          'chocolat',
          'coco',
          'cougars',
          'courtney',
          'dolphins',
          'dominic',
          'donkey',
          'dusty',
          'eminem',
          'energy',
          'fearless',
          'forest',
          'forever',
          'glenn',
          'guinness',
          'hotdog',
          'indian',
          'jared',
          'jimbo',
          'johnson',
          'jojo',
          'josie',
          'kristin',
          'lloyd',
          'lorraine',
          'lynn',
          'maxime',
          'memory',
          'mimi',
          'mirror',
          'nebraska',
          'nemesis',
          'network',
          'nigel',
          'oatmeal',
          'patton',
          'pedro',
          'planet',
          'players',
          'portland',
          'praise',
          'psalms',
          'qwaszx',
          'raiders',
          'rambo1',
          'rancid',
          'shawn',
          'shelley',
          'softball',
          'speedo',
          'sports',
          'ssssss',
          'steele',
          'steph',
          'stephani',
          'sunday',
          'tiffany',
          'tigre',
          'toronto',
          'trixie',
          'undead',
          'valentin',
          'velvet',
          'viking',
          'walker',
          'watson',
          'young',
          'babygirl',
          'pretty',
          'hottie',
          'teamo',
          '987654321',
          'naruto',
          'spongebob',
          'daniela',
          'princesa',
          'christ',
          'blessed',
          'single',
          'qazwsx',
          'pokemon',
          'iloveyou1',
          'iloveyou2',
          'fuckyou1',
          'hahaha',
          'poop',
          'blessing',
          'blahblah',
          'blink182',
          '123qwe',
          'trinity',
          'passw0rd',
          'google',
          'looking',
          'spirit',
          'iloveyou!',
          'qwerty1',
          'onelove',
          'mylove',
          '222222',
          'ilovegod',
          'football1',
          'loving',
          'emmanuel',
          '1q2w3e4r',
          'red123',
          'blabla',
          '112233',
          'hallo',
          'spiderman',
          'simpsons',
          'monster',
          'november',
          'brooklyn',
          'poopoo',
          'darkness',
          '159753',
          'pineapple',
          'chester',
          '1qaz2wsx',
          'drowssap',
          'monkey12',
          'wordpass',
          'q1w2e3r4',
          'coolness',
          '11235813',
          'something',
          'alexandra',
          'estrella',
          'miguel',
          'iloveme',
          'sayang',
          'princess1',
          '555555',
          '999999',
          'alejandro',
          'brittany',
          'alejandra',
          'tequiero',
          'antonio',
          '987654',
          '00000',
          'fernando',
          'corazon',
          'cristina',
          'kisses',
          'myspace',
          'rebelde',
          'babygurl',
          'alyssa',
          'mahalkita',
          'gabriela',
          'pictures',
          'hellokitty',
          'babygirl1',
          'angelica',
          'mahalko',
          'mariana',
          'eduardo',
          'andres',
          'ronaldo',
          'inuyasha',
          'adriana',
          'celtic',
          'samsung',
          'angelo',
          '456789',
          'sebastian',
          'karina',
          'hotmail',
          '0123456789',
          'barcelona',
          'cameron',
          'slipknot',
          'cutiepie',
          '50cent',
          'bonita',
          'maganda',
          'babyboy',
          'natalie',
          'cuteako',
          'javier',
          '789456123',
          '123654',
          'bowwow',
          'portugal',
          '777777',
          'volleyball',
          'january',
          'cristian',
          'bianca',
          'chrisbrown',
          '101010',
          'sweet',
          'panget',
          'benfica',
          'love123',
          'lollipop',
          'camila',
          'qwertyuiop',
          'harrypotter',
          'ihateyou',
          'christine',
          'lorena',
          'andreea',
          'charmed',
          'rafael',
          'brianna',
          'aaliyah',
          'johncena',
          'lovelove',
          'gangsta',
          '333333',
          'hiphop',
          'mybaby',
          'sergio',
          'metallica',
          'myspace1',
          'babyblue',
          'badboy',
          'fernanda',
          'westlife',
          'sasuke',
          'steaua',
          'roberto',
          'slideshow',
          'asdfghjkl',
          'santiago',
          'jayson',
          '5201314',
          'jerome',
          'gandako',
          'gatita',
          'babyko',
          '246810',
          'sweetheart',
          'chivas',
          'alberto',
          'valeria',
          'nicole1',
          '12345678910',
          'leonardo',
          'jayjay',
          'liliana',
          'sexygirl',
          '232323',
          'amores',
          'anthony1',
          'bitch1',
          'fatima',
          'miamor',
          'lover',
          'lalala',
          '252525',
          'skittles',
          'colombia',
          '159357',
          'manutd',
          '123456a',
          'britney',
          'katrina',
          'christina',
          'pasaway',
          'mahal',
          'tatiana',
          'cantik',
          '0123456',
          'teiubesc',
          '147258369',
          'natalia',
          'francisco',
          'amorcito',
          'paola',
          'angelito',
          'manchester',
          'mommy1',
          '147258',
          'amigos',
          'marlon',
          'linkinpark',
          '147852',
          'diego',
          '444444',
          'iverson',
          'andrei',
          'justine',
          'frankie',
          'pimpin',
          'fashion',
          'bestfriend',
          'england',
          'hermosa',
          '456123',
          '102030',
          'sporting',
          'hearts',
          'potter',
          'iloveu2',
          'number1',
          '212121',
          'truelove',
          'jayden',
          'savannah',
          'hottie1',
          'ganda',
          'scotland',
          'ilovehim',
          'shakira',
          'estrellita',
          'brandon1',
          'sweets',
          'familia',
          'love12',
          'omarion',
          'monkeys',
          'loverboy',
          'elijah',
          'ronnie',
          'mamita',
          '999999999',
          'broken',
          'rodrigo',
          'westside',
          'mauricio',
          'amigas',
          'preciosa',
          'shopping',
          'flores',
          'isabella',
          'martinez',
          'elaine',
          'friendster',
          'cheche',
          'gracie',
          'connor',
          'valentina',
          'darling',
          'santos',
          'joanne',
          'fuckyou2',
          'pebbles',
          'sunshine1',
          'gangster',
          'gloria',
          'darkangel',
          'bettyboop',
          'jessica1',
          'cheyenne',
          'dustin',
          'iubire',
          'a123456',
          'purple1',
          'bestfriends',
          'inlove',
          'batista',
          'karla',
          'chacha',
          'marian',
          'sexyme',
          'pogiako',
          'jordan1',
          '010203',
          'daddy1',
          'daddysgirl',
          'billabong',
          'pinky',
          'erika',
          'skater',
          'nenita',
          'tigger1',
          'gatito',
          'lokita',
          'maldita',
          'buttercup',
          'bambam',
          'glitter',
          '123789',
          'sister',
          'zacefron',
          'tokiohotel',
          'loveya',
          'lovebug',
          'bubblegum',
          'marissa',
          'cecilia',
          'lollypop',
          'nicolas',
          'puppies',
          'ariana',
          'chubby',
          'sexybitch',
          'roxana',
          'mememe',
          'susana',
          'baller',
          'hotstuff',
          'carter',
          'babylove',
          'angelina',
          'playgirl',
          'sweet16',
          '012345',
          'bhebhe',
          'marcos',
          'loveme1',
          'milagros',
          'lilmama',
          'beyonce',
          'lovely1',
          'catdog',
          'armando',
          'margarita',
          '151515',
          'loves',
          '202020',
          'gerard',
          'undertaker',
          'amistad',
          'capricorn',
          'delfin',
          'cheerleader',
          'password2',
          'PASSWORD',
          'lizzie',
          'matthew1',
          'enrique',
          'badgirl',
          '141414',
          'dancing',
          'cuteme',
          'amelia',
          'skyline',
          'angeles',
          'janine',
          'carlitos',
          'justme',
          'legolas',
          'michelle1',
          'cinderella',
          'jesuschrist',
          'ilovejesus',
          'tazmania',
          'tekiero',
          'thebest',
          'princesita',
          'lucky7',
          'jesucristo',
          'buddy1',
          'regina',
          'myself',
          'lipgloss',
          'jazmin',
          'rosita',
          'chichi',
          'pangit',
          'mierda',
          '741852963',
          'hernandez',
          'arturo',
          'silvia',
          'melvin',
          'celeste',
          'pussycat',
          'gorgeous',
          'honeyko',
          'mylife',
          'babyboo',
          'loveu',
          'lupita',
          'panthers',
          'hollywood',
          'alfredo',
          'musica',
          'hawaii',
          'sparkle',
          'kristina',
          'sexymama',
          'crazy',
          'scarface',
          '098765',
          'hayden',
          'micheal',
          '242424',
          '0987654321',
          'marisol',
          'jeremiah',
          'mhine',
          'isaiah',
          'lolipop',
          'butterfly1',
          'xbox360',
          'madalina',
          'anamaria',
          'yourmom',
          'jasmine1',
          'bubbles1',
          'beatriz',
          'diamonds',
          'friendship',
          'sweetness',
          'desiree',
          '741852',
          'hannah1',
          'bananas',
          'julius',
          'leanne',
          'marie1',
          'lover1',
          'twinkle',
          'february',
          'bebita',
          '87654321',
          'twilight',
          'imissyou',
          'pollito',
          'ashlee',
          'cookie1',
          '147852369',
          'beckham',
          'simone',
          'nursing',
          'torres',
          'damian',
          '123123123',
          'joshua1',
          'babyface',
          'dinamo',
          'mommy',
          'juliana',
          'cassandra',
          'redsox',
          'gundam',
          '0000',
          'ou812',
          'dave',
          'golf',
          'molson',
          'Monday',
          'newpass',
          'thx1138',
          '1',
          'Internet',
          'coke',
          'foobar',
          'abc',
          'fish',
          'fred',
          'help',
          'ncc1701d',
          'newuser',
          'none',
          'pat',
          'dog',
          'duck',
          'duke',
          'floyd',
          'guest',
          'joe',
          'kingfish',
          'micro',
          'sam',
          'telecom',
          'test1',
          '7777',
          'absolut',
          'babylon5',
          'backup',
          'bill',
          'bird33',
          'deliver',
          'fire',
          'flip',
          'galileo',
          'gopher',
          'hansolo',
          'jane',
          'jim',
          'mom',
          'passwd',
          'phil',
          'phish',
          'porsche911',
          'rain',
          'red',
          'sergei',
          'training',
          'truck',
          'video',
          'volvo',
          '007',
          '1969',
          '5683',
          'Bond007',
          'Friday',
          'Hendrix',
          'October',
          'Taurus',
          'aaa',
          'alexandr',
          'catalog',
          'challenge',
          'clipper',
          'coltrane',
          'cyrano',
          'dan',
          'dawn',
          'dean',
          'deutsch',
          'dilbert',
          'e-mail',
          'export',
          'ford',
          'fountain',
          'fox',
          'frog',
          'gabriell',
          'garlic',
          'goforit',
          'grateful',
          'hoops',
          'lady',
          'ledzep',
          'lee',
          'mailman',
          'mantra',
          'market',
          'mazda1',
          'metallic',
          'ncc1701e',
          'nesbitt',
          'open',
          'pete',
          'quest',
          'republic',
          'research',
          'supra',
          'tara',
          'testing',
          'xanadu',
          'xxxx',
          'zaphod',
          'zeus',
          '0007',
          '1022',
          '10sne1',
          '1973',
          '1978',
          '2000',
          '2222',
          '3bears',
          'Broadway',
          'Fisher',
          'Jeanne',
          'Killer',
          'Knight',
          'Master',
          'Pepper',
          'Sierra',
          'Tennis',
          'abacab',
          'abcd',
          'ace',
          'acropolis',
          'amy',
          'anders',
          'avenir',
          'basil',
          'bass',
          'beer',
          'ben',
          'bliss',
          'blowfish',
          'boss',
          'bridges',
          'buck',
          'bugsy',
          'bull',
          'cannondale',
          'canon',
          'catnip',
          'chip',
          'civil',
          'content',
          'cook',
          'cordelia',
          'crack1',
          'cyber',
          'daisie',
          'dark1',
          'database',
          'deadhead',
          'denali',
          'depeche',
          'dickens',
          'emmitt',
          'entropy',
          'farout',
          'farside',
          'feedback',
          'fidel',
          'firenze',
          'fish1',
          'fletch',
          'fool',
          'fozzie',
          'fun',
          'gargoyle',
          'gasman',
          'gold',
          'graphic',
          'hell',
          'image',
          'intern',
          'intrepid',
          'jeff',
          'jkl123',
          'joel',
          'johanna1',
          'kidder',
          'kim',
          'king',
          'kirk',
          'kris',
          'lambda',
          'leon',
          'logical',
          'lorrie',
          'major',
          'mariner',
          'mark1',
          'max',
          'media',
          'merlot',
          'midway',
          'mine',
          'mmouse',
          'moon',
          'mopar',
          'mortimer',
          'nermal',
          'nina',
          'olsen',
          'opera',
          'overkill',
          'pacers',
          'packer',
          'picard',
          'polar',
          'polo',
          'primus',
          'prometheus',
          'public',
          'radio',
          'rastafarian',
          'reptile',
          'rob',
          'robotech',
          'rodeo',
          'rolex',
          'rouge',
          'roy',
          'ruby',
          'salasana',
          'scarecrow',
          'scout',
          'scuba1',
          'sergey',
          'skibum',
          'skunk',
          'sound',
          'starter',
          'sting1',
          'sunbird',
          'tbird',
          'teflon',
          'temporal',
          'terminal',
          'the',
          'thejudge',
          'time',
          'toby',
          'today',
          'tokyo',
          'tree',
          'trout',
          'vader',
          'val',
          'valhalla',
          'windsurf',
          'wolf',
          'wolf1',
          'xcountry',
          'yoda',
          'yukon',
          '1213',
          '1214',
          '1225',
          '1313',
          '1818',
          '1975',
          '1977',
          '1991',
          '1kitty',
          '2001',
          '2020',
          '2112',
          '2kids',
          '333',
          '4444',
          '5050',
          '57chevy',
          '7dwarfs',
          'Animals',
          'Ariel',
          'Bismillah',
          'Booboo',
          'Boston',
          'Carol',
          'Computer',
          'Creative',
          'Curtis',
          'Denise',
          'Eagles',
          'Esther',
          'Fishing',
          'Freddy',
          'Gandalf',
          'Golden',
          'Goober',
          'Hacker',
          'Harley',
          'Henry',
          'Hershey',
          'Jackson',
          'Jersey',
          'Joanna',
          'Johnson',
          'Katie',
          'Kitten',
          'Liberty',
          'Lindsay',
          'Lizard',
          'Madeline',
          'Margaret',
          'Maxwell',
          'Money',
          'Monster',
          'Pamela',
          'Peaches',
          'Peter',
          'Phoenix',
          'Piglet',
          'Pookie',
          'Rabbit',
          'Raiders',
          'Random',
          'Russell',
          'Sammy',
          'Saturn',
          'Skeeter',
          'Smokey',
          'Sparky',
          'Speedy',
          'Sterling',
          'Theresa',
          'Thunder',
          'Vincent',
          'Willow',
          'Winnie',
          'Wolverine',
          'aaaa',
          'aardvark',
          'abbott',
          'acura',
          'admin',
          'admin1',
          'adrock',
          'aerobics',
          'agent',
          'airwolf',
          'ali',
          'alien',
          'allegro',
          'allstate',
          'altamira',
          'altima1',
          'andrew!',
          'ann',
          'anne',
          'anneli',
          'aptiva',
          'arrow',
          'asdf;lkj',
          'assmunch',
          'baraka',
          'barnyard',
          'bart',
          'bartman',
          'beasty',
          'beavis1',
          'bebe',
          'belgium',
          'beowulf',
          'beryl',
          'best',
          'bharat',
          'bichon',
          'bigal',
          'biker',
          'bilbo',
          'bills',
          'bimmer',
          'biochem',
          'birdy',
          'blinds',
          'blitz',
          'bluejean',
          'bogey',
          'bogus',
          'boulder',
          'bourbon',
          'boxer',
          'brain',
          'branch',
          'britain',
          'broker',
          'bucks',
          'buffett',
          'bugs',
          'bulls',
          'burns',
          'buzz',
          'c00per',
          'calgary',
          'camay',
          'carl',
          'cat',
          'cement',
          'cessna',
          'chad',
          'chainsaw',
          'chameleon',
          'chang',
          'chess',
          'chinook',
          'chouette',
          'chronos',
          'cicero',
          'circuit',
          'cirque',
          'cirrus',
          'clapton',
          'clarkson',
          'class',
          'claudel',
          'cleo',
          'cliff',
          'clock',
          'color',
          'comet',
          'concept',
          'concorde',
          'coolbean',
          'corky',
          'cornflake',
          'corwin',
          'cows',
          'crescent',
          'cross',
          'crowley',
          'cthulhu',
          'cunt',
          'current',
          'cutlass',
          'daedalus',
          'dagger1',
          'daily',
          'dale',
          'dana',
          'daytek',
          'dead',
          'decker',
          'dharma',
          'dillweed',
          'dipper',
          'disco',
          'dixon',
          'doitnow',
          'doors',
          'dork',
          'doug',
          'dutch',
          'effie',
          'ella',
          'elsie',
          'engage',
          'eric1',
          'ernie1',
          'escort1',
          'excel',
          'faculty',
          'fairview',
          'faust',
          'fenris',
          'finance',
          'first',
          'fishhead',
          'flanders',
          'fleurs',
          'flute',
          'flyboy',
          'flyer',
          'franka',
          'frederic',
          'free',
          'front242',
          'frontier',
          'fugazi',
          'funtime',
          'gaby',
          'gaelic',
          'gambler',
          'gammaphi',
          'garfunkel',
          'garth',
          'gary',
          'gateway2',
          'gator1',
          'gibbons',
          'gigi',
          'gilgamesh',
          'goat',
          'godiva',
          'goethe',
          'gofish',
          'good',
          'gramps',
          'gravis',
          'gray',
          'greed',
          'greg',
          'greg1',
          'greta',
          'gretzky',
          'guido',
          'gumby',
          'h2opolo',
          'hamid',
          'hank',
          'hawkeye1',
          'health1',
          'hello8',
          'help123',
          'helper',
          'homerj',
          'hoosier',
          'hope',
          'huang',
          'hugo',
          'hydrogen',
          'ib6ub9',
          'insight',
          'instructor',
          'integral',
          'iomega',
          'iris',
          'izzy',
          'jazz',
          'jean',
          'jeepster',
          'jetta1',
          'joanie',
          'josee',
          'joy',
          'julia2',
          'jumbo',
          'jump',
          'justice4',
          'kalamazoo',
          'kali',
          'kat',
          'kate',
          'kerala',
          'kids',
          'kiwi',
          'kleenex',
          'kombat',
          'lamer',
          'laser',
          'laserjet',
          'lassie1',
          'leblanc',
          'legal',
          'leo',
          'life',
          'lions',
          'liz',
          'logger',
          'logos',
          'loislane',
          'loki',
          'longer',
          'lori',
          'lost',
          'lotus',
          'lou',
          'macha',
          'macross',
          'madoka',
          'makeitso',
          'mallard',
          'marc',
          'math',
          'mattingly',
          'mechanic',
          'meister',
          'mercer',
          'merde',
          'merrill',
          'michal',
          'michou',
          'mickel',
          'minou',
          'mobydick',
          'modem',
          'mojo',
          'montana3',
          'montrose',
          'motor',
          'mowgli',
          'mulder1',
          'muscle',
          'neil',
          'neutrino',
          'newaccount',
          'nicklaus',
          'nightshade',
          'nightwing',
          'nike',
          'none1',
          'nopass',
          'nouveau',
          'novell',
          'oaxaca',
          'obiwan',
          'obsession',
          'orville',
          'otter',
          'ozzy',
          'packrat',
          'paint',
          'papa',
          'paradigm',
          'pass',
          'pavel',
          'peterk',
          'phialpha',
          'phishy',
          'piano1',
          'pianoman',
          'pianos',
          'pipeline',
          'plato',
          'play',
          'poetic',
          'print',
          'printing',
          'provider',
          'qqq111',
          'quebec',
          'qwer',
          'racer',
          'racerx',
          'radar',
          'rafiki',
          'raleigh',
          'rasta1',
          'redcloud',
          'redfish',
          'redwing',
          'redwood',
          'reed',
          'rene',
          'reznor',
          'rhino',
          'ripple',
          'rita',
          'robocop',
          'robotics',
          'roche',
          'roni',
          'rossignol',
          'rugger',
          'safety1',
          'saigon',
          'satori',
          'saturn5',
          'schnapps',
          'scotch',
          'scuba',
          'secret3',
          'seeker',
          'services',
          'sex',
          'shanghai',
          'shazam',
          'shelter',
          'sigmachi',
          'signal',
          'signature',
          'simsim',
          'skydive',
          'slick',
          'smegma',
          'smiths',
          'smurfy',
          'snow',
          'sober1',
          'sonics',
          'sony',
          'spazz',
          'sphynx',
          'spock',
          'spoon',
          'spot',
          'sprocket',
          'starbuck',
          'steel',
          'stephi',
          'sting',
          'stocks',
          'storage',
          'strat',
          'strato',
          'stud',
          'student2',
          'susanna',
          'swanson',
          'swim',
          'switzer',
          'system5',
          't-bone',
          'talon',
          'tarheel',
          'tata',
          'tazdevil',
          'tester',
          'testtest',
          'thisisit',
          'thorne',
          'tightend',
          'tim',
          'tom',
          'tool',
          'total',
          'toucan',
          'transfer',
          'transit',
          'transport',
          'trapper',
          'trash',
          'trophy',
          'tucson',
          'turbo2',
          'unity',
          'upsilon',
          'vedder',
          'vette',
          'vikram',
          'virago',
          'visual',
          'volcano',
          'walden',
          'waldo',
          'walleye',
          'webmaster',
          'wedge',
          'whale1',
          'whit',
          'whoville',
          'wibble',
          'will',
          'wombat1',
          'word',
          'world',
          'x-files',
          'xxx123',
          'zack',
          'zepplin',
          'zoltan',
          'zoomer',
          '123go',
          '21122112',
          '5555',
          '911',
          'FuckYou',
          'Fuckyou',
          'Gizmo',
          'Hello',
          'Michel',
          'Qwerty',
          'Windows',
          'angus',
          'aspen',
          'ass',
          'bird',
          'booster',
          'byteme',
          'cats',
          'changeit',
          'christia',
          'christoph',
          'classroom',
          'cloclo',
          'corrado',
          'dasha',
          'fiction',
          'french1',
          'fubar',
          'gator',
          'gilles',
          'gocougs',
          'hilbert',
          'hola',
          'home',
          'judy',
          'koko',
          'lulu',
          'mac',
          'macintosh',
          'mailer',
          'mars',
          'meow',
          'ne1469',
          'niki',
          'paul',
          'politics',
          'pomme',
          'property',
          'ruth',
          'sales',
          'salut',
          'scrooge',
          'skidoo',
          'spain',
          'surf',
          'sylvie',
          'symbol',
          'forum',
          'rotimi',
          'god',
          'saved',
          '2580',
          '1998',
          'xxx',
          '1928',
          '777',
          'info',
          'a',
          'netware',
          'sun',
          'tech',
          'doom',
          'mmm',
          'one',
          'ppp',
          '1911',
          '1948',
          '1996',
          '5252',
          'Champs',
          'Tuesday',
          'bach',
          'crow',
          'don',
          'draft',
          'hal9000',
          'herzog',
          'huey',
          'jethrotull',
          'jussi',
          'mail',
          'miki',
          'nicarao',
          'snowski',
          '1316',
          '1412',
          '1430',
          '1952',
          '1953',
          '1955',
          '1956',
          '1960',
          '1964',
          '1qw23e',
          '22',
          '2200',
          '2252',
          '3010',
          '3112',
          '4788',
          '6262',
          'Alpha',
          'Bastard',
          'Beavis',
          'Cardinal',
          'Celtics',
          'Cougar',
          'Darkman',
          'Figaro',
          'Fortune',
          'Geronimo',
          'Hammer',
          'Homer',
          'Janet',
          'Mellon',
          'Merlot',
          'Metallic',
          'Montreal',
          'Newton',
          'Paladin',
          'Peanuts',
          'Service',
          'Vernon',
          'Waterloo',
          'Webster',
          'aki123',
          'aqua',
          'aylmer',
          'beta',
          'bozo',
          'car',
          'chat',
          'chinacat',
          'cora',
          'courier',
          'dogbert',
          'eieio',
          'elina1',
          'fly',
          'funguy',
          'fuzz',
          'ggeorge',
          'glider1',
          'gone',
          'hawk',
          'heikki',
          'histoire',
          'hugh',
          'if6was9',
          'ingvar',
          'jan',
          'jedi',
          'jimi',
          'juhani',
          'khan',
          'lima',
          'midvale',
          'neko',
          'nesbit',
          'nexus6',
          'nisse',
          'notta1',
          'pam',
          'park',
          'pole',
          'pope',
          'pyro',
          'ram',
          'reliant',
          'rex',
          'rush',
          'seoul',
          'skip',
          'stan',
          'sue',
          'suzy',
          'tab',
          'testi',
          'thelorax',
          'tika',
          'tnt',
          'toto1',
          'tre',
          'wind',
          'x-men',
          'xyz',
          'zxc',
          '369',
          'Abcdef',
          'Asdfgh',
          'Changeme',
          'NCC1701',
          'Zxcvbnm',
          'demo',
          'doom2',
          'e',
          'good-luck',
          'homebrew',
          'm1911a1',
          'nat',
          'ne1410s',
          'ne14a69',
          'zhongguo',
          'sample123',
          '0852',
          'basf',
          'OU812',
          '!@#$%',
          'informix',
          'majordomo',
          'news',
          'temp',
          'trek',
          '!@#$%^',
          '!@#$%^&*',
          'Pentium',
          'Raistlin',
          'adi',
          'bmw',
          'law',
          'm',
          'new',
          'opus',
          'plus',
          'visa',
          'www',
          'y',
          'zzz',
          '1332',
          '1950',
          '3141',
          '3533',
          '4055',
          '4854',
          '6301',
          'Bonzo',
          'ChangeMe',
          'Front242',
          'Gretel',
          'Michel1',
          'Noriko',
          'Sidekick',
          'Sverige',
          'Swoosh',
          'Woodrow',
          'aa',
          'ayelet',
          'barn',
          'betacam',
          'biz',
          'boat',
          'cuda',
          'doc',
          'hal',
          'hallowell',
          'haro',
          'hosehead',
          'i',
          'ilmari',
          'irmeli',
          'j1l2t3',
          'jer',
          'kcin',
          'kerrya',
          'kissa2',
          'leaf',
          'lissabon',
          'mart',
          'matti1',
          'mech',
          'morecats',
          'paagal',
          'performa',
          'prof',
          'ratio',
          'ship',
          'slip',
          'stivers',
          'tapani',
          'targas',
          'test2',
          'test3',
          'tula',
          'unix',
          'user1',
          'xanth',
          '!@#$%^&',
          '1701d',
          '@#$%^&',
          'Qwert',
          'allo',
          'dirk',
          'go',
          'newcourt',
          'nite',
          'notused',
          'sss']

def CreatePasswordVerifier_Method1(password):
    verifier = 0
    password = password[:15]
    passwordarray = struct.pack('B', len(password)) + password.encode()
    for passwordbyte in passwordarray[::-1]:
        if verifier & 0x4000 == 0x0:
            intermediate1 = 0
        else:
            intermediate1 = 1
        intermediate2 = verifier * 2
        intermediate2 = intermediate2 & 0x7FFF
        intermediate3 = intermediate1 | intermediate2
        verifier = intermediate3 ^ P23Ord(passwordbyte)
    return verifier ^ 0xCE4B

def AnalyzeXORObfuscationStructure(data, passwordlistFilename):
    key, verifier = struct.unpack('<HH', data)
    password = None
    for candidate in GetDictionary(passwordlistFilename):
        if CreatePasswordVerifier_Method1(candidate) == verifier:
            password = candidate
            break
    return key, verifier, password

def rol(byte, count):
    return (byte << count | byte >> (8 - count)) & 0xFF

def ror(byte, count):
    return (byte >> count | byte << (8 - count)) & 0xFF

def RorBytes(data, index):
    return data[index:] + data[:index]

def Xor(data, key):
    if sys.version_info[0] > 2:
        return bytes([byte ^ key[index % len(key)] for index, byte in enumerate(data)])
    else:
        return ''.join([chr(ord(char) ^ ord(key[index % len(key)])) for index, char in enumerate(data)])

def XorDeobfuscate(data, key, position):
    return bytes([ror(byte, 5) for byte in Xor(data, RorBytes(key, position % 16))])

def FindOpcodeInLine(opcodes, line):
    for opcode in opcodes.split(','):
        if opcode.lower() in line.lower():
            return True
    return False

class cBIFF(cPluginParent):
    macroOnly = False
    name = 'BIFF plugin'

    def __init__(self, name, stream, options):
        self.streamname = name
        self.stream = stream
        self.options = options
        self.ran = False

    def Analyze(self):
        result = []
        dOpcodes = {
            0x06: 'FORMULA : Cell Formula',
            0x0A: 'EOF : End of File',
            0x0C: 'CALCCOUNT : Iteration Count',
            0x0D: 'CALCMODE : Calculation Mode',
            0x0E: 'PRECISION : Precision',
            0x0F: 'REFMODE : Reference Mode',
            0x10: 'DELTA : Iteration Increment',
            0x11: 'ITERATION : Iteration Mode',
            0x12: 'PROTECT : Protection Flag',
            0x13: 'PASSWORD : Protection Password',
            0x14: 'HEADER : Print Header on Each Page',
            0x15: 'FOOTER : Print Footer on Each Page',
            0x16: 'EXTERNCOUNT : Number of External References',
            0x17: 'EXTERNSHEET : External Reference',
            0x18: 'LABEL : Cell Value, String Constant',
            0x19: 'WINDOWPROTECT : Windows Are Protected',
            0x1A: 'VERTICALPAGEBREAKS : Explicit Column Page Breaks',
            0x1B: 'HORIZONTALPAGEBREAKS : Explicit Row Page Breaks',
            0x1C: 'NOTE : Comment Associated with a Cell',
            0x1D: 'SELECTION : Current Selection',
            0x22: '1904 : 1904 Date System',
            0x26: 'LEFTMARGIN : Left Margin Measurement',
            0x27: 'RIGHTMARGIN : Right Margin Measurement',
            0x28: 'TOPMARGIN : Top Margin Measurement',
            0x29: 'BOTTOMMARGIN : Bottom Margin Measurement',
            0x2A: 'PRINTHEADERS : Print Row/Column Labels',
            0x2B: 'PRINTGRIDLINES : Print Gridlines Flag',
            0x2F: 'FILEPASS : File Is Password-Protected',
            0x31: 'FONT',
            0x32: 'FONT2',
            0x3C: 'CONTINUE : Continues Long Records',
            0x3D: 'WINDOW1 : Window Information',
            0x40: 'BACKUP : Save Backup Version of the File',
            0x41: 'PANE : Number of Panes and Their Position',
            0x42: 'CODENAME : VBE Object Name',
            0x42: 'CODEPAGE : Default Code Page',
            0x4D: 'PLS : Environment-Specific Print Record',
            0x50: 'DCON : Data Consolidation Information',
            0x51: 'DCONREF : Data Consolidation References',
            0x52: 'DCONNAME : Data Consolidation Named References',
            0x55: 'DEFCOLWIDTH : Default Width for Columns',
            0x59: 'XCT : CRN Record Count',
            0x5A: 'CRN : Nonresident Operands',
            0x5B: 'FILESHARING : File-Sharing Information',
            0x5C: 'WRITEACCESS : Write Access User Name',
            0x5D: 'OBJ : Describes a Graphic Object',
            0x5E: 'UNCALCED : Recalculation Status',
            0x5F: 'SAVERECALC : Recalculate Before Save',
            0x60: 'TEMPLATE : Workbook Is a Template',
            0x63: 'OBJPROTECT : Objects Are Protected',
            0x7D: 'COLINFO : Column Formatting Information',
            0x7E: 'RK : Cell Value, RK Number',
            0x7F: 'IMDATA : Image Data',
            0x80: 'GUTS : Size of Row and Column Gutters',
            0x81: 'WSBOOL : Additional Workspace Information',
            0x82: 'GRIDSET : State Change of Gridlines Option',
            0x83: 'HCENTER : Center Between Horizontal Margins',
            0x84: 'VCENTER : Center Between Vertical Margins',
            0x85: 'BOUNDSHEET : Sheet Information',
            0x86: 'WRITEPROT : Workbook Is Write-Protected',
            0x87: 'ADDIN : Workbook Is an Add-in Macro',
            0x88: 'EDG : Edition Globals',
            0x89: 'PUB : Publisher',
            0x8C: 'COUNTRY : Default Country and WIN.INI Country',
            0x8D: 'HIDEOBJ : Object Display Options',
            0x90: 'SORT : Sorting Options',
            0x91: 'SUB : Subscriber',
            0x92: 'PALETTE : Color Palette Definition',
            0x94: 'LHRECORD : .WK? File Conversion Information',
            0x95: 'LHNGRAPH : Named Graph Information',
            0x96: 'SOUND : Sound Note',
            0x98: 'LPR : Sheet Was Printed Using LINE.PRINT(',
            0x99: 'STANDARDWIDTH : Standard Column Width',
            0x9A: 'FNGROUPNAME : Function Group Name',
            0x9B: 'FILTERMODE : Sheet Contains Filtered List',
            0x9C: 'FNGROUPCOUNT : Built-in Function Group Count',
            0x9D: 'AUTOFILTERINFO : Drop-Down Arrow Count',
            0x9E: 'AUTOFILTER : AutoFilter Data',
            0xA0: 'SCL : Window Zoom Magnification',
            0xA1: 'SETUP : Page Setup',
            0xA9: 'COORDLIST : Polygon Object Vertex Coordinates',
            0xAB: 'GCW : Global Column-Width Flags',
            0xAE: 'SCENMAN : Scenario Output Data',
            0xAF: 'SCENARIO : Scenario Data',
            0xB0: 'SXVIEW : View Definition',
            0xB1: 'SXVD : View Fields',
            0xB2: 'SXVI : View Item',
            0xB4: 'SXIVD : Row/Column Field IDs',
            0xB5: 'SXLI : Line Item Array',
            0xB6: 'SXPI : Page Item',
            0xB8: 'DOCROUTE : Routing Slip Information',
            0xB9: 'RECIPNAME : Recipient Name',
            0xBC: 'SHRFMLA : Shared Formula',
            0xBD: 'MULRK : Multiple  RK Cells',
            0xBE: 'MULBLANK : Multiple Blank Cells',
            0xC1: 'MMS :  ADDMENU / DELMENU Record Group Count',
            0xC2: 'ADDMENU : Menu Addition',
            0xC3: 'DELMENU : Menu Deletion',
            0xC5: 'SXDI : Data Item',
            0xC6: 'SXDB : PivotTable Cache Data',
            0xCD: 'SXSTRING : String',
            0xD0: 'SXTBL : Multiple Consolidation Source Info',
            0xD1: 'SXTBRGIITM : Page Item Name Count',
            0xD2: 'SXTBPG : Page Item Indexes',
            0xD3: 'OBPROJ : Visual Basic Project',
            0xD5: 'SXIDSTM : Stream ID',
            0xD6: 'RSTRING : Cell with Character Formatting',
            0xD7: 'DBCELL : Stream Offsets',
            0xDA: 'BOOKBOOL : Workbook Option Flag',
            0xDC: 'PARAMQRY : Query Parameters',
            0xDC: 'SXEXT : External Source Information',
            0xDD: 'SCENPROTECT : Scenario Protection',
            0xDE: 'OLESIZE : Size of OLE Object',
            0xDF: 'UDDESC : Description String for Chart Autoformat',
            0xE0: 'XF : Extended Format',
            0xE1: 'INTERFACEHDR : Beginning of User Interface Records',
            0xE2: 'INTERFACEEND : End of User Interface Records',
            0xE3: 'SXVS : View Source',
            0xE5: 'MERGECELLS : Merged Cells',
            0xEA: 'TABIDCONF : Sheet Tab ID of Conflict History',
            0xEB: 'MSODRAWINGGROUP : Microsoft Office Drawing Group',
            0xEC: 'MSODRAWING : Microsoft Office Drawing',
            0xED: 'MSODRAWINGSELECTION : Microsoft Office Drawing Selection',
            0xF0: 'SXRULE : PivotTable Rule Data',
            0xF1: 'SXEX : PivotTable View Extended Information',
            0xF2: 'SXFILT : PivotTable Rule Filter',
            0xF4: 'SXDXF : Pivot Table Formatting',
            0xF5: 'SXITM : Pivot Table Item Indexes',
            0xF6: 'SXNAME : PivotTable Name',
            0xF7: 'SXSELECT : PivotTable Selection Information',
            0xF8: 'SXPAIR : PivotTable Name Pair',
            0xF9: 'SXFMLA : Pivot Table Parsed Expression',
            0xFB: 'SXFORMAT : PivotTable Format Record',
            0xFC: 'SST : Shared String Table',
            0xFD: 'LABELSST : Cell Value, String Constant/ SST',
            0xFF: 'EXTSST : Extended Shared String Table',
            0x100: 'SXVDEX : Extended PivotTable View Fields',
            0x103: 'SXFORMULA : PivotTable Formula Record',
            0x122: 'SXDBEX : PivotTable Cache Data',
            0x13D: 'TABID : Sheet Tab Index Array',
            0x160: 'USESELFS : Natural Language Formulas Flag',
            0x161: 'DSF : Double Stream File',
            0x162: 'XL5MODIFY : Flag for  DSF',
            0x1A5: 'FILESHARING2 : File-Sharing Information for Shared Lists',
            0x1A9: 'USERBVIEW : Workbook Custom View Settings',
            0x1AA: 'USERSVIEWBEGIN : Custom View Settings',
            0x1AB: 'USERSVIEWEND : End of Custom View Records',
            0x1AD: 'QSI : External Data Range',
            0x1AE: 'SUPBOOK : Supporting Workbook',
            0x1AF: 'PROT4REV : Shared Workbook Protection Flag',
            0x1B0: 'CONDFMT : Conditional Formatting Range Information',
            0x1B1: 'CF : Conditional Formatting Conditions',
            0x1B2: 'DVAL : Data Validation Information',
            0x1B5: 'DCONBIN : Data Consolidation Information',
            0x1B6: 'TXO : Text Object',
            0x1B7: 'REFRESHALL : Refresh Flag',
            0x1B8: 'HLINK : Hyperlink',
            0x1BB: 'SXFDBTYPE : SQL Datatype Identifier',
            0x1BC: 'PROT4REVPASS : Shared Workbook Protection Password',
            0x1BE: 'DV : Data Validation Criteria',
            0x1C0: 'EXCEL9FILE : Excel 9 File',
            0x1C1: 'RECALCID : Recalc Information',
            0x200: 'DIMENSIONS : Cell Table Size',
            0x201: 'BLANK : Cell Value, Blank Cell',
            0x203: 'NUMBER : Cell Value, Floating-Point Number',
            0x204: 'LABEL : Cell Value, String Constant',
            0x205: 'BOOLERR : Cell Value, Boolean or Error',
            0x207: 'STRING : String Value of a Formula',
            0x208: 'ROW : Describes a Row',
            0x20B: 'INDEX : Index Record',
            0x218: 'NAME : Defined Name',
            0x221: 'ARRAY : Array-Entered Formula',
            0x223: 'EXTERNNAME : Externally Referenced Name',
            0x225: 'DEFAULTROWHEIGHT : Default Row Height',
            0x231: 'FONT : Font Description',
            0x236: 'TABLE : Data Table',
            0x23E: 'WINDOW2 : Sheet Window Information',
            0x27E: 'RK : Cell Value, RK Number',
            0x293: 'STYLE : Style Information',
            0x406: 'FORMULA : Cell Formula',
            0x41E: 'FORMAT : Number Format',
            0x800: 'HLINKTOOLTIP : Hyperlink Tooltip',
            0x801: 'WEBPUB : Web Publish Item',
            0x802: 'QSISXTAG : PivotTable and Query Table Extensions',
            0x803: 'DBQUERYEXT : Database Query Extensions',
            0x804: 'EXTSTRING :  FRT String',
            0x805: 'TXTQUERY : Text Query Information',
            0x806: 'QSIR : Query Table Formatting',
            0x807: 'QSIF : Query Table Field Formatting',
            0x809: 'BOF : Beginning of File',
            0x80A: 'OLEDBCONN : OLE Database Connection',
            0x80B: 'WOPT : Web Options',
            0x80C: 'SXVIEWEX : Pivot Table OLAP Extensions',
            0x80D: 'SXTH : PivotTable OLAP Hierarchy',
            0x80E: 'SXPIEX : OLAP Page Item Extensions',
            0x80F: 'SXVDTEX : View Dimension OLAP Extensions',
            0x810: 'SXVIEWEX9 : Pivot Table Extensions',
            0x812: 'CONTINUEFRT : Continued  FRT',
            0x813: 'REALTIMEDATA : Real-Time Data (RTD)',
            0x862: 'SHEETEXT : Extra Sheet Info',
            0x863: 'BOOKEXT : Extra Book Info',
            0x864: 'SXADDL : Pivot Table Additional Info',
            0x865: 'CRASHRECERR : Crash Recovery Error',
            0x866: 'HFPicture : Header / Footer Picture',
            0x867: 'FEATHEADR : Shared Feature Header',
            0x868: 'FEAT : Shared Feature Record',
            0x86A: 'DATALABEXT : Chart Data Label Extension',
            0x86B: 'DATALABEXTCONTENTS : Chart Data Label Extension Contents',
            0x86C: 'CELLWATCH : Cell Watch',
            0x86d: 'FEATINFO : Shared Feature Info Record',
            0x871: 'FEATHEADR11 : Shared Feature Header 11',
            0x872: 'FEAT11 : Shared Feature 11 Record',
            0x873: 'FEATINFO11 : Shared Feature Info 11 Record',
            0x874: 'DROPDOWNOBJIDS : Drop Down Object',
            0x875: 'CONTINUEFRT11 : Continue  FRT 11',
            0x876: 'DCONN : Data Connection',
            0x877: 'LIST12 : Extra Table Data Introduced in Excel 2007',
            0x878: 'FEAT12 : Shared Feature 12 Record',
            0x879: 'CONDFMT12 : Conditional Formatting Range Information 12',
            0x87A: 'CF12 : Conditional Formatting Condition 12',
            0x87B: 'CFEX : Conditional Formatting Extension',
            0x87C: 'XFCRC : XF Extensions Checksum',
            0x87D: 'XFEXT : XF Extension',
            0x87E: 'EZFILTER12 : AutoFilter Data Introduced in Excel 2007',
            0x87F: 'CONTINUEFRT12 : Continue FRT 12',
            0x881: 'SXADDL12 : Additional Workbook Connections Information',
            0x884: 'MDTINFO : Information about a Metadata Type',
            0x885: 'MDXSTR : MDX Metadata String',
            0x886: 'MDXTUPLE : Tuple MDX Metadata',
            0x887: 'MDXSET : Set MDX Metadata',
            0x888: 'MDXPROP : Member Property MDX Metadata',
            0x889: 'MDXKPI : Key Performance Indicator MDX Metadata',
            0x88A: 'MDTB : Block of Metadata Records',
            0x88B: 'PLV : Page Layout View Settings in Excel 2007',
            0x88C: 'COMPAT12 : Compatibility Checker 12',
            0x88D: 'DXF : Differential XF',
            0x88E: 'TABLESTYLES : Table Styles',
            0x88F: 'TABLESTYLE : Table Style',
            0x890: 'TABLESTYLEELEMENT : Table Style Element',
            0x892: 'STYLEEXT : Named Cell Style Extension',
            0x893: 'NAMEPUBLISH : Publish To Excel Server Data for Name',
            0x894: 'NAMECMT : Name Comment',
            0x895: 'SORTDATA12 : Sort Data 12',
            0x896: 'THEME : Theme',
            0x897: 'GUIDTYPELIB : VB Project Typelib GUID',
            0x898: 'FNGRP12 : Function Group',
            0x899: 'NAMEFNGRP12 : Extra Function Group',
            0x89A: 'MTRSETTINGS : Multi-Threaded Calculation Settings',
            0x89B: 'COMPRESSPICTURES : Automatic Picture Compression Mode',
            0x89C: 'HEADERFOOTER : Header Footer',
            0x8A3: 'FORCEFULLCALCULATION : Force Full Calculation Settings',
            0x8c1: 'LISTOBJ : List Object',
            0x8c2: 'LISTFIELD : List Field',
            0x8c3: 'LISTDV : List Data Validation',
            0x8c4: 'LISTCONDFMT : List Conditional Formatting',
            0x8c5: 'LISTCF : List Cell Formatting',
            0x8c6: 'FMQRY : Filemaker queries',
            0x8c7: 'FMSQRY : File maker queries',
            0x8c8: 'PLV : Page Layout View in Mac Excel 11',
            0x8c9: 'LNEXT : Extension information for borders in Mac Office 11',
            0x8ca: 'MKREXT : Extension information for markers in Mac Office 11'
        }

        # https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/0f2ea0a1-9fc8-468d-97aa-9d333b72d106?redirectedfrom=MSDN
        recordsNotXORObfuscated = [ 0x2F, # FILEPASS
                                    0xE1, # INTERFACEHDR
                                   0x138, # RRDHEAD
                                   0x194, # USREXCL
                                   0x195, # FILELOCK
                                   0x196, # RRDINFO
                                   0x809, # BOF
        ]

        if self.streamname in [['Workbook'], ['Book']]:
            self.ran = True
            stream = self.stream

            oParser = optparse.OptionParser()
            oParser.add_option('-s', '--strings', action='store_true', default=False, help='Dump strings')
            oParser.add_option('-a', '--hexascii', action='store_true', default=False, help='Dump hex ascii')
            oParser.add_option('-X', '--hex', action='store_true', default=False, help='Dump hex without whitespace')
            oParser.add_option('-R', '--hexrecord', action='store_true', default=False, help='Dump hex of complete record without whitespace')
            oParser.add_option('-b', '--formulabytes', action='store_true', default=False, help='Dump formula bytes')
            oParser.add_option('-d', '--dump', action='store_true', default=False, help='Dump')
            oParser.add_option('-x', '--xlm', action='store_true', default=False, help='Select all records relevant for Excel 4.0 macros')
            oParser.add_option('-o', '--opcode', type=str, default='', help='Opcode to filter for (use , to separate multiple opcodes')
            oParser.add_option('-f', '--find', type=str, default='', help='Content to search for')
            oParser.add_option('-c', '--csv', action='store_true', default=False, help='Produce CSV')
            oParser.add_option('-j', '--json', action='store_true', default=False, help='Produce JSON')
            oParser.add_option('-r', '--cellrefformat', type=str, default='rc', help='Cell reference format (RC, LN)')
            oParser.add_option('-S', '--statistics', action='store_true', default=False, help='Produce BIFF record statistics')
            oParser.add_option('-w', '--wordlist', type=str, default='', help='Try to crack password with provided passwordlist')
            oParser.add_option('-D', '--xordeobfuscate', action='store_true', default=False, help='XOR Deobfuscate')
            (options, args) = oParser.parse_args(self.options.split(' '))

            if options.find.startswith('0x'):
                options.find = binascii.a2b_hex(options.find[2:])

            if options.wordlist == '':
                passwordlistFilename = '.'
            else:
                passwordlistFilename = options.wordlist

            position = 0
            macros4Found = False
            filepassFound = False
            isBIFF8 = True
            dSheetNames = {}
            sheetNames = []
            definesNames = []
            currentSheetname = ''
            dOpcodeStatistics = {}
            xorObfuscationKey = None
            while position < len(stream):
                decrypted = False
                formatcodes = 'HH'
                formatsize = struct.calcsize(formatcodes)
                if len(stream[position:position + formatsize]) < formatsize:
                    break
                header = stream[position:position + formatsize]
                opcode, length = struct.unpack(formatcodes, header)
                dOpcodeStatistics[opcode] = [dOpcodeStatistics.get(opcode, [0, 0])[0] + 1, dOpcodeStatistics.get(opcode, [0, 0])[1] + length]
                data = stream[position + formatsize:position + formatsize + length]
                if xorObfuscationKey != None and xorObfuscationKey != '?' and options.xordeobfuscate:
                    if not opcode in recordsNotXORObfuscated:
                        dataDeobfuscated = XorDeobfuscate(data, xorObfuscationKey, position + 4 + len(data))
                        decrypted = True
                        if opcode == 0x85: #BOUNDSHEET
                            data = data[:4] + dataDeobfuscated[4:]
                        else:
                            data = dataDeobfuscated
                positionBIFFRecord = position
                position = position + formatsize + length

                if opcode in dOpcodes:
                    opcodename = dOpcodes[opcode]
                else:
                    opcodename = ''
                line = '%04x %6d %s' % (opcode, length, opcodename)

                csvrow = None

                # PASSWORD record and PROT4REVPASS reconrd
                if (opcode == 0x13 or opcode == 0x01bc) and len(data) == 2:
                    if not filepassFound or decrypted:
                        verifier = struct.unpack('<H', data)[0]
                        if verifier == 0:
                            line += ' - password not set'
                        else:
                            password = None
                            for candidate in GetDictionary(passwordlistFilename):
                                if CreatePasswordVerifier_Method1(candidate) == verifier:
                                    password = candidate
                                    line += ' - password: ' + password
                                    break
                            if password == None:
                                    line += ' - password not recovered: verifier 0x%04x' % verifier

                # FORMULA record
                if opcode == 0x06 and len(data) >= 21:
                    if not filepassFound:
                        cellref, dummy = ParseLoc(data, options.cellrefformat, True)
                        formatcodes = 'H'
                        formatsize = struct.calcsize(formatcodes)
                        length = struct.unpack(formatcodes, data[20:20 + formatsize])[0]
                        expression = data[22:]
                        parsedExpression, stack = ParseExpression(expression, definesNames, sheetNames, options.cellrefformat)
                        line += ' - %s len=%d %s' % (cellref, length, parsedExpression)
                        if len(stack) == 1:
                            csvrow = [currentSheetname, cellref, stack[0], '']
                        else:
                            csvrow = [currentSheetname, cellref, repr(stack), '']
                        if options.formulabytes:
                            data_hex = P23Decode(binascii.b2a_hex(data))
                            spaced_data_hex = ' '.join(a+b for a,b in zip(data_hex[::2], data_hex[1::2]))
                            line += '\nFORMULA BYTES: %s' % spaced_data_hex

                # LABEL record #a# difference BIFF4 and BIFF5+
                if opcode == 0x18 and len(data) >= 16:
                    if not filepassFound:
                        flags = P23Ord(data[0])
                        lnName = P23Ord(data[3])
                        szFormula = P23Ord(data[4]) + P23Ord(data[5]) * 0x100
                        offset = 14
                        if P23Ord(data[offset]) == 0:  #a# hack with BIFF8 Unicode
                            offset = 15
                        if flags & 0x20:
                            dBuildInNames = {1: 'Auto_Open', 2: 'Auto_Close'}
                            code = P23Ord(data[offset])
                            name = dBuildInNames.get(code, '?')
                            line += ' - built-in-name %d %s' % (code, name)
                        else:
                            name = P23Decode(data[offset:offset+lnName])
                            line += ' - %s' % (name)
                        definesNames.append(name)
                        if flags & 0x01:
                            line += ' hidden'
                        try:
                            parsedExpression, stack = ParseExpression(data[offset+lnName:offset+lnName+szFormula], definesNames, sheetNames, options.cellrefformat)
                        except IndexError:
                            parsedExpression = '*PARSING ERROR*'
                        line += ' len=%d %s' % (szFormula, parsedExpression)

                # FILEPASS record
                if opcode == 0x2f:
                    filepassFound = True
                    if len(data) == 4:
                        line += ' - XOR obfuscation < BIFF8'
                        key, verifier, password = AnalyzeXORObfuscationStructure(data, passwordlistFilename)
                        xorObfuscationKey = '?'
                        if password != None:
                            line += ' - password: ' + password
                            if password == 'VelvetSweatshop':
                                keyVelvetSweatshop = binascii.a2b_hex('87 6B 9A E2 1E E3 05 62 1E 69 96 60 98 6E 94 04'.replace(' ', ''))
                                xorObfuscationKey = keyVelvetSweatshop
                    elif len(data) >= 6:
                        formatcodes = '<HHH'
                        formatsize = struct.calcsize(formatcodes)
                        encryptionMethod, encryptionKey, hashValue = struct.unpack(formatcodes, data[0:formatsize])
                        if encryptionMethod == 0:
                            line += ' - XOR obfuscation BIFF8'
                            key, verifier, password = AnalyzeXORObfuscationStructure(data[2:], passwordlistFilename)
                            if password != None:
                                line += ' - password: ' + password
                                if password == 'VelvetSweatshop':
                                    keyVelvetSweatshop = binascii.a2b_hex('87 6B 9A E2 1E E3 05 62 1E 69 96 60 98 6E 94 04'.replace(' ', ''))
                                    xorObfuscationKey = keyVelvetSweatshop
                            else:
                                xorObfuscationKey = '?'
                        elif encryptionMethod == 1:
                            line += ' - RC4'
                        else:
                            line += ' - unknown encryption method 0x%04x' % encryptionMethod

                # WRITEACCESS record
                if opcode == 0x5C and len(data) == 112 and xorObfuscationKey == '?' and data[-0x10:] == data[-0x20:-0x10]:
                    # extract 16-byte long XOR obfuscation key from WRITEACCESS record that contains a username that is padded with space characters (0x20) to a length of 112 bytes
                    keyextracted = [byte ^ rol(0x20, 5) for byte in data[-0x10:]]
                    keyextracted = RorBytes(keyextracted, (positionBIFFRecord + 8 + len(data)) % 16)
                    xorObfuscationKey = keyextracted
                    if xorObfuscationKey != None and xorObfuscationKey != '?' and options.xordeobfuscate:
                        data = XorDeobfuscate(data, xorObfuscationKey, positionBIFFRecord + 4 + len(data))
                        decrypted = True

                # BOUNDSHEET record
                if opcode == 0x85 and len(data) >= 6:
                    if not filepassFound or xorObfuscationKey != None and xorObfuscationKey != '?' and options.xordeobfuscate:
                        formatcodes = '<IBB'
                        formatsize = struct.calcsize(formatcodes)
                        positionBOF, sheetState, sheetType = struct.unpack(formatcodes, data[0:formatsize])
                        dSheetType = {0: 'worksheet or dialog sheet', 1: 'Excel 4.0 macro sheet', 2: 'chart', 6: 'Visual Basic module'}
                        if sheetType == 1:
                            macros4Found = True
                        sheetName = ShortXLUnicodeString(data[6:], isBIFF8)
                        dSheetNames[positionBOF] = sheetName
                        sheetNames.append(sheetName)

                        dSheetState = {0: 'visible', 1: 'hidden', 2: 'very hidden', 3: 'visibility=3'}
                        visibility = ''
                        if sheetState > 3:
                            visibility = 'reserved bits not zero: 0x%02x ' % (sheetState & 0xFC)
                        visibility += dSheetState.get(sheetState & 3, '0x%02x' % (sheetState & 3))

                        line += ' - %s, %s - %s' % (dSheetType.get(sheetType, '%02x' % sheetType), visibility, sheetName)

                # BOF record
                if opcode == 0x0809 and len(data) >= 8:
                    if not filepassFound:
                        formatcodes = '<HHHH'
                        formatsize = struct.calcsize(formatcodes)
                        vers, dt, rupBuild, rupYear = struct.unpack(formatcodes, data[0:formatsize])
                        dBIFFVersion = {0x0500: 'BIFF5/BIFF7', 0x0600: 'BIFF8'}
                        isBIFF8 = dBIFFVersion == 0x0600
                        dStreamType = {5: 'workbook', 6: 'Visual Basic Module', 0x10: 'dialog sheet/worksheet', 0x20: 'chart sheet', 0x40: 'Excel 4.0 macro sheet', 0x100: 'Workspace file'}
                        line += ' - %s %s 0x%04x %d' % (dBIFFVersion.get(vers, '0x%04x' % vers), dStreamType.get(dt, '0x%04x' % dt), rupBuild, rupYear)
                        if positionBIFFRecord in dSheetNames:
                            line += ' - %s' % (dSheetNames[positionBIFFRecord])
                            currentSheetname = dSheetNames[positionBIFFRecord]

                # STRING record
                if opcode == 0x207 and len(data) >= 4:
                    if not filepassFound:
                        values = list(Strings(data[3:]).values())
                        strings = ''
                        if values[0] != []:
                            strings = values[0][0].encode()
                        if values[1] != []:
                            if strings != '':
                                strings += ' '
                            strings += ' '.join(values[1])
                        line += ' - %s' % strings

                # number record
                if opcode == 0x0203:
                    if not filepassFound:
                        cellref, data2 = ParseLoc(data, options.cellrefformat, True)
                        formatcodes = '<Hd'
                        formatsize = struct.calcsize(formatcodes)
                        xf, value = struct.unpack(formatcodes, data2[:formatsize])
                        line += ' - %s %.20f' % (cellref, value)
                        csvrow = [currentSheetname, cellref, '', '%.20f' % value]

                # RK record
                if opcode == 0x027E and len(data) == 10:
                    if not filepassFound:
                        cellref, data2 = ParseLoc(data, options.cellrefformat, True)
                        formatcodes = '<H'
                        formatsize = struct.calcsize(formatcodes)
                        xf = struct.unpack(formatcodes, data2[:formatsize])
                        value = DecodeRKValue(data2[formatsize:])
                        line += ' - %s %f' % (cellref, value)
                        csvrow = [currentSheetname, cellref, '', '%.20f' % value]

                if options.find == '' and options.opcode == '' and not options.xlm or options.opcode != '' and FindOpcodeInLine(options.opcode, line) or options.find != '' and options.find.encode() in data or options.xlm and opcode in [0x06, 0x18, 0x85, 0x207]:
                    if not options.hex and not options.dump:
                        if options.csv or options.json:
                            if csvrow != None:
                                result.append(csvrow)
                        else:
                            result.append(line)

                    if options.hexascii:
                        result.extend(' ' + foundstring for foundstring in HexASCII(data, 8))
                    elif options.strings:
                        dEncodings = {'s': 'ASCII', 'L': 'UNICODE'}
                        for encoding, strings in Strings(data).items():
                            if len(strings) > 0:
                                result.append(' ' + dEncodings[encoding] + ':')
                                result.extend('  ' + foundstring for foundstring in strings)
                    elif options.hex:
                        result.append(binascii.b2a_hex(data).decode('latin'))
                    elif options.hexrecord:
                        result.append(' ' + binascii.b2a_hex(header + data).decode('latin'))
                    elif options.dump:
                        result = data

            if options.xlm and filepassFound and not (xorObfuscationKey != None and xorObfuscationKey != '?' and options.xordeobfuscate):
                result = ['Warning: FILEPASS record found, file is password protected']
            elif options.statistics:
                stats = []
                for opcode in sorted(dOpcodeStatistics.keys()):
                    stats.append((opcode, dOpcodes.get(opcode, ''), dOpcodeStatistics[opcode][0], dOpcodeStatistics[opcode][1]))
                if options.csv:
                    result = [MakeCSVLine(['opcode', 'description', 'count', 'totalsize'], DEFAULT_SEPARATOR, QUOTE)]
                else:
                    result = []
                for item in stats:
                    if options.csv:
                        result.append(MakeCSVLine(item, DEFAULT_SEPARATOR, QUOTE))
                    else:
                        result.append('%d %s: %d %d' % item)
            elif options.xlm and not macros4Found:
                result = []
            elif options.csv:
                result = [MakeCSVLine(row, DEFAULT_SEPARATOR, QUOTE) for row in [['Sheet', 'Reference', 'Formula', 'Value']] + result]
            elif options.json:
                result = json.dumps(result)
            elif filepassFound:
                result.append('Warning: FILEPASS record found, file is password protected')

        return result

AddPlugin(cBIFF)
