From 9d83ad93d04a1e16fe4a2acadf5f9f10bef6d1b9 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 5 Jun 2021 21:25:06 +0530 Subject: [cleanup] Mark unused files --- devscripts/buildserver.py | 2 + devscripts/gh-pages.unused/add-version.py | 43 ++ devscripts/gh-pages.unused/generate-download.py | 22 + devscripts/gh-pages.unused/sign-versions.py | 34 + devscripts/gh-pages.unused/update-copyright.py | 21 + devscripts/gh-pages.unused/update-feed.py | 76 +++ devscripts/gh-pages.unused/update-sites.py | 37 ++ devscripts/gh-pages/add-version.py | 43 -- devscripts/gh-pages/generate-download.py | 22 - devscripts/gh-pages/sign-versions.py | 34 - devscripts/gh-pages/update-copyright.py | 21 - devscripts/gh-pages/update-feed.py | 76 --- devscripts/gh-pages/update-sites.py | 37 -- devscripts/release.sh | 1 + devscripts/wine-py2exe.sh | 2 + test/swftests.unused/.gitignore | 1 + test/swftests.unused/ArrayAccess.as | 19 + test/swftests.unused/ClassCall.as | 17 + test/swftests.unused/ClassConstruction.as | 15 + test/swftests.unused/ConstArrayAccess.as | 18 + test/swftests.unused/ConstantInt.as | 12 + test/swftests.unused/DictCall.as | 10 + test/swftests.unused/EqualsOperator.as | 10 + test/swftests.unused/LocalVars.as | 13 + test/swftests.unused/MemberAssignment.as | 22 + test/swftests.unused/NeOperator.as | 24 + test/swftests.unused/PrivateCall.as | 21 + test/swftests.unused/PrivateVoidCall.as | 22 + test/swftests.unused/StaticAssignment.as | 13 + test/swftests.unused/StaticRetrieval.as | 16 + test/swftests.unused/StringBasics.as | 11 + test/swftests.unused/StringCharCodeAt.as | 11 + test/swftests.unused/StringConversion.as | 11 + test/swftests/.gitignore | 1 - test/swftests/ArrayAccess.as | 19 - test/swftests/ClassCall.as | 17 - test/swftests/ClassConstruction.as | 15 - test/swftests/ConstArrayAccess.as | 18 - test/swftests/ConstantInt.as | 12 - test/swftests/DictCall.as | 10 - test/swftests/EqualsOperator.as | 10 - test/swftests/LocalVars.as | 13 - test/swftests/MemberAssignment.as | 22 - test/swftests/NeOperator.as | 24 - test/swftests/PrivateCall.as | 21 - test/swftests/PrivateVoidCall.as | 22 - test/swftests/StaticAssignment.as | 13 - test/swftests/StaticRetrieval.as | 16 - test/swftests/StringBasics.as | 11 - test/swftests/StringCharCodeAt.as | 11 - test/swftests/StringConversion.as | 11 - test/test_aes.py | 1 - test/test_swfinterp.py | 80 --- test/test_swfinterp.py.disabled | 80 +++ yt_dlp/swfinterp.py | 834 ------------------------ yt_dlp/swfinterp.py.disabled | 834 ++++++++++++++++++++++++ 56 files changed, 1418 insertions(+), 1414 deletions(-) create mode 100644 devscripts/gh-pages.unused/add-version.py create mode 100644 devscripts/gh-pages.unused/generate-download.py create mode 100644 devscripts/gh-pages.unused/sign-versions.py create mode 100644 devscripts/gh-pages.unused/update-copyright.py create mode 100644 devscripts/gh-pages.unused/update-feed.py create mode 100644 devscripts/gh-pages.unused/update-sites.py delete mode 100755 devscripts/gh-pages/add-version.py delete mode 100755 devscripts/gh-pages/generate-download.py delete mode 100755 devscripts/gh-pages/sign-versions.py delete mode 100755 devscripts/gh-pages/update-copyright.py delete mode 100755 devscripts/gh-pages/update-feed.py delete mode 100755 devscripts/gh-pages/update-sites.py create mode 100644 test/swftests.unused/.gitignore create mode 100644 test/swftests.unused/ArrayAccess.as create mode 100644 test/swftests.unused/ClassCall.as create mode 100644 test/swftests.unused/ClassConstruction.as create mode 100644 test/swftests.unused/ConstArrayAccess.as create mode 100644 test/swftests.unused/ConstantInt.as create mode 100644 test/swftests.unused/DictCall.as create mode 100644 test/swftests.unused/EqualsOperator.as create mode 100644 test/swftests.unused/LocalVars.as create mode 100644 test/swftests.unused/MemberAssignment.as create mode 100644 test/swftests.unused/NeOperator.as create mode 100644 test/swftests.unused/PrivateCall.as create mode 100644 test/swftests.unused/PrivateVoidCall.as create mode 100644 test/swftests.unused/StaticAssignment.as create mode 100644 test/swftests.unused/StaticRetrieval.as create mode 100644 test/swftests.unused/StringBasics.as create mode 100644 test/swftests.unused/StringCharCodeAt.as create mode 100644 test/swftests.unused/StringConversion.as delete mode 100644 test/swftests/.gitignore delete mode 100644 test/swftests/ArrayAccess.as delete mode 100644 test/swftests/ClassCall.as delete mode 100644 test/swftests/ClassConstruction.as delete mode 100644 test/swftests/ConstArrayAccess.as delete mode 100644 test/swftests/ConstantInt.as delete mode 100644 test/swftests/DictCall.as delete mode 100644 test/swftests/EqualsOperator.as delete mode 100644 test/swftests/LocalVars.as delete mode 100644 test/swftests/MemberAssignment.as delete mode 100644 test/swftests/NeOperator.as delete mode 100644 test/swftests/PrivateCall.as delete mode 100644 test/swftests/PrivateVoidCall.as delete mode 100644 test/swftests/StaticAssignment.as delete mode 100644 test/swftests/StaticRetrieval.as delete mode 100644 test/swftests/StringBasics.as delete mode 100644 test/swftests/StringCharCodeAt.as delete mode 100644 test/swftests/StringConversion.as delete mode 100644 test/test_swfinterp.py create mode 100644 test/test_swfinterp.py.disabled delete mode 100644 yt_dlp/swfinterp.py create mode 100644 yt_dlp/swfinterp.py.disabled diff --git a/devscripts/buildserver.py b/devscripts/buildserver.py index 9b5305a67..cd544b816 100644 --- a/devscripts/buildserver.py +++ b/devscripts/buildserver.py @@ -1,3 +1,5 @@ +# UNUSED + #!/usr/bin/python3 import argparse diff --git a/devscripts/gh-pages.unused/add-version.py b/devscripts/gh-pages.unused/add-version.py new file mode 100644 index 000000000..9ea01374d --- /dev/null +++ b/devscripts/gh-pages.unused/add-version.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +from __future__ import unicode_literals + +import json +import sys +import hashlib +import os.path + + +if len(sys.argv) <= 1: + print('Specify the version number as parameter') + sys.exit() +version = sys.argv[1] + +with open('update/LATEST_VERSION', 'w') as f: + f.write(version) + +versions_info = json.load(open('update/versions.json')) +if 'signature' in versions_info: + del versions_info['signature'] + +new_version = {} + +filenames = { + 'bin': 'yt-dlp', + 'exe': 'yt-dlp.exe', + 'tar': 'yt-dlp-%s.tar.gz' % version} +build_dir = os.path.join('..', '..', 'build', version) +for key, filename in filenames.items(): + url = 'https://yt-dl.org/downloads/%s/%s' % (version, filename) + fn = os.path.join(build_dir, filename) + with open(fn, 'rb') as f: + data = f.read() + if not data: + raise ValueError('File %s is empty!' % fn) + sha256sum = hashlib.sha256(data).hexdigest() + new_version[key] = (url, sha256sum) + +versions_info['versions'][version] = new_version +versions_info['latest'] = version + +with open('update/versions.json', 'w') as jsonf: + json.dump(versions_info, jsonf, indent=4, sort_keys=True) diff --git a/devscripts/gh-pages.unused/generate-download.py b/devscripts/gh-pages.unused/generate-download.py new file mode 100644 index 000000000..a873d32ee --- /dev/null +++ b/devscripts/gh-pages.unused/generate-download.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +from __future__ import unicode_literals + +import json + +versions_info = json.load(open('update/versions.json')) +version = versions_info['latest'] +version_dict = versions_info['versions'][version] + +# Read template page +with open('download.html.in', 'r', encoding='utf-8') as tmplf: + template = tmplf.read() + +template = template.replace('@PROGRAM_VERSION@', version) +template = template.replace('@PROGRAM_URL@', version_dict['bin'][0]) +template = template.replace('@PROGRAM_SHA256SUM@', version_dict['bin'][1]) +template = template.replace('@EXE_URL@', version_dict['exe'][0]) +template = template.replace('@EXE_SHA256SUM@', version_dict['exe'][1]) +template = template.replace('@TAR_URL@', version_dict['tar'][0]) +template = template.replace('@TAR_SHA256SUM@', version_dict['tar'][1]) +with open('download.html', 'w', encoding='utf-8') as dlf: + dlf.write(template) diff --git a/devscripts/gh-pages.unused/sign-versions.py b/devscripts/gh-pages.unused/sign-versions.py new file mode 100644 index 000000000..fa389c358 --- /dev/null +++ b/devscripts/gh-pages.unused/sign-versions.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +from __future__ import unicode_literals, with_statement + +import rsa +import json +from binascii import hexlify + +try: + input = raw_input +except NameError: + pass + +versions_info = json.load(open('update/versions.json')) +if 'signature' in versions_info: + del versions_info['signature'] + +print('Enter the PKCS1 private key, followed by a blank line:') +privkey = b'' +while True: + try: + line = input() + except EOFError: + break + if line == '': + break + privkey += line.encode('ascii') + b'\n' +privkey = rsa.PrivateKey.load_pkcs1(privkey) + +signature = hexlify(rsa.pkcs1.sign(json.dumps(versions_info, sort_keys=True).encode('utf-8'), privkey, 'SHA-256')).decode() +print('signature: ' + signature) + +versions_info['signature'] = signature +with open('update/versions.json', 'w') as versionsf: + json.dump(versions_info, versionsf, indent=4, sort_keys=True) diff --git a/devscripts/gh-pages.unused/update-copyright.py b/devscripts/gh-pages.unused/update-copyright.py new file mode 100644 index 000000000..e122d0283 --- /dev/null +++ b/devscripts/gh-pages.unused/update-copyright.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from __future__ import with_statement, unicode_literals + +import datetime +import glob +import io # For Python 2 compatibility +import os +import re + +year = str(datetime.datetime.now().year) +for fn in glob.glob('*.html*'): + with io.open(fn, encoding='utf-8') as f: + content = f.read() + newc = re.sub(r'(?PCopyright © 2011-)(?P[0-9]{4})', 'Copyright © 2011-' + year, content) + if content != newc: + tmpFn = fn + '.part' + with io.open(tmpFn, 'wt', encoding='utf-8') as outf: + outf.write(newc) + os.rename(tmpFn, fn) diff --git a/devscripts/gh-pages.unused/update-feed.py b/devscripts/gh-pages.unused/update-feed.py new file mode 100644 index 000000000..c9f2fdb07 --- /dev/null +++ b/devscripts/gh-pages.unused/update-feed.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +from __future__ import unicode_literals + +import datetime +import io +import json +import textwrap + + +atom_template = textwrap.dedent("""\ + + + + yt-dlp releases + https://yt-dl.org/feed/yt-dlp-updates-feed + @TIMESTAMP@ + @ENTRIES@ + """) + +entry_template = textwrap.dedent(""" + + https://yt-dl.org/feed/yt-dlp-updates-feed/yt-dlp-@VERSION@ + New version @VERSION@ + + +
+ Downloads available at https://yt-dl.org/downloads/@VERSION@/ +
+
+ + The yt-dlp maintainers + + @TIMESTAMP@ +
+ """) + +now = datetime.datetime.now() +now_iso = now.isoformat() + 'Z' + +atom_template = atom_template.replace('@TIMESTAMP@', now_iso) + +versions_info = json.load(open('update/versions.json')) +versions = list(versions_info['versions'].keys()) +versions.sort() + +entries = [] +for v in versions: + fields = v.split('.') + year, month, day = map(int, fields[:3]) + faked = 0 + patchlevel = 0 + while True: + try: + datetime.date(year, month, day) + except ValueError: + day -= 1 + faked += 1 + assert day > 0 + continue + break + if len(fields) >= 4: + try: + patchlevel = int(fields[3]) + except ValueError: + patchlevel = 1 + timestamp = '%04d-%02d-%02dT00:%02d:%02dZ' % (year, month, day, faked, patchlevel) + + entry = entry_template.replace('@TIMESTAMP@', timestamp) + entry = entry.replace('@VERSION@', v) + entries.append(entry) + +entries_str = textwrap.indent(''.join(entries), '\t') +atom_template = atom_template.replace('@ENTRIES@', entries_str) + +with io.open('update/releases.atom', 'w', encoding='utf-8') as atom_file: + atom_file.write(atom_template) diff --git a/devscripts/gh-pages.unused/update-sites.py b/devscripts/gh-pages.unused/update-sites.py new file mode 100644 index 000000000..b53685fcc --- /dev/null +++ b/devscripts/gh-pages.unused/update-sites.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +from __future__ import unicode_literals + +import sys +import os +import textwrap + +# We must be able to import yt_dlp +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + +import yt_dlp + + +def main(): + with open('supportedsites.html.in', 'r', encoding='utf-8') as tmplf: + template = tmplf.read() + + ie_htmls = [] + for ie in yt_dlp.list_extractors(age_limit=None): + ie_html = '{}'.format(ie.IE_NAME) + ie_desc = getattr(ie, 'IE_DESC', None) + if ie_desc is False: + continue + elif ie_desc is not None: + ie_html += ': {}'.format(ie.IE_DESC) + if not ie.working(): + ie_html += ' (Currently broken)' + ie_htmls.append('
  • {}
  • '.format(ie_html)) + + template = template.replace('@SITES@', textwrap.indent('\n'.join(ie_htmls), '\t')) + + with open('supportedsites.html', 'w', encoding='utf-8') as sitesf: + sitesf.write(template) + + +if __name__ == '__main__': + main() diff --git a/devscripts/gh-pages/add-version.py b/devscripts/gh-pages/add-version.py deleted file mode 100755 index 9ea01374d..000000000 --- a/devscripts/gh-pages/add-version.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import unicode_literals - -import json -import sys -import hashlib -import os.path - - -if len(sys.argv) <= 1: - print('Specify the version number as parameter') - sys.exit() -version = sys.argv[1] - -with open('update/LATEST_VERSION', 'w') as f: - f.write(version) - -versions_info = json.load(open('update/versions.json')) -if 'signature' in versions_info: - del versions_info['signature'] - -new_version = {} - -filenames = { - 'bin': 'yt-dlp', - 'exe': 'yt-dlp.exe', - 'tar': 'yt-dlp-%s.tar.gz' % version} -build_dir = os.path.join('..', '..', 'build', version) -for key, filename in filenames.items(): - url = 'https://yt-dl.org/downloads/%s/%s' % (version, filename) - fn = os.path.join(build_dir, filename) - with open(fn, 'rb') as f: - data = f.read() - if not data: - raise ValueError('File %s is empty!' % fn) - sha256sum = hashlib.sha256(data).hexdigest() - new_version[key] = (url, sha256sum) - -versions_info['versions'][version] = new_version -versions_info['latest'] = version - -with open('update/versions.json', 'w') as jsonf: - json.dump(versions_info, jsonf, indent=4, sort_keys=True) diff --git a/devscripts/gh-pages/generate-download.py b/devscripts/gh-pages/generate-download.py deleted file mode 100755 index a873d32ee..000000000 --- a/devscripts/gh-pages/generate-download.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import unicode_literals - -import json - -versions_info = json.load(open('update/versions.json')) -version = versions_info['latest'] -version_dict = versions_info['versions'][version] - -# Read template page -with open('download.html.in', 'r', encoding='utf-8') as tmplf: - template = tmplf.read() - -template = template.replace('@PROGRAM_VERSION@', version) -template = template.replace('@PROGRAM_URL@', version_dict['bin'][0]) -template = template.replace('@PROGRAM_SHA256SUM@', version_dict['bin'][1]) -template = template.replace('@EXE_URL@', version_dict['exe'][0]) -template = template.replace('@EXE_SHA256SUM@', version_dict['exe'][1]) -template = template.replace('@TAR_URL@', version_dict['tar'][0]) -template = template.replace('@TAR_SHA256SUM@', version_dict['tar'][1]) -with open('download.html', 'w', encoding='utf-8') as dlf: - dlf.write(template) diff --git a/devscripts/gh-pages/sign-versions.py b/devscripts/gh-pages/sign-versions.py deleted file mode 100755 index fa389c358..000000000 --- a/devscripts/gh-pages/sign-versions.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import unicode_literals, with_statement - -import rsa -import json -from binascii import hexlify - -try: - input = raw_input -except NameError: - pass - -versions_info = json.load(open('update/versions.json')) -if 'signature' in versions_info: - del versions_info['signature'] - -print('Enter the PKCS1 private key, followed by a blank line:') -privkey = b'' -while True: - try: - line = input() - except EOFError: - break - if line == '': - break - privkey += line.encode('ascii') + b'\n' -privkey = rsa.PrivateKey.load_pkcs1(privkey) - -signature = hexlify(rsa.pkcs1.sign(json.dumps(versions_info, sort_keys=True).encode('utf-8'), privkey, 'SHA-256')).decode() -print('signature: ' + signature) - -versions_info['signature'] = signature -with open('update/versions.json', 'w') as versionsf: - json.dump(versions_info, versionsf, indent=4, sort_keys=True) diff --git a/devscripts/gh-pages/update-copyright.py b/devscripts/gh-pages/update-copyright.py deleted file mode 100755 index e122d0283..000000000 --- a/devscripts/gh-pages/update-copyright.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python3 -# coding: utf-8 - -from __future__ import with_statement, unicode_literals - -import datetime -import glob -import io # For Python 2 compatibility -import os -import re - -year = str(datetime.datetime.now().year) -for fn in glob.glob('*.html*'): - with io.open(fn, encoding='utf-8') as f: - content = f.read() - newc = re.sub(r'(?PCopyright © 2011-)(?P[0-9]{4})', 'Copyright © 2011-' + year, content) - if content != newc: - tmpFn = fn + '.part' - with io.open(tmpFn, 'wt', encoding='utf-8') as outf: - outf.write(newc) - os.rename(tmpFn, fn) diff --git a/devscripts/gh-pages/update-feed.py b/devscripts/gh-pages/update-feed.py deleted file mode 100755 index c9f2fdb07..000000000 --- a/devscripts/gh-pages/update-feed.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import unicode_literals - -import datetime -import io -import json -import textwrap - - -atom_template = textwrap.dedent("""\ - - - - yt-dlp releases - https://yt-dl.org/feed/yt-dlp-updates-feed - @TIMESTAMP@ - @ENTRIES@ - """) - -entry_template = textwrap.dedent(""" - - https://yt-dl.org/feed/yt-dlp-updates-feed/yt-dlp-@VERSION@ - New version @VERSION@ - - -
    - Downloads available at https://yt-dl.org/downloads/@VERSION@/ -
    -
    - - The yt-dlp maintainers - - @TIMESTAMP@ -
    - """) - -now = datetime.datetime.now() -now_iso = now.isoformat() + 'Z' - -atom_template = atom_template.replace('@TIMESTAMP@', now_iso) - -versions_info = json.load(open('update/versions.json')) -versions = list(versions_info['versions'].keys()) -versions.sort() - -entries = [] -for v in versions: - fields = v.split('.') - year, month, day = map(int, fields[:3]) - faked = 0 - patchlevel = 0 - while True: - try: - datetime.date(year, month, day) - except ValueError: - day -= 1 - faked += 1 - assert day > 0 - continue - break - if len(fields) >= 4: - try: - patchlevel = int(fields[3]) - except ValueError: - patchlevel = 1 - timestamp = '%04d-%02d-%02dT00:%02d:%02dZ' % (year, month, day, faked, patchlevel) - - entry = entry_template.replace('@TIMESTAMP@', timestamp) - entry = entry.replace('@VERSION@', v) - entries.append(entry) - -entries_str = textwrap.indent(''.join(entries), '\t') -atom_template = atom_template.replace('@ENTRIES@', entries_str) - -with io.open('update/releases.atom', 'w', encoding='utf-8') as atom_file: - atom_file.write(atom_template) diff --git a/devscripts/gh-pages/update-sites.py b/devscripts/gh-pages/update-sites.py deleted file mode 100755 index b53685fcc..000000000 --- a/devscripts/gh-pages/update-sites.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import unicode_literals - -import sys -import os -import textwrap - -# We must be able to import yt_dlp -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) - -import yt_dlp - - -def main(): - with open('supportedsites.html.in', 'r', encoding='utf-8') as tmplf: - template = tmplf.read() - - ie_htmls = [] - for ie in yt_dlp.list_extractors(age_limit=None): - ie_html = '{}'.format(ie.IE_NAME) - ie_desc = getattr(ie, 'IE_DESC', None) - if ie_desc is False: - continue - elif ie_desc is not None: - ie_html += ': {}'.format(ie.IE_DESC) - if not ie.working(): - ie_html += ' (Currently broken)' - ie_htmls.append('
  • {}
  • '.format(ie_html)) - - template = template.replace('@SITES@', textwrap.indent('\n'.join(ie_htmls), '\t')) - - with open('supportedsites.html', 'w', encoding='utf-8') as sitesf: - sitesf.write(template) - - -if __name__ == '__main__': - main() diff --git a/devscripts/release.sh b/devscripts/release.sh index d0266f391..188b166e6 100755 --- a/devscripts/release.sh +++ b/devscripts/release.sh @@ -1,4 +1,5 @@ # Unused + #!/bin/bash # IMPORTANT: the following assumptions are made diff --git a/devscripts/wine-py2exe.sh b/devscripts/wine-py2exe.sh index dc2d6501a..8bc8ce55b 100755 --- a/devscripts/wine-py2exe.sh +++ b/devscripts/wine-py2exe.sh @@ -1,3 +1,5 @@ +# UNUSED + #!/bin/bash # Run with as parameter a setup.py that works in the current directory diff --git a/test/swftests.unused/.gitignore b/test/swftests.unused/.gitignore new file mode 100644 index 000000000..da97ff7ca --- /dev/null +++ b/test/swftests.unused/.gitignore @@ -0,0 +1 @@ +*.swf diff --git a/test/swftests.unused/ArrayAccess.as b/test/swftests.unused/ArrayAccess.as new file mode 100644 index 000000000..e22caa386 --- /dev/null +++ b/test/swftests.unused/ArrayAccess.as @@ -0,0 +1,19 @@ +// input: [["a", "b", "c", "d"]] +// output: ["c", "b", "a", "d"] + +package { +public class ArrayAccess { + public static function main(ar:Array):Array { + var aa:ArrayAccess = new ArrayAccess(); + return aa.f(ar, 2); + } + + private function f(ar:Array, num:Number):Array{ + var x:String = ar[0]; + var y:String = ar[num % ar.length]; + ar[0] = y; + ar[num] = x; + return ar; + } +} +} diff --git a/test/swftests.unused/ClassCall.as b/test/swftests.unused/ClassCall.as new file mode 100644 index 000000000..aef58daf3 --- /dev/null +++ b/test/swftests.unused/ClassCall.as @@ -0,0 +1,17 @@ +// input: [] +// output: 121 + +package { +public class ClassCall { + public static function main():int{ + var f:OtherClass = new OtherClass(); + return f.func(100,20); + } +} +} + +class OtherClass { + public function func(x: int, y: int):int { + return x+y+1; + } +} diff --git a/test/swftests.unused/ClassConstruction.as b/test/swftests.unused/ClassConstruction.as new file mode 100644 index 000000000..436479f8f --- /dev/null +++ b/test/swftests.unused/ClassConstruction.as @@ -0,0 +1,15 @@ +// input: [] +// output: 0 + +package { +public class ClassConstruction { + public static function main():int{ + var f:Foo = new Foo(); + return 0; + } +} +} + +class Foo { + +} diff --git a/test/swftests.unused/ConstArrayAccess.as b/test/swftests.unused/ConstArrayAccess.as new file mode 100644 index 000000000..07dc3f460 --- /dev/null +++ b/test/swftests.unused/ConstArrayAccess.as @@ -0,0 +1,18 @@ +// input: [] +// output: 4 + +package { +public class ConstArrayAccess { + private static const x:int = 2; + private static const ar:Array = ["42", "3411"]; + + public static function main():int{ + var c:ConstArrayAccess = new ConstArrayAccess(); + return c.f(); + } + + public function f(): int { + return ar[1].length; + } +} +} diff --git a/test/swftests.unused/ConstantInt.as b/test/swftests.unused/ConstantInt.as new file mode 100644 index 000000000..e0bbb6166 --- /dev/null +++ b/test/swftests.unused/ConstantInt.as @@ -0,0 +1,12 @@ +// input: [] +// output: 2 + +package { +public class ConstantInt { + private static const x:int = 2; + + public static function main():int{ + return x; + } +} +} diff --git a/test/swftests.unused/DictCall.as b/test/swftests.unused/DictCall.as new file mode 100644 index 000000000..c2d174cc2 --- /dev/null +++ b/test/swftests.unused/DictCall.as @@ -0,0 +1,10 @@ +// input: [{"x": 1, "y": 2}] +// output: 3 + +package { +public class DictCall { + public static function main(d:Object):int{ + return d.x + d.y; + } +} +} diff --git a/test/swftests.unused/EqualsOperator.as b/test/swftests.unused/EqualsOperator.as new file mode 100644 index 000000000..837a69a46 --- /dev/null +++ b/test/swftests.unused/EqualsOperator.as @@ -0,0 +1,10 @@ +// input: [] +// output: false + +package { +public class EqualsOperator { + public static function main():Boolean{ + return 1 == 2; + } +} +} diff --git a/test/swftests.unused/LocalVars.as b/test/swftests.unused/LocalVars.as new file mode 100644 index 000000000..b2911a9f3 --- /dev/null +++ b/test/swftests.unused/LocalVars.as @@ -0,0 +1,13 @@ +// input: [1, 2] +// output: 3 + +package { +public class LocalVars { + public static function main(a:int, b:int):int{ + var c:int = a + b + b; + var d:int = c - b; + var e:int = d; + return e; + } +} +} diff --git a/test/swftests.unused/MemberAssignment.as b/test/swftests.unused/MemberAssignment.as new file mode 100644 index 000000000..dcba5e3ff --- /dev/null +++ b/test/swftests.unused/MemberAssignment.as @@ -0,0 +1,22 @@ +// input: [1] +// output: 2 + +package { +public class MemberAssignment { + public var v:int; + + public function g():int { + return this.v; + } + + public function f(a:int):int{ + this.v = a; + return this.v + this.g(); + } + + public static function main(a:int): int { + var v:MemberAssignment = new MemberAssignment(); + return v.f(a); + } +} +} diff --git a/test/swftests.unused/NeOperator.as b/test/swftests.unused/NeOperator.as new file mode 100644 index 000000000..61dcbc4e9 --- /dev/null +++ b/test/swftests.unused/NeOperator.as @@ -0,0 +1,24 @@ +// input: [] +// output: 123 + +package { +public class NeOperator { + public static function main(): int { + var res:int = 0; + if (1 != 2) { + res += 3; + } else { + res += 4; + } + if (2 != 2) { + res += 10; + } else { + res += 20; + } + if (9 == 9) { + res += 100; + } + return res; + } +} +} diff --git a/test/swftests.unused/PrivateCall.as b/test/swftests.unused/PrivateCall.as new file mode 100644 index 000000000..f1c110a37 --- /dev/null +++ b/test/swftests.unused/PrivateCall.as @@ -0,0 +1,21 @@ +// input: [] +// output: 9 + +package { +public class PrivateCall { + public static function main():int{ + var f:OtherClass = new OtherClass(); + return f.func(); + } +} +} + +class OtherClass { + private function pf():int { + return 9; + } + + public function func():int { + return this.pf(); + } +} diff --git a/test/swftests.unused/PrivateVoidCall.as b/test/swftests.unused/PrivateVoidCall.as new file mode 100644 index 000000000..2cc016797 --- /dev/null +++ b/test/swftests.unused/PrivateVoidCall.as @@ -0,0 +1,22 @@ +// input: [] +// output: 9 + +package { +public class PrivateVoidCall { + public static function main():int{ + var f:OtherClass = new OtherClass(); + f.func(); + return 9; + } +} +} + +class OtherClass { + private function pf():void { + ; + } + + public function func():void { + this.pf(); + } +} diff --git a/test/swftests.unused/StaticAssignment.as b/test/swftests.unused/StaticAssignment.as new file mode 100644 index 000000000..b061c219d --- /dev/null +++ b/test/swftests.unused/StaticAssignment.as @@ -0,0 +1,13 @@ +// input: [1] +// output: 1 + +package { +public class StaticAssignment { + public static var v:int; + + public static function main(a:int):int{ + v = a; + return v; + } +} +} diff --git a/test/swftests.unused/StaticRetrieval.as b/test/swftests.unused/StaticRetrieval.as new file mode 100644 index 000000000..c8352d819 --- /dev/null +++ b/test/swftests.unused/StaticRetrieval.as @@ -0,0 +1,16 @@ +// input: [] +// output: 1 + +package { +public class StaticRetrieval { + public static var v:int; + + public static function main():int{ + if (v) { + return 0; + } else { + return 1; + } + } +} +} diff --git a/test/swftests.unused/StringBasics.as b/test/swftests.unused/StringBasics.as new file mode 100644 index 000000000..d27430b13 --- /dev/null +++ b/test/swftests.unused/StringBasics.as @@ -0,0 +1,11 @@ +// input: [] +// output: 3 + +package { +public class StringBasics { + public static function main():int{ + var s:String = "abc"; + return s.length; + } +} +} diff --git a/test/swftests.unused/StringCharCodeAt.as b/test/swftests.unused/StringCharCodeAt.as new file mode 100644 index 000000000..c20d74d65 --- /dev/null +++ b/test/swftests.unused/StringCharCodeAt.as @@ -0,0 +1,11 @@ +// input: [] +// output: 9897 + +package { +public class StringCharCodeAt { + public static function main():int{ + var s:String = "abc"; + return s.charCodeAt(1) * 100 + s.charCodeAt(); + } +} +} diff --git a/test/swftests.unused/StringConversion.as b/test/swftests.unused/StringConversion.as new file mode 100644 index 000000000..c976f5042 --- /dev/null +++ b/test/swftests.unused/StringConversion.as @@ -0,0 +1,11 @@ +// input: [] +// output: 2 + +package { +public class StringConversion { + public static function main():int{ + var s:String = String(99); + return s.length; + } +} +} diff --git a/test/swftests/.gitignore b/test/swftests/.gitignore deleted file mode 100644 index da97ff7ca..000000000 --- a/test/swftests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.swf diff --git a/test/swftests/ArrayAccess.as b/test/swftests/ArrayAccess.as deleted file mode 100644 index e22caa386..000000000 --- a/test/swftests/ArrayAccess.as +++ /dev/null @@ -1,19 +0,0 @@ -// input: [["a", "b", "c", "d"]] -// output: ["c", "b", "a", "d"] - -package { -public class ArrayAccess { - public static function main(ar:Array):Array { - var aa:ArrayAccess = new ArrayAccess(); - return aa.f(ar, 2); - } - - private function f(ar:Array, num:Number):Array{ - var x:String = ar[0]; - var y:String = ar[num % ar.length]; - ar[0] = y; - ar[num] = x; - return ar; - } -} -} diff --git a/test/swftests/ClassCall.as b/test/swftests/ClassCall.as deleted file mode 100644 index aef58daf3..000000000 --- a/test/swftests/ClassCall.as +++ /dev/null @@ -1,17 +0,0 @@ -// input: [] -// output: 121 - -package { -public class ClassCall { - public static function main():int{ - var f:OtherClass = new OtherClass(); - return f.func(100,20); - } -} -} - -class OtherClass { - public function func(x: int, y: int):int { - return x+y+1; - } -} diff --git a/test/swftests/ClassConstruction.as b/test/swftests/ClassConstruction.as deleted file mode 100644 index 436479f8f..000000000 --- a/test/swftests/ClassConstruction.as +++ /dev/null @@ -1,15 +0,0 @@ -// input: [] -// output: 0 - -package { -public class ClassConstruction { - public static function main():int{ - var f:Foo = new Foo(); - return 0; - } -} -} - -class Foo { - -} diff --git a/test/swftests/ConstArrayAccess.as b/test/swftests/ConstArrayAccess.as deleted file mode 100644 index 07dc3f460..000000000 --- a/test/swftests/ConstArrayAccess.as +++ /dev/null @@ -1,18 +0,0 @@ -// input: [] -// output: 4 - -package { -public class ConstArrayAccess { - private static const x:int = 2; - private static const ar:Array = ["42", "3411"]; - - public static function main():int{ - var c:ConstArrayAccess = new ConstArrayAccess(); - return c.f(); - } - - public function f(): int { - return ar[1].length; - } -} -} diff --git a/test/swftests/ConstantInt.as b/test/swftests/ConstantInt.as deleted file mode 100644 index e0bbb6166..000000000 --- a/test/swftests/ConstantInt.as +++ /dev/null @@ -1,12 +0,0 @@ -// input: [] -// output: 2 - -package { -public class ConstantInt { - private static const x:int = 2; - - public static function main():int{ - return x; - } -} -} diff --git a/test/swftests/DictCall.as b/test/swftests/DictCall.as deleted file mode 100644 index c2d174cc2..000000000 --- a/test/swftests/DictCall.as +++ /dev/null @@ -1,10 +0,0 @@ -// input: [{"x": 1, "y": 2}] -// output: 3 - -package { -public class DictCall { - public static function main(d:Object):int{ - return d.x + d.y; - } -} -} diff --git a/test/swftests/EqualsOperator.as b/test/swftests/EqualsOperator.as deleted file mode 100644 index 837a69a46..000000000 --- a/test/swftests/EqualsOperator.as +++ /dev/null @@ -1,10 +0,0 @@ -// input: [] -// output: false - -package { -public class EqualsOperator { - public static function main():Boolean{ - return 1 == 2; - } -} -} diff --git a/test/swftests/LocalVars.as b/test/swftests/LocalVars.as deleted file mode 100644 index b2911a9f3..000000000 --- a/test/swftests/LocalVars.as +++ /dev/null @@ -1,13 +0,0 @@ -// input: [1, 2] -// output: 3 - -package { -public class LocalVars { - public static function main(a:int, b:int):int{ - var c:int = a + b + b; - var d:int = c - b; - var e:int = d; - return e; - } -} -} diff --git a/test/swftests/MemberAssignment.as b/test/swftests/MemberAssignment.as deleted file mode 100644 index dcba5e3ff..000000000 --- a/test/swftests/MemberAssignment.as +++ /dev/null @@ -1,22 +0,0 @@ -// input: [1] -// output: 2 - -package { -public class MemberAssignment { - public var v:int; - - public function g():int { - return this.v; - } - - public function f(a:int):int{ - this.v = a; - return this.v + this.g(); - } - - public static function main(a:int): int { - var v:MemberAssignment = new MemberAssignment(); - return v.f(a); - } -} -} diff --git a/test/swftests/NeOperator.as b/test/swftests/NeOperator.as deleted file mode 100644 index 61dcbc4e9..000000000 --- a/test/swftests/NeOperator.as +++ /dev/null @@ -1,24 +0,0 @@ -// input: [] -// output: 123 - -package { -public class NeOperator { - public static function main(): int { - var res:int = 0; - if (1 != 2) { - res += 3; - } else { - res += 4; - } - if (2 != 2) { - res += 10; - } else { - res += 20; - } - if (9 == 9) { - res += 100; - } - return res; - } -} -} diff --git a/test/swftests/PrivateCall.as b/test/swftests/PrivateCall.as deleted file mode 100644 index f1c110a37..000000000 --- a/test/swftests/PrivateCall.as +++ /dev/null @@ -1,21 +0,0 @@ -// input: [] -// output: 9 - -package { -public class PrivateCall { - public static function main():int{ - var f:OtherClass = new OtherClass(); - return f.func(); - } -} -} - -class OtherClass { - private function pf():int { - return 9; - } - - public function func():int { - return this.pf(); - } -} diff --git a/test/swftests/PrivateVoidCall.as b/test/swftests/PrivateVoidCall.as deleted file mode 100644 index 2cc016797..000000000 --- a/test/swftests/PrivateVoidCall.as +++ /dev/null @@ -1,22 +0,0 @@ -// input: [] -// output: 9 - -package { -public class PrivateVoidCall { - public static function main():int{ - var f:OtherClass = new OtherClass(); - f.func(); - return 9; - } -} -} - -class OtherClass { - private function pf():void { - ; - } - - public function func():void { - this.pf(); - } -} diff --git a/test/swftests/StaticAssignment.as b/test/swftests/StaticAssignment.as deleted file mode 100644 index b061c219d..000000000 --- a/test/swftests/StaticAssignment.as +++ /dev/null @@ -1,13 +0,0 @@ -// input: [1] -// output: 1 - -package { -public class StaticAssignment { - public static var v:int; - - public static function main(a:int):int{ - v = a; - return v; - } -} -} diff --git a/test/swftests/StaticRetrieval.as b/test/swftests/StaticRetrieval.as deleted file mode 100644 index c8352d819..000000000 --- a/test/swftests/StaticRetrieval.as +++ /dev/null @@ -1,16 +0,0 @@ -// input: [] -// output: 1 - -package { -public class StaticRetrieval { - public static var v:int; - - public static function main():int{ - if (v) { - return 0; - } else { - return 1; - } - } -} -} diff --git a/test/swftests/StringBasics.as b/test/swftests/StringBasics.as deleted file mode 100644 index d27430b13..000000000 --- a/test/swftests/StringBasics.as +++ /dev/null @@ -1,11 +0,0 @@ -// input: [] -// output: 3 - -package { -public class StringBasics { - public static function main():int{ - var s:String = "abc"; - return s.length; - } -} -} diff --git a/test/swftests/StringCharCodeAt.as b/test/swftests/StringCharCodeAt.as deleted file mode 100644 index c20d74d65..000000000 --- a/test/swftests/StringCharCodeAt.as +++ /dev/null @@ -1,11 +0,0 @@ -// input: [] -// output: 9897 - -package { -public class StringCharCodeAt { - public static function main():int{ - var s:String = "abc"; - return s.charCodeAt(1) * 100 + s.charCodeAt(); - } -} -} diff --git a/test/swftests/StringConversion.as b/test/swftests/StringConversion.as deleted file mode 100644 index c976f5042..000000000 --- a/test/swftests/StringConversion.as +++ /dev/null @@ -1,11 +0,0 @@ -// input: [] -// output: 2 - -package { -public class StringConversion { - public static function main():int{ - var s:String = String(99); - return s.length; - } -} -} diff --git a/test/test_aes.py b/test/test_aes.py index 4fd87ce22..d2e51af29 100644 --- a/test/test_aes.py +++ b/test/test_aes.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - from __future__ import unicode_literals # Allow direct execution diff --git a/test/test_swfinterp.py b/test/test_swfinterp.py deleted file mode 100644 index 5d5b21e6d..000000000 --- a/test/test_swfinterp.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import unicode_literals - -# Allow direct execution -import os -import sys -import unittest -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - - -import errno -import io -import json -import re -import subprocess - -from yt_dlp.swfinterp import SWFInterpreter - - -TEST_DIR = os.path.join( - os.path.dirname(os.path.abspath(__file__)), 'swftests') - - -class TestSWFInterpreter(unittest.TestCase): - pass - - -def _make_testfunc(testfile): - m = re.match(r'^(.*)\.(as)$', testfile) - if not m: - return - test_id = m.group(1) - - def test_func(self): - as_file = os.path.join(TEST_DIR, testfile) - swf_file = os.path.join(TEST_DIR, test_id + '.swf') - if ((not os.path.exists(swf_file)) - or os.path.getmtime(swf_file) < os.path.getmtime(as_file)): - # Recompile - try: - subprocess.check_call([ - 'mxmlc', '-output', swf_file, - '-static-link-runtime-shared-libraries', as_file]) - except OSError as ose: - if ose.errno == errno.ENOENT: - print('mxmlc not found! Skipping test.') - return - raise - - with open(swf_file, 'rb') as swf_f: - swf_content = swf_f.read() - swfi = SWFInterpreter(swf_content) - - with io.open(as_file, 'r', encoding='utf-8') as as_f: - as_content = as_f.read() - - def _find_spec(key): - m = re.search( - r'(?m)^//\s*%s:\s*(.*?)\n' % re.escape(key), as_content) - if not m: - raise ValueError('Cannot find %s in %s' % (key, testfile)) - return json.loads(m.group(1)) - - input_args = _find_spec('input') - output = _find_spec('output') - - swf_class = swfi.extract_class(test_id) - func = swfi.extract_function(swf_class, 'main') - res = func(input_args) - self.assertEqual(res, output) - - test_func.__name__ = str('test_swf_' + test_id) - setattr(TestSWFInterpreter, test_func.__name__, test_func) - - -for testfile in os.listdir(TEST_DIR): - _make_testfunc(testfile) - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_swfinterp.py.disabled b/test/test_swfinterp.py.disabled new file mode 100644 index 000000000..5d5b21e6d --- /dev/null +++ b/test/test_swfinterp.py.disabled @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +from __future__ import unicode_literals + +# Allow direct execution +import os +import sys +import unittest +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +import errno +import io +import json +import re +import subprocess + +from yt_dlp.swfinterp import SWFInterpreter + + +TEST_DIR = os.path.join( + os.path.dirname(os.path.abspath(__file__)), 'swftests') + + +class TestSWFInterpreter(unittest.TestCase): + pass + + +def _make_testfunc(testfile): + m = re.match(r'^(.*)\.(as)$', testfile) + if not m: + return + test_id = m.group(1) + + def test_func(self): + as_file = os.path.join(TEST_DIR, testfile) + swf_file = os.path.join(TEST_DIR, test_id + '.swf') + if ((not os.path.exists(swf_file)) + or os.path.getmtime(swf_file) < os.path.getmtime(as_file)): + # Recompile + try: + subprocess.check_call([ + 'mxmlc', '-output', swf_file, + '-static-link-runtime-shared-libraries', as_file]) + except OSError as ose: + if ose.errno == errno.ENOENT: + print('mxmlc not found! Skipping test.') + return + raise + + with open(swf_file, 'rb') as swf_f: + swf_content = swf_f.read() + swfi = SWFInterpreter(swf_content) + + with io.open(as_file, 'r', encoding='utf-8') as as_f: + as_content = as_f.read() + + def _find_spec(key): + m = re.search( + r'(?m)^//\s*%s:\s*(.*?)\n' % re.escape(key), as_content) + if not m: + raise ValueError('Cannot find %s in %s' % (key, testfile)) + return json.loads(m.group(1)) + + input_args = _find_spec('input') + output = _find_spec('output') + + swf_class = swfi.extract_class(test_id) + func = swfi.extract_function(swf_class, 'main') + res = func(input_args) + self.assertEqual(res, output) + + test_func.__name__ = str('test_swf_' + test_id) + setattr(TestSWFInterpreter, test_func.__name__, test_func) + + +for testfile in os.listdir(TEST_DIR): + _make_testfunc(testfile) + +if __name__ == '__main__': + unittest.main() diff --git a/yt_dlp/swfinterp.py b/yt_dlp/swfinterp.py deleted file mode 100644 index 0c7158575..000000000 --- a/yt_dlp/swfinterp.py +++ /dev/null @@ -1,834 +0,0 @@ -from __future__ import unicode_literals - -import collections -import io -import zlib - -from .compat import ( - compat_str, - compat_struct_unpack, -) -from .utils import ( - ExtractorError, -) - - -def _extract_tags(file_contents): - if file_contents[1:3] != b'WS': - raise ExtractorError( - 'Not an SWF file; header is %r' % file_contents[:3]) - if file_contents[:1] == b'C': - content = zlib.decompress(file_contents[8:]) - else: - raise NotImplementedError( - 'Unsupported compression format %r' % - file_contents[:1]) - - # Determine number of bits in framesize rectangle - framesize_nbits = compat_struct_unpack('!B', content[:1])[0] >> 3 - framesize_len = (5 + 4 * framesize_nbits + 7) // 8 - - pos = framesize_len + 2 + 2 - while pos < len(content): - header16 = compat_struct_unpack('> 6 - tag_len = header16 & 0x3f - if tag_len == 0x3f: - tag_len = compat_struct_unpack('= 0x80) else b'\x00' - return compat_struct_unpack('= 0 - resb = reader.read(count) - assert len(resb) == count - return resb - - -def _read_byte(reader): - resb = _read_bytes(1, reader=reader) - res = compat_struct_unpack('> 4 - methods = {} - constants = None - if kind == 0x00: # Slot - u30() # Slot id - u30() # type_name_idx - vindex = u30() - if vindex != 0: - read_byte() # vkind - elif kind == 0x06: # Const - u30() # Slot id - u30() # type_name_idx - vindex = u30() - vkind = 'any' - if vindex != 0: - vkind = read_byte() - if vkind == 0x03: # Constant_Int - value = self.constant_ints[vindex] - elif vkind == 0x04: # Constant_UInt - value = self.constant_uints[vindex] - else: - return {}, None # Ignore silently for now - constants = {self.multinames[trait_name_idx]: value} - elif kind in (0x01, 0x02, 0x03): # Method / Getter / Setter - u30() # disp_id - method_idx = u30() - methods[self.multinames[trait_name_idx]] = method_idx - elif kind == 0x04: # Class - u30() # slot_id - u30() # classi - elif kind == 0x05: # Function - u30() # slot_id - function_idx = u30() - methods[function_idx] = self.multinames[trait_name_idx] - else: - raise ExtractorError('Unsupported trait kind %d' % kind) - - if attrs & 0x4 != 0: # Metadata present - metadata_count = u30() - for _c3 in range(metadata_count): - u30() # metadata index - - return methods, constants - - # Classes - class_count = u30() - classes = [] - for class_id in range(class_count): - name_idx = u30() - - cname = self.multinames[name_idx] - avm_class = _AVMClass(name_idx, cname) - classes.append(avm_class) - - u30() # super_name idx - flags = read_byte() - if flags & 0x08 != 0: # Protected namespace is present - u30() # protected_ns_idx - intrf_count = u30() - for _c2 in range(intrf_count): - u30() - u30() # iinit - trait_count = u30() - for _c2 in range(trait_count): - trait_methods, trait_constants = parse_traits_info() - avm_class.register_methods(trait_methods) - if trait_constants: - avm_class.constants.update(trait_constants) - - assert len(classes) == class_count - self._classes_by_name = dict((c.name, c) for c in classes) - - for avm_class in classes: - avm_class.cinit_idx = u30() - trait_count = u30() - for _c2 in range(trait_count): - trait_methods, trait_constants = parse_traits_info() - avm_class.register_methods(trait_methods) - if trait_constants: - avm_class.constants.update(trait_constants) - - # Scripts - script_count = u30() - for _c in range(script_count): - u30() # init - trait_count = u30() - for _c2 in range(trait_count): - parse_traits_info() - - # Method bodies - method_body_count = u30() - Method = collections.namedtuple('Method', ['code', 'local_count']) - self._all_methods = [] - for _c in range(method_body_count): - method_idx = u30() - u30() # max_stack - local_count = u30() - u30() # init_scope_depth - u30() # max_scope_depth - code_length = u30() - code = read_bytes(code_length) - m = Method(code, local_count) - self._all_methods.append(m) - for avm_class in classes: - if method_idx in avm_class.method_idxs: - avm_class.methods[avm_class.method_idxs[method_idx]] = m - exception_count = u30() - for _c2 in range(exception_count): - u30() # from - u30() # to - u30() # target - u30() # exc_type - u30() # var_name - trait_count = u30() - for _c2 in range(trait_count): - parse_traits_info() - - assert p + code_reader.tell() == len(code_tag) - - def patch_function(self, avm_class, func_name, f): - self._patched_functions[(avm_class, func_name)] = f - - def extract_class(self, class_name, call_cinit=True): - try: - res = self._classes_by_name[class_name] - except KeyError: - raise ExtractorError('Class %r not found' % class_name) - - if call_cinit and hasattr(res, 'cinit_idx'): - res.register_methods({'$cinit': res.cinit_idx}) - res.methods['$cinit'] = self._all_methods[res.cinit_idx] - cinit = self.extract_function(res, '$cinit') - cinit([]) - - return res - - def extract_function(self, avm_class, func_name): - p = self._patched_functions.get((avm_class, func_name)) - if p: - return p - if func_name in avm_class.method_pyfunctions: - return avm_class.method_pyfunctions[func_name] - if func_name in self._classes_by_name: - return self._classes_by_name[func_name].make_object() - if func_name not in avm_class.methods: - raise ExtractorError('Cannot find function %s.%s' % ( - avm_class.name, func_name)) - m = avm_class.methods[func_name] - - def resfunc(args): - # Helper functions - coder = io.BytesIO(m.code) - s24 = lambda: _s24(coder) - u30 = lambda: _u30(coder) - - registers = [avm_class.variables] + list(args) + [None] * m.local_count - stack = [] - scopes = collections.deque([ - self._classes_by_name, avm_class.constants, avm_class.variables]) - while True: - opcode = _read_byte(coder) - if opcode == 9: # label - pass # Spec says: "Do nothing." - elif opcode == 16: # jump - offset = s24() - coder.seek(coder.tell() + offset) - elif opcode == 17: # iftrue - offset = s24() - value = stack.pop() - if value: - coder.seek(coder.tell() + offset) - elif opcode == 18: # iffalse - offset = s24() - value = stack.pop() - if not value: - coder.seek(coder.tell() + offset) - elif opcode == 19: # ifeq - offset = s24() - value2 = stack.pop() - value1 = stack.pop() - if value2 == value1: - coder.seek(coder.tell() + offset) - elif opcode == 20: # ifne - offset = s24() - value2 = stack.pop() - value1 = stack.pop() - if value2 != value1: - coder.seek(coder.tell() + offset) - elif opcode == 21: # iflt - offset = s24() - value2 = stack.pop() - value1 = stack.pop() - if value1 < value2: - coder.seek(coder.tell() + offset) - elif opcode == 32: # pushnull - stack.append(None) - elif opcode == 33: # pushundefined - stack.append(undefined) - elif opcode == 36: # pushbyte - v = _read_byte(coder) - stack.append(v) - elif opcode == 37: # pushshort - v = u30() - stack.append(v) - elif opcode == 38: # pushtrue - stack.append(True) - elif opcode == 39: # pushfalse - stack.append(False) - elif opcode == 40: # pushnan - stack.append(float('NaN')) - elif opcode == 42: # dup - value = stack[-1] - stack.append(value) - elif opcode == 44: # pushstring - idx = u30() - stack.append(self.constant_strings[idx]) - elif opcode == 48: # pushscope - new_scope = stack.pop() - scopes.append(new_scope) - elif opcode == 66: # construct - arg_count = u30() - args = list(reversed( - [stack.pop() for _ in range(arg_count)])) - obj = stack.pop() - res = obj.avm_class.make_object() - stack.append(res) - elif opcode == 70: # callproperty - index = u30() - mname = self.multinames[index] - arg_count = u30() - args = list(reversed( - [stack.pop() for _ in range(arg_count)])) - obj = stack.pop() - - if obj == StringClass: - if mname == 'String': - assert len(args) == 1 - assert isinstance(args[0], ( - int, compat_str, _Undefined)) - if args[0] == undefined: - res = 'undefined' - else: - res = compat_str(args[0]) - stack.append(res) - continue - else: - raise NotImplementedError( - 'Function String.%s is not yet implemented' - % mname) - elif isinstance(obj, _AVMClass_Object): - func = self.extract_function(obj.avm_class, mname) - res = func(args) - stack.append(res) - continue - elif isinstance(obj, _AVMClass): - func = self.extract_function(obj, mname) - res = func(args) - stack.append(res) - continue - elif isinstance(obj, _ScopeDict): - if mname in obj.avm_class.method_names: - func = self.extract_function(obj.avm_class, mname) - res = func(args) - else: - res = obj[mname] - stack.append(res) - continue - elif isinstance(obj, compat_str): - if mname == 'split': - assert len(args) == 1 - assert isinstance(args[0], compat_str) - if args[0] == '': - res = list(obj) - else: - res = obj.split(args[0]) - stack.append(res) - continue - elif mname == 'charCodeAt': - assert len(args) <= 1 - idx = 0 if len(args) == 0 else args[0] - assert isinstance(idx, int) - res = ord(obj[idx]) - stack.append(res) - continue - elif isinstance(obj, list): - if mname == 'slice': - assert len(args) == 1 - assert isinstance(args[0], int) - res = obj[args[0]:] - stack.append(res) - continue - elif mname == 'join': - assert len(args) == 1 - assert isinstance(args[0], compat_str) - res = args[0].join(obj) - stack.append(res) - continue - raise NotImplementedError( - 'Unsupported property %r on %r' - % (mname, obj)) - elif opcode == 71: # returnvoid - res = undefined - return res - elif opcode == 72: # returnvalue - res = stack.pop() - return res - elif opcode == 73: # constructsuper - # Not yet implemented, just hope it works without it - arg_count = u30() - args = list(reversed( - [stack.pop() for _ in range(arg_count)])) - obj = stack.pop() - elif opcode == 74: # constructproperty - index = u30() - arg_count = u30() - args = list(reversed( - [stack.pop() for _ in range(arg_count)])) - obj = stack.pop() - - mname = self.multinames[index] - assert isinstance(obj, _AVMClass) - - # We do not actually call the constructor for now; - # we just pretend it does nothing - stack.append(obj.make_object()) - elif opcode == 79: # callpropvoid - index = u30() - mname = self.multinames[index] - arg_count = u30() - args = list(reversed( - [stack.pop() for _ in range(arg_count)])) - obj = stack.pop() - if isinstance(obj, _AVMClass_Object): - func = self.extract_function(obj.avm_class, mname) - res = func(args) - assert res is undefined - continue - if isinstance(obj, _ScopeDict): - assert mname in obj.avm_class.method_names - func = self.extract_function(obj.avm_class, mname) - res = func(args) - assert res is undefined - continue - if mname == 'reverse': - assert isinstance(obj, list) - obj.reverse() - else: - raise NotImplementedError( - 'Unsupported (void) property %r on %r' - % (mname, obj)) - elif opcode == 86: # newarray - arg_count = u30() - arr = [] - for i in range(arg_count): - arr.append(stack.pop()) - arr = arr[::-1] - stack.append(arr) - elif opcode == 93: # findpropstrict - index = u30() - mname = self.multinames[index] - for s in reversed(scopes): - if mname in s: - res = s - break - else: - res = scopes[0] - if mname not in res and mname in _builtin_classes: - stack.append(_builtin_classes[mname]) - else: - stack.append(res[mname]) - elif opcode == 94: # findproperty - index = u30() - mname = self.multinames[index] - for s in reversed(scopes): - if mname in s: - res = s - break - else: - res = avm_class.variables - stack.append(res) - elif opcode == 96: # getlex - index = u30() - mname = self.multinames[index] - for s in reversed(scopes): - if mname in s: - scope = s - break - else: - scope = avm_class.variables - - if mname in scope: - res = scope[mname] - elif mname in _builtin_classes: - res = _builtin_classes[mname] - else: - # Assume uninitialized - # TODO warn here - res = undefined - stack.append(res) - elif opcode == 97: # setproperty - index = u30() - value = stack.pop() - idx = self.multinames[index] - if isinstance(idx, _Multiname): - idx = stack.pop() - obj = stack.pop() - obj[idx] = value - elif opcode == 98: # getlocal - index = u30() - stack.append(registers[index]) - elif opcode == 99: # setlocal - index = u30() - value = stack.pop() - registers[index] = value - elif opcode == 102: # getproperty - index = u30() - pname = self.multinames[index] - if pname == 'length': - obj = stack.pop() - assert isinstance(obj, (compat_str, list)) - stack.append(len(obj)) - elif isinstance(pname, compat_str): # Member access - obj = stack.pop() - if isinstance(obj, _AVMClass): - res = obj.static_properties[pname] - stack.append(res) - continue - - assert isinstance(obj, (dict, _ScopeDict)),\ - 'Accessing member %r on %r' % (pname, obj) - res = obj.get(pname, undefined) - stack.append(res) - else: # Assume attribute access - idx = stack.pop() - assert isinstance(idx, int) - obj = stack.pop() - assert isinstance(obj, list) - stack.append(obj[idx]) - elif opcode == 104: # initproperty - index = u30() - value = stack.pop() - idx = self.multinames[index] - if isinstance(idx, _Multiname): - idx = stack.pop() - obj = stack.pop() - obj[idx] = value - elif opcode == 115: # convert_ - value = stack.pop() - intvalue = int(value) - stack.append(intvalue) - elif opcode == 128: # coerce - u30() - elif opcode == 130: # coerce_a - value = stack.pop() - # um, yes, it's any value - stack.append(value) - elif opcode == 133: # coerce_s - assert isinstance(stack[-1], (type(None), compat_str)) - elif opcode == 147: # decrement - value = stack.pop() - assert isinstance(value, int) - stack.append(value - 1) - elif opcode == 149: # typeof - value = stack.pop() - return { - _Undefined: 'undefined', - compat_str: 'String', - int: 'Number', - float: 'Number', - }[type(value)] - elif opcode == 160: # add - value2 = stack.pop() - value1 = stack.pop() - res = value1 + value2 - stack.append(res) - elif opcode == 161: # subtract - value2 = stack.pop() - value1 = stack.pop() - res = value1 - value2 - stack.append(res) - elif opcode == 162: # multiply - value2 = stack.pop() - value1 = stack.pop() - res = value1 * value2 - stack.append(res) - elif opcode == 164: # modulo - value2 = stack.pop() - value1 = stack.pop() - res = value1 % value2 - stack.append(res) - elif opcode == 168: # bitand - value2 = stack.pop() - value1 = stack.pop() - assert isinstance(value1, int) - assert isinstance(value2, int) - res = value1 & value2 - stack.append(res) - elif opcode == 171: # equals - value2 = stack.pop() - value1 = stack.pop() - result = value1 == value2 - stack.append(result) - elif opcode == 175: # greaterequals - value2 = stack.pop() - value1 = stack.pop() - result = value1 >= value2 - stack.append(result) - elif opcode == 192: # increment_i - value = stack.pop() - assert isinstance(value, int) - stack.append(value + 1) - elif opcode == 208: # getlocal_0 - stack.append(registers[0]) - elif opcode == 209: # getlocal_1 - stack.append(registers[1]) - elif opcode == 210: # getlocal_2 - stack.append(registers[2]) - elif opcode == 211: # getlocal_3 - stack.append(registers[3]) - elif opcode == 212: # setlocal_0 - registers[0] = stack.pop() - elif opcode == 213: # setlocal_1 - registers[1] = stack.pop() - elif opcode == 214: # setlocal_2 - registers[2] = stack.pop() - elif opcode == 215: # setlocal_3 - registers[3] = stack.pop() - else: - raise NotImplementedError( - 'Unsupported opcode %d' % opcode) - - avm_class.method_pyfunctions[func_name] = resfunc - return resfunc diff --git a/yt_dlp/swfinterp.py.disabled b/yt_dlp/swfinterp.py.disabled new file mode 100644 index 000000000..0c7158575 --- /dev/null +++ b/yt_dlp/swfinterp.py.disabled @@ -0,0 +1,834 @@ +from __future__ import unicode_literals + +import collections +import io +import zlib + +from .compat import ( + compat_str, + compat_struct_unpack, +) +from .utils import ( + ExtractorError, +) + + +def _extract_tags(file_contents): + if file_contents[1:3] != b'WS': + raise ExtractorError( + 'Not an SWF file; header is %r' % file_contents[:3]) + if file_contents[:1] == b'C': + content = zlib.decompress(file_contents[8:]) + else: + raise NotImplementedError( + 'Unsupported compression format %r' % + file_contents[:1]) + + # Determine number of bits in framesize rectangle + framesize_nbits = compat_struct_unpack('!B', content[:1])[0] >> 3 + framesize_len = (5 + 4 * framesize_nbits + 7) // 8 + + pos = framesize_len + 2 + 2 + while pos < len(content): + header16 = compat_struct_unpack('> 6 + tag_len = header16 & 0x3f + if tag_len == 0x3f: + tag_len = compat_struct_unpack('= 0x80) else b'\x00' + return compat_struct_unpack('= 0 + resb = reader.read(count) + assert len(resb) == count + return resb + + +def _read_byte(reader): + resb = _read_bytes(1, reader=reader) + res = compat_struct_unpack('> 4 + methods = {} + constants = None + if kind == 0x00: # Slot + u30() # Slot id + u30() # type_name_idx + vindex = u30() + if vindex != 0: + read_byte() # vkind + elif kind == 0x06: # Const + u30() # Slot id + u30() # type_name_idx + vindex = u30() + vkind = 'any' + if vindex != 0: + vkind = read_byte() + if vkind == 0x03: # Constant_Int + value = self.constant_ints[vindex] + elif vkind == 0x04: # Constant_UInt + value = self.constant_uints[vindex] + else: + return {}, None # Ignore silently for now + constants = {self.multinames[trait_name_idx]: value} + elif kind in (0x01, 0x02, 0x03): # Method / Getter / Setter + u30() # disp_id + method_idx = u30() + methods[self.multinames[trait_name_idx]] = method_idx + elif kind == 0x04: # Class + u30() # slot_id + u30() # classi + elif kind == 0x05: # Function + u30() # slot_id + function_idx = u30() + methods[function_idx] = self.multinames[trait_name_idx] + else: + raise ExtractorError('Unsupported trait kind %d' % kind) + + if attrs & 0x4 != 0: # Metadata present + metadata_count = u30() + for _c3 in range(metadata_count): + u30() # metadata index + + return methods, constants + + # Classes + class_count = u30() + classes = [] + for class_id in range(class_count): + name_idx = u30() + + cname = self.multinames[name_idx] + avm_class = _AVMClass(name_idx, cname) + classes.append(avm_class) + + u30() # super_name idx + flags = read_byte() + if flags & 0x08 != 0: # Protected namespace is present + u30() # protected_ns_idx + intrf_count = u30() + for _c2 in range(intrf_count): + u30() + u30() # iinit + trait_count = u30() + for _c2 in range(trait_count): + trait_methods, trait_constants = parse_traits_info() + avm_class.register_methods(trait_methods) + if trait_constants: + avm_class.constants.update(trait_constants) + + assert len(classes) == class_count + self._classes_by_name = dict((c.name, c) for c in classes) + + for avm_class in classes: + avm_class.cinit_idx = u30() + trait_count = u30() + for _c2 in range(trait_count): + trait_methods, trait_constants = parse_traits_info() + avm_class.register_methods(trait_methods) + if trait_constants: + avm_class.constants.update(trait_constants) + + # Scripts + script_count = u30() + for _c in range(script_count): + u30() # init + trait_count = u30() + for _c2 in range(trait_count): + parse_traits_info() + + # Method bodies + method_body_count = u30() + Method = collections.namedtuple('Method', ['code', 'local_count']) + self._all_methods = [] + for _c in range(method_body_count): + method_idx = u30() + u30() # max_stack + local_count = u30() + u30() # init_scope_depth + u30() # max_scope_depth + code_length = u30() + code = read_bytes(code_length) + m = Method(code, local_count) + self._all_methods.append(m) + for avm_class in classes: + if method_idx in avm_class.method_idxs: + avm_class.methods[avm_class.method_idxs[method_idx]] = m + exception_count = u30() + for _c2 in range(exception_count): + u30() # from + u30() # to + u30() # target + u30() # exc_type + u30() # var_name + trait_count = u30() + for _c2 in range(trait_count): + parse_traits_info() + + assert p + code_reader.tell() == len(code_tag) + + def patch_function(self, avm_class, func_name, f): + self._patched_functions[(avm_class, func_name)] = f + + def extract_class(self, class_name, call_cinit=True): + try: + res = self._classes_by_name[class_name] + except KeyError: + raise ExtractorError('Class %r not found' % class_name) + + if call_cinit and hasattr(res, 'cinit_idx'): + res.register_methods({'$cinit': res.cinit_idx}) + res.methods['$cinit'] = self._all_methods[res.cinit_idx] + cinit = self.extract_function(res, '$cinit') + cinit([]) + + return res + + def extract_function(self, avm_class, func_name): + p = self._patched_functions.get((avm_class, func_name)) + if p: + return p + if func_name in avm_class.method_pyfunctions: + return avm_class.method_pyfunctions[func_name] + if func_name in self._classes_by_name: + return self._classes_by_name[func_name].make_object() + if func_name not in avm_class.methods: + raise ExtractorError('Cannot find function %s.%s' % ( + avm_class.name, func_name)) + m = avm_class.methods[func_name] + + def resfunc(args): + # Helper functions + coder = io.BytesIO(m.code) + s24 = lambda: _s24(coder) + u30 = lambda: _u30(coder) + + registers = [avm_class.variables] + list(args) + [None] * m.local_count + stack = [] + scopes = collections.deque([ + self._classes_by_name, avm_class.constants, avm_class.variables]) + while True: + opcode = _read_byte(coder) + if opcode == 9: # label + pass # Spec says: "Do nothing." + elif opcode == 16: # jump + offset = s24() + coder.seek(coder.tell() + offset) + elif opcode == 17: # iftrue + offset = s24() + value = stack.pop() + if value: + coder.seek(coder.tell() + offset) + elif opcode == 18: # iffalse + offset = s24() + value = stack.pop() + if not value: + coder.seek(coder.tell() + offset) + elif opcode == 19: # ifeq + offset = s24() + value2 = stack.pop() + value1 = stack.pop() + if value2 == value1: + coder.seek(coder.tell() + offset) + elif opcode == 20: # ifne + offset = s24() + value2 = stack.pop() + value1 = stack.pop() + if value2 != value1: + coder.seek(coder.tell() + offset) + elif opcode == 21: # iflt + offset = s24() + value2 = stack.pop() + value1 = stack.pop() + if value1 < value2: + coder.seek(coder.tell() + offset) + elif opcode == 32: # pushnull + stack.append(None) + elif opcode == 33: # pushundefined + stack.append(undefined) + elif opcode == 36: # pushbyte + v = _read_byte(coder) + stack.append(v) + elif opcode == 37: # pushshort + v = u30() + stack.append(v) + elif opcode == 38: # pushtrue + stack.append(True) + elif opcode == 39: # pushfalse + stack.append(False) + elif opcode == 40: # pushnan + stack.append(float('NaN')) + elif opcode == 42: # dup + value = stack[-1] + stack.append(value) + elif opcode == 44: # pushstring + idx = u30() + stack.append(self.constant_strings[idx]) + elif opcode == 48: # pushscope + new_scope = stack.pop() + scopes.append(new_scope) + elif opcode == 66: # construct + arg_count = u30() + args = list(reversed( + [stack.pop() for _ in range(arg_count)])) + obj = stack.pop() + res = obj.avm_class.make_object() + stack.append(res) + elif opcode == 70: # callproperty + index = u30() + mname = self.multinames[index] + arg_count = u30() + args = list(reversed( + [stack.pop() for _ in range(arg_count)])) + obj = stack.pop() + + if obj == StringClass: + if mname == 'String': + assert len(args) == 1 + assert isinstance(args[0], ( + int, compat_str, _Undefined)) + if args[0] == undefined: + res = 'undefined' + else: + res = compat_str(args[0]) + stack.append(res) + continue + else: + raise NotImplementedError( + 'Function String.%s is not yet implemented' + % mname) + elif isinstance(obj, _AVMClass_Object): + func = self.extract_function(obj.avm_class, mname) + res = func(args) + stack.append(res) + continue + elif isinstance(obj, _AVMClass): + func = self.extract_function(obj, mname) + res = func(args) + stack.append(res) + continue + elif isinstance(obj, _ScopeDict): + if mname in obj.avm_class.method_names: + func = self.extract_function(obj.avm_class, mname) + res = func(args) + else: + res = obj[mname] + stack.append(res) + continue + elif isinstance(obj, compat_str): + if mname == 'split': + assert len(args) == 1 + assert isinstance(args[0], compat_str) + if args[0] == '': + res = list(obj) + else: + res = obj.split(args[0]) + stack.append(res) + continue + elif mname == 'charCodeAt': + assert len(args) <= 1 + idx = 0 if len(args) == 0 else args[0] + assert isinstance(idx, int) + res = ord(obj[idx]) + stack.append(res) + continue + elif isinstance(obj, list): + if mname == 'slice': + assert len(args) == 1 + assert isinstance(args[0], int) + res = obj[args[0]:] + stack.append(res) + continue + elif mname == 'join': + assert len(args) == 1 + assert isinstance(args[0], compat_str) + res = args[0].join(obj) + stack.append(res) + continue + raise NotImplementedError( + 'Unsupported property %r on %r' + % (mname, obj)) + elif opcode == 71: # returnvoid + res = undefined + return res + elif opcode == 72: # returnvalue + res = stack.pop() + return res + elif opcode == 73: # constructsuper + # Not yet implemented, just hope it works without it + arg_count = u30() + args = list(reversed( + [stack.pop() for _ in range(arg_count)])) + obj = stack.pop() + elif opcode == 74: # constructproperty + index = u30() + arg_count = u30() + args = list(reversed( + [stack.pop() for _ in range(arg_count)])) + obj = stack.pop() + + mname = self.multinames[index] + assert isinstance(obj, _AVMClass) + + # We do not actually call the constructor for now; + # we just pretend it does nothing + stack.append(obj.make_object()) + elif opcode == 79: # callpropvoid + index = u30() + mname = self.multinames[index] + arg_count = u30() + args = list(reversed( + [stack.pop() for _ in range(arg_count)])) + obj = stack.pop() + if isinstance(obj, _AVMClass_Object): + func = self.extract_function(obj.avm_class, mname) + res = func(args) + assert res is undefined + continue + if isinstance(obj, _ScopeDict): + assert mname in obj.avm_class.method_names + func = self.extract_function(obj.avm_class, mname) + res = func(args) + assert res is undefined + continue + if mname == 'reverse': + assert isinstance(obj, list) + obj.reverse() + else: + raise NotImplementedError( + 'Unsupported (void) property %r on %r' + % (mname, obj)) + elif opcode == 86: # newarray + arg_count = u30() + arr = [] + for i in range(arg_count): + arr.append(stack.pop()) + arr = arr[::-1] + stack.append(arr) + elif opcode == 93: # findpropstrict + index = u30() + mname = self.multinames[index] + for s in reversed(scopes): + if mname in s: + res = s + break + else: + res = scopes[0] + if mname not in res and mname in _builtin_classes: + stack.append(_builtin_classes[mname]) + else: + stack.append(res[mname]) + elif opcode == 94: # findproperty + index = u30() + mname = self.multinames[index] + for s in reversed(scopes): + if mname in s: + res = s + break + else: + res = avm_class.variables + stack.append(res) + elif opcode == 96: # getlex + index = u30() + mname = self.multinames[index] + for s in reversed(scopes): + if mname in s: + scope = s + break + else: + scope = avm_class.variables + + if mname in scope: + res = scope[mname] + elif mname in _builtin_classes: + res = _builtin_classes[mname] + else: + # Assume uninitialized + # TODO warn here + res = undefined + stack.append(res) + elif opcode == 97: # setproperty + index = u30() + value = stack.pop() + idx = self.multinames[index] + if isinstance(idx, _Multiname): + idx = stack.pop() + obj = stack.pop() + obj[idx] = value + elif opcode == 98: # getlocal + index = u30() + stack.append(registers[index]) + elif opcode == 99: # setlocal + index = u30() + value = stack.pop() + registers[index] = value + elif opcode == 102: # getproperty + index = u30() + pname = self.multinames[index] + if pname == 'length': + obj = stack.pop() + assert isinstance(obj, (compat_str, list)) + stack.append(len(obj)) + elif isinstance(pname, compat_str): # Member access + obj = stack.pop() + if isinstance(obj, _AVMClass): + res = obj.static_properties[pname] + stack.append(res) + continue + + assert isinstance(obj, (dict, _ScopeDict)),\ + 'Accessing member %r on %r' % (pname, obj) + res = obj.get(pname, undefined) + stack.append(res) + else: # Assume attribute access + idx = stack.pop() + assert isinstance(idx, int) + obj = stack.pop() + assert isinstance(obj, list) + stack.append(obj[idx]) + elif opcode == 104: # initproperty + index = u30() + value = stack.pop() + idx = self.multinames[index] + if isinstance(idx, _Multiname): + idx = stack.pop() + obj = stack.pop() + obj[idx] = value + elif opcode == 115: # convert_ + value = stack.pop() + intvalue = int(value) + stack.append(intvalue) + elif opcode == 128: # coerce + u30() + elif opcode == 130: # coerce_a + value = stack.pop() + # um, yes, it's any value + stack.append(value) + elif opcode == 133: # coerce_s + assert isinstance(stack[-1], (type(None), compat_str)) + elif opcode == 147: # decrement + value = stack.pop() + assert isinstance(value, int) + stack.append(value - 1) + elif opcode == 149: # typeof + value = stack.pop() + return { + _Undefined: 'undefined', + compat_str: 'String', + int: 'Number', + float: 'Number', + }[type(value)] + elif opcode == 160: # add + value2 = stack.pop() + value1 = stack.pop() + res = value1 + value2 + stack.append(res) + elif opcode == 161: # subtract + value2 = stack.pop() + value1 = stack.pop() + res = value1 - value2 + stack.append(res) + elif opcode == 162: # multiply + value2 = stack.pop() + value1 = stack.pop() + res = value1 * value2 + stack.append(res) + elif opcode == 164: # modulo + value2 = stack.pop() + value1 = stack.pop() + res = value1 % value2 + stack.append(res) + elif opcode == 168: # bitand + value2 = stack.pop() + value1 = stack.pop() + assert isinstance(value1, int) + assert isinstance(value2, int) + res = value1 & value2 + stack.append(res) + elif opcode == 171: # equals + value2 = stack.pop() + value1 = stack.pop() + result = value1 == value2 + stack.append(result) + elif opcode == 175: # greaterequals + value2 = stack.pop() + value1 = stack.pop() + result = value1 >= value2 + stack.append(result) + elif opcode == 192: # increment_i + value = stack.pop() + assert isinstance(value, int) + stack.append(value + 1) + elif opcode == 208: # getlocal_0 + stack.append(registers[0]) + elif opcode == 209: # getlocal_1 + stack.append(registers[1]) + elif opcode == 210: # getlocal_2 + stack.append(registers[2]) + elif opcode == 211: # getlocal_3 + stack.append(registers[3]) + elif opcode == 212: # setlocal_0 + registers[0] = stack.pop() + elif opcode == 213: # setlocal_1 + registers[1] = stack.pop() + elif opcode == 214: # setlocal_2 + registers[2] = stack.pop() + elif opcode == 215: # setlocal_3 + registers[3] = stack.pop() + else: + raise NotImplementedError( + 'Unsupported opcode %d' % opcode) + + avm_class.method_pyfunctions[func_name] = resfunc + return resfunc -- cgit v1.2.3