├── FrameScan.py ├── FrameScan.spec ├── Plugins ├── Modules │ ├── fake_useragent-1.1.1.dist-info │ │ ├── AUTHORS │ │ ├── INSTALLER │ │ ├── LICENSE │ │ ├── METADATA │ │ ├── RECORD │ │ ├── REQUESTED │ │ ├── WHEEL │ │ └── top_level.txt │ ├── fake_useragent │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── errors.cpython-37.pyc │ │ │ ├── fake.cpython-37.pyc │ │ │ ├── log.cpython-37.pyc │ │ │ ├── settings.cpython-37.pyc │ │ │ └── utils.cpython-37.pyc │ │ ├── data │ │ │ └── browsers.json │ │ ├── errors.py │ │ ├── fake.py │ │ ├── log.py │ │ ├── settings.py │ │ └── utils.py │ ├── importlib_resources │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── _adapters.cpython-37.pyc │ │ │ ├── _common.cpython-37.pyc │ │ │ ├── _compat.cpython-37.pyc │ │ │ ├── _itertools.cpython-37.pyc │ │ │ ├── _legacy.cpython-37.pyc │ │ │ ├── abc.cpython-37.pyc │ │ │ ├── readers.cpython-37.pyc │ │ │ └── simple.cpython-37.pyc │ │ ├── _adapters.py │ │ ├── _common.py │ │ ├── _compat.py │ │ ├── _itertools.py │ │ ├── _legacy.py │ │ ├── abc.py │ │ ├── py.typed │ │ ├── readers.py │ │ ├── simple.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── _compat.cpython-37.pyc │ │ │ ├── test_compatibilty_files.cpython-37.pyc │ │ │ ├── test_contents.cpython-37.pyc │ │ │ ├── test_files.cpython-37.pyc │ │ │ ├── test_open.cpython-37.pyc │ │ │ ├── test_path.cpython-37.pyc │ │ │ ├── test_read.cpython-37.pyc │ │ │ ├── test_reader.cpython-37.pyc │ │ │ ├── test_resource.cpython-37.pyc │ │ │ ├── update-zips.cpython-37.pyc │ │ │ └── util.cpython-37.pyc │ │ │ ├── _compat.py │ │ │ ├── data01 │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-37.pyc │ │ │ ├── binary.file │ │ │ ├── subdirectory │ │ │ │ ├── __init__.py │ │ │ │ ├── __pycache__ │ │ │ │ │ └── __init__.cpython-37.pyc │ │ │ │ └── binary.file │ │ │ ├── utf-16.file │ │ │ └── utf-8.file │ │ │ ├── data02 │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-37.pyc │ │ │ ├── one │ │ │ │ ├── __init__.py │ │ │ │ ├── __pycache__ │ │ │ │ │ └── __init__.cpython-37.pyc │ │ │ │ └── resource1.txt │ │ │ └── two │ │ │ │ ├── __init__.py │ │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-37.pyc │ │ │ │ └── resource2.txt │ │ │ ├── namespacedata01 │ │ │ ├── binary.file │ │ │ ├── utf-16.file │ │ │ └── utf-8.file │ │ │ ├── test_compatibilty_files.py │ │ │ ├── test_contents.py │ │ │ ├── test_files.py │ │ │ ├── test_open.py │ │ │ ├── test_path.py │ │ │ ├── test_read.py │ │ │ ├── test_reader.py │ │ │ ├── test_resource.py │ │ │ ├── update-zips.py │ │ │ ├── util.py │ │ │ ├── zipdata01 │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-37.pyc │ │ │ └── ziptestdata.zip │ │ │ └── zipdata02 │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ └── __init__.cpython-37.pyc │ │ │ └── ziptestdata.zip │ └── ysoserial-0.0.8-SNAPSHOT-all.jar └── Vuln_Plugins │ └── test │ ├── Plugins_漏洞插件模板.py │ ├── __pycache__ │ ├── 111.cpython-37.pyc │ ├── 122cpython-37.pyc │ ├── GetFileContent_fileread.cpython-37.pyc │ ├── GetFile_fileread - 副本.cpython-37.pyc │ ├── GetFile_fileread.cpython-37.pyc │ ├── GetFile_fileread_exp.cpython-37.pyc │ ├── GetFile_fileread_poc.cpython-37.pyc │ ├── GetXMLList_fileread.cpython-37.pyc │ ├── Plugins_23d.cpython-37.pyc │ ├── Plugins_aaa.cpython-37.pyc │ ├── Plugins_asdcpython-37.pyc │ ├── Plugins_test - 副本 (2).cpython-37.pyc │ ├── Plugins_test - 副本 (3).cpython-37.pyc │ ├── Plugins_test - 副本 (4).cpython-37.pyc │ ├── Plugins_test - 副本 (5).cpython-37.pyc │ ├── Plugins_test - 副本 (6).cpython-37.pyc │ ├── Plugins_test - 副本.cpython-37.pyc │ ├── Plugins_test.cpython-37.pyc │ ├── Plugins_test2.cpython-37.pyc │ ├── Plugins_wedfg.cpython-37.pyc │ ├── Plugins_漏洞插件模板.cpython-37.pyc │ ├── Plugins_金山防火墙_editschedule.php_远程命令执行.cpython-37.pyc │ ├── acsoft_GetFileContent_fileread.cpython-37.pyc │ ├── acsoft_GetFile_fileread.cpython-37.pyc │ ├── acsoft_GetXMLList_fileread.cpython-37.pyc │ ├── test.cpython-37.pyc │ ├── test22_exp.cpython-37.pyc │ ├── test2_poc.cpython-37.pyc │ ├── test_exp.cpython-37.pyc │ └── test_poc.cpython-37.pyc │ └── setup.py ├── Plugins_漏洞插件模板.py ├── README.md ├── VULN_DB.db ├── __pycache__ └── frozen_dir.cpython-37.pyc ├── color.py ├── color.pyc ├── frozen_dir.py ├── main.ico ├── modules ├── Class_Poc.py └── __pycache__ │ ├── Class_Poc.cpython-311.pyc │ └── Class_Poc.cpython-37.pyc └── requirements.txt /FrameScan.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['FrameScan.py'], 7 | pathex=['D:\\code\\Python37\\obj\\FrameScan'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=['bs4','uuid','xml.etree','xml.etree.ElementTree','eventlet.hubs.epolls', 'eventlet.hubs.kqueue','eventlet.hubs.selects', 'dns','dns.asyncresolver','dns.versioned', 'dns.dnssec', 'dns.asyncquery','dns.asyncbackend','dns.e164', 'dns.hash', 'dns.namedict', 'dns.tsigkeyring', 'dns.update', 'dns.version', 'dns.zone'], 11 | hookspath=[''], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher, 17 | noarchive=False) 18 | pyz = PYZ(a.pure, a.zipped_data, 19 | cipher=block_cipher) 20 | exe = EXE(pyz, 21 | a.scripts, 22 | a.binaries, 23 | a.zipfiles, 24 | a.datas, 25 | [], 26 | name='FrameScan', 27 | debug=False, 28 | bootloader_ignore_signals=False, 29 | strip=False, 30 | upx=True, 31 | upx_exclude=[], 32 | runtime_tmpdir=None, 33 | console=True , icon='main.ico') 34 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/AUTHORS: -------------------------------------------------------------------------------- 1 | fake-useragent contributors 2 | 3 | Original author: 4 | 5 | Victor Kovtun @hellysmile 6 | 7 | Second author/maintainer: 8 | 9 | Melroy van den Berg @danger89 10 | 11 | Contributors: 12 | 13 | Alexey Shablevskiy @pcinkh 14 | Christian Clauss @cclauss 15 | Jordan Vuong @Jordan9675 16 | Mohamad Nour Chawich @mochawich 17 | Simon Wenmouth @simon-wenmouth 18 | 19 | 20 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/INSTALLER: -------------------------------------------------------------------------------- 1 | pip 2 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright (c) hellysmile@gmail.com 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/METADATA: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.1 2 | Name: fake-useragent 3 | Version: 1.1.1 4 | Summary: Up-to-date simple useragent faker with real world database 5 | Author-email: Victor Kovtun , Melroy van den Berg 6 | Project-URL: Homepage, https://github.com/fake-useragent/fake-useragent 7 | Keywords: user,agent,user agent,useragent,fake,fake useragent,fake user agent 8 | Classifier: Development Status :: 5 - Production/Stable 9 | Classifier: Intended Audience :: Developers 10 | Classifier: License :: OSI Approved :: Apache Software License 11 | Classifier: Operating System :: POSIX 12 | Classifier: Operating System :: MacOS :: MacOS X 13 | Classifier: Operating System :: Microsoft :: Windows 14 | Classifier: Programming Language :: Python 15 | Classifier: Programming Language :: Python :: 3 16 | Classifier: Programming Language :: Python :: 3 :: Only 17 | Classifier: Operating System :: OS Independent 18 | Classifier: Topic :: Internet :: WWW/HTTP 19 | Classifier: Topic :: Software Development 20 | Classifier: Topic :: Software Development :: Libraries :: Python Modules 21 | Classifier: Topic :: Utilities 22 | Description-Content-Type: text/markdown 23 | License-File: LICENSE 24 | License-File: AUTHORS 25 | Requires-Dist: importlib-resources (>=5.0) ; python_version < "3.10" 26 | Requires-Dist: importlib-metadata (~=4.0) ; python_version < "3.8" 27 | 28 | [![Test & Deploy fake-useragent](https://github.com/fake-useragent/fake-useragent/actions/workflows/action.yml/badge.svg?branch=master)](https://github.com/fake-useragent/fake-useragent/actions/workflows/action.yml?query=branch%3Amaster) 29 | 30 | # fake-useragent 31 | 32 | Up-to-date simple useragent faker with real world database 33 | 34 | ## Features 35 | 36 | - Data is pre-downloaded from [useragentstring.com](http://useragentstring.com/) and part of the package 37 | - Retrieves user-agent strings locally 38 | - Supports Python 3.x 39 | - _Fallback_ to external resource ([useragentstring.com](http://useragentstring.com/)) + caching 40 | 41 | ### Installation 42 | 43 | ```sh 44 | pip install fake-useragent 45 | ``` 46 | 47 | Or if you have multiple Python / pip versions installed, use `pip3`: 48 | 49 | ```sh 50 | pip3 install fake-useragent 51 | ``` 52 | 53 | ### Usage 54 | 55 | ```py 56 | from fake_useragent import UserAgent 57 | ua = UserAgent() 58 | 59 | ua.ie 60 | # Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US); 61 | ua.msie 62 | # Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)' 63 | ua['Internet Explorer'] 64 | # Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US) 65 | ua.opera 66 | # Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11 67 | ua.chrome 68 | # Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2' 69 | ua.google 70 | # Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.13 (KHTML, like Gecko) Chrome/24.0.1290.1 Safari/537.13 71 | ua['google chrome'] 72 | # Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11 73 | ua.firefox 74 | # Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1 75 | ua.ff 76 | # Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1 77 | ua.safari 78 | # Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 79 | 80 | # and the best one, get a random browser user-agent string 81 | ua.random 82 | ``` 83 | 84 | ### Notes 85 | 86 | If you want to specify your own browser list, you can do that via the `browsers` argument (default is: `["chrome", "edge", "internet explorer", "firefox", "safari", "opera"]`). 87 | 88 | ```py 89 | from fake_useragent import UserAgent 90 | ua = UserAgent(browsers=['edge', 'chrome']) 91 | ua.random 92 | ``` 93 | 94 | You can add your own fallback string using the `fallback` parameter, in rare cases everything else failed: 95 | 96 | ```py 97 | import fake_useragent 98 | 99 | ua = fake_useragent.UserAgent(fallback='your favorite Browser') 100 | # in case if something went wrong, one more time it is REALLY!!! rare case 101 | ua.random == 'your favorite Browser' 102 | ``` 103 | 104 | If you will try to get unknown browser: 105 | 106 | ```py 107 | from fake_useragent import UserAgent 108 | ua = UserAgent() 109 | ua.unknown 110 | # Traceback (most recent call last): 111 | # ... 112 | # fake_useragent.errors.FakeUserAgentError: Error occurred during getting browser: unknown 113 | ``` 114 | 115 | By default `fake-useragent` will use it's local ([`browsers.json`](./fake_useragent/data/browsers.json)) data file as the data source. 116 | 117 | If you don't want to use the local data, but use the external data source to retrieve the user-agents. Set `use_external_data` to `True`: 118 | 119 | ```py 120 | from fake_useragent import UserAgent 121 | ua = UserAgent(use_external_data=True) 122 | ``` 123 | 124 | As a fallback method `fake-useragent` will retrieve it's data from an external data source and stores in a cache file _or_ when you expcility set `use_external_data=True` as parameter. 125 | You can trigger an update to the cache file by calling `update()`: 126 | 127 | ```py 128 | from fake_useragent import UserAgent 129 | ua = UserAgent() 130 | ua.update() 131 | ``` 132 | 133 | The default location of the external resource cache file is in your os temp dir, like `/tmp`. 134 | You can change the temp directory by changing `cache_path` (mainly useful together when `use_external_data` is set to True). 135 | 136 | ```py 137 | import fake_useragent 138 | 139 | # I am strongly! recommend using a version suffix 140 | location = '/home/user/fake_useragent%s.json' % fake_useragent.VERSION 141 | 142 | ua = fake_useragent.UserAgent(use_external_data=True, cache_path=location) 143 | ua.random 144 | ``` 145 | 146 | If you need to safe some attributes from overriding them in UserAgent by `__getattr__` method 147 | use `safe_attrs` you can pass there attributes names. 148 | At least this will prevent you from raising FakeUserAgentError when attribute not found. 149 | 150 | For example, when using fake*useragent with `injections `* you need to: 151 | 152 | ```py 153 | import fake_useragent 154 | 155 | ua = fake_useragent.UserAgent(safe_attrs=('__injections__',)) 156 | ``` 157 | 158 | Please, do not use if you don't understand why you need this. 159 | This is magic for rarely extreme case. 160 | 161 | ### Experiencing issues? 162 | 163 | Make sure that you using latest version! 164 | 165 | ```sh 166 | pip install --upgrade fake-useragent 167 | ``` 168 | 169 | Check version via python console: 170 | 171 | ```py 172 | import fake_useragent 173 | 174 | print(fake_useragent.VERSION) 175 | ``` 176 | 177 | And you are always welcome to post [issues](https://github.com/fake-useragent/fake-useragent/issues). 178 | 179 | Please do not forget to mention the version that you are using. 180 | 181 | ### Developers 182 | 183 | Since GitHub Actions is unable to reach useragentstring.com. We can run the script below to automatically scrape the user-agent strings from the external data source. The script will copy the [JSONlines](https://jsonlines.org/) file to the `src/fake_useragent/data` directory. Execute: 184 | 185 | ```sh 186 | ./update_data_file.sh 187 | ``` 188 | 189 | The data JSON file is part of the Python package, see [pyproject.toml](pyproject.toml). Read more about [Data files support](https://setuptools.pypa.io/en/latest/userguide/datafiles.html). 190 | 191 | ### Tests 192 | 193 | ```sh 194 | pip install -r requirements.txt 195 | tox 196 | ``` 197 | 198 | ### Changelog 199 | 200 | - 1.1.1 December 4, 2022 201 | 202 | - Remove whitespaces from user agent strings, this is a patch release 203 | 204 | - 1.1.0 November 26, 2022 205 | 206 | - Add `pkg_resource` as fallback mechanism in trying to retrieve the local JSON data file 207 | 208 | - 1.0.1 November 10, 2022 209 | 210 | - Add `importlib-metadata` & `importlib-resources` as dependencies 211 | - Check on specific Python version regarding the importlib resources (python v3.10 or higher) in order to have `files()` working 212 | - `importlib_metadata` should now also work on Python version before 3.8 213 | - Remove obsolete `MANIFEST.in` file 214 | 215 | - 1.0.0 November 17, 2022 216 | 217 | - Make the JSON Lines data file part of the Python package, data is retrieved locally 218 | - Extend the `myproject.toml` file with `package-data` support 219 | - Remove centralized caching server implementation 220 | - Make real unit-tests which should run reliable, fast, independent and without Internet connection 221 | 222 | - 0.1.14 November 5, 2022 223 | 224 | - Improve code quality standards using modern Python >=3.7 syntax 225 | - Migrated to `pyproject.toml` build system format + syntax check 226 | - Add additional classifiers to the toml file 227 | - Improved `tox.ini` file 228 | - Improved GitHub Actions job using pip cache 229 | - And various small fixes 230 | 231 | - 0.1.13 October 21, 2022 232 | 233 | - Implement `browsers` argument, allowing you to override the browser names you want to use 234 | - Fix browser listing of Internet Explorer and Edge 235 | - Don't depend on w3schools.com anymore 236 | - Clean-up data (temp) file format 237 | - Update fallback cache server URL / use JSON Lines as file format 238 | - Move to GitHub Actions instead of Travis 239 | - Using [`black`](https://pypi.org/project/black/) Python formatter in favour of Flake 240 | 241 | - 0.1.12 March 31, 2022 242 | 243 | - forked 244 | 245 | - 0.1.11 October 4, 2018 246 | 247 | - moved `s3 + cloudfront` fallback to `heroku.com`, cuz someone from Florida did ~25M requests last month 248 | 249 | - 0.1.10 February 11, 2018 250 | 251 | - Minor fix docs `cloudfront` url 252 | 253 | - 0.1.9 February 11, 2018 254 | 255 | - fix `w3schools.com` renamed `IE/Edge` to `Edge/IE` 256 | - moved `heroku.com` fallback to `s3 + cloudfront` 257 | - stop testing Python3.3 and pypy 258 | 259 | - 0.1.8 November 2, 2017 260 | 261 | - fix `useragentstring.com` `Can't connect to local MySQL server through socket` 262 | 263 | - 0.1.7 April 2, 2017 264 | 265 | - fix broken README.rst 266 | 267 | - 0.1.6 April 2, 2017 268 | 269 | - fixes bug `use_cache_server` do not affected anything 270 | - `w3schools.com `\_ moved to `https` 271 | - `verify_ssl` options added, by default it is `True` (`urllib.urlopen` ssl context for Python 2.7.9- and 3.4.3- is not supported) 272 | 273 | - 0.1.5 February 28, 2017 274 | 275 | - added `ua.edge` alias to Internet Explorer 276 | - w3schools.com starts displaying `Edge` statistic 277 | - Python 2.6 is not tested anymore 278 | - `use_cache_server` option added 279 | - Increased `fake_useragent.settings.HTTP_TIMEOUT` to 5 seconds 280 | 281 | - 0.1.4 December 14, 2016 282 | 283 | - Added custom data file location support 284 | - Added `fallback` browser support, in case of unavailable data sources 285 | - Added alias `fake_useragent.FakeUserAgent` for `fake_useragent.UserAgent` 286 | - Added alias `fake_useragent.UserAgentError` for `fake_useragent.FakeUserAgentError` 287 | - Reduced `fake_useragent.settings.HTTP_TIMEOUT` to 3 seconds 288 | - Started migration to new data file format 289 | - Simplified a lot 4+ years out of date code 290 | - Better thread/greenlet safety 291 | - Added verbose logging 292 | - Added `safe_attrs` for prevent overriding by `__getattr__` 293 | 294 | - 0.1.3 November 24, 2016 295 | 296 | - Added hosted data file, when remote services is unavailable 297 | - Raises `fake_useragent.errors.FakeUserAgentError` in case when there is not way to download data 298 | - Raises `fake_useragent.errors.FakeUserAgentError` instead of `None` in case of unknown browser 299 | - Added `gevent.sleep` support in `gevent` patched environment when trying to download data 300 | 301 | - X.X.X xxxxxxx xx, xxxx 302 | - xxxxx ????? 303 | 304 | ### Authors 305 | 306 | You can visit [authors page](https://github.com/fake-useragent/fake-useragent/blob/master/AUTHORS). 307 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/RECORD: -------------------------------------------------------------------------------- 1 | fake_useragent-1.1.1.dist-info/AUTHORS,sha256=mhMJ71pwkendkm3WhzuJqeJ30fwgv9ZN9rIQYFhOCWU,416 2 | fake_useragent-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 3 | fake_useragent-1.1.1.dist-info/LICENSE,sha256=_Ztic_IrfCnbxRYLgA-IJLdM8Ej4njmhG1wjwQ9G1pI,11350 4 | fake_useragent-1.1.1.dist-info/METADATA,sha256=6mpUFXhPg5DxxAeWnoE8IqfFB57EIbQcO8CCbfbhDBY,10763 5 | fake_useragent-1.1.1.dist-info/RECORD,, 6 | fake_useragent-1.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 7 | fake_useragent-1.1.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92 8 | fake_useragent-1.1.1.dist-info/top_level.txt,sha256=E3UkMtxIGd_XibNEcmO_SqpBojSyHGs8XViImlALu-E,15 9 | fake_useragent/__init__.py,sha256=EWYvJraItFoSKHBgSOjzGKl8iLy6ixXgSAqypFHbqTo,261 10 | fake_useragent/__pycache__/__init__.cpython-37.pyc,, 11 | fake_useragent/__pycache__/errors.cpython-37.pyc,, 12 | fake_useragent/__pycache__/fake.cpython-37.pyc,, 13 | fake_useragent/__pycache__/log.cpython-37.pyc,, 14 | fake_useragent/__pycache__/settings.cpython-37.pyc,, 15 | fake_useragent/__pycache__/utils.cpython-37.pyc,, 16 | fake_useragent/data/browsers.json,sha256=qoD1sD7VFZMMtM8ViZWzceGHnPXOGTnY6ntpehuWe1Y,441951 17 | fake_useragent/errors.py,sha256=ds-R7AepfhJf-2CEu82p2VdKXx95UGieR-_EXc_1_VI,99 18 | fake_useragent/fake.py,sha256=4hTbv5_3wH_XGy-0Jp2ggKd1HFEpeaM9tkiyE2a7ML0,4570 19 | fake_useragent/log.py,sha256=y182BcMTIwvHHyS3gn5ZrgQuTGSNwKhD9imeQ6KJK10,56 20 | fake_useragent/settings.py,sha256=qRjrqljZx6DTAbN1E42czXWouPc11n1JjuQDc9QLw9A,895 21 | fake_useragent/utils.py,sha256=3B2sCm8kDvdKHQlHJS_w_lmAulSyyB0U-8ctRhMZAAc,6281 22 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/REQUESTED: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent-1.1.1.dist-info/REQUESTED -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/WHEEL: -------------------------------------------------------------------------------- 1 | Wheel-Version: 1.0 2 | Generator: bdist_wheel (0.38.4) 3 | Root-Is-Purelib: true 4 | Tag: py3-none-any 5 | 6 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent-1.1.1.dist-info/top_level.txt: -------------------------------------------------------------------------------- 1 | fake_useragent 2 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__init__.py: -------------------------------------------------------------------------------- 1 | from fake_useragent.fake import FakeUserAgent, UserAgent # noqa # isort:skip 2 | from fake_useragent.errors import ( 3 | FakeUserAgentError, 4 | UserAgentError, 5 | ) # noqa # isort:skip 6 | from fake_useragent.settings import __version__ as VERSION # noqa # isort:skip 7 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__pycache__/errors.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent/__pycache__/errors.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__pycache__/fake.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent/__pycache__/fake.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__pycache__/log.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent/__pycache__/log.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__pycache__/settings.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent/__pycache__/settings.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/__pycache__/utils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/fake_useragent/__pycache__/utils.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/errors.py: -------------------------------------------------------------------------------- 1 | class FakeUserAgentError(Exception): 2 | pass 3 | 4 | 5 | # common alias 6 | UserAgentError = FakeUserAgentError 7 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/fake.py: -------------------------------------------------------------------------------- 1 | import random 2 | from threading import Lock 3 | 4 | from fake_useragent import settings 5 | from fake_useragent.errors import FakeUserAgentError 6 | from fake_useragent.log import logger 7 | from fake_useragent.utils import load, load_cached, str_types, update 8 | 9 | 10 | class FakeUserAgent: 11 | def __init__( 12 | self, 13 | use_external_data=False, 14 | cache_path=settings.DB, 15 | fallback=None, 16 | browsers=["chrome", "edge", "internet explorer", "firefox", "safari", "opera"], 17 | verify_ssl=True, 18 | safe_attrs=tuple(), 19 | ): 20 | assert isinstance( 21 | use_external_data, bool 22 | ), "use_external_data must be True or False" 23 | 24 | self.use_external_data = use_external_data 25 | 26 | assert isinstance(cache_path, str_types), "cache_path must be string or unicode" 27 | 28 | self.cache_path = cache_path 29 | 30 | if fallback is not None: 31 | assert isinstance(fallback, str_types), "fallback must be string or unicode" 32 | 33 | self.fallback = fallback 34 | 35 | assert isinstance(browsers, (list, str)), "browsers must be list or string" 36 | 37 | self.browsers = browsers 38 | 39 | assert isinstance(verify_ssl, bool), "verify_ssl must be True or False" 40 | 41 | self.verify_ssl = verify_ssl 42 | 43 | assert isinstance( 44 | safe_attrs, (list, set, tuple) 45 | ), "safe_attrs must be list\\tuple\\set of strings or unicode" 46 | 47 | if safe_attrs: 48 | str_types_safe_attrs = [isinstance(attr, str_types) for attr in safe_attrs] 49 | 50 | assert all( 51 | str_types_safe_attrs 52 | ), "safe_attrs must be list\\tuple\\set of strings or unicode" 53 | 54 | self.safe_attrs = set(safe_attrs) 55 | 56 | # initial empty data 57 | self.data_browsers = {} 58 | 59 | self.load() 60 | 61 | def load(self): 62 | try: 63 | with self.load.lock: 64 | if self.use_external_data: 65 | # Use external resource to retrieve browser data 66 | self.data_browsers = load_cached( 67 | self.cache_path, 68 | self.browsers, 69 | verify_ssl=self.verify_ssl, 70 | ) 71 | else: 72 | # By default we will try to load our local file 73 | self.data_browsers = load( 74 | self.browsers, 75 | verify_ssl=self.verify_ssl, 76 | ) 77 | except FakeUserAgentError: 78 | if self.fallback is None: 79 | raise 80 | else: 81 | logger.warning( 82 | "Error occurred during fetching data, " 83 | "but was suppressed with fallback.", 84 | ) 85 | 86 | load.lock = Lock() 87 | 88 | def update(self, use_external_data=None): 89 | with self.update.lock: 90 | if use_external_data is not None: 91 | assert isinstance( 92 | use_external_data, bool 93 | ), "use_external_data must be True or False" 94 | 95 | self.use_external_data = use_external_data 96 | 97 | # Update tmp cache file from external data source 98 | if self.use_external_data: 99 | update( 100 | self.cache_path, 101 | self.browsers, 102 | verify_ssl=self.verify_ssl, 103 | ) 104 | 105 | self.load() 106 | 107 | update.lock = Lock() 108 | 109 | def __getitem__(self, attr): 110 | return self.__getattr__(attr) 111 | 112 | def __getattr__(self, attr): 113 | if attr in self.safe_attrs: 114 | return super(UserAgent, self).__getattr__(attr) 115 | 116 | try: 117 | for value, replacement in settings.REPLACEMENTS.items(): 118 | attr = attr.replace(value, replacement) 119 | 120 | attr = attr.lower() 121 | 122 | if attr == "random": 123 | # Pick a random browser from the browsers argument list 124 | browser_name = random.choice(self.browsers) 125 | else: 126 | browser_name = settings.SHORTCUTS.get(attr, attr) 127 | 128 | # Pick a random user-agent string for a specific browser 129 | return random.choice(self.data_browsers[browser_name]) 130 | except (KeyError, IndexError): 131 | if self.fallback is None: 132 | raise FakeUserAgentError( 133 | f"Error occurred during getting browser: {attr}" 134 | ) # noqa 135 | else: 136 | logger.warning( 137 | f"Error occurred during getting browser: {attr}, " 138 | "but was suppressed with fallback.", 139 | ) 140 | 141 | return self.fallback 142 | 143 | 144 | # common alias 145 | UserAgent = FakeUserAgent 146 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/log.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | logger = logging.getLogger(__package__) 4 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | 4 | try: 5 | from importlib import metadata 6 | except ImportError: 7 | # Running on pre-3.8 Python; use importlib-metadata package 8 | import importlib_metadata as metadata 9 | 10 | __version__ = metadata.version("fake-useragent") 11 | 12 | DB = os.path.join( 13 | tempfile.gettempdir(), 14 | "fake_useragent_{version}.json".format( 15 | version=__version__, 16 | ), 17 | ) 18 | 19 | BROWSER_BASE_PAGE = "https://useragentstring.com/pages/{browser}/" # noqa 20 | 21 | BROWSERS_COUNT_LIMIT = 50 22 | 23 | REPLACEMENTS = { 24 | " ": "", 25 | "_": "", 26 | } 27 | 28 | SHORTCUTS = { 29 | "internetexplorer": "internet explorer", 30 | "ie": "internet explorer", 31 | "msie": "internet explorer", 32 | "microsoft edge": "edge", 33 | "google": "chrome", 34 | "googlechrome": "chrome", 35 | "ff": "firefox", 36 | } 37 | 38 | OVERRIDES = { 39 | "Edge/IE": "Internet Explorer", 40 | "IE/Edge": "Internet Explorer", 41 | } 42 | 43 | HTTP_TIMEOUT = 5 44 | 45 | HTTP_RETRIES = 2 46 | 47 | HTTP_DELAY = 0.1 48 | -------------------------------------------------------------------------------- /Plugins/Modules/fake_useragent/utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import contextlib 3 | import inspect 4 | import io 5 | import json 6 | import os 7 | import re 8 | import ssl 9 | import time 10 | 11 | 12 | # We need files() from Python 3.10 or higher 13 | if sys.version_info >= (3, 10): 14 | import importlib.resources as ilr 15 | else: 16 | import importlib_resources as ilr 17 | 18 | from urllib.error import URLError 19 | from urllib.parse import quote_plus 20 | from urllib import request 21 | from fake_useragent.log import logger 22 | 23 | # Fallback method for retrieving data file 24 | try: 25 | from pkg_resources import resource_filename 26 | except: 27 | pass 28 | 29 | str_types = (str,) 30 | text = str 31 | urlopen_args = inspect.getfullargspec(request.urlopen).kwonlyargs 32 | urlopen_has_ssl_context = "context" in urlopen_args 33 | 34 | 35 | def get(url, verify_ssl=True): 36 | attempt = 0 37 | 38 | while True: 39 | requestObj = request.Request(url) 40 | 41 | attempt += 1 42 | 43 | try: 44 | if urlopen_has_ssl_context: 45 | if not verify_ssl: 46 | context = ssl._create_unverified_context() 47 | else: 48 | context = None 49 | 50 | with contextlib.closing( 51 | request.urlopen( 52 | requestObj, 53 | timeout=settings.HTTP_TIMEOUT, 54 | context=context, 55 | ) 56 | ) as response: 57 | return response.read() 58 | else: # ssl context is not supported ;( 59 | with contextlib.closing( 60 | request.urlopen( 61 | requestObj, 62 | timeout=settings.HTTP_TIMEOUT, 63 | ) 64 | ) as response: 65 | return response.read() 66 | except (URLError, OSError) as exc: 67 | logger.debug( 68 | "Error occurred during fetching %s", 69 | url, 70 | exc_info=exc, 71 | ) 72 | 73 | if attempt == settings.HTTP_RETRIES: 74 | raise FakeUserAgentError("Maximum amount of retries reached") 75 | else: 76 | logger.debug( 77 | "Sleeping for %s seconds", 78 | settings.HTTP_DELAY, 79 | ) 80 | time.sleep(settings.HTTP_DELAY) 81 | 82 | 83 | def get_browser_user_agents_online(browser, verify_ssl=True): 84 | """ 85 | Retrieve browser user agent strings from website 86 | """ 87 | html = get( 88 | settings.BROWSER_BASE_PAGE.format(browser=quote_plus(browser)), 89 | verify_ssl=verify_ssl, 90 | ) 91 | try: 92 | html = html.decode("utf-8") 93 | except (UnicodeDecodeError, AttributeError): 94 | pass 95 | html = html.split("
")[1] 96 | html = html.split("
")[0] 97 | 98 | pattern = r"(.+?)" 99 | browsers_iter = re.finditer(pattern, html, re.UNICODE) 100 | 101 | browsers = [] 102 | 103 | for browser in browsers_iter: 104 | if "more" in browser.group(1).lower(): 105 | continue 106 | 107 | browsers.append(browser.group(1)) 108 | 109 | if len(browsers) == settings.BROWSERS_COUNT_LIMIT: 110 | break 111 | 112 | if not browsers: 113 | raise FakeUserAgentError( 114 | "No browser user-agent strings found for browser: {browser}".format( 115 | browser=browser 116 | ) 117 | ) 118 | 119 | return browsers 120 | 121 | 122 | def load(browsers, use_local_file=True, verify_ssl=True): 123 | data = {} 124 | fetch_online = True 125 | if use_local_file: 126 | try: 127 | json_lines = ( 128 | ilr.files("fake_useragent.data").joinpath("browsers.json").read_text() 129 | ) 130 | for line in json_lines.splitlines(): 131 | data.update(json.loads(line)) 132 | fetch_online = False 133 | ret = data 134 | except Exception as exc: 135 | # Empty data just to be sure 136 | data = {} 137 | logger.warning( 138 | "Unable to find local data/json file or could not parse the contents using importlib-resources. Try pkg-resource next.", 139 | exc_info=exc, 140 | ) 141 | try: 142 | with open( 143 | resource_filename("fake_useragent", "data/browsers.json") 144 | ) as file: 145 | json_lines = file.read() 146 | for line in json_lines.splitlines(): 147 | data.update(json.loads(line)) 148 | fetch_online = False 149 | ret = data 150 | except Exception as exc2: 151 | # Empty data just to be sure 152 | data = {} 153 | logger.warning( 154 | "Could not find local data/json file or could not parse the contents using pkg-resource. Fallback to external resource.", 155 | exc_info=exc2, 156 | ) 157 | 158 | # Fallback behaviour or use_external_data parameter is explicitly set to True 159 | if fetch_online: 160 | try: 161 | # For each browser receive the user-agent strings 162 | for browser_name in browsers: 163 | browser_name = browser_name.lower().strip() 164 | data[browser_name] = get_browser_user_agents_online( 165 | browser_name, 166 | verify_ssl=verify_ssl, 167 | ) 168 | except Exception: 169 | raise FakeUserAgentError("Could not load data from external website") 170 | else: 171 | ret = data 172 | 173 | if not ret: 174 | raise FakeUserAgentError("Data dictionary is empty", ret) 175 | 176 | if not isinstance(ret, dict): 177 | raise FakeUserAgentError("Data is not dictionary ", ret) 178 | 179 | return ret 180 | 181 | 182 | def write(path, data): 183 | with open(path, encoding="utf-8", mode="w") as fp: 184 | dumped = json.dumps(data) 185 | 186 | if not isinstance(dumped, text): # Python 2 187 | dumped = dumped.decode("utf-8") 188 | 189 | fp.write(dumped) 190 | 191 | 192 | def read(path): 193 | with open(path, encoding="utf-8") as fp: 194 | return json.loads(fp.read()) 195 | 196 | 197 | def exist(path): 198 | return os.path.isfile(path) 199 | 200 | 201 | def rm(path): 202 | if exist(path): 203 | os.remove(path) 204 | 205 | 206 | def update(cache_path, browsers, verify_ssl=True): 207 | rm(cache_path) 208 | 209 | write(cache_path, load(browsers, use_local_file=False, verify_ssl=verify_ssl)) 210 | 211 | 212 | def load_cached(cache_path, browsers, verify_ssl=True): 213 | if not exist(cache_path): 214 | update(cache_path, browsers, verify_ssl=verify_ssl) 215 | 216 | return read(cache_path) 217 | 218 | 219 | from fake_useragent import settings # noqa # isort:skip 220 | from fake_useragent.errors import FakeUserAgentError # noqa # isort:skip 221 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__init__.py: -------------------------------------------------------------------------------- 1 | """Read resources contained within a package.""" 2 | 3 | from ._common import ( 4 | as_file, 5 | files, 6 | Package, 7 | ) 8 | 9 | from ._legacy import ( 10 | contents, 11 | open_binary, 12 | read_binary, 13 | open_text, 14 | read_text, 15 | is_resource, 16 | path, 17 | Resource, 18 | ) 19 | 20 | from importlib_resources.abc import ResourceReader 21 | 22 | 23 | __all__ = [ 24 | 'Package', 25 | 'Resource', 26 | 'ResourceReader', 27 | 'as_file', 28 | 'contents', 29 | 'files', 30 | 'is_resource', 31 | 'open_binary', 32 | 'open_text', 33 | 'path', 34 | 'read_binary', 35 | 'read_text', 36 | ] 37 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/_adapters.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/_adapters.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/_common.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/_common.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/_compat.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/_compat.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/_itertools.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/_itertools.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/_legacy.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/_legacy.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/abc.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/abc.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/readers.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/readers.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/__pycache__/simple.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/__pycache__/simple.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/_adapters.py: -------------------------------------------------------------------------------- 1 | from contextlib import suppress 2 | from io import TextIOWrapper 3 | 4 | from . import abc 5 | 6 | 7 | class SpecLoaderAdapter: 8 | """ 9 | Adapt a package spec to adapt the underlying loader. 10 | """ 11 | 12 | def __init__(self, spec, adapter=lambda spec: spec.loader): 13 | self.spec = spec 14 | self.loader = adapter(spec) 15 | 16 | def __getattr__(self, name): 17 | return getattr(self.spec, name) 18 | 19 | 20 | class TraversableResourcesLoader: 21 | """ 22 | Adapt a loader to provide TraversableResources. 23 | """ 24 | 25 | def __init__(self, spec): 26 | self.spec = spec 27 | 28 | def get_resource_reader(self, name): 29 | return CompatibilityFiles(self.spec)._native() 30 | 31 | 32 | def _io_wrapper(file, mode='r', *args, **kwargs): 33 | if mode == 'r': 34 | return TextIOWrapper(file, *args, **kwargs) 35 | elif mode == 'rb': 36 | return file 37 | raise ValueError( 38 | "Invalid mode value '{}', only 'r' and 'rb' are supported".format(mode) 39 | ) 40 | 41 | 42 | class CompatibilityFiles: 43 | """ 44 | Adapter for an existing or non-existent resource reader 45 | to provide a compatibility .files(). 46 | """ 47 | 48 | class SpecPath(abc.Traversable): 49 | """ 50 | Path tied to a module spec. 51 | Can be read and exposes the resource reader children. 52 | """ 53 | 54 | def __init__(self, spec, reader): 55 | self._spec = spec 56 | self._reader = reader 57 | 58 | def iterdir(self): 59 | if not self._reader: 60 | return iter(()) 61 | return iter( 62 | CompatibilityFiles.ChildPath(self._reader, path) 63 | for path in self._reader.contents() 64 | ) 65 | 66 | def is_file(self): 67 | return False 68 | 69 | is_dir = is_file 70 | 71 | def joinpath(self, other): 72 | if not self._reader: 73 | return CompatibilityFiles.OrphanPath(other) 74 | return CompatibilityFiles.ChildPath(self._reader, other) 75 | 76 | @property 77 | def name(self): 78 | return self._spec.name 79 | 80 | def open(self, mode='r', *args, **kwargs): 81 | return _io_wrapper(self._reader.open_resource(None), mode, *args, **kwargs) 82 | 83 | class ChildPath(abc.Traversable): 84 | """ 85 | Path tied to a resource reader child. 86 | Can be read but doesn't expose any meaningful children. 87 | """ 88 | 89 | def __init__(self, reader, name): 90 | self._reader = reader 91 | self._name = name 92 | 93 | def iterdir(self): 94 | return iter(()) 95 | 96 | def is_file(self): 97 | return self._reader.is_resource(self.name) 98 | 99 | def is_dir(self): 100 | return not self.is_file() 101 | 102 | def joinpath(self, other): 103 | return CompatibilityFiles.OrphanPath(self.name, other) 104 | 105 | @property 106 | def name(self): 107 | return self._name 108 | 109 | def open(self, mode='r', *args, **kwargs): 110 | return _io_wrapper( 111 | self._reader.open_resource(self.name), mode, *args, **kwargs 112 | ) 113 | 114 | class OrphanPath(abc.Traversable): 115 | """ 116 | Orphan path, not tied to a module spec or resource reader. 117 | Can't be read and doesn't expose any meaningful children. 118 | """ 119 | 120 | def __init__(self, *path_parts): 121 | if len(path_parts) < 1: 122 | raise ValueError('Need at least one path part to construct a path') 123 | self._path = path_parts 124 | 125 | def iterdir(self): 126 | return iter(()) 127 | 128 | def is_file(self): 129 | return False 130 | 131 | is_dir = is_file 132 | 133 | def joinpath(self, other): 134 | return CompatibilityFiles.OrphanPath(*self._path, other) 135 | 136 | @property 137 | def name(self): 138 | return self._path[-1] 139 | 140 | def open(self, mode='r', *args, **kwargs): 141 | raise FileNotFoundError("Can't open orphan path") 142 | 143 | def __init__(self, spec): 144 | self.spec = spec 145 | 146 | @property 147 | def _reader(self): 148 | with suppress(AttributeError): 149 | return self.spec.loader.get_resource_reader(self.spec.name) 150 | 151 | def _native(self): 152 | """ 153 | Return the native reader if it supports files(). 154 | """ 155 | reader = self._reader 156 | return reader if hasattr(reader, 'files') else self 157 | 158 | def __getattr__(self, attr): 159 | return getattr(self._reader, attr) 160 | 161 | def files(self): 162 | return CompatibilityFiles.SpecPath(self.spec, self._reader) 163 | 164 | 165 | def wrap_spec(package): 166 | """ 167 | Construct a package spec with traversable compatibility 168 | on the spec/loader/reader. 169 | """ 170 | return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) 171 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/_common.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pathlib 3 | import tempfile 4 | import functools 5 | import contextlib 6 | import types 7 | import importlib 8 | 9 | from typing import Union, Optional 10 | from .abc import ResourceReader, Traversable 11 | 12 | from ._compat import wrap_spec 13 | 14 | Package = Union[types.ModuleType, str] 15 | 16 | 17 | def files(package): 18 | # type: (Package) -> Traversable 19 | """ 20 | Get a Traversable resource from a package 21 | """ 22 | return from_package(get_package(package)) 23 | 24 | 25 | def get_resource_reader(package): 26 | # type: (types.ModuleType) -> Optional[ResourceReader] 27 | """ 28 | Return the package's loader if it's a ResourceReader. 29 | """ 30 | # We can't use 31 | # a issubclass() check here because apparently abc.'s __subclasscheck__() 32 | # hook wants to create a weak reference to the object, but 33 | # zipimport.zipimporter does not support weak references, resulting in a 34 | # TypeError. That seems terrible. 35 | spec = package.__spec__ 36 | reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore 37 | if reader is None: 38 | return None 39 | return reader(spec.name) # type: ignore 40 | 41 | 42 | def resolve(cand): 43 | # type: (Package) -> types.ModuleType 44 | return cand if isinstance(cand, types.ModuleType) else importlib.import_module(cand) 45 | 46 | 47 | def get_package(package): 48 | # type: (Package) -> types.ModuleType 49 | """Take a package name or module object and return the module. 50 | 51 | Raise an exception if the resolved module is not a package. 52 | """ 53 | resolved = resolve(package) 54 | if wrap_spec(resolved).submodule_search_locations is None: 55 | raise TypeError(f'{package!r} is not a package') 56 | return resolved 57 | 58 | 59 | def from_package(package): 60 | """ 61 | Return a Traversable object for the given package. 62 | 63 | """ 64 | spec = wrap_spec(package) 65 | reader = spec.loader.get_resource_reader(spec.name) 66 | return reader.files() 67 | 68 | 69 | @contextlib.contextmanager 70 | def _tempfile( 71 | reader, 72 | suffix='', 73 | # gh-93353: Keep a reference to call os.remove() in late Python 74 | # finalization. 75 | *, 76 | _os_remove=os.remove, 77 | ): 78 | # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' 79 | # blocks due to the need to close the temporary file to work on Windows 80 | # properly. 81 | fd, raw_path = tempfile.mkstemp(suffix=suffix) 82 | try: 83 | try: 84 | os.write(fd, reader()) 85 | finally: 86 | os.close(fd) 87 | del reader 88 | yield pathlib.Path(raw_path) 89 | finally: 90 | try: 91 | _os_remove(raw_path) 92 | except FileNotFoundError: 93 | pass 94 | 95 | 96 | @functools.singledispatch 97 | def as_file(path): 98 | """ 99 | Given a Traversable object, return that object as a 100 | path on the local file system in a context manager. 101 | """ 102 | return _tempfile(path.read_bytes, suffix=path.name) 103 | 104 | 105 | @as_file.register(pathlib.Path) 106 | @contextlib.contextmanager 107 | def _(path): 108 | """ 109 | Degenerate behavior for pathlib.Path objects. 110 | """ 111 | yield path 112 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/_compat.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | 3 | import abc 4 | import os 5 | import sys 6 | import pathlib 7 | from contextlib import suppress 8 | from typing import Union 9 | 10 | 11 | if sys.version_info >= (3, 10): 12 | from zipfile import Path as ZipPath # type: ignore 13 | else: 14 | from zipp import Path as ZipPath # type: ignore 15 | 16 | 17 | try: 18 | from typing import runtime_checkable # type: ignore 19 | except ImportError: 20 | 21 | def runtime_checkable(cls): # type: ignore 22 | return cls 23 | 24 | 25 | try: 26 | from typing import Protocol # type: ignore 27 | except ImportError: 28 | Protocol = abc.ABC # type: ignore 29 | 30 | 31 | class TraversableResourcesLoader: 32 | """ 33 | Adapt loaders to provide TraversableResources and other 34 | compatibility. 35 | 36 | Used primarily for Python 3.9 and earlier where the native 37 | loaders do not yet implement TraversableResources. 38 | """ 39 | 40 | def __init__(self, spec): 41 | self.spec = spec 42 | 43 | @property 44 | def path(self): 45 | return self.spec.origin 46 | 47 | def get_resource_reader(self, name): 48 | from . import readers, _adapters 49 | 50 | def _zip_reader(spec): 51 | with suppress(AttributeError): 52 | return readers.ZipReader(spec.loader, spec.name) 53 | 54 | def _namespace_reader(spec): 55 | with suppress(AttributeError, ValueError): 56 | return readers.NamespaceReader(spec.submodule_search_locations) 57 | 58 | def _available_reader(spec): 59 | with suppress(AttributeError): 60 | return spec.loader.get_resource_reader(spec.name) 61 | 62 | def _native_reader(spec): 63 | reader = _available_reader(spec) 64 | return reader if hasattr(reader, 'files') else None 65 | 66 | def _file_reader(spec): 67 | try: 68 | path = pathlib.Path(self.path) 69 | except TypeError: 70 | return None 71 | if path.exists(): 72 | return readers.FileReader(self) 73 | 74 | return ( 75 | # native reader if it supplies 'files' 76 | _native_reader(self.spec) 77 | or 78 | # local ZipReader if a zip module 79 | _zip_reader(self.spec) 80 | or 81 | # local NamespaceReader if a namespace module 82 | _namespace_reader(self.spec) 83 | or 84 | # local FileReader 85 | _file_reader(self.spec) 86 | # fallback - adapt the spec ResourceReader to TraversableReader 87 | or _adapters.CompatibilityFiles(self.spec) 88 | ) 89 | 90 | 91 | def wrap_spec(package): 92 | """ 93 | Construct a package spec with traversable compatibility 94 | on the spec/loader/reader. 95 | 96 | Supersedes _adapters.wrap_spec to use TraversableResourcesLoader 97 | from above for older Python compatibility (<3.10). 98 | """ 99 | from . import _adapters 100 | 101 | return _adapters.SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) 102 | 103 | 104 | if sys.version_info >= (3, 9): 105 | StrPath = Union[str, os.PathLike[str]] 106 | else: 107 | # PathLike is only subscriptable at runtime in 3.9+ 108 | StrPath = Union[str, "os.PathLike[str]"] 109 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/_itertools.py: -------------------------------------------------------------------------------- 1 | from itertools import filterfalse 2 | 3 | from typing import ( 4 | Callable, 5 | Iterable, 6 | Iterator, 7 | Optional, 8 | Set, 9 | TypeVar, 10 | Union, 11 | ) 12 | 13 | # Type and type variable definitions 14 | _T = TypeVar('_T') 15 | _U = TypeVar('_U') 16 | 17 | 18 | def unique_everseen( 19 | iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None 20 | ) -> Iterator[_T]: 21 | "List unique elements, preserving order. Remember all elements ever seen." 22 | # unique_everseen('AAAABBBCCDAABBB') --> A B C D 23 | # unique_everseen('ABBCcAD', str.lower) --> A B C D 24 | seen: Set[Union[_T, _U]] = set() 25 | seen_add = seen.add 26 | if key is None: 27 | for element in filterfalse(seen.__contains__, iterable): 28 | seen_add(element) 29 | yield element 30 | else: 31 | for element in iterable: 32 | k = key(element) 33 | if k not in seen: 34 | seen_add(k) 35 | yield element 36 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/_legacy.py: -------------------------------------------------------------------------------- 1 | import functools 2 | import os 3 | import pathlib 4 | import types 5 | import warnings 6 | 7 | from typing import Union, Iterable, ContextManager, BinaryIO, TextIO, Any 8 | 9 | from . import _common 10 | 11 | Package = Union[types.ModuleType, str] 12 | Resource = str 13 | 14 | 15 | def deprecated(func): 16 | @functools.wraps(func) 17 | def wrapper(*args, **kwargs): 18 | warnings.warn( 19 | f"{func.__name__} is deprecated. Use files() instead. " 20 | "Refer to https://importlib-resources.readthedocs.io" 21 | "/en/latest/using.html#migrating-from-legacy for migration advice.", 22 | DeprecationWarning, 23 | stacklevel=2, 24 | ) 25 | return func(*args, **kwargs) 26 | 27 | return wrapper 28 | 29 | 30 | def normalize_path(path): 31 | # type: (Any) -> str 32 | """Normalize a path by ensuring it is a string. 33 | 34 | If the resulting string contains path separators, an exception is raised. 35 | """ 36 | str_path = str(path) 37 | parent, file_name = os.path.split(str_path) 38 | if parent: 39 | raise ValueError(f'{path!r} must be only a file name') 40 | return file_name 41 | 42 | 43 | @deprecated 44 | def open_binary(package: Package, resource: Resource) -> BinaryIO: 45 | """Return a file-like object opened for binary reading of the resource.""" 46 | return (_common.files(package) / normalize_path(resource)).open('rb') 47 | 48 | 49 | @deprecated 50 | def read_binary(package: Package, resource: Resource) -> bytes: 51 | """Return the binary contents of the resource.""" 52 | return (_common.files(package) / normalize_path(resource)).read_bytes() 53 | 54 | 55 | @deprecated 56 | def open_text( 57 | package: Package, 58 | resource: Resource, 59 | encoding: str = 'utf-8', 60 | errors: str = 'strict', 61 | ) -> TextIO: 62 | """Return a file-like object opened for text reading of the resource.""" 63 | return (_common.files(package) / normalize_path(resource)).open( 64 | 'r', encoding=encoding, errors=errors 65 | ) 66 | 67 | 68 | @deprecated 69 | def read_text( 70 | package: Package, 71 | resource: Resource, 72 | encoding: str = 'utf-8', 73 | errors: str = 'strict', 74 | ) -> str: 75 | """Return the decoded string of the resource. 76 | 77 | The decoding-related arguments have the same semantics as those of 78 | bytes.decode(). 79 | """ 80 | with open_text(package, resource, encoding, errors) as fp: 81 | return fp.read() 82 | 83 | 84 | @deprecated 85 | def contents(package: Package) -> Iterable[str]: 86 | """Return an iterable of entries in `package`. 87 | 88 | Note that not all entries are resources. Specifically, directories are 89 | not considered resources. Use `is_resource()` on each entry returned here 90 | to check if it is a resource or not. 91 | """ 92 | return [path.name for path in _common.files(package).iterdir()] 93 | 94 | 95 | @deprecated 96 | def is_resource(package: Package, name: str) -> bool: 97 | """True if `name` is a resource inside `package`. 98 | 99 | Directories are *not* resources. 100 | """ 101 | resource = normalize_path(name) 102 | return any( 103 | traversable.name == resource and traversable.is_file() 104 | for traversable in _common.files(package).iterdir() 105 | ) 106 | 107 | 108 | @deprecated 109 | def path( 110 | package: Package, 111 | resource: Resource, 112 | ) -> ContextManager[pathlib.Path]: 113 | """A context manager providing a file path object to the resource. 114 | 115 | If the resource does not already exist on its own on the file system, 116 | a temporary file will be created. If the file was created, the file 117 | will be deleted upon exiting the context manager (no exception is 118 | raised if the file was deleted prior to the context manager 119 | exiting). 120 | """ 121 | return _common.as_file(_common.files(package) / normalize_path(resource)) 122 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/abc.py: -------------------------------------------------------------------------------- 1 | import abc 2 | import io 3 | import itertools 4 | import pathlib 5 | from typing import Any, BinaryIO, Iterable, Iterator, NoReturn, Text, Optional 6 | 7 | from ._compat import runtime_checkable, Protocol, StrPath 8 | 9 | 10 | __all__ = ["ResourceReader", "Traversable", "TraversableResources"] 11 | 12 | 13 | class ResourceReader(metaclass=abc.ABCMeta): 14 | """Abstract base class for loaders to provide resource reading support.""" 15 | 16 | @abc.abstractmethod 17 | def open_resource(self, resource: Text) -> BinaryIO: 18 | """Return an opened, file-like object for binary reading. 19 | 20 | The 'resource' argument is expected to represent only a file name. 21 | If the resource cannot be found, FileNotFoundError is raised. 22 | """ 23 | # This deliberately raises FileNotFoundError instead of 24 | # NotImplementedError so that if this method is accidentally called, 25 | # it'll still do the right thing. 26 | raise FileNotFoundError 27 | 28 | @abc.abstractmethod 29 | def resource_path(self, resource: Text) -> Text: 30 | """Return the file system path to the specified resource. 31 | 32 | The 'resource' argument is expected to represent only a file name. 33 | If the resource does not exist on the file system, raise 34 | FileNotFoundError. 35 | """ 36 | # This deliberately raises FileNotFoundError instead of 37 | # NotImplementedError so that if this method is accidentally called, 38 | # it'll still do the right thing. 39 | raise FileNotFoundError 40 | 41 | @abc.abstractmethod 42 | def is_resource(self, path: Text) -> bool: 43 | """Return True if the named 'path' is a resource. 44 | 45 | Files are resources, directories are not. 46 | """ 47 | raise FileNotFoundError 48 | 49 | @abc.abstractmethod 50 | def contents(self) -> Iterable[str]: 51 | """Return an iterable of entries in `package`.""" 52 | raise FileNotFoundError 53 | 54 | 55 | class TraversalError(Exception): 56 | pass 57 | 58 | 59 | @runtime_checkable 60 | class Traversable(Protocol): 61 | """ 62 | An object with a subset of pathlib.Path methods suitable for 63 | traversing directories and opening files. 64 | 65 | Any exceptions that occur when accessing the backing resource 66 | may propagate unaltered. 67 | """ 68 | 69 | @abc.abstractmethod 70 | def iterdir(self) -> Iterator["Traversable"]: 71 | """ 72 | Yield Traversable objects in self 73 | """ 74 | 75 | def read_bytes(self) -> bytes: 76 | """ 77 | Read contents of self as bytes 78 | """ 79 | with self.open('rb') as strm: 80 | return strm.read() 81 | 82 | def read_text(self, encoding: Optional[str] = None) -> str: 83 | """ 84 | Read contents of self as text 85 | """ 86 | with self.open(encoding=encoding) as strm: 87 | return strm.read() 88 | 89 | @abc.abstractmethod 90 | def is_dir(self) -> bool: 91 | """ 92 | Return True if self is a directory 93 | """ 94 | 95 | @abc.abstractmethod 96 | def is_file(self) -> bool: 97 | """ 98 | Return True if self is a file 99 | """ 100 | 101 | def joinpath(self, *descendants: StrPath) -> "Traversable": 102 | """ 103 | Return Traversable resolved with any descendants applied. 104 | 105 | Each descendant should be a path segment relative to self 106 | and each may contain multiple levels separated by 107 | ``posixpath.sep`` (``/``). 108 | """ 109 | if not descendants: 110 | return self 111 | names = itertools.chain.from_iterable( 112 | path.parts for path in map(pathlib.PurePosixPath, descendants) 113 | ) 114 | target = next(names) 115 | matches = ( 116 | traversable for traversable in self.iterdir() if traversable.name == target 117 | ) 118 | try: 119 | match = next(matches) 120 | except StopIteration: 121 | raise TraversalError( 122 | "Target not found during traversal.", target, list(names) 123 | ) 124 | return match.joinpath(*names) 125 | 126 | def __truediv__(self, child: StrPath) -> "Traversable": 127 | """ 128 | Return Traversable child in self 129 | """ 130 | return self.joinpath(child) 131 | 132 | @abc.abstractmethod 133 | def open(self, mode='r', *args, **kwargs): 134 | """ 135 | mode may be 'r' or 'rb' to open as text or binary. Return a handle 136 | suitable for reading (same as pathlib.Path.open). 137 | 138 | When opening as text, accepts encoding parameters such as those 139 | accepted by io.TextIOWrapper. 140 | """ 141 | 142 | @abc.abstractproperty 143 | def name(self) -> str: 144 | """ 145 | The base name of this object without any parent references. 146 | """ 147 | 148 | 149 | class TraversableResources(ResourceReader): 150 | """ 151 | The required interface for providing traversable 152 | resources. 153 | """ 154 | 155 | @abc.abstractmethod 156 | def files(self) -> "Traversable": 157 | """Return a Traversable object for the loaded package.""" 158 | 159 | def open_resource(self, resource: StrPath) -> io.BufferedReader: 160 | return self.files().joinpath(resource).open('rb') 161 | 162 | def resource_path(self, resource: Any) -> NoReturn: 163 | raise FileNotFoundError(resource) 164 | 165 | def is_resource(self, path: StrPath) -> bool: 166 | return self.files().joinpath(path).is_file() 167 | 168 | def contents(self) -> Iterator[str]: 169 | return (item.name for item in self.files().iterdir()) 170 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/py.typed -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/readers.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import pathlib 3 | import operator 4 | 5 | from . import abc 6 | 7 | from ._itertools import unique_everseen 8 | from ._compat import ZipPath 9 | 10 | 11 | def remove_duplicates(items): 12 | return iter(collections.OrderedDict.fromkeys(items)) 13 | 14 | 15 | class FileReader(abc.TraversableResources): 16 | def __init__(self, loader): 17 | self.path = pathlib.Path(loader.path).parent 18 | 19 | def resource_path(self, resource): 20 | """ 21 | Return the file system path to prevent 22 | `resources.path()` from creating a temporary 23 | copy. 24 | """ 25 | return str(self.path.joinpath(resource)) 26 | 27 | def files(self): 28 | return self.path 29 | 30 | 31 | class ZipReader(abc.TraversableResources): 32 | def __init__(self, loader, module): 33 | _, _, name = module.rpartition('.') 34 | self.prefix = loader.prefix.replace('\\', '/') + name + '/' 35 | self.archive = loader.archive 36 | 37 | def open_resource(self, resource): 38 | try: 39 | return super().open_resource(resource) 40 | except KeyError as exc: 41 | raise FileNotFoundError(exc.args[0]) 42 | 43 | def is_resource(self, path): 44 | # workaround for `zipfile.Path.is_file` returning true 45 | # for non-existent paths. 46 | target = self.files().joinpath(path) 47 | return target.is_file() and target.exists() 48 | 49 | def files(self): 50 | return ZipPath(self.archive, self.prefix) 51 | 52 | 53 | class MultiplexedPath(abc.Traversable): 54 | """ 55 | Given a series of Traversable objects, implement a merged 56 | version of the interface across all objects. Useful for 57 | namespace packages which may be multihomed at a single 58 | name. 59 | """ 60 | 61 | def __init__(self, *paths): 62 | self._paths = list(map(pathlib.Path, remove_duplicates(paths))) 63 | if not self._paths: 64 | message = 'MultiplexedPath must contain at least one path' 65 | raise FileNotFoundError(message) 66 | if not all(path.is_dir() for path in self._paths): 67 | raise NotADirectoryError('MultiplexedPath only supports directories') 68 | 69 | def iterdir(self): 70 | files = (file for path in self._paths for file in path.iterdir()) 71 | return unique_everseen(files, key=operator.attrgetter('name')) 72 | 73 | def read_bytes(self): 74 | raise FileNotFoundError(f'{self} is not a file') 75 | 76 | def read_text(self, *args, **kwargs): 77 | raise FileNotFoundError(f'{self} is not a file') 78 | 79 | def is_dir(self): 80 | return True 81 | 82 | def is_file(self): 83 | return False 84 | 85 | def joinpath(self, *descendants): 86 | try: 87 | return super().joinpath(*descendants) 88 | except abc.TraversalError as exc: 89 | # One of the paths didn't resolve. 90 | msg, target, names = exc.args 91 | if names: # pragma: nocover 92 | raise 93 | # It was the last; construct result with the first path. 94 | return self._paths[0].joinpath(target) 95 | 96 | def open(self, *args, **kwargs): 97 | raise FileNotFoundError(f'{self} is not a file') 98 | 99 | @property 100 | def name(self): 101 | return self._paths[0].name 102 | 103 | def __repr__(self): 104 | paths = ', '.join(f"'{path}'" for path in self._paths) 105 | return f'MultiplexedPath({paths})' 106 | 107 | 108 | class NamespaceReader(abc.TraversableResources): 109 | def __init__(self, namespace_path): 110 | if 'NamespacePath' not in str(namespace_path): 111 | raise ValueError('Invalid path') 112 | self.path = MultiplexedPath(*list(namespace_path)) 113 | 114 | def resource_path(self, resource): 115 | """ 116 | Return the file system path to prevent 117 | `resources.path()` from creating a temporary 118 | copy. 119 | """ 120 | return str(self.path.joinpath(resource)) 121 | 122 | def files(self): 123 | return self.path 124 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/simple.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interface adapters for low-level readers. 3 | """ 4 | 5 | import abc 6 | import io 7 | import itertools 8 | from typing import BinaryIO, List 9 | 10 | from .abc import Traversable, TraversableResources 11 | 12 | 13 | class SimpleReader(abc.ABC): 14 | """ 15 | The minimum, low-level interface required from a resource 16 | provider. 17 | """ 18 | 19 | @abc.abstractproperty 20 | def package(self): 21 | # type: () -> str 22 | """ 23 | The name of the package for which this reader loads resources. 24 | """ 25 | 26 | @abc.abstractmethod 27 | def children(self): 28 | # type: () -> List['SimpleReader'] 29 | """ 30 | Obtain an iterable of SimpleReader for available 31 | child containers (e.g. directories). 32 | """ 33 | 34 | @abc.abstractmethod 35 | def resources(self): 36 | # type: () -> List[str] 37 | """ 38 | Obtain available named resources for this virtual package. 39 | """ 40 | 41 | @abc.abstractmethod 42 | def open_binary(self, resource): 43 | # type: (str) -> BinaryIO 44 | """ 45 | Obtain a File-like for a named resource. 46 | """ 47 | 48 | @property 49 | def name(self): 50 | return self.package.split('.')[-1] 51 | 52 | 53 | class ResourceHandle(Traversable): 54 | """ 55 | Handle to a named resource in a ResourceReader. 56 | """ 57 | 58 | def __init__(self, parent, name): 59 | # type: (ResourceContainer, str) -> None 60 | self.parent = parent 61 | self.name = name # type: ignore 62 | 63 | def is_file(self): 64 | return True 65 | 66 | def is_dir(self): 67 | return False 68 | 69 | def open(self, mode='r', *args, **kwargs): 70 | stream = self.parent.reader.open_binary(self.name) 71 | if 'b' not in mode: 72 | stream = io.TextIOWrapper(*args, **kwargs) 73 | return stream 74 | 75 | def joinpath(self, name): 76 | raise RuntimeError("Cannot traverse into a resource") 77 | 78 | 79 | class ResourceContainer(Traversable): 80 | """ 81 | Traversable container for a package's resources via its reader. 82 | """ 83 | 84 | def __init__(self, reader): 85 | # type: (SimpleReader) -> None 86 | self.reader = reader 87 | 88 | def is_dir(self): 89 | return True 90 | 91 | def is_file(self): 92 | return False 93 | 94 | def iterdir(self): 95 | files = (ResourceHandle(self, name) for name in self.reader.resources) 96 | dirs = map(ResourceContainer, self.reader.children()) 97 | return itertools.chain(files, dirs) 98 | 99 | def open(self, *args, **kwargs): 100 | raise IsADirectoryError() 101 | 102 | 103 | class TraversableReader(TraversableResources, SimpleReader): 104 | """ 105 | A TraversableResources based on SimpleReader. Resource providers 106 | may derive from this class to provide the TraversableResources 107 | interface by supplying the SimpleReader interface. 108 | """ 109 | 110 | def files(self): 111 | return ResourceContainer(self) 112 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/_compat.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/_compat.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_compatibilty_files.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_compatibilty_files.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_contents.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_contents.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_files.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_files.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_open.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_open.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_path.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_path.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_read.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_read.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_reader.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_reader.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/test_resource.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/test_resource.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/update-zips.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/update-zips.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/__pycache__/util.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/__pycache__/util.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/_compat.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | try: 5 | from test.support import import_helper # type: ignore 6 | except ImportError: 7 | # Python 3.9 and earlier 8 | class import_helper: # type: ignore 9 | from test.support import modules_setup, modules_cleanup 10 | 11 | 12 | try: 13 | # Python 3.10 14 | from test.support.os_helper import unlink 15 | except ImportError: 16 | from test.support import unlink as _unlink 17 | 18 | def unlink(target): 19 | return _unlink(os.fspath(target)) 20 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data01/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data01/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/binary.file: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/subdirectory/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data01/subdirectory/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/subdirectory/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data01/subdirectory/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/subdirectory/binary.file: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/utf-16.file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data01/utf-16.file -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data01/utf-8.file: -------------------------------------------------------------------------------- 1 | Hello, UTF-8 world! 2 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data02/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data02/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/one/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data02/one/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/one/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data02/one/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/one/resource1.txt: -------------------------------------------------------------------------------- 1 | one resource 2 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/two/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data02/two/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/two/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/data02/two/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/data02/two/resource2.txt: -------------------------------------------------------------------------------- 1 | two resource 2 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/namespacedata01/binary.file: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/namespacedata01/utf-16.file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/namespacedata01/utf-16.file -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/namespacedata01/utf-8.file: -------------------------------------------------------------------------------- 1 | Hello, UTF-8 world! 2 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_compatibilty_files.py: -------------------------------------------------------------------------------- 1 | import io 2 | import unittest 3 | 4 | import importlib_resources as resources 5 | 6 | from importlib_resources._adapters import ( 7 | CompatibilityFiles, 8 | wrap_spec, 9 | ) 10 | 11 | from . import util 12 | 13 | 14 | class CompatibilityFilesTests(unittest.TestCase): 15 | @property 16 | def package(self): 17 | bytes_data = io.BytesIO(b'Hello, world!') 18 | return util.create_package( 19 | file=bytes_data, 20 | path='some_path', 21 | contents=('a', 'b', 'c'), 22 | ) 23 | 24 | @property 25 | def files(self): 26 | return resources.files(self.package) 27 | 28 | def test_spec_path_iter(self): 29 | self.assertEqual( 30 | sorted(path.name for path in self.files.iterdir()), 31 | ['a', 'b', 'c'], 32 | ) 33 | 34 | def test_child_path_iter(self): 35 | self.assertEqual(list((self.files / 'a').iterdir()), []) 36 | 37 | def test_orphan_path_iter(self): 38 | self.assertEqual(list((self.files / 'a' / 'a').iterdir()), []) 39 | self.assertEqual(list((self.files / 'a' / 'a' / 'a').iterdir()), []) 40 | 41 | def test_spec_path_is(self): 42 | self.assertFalse(self.files.is_file()) 43 | self.assertFalse(self.files.is_dir()) 44 | 45 | def test_child_path_is(self): 46 | self.assertTrue((self.files / 'a').is_file()) 47 | self.assertFalse((self.files / 'a').is_dir()) 48 | 49 | def test_orphan_path_is(self): 50 | self.assertFalse((self.files / 'a' / 'a').is_file()) 51 | self.assertFalse((self.files / 'a' / 'a').is_dir()) 52 | self.assertFalse((self.files / 'a' / 'a' / 'a').is_file()) 53 | self.assertFalse((self.files / 'a' / 'a' / 'a').is_dir()) 54 | 55 | def test_spec_path_name(self): 56 | self.assertEqual(self.files.name, 'testingpackage') 57 | 58 | def test_child_path_name(self): 59 | self.assertEqual((self.files / 'a').name, 'a') 60 | 61 | def test_orphan_path_name(self): 62 | self.assertEqual((self.files / 'a' / 'b').name, 'b') 63 | self.assertEqual((self.files / 'a' / 'b' / 'c').name, 'c') 64 | 65 | def test_spec_path_open(self): 66 | self.assertEqual(self.files.read_bytes(), b'Hello, world!') 67 | self.assertEqual(self.files.read_text(), 'Hello, world!') 68 | 69 | def test_child_path_open(self): 70 | self.assertEqual((self.files / 'a').read_bytes(), b'Hello, world!') 71 | self.assertEqual((self.files / 'a').read_text(), 'Hello, world!') 72 | 73 | def test_orphan_path_open(self): 74 | with self.assertRaises(FileNotFoundError): 75 | (self.files / 'a' / 'b').read_bytes() 76 | with self.assertRaises(FileNotFoundError): 77 | (self.files / 'a' / 'b' / 'c').read_bytes() 78 | 79 | def test_open_invalid_mode(self): 80 | with self.assertRaises(ValueError): 81 | self.files.open('0') 82 | 83 | def test_orphan_path_invalid(self): 84 | with self.assertRaises(ValueError): 85 | CompatibilityFiles.OrphanPath() 86 | 87 | def test_wrap_spec(self): 88 | spec = wrap_spec(self.package) 89 | self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles) 90 | 91 | 92 | class CompatibilityFilesNoReaderTests(unittest.TestCase): 93 | @property 94 | def package(self): 95 | return util.create_package_from_loader(None) 96 | 97 | @property 98 | def files(self): 99 | return resources.files(self.package) 100 | 101 | def test_spec_path_joinpath(self): 102 | self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath) 103 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_contents.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import importlib_resources as resources 3 | 4 | from . import data01 5 | from . import util 6 | 7 | 8 | class ContentsTests: 9 | expected = { 10 | '__init__.py', 11 | 'binary.file', 12 | 'subdirectory', 13 | 'utf-16.file', 14 | 'utf-8.file', 15 | } 16 | 17 | def test_contents(self): 18 | contents = {path.name for path in resources.files(self.data).iterdir()} 19 | assert self.expected <= contents 20 | 21 | 22 | class ContentsDiskTests(ContentsTests, unittest.TestCase): 23 | def setUp(self): 24 | self.data = data01 25 | 26 | 27 | class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase): 28 | pass 29 | 30 | 31 | class ContentsNamespaceTests(ContentsTests, unittest.TestCase): 32 | expected = { 33 | # no __init__ because of namespace design 34 | # no subdirectory as incidental difference in fixture 35 | 'binary.file', 36 | 'utf-16.file', 37 | 'utf-8.file', 38 | } 39 | 40 | def setUp(self): 41 | from . import namespacedata01 42 | 43 | self.data = namespacedata01 44 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_files.py: -------------------------------------------------------------------------------- 1 | import typing 2 | import unittest 3 | 4 | import importlib_resources as resources 5 | from importlib_resources.abc import Traversable 6 | from . import data01 7 | from . import util 8 | 9 | 10 | class FilesTests: 11 | def test_read_bytes(self): 12 | files = resources.files(self.data) 13 | actual = files.joinpath('utf-8.file').read_bytes() 14 | assert actual == b'Hello, UTF-8 world!\n' 15 | 16 | def test_read_text(self): 17 | files = resources.files(self.data) 18 | actual = files.joinpath('utf-8.file').read_text(encoding='utf-8') 19 | assert actual == 'Hello, UTF-8 world!\n' 20 | 21 | @unittest.skipUnless( 22 | hasattr(typing, 'runtime_checkable'), 23 | "Only suitable when typing supports runtime_checkable", 24 | ) 25 | def test_traversable(self): 26 | assert isinstance(resources.files(self.data), Traversable) 27 | 28 | 29 | class OpenDiskTests(FilesTests, unittest.TestCase): 30 | def setUp(self): 31 | self.data = data01 32 | 33 | 34 | class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase): 35 | pass 36 | 37 | 38 | class OpenNamespaceTests(FilesTests, unittest.TestCase): 39 | def setUp(self): 40 | from . import namespacedata01 41 | 42 | self.data = namespacedata01 43 | 44 | 45 | if __name__ == '__main__': 46 | unittest.main() 47 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_open.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import importlib_resources as resources 4 | from . import data01 5 | from . import util 6 | 7 | 8 | class CommonBinaryTests(util.CommonTests, unittest.TestCase): 9 | def execute(self, package, path): 10 | target = resources.files(package).joinpath(path) 11 | with target.open('rb'): 12 | pass 13 | 14 | 15 | class CommonTextTests(util.CommonTests, unittest.TestCase): 16 | def execute(self, package, path): 17 | target = resources.files(package).joinpath(path) 18 | with target.open(): 19 | pass 20 | 21 | 22 | class OpenTests: 23 | def test_open_binary(self): 24 | target = resources.files(self.data) / 'binary.file' 25 | with target.open('rb') as fp: 26 | result = fp.read() 27 | self.assertEqual(result, b'\x00\x01\x02\x03') 28 | 29 | def test_open_text_default_encoding(self): 30 | target = resources.files(self.data) / 'utf-8.file' 31 | with target.open() as fp: 32 | result = fp.read() 33 | self.assertEqual(result, 'Hello, UTF-8 world!\n') 34 | 35 | def test_open_text_given_encoding(self): 36 | target = resources.files(self.data) / 'utf-16.file' 37 | with target.open(encoding='utf-16', errors='strict') as fp: 38 | result = fp.read() 39 | self.assertEqual(result, 'Hello, UTF-16 world!\n') 40 | 41 | def test_open_text_with_errors(self): 42 | # Raises UnicodeError without the 'errors' argument. 43 | target = resources.files(self.data) / 'utf-16.file' 44 | with target.open(encoding='utf-8', errors='strict') as fp: 45 | self.assertRaises(UnicodeError, fp.read) 46 | with target.open(encoding='utf-8', errors='ignore') as fp: 47 | result = fp.read() 48 | self.assertEqual( 49 | result, 50 | 'H\x00e\x00l\x00l\x00o\x00,\x00 ' 51 | '\x00U\x00T\x00F\x00-\x001\x006\x00 ' 52 | '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', 53 | ) 54 | 55 | def test_open_binary_FileNotFoundError(self): 56 | target = resources.files(self.data) / 'does-not-exist' 57 | self.assertRaises(FileNotFoundError, target.open, 'rb') 58 | 59 | def test_open_text_FileNotFoundError(self): 60 | target = resources.files(self.data) / 'does-not-exist' 61 | self.assertRaises(FileNotFoundError, target.open) 62 | 63 | 64 | class OpenDiskTests(OpenTests, unittest.TestCase): 65 | def setUp(self): 66 | self.data = data01 67 | 68 | 69 | class OpenDiskNamespaceTests(OpenTests, unittest.TestCase): 70 | def setUp(self): 71 | from . import namespacedata01 72 | 73 | self.data = namespacedata01 74 | 75 | 76 | class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase): 77 | pass 78 | 79 | 80 | if __name__ == '__main__': 81 | unittest.main() 82 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_path.py: -------------------------------------------------------------------------------- 1 | import io 2 | import unittest 3 | 4 | import importlib_resources as resources 5 | from . import data01 6 | from . import util 7 | 8 | 9 | class CommonTests(util.CommonTests, unittest.TestCase): 10 | def execute(self, package, path): 11 | with resources.as_file(resources.files(package).joinpath(path)): 12 | pass 13 | 14 | 15 | class PathTests: 16 | def test_reading(self): 17 | # Path should be readable. 18 | # Test also implicitly verifies the returned object is a pathlib.Path 19 | # instance. 20 | target = resources.files(self.data) / 'utf-8.file' 21 | with resources.as_file(target) as path: 22 | self.assertTrue(path.name.endswith("utf-8.file"), repr(path)) 23 | # pathlib.Path.read_text() was introduced in Python 3.5. 24 | with path.open('r', encoding='utf-8') as file: 25 | text = file.read() 26 | self.assertEqual('Hello, UTF-8 world!\n', text) 27 | 28 | 29 | class PathDiskTests(PathTests, unittest.TestCase): 30 | data = data01 31 | 32 | def test_natural_path(self): 33 | """ 34 | Guarantee the internal implementation detail that 35 | file-system-backed resources do not get the tempdir 36 | treatment. 37 | """ 38 | target = resources.files(self.data) / 'utf-8.file' 39 | with resources.as_file(target) as path: 40 | assert 'data' in str(path) 41 | 42 | 43 | class PathMemoryTests(PathTests, unittest.TestCase): 44 | def setUp(self): 45 | file = io.BytesIO(b'Hello, UTF-8 world!\n') 46 | self.addCleanup(file.close) 47 | self.data = util.create_package( 48 | file=file, path=FileNotFoundError("package exists only in memory") 49 | ) 50 | self.data.__spec__.origin = None 51 | self.data.__spec__.has_location = False 52 | 53 | 54 | class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase): 55 | def test_remove_in_context_manager(self): 56 | # It is not an error if the file that was temporarily stashed on the 57 | # file system is removed inside the `with` stanza. 58 | target = resources.files(self.data) / 'utf-8.file' 59 | with resources.as_file(target) as path: 60 | path.unlink() 61 | 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_read.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import importlib_resources as resources 3 | 4 | from . import data01 5 | from . import util 6 | from importlib import import_module 7 | 8 | 9 | class CommonBinaryTests(util.CommonTests, unittest.TestCase): 10 | def execute(self, package, path): 11 | resources.files(package).joinpath(path).read_bytes() 12 | 13 | 14 | class CommonTextTests(util.CommonTests, unittest.TestCase): 15 | def execute(self, package, path): 16 | resources.files(package).joinpath(path).read_text() 17 | 18 | 19 | class ReadTests: 20 | def test_read_bytes(self): 21 | result = resources.files(self.data).joinpath('binary.file').read_bytes() 22 | self.assertEqual(result, b'\0\1\2\3') 23 | 24 | def test_read_text_default_encoding(self): 25 | result = resources.files(self.data).joinpath('utf-8.file').read_text() 26 | self.assertEqual(result, 'Hello, UTF-8 world!\n') 27 | 28 | def test_read_text_given_encoding(self): 29 | result = ( 30 | resources.files(self.data) 31 | .joinpath('utf-16.file') 32 | .read_text(encoding='utf-16') 33 | ) 34 | self.assertEqual(result, 'Hello, UTF-16 world!\n') 35 | 36 | def test_read_text_with_errors(self): 37 | # Raises UnicodeError without the 'errors' argument. 38 | target = resources.files(self.data) / 'utf-16.file' 39 | self.assertRaises(UnicodeError, target.read_text, encoding='utf-8') 40 | result = target.read_text(encoding='utf-8', errors='ignore') 41 | self.assertEqual( 42 | result, 43 | 'H\x00e\x00l\x00l\x00o\x00,\x00 ' 44 | '\x00U\x00T\x00F\x00-\x001\x006\x00 ' 45 | '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', 46 | ) 47 | 48 | 49 | class ReadDiskTests(ReadTests, unittest.TestCase): 50 | data = data01 51 | 52 | 53 | class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): 54 | def test_read_submodule_resource(self): 55 | submodule = import_module('ziptestdata.subdirectory') 56 | result = resources.files(submodule).joinpath('binary.file').read_bytes() 57 | self.assertEqual(result, b'\0\1\2\3') 58 | 59 | def test_read_submodule_resource_by_name(self): 60 | result = ( 61 | resources.files('ziptestdata.subdirectory') 62 | .joinpath('binary.file') 63 | .read_bytes() 64 | ) 65 | self.assertEqual(result, b'\0\1\2\3') 66 | 67 | 68 | class ReadNamespaceTests(ReadTests, unittest.TestCase): 69 | def setUp(self): 70 | from . import namespacedata01 71 | 72 | self.data = namespacedata01 73 | 74 | 75 | if __name__ == '__main__': 76 | unittest.main() 77 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_reader.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import sys 3 | import pathlib 4 | import unittest 5 | 6 | from importlib import import_module 7 | from importlib_resources.readers import MultiplexedPath, NamespaceReader 8 | 9 | 10 | class MultiplexedPathTest(unittest.TestCase): 11 | @classmethod 12 | def setUpClass(cls): 13 | path = pathlib.Path(__file__).parent / 'namespacedata01' 14 | cls.folder = str(path) 15 | 16 | def test_init_no_paths(self): 17 | with self.assertRaises(FileNotFoundError): 18 | MultiplexedPath() 19 | 20 | def test_init_file(self): 21 | with self.assertRaises(NotADirectoryError): 22 | MultiplexedPath(os.path.join(self.folder, 'binary.file')) 23 | 24 | def test_iterdir(self): 25 | contents = {path.name for path in MultiplexedPath(self.folder).iterdir()} 26 | try: 27 | contents.remove('__pycache__') 28 | except (KeyError, ValueError): 29 | pass 30 | self.assertEqual(contents, {'binary.file', 'utf-16.file', 'utf-8.file'}) 31 | 32 | def test_iterdir_duplicate(self): 33 | data01 = os.path.abspath(os.path.join(__file__, '..', 'data01')) 34 | contents = { 35 | path.name for path in MultiplexedPath(self.folder, data01).iterdir() 36 | } 37 | for remove in ('__pycache__', '__init__.pyc'): 38 | try: 39 | contents.remove(remove) 40 | except (KeyError, ValueError): 41 | pass 42 | self.assertEqual( 43 | contents, 44 | {'__init__.py', 'binary.file', 'subdirectory', 'utf-16.file', 'utf-8.file'}, 45 | ) 46 | 47 | def test_is_dir(self): 48 | self.assertEqual(MultiplexedPath(self.folder).is_dir(), True) 49 | 50 | def test_is_file(self): 51 | self.assertEqual(MultiplexedPath(self.folder).is_file(), False) 52 | 53 | def test_open_file(self): 54 | path = MultiplexedPath(self.folder) 55 | with self.assertRaises(FileNotFoundError): 56 | path.read_bytes() 57 | with self.assertRaises(FileNotFoundError): 58 | path.read_text() 59 | with self.assertRaises(FileNotFoundError): 60 | path.open() 61 | 62 | def test_join_path(self): 63 | prefix = os.path.abspath(os.path.join(__file__, '..')) 64 | data01 = os.path.join(prefix, 'data01') 65 | path = MultiplexedPath(self.folder, data01) 66 | self.assertEqual( 67 | str(path.joinpath('binary.file'))[len(prefix) + 1 :], 68 | os.path.join('namespacedata01', 'binary.file'), 69 | ) 70 | self.assertEqual( 71 | str(path.joinpath('subdirectory'))[len(prefix) + 1 :], 72 | os.path.join('data01', 'subdirectory'), 73 | ) 74 | self.assertEqual( 75 | str(path.joinpath('imaginary'))[len(prefix) + 1 :], 76 | os.path.join('namespacedata01', 'imaginary'), 77 | ) 78 | self.assertEqual(path.joinpath(), path) 79 | 80 | def test_repr(self): 81 | self.assertEqual( 82 | repr(MultiplexedPath(self.folder)), 83 | f"MultiplexedPath('{self.folder}')", 84 | ) 85 | 86 | def test_name(self): 87 | self.assertEqual( 88 | MultiplexedPath(self.folder).name, 89 | os.path.basename(self.folder), 90 | ) 91 | 92 | 93 | class NamespaceReaderTest(unittest.TestCase): 94 | site_dir = str(pathlib.Path(__file__).parent) 95 | 96 | @classmethod 97 | def setUpClass(cls): 98 | sys.path.append(cls.site_dir) 99 | 100 | @classmethod 101 | def tearDownClass(cls): 102 | sys.path.remove(cls.site_dir) 103 | 104 | def test_init_error(self): 105 | with self.assertRaises(ValueError): 106 | NamespaceReader(['path1', 'path2']) 107 | 108 | def test_resource_path(self): 109 | namespacedata01 = import_module('namespacedata01') 110 | reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) 111 | 112 | root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01')) 113 | self.assertEqual( 114 | reader.resource_path('binary.file'), os.path.join(root, 'binary.file') 115 | ) 116 | self.assertEqual( 117 | reader.resource_path('imaginary'), os.path.join(root, 'imaginary') 118 | ) 119 | 120 | def test_files(self): 121 | namespacedata01 = import_module('namespacedata01') 122 | reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) 123 | root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01')) 124 | self.assertIsInstance(reader.files(), MultiplexedPath) 125 | self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')") 126 | 127 | 128 | if __name__ == '__main__': 129 | unittest.main() 130 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/test_resource.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | import importlib_resources as resources 4 | import uuid 5 | import pathlib 6 | 7 | from . import data01 8 | from . import zipdata01, zipdata02 9 | from . import util 10 | from importlib import import_module 11 | from ._compat import import_helper, unlink 12 | 13 | 14 | class ResourceTests: 15 | # Subclasses are expected to set the `data` attribute. 16 | 17 | def test_is_file_exists(self): 18 | target = resources.files(self.data) / 'binary.file' 19 | self.assertTrue(target.is_file()) 20 | 21 | def test_is_file_missing(self): 22 | target = resources.files(self.data) / 'not-a-file' 23 | self.assertFalse(target.is_file()) 24 | 25 | def test_is_dir(self): 26 | target = resources.files(self.data) / 'subdirectory' 27 | self.assertFalse(target.is_file()) 28 | self.assertTrue(target.is_dir()) 29 | 30 | 31 | class ResourceDiskTests(ResourceTests, unittest.TestCase): 32 | def setUp(self): 33 | self.data = data01 34 | 35 | 36 | class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase): 37 | pass 38 | 39 | 40 | def names(traversable): 41 | return {item.name for item in traversable.iterdir()} 42 | 43 | 44 | class ResourceLoaderTests(unittest.TestCase): 45 | def test_resource_contents(self): 46 | package = util.create_package( 47 | file=data01, path=data01.__file__, contents=['A', 'B', 'C'] 48 | ) 49 | self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'}) 50 | 51 | def test_is_file(self): 52 | package = util.create_package( 53 | file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] 54 | ) 55 | self.assertTrue(resources.files(package).joinpath('B').is_file()) 56 | 57 | def test_is_dir(self): 58 | package = util.create_package( 59 | file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] 60 | ) 61 | self.assertTrue(resources.files(package).joinpath('D').is_dir()) 62 | 63 | def test_resource_missing(self): 64 | package = util.create_package( 65 | file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] 66 | ) 67 | self.assertFalse(resources.files(package).joinpath('Z').is_file()) 68 | 69 | 70 | class ResourceCornerCaseTests(unittest.TestCase): 71 | def test_package_has_no_reader_fallback(self): 72 | # Test odd ball packages which: 73 | # 1. Do not have a ResourceReader as a loader 74 | # 2. Are not on the file system 75 | # 3. Are not in a zip file 76 | module = util.create_package( 77 | file=data01, path=data01.__file__, contents=['A', 'B', 'C'] 78 | ) 79 | # Give the module a dummy loader. 80 | module.__loader__ = object() 81 | # Give the module a dummy origin. 82 | module.__file__ = '/path/which/shall/not/be/named' 83 | module.__spec__.loader = module.__loader__ 84 | module.__spec__.origin = module.__file__ 85 | self.assertFalse(resources.files(module).joinpath('A').is_file()) 86 | 87 | 88 | class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): 89 | ZIP_MODULE = zipdata01 # type: ignore 90 | 91 | def test_is_submodule_resource(self): 92 | submodule = import_module('ziptestdata.subdirectory') 93 | self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file()) 94 | 95 | def test_read_submodule_resource_by_name(self): 96 | self.assertTrue( 97 | resources.files('ziptestdata.subdirectory') 98 | .joinpath('binary.file') 99 | .is_file() 100 | ) 101 | 102 | def test_submodule_contents(self): 103 | submodule = import_module('ziptestdata.subdirectory') 104 | self.assertEqual( 105 | names(resources.files(submodule)), {'__init__.py', 'binary.file'} 106 | ) 107 | 108 | def test_submodule_contents_by_name(self): 109 | self.assertEqual( 110 | names(resources.files('ziptestdata.subdirectory')), 111 | {'__init__.py', 'binary.file'}, 112 | ) 113 | 114 | 115 | class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase): 116 | ZIP_MODULE = zipdata02 # type: ignore 117 | 118 | def test_unrelated_contents(self): 119 | """ 120 | Test thata zip with two unrelated subpackages return 121 | distinct resources. Ref python/importlib_resources#44. 122 | """ 123 | self.assertEqual( 124 | names(resources.files('ziptestdata.one')), 125 | {'__init__.py', 'resource1.txt'}, 126 | ) 127 | self.assertEqual( 128 | names(resources.files('ziptestdata.two')), 129 | {'__init__.py', 'resource2.txt'}, 130 | ) 131 | 132 | 133 | class DeletingZipsTest(unittest.TestCase): 134 | """Having accessed resources in a zip file should not keep an open 135 | reference to the zip. 136 | """ 137 | 138 | ZIP_MODULE = zipdata01 139 | 140 | def setUp(self): 141 | modules = import_helper.modules_setup() 142 | self.addCleanup(import_helper.modules_cleanup, *modules) 143 | 144 | data_path = pathlib.Path(self.ZIP_MODULE.__file__) 145 | data_dir = data_path.parent 146 | self.source_zip_path = data_dir / 'ziptestdata.zip' 147 | self.zip_path = pathlib.Path(f'{uuid.uuid4()}.zip').absolute() 148 | self.zip_path.write_bytes(self.source_zip_path.read_bytes()) 149 | sys.path.append(str(self.zip_path)) 150 | self.data = import_module('ziptestdata') 151 | 152 | def tearDown(self): 153 | try: 154 | sys.path.remove(str(self.zip_path)) 155 | except ValueError: 156 | pass 157 | 158 | try: 159 | del sys.path_importer_cache[str(self.zip_path)] 160 | del sys.modules[self.data.__name__] 161 | except KeyError: 162 | pass 163 | 164 | try: 165 | unlink(self.zip_path) 166 | except OSError: 167 | # If the test fails, this will probably fail too 168 | pass 169 | 170 | def test_iterdir_does_not_keep_open(self): 171 | c = [item.name for item in resources.files('ziptestdata').iterdir()] 172 | self.zip_path.unlink() 173 | del c 174 | 175 | def test_is_file_does_not_keep_open(self): 176 | c = resources.files('ziptestdata').joinpath('binary.file').is_file() 177 | self.zip_path.unlink() 178 | del c 179 | 180 | def test_is_file_failure_does_not_keep_open(self): 181 | c = resources.files('ziptestdata').joinpath('not-present').is_file() 182 | self.zip_path.unlink() 183 | del c 184 | 185 | @unittest.skip("Desired but not supported.") 186 | def test_as_file_does_not_keep_open(self): # pragma: no cover 187 | c = resources.as_file(resources.files('ziptestdata') / 'binary.file') 188 | self.zip_path.unlink() 189 | del c 190 | 191 | def test_entered_path_does_not_keep_open(self): 192 | # This is what certifi does on import to make its bundle 193 | # available for the process duration. 194 | c = resources.as_file( 195 | resources.files('ziptestdata') / 'binary.file' 196 | ).__enter__() 197 | self.zip_path.unlink() 198 | del c 199 | 200 | def test_read_binary_does_not_keep_open(self): 201 | c = resources.files('ziptestdata').joinpath('binary.file').read_bytes() 202 | self.zip_path.unlink() 203 | del c 204 | 205 | def test_read_text_does_not_keep_open(self): 206 | c = resources.files('ziptestdata').joinpath('utf-8.file').read_text() 207 | self.zip_path.unlink() 208 | del c 209 | 210 | 211 | class ResourceFromNamespaceTest01(unittest.TestCase): 212 | site_dir = str(pathlib.Path(__file__).parent) 213 | 214 | @classmethod 215 | def setUpClass(cls): 216 | sys.path.append(cls.site_dir) 217 | 218 | @classmethod 219 | def tearDownClass(cls): 220 | sys.path.remove(cls.site_dir) 221 | 222 | def test_is_submodule_resource(self): 223 | self.assertTrue( 224 | resources.files(import_module('namespacedata01')) 225 | .joinpath('binary.file') 226 | .is_file() 227 | ) 228 | 229 | def test_read_submodule_resource_by_name(self): 230 | self.assertTrue( 231 | resources.files('namespacedata01').joinpath('binary.file').is_file() 232 | ) 233 | 234 | def test_submodule_contents(self): 235 | contents = names(resources.files(import_module('namespacedata01'))) 236 | try: 237 | contents.remove('__pycache__') 238 | except KeyError: 239 | pass 240 | self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) 241 | 242 | def test_submodule_contents_by_name(self): 243 | contents = names(resources.files('namespacedata01')) 244 | try: 245 | contents.remove('__pycache__') 246 | except KeyError: 247 | pass 248 | self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) 249 | 250 | 251 | if __name__ == '__main__': 252 | unittest.main() 253 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/update-zips.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generate the zip test data files. 3 | 4 | Run to build the tests/zipdataNN/ziptestdata.zip files from 5 | files in tests/dataNN. 6 | 7 | Replaces the file with the working copy, but does commit anything 8 | to the source repo. 9 | """ 10 | 11 | import contextlib 12 | import os 13 | import pathlib 14 | import zipfile 15 | 16 | 17 | def main(): 18 | """ 19 | >>> from unittest import mock 20 | >>> monkeypatch = getfixture('monkeypatch') 21 | >>> monkeypatch.setattr(zipfile, 'ZipFile', mock.MagicMock()) 22 | >>> print(); main() # print workaround for bpo-32509 23 | 24 | ...data01... -> ziptestdata/... 25 | ... 26 | ...data02... -> ziptestdata/... 27 | ... 28 | """ 29 | suffixes = '01', '02' 30 | tuple(map(generate, suffixes)) 31 | 32 | 33 | def generate(suffix): 34 | root = pathlib.Path(__file__).parent.relative_to(os.getcwd()) 35 | zfpath = root / f'zipdata{suffix}/ziptestdata.zip' 36 | with zipfile.ZipFile(zfpath, 'w') as zf: 37 | for src, rel in walk(root / f'data{suffix}'): 38 | dst = 'ziptestdata' / pathlib.PurePosixPath(rel.as_posix()) 39 | print(src, '->', dst) 40 | zf.write(src, dst) 41 | 42 | 43 | def walk(datapath): 44 | for dirpath, dirnames, filenames in os.walk(datapath): 45 | with contextlib.suppress(ValueError): 46 | dirnames.remove('__pycache__') 47 | for filename in filenames: 48 | res = pathlib.Path(dirpath) / filename 49 | rel = res.relative_to(datapath) 50 | yield res, rel 51 | 52 | 53 | __name__ == '__main__' and main() 54 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/util.py: -------------------------------------------------------------------------------- 1 | import abc 2 | import importlib 3 | import io 4 | import sys 5 | import types 6 | from pathlib import Path, PurePath 7 | 8 | from . import data01 9 | from . import zipdata01 10 | from ..abc import ResourceReader 11 | from ._compat import import_helper 12 | 13 | 14 | from importlib.machinery import ModuleSpec 15 | 16 | 17 | class Reader(ResourceReader): 18 | def __init__(self, **kwargs): 19 | vars(self).update(kwargs) 20 | 21 | def get_resource_reader(self, package): 22 | return self 23 | 24 | def open_resource(self, path): 25 | self._path = path 26 | if isinstance(self.file, Exception): 27 | raise self.file 28 | return self.file 29 | 30 | def resource_path(self, path_): 31 | self._path = path_ 32 | if isinstance(self.path, Exception): 33 | raise self.path 34 | return self.path 35 | 36 | def is_resource(self, path_): 37 | self._path = path_ 38 | if isinstance(self.path, Exception): 39 | raise self.path 40 | 41 | def part(entry): 42 | return entry.split('/') 43 | 44 | return any( 45 | len(parts) == 1 and parts[0] == path_ for parts in map(part, self._contents) 46 | ) 47 | 48 | def contents(self): 49 | if isinstance(self.path, Exception): 50 | raise self.path 51 | yield from self._contents 52 | 53 | 54 | def create_package_from_loader(loader, is_package=True): 55 | name = 'testingpackage' 56 | module = types.ModuleType(name) 57 | spec = ModuleSpec(name, loader, origin='does-not-exist', is_package=is_package) 58 | module.__spec__ = spec 59 | module.__loader__ = loader 60 | return module 61 | 62 | 63 | def create_package(file=None, path=None, is_package=True, contents=()): 64 | return create_package_from_loader( 65 | Reader(file=file, path=path, _contents=contents), 66 | is_package, 67 | ) 68 | 69 | 70 | class CommonTests(metaclass=abc.ABCMeta): 71 | """ 72 | Tests shared by test_open, test_path, and test_read. 73 | """ 74 | 75 | @abc.abstractmethod 76 | def execute(self, package, path): 77 | """ 78 | Call the pertinent legacy API function (e.g. open_text, path) 79 | on package and path. 80 | """ 81 | 82 | def test_package_name(self): 83 | # Passing in the package name should succeed. 84 | self.execute(data01.__name__, 'utf-8.file') 85 | 86 | def test_package_object(self): 87 | # Passing in the package itself should succeed. 88 | self.execute(data01, 'utf-8.file') 89 | 90 | def test_string_path(self): 91 | # Passing in a string for the path should succeed. 92 | path = 'utf-8.file' 93 | self.execute(data01, path) 94 | 95 | def test_pathlib_path(self): 96 | # Passing in a pathlib.PurePath object for the path should succeed. 97 | path = PurePath('utf-8.file') 98 | self.execute(data01, path) 99 | 100 | def test_importing_module_as_side_effect(self): 101 | # The anchor package can already be imported. 102 | del sys.modules[data01.__name__] 103 | self.execute(data01.__name__, 'utf-8.file') 104 | 105 | def test_non_package_by_name(self): 106 | # The anchor package cannot be a module. 107 | with self.assertRaises(TypeError): 108 | self.execute(__name__, 'utf-8.file') 109 | 110 | def test_non_package_by_package(self): 111 | # The anchor package cannot be a module. 112 | with self.assertRaises(TypeError): 113 | module = sys.modules['importlib_resources.tests.util'] 114 | self.execute(module, 'utf-8.file') 115 | 116 | def test_missing_path(self): 117 | # Attempting to open or read or request the path for a 118 | # non-existent path should succeed if open_resource 119 | # can return a viable data stream. 120 | bytes_data = io.BytesIO(b'Hello, world!') 121 | package = create_package(file=bytes_data, path=FileNotFoundError()) 122 | self.execute(package, 'utf-8.file') 123 | self.assertEqual(package.__loader__._path, 'utf-8.file') 124 | 125 | def test_extant_path(self): 126 | # Attempting to open or read or request the path when the 127 | # path does exist should still succeed. Does not assert 128 | # anything about the result. 129 | bytes_data = io.BytesIO(b'Hello, world!') 130 | # any path that exists 131 | path = __file__ 132 | package = create_package(file=bytes_data, path=path) 133 | self.execute(package, 'utf-8.file') 134 | self.assertEqual(package.__loader__._path, 'utf-8.file') 135 | 136 | def test_useless_loader(self): 137 | package = create_package(file=FileNotFoundError(), path=FileNotFoundError()) 138 | with self.assertRaises(FileNotFoundError): 139 | self.execute(package, 'utf-8.file') 140 | 141 | 142 | class ZipSetupBase: 143 | ZIP_MODULE = None 144 | 145 | @classmethod 146 | def setUpClass(cls): 147 | data_path = Path(cls.ZIP_MODULE.__file__) 148 | data_dir = data_path.parent 149 | cls._zip_path = str(data_dir / 'ziptestdata.zip') 150 | sys.path.append(cls._zip_path) 151 | cls.data = importlib.import_module('ziptestdata') 152 | 153 | @classmethod 154 | def tearDownClass(cls): 155 | try: 156 | sys.path.remove(cls._zip_path) 157 | except ValueError: 158 | pass 159 | 160 | try: 161 | del sys.path_importer_cache[cls._zip_path] 162 | del sys.modules[cls.data.__name__] 163 | except KeyError: 164 | pass 165 | 166 | try: 167 | del cls.data 168 | del cls._zip_path 169 | except AttributeError: 170 | pass 171 | 172 | def setUp(self): 173 | modules = import_helper.modules_setup() 174 | self.addCleanup(import_helper.modules_cleanup, *modules) 175 | 176 | 177 | class ZipSetup(ZipSetupBase): 178 | ZIP_MODULE = zipdata01 # type: ignore 179 | -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/zipdata01/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/zipdata01/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/zipdata01/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/zipdata01/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/zipdata01/ziptestdata.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/zipdata01/ziptestdata.zip -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/zipdata02/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/zipdata02/__init__.py -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/zipdata02/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/zipdata02/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Modules/importlib_resources/tests/zipdata02/ziptestdata.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/importlib_resources/tests/zipdata02/ziptestdata.zip -------------------------------------------------------------------------------- /Plugins/Modules/ysoserial-0.0.8-SNAPSHOT-all.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Modules/ysoserial-0.0.8-SNAPSHOT-all.jar -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/Plugins_漏洞插件模板.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | #!/usr/bin/python 3 | import sys 4 | import requests,argparse,os 5 | from urllib.parse import urlparse 6 | try: 7 | import frozen_dir 8 | #框架引用调用/Plugins/Modules/目录下文件。 9 | ysoserial = frozen_dir.app_path() + "/Plugins/Modules/xxx文件名.jar" 10 | except: 11 | #单文件执行调用当前目录文件 12 | ysoserial = 'xxx文件名.jar' 13 | 14 | def vuln_info(): 15 | vuln_info = { 16 | "vuln_name":"POC测试漏洞", #漏洞名称 17 | 'vuln_referer':'http://baidu.com', #漏洞来源 18 | 'vuln_author':'qianxiao996', #插件作者 19 | 'cms_name':'test',#cms_name需要和上级目录保持一致。扫描器自动添加会调用。GUI版本不会调用 20 | 'vuln_description':'''漏洞描述''', 21 | 'vuln_identifier':'''漏洞编号。''', 22 | 'vuln_class':'漏洞分类',#如:信息泄漏、远程命令执行、任意文件上传、SQL注入、XML注入、任意文件读取、本地文件包含、认证绕过/未认证、弱口令、目录遍历、其他、反序列化漏洞、OGNL表达式注入、SSRF、后门、任意文件下载、鉴权绕过、暴力破解、命令注入、路径泄露、XSS、远程文件包含、CSRF、任意文件包含、代码注入、任意文件写入、密码硬编码、文件包含、任意用户注册、缓冲区溢出、用户枚举漏洞、任意文件删除、任意页面上传、管理权限等 23 | 'vuln_solution':'''修复建议。''', 24 | 'FofaQuery_type':'socket', #socket、http 25 | 'FofaQuery_link':'/', #此处的路径会加在url拼接访问,进行FofaQuery的条件匹配 此处为all为全部页面都检测 26 | 'FofaQuery_rule':'title="百度"',#header="JSESSIONID" || body="Struts Problem Report" || body="There is no Action mapped for namespace" || body="No result defined for action and result input" || header="Servlet" || header="JBoss",port="60001" 27 | #header', 'body', 'title', 'banner','port','banner','service','protocol','server' 28 | 'ispoc':1, #是否有poc 1为有 0为无 29 | 'isexp':1 #是否有exp 1为有 0为无 30 | } 31 | return vuln_info 32 | def _out(type,text): 33 | print("[*] "+type+":\n "+text) 34 | # func_out 输出函数对象 url:url hostname:主机地址 port:端口 scheme:服务 heads:http自定义头信息 35 | # plugins_temp_data 全局变量,可存储数据至do_exp使用 36 | def do_poc(url,hostname,port,scheme,heads={},func_out=_out,plugins_temp_data={}): 37 | try: 38 | #存储数据至do_exp函数使用 39 | plugins_temp_data['key']='11' 40 | 41 | # func_out('Debug',"debug信息") 42 | # func_out('Error',"错误信息",) 43 | # func_out('Info',"info信息") 44 | # 返回参数 45 | #Result返回是否存在, 46 | #Result_Info为返回的信息,可以为Paylaod 47 | #Debug debug信息 默认不会显示,勾选显示调试信息会输出此结果 48 | #Error_Info无论何时都会输出 49 | result = {"Result":False,"Result_Info":""} 50 | result['Result'] = True 51 | result['Result_Info']= url 52 | return result 53 | except Exception as e: 54 | func_out('Error',str(e)+str(e.__traceback__.tb_lineno)+'行') 55 | 56 | 57 | #exp_data 58 | # { 59 | # "type":"cmd", #cmd,shell,uploadfile 60 | # "command":"whoami", #cmd命令 61 | # "reverse_ip":"127.0.0.1", #反弹shell的ip 62 | # "reverse_port":"8888", #反弹shell的端口 63 | # "filename":"conf.php", #写入文件的名字 64 | # "filename_contents":"shell内容", #shell文件内容 65 | # } 66 | # url:url hostname:主机地址 port:端口 scheme:服务 heads:自定义请求头 func_out 输出函数对象 67 | def do_exp(url,hostname,port,scheme,heads={},exp_data={},func_out=_out,plugins_temp_data={}): 68 | # 返回参数 69 | # Result返回是否成功, 70 | # Result_Info为返回的信息,可以为Paylaod 71 | result = {"Result": False, "Result_Info": ""} 72 | try: 73 | 74 | #获取全局变量数据 75 | key = plugins_temp_data.get('key') 76 | 77 | #输出各种信息。参数一类型,默认Debug,可选【Debug、Error、Info】 参数二位具体内容 78 | func_out('Debug',"debug信息") 79 | func_out('Error',"错误信息",) 80 | func_out('Info',"info信息") 81 | 82 | #命令执行 83 | if exp_data['type']=='cmd': 84 | ##处理你的命令执行 85 | result['Result'] = True 86 | result['Result_Info'] = "root" 87 | result['Result_Info'] =plugins_temp_data 88 | 89 | #反弹shell 90 | elif exp_data['type']=='shell': 91 | ##处理你的反弹shell 92 | result['Result'] = True 93 | result['Result_Info'] = "反弹成功" 94 | #上传文件 95 | elif exp_data['type']=='uploadfile': 96 | ##处理你的上传操作 97 | result['Result'] = True 98 | result['Result_Info'] = "上传成功" 99 | except Exception as e: 100 | func_out('Error',str(e)+str(e.__traceback__.tb_lineno)+'行') 101 | return result 102 | 103 | 104 | 105 | 106 | 107 | if __name__== '__main__': 108 | #2.创建解析器 109 | parser = argparse.ArgumentParser() 110 | # 3.添加参数 111 | url_file = parser.add_mutually_exclusive_group(required=True) 112 | url_file.add_argument("-u", "--url",type=str, default="") 113 | url_file.add_argument("-f", "--file",type=str, default="") 114 | 115 | parser.add_argument("-m","--mode", type=str, default="poc",help="poc or exp",required =False,choices =["poc","exp","cmd","shell","upload"]) 116 | 117 | mxgroup = parser.add_mutually_exclusive_group(required=False) 118 | mxgroup.add_argument("--cmd", type=str, default="whoami",help="cmd",required =False) 119 | mxgroup.add_argument("--shell", type=str, default="127.0.0.1:8080",help="shell",required =False) 120 | mxgroup.add_argument("--upload", type=str, default="shell.php",help="upload filepath",required =False) 121 | print("漏洞信息如下:") 122 | vuln_info = vuln_info() 123 | try: 124 | import prettytable 125 | table = prettytable.PrettyTable() 126 | table.field_names = ['字段名称','值'] 127 | for i in vuln_info: 128 | table.add_row([i,vuln_info[i]]) 129 | print(table) 130 | except: 131 | for i in vuln_info: 132 | print("\t"+str(i)+":"+str(vuln_info[i])) 133 | print("\n[*] 开始执行...") 134 | 135 | # 4.解析参数 136 | hp = parser.parse_args() 137 | all_url= [] 138 | if hp.file: 139 | f=open(hp.file,encoding='utf-8') 140 | file_Data = f.read() 141 | f.close() 142 | all_url = str(file_Data).splitlines() 143 | else: 144 | all_url.append(hp.url) 145 | 146 | if hp.mode =='poc': 147 | for i in all_url: 148 | _url = urlparse(i) 149 | # print(_url) 150 | hostname = _url.hostname 151 | port = _url.port 152 | scheme = _url.scheme 153 | result = do_poc(i,hostname,port,scheme) 154 | print("[*] URL:"+i+"\n[+] 检测结果:"+("Success" if result.get("Result") else "Faile")+"\t返回信息:"+result.get("Result_Info")+"\n" ) 155 | 156 | elif vuln_info.get('isexp'): 157 | if hp.mode =='cmd': 158 | exp_data= { 159 | "type":"cmd", #cmd,shell,uploadfile 160 | "command":hp.cmd #cmd命令 161 | } 162 | elif hp.mode =='shell': 163 | exp_data= { 164 | "type":"shell", #cmd,shell,uploadfile 165 | "reverse_ip":hp.shell.split(":")[0], #反弹shell的ip 166 | "reverse_port":hp.shell.split(":")[1] #反弹shell的端口 167 | } 168 | elif hp.mode =='upload': 169 | try: 170 | filedata_=open(hp.upload,encoding="utf-8").read() 171 | except: 172 | filedata_=open(hp.upload,encoding="gb2312").read() 173 | exp_data= { 174 | "type":"uploadfile", #cmd,shell,uploadfile 175 | "filename":os.path.basename(hp.upload), 176 | "filename_contents":filedata_ 177 | } 178 | else: 179 | exp_data= { 180 | "type":"cmd", #cmd,shell,uploadfile 181 | "command":"whoami", #cmd命令 182 | } 183 | for i in all_url: 184 | _url = urlparse(i) 185 | # print(_url) 186 | hostname = _url.hostname 187 | port = _url.port 188 | scheme = _url.scheme 189 | result = do_exp(i,hostname,port,scheme,heads={},exp_data=exp_data) 190 | print("[*] URL:"+i+"\n[+] 执行结果:"+("Success" if result.get("Result") else "Faile")+"\n"+result.get("Result_Info")+"\n") 191 | else: 192 | print("[E] 该漏洞没有EXP!") 193 | print("[*] 运行完毕!") 194 | 195 | -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/111.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/111.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/122cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/122cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/GetFileContent_fileread.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/GetFileContent_fileread.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread - 副本.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread - 副本.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread_exp.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread_exp.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread_poc.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/GetFile_fileread_poc.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/GetXMLList_fileread.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/GetXMLList_fileread.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_23d.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_23d.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_aaa.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_aaa.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_asdcpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_asdcpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (2).cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (2).cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (3).cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (3).cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (4).cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (4).cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (5).cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (5).cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (6).cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本 (6).cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test - 副本.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_test2.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_test2.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_wedfg.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_wedfg.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_漏洞插件模板.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_漏洞插件模板.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/Plugins_金山防火墙_editschedule.php_远程命令执行.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/Plugins_金山防火墙_editschedule.php_远程命令执行.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/acsoft_GetFileContent_fileread.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/acsoft_GetFileContent_fileread.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/acsoft_GetFile_fileread.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/acsoft_GetFile_fileread.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/acsoft_GetXMLList_fileread.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/acsoft_GetXMLList_fileread.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/test.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/test.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/test22_exp.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/test22_exp.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/test2_poc.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/test2_poc.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/test_exp.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/test_exp.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/__pycache__/test_poc.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/__pycache__/test_poc.cpython-37.pyc -------------------------------------------------------------------------------- /Plugins/Vuln_Plugins/test/setup.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/Plugins/Vuln_Plugins/test/setup.py -------------------------------------------------------------------------------- /Plugins_漏洞插件模板.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | #!/usr/bin/python 3 | import requests 4 | def vuln_info(): 5 | info={ 6 | 'vuln_name': 'POC测试漏洞', #漏洞名称 7 | 'vuln_referer':'http://baidu.com', #漏洞来源 8 | 'vuln_author':'qianxiao996', #插件作者 9 | 'cms_name':'test',#cms_name需要和上级目录保持一致。扫描器自动添加会调用。GUI版本不会调用 10 | 'vuln_description':'''漏洞描述''', 11 | 'vuln_identifier':'''漏洞编号。''', 12 | 'vuln_class':'漏洞分类',#如:信息泄漏、远程命令执行、任意文件上传、SQL注入、XML注入、任意文件读取、本地文件包含、认证绕过/未认证、弱口令、目录遍历、其他、反序列化漏洞、OGNL表达式注入、SSRF、后门、任意文件下载、鉴权绕过、暴力破解、命令注入、路径泄露、XSS、远程文件包含、CSRF、任意文件包含、代码注入、任意文件写入、密码硬编码、文件包含、任意用户注册、缓冲区溢出、用户枚举漏洞、任意文件删除、任意页面上传、管理权限等 13 | 'vuln_solution':'''修复建议。''', 14 | 'FofaQuery_type':'socket', #socket、http 15 | 'FofaQuery_link':'/', #此处的路径会加在url拼接访问,进行FofaQuery的条件匹配 此处为all为全部页面都检测 16 | 'FofaQuery_rule':'title="百度"',#header="JSESSIONID" || body="Struts Problem Report" || body="There is no Action mapped for namespace" || body="No result defined for action and result input" || header="Servlet" || header="JBoss",port="60001" 17 | #header', 'body', 'title', 'banner','port','banner','service','protocol','server' 18 | 'ispoc':1, #是否有poc 1为有 0为无 19 | 'isexp':1 #是否有exp 1为有 0为无 20 | } 21 | return info 22 | # url:url hostname:主机地址 port:端口 scheme:服务 heads:http自定义头信息 23 | def do_poc(url,hostname,port,scheme,heads={}): 24 | try: 25 | # 返回参数 26 | #Result返回是否存在, 27 | #Result_Info为返回的信息,可以为Paylaod 28 | #Debug debug信息 默认不会显示,勾选显示调试信息会输出此结果 29 | #Error_Info无论何时都会输出 30 | result = {"Result":True,"Result_Info":"payload","Debug_Info":"","Error_Info":""} 31 | result['Result_Info']= 'payload' 32 | result['Debug_Info'] = 'ddd' 33 | result['Error_Info'] = "dsaaaaaaaa" 34 | except Exception as e: 35 | result['Error_Info'] = str(e)+str(e.__traceback__.tb_lineno)+'行' 36 | return result 37 | 38 | # { 39 | # "type":"cmd", #cmd,shell,uploadfile 40 | # "command":"whoami", #cmd命令 41 | # "reverse_ip":"127.0.0.1", #反弹shell的ip 42 | # "reverse_port":"8888", #反弹shell的端口 43 | # "filename":"conf.php", #写入文件的名字 44 | # "filename_contents":"shell内容", #shell文件内容 45 | # } 46 | # url:url hostname:主机地址 port:端口 scheme:服务 heads:自定义请求头 47 | def do_exp(url,hostname,port,scheme,heads={},exp_data={}): 48 | try: 49 | # 返回参数 50 | #Result返回是否成功, 51 | #Result_Info为返回的信息,可以为Paylaod 52 | #Debug debug信息 默认不会显示,勾选显示调试信息会输出此结果 53 | #Error_Info无论何时都会输出 54 | result = {"Result":False,"Result_Info":"payload","Debug_Info":"","Error_Info":""} 55 | #命令执行 56 | if exp_data['type']=='cmd': 57 | result['Result'] = True 58 | result['Result_Info'] = "root" 59 | #反弹shell 60 | if exp_data['type']=='shell': 61 | result['Result'] = True 62 | result['Result_Info'] = "反弹成功" 63 | #上传文件 64 | if exp_data['type']=='uploadfile': 65 | result['Result'] = True 66 | result['Result_Info'] = "上传成功" 67 | 68 | # 69 | result['Debug_Info'] = "1" 70 | except Exception as e: 71 | result['Error_Info'] = str(e)+str(e.__traceback__.tb_lineno)+'行' 72 | return result 73 | 74 | 75 | 76 | 77 | if __name__== '__main__': 78 | url='http://127.0.0.1/' 79 | # aa= do_exp(url,'','','','',exp_data) 80 | # print(aa) 81 | aa = do_poc(args.url,'','','',heads={}) 82 | print(aa) 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FrameScan 2 | 3 | ## 工具简介 4 | 5 | FrameScan是一款python3编写的简易的cms漏洞检测利用框架,支持漏洞检测与简单利用方式,支持大多数CMS,可以自定义CMS类型及自行编写POC。旨在帮助有安全经验的安全工程师对已知的应用快速发现漏洞。 6 | 7 | ## 支持平台 8 | 9 | - Windows 10 | - Linux 11 | - MAC(请自测) 12 | 13 | ## 工具特点 14 | 15 | - 单URL批量检测 16 | - 单URL单漏洞检测 17 | - 单URL指定CMS检测 18 | - 多URL单漏洞检测 19 | - 单URL单漏洞检测 20 | - 单URL指定CMS检测 21 | - 单URL 漏洞利用 22 | - 多URL 漏洞利用 23 | 24 | 详细参数如下: 25 | 26 | ``` 27 | 28 | _____ ____ 29 | | ___| __ __ _ _ __ ___ ___/ ___| ___ __ _ _ __ 30 | | |_ | '__/ _` | '_ ` _ \ / _ \___ \ / __/ _` | '_ \ 31 | | _|| | | (_| | | | | | | __/___) | (_| (_| | | | | 32 | |_| |_| \__,_|_| |_| |_|\___|____/ \___\__,_|_| |_| 33 | 34 | Options: Code by qianxiao996 35 | -------------------------------------------------------------- 36 | All: 37 | -u Target URL 目标URL 38 | -f Load urls file 文件路径 39 | -m mode:poc or exp 选择运行模式(默认POC) 40 | 41 | POC Mode: 42 | -n Use poc name 使用单个漏洞检测POC 43 | -cms Specify CMS 指定webapp or CMS类型 44 | 45 | EXP Mode: 46 | -v Use exp name 指定漏洞EXP名称 47 | -cmd RCE Command(whoami) 执行cmd命令(默认:whoami) 48 | -shell Return webshell 反弹Webshell(127.0.0.1:8080) 49 | 50 | Search: 51 | -ls List Specify CMS poc 查找关键词漏洞(匹配漏洞名称) 52 | -la List CMS POC 列出指定CMS漏洞(匹配CMS) 53 | -l List avalible pocs 列出所有POC 54 | 55 | Output: 56 | -txt Save Result(txt) 输出扫描结果(txt) 57 | -html Save Result(html) 输出扫描结果(html) 58 | 59 | Other: 60 | -r Reload POC 重新加载POC 61 | -t Threads 指定线程数量,默认10 62 | -h Get help 帮助信息 63 | --timeout Scan timeout time(10s) 请求超时时间(10s) 64 | 65 | Example: 66 | python3 FrameScan.py -u http://example.com -cms thinkphp 67 | python3 FrameScan.py -f url.txt -m exp -v CVE-2019-2729 68 | python3 FrameScan.py -u http://example.com:7001 -m exp -v CVE-2019-2729 69 | python3 FrameScan.py -f list.txt -txt results.txt 70 | -------------------------------------------------------------- 71 | FrameScan V1.6 20210521 Blog:blog.qianxiao996.cn 72 | ``` 73 | 74 | 75 | ## 使用方法 76 | 77 | 下载项目 78 | 79 | ```python 80 | git clone https://github.com/qianxiao996/FrameScan 81 | ``` 82 | 83 | 安装依赖 84 | 85 | ``` 86 | python3 -m pip install requirements.txt 87 | ``` 88 | 89 | 单URL批量检测 90 | 91 | ``` 92 | python3 FrameScan.py -u URL 93 | ``` 94 | 95 | 单URL单漏洞检测(POC_NAME可以用 -l、-s、-la进行查询) 96 | 97 | ``` 98 | python3 FrameScan.py -u URL -n POC_NAME 99 | ``` 100 | 101 | 单URL指定CMS检测 102 | 103 | ``` 104 | python3 FrameScan.py -u URL -cms CMS_NAME 105 | ``` 106 | 107 | 多URL批量检测 108 | 109 | ``` 110 | python3 FrameScan.py -f 文件名 111 | ``` 112 | 113 | 多URL单漏洞检测 114 | 115 | ``` 116 | python3 FrameScan.py -f 文件名 -n POC_NAME 117 | ``` 118 | 119 | 多URL指定CMS检测 120 | 121 | ``` 122 | python3 FrameScan.py -f 文件名 -cms CMS_NAME 123 | ``` 124 | 125 | 输出到TXT或者HTML文件 126 | 127 | ``` 128 | python3 FrameScan.py -u URL -txt 文件名 129 | python3 FrameScan.py -u URL -html 文件名 130 | ``` 131 | 132 | 单URL漏洞利用 133 | 134 | ``` 135 | python3 FrameScan.py -u URL -m exp -v exp_name 136 | python3 FrameScan.py -u URL -m exp -v exp_name -c whoami 137 | python3 FrameScan.py -u URL -m exp -v exp_name -shell 127.0.0.1:8080 #127.0.0.1:8080为反弹shell的端口 138 | ``` 139 | 140 | 多URL漏洞利用 141 | 142 | ``` 143 | python3 FrameScan.py -f 文件 -m exp -v exp_name 144 | python3 FrameScan.py -f 文件 -m exp -v exp_name -c whoami 145 | python3 FrameScan.py -f 文件 -m exp -v exp_name -shell 146 | ``` 147 | 148 | ## 插件模板 149 | 150 | ### python插件 151 | 152 | 插件命名格式为Plugins_插件名.py。请规范编写。脚本中为示例代码。插件模板与GUI统一,可以相互调用。 153 | 154 | ```python 155 | # -*- coding: UTF-8 -*- 156 | #!/usr/bin/python 157 | import requests 158 | def vuln_info(): 159 | info={ 160 | 'vuln_name': 'POC测试漏洞', #漏洞名称 161 | 'vuln_referer':'http://baidu.com', #漏洞来源 162 | 'vuln_author':'qianxiao996', #插件作者 163 | 'cms_name':'test',#cms_name需要和上级目录保持一致。扫描器自动添加会调用。GUI版本不会调用 164 | 'vuln_description':'''漏洞描述''', 165 | 'vuln_identifier':'''漏洞编号。''', 166 | 'vuln_class':'漏洞分类',#如:信息泄漏、远程命令执行、任意文件上传、SQL注入、XML注入、任意文件读取、本地文件包含、认证绕过/未认证、弱口令、目录遍历、其他、反序列化漏洞、OGNL表达式注入、SSRF、后门、任意文件下载、鉴权绕过、暴力破解、命令注入、路径泄露、XSS、远程文件包含、CSRF、任意文件包含、代码注入、任意文件写入、密码硬编码、文件包含、任意用户注册、缓冲区溢出、用户枚举漏洞、任意文件删除、任意页面上传、管理权限等 167 | 'vuln_solution':'''修复建议。''', 168 | 'FofaQuery_type':'socket', #socket、http 169 | 'FofaQuery_link':'/', #此处的路径会加在url拼接访问,进行FofaQuery的条件匹配 此处为all为全部页面都检测 170 | 'FofaQuery_rule':'title="百度"',#header="JSESSIONID" || body="Struts Problem Report" || body="There is no Action mapped for namespace" || body="No result defined for action and result input" || header="Servlet" || header="JBoss",port="60001" 171 | #header', 'body', 'title', 'banner','port','banner','service','protocol','server' 172 | 'ispoc':1, #是否有poc 1为有 0为无 173 | 'isexp':1 #是否有exp 1为有 0为无 174 | } 175 | return info 176 | # url:url hostname:主机地址 port:端口 scheme:服务 heads:http自定义头信息 177 | def do_poc(url,hostname,port,scheme,heads={}): 178 | try: 179 | # 返回参数 180 | #Result返回是否存在, 181 | #Result_Info为返回的信息,可以为Paylaod 182 | #Debug debug信息 默认不会显示,勾选显示调试信息会输出此结果 183 | #Error_Info无论何时都会输出 184 | result = {"Result":True,"Result_Info":"payload","Debug_Info":"","Error_Info":""} 185 | result['Result_Info']= 'payload' 186 | result['Debug_Info'] = 'ddd' 187 | result['Error_Info'] = "dsaaaaaaaa" 188 | except Exception as e: 189 | result['Error_Info'] = str(e)+str(e.__traceback__.tb_lineno)+'行' 190 | return result 191 | 192 | # { 193 | # "type":"cmd", #cmd,shell,uploadfile 194 | # "command":"whoami", #cmd命令 195 | # "reverse_ip":"127.0.0.1", #反弹shell的ip 196 | # "reverse_port":"8888", #反弹shell的端口 197 | # "filename":"conf.php", #写入文件的名字 198 | # "filename_contents":"shell内容", #shell文件内容 199 | # } 200 | # url:url hostname:主机地址 port:端口 scheme:服务 heads:自定义请求头 201 | def do_exp(url,hostname,port,scheme,heads={},exp_data={}): 202 | try: 203 | # 返回参数 204 | #Result返回是否成功, 205 | #Result_Info为返回的信息,可以为Paylaod 206 | #Debug debug信息 默认不会显示,勾选显示调试信息会输出此结果 207 | #Error_Info无论何时都会输出 208 | result = {"Result":False,"Result_Info":"payload","Debug_Info":"","Error_Info":""} 209 | #命令执行 210 | if exp_data['type']=='cmd': 211 | result['Result'] = True 212 | result['Result_Info'] = "root" 213 | #反弹shell 214 | if exp_data['type']=='shell': 215 | result['Result'] = True 216 | result['Result_Info'] = "反弹成功" 217 | #上传文件 218 | if exp_data['type']=='uploadfile': 219 | result['Result'] = True 220 | result['Result_Info'] = "上传成功" 221 | 222 | # 223 | result['Debug_Info'] = "1" 224 | except Exception as e: 225 | result['Error_Info'] = str(e)+str(e.__traceback__.tb_lineno)+'行' 226 | return result 227 | 228 | 229 | 230 | 231 | if __name__== '__main__': 232 | url='http://127.0.0.1/' 233 | # aa= do_exp(url,'','','','',exp_data) 234 | # print(aa) 235 | aa = do_poc(args.url,'','','',heads={}) 236 | print(aa) 237 | 238 | ``` 239 | 240 | ### Yaml插件 241 | 242 | 请参考[FrameScan-Yaml插件文档](https://github.com/qianxiao996/FrameScan-Yaml/) 243 | 244 | ## 警告! 245 | **请勿用于非法用途!否则自行承担一切后果** 246 | 247 | -------------------------------------------------------------------------------- /VULN_DB.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/VULN_DB.db -------------------------------------------------------------------------------- /__pycache__/frozen_dir.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/__pycache__/frozen_dir.cpython-37.pyc -------------------------------------------------------------------------------- /color.py: -------------------------------------------------------------------------------- 1 | from colorama import init, Fore, Back, Style 2 | init(autoreset=True) # 初始化,并且设置颜色设置自动恢复 3 | class Colored(object): 4 | def magenta(self, s): 5 | return Style.BRIGHT+Fore.MAGENTA+s+Fore.RESET+Style.RESET_ALL 6 | def green(self, s): 7 | return Style.BRIGHT+Fore.GREEN+s+Fore.RESET+Style.RESET_ALL 8 | def white(self, s): 9 | return Fore.WHITE+s+Fore.RESET+Style.RESET_ALL 10 | def cyan(self, s): 11 | return Style.BRIGHT+Fore.CYAN+s+Fore.RESET+Style.RESET_ALL 12 | def ccyan(self, s): 13 | return Fore.CYAN+s+Fore.RESET+Style.RESET_ALL 14 | def yellow(self, s): 15 | return Style.BRIGHT+Fore.YELLOW+s+Fore.RESET+Style.RESET_ALL 16 | def red(self, s): 17 | return Style.BRIGHT+Fore.RED+s+Fore.RESET+Style.RESET_ALL 18 | def blue(self, s): 19 | 20 | return(Style.BRIGHT+Fore.BLUE + str(s) + Fore.RESET+Style.RESET_ALL) 21 | def yeinfo(self): 22 | return Style.BRIGHT+Fore.YELLOW+"[INFO]"+Fore.RESET+Style.RESET_ALL 23 | def rewarn(self): 24 | return Style.BRIGHT+Fore.RED+"[WARN]"+Fore.RESET+Style.RESET_ALL -------------------------------------------------------------------------------- /color.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/color.pyc -------------------------------------------------------------------------------- /frozen_dir.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | import os 4 | 5 | def app_path(): 6 | """Returns the base application path.""" 7 | if hasattr(sys, 'frozen'): 8 | # Handles PyInstaller 9 | return os.path.dirname(sys.executable) #使用pyinstaller打包后的exe目录 10 | return os.path.dirname(__file__) #没打包前的py目录 11 | -------------------------------------------------------------------------------- /main.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/main.ico -------------------------------------------------------------------------------- /modules/Class_Poc.py: -------------------------------------------------------------------------------- 1 | from random import * 2 | from colorama import Fore 3 | from prettytable import PrettyTable 4 | import re,os,importlib 5 | import random,sys 6 | from tqdm import tqdm 7 | import operator 8 | from string import Template 9 | import requests,string 10 | import datetime 11 | from requests.adapters import HTTPAdapter 12 | from requests.packages.urllib3.util.retry import Retry 13 | #屏蔽SSl警告 14 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 15 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 16 | 17 | 18 | application_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "modules") 19 | if application_path not in sys.path: 20 | sys.path.append(application_path) 21 | # 遍历目录下的所有模块并导入 22 | for module in os.listdir(application_path): 23 | if module.endswith('.py') and not module.startswith("Class_") and not module.startswith("Main.py"): 24 | try: 25 | module_name = module[:-3] # 假设您的模块名为my_module.py 26 | module = importlib.import_module(module_name) 27 | # 将模块注册到全局变量中 28 | globals()[module_name] = module 29 | except Exception as e: 30 | print("引入模块失败:"+str(e)) 31 | # print(str(e) + '----' + str(e.__traceback__.tb_lineno) + '行') 32 | retry_times = 3 # 设置重试次数 33 | retry_backoff_factor = 1 # 设置重试间隔时间 34 | user_agent_list = [ 35 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1' 36 | 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36' 37 | 'Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36' 38 | 'Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1' 39 | 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 40 | 'Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666' 41 | 'Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.188 Safari/537.36 CrKey/1.54.250320' 42 | 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+' 43 | 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+' 44 | 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 45 | 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 46 | 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 47 | 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36' 48 | 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36' 49 | 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36' 50 | 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true' 51 | 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.0.0 Mobile Safari/537.36' 52 | 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263' 53 | 'Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 54 | 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36' 55 | 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 56 | 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 57 | 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 58 | 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 59 | 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 60 | 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36' 61 | 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)' 62 | 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13' 63 | 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36' 64 | 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36' 65 | 'Mozilla/5.0 (Linux; Android 11; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36' 66 | 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 67 | 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 68 | 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' 69 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1' 70 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1' 71 | 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1' 72 | ] 73 | class Class_Poc: 74 | def __init__(self,url,poc,timeout,debug): 75 | self.url = url.strip() 76 | self.poc=poc 77 | self.timeout=timeout 78 | self.session = requests.Session() 79 | retry = Retry(total=retry_times, backoff_factor=retry_backoff_factor) 80 | adapter = HTTPAdapter(max_retries=retry) 81 | self.session.mount('http://', adapter) 82 | self.session.mount('https://', adapter) 83 | self.all_global_var={}#存放所有的全局变量 84 | self.all_global_payload = {} #所有payload 85 | self.all_request_name_list={} 86 | self.debug=debug 87 | def main(self): 88 | poc_name = self.poc.get("name") 89 | poc_transport = self.poc.get("transport") 90 | poc_rules = self.poc.get("rules") 91 | poc_expression = self.poc.get("expression") 92 | poc_detail = self.poc.get("detail") 93 | poc_re_str = self.poc.get("output") 94 | poc_set = self.poc.get("set") 95 | poc_payload = self.poc.get("payload") 96 | self.set_bianliang(poc_set) 97 | self.set_payload(poc_payload) 98 | # print(self.all_global_var) 99 | if poc_transport.lower()=="http": 100 | try: 101 | response = self.poc_request_http(poc_rules) 102 | if type(response) !=requests.models.Response: 103 | result = {"url":self.url,"poc":self.poc,"result":False,"others":response} 104 | else: 105 | is_success = self.main_poc_expression(poc_expression) 106 | resultaa="" 107 | if is_success: 108 | resultaa = self.re_others(response,poc_re_str) 109 | result = {"url":self.url,"poc":self.poc,"result":is_success,"others":resultaa} 110 | if self.debug: 111 | tqdm.write(self.out_debug_info("Replace Main Output","原始字符串:%s 替换后:%s"%(poc_re_str,resultaa))) 112 | except Exception as e: 113 | result = {"url":self.url,"poc":self.poc,"result":False,"others":'Error:'+str(e)+' 行:'+str(e.__traceback__.tb_lineno)} 114 | elif poc_transport.lower()=="tcp": 115 | result = {"url":self.url,"name":self.poc.get("name"),"result":"False","others":"暂不支持此协议,待开发!"} 116 | elif poc_transport.lower()=="udp": 117 | result = {"url":self.url,"name":self.poc.get("name"),"result":"False","others":"暂不支持此协议,待开发!"} 118 | else: 119 | result = {"url":self.url,"name":self.poc.get("name"),"result":"False","others":"协议不正确"} 120 | if self.debug: 121 | tqdm.write(self.out_debug_info("Return","输出结果:%s"%(result))) 122 | return result 123 | def re_others(self,response,poc_re_str): 124 | #此处先匹配{{}}进行代码执行替换,然后实现字符串模板替换。$a形式 125 | poc_re_str = self.replace_Template_var(poc_re_str) 126 | if poc_re_str: 127 | pattern = r'\{\{(.*?)\}\}' 128 | result = re.findall(pattern, poc_re_str) 129 | if result: 130 | for item in result: 131 | try: 132 | try: 133 | var_str = str(eval(item)) 134 | except Exception as e: 135 | self.out_error_info("eval code",e,"代码["+item+"] 执行错误:"+str(e)) 136 | var_str="" 137 | poc_re_str =poc_re_str.replace("{{%s}}"%item,var_str) 138 | except Exception as e: 139 | self.out_error_info("eval code",e,str(e)) 140 | # poc_re_str = self.replace_Template_var(poc_re_str) 141 | return poc_re_str 142 | else: 143 | return "" 144 | 145 | def out_error_info(self,type_str,e,text): 146 | tqdm.write(Fore.RED+"[E] ["+str(e.__traceback__.tb_lineno).strip()+"行]["+self.poc.get("name")+"]["+type_str+"] "+text) 147 | def out_debug_info(self,type,text): 148 | return Fore.MAGENTA +"["+Fore.CYAN+"Debug"+Fore.MAGENTA+"]["+Fore.CYAN+type+Fore.MAGENTA+"] "+text 149 | def main_poc_expression(self,expression): 150 | poc_expression = self.replace_Template_var(expression) 151 | poc_expression =expression.replace("&&"," and ").replace("||"," or ") 152 | for i in self.all_request_name_list: 153 | poc_expression = poc_expression.replace(str(i)+"()",str(self.all_request_name_list[i])) 154 | # print(poc_expression) 155 | if self.debug: 156 | tqdm.write(self.out_debug_info("Main Expression","原始字符串:%s 替换后:%s"%(expression,poc_expression))) 157 | try: 158 | if eval(poc_expression): 159 | return True 160 | else: 161 | return False 162 | except Exception as e: 163 | self.out_error_info("eval code",e,"代码["+poc_expression+"] 执行错误:"+str(e)) 164 | 165 | def set_payload(self,poc_set): 166 | try: 167 | if poc_set: 168 | for i in poc_set.keys(): 169 | try: 170 | self.all_global_payload[i]=poc_set[i] 171 | except Exception as e: 172 | self.out_error_info("set payload",e,"Payload名:"+i+" Payload值:"+poc_set[i]+" 错误信息:"+str(e)) 173 | if self.debug: 174 | tqdm.write(self.out_debug_info("set payload", "Payload名%s Payload值:%s"%(i,poc_set[i]))) 175 | # exec(f'global {i}\n{i}={poc_set[i]}') 176 | except Exception as e: 177 | self.out_error_info("set var",e,"设置变量出错:"+str(e)) 178 | 179 | def set_bianliang(self,poc_set): 180 | try: 181 | if poc_set: 182 | for i in poc_set.keys(): 183 | try: 184 | exec(f'self.all_global_var[i]={poc_set[i]}') 185 | except Exception as e: 186 | self.out_error_info("set var",e,"变量名:"+i+" 变量值:"+poc_set[i]+" 错误信息:"+str(e)) 187 | if self.debug: 188 | tqdm.write(self.out_debug_info("set var", "变量名:%s 变量Str:%s 变量值:%s"%(i,poc_set[i],self.all_global_var[i]))) 189 | # exec(f'global {i}\n{i}={poc_set[i]}') 190 | except Exception as e: 191 | self.out_error_info("set var",e,"设置变量出错:"+str(e)) 192 | def poc_request_http(self,poc_rules): 193 | try: 194 | # r = s.post(url,headers=headers) 195 | for i in poc_rules: 196 | request_methods= poc_rules[i].get("request").get("method").strip() 197 | request_path= poc_rules[i].get("request").get("path").strip() 198 | request_headers= poc_rules[i].get("request").get("headers") 199 | request_body= poc_rules[i].get("request").get("body") 200 | request_body =self.replace_Template_var(request_body) 201 | request_headers =self.replace_Template_var_headers(request_headers) 202 | if not request_headers.get("User-Agent"): 203 | request_headers['User-Agent'] = random.choice(user_agent_list) 204 | if self.debug: 205 | #debug 206 | http_request_str="[%s] HTTP请求:%s\n%s\n%s %s\nHost: %s\n"%(self.poc.get("name"),i,"-"*100,request_methods,request_path,self.url) 207 | if len(request_headers)>0: 208 | for header in request_headers: 209 | if header: 210 | http_request_str+="%s: %s\n"%(header,str(request_headers[header])) 211 | if request_body: 212 | http_request_str+="\n%s"%(str(request_body)+"\n"+"-"*100) 213 | 214 | tqdm.write(self.out_debug_info("Request",http_request_str) ) 215 | if request_path.startswith("^"): 216 | request_url = self.url 217 | elif request_path.strip().startswith("/"): 218 | if self.url.strip().endswith("/"): 219 | request_url = self.url[:-1].strip()+ request_path.strip() 220 | else: 221 | request_url = self.url.strip()+ request_path.strip() 222 | else: 223 | request_url = self.url.strip()+ "/"+request_path.strip() 224 | # request_methods= poc_rules[i].get("request").get("method") 225 | request_url =self.replace_Template_var(request_url) 226 | # print(request_url) 227 | output_list= poc_rules[i].get("output") 228 | 229 | if poc_rules[i].get("request").get("follow_redirects"): 230 | request_follow_redirects= True 231 | else: 232 | request_follow_redirects= False 233 | try: 234 | response = self.single_request_http(request_url,request_methods,request_body,request_headers,request_follow_redirects) 235 | except requests.exceptions.RequestException as e: 236 | response="HTTP请求异常:"+str(e) 237 | # tqdm.write(response) 238 | continue 239 | if self.debug: 240 | #debug 241 | return_result_str= "[%s][%s] HTTP返回:%s\n%s\n"%(self.poc.get("name"),request_url,i,'-'*100) 242 | return_result_str += "HTTP/1.1 %s %s\n"%(response.status_code,response.reason) 243 | if response.headers: 244 | for zz in response.headers: 245 | return_result_str += "%s: %s\n"%(zz,response.headers[zz]) 246 | if response.text: 247 | return_result_str += "\n%s"%(response.text) 248 | tqdm.write(self.out_debug_info("Response",return_result_str+"\n"+'-'*100) ) 249 | expression =poc_rules[i].get("expression") 250 | expression = self.replace_Template_var(expression) 251 | expression =expression.replace("&&","and").replace("||","or") 252 | if self.is_expression(response,expression): 253 | if self.debug: 254 | tqdm.write(self.out_debug_info("Expression","判断条件:%s 判断结果:%s"%(expression,'True'))) 255 | self.all_request_name_list[i] = True 256 | # exec(f'global {i}\n{i}=True') 257 | self.output_var(response,output_list) 258 | #匹配成功读取output做环境变量 259 | else: 260 | self.all_request_name_list[i] = False 261 | if self.debug: 262 | tqdm.write(self.out_debug_info("Expression","判断条件:%s 判断结果:%s"%(expression,'Flase'))) 263 | # exec(f'global {i}\n{i}=False') 264 | #失败则下一个请求 265 | 266 | return response 267 | except Exception as e: 268 | self.out_error_info("poc rquests",e,str(e)) 269 | # tqdm.write(Fore.RED+"[E] ["+self.poc.get("name")+"]"+str(e) + '----' + str(e.__traceback__.tb_lineno) + '行') 270 | return None 271 | def replace_Template_var(self,body): 272 | if body: 273 | temp_request_body = Template(body) 274 | try: 275 | # body = temp_request_body.substitute(self.all_global_var) 276 | body = temp_request_body.safe_substitute(self.all_global_var) 277 | temp2_request_body = Template(body) 278 | body = temp2_request_body.safe_substitute(self.all_global_payload) 279 | except Exception as e: 280 | self.out_error_info("replace template",e,"模板替换异常:"+str(e)) 281 | # tqdm.write(Fore.RED+"[E] ["+self.poc.get("name")+"]"+str(e) + '----' + str(e.__traceback__.tb_lineno) + '行') 282 | return body 283 | def replace_Template_var_headers(self,headers): 284 | for i in headers: 285 | headers[i] = self.replace_Template_var(headers[i]) 286 | return headers 287 | def is_expression(self,response,expression): 288 | # print(expression) 289 | # if response.status_code==200 and operator.contains(response.text,'html'): 290 | try: 291 | if eval(expression): 292 | return True 293 | else: 294 | return False 295 | except Exception as e: 296 | self.out_error_info("eval code",e,"代码["+expression+"] 执行错误:"+str(e)) 297 | 298 | def output_var(self,response,output_list): 299 | 300 | try: 301 | if output_list: 302 | for i in output_list: 303 | replace_result = self.re_others(response,output_list[i]) 304 | self.all_global_var[i] = replace_result 305 | if self.debug: 306 | tqdm.write(self.out_debug_info("Replace Output","变量名:%s 替换前:%s 替换后:%s"%(i,output_list[i],replace_result))) 307 | except Exception as e: 308 | self.out_error_info("output",e,str(e)) 309 | # tqdm.write(Fore.RED+"[E] ["+self.poc.get("name")+"]"+str(e) + '----' + str(e.__traceback__.tb_lineno) + '行') 310 | 311 | def single_request_http(self,request_url,request_methods,data,headers,request_follow_redirects): 312 | response = self.session.request(request_methods.upper(), request_url,data=data,headers=headers,allow_redirects=request_follow_redirects,verify=False,timeout=self.timeout) 313 | # print(type(response.status_code), response.status_code) 314 | return response 315 | # print(type(response.status_code), response.status_code) 316 | # print(type(response.headers), response.headers) 317 | # print(type(response.cookies), response.cookies) 318 | # print(type(response.url), response.url) 319 | # print(type(response.history), response.history) -------------------------------------------------------------------------------- /modules/__pycache__/Class_Poc.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/modules/__pycache__/Class_Poc.cpython-311.pyc -------------------------------------------------------------------------------- /modules/__pycache__/Class_Poc.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianxiao996/FrameScan/0a74bc6aefd6a01418ec6b3f74e44b4446fd86b8/modules/__pycache__/Class_Poc.cpython-37.pyc -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.8.1 2 | certifi==2024.7.4 3 | charset-normalizer==3.3.2 4 | colorama==0.4.6 5 | Django==5.0.7 6 | dnspython==2.3.0 7 | eventlet==0.33.3 8 | greenlet==3.0.1 9 | idna==3.4 10 | image==1.5.33 11 | importlib-metadata==6.7.0 12 | Nuitka==1.7.9 13 | ordered-set==4.1.0 14 | pillow==10.4.0 15 | prettytable==3.7.0 16 | PyYAML==6.0.1 17 | qrcode==7.3.1 18 | requests==2.31.0 19 | six==1.16.0 20 | some-package==0.1 21 | sqlparse==0.5.1 22 | tqdm==4.66.5 23 | typing_extensions==4.7.1 24 | tzdata==2024.1 25 | urllib3==2.0.7 26 | wcwidth==0.2.10 27 | wifi-password==1.1.1 28 | wincertstore==0.2 29 | zipp==3.15.0 30 | zstandard==0.21.0 31 | --------------------------------------------------------------------------------